ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rundll32.c
Go to the documentation of this file.
00001 /*
00002  * ReactOS rundll32
00003  * Copyright (C) 2003-2004 ReactOS Team
00004  *
00005  * COPYRIGHT:       See COPYING in the top level directory
00006  * PROJECT:         ReactOS rundll32.exe
00007  * FILE:            base/system/rundll32/rundll32.c
00008  * PURPOSE:         Run a DLL as a program
00009  * PROGRAMMER:      ShadowFlare (blakflare@hotmail.com)
00010  */
00011 
00012 #define WIN32_LEAN_AND_MEAN
00013 
00014 // Both UNICODE and _UNICODE must be either defined or undefined
00015 // because some headers use UNICODE and others use _UNICODE
00016 #ifdef UNICODE
00017 #ifndef _UNICODE
00018 #define _UNICODE
00019 #endif
00020 #else
00021 #ifdef _UNICODE
00022 #define UNICODE
00023 #endif
00024 #endif
00025 
00026 #include <windows.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <malloc.h>
00030 #include <tchar.h>
00031 #include "resource.h"
00032 
00033 typedef int (WINAPI *DllWinMainW)(
00034   HWND hWnd,
00035   HINSTANCE hInstance,
00036   LPWSTR lpwCmdLine,
00037   int nCmdShow
00038 );
00039 typedef int (WINAPI *DllWinMainA)(
00040   HWND hWnd,
00041   HINSTANCE hInstance,
00042   LPSTR lpCmdLine,
00043   int nCmdShow
00044 );
00045 
00046 /*
00047 LPCTSTR DllNotLoaded = _T("LoadLibrary failed to load \"%s\"");
00048 LPCTSTR MissingEntry = _T("Missing entry point:%s\nIn %s");
00049 */
00050 LPCTSTR rundll32_wtitle = _T("rundll32");
00051 LPCTSTR rundll32_wclass = _T("rundll32_window");
00052 
00053 TCHAR ModuleFileName[MAX_PATH+1];
00054 LPTSTR ModuleTitle;
00055 
00056 
00057 // CommandLineToArgv converts a command-line string to argc and
00058 // argv similar to the ones in the standard main function.
00059 // This is a specialized version coded specifically for rundll32
00060 // and is not intended to be used in any other program.
00061 LPTSTR *WINAPI CommandLineToArgv(LPCTSTR lpCmdLine, int *lpArgc)
00062 {
00063     LPTSTR *argv, lpSrc, lpDest, lpArg;
00064     int argc, nBSlash, nNames;
00065     BOOL bInQuotes, bFirstChar;
00066 
00067     // If null was passed in for lpCmdLine, there are no arguments
00068     if (!lpCmdLine) {
00069         if (lpArgc)
00070             *lpArgc = 0;
00071         return 0;
00072     }
00073 
00074     lpSrc = (LPTSTR)lpCmdLine;
00075     // Skip spaces at beginning
00076     while (*lpSrc == _T(' ') || *lpSrc == _T('\t'))
00077         lpSrc++;
00078 
00079     // If command-line starts with null, there are no arguments
00080     if (*lpSrc == 0) {
00081         if (lpArgc)
00082             *lpArgc = 0;
00083         return 0;
00084     }
00085 
00086     lpArg = lpSrc;
00087     argc = 0;
00088     nBSlash = 0;
00089     bInQuotes = FALSE;
00090     bFirstChar = TRUE;
00091     nNames = 0;
00092 
00093     // Count the number of arguments
00094     while (nNames < 4) {
00095         if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
00096             // Whitespace not enclosed in quotes signals the start of another argument
00097             argc++;
00098 
00099             // Skip whitespace between arguments
00100             while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2))
00101                 lpSrc++;
00102             if (*lpSrc == 0)
00103                 break;
00104             if (nNames >= 3) {
00105                 // Increment the count for the last argument
00106                 argc++;
00107                 break;
00108             }
00109             nBSlash = 0;
00110             bFirstChar = TRUE;
00111             continue;
00112         }
00113         else if (*lpSrc == _T('\\')) {
00114             // Count consecutive backslashes
00115             nBSlash++;
00116             bFirstChar = FALSE;
00117         }
00118         else if (*lpSrc == _T('\"') && !(nBSlash & 1)) {
00119             // Open or close quotes
00120             bInQuotes = !bInQuotes;
00121             nBSlash = 0;
00122         }
00123         else {
00124             // Some other character
00125             nBSlash = 0;
00126             if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1))
00127                 nNames++;
00128             bFirstChar = FALSE;
00129         }
00130         lpSrc++;
00131     }
00132 
00133     // Allocate space for the pointers in argv and the strings in one block
00134     argv = (LPTSTR *)malloc(argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR));
00135 
00136     if (!argv) {
00137         // Memory allocation failed
00138         if (lpArgc)
00139             *lpArgc = 0;
00140         return 0;
00141     }
00142 
00143     lpSrc = lpArg;
00144     lpDest = lpArg = (LPTSTR)(argv + argc);
00145     argc = 0;
00146     nBSlash = 0;
00147     bInQuotes = FALSE;
00148     bFirstChar = TRUE;
00149     nNames = 0;
00150 
00151     // Fill the argument array
00152     while (nNames < 4) {
00153         if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
00154             // Whitespace not enclosed in quotes signals the start of another argument
00155             // Null-terminate argument
00156             *lpDest++ = 0;
00157             argv[argc++] = lpArg;
00158 
00159             // Skip whitespace between arguments
00160             while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2))
00161                 lpSrc++;
00162             if (*lpSrc == 0)
00163                 break;
00164             lpArg = lpDest;
00165             if (nNames >= 3) {
00166                 // Copy the rest of the command-line to the last argument
00167                 argv[argc++] = lpArg;
00168                 _tcscpy(lpArg,lpSrc);
00169                 break;
00170             }
00171             nBSlash = 0;
00172             bFirstChar = TRUE;
00173             continue;
00174         }
00175         else if (*lpSrc == _T('\\')) {
00176             *lpDest++ = _T('\\');
00177             lpSrc++;
00178 
00179             // Count consecutive backslashes
00180             nBSlash++;
00181             bFirstChar = FALSE;
00182         }
00183         else if (*lpSrc == _T('\"')) {
00184             if (!(nBSlash & 1)) {
00185                 // If an even number of backslashes are before the quotes,
00186                 // the quotes don't go in the output
00187                 lpDest -= nBSlash / 2;
00188                 bInQuotes = !bInQuotes;
00189             }
00190             else {
00191                 // If an odd number of backslashes are before the quotes,
00192                 // output a quote
00193                 lpDest -= (nBSlash + 1) / 2;
00194                 *lpDest++ = _T('\"');
00195                 bFirstChar = FALSE;
00196             }
00197             lpSrc++;
00198             nBSlash = 0;
00199         }
00200         else {
00201             // Copy other characters
00202             if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1))
00203                 nNames++;
00204             *lpDest++ = *lpSrc++;
00205             nBSlash = 0;
00206             bFirstChar = FALSE;
00207         }
00208     }
00209 
00210     if (lpArgc)
00211         *lpArgc = argc;
00212     return argv;
00213 }
00214 
00215 void GetModuleTitle(void)
00216 {
00217     LPTSTR lpStr;
00218 
00219     GetModuleFileName(0,ModuleFileName,MAX_PATH);
00220     ModuleTitle = ModuleFileName;
00221 
00222     for (lpStr = ModuleFileName;*lpStr;lpStr++) {
00223         if (*lpStr == _T('\\'))
00224             ModuleTitle = lpStr+1;
00225     }
00226 
00227     for (lpStr = ModuleTitle;*lpStr;lpStr++) {
00228         if (_tcsicmp(lpStr,_T(".exe"))==0)
00229             break;
00230     }
00231 
00232     *lpStr = 0;
00233 }
00234 
00235 // The macro ConvertToWideChar takes a tstring parameter and returns
00236 // a pointer to a unicode string.  A conversion is performed if
00237 // neccessary.  FreeConvertedWideChar string should be used on the
00238 // return value of ConvertToWideChar when the string is no longer
00239 // needed.  The original string or the string that is returned
00240 // should not be modified until FreeConvertedWideChar has been called.
00241 #ifdef UNICODE
00242 #define ConvertToWideChar(lptString) (lptString)
00243 #define FreeConvertedWideChar(lpwString)
00244 #else
00245 
00246 LPWSTR ConvertToWideChar(LPCSTR lpString)
00247 {
00248     LPWSTR lpwString;
00249     size_t nStrLen;
00250 
00251     nStrLen = strlen(lpString) + 1;
00252 
00253     lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR));
00254     MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen);
00255 
00256     return lpwString;
00257 }
00258 
00259 #define FreeConvertedWideChar(lpwString) free(lpwString)
00260 #endif
00261 
00262 // The macro ConvertToMultiByte takes a tstring parameter and returns
00263 // a pointer to an ansi string.  A conversion is performed if
00264 // neccessary.  FreeConvertedMultiByte string should be used on the
00265 // return value of ConvertToMultiByte when the string is no longer
00266 // needed.  The original string or the string that is returned
00267 // should not be modified until FreeConvertedMultiByte has been called.
00268 #ifdef UNICODE
00269 #define ConvertToMultiByte(lptString) DuplicateToMultiByte(lptString,0)
00270 #define FreeConvertedMultiByte(lpaString) free(lpaString)
00271 #else
00272 #define ConvertToMultiByte(lptString) (lptString)
00273 #define FreeConvertedMultiByte(lpaString)
00274 #endif
00275 
00276 // DuplicateToMultiByte takes a tstring parameter and always returns
00277 // a pointer to a duplicate ansi string.  If nBufferSize is zero,
00278 // the buffer length is the exact size of the string plus the
00279 // terminating null.  If nBufferSize is nonzero, the buffer length
00280 // is equal to nBufferSize.  As with strdup, free should be called
00281 // for the returned string when it is no longer needed.
00282 LPSTR DuplicateToMultiByte(LPCTSTR lptString, size_t nBufferSize)
00283 {
00284     LPSTR lpString;
00285     size_t nStrLen;
00286 
00287     nStrLen = _tcslen(lptString) + 1;
00288     if (nBufferSize == 0) nBufferSize = nStrLen;
00289 
00290     lpString = (LPSTR)malloc(nBufferSize);
00291 #ifdef UNICODE
00292     WideCharToMultiByte(0,0,lptString,nStrLen,lpString,nBufferSize,0,0);
00293 #else
00294     strncpy(lpString,lptString,nBufferSize);
00295 #endif
00296 
00297     return lpString;
00298 }
00299 
00300 LRESULT CALLBACK EmptyWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00301 {
00302     return DefWindowProc(hWnd, uMsg, wParam, lParam);
00303 }
00304 
00305 // Registers a minimal window class for passing to the dll function
00306 BOOL RegisterBlankClass(HINSTANCE hInstance, HINSTANCE hPrevInstance)
00307 {
00308     WNDCLASSEX wcex;
00309 
00310     wcex.cbSize = sizeof(WNDCLASSEX);
00311     wcex.style         = 0;
00312     wcex.lpfnWndProc   = EmptyWindowProc;
00313     wcex.cbClsExtra    = 0;
00314     wcex.cbWndExtra    = 0;
00315     wcex.hInstance     = hInstance;
00316     wcex.hIcon         = 0;
00317     wcex.hCursor       = 0;
00318     wcex.hbrBackground = 0;
00319     wcex.lpszMenuName  = 0;
00320     wcex.lpszClassName = rundll32_wclass;
00321     wcex.hIconSm       = 0;
00322 
00323     return (RegisterClassEx(&wcex) != (ATOM)0);
00324 }
00325 
00326 int WINAPI _tWinMain(
00327   HINSTANCE hInstance,
00328   HINSTANCE hPrevInstance,
00329   LPTSTR lpCmdLine,
00330   int nCmdShow
00331 )
00332 {
00333     int argc;
00334     TCHAR szMsg[RC_STRING_MAX_SIZE];
00335 
00336     LPTSTR *argv;
00337     LPTSTR lptCmdLine,lptDllName,lptFuncName,lptMsgBuffer;
00338     LPSTR lpFuncName,lpaCmdLine;
00339     LPWSTR lpwCmdLine;
00340     HMODULE hDll;
00341     DllWinMainW fnDllWinMainW;
00342     DllWinMainA fnDllWinMainA;
00343     HWND hWindow;
00344     int nRetVal,i;
00345     size_t nStrLen;
00346 
00347     // Get command-line in argc-argv format
00348     argv = CommandLineToArgv(GetCommandLine(),&argc);
00349 
00350     // Skip all beginning arguments starting with a slash (/)
00351     for (i = 1; i < argc; i++)
00352         if (*argv[i] != _T('/')) break;
00353 
00354     // If no dll was specified, there is nothing to do
00355     if (i >= argc) {
00356         if (argv) free(argv);
00357         return 0;
00358     }
00359 
00360     lptDllName = argv[i++];
00361 
00362     // The next argument, which specifies the name of the dll function,
00363     // can either have a comma between it and the dll filename or a space.
00364     // Using a comma here is the preferred method
00365     if (i < argc)
00366         lptFuncName = argv[i++];
00367     else
00368         lptFuncName = _T("");
00369 
00370     // If no function name was specified, nothing needs to be done
00371     if (!*lptFuncName) {
00372         if (argv) free(argv);
00373         return 0;
00374     }
00375 
00376     // The rest of the arguments will be passed to dll function
00377     if (i < argc)
00378         lptCmdLine = argv[i];
00379     else
00380         lptCmdLine = _T("");
00381 
00382     nRetVal = 0;
00383 
00384     // Everything is all setup, so load the dll now
00385     hDll = LoadLibrary(lptDllName);
00386     if (hDll) {
00387         nStrLen = _tcslen(lptFuncName);
00388         // Make a non-unicode version of the function name,
00389         // since that is all GetProcAddress accepts
00390         lpFuncName = DuplicateToMultiByte(lptFuncName,nStrLen + 2);
00391 
00392 #ifdef UNICODE
00393         lpFuncName[nStrLen] = 'W';
00394         lpFuncName[nStrLen+1] = 0;
00395         // Get address of unicode version of the dll function if it exists
00396         fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName);
00397         fnDllWinMainA = 0;
00398         if (!fnDllWinMainW) {
00399             // If no unicode function was found, get the address of the non-unicode function
00400             lpFuncName[nStrLen] = 'A';
00401             fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
00402             if (!fnDllWinMainA) {
00403                 // If first non-unicode function was not found, get the address
00404                 // of the other non-unicode function
00405                 lpFuncName[nStrLen] = 0;
00406                 fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
00407             }
00408         }
00409 #else
00410         // Get address of non-unicode version of the dll function if it exists
00411         fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
00412         fnDllWinMainW = 0;
00413         if (!fnDllWinMainA) {
00414             // If first non-unicode function was not found, get the address
00415             // of the other non-unicode function
00416             lpFuncName[nStrLen] = 'A';
00417             lpFuncName[nStrLen+1] = 0;
00418             fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
00419             if (!fnDllWinMainA) {
00420                 // If non-unicode function was not found, get the address of the unicode function
00421                 lpFuncName[nStrLen] = 'W';
00422                 fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName);
00423             }
00424         }
00425 #endif
00426 
00427         free(lpFuncName);
00428 
00429         if (!RegisterBlankClass(hInstance, hPrevInstance))
00430         {
00431             return 0;
00432         }
00433         // Create a window so we can pass a window handle to
00434         // the dll function; this is required
00435         hWindow = CreateWindowEx(0,rundll32_wclass,rundll32_wtitle,0,CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,hInstance,0);
00436 
00437         if (fnDllWinMainW) {
00438             // Convert the command-line string to unicode and call the dll function
00439             lpwCmdLine = ConvertToWideChar(lptCmdLine);
00440             nRetVal = fnDllWinMainW(hWindow,hInstance,lpwCmdLine,nCmdShow);
00441             FreeConvertedWideChar(lpwCmdLine);
00442         }
00443         else if (fnDllWinMainA) {
00444             // Convert the command-line string to ansi and call the dll function
00445             lpaCmdLine = ConvertToMultiByte(lptCmdLine);
00446             nRetVal = fnDllWinMainA(hWindow,hInstance,lpaCmdLine,nCmdShow);
00447             FreeConvertedMultiByte(lpaCmdLine);
00448         }
00449         else {
00450             // The specified dll function was not found; display an error message
00451             GetModuleTitle();
00452             LoadString( GetModuleHandle(NULL), IDS_MissingEntry, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
00453 
00454             lptMsgBuffer = (LPTSTR)malloc((_tcslen(szMsg) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
00455             _stprintf(lptMsgBuffer,szMsg,lptFuncName,lptDllName);
00456             MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR);
00457             free(lptMsgBuffer);
00458         }
00459 
00460         DestroyWindow(hWindow);
00461         UnregisterClass(rundll32_wclass,hInstance);
00462 
00463         // The dll function has finished executing, so unload it
00464         FreeLibrary(hDll);
00465     }
00466     else {
00467         // The dll could not be loaded; display an error message
00468         GetModuleTitle();
00469         LoadString( GetModuleHandle(NULL), IDS_DllNotLoaded, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
00470 
00471         lptMsgBuffer = (LPTSTR)malloc((_tcslen(szMsg) - 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
00472         _stprintf(lptMsgBuffer,szMsg,lptDllName);
00473 
00474         MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR);
00475         free(lptMsgBuffer);
00476     }
00477 
00478     if (argv) free(argv);
00479     return nRetVal;
00480 }
00481 

Generated on Sat May 26 2012 04:17:41 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.