Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenregsvr32.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS regsvr32 00003 * Copyright (C) 2004-2006 ReactOS Team 00004 * 00005 * COPYRIGHT: See COPYING in the top level directory 00006 * PROJECT: ReactOS regsvr32.exe 00007 * FILE: base/system/regsvr32/regsvr32.c 00008 * PURPOSE: Register a COM component in the registry 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 <ole2.h> 00028 #include <stdio.h> 00029 #include <string.h> 00030 #include <malloc.h> 00031 #include <tchar.h> 00032 00033 typedef HRESULT (WINAPI *DLLREGISTER)(void); 00034 typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPWSTR lpwCmdLine); 00035 00036 #define EXITCODE_SUCCESS 0 00037 #define EXITCODE_PARAMERROR 1 00038 #define EXITCODE_LOADERROR 3 00039 #define EXITCODE_NOENTRY 4 00040 #define EXITCODE_FAILURE 5 00041 00042 LPCSTR szDllRegister = "DllRegisterServer"; 00043 LPCSTR szDllUnregister = "DllUnregisterServer"; 00044 LPCSTR szDllInstall = "DllInstall"; 00045 #ifdef UNICODE 00046 LPCWSTR tszDllRegister = L"DllRegisterServer"; 00047 LPCWSTR tszDllUnregister = L"DllUnregisterServer"; 00048 LPCWSTR tszDllInstall = L"DllInstall"; 00049 #else 00050 #define tszDllRegister szDllRegister 00051 #define tszDllUnregister szDllUnregister 00052 #define tszDllInstall szDllInstall 00053 #endif 00054 00055 00056 00057 #include "resource.h" 00058 00059 LPCTSTR ModuleTitle = _T("RegSvr32"); 00060 00061 TCHAR UsageMessage[RC_STRING_MAX_SIZE]; 00062 TCHAR NoDllSpecified[RC_STRING_MAX_SIZE]; 00063 TCHAR InvalidFlag[RC_STRING_MAX_SIZE]; 00064 TCHAR SwitchN_NoI[RC_STRING_MAX_SIZE]; 00065 TCHAR DllNotLoaded[RC_STRING_MAX_SIZE]; 00066 TCHAR MissingEntry[RC_STRING_MAX_SIZE]; 00067 TCHAR FailureMessage[RC_STRING_MAX_SIZE]; 00068 TCHAR SuccessMessage[RC_STRING_MAX_SIZE]; 00069 00070 00071 // The macro CommandLineToArgv maps to a function that converts 00072 // a command-line string to argc and argv similar to the ones 00073 // in the standard main function. If this code is compiled for 00074 // unicode, the build-in Windows API function is used, otherwise 00075 // a non-unicode non-API version is used for compatibility with 00076 // Windows versions that have no unicode support. 00077 #ifdef UNICODE 00078 #define CommandLineToArgv CommandLineToArgvW 00079 #include <shellapi.h> 00080 #else 00081 #define CommandLineToArgv CommandLineToArgvT 00082 00083 LPTSTR *WINAPI CommandLineToArgvT(LPCTSTR lpCmdLine, int *lpArgc) 00084 { 00085 HGLOBAL hargv; 00086 LPTSTR *argv, lpSrc, lpDest, lpArg; 00087 int argc, nBSlash; 00088 BOOL bInQuotes; 00089 00090 // If null was passed in for lpCmdLine, there are no arguments 00091 if (!lpCmdLine) { 00092 if (lpArgc) 00093 *lpArgc = 0; 00094 return 0; 00095 } 00096 00097 lpSrc = (LPTSTR)lpCmdLine; 00098 // Skip spaces at beginning 00099 while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) 00100 lpSrc++; 00101 00102 // If command-line starts with null, there are no arguments 00103 if (*lpSrc == 0) { 00104 if (lpArgc) 00105 *lpArgc = 0; 00106 return 0; 00107 } 00108 00109 lpArg = lpSrc; 00110 argc = 0; 00111 nBSlash = 0; 00112 bInQuotes = FALSE; 00113 00114 // Count the number of arguments 00115 while (1) { 00116 if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { 00117 // Whitespace not enclosed in quotes signals the start of another argument 00118 argc++; 00119 00120 // Skip whitespace between arguments 00121 while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) 00122 lpSrc++; 00123 if (*lpSrc == 0) 00124 break; 00125 nBSlash = 0; 00126 continue; 00127 } 00128 else if (*lpSrc == _T('\\')) { 00129 // Count consecutive backslashes 00130 nBSlash++; 00131 } 00132 else if (*lpSrc == _T('\"') && !(nBSlash & 1)) { 00133 // Open or close quotes 00134 bInQuotes = !bInQuotes; 00135 nBSlash = 0; 00136 } 00137 else { 00138 // Some other character 00139 nBSlash = 0; 00140 } 00141 lpSrc++; 00142 } 00143 00144 // Allocate space the same way as CommandLineToArgvW for compatibility 00145 hargv = GlobalAlloc(0, argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR)); 00146 argv = (LPTSTR *)GlobalLock(hargv); 00147 00148 if (!argv) { 00149 // Memory allocation failed 00150 if (lpArgc) 00151 *lpArgc = 0; 00152 return 0; 00153 } 00154 00155 lpSrc = lpArg; 00156 lpDest = lpArg = (LPTSTR)(argv + argc); 00157 argc = 0; 00158 nBSlash = 0; 00159 bInQuotes = FALSE; 00160 00161 // Fill the argument array 00162 while (1) { 00163 if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { 00164 // Whitespace not enclosed in quotes signals the start of another argument 00165 // Null-terminate argument 00166 *lpDest++ = 0; 00167 argv[argc++] = lpArg; 00168 00169 // Skip whitespace between arguments 00170 while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) 00171 lpSrc++; 00172 if (*lpSrc == 0) 00173 break; 00174 lpArg = lpDest; 00175 nBSlash = 0; 00176 continue; 00177 } 00178 else if (*lpSrc == _T('\\')) { 00179 *lpDest++ = _T('\\'); 00180 lpSrc++; 00181 00182 // Count consecutive backslashes 00183 nBSlash++; 00184 } 00185 else if (*lpSrc == _T('\"')) { 00186 if (!(nBSlash & 1)) { 00187 // If an even number of backslashes are before the quotes, 00188 // the quotes don't go in the output 00189 lpDest -= nBSlash / 2; 00190 bInQuotes = !bInQuotes; 00191 } 00192 else { 00193 // If an odd number of backslashes are before the quotes, 00194 // output a quote 00195 lpDest -= (nBSlash + 1) / 2; 00196 *lpDest++ = _T('\"'); 00197 } 00198 lpSrc++; 00199 nBSlash = 0; 00200 } 00201 else { 00202 // Copy other characters 00203 *lpDest++ = *lpSrc++; 00204 nBSlash = 0; 00205 } 00206 } 00207 00208 if (lpArgc) 00209 *lpArgc = argc; 00210 return argv; 00211 } 00212 00213 #endif 00214 00215 // The macro ConvertToWideChar takes a tstring parameter and returns 00216 // a pointer to a unicode string. A conversion is performed if 00217 // neccessary. FreeConvertedWideChar string should be used on the 00218 // return value of ConvertToWideChar when the string is no longer 00219 // needed. The original string or the string that is returned 00220 // should not be modified until FreeConvertedWideChar has been called. 00221 #ifdef UNICODE 00222 #define ConvertToWideChar(lptString) (lptString) 00223 #define FreeConvertedWideChar(lpwString) ((void) 0) 00224 #else 00225 00226 LPWSTR ConvertToWideChar(LPCSTR lpString) 00227 { 00228 LPWSTR lpwString; 00229 size_t nStrLen; 00230 00231 nStrLen = strlen(lpString) + 1; 00232 00233 lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR)); 00234 MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen); 00235 00236 return lpwString; 00237 } 00238 00239 #define FreeConvertedWideChar(lpwString) free(lpwString) 00240 #endif 00241 00242 void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType) 00243 { 00244 if (!bSilent) 00245 MessageBox(0,lpMessage,lpTitle,uType); 00246 if (bConsole) 00247 _tprintf(_T("%s: %s\n\n"),lpTitle,lpMessage); 00248 } 00249 00250 int WINAPI _tWinMain( 00251 HINSTANCE hInstance, 00252 HINSTANCE hPrevInstance, 00253 LPTSTR lpCmdLine, 00254 int nCmdShow 00255 ) 00256 { 00257 int argc; 00258 LPTSTR *argv; 00259 LPTSTR lptDllName,lptDllCmdLine,lptMsgBuffer; 00260 LPCTSTR lptFuncName; 00261 LPCSTR lpFuncName; 00262 LPWSTR lpwDllCmdLine; 00263 BOOL bUnregister,bSilent,bConsole,bInstall,bNoRegister; 00264 UINT nDllCount; 00265 HMODULE hDll; 00266 DLLREGISTER fnDllRegister; 00267 DLLINSTALL fnDllInstall; 00268 HRESULT hResult; 00269 DWORD dwErr; 00270 int nRetValue,i; 00271 00272 // Get Langues msg 00273 LoadString( GetModuleHandle(NULL), IDS_UsageMessage, (LPTSTR) UsageMessage,RC_STRING_MAX_SIZE); 00274 LoadString( GetModuleHandle(NULL), IDS_NoDllSpecified, (LPTSTR) NoDllSpecified,RC_STRING_MAX_SIZE); 00275 LoadString( GetModuleHandle(NULL), IDS_InvalidFlag, (LPTSTR) InvalidFlag,RC_STRING_MAX_SIZE); 00276 LoadString( GetModuleHandle(NULL), IDS_SwitchN_NoI, (LPTSTR) SwitchN_NoI,RC_STRING_MAX_SIZE); 00277 00278 LoadString( GetModuleHandle(NULL), IDS_DllNotLoaded, (LPTSTR) DllNotLoaded,RC_STRING_MAX_SIZE); 00279 LoadString( GetModuleHandle(NULL), IDS_MissingEntry, (LPTSTR) MissingEntry,RC_STRING_MAX_SIZE); 00280 LoadString( GetModuleHandle(NULL), IDS_FailureMessage, (LPTSTR) FailureMessage,RC_STRING_MAX_SIZE); 00281 LoadString( GetModuleHandle(NULL), IDS_SuccessMessage, (LPTSTR) SuccessMessage,RC_STRING_MAX_SIZE); 00282 00283 // Get command-line in argc-argv format 00284 argv = CommandLineToArgv(GetCommandLine(),&argc); 00285 00286 // Initialize variables 00287 lptFuncName = 0; 00288 lptDllCmdLine = 0; 00289 nDllCount = 0; 00290 bUnregister = FALSE; 00291 bSilent = FALSE; 00292 bConsole = FALSE; 00293 bInstall = FALSE; 00294 bNoRegister = FALSE; 00295 00296 // Find all arguments starting with a slash (/) 00297 for (i = 1; i < argc; i++) { 00298 if (*argv[i] == _T('/')) { 00299 switch (argv[i][1]) { 00300 case _T('u'): 00301 case _T('U'): 00302 bUnregister = TRUE; 00303 break; 00304 case _T('s'): 00305 case _T('S'): 00306 bSilent = TRUE; 00307 break; 00308 case _T('c'): 00309 case _T('C'): 00310 bConsole = TRUE; 00311 break; 00312 case _T('i'): 00313 case _T('I'): 00314 bInstall = TRUE; 00315 lptDllCmdLine = argv[i]; 00316 while (*lptDllCmdLine != 0 && *lptDllCmdLine != _T(':')) 00317 lptDllCmdLine++; 00318 if (*lptDllCmdLine == _T(':')) 00319 lptDllCmdLine++; 00320 break; 00321 case _T('n'): 00322 case _T('N'): 00323 bNoRegister = TRUE; 00324 break; 00325 default: 00326 if (!lptFuncName) 00327 lptFuncName = argv[i]; 00328 } 00329 } 00330 else { 00331 nDllCount++; 00332 } 00333 } 00334 00335 // An unrecognized flag was used, display a message and show available options 00336 00337 if (lptFuncName) { 00338 lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(InvalidFlag) - 2 + _tcslen(lptFuncName) + 1) * sizeof(TCHAR)); 00339 _stprintf(lptMsgBuffer + (_tcslen(UsageMessage) - 2),InvalidFlag,lptFuncName); 00340 _stprintf(lptMsgBuffer,UsageMessage,lptMsgBuffer + (_tcslen(UsageMessage) - 2)); 00341 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00342 free(lptMsgBuffer); 00343 GlobalFree(argv); 00344 return EXITCODE_PARAMERROR; 00345 } 00346 00347 // /n was used without /i, display a message and show available options 00348 if (bNoRegister && (!bInstall)) { 00349 lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(SwitchN_NoI) + 1) * sizeof(TCHAR)); 00350 _stprintf(lptMsgBuffer,UsageMessage,SwitchN_NoI); 00351 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00352 free(lptMsgBuffer); 00353 GlobalFree(argv); 00354 return EXITCODE_PARAMERROR; 00355 } 00356 00357 // No dll was specified, display a message and show available options 00358 if (nDllCount == 0) { 00359 lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(NoDllSpecified) + 1) * sizeof(TCHAR)); 00360 _stprintf(lptMsgBuffer,UsageMessage,NoDllSpecified); 00361 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00362 free(lptMsgBuffer); 00363 GlobalFree(argv); 00364 return EXITCODE_PARAMERROR; 00365 } 00366 00367 nRetValue = EXITCODE_SUCCESS; 00368 if (!bUnregister) { 00369 lpFuncName = szDllRegister; 00370 lptFuncName = tszDllRegister; 00371 } 00372 else { 00373 lpFuncName = szDllUnregister; 00374 lptFuncName = tszDllUnregister; 00375 } 00376 00377 if (lptDllCmdLine) 00378 lpwDllCmdLine = ConvertToWideChar(lptDllCmdLine); 00379 else 00380 lpwDllCmdLine = 0; 00381 00382 // Initialize OLE32 before attempting to register the 00383 // dll. Some dll's require this to register properly 00384 OleInitialize(0); 00385 00386 // (Un)register every dll whose filename was passed in the command-line string 00387 for (i = 1; i < argc && nRetValue == EXITCODE_SUCCESS; i++) { 00388 // Arguments that do not start with a slash (/) are filenames 00389 if (*argv[i] != _T('/')) { 00390 lptDllName = argv[i]; 00391 00392 // Everything is all setup, so load the dll now 00393 hDll = LoadLibraryEx(lptDllName,0,LOAD_WITH_ALTERED_SEARCH_PATH); 00394 if (hDll) { 00395 if (!bNoRegister) { 00396 // Get the address of DllRegisterServer or DllUnregisterServer 00397 fnDllRegister = (DLLREGISTER)GetProcAddress(hDll,lpFuncName); 00398 if (fnDllRegister) { 00399 // If the function exists, call it 00400 hResult = fnDllRegister(); 00401 if (hResult == S_OK) { 00402 // (Un)register succeeded, display a message 00403 lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); 00404 _stprintf(lptMsgBuffer,SuccessMessage,lptFuncName,lptDllName); 00405 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); 00406 } 00407 else { 00408 // (Un)register failed, display a message 00409 lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); 00410 _stprintf(lptMsgBuffer,FailureMessage,lptFuncName,lptDllName,hResult); 00411 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00412 } 00413 free(lptMsgBuffer); 00414 if (hResult != S_OK) 00415 nRetValue = EXITCODE_FAILURE; 00416 } 00417 else { 00418 FreeLibrary(hDll); 00419 // Dll(Un)register was not found, display an error message 00420 lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(lptFuncName) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR)); 00421 _stprintf(lptMsgBuffer,MissingEntry,lptDllName,lptFuncName,lptFuncName,lptDllName); 00422 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00423 free(lptMsgBuffer); 00424 nRetValue = EXITCODE_NOENTRY; 00425 } 00426 } 00427 00428 if (bInstall && nRetValue == EXITCODE_SUCCESS) { 00429 // Get the address of DllInstall 00430 fnDllInstall = (DLLINSTALL)GetProcAddress(hDll,szDllInstall); 00431 if (fnDllInstall) { 00432 // If the function exists, call it 00433 if (!bUnregister) 00434 hResult = fnDllInstall(1,lpwDllCmdLine); 00435 else 00436 hResult = fnDllInstall(0,lpwDllCmdLine); 00437 if (hResult == S_OK) { 00438 // (Un)install succeeded, display a message 00439 lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); 00440 _stprintf(lptMsgBuffer,SuccessMessage,tszDllInstall,lptDllName); 00441 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); 00442 } 00443 else { 00444 // (Un)install failed, display a message 00445 lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); 00446 _stprintf(lptMsgBuffer,FailureMessage,tszDllInstall,lptDllName,hResult); 00447 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00448 } 00449 free(lptMsgBuffer); 00450 if (hResult != S_OK) 00451 nRetValue = EXITCODE_FAILURE; 00452 } 00453 else { 00454 FreeLibrary(hDll); 00455 // DllInstall was not found, display an error message 00456 lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(tszDllInstall) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR)); 00457 _stprintf(lptMsgBuffer,MissingEntry,lptDllName,tszDllInstall,tszDllInstall,lptDllName); 00458 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00459 free(lptMsgBuffer); 00460 nRetValue = EXITCODE_NOENTRY; 00461 } 00462 } 00463 00464 // The dll function has finished executing, so unload it 00465 FreeLibrary(hDll); 00466 } 00467 else { 00468 // The dll could not be loaded; display an error message 00469 dwErr = GetLastError(); 00470 lptMsgBuffer = (LPTSTR)malloc((_tcslen(DllNotLoaded) + 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); 00471 _stprintf(lptMsgBuffer,DllNotLoaded,lptDllName,dwErr); 00472 DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); 00473 free(lptMsgBuffer); 00474 nRetValue = EXITCODE_LOADERROR; 00475 } 00476 } 00477 } 00478 00479 if (lpwDllCmdLine) 00480 FreeConvertedWideChar(lpwDllCmdLine); 00481 GlobalFree(argv); 00482 OleUninitialize(); 00483 return nRetValue; 00484 } 00485 Generated on Sun May 27 2012 04:18:48 for ReactOS by
1.7.6.1
|