From b1fc9ebb0238987e4ae7aa39fa1f506a07467b08 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sun, 15 Feb 2004 05:51:20 +0000 Subject: [PATCH] Author: ShadowFlare Arty's note: Added ShadowFlare's regsvr32. The one in rosapps doesn't seem to build, so I think it should be eventually removed. I'm putting this one here instead of rosapps because it goes with some of the other apps in this directory (like rundll32) svn path=/trunk/; revision=8183 --- reactos/apps/utils/regsvr32/.cvsignore | 6 + reactos/apps/utils/regsvr32/makefile | 21 + reactos/apps/utils/regsvr32/regsvr32.c | 487 ++++++++++++++++++++++++ reactos/apps/utils/regsvr32/regsvr32.rc | 38 ++ 4 files changed, 552 insertions(+) create mode 100644 reactos/apps/utils/regsvr32/.cvsignore create mode 100644 reactos/apps/utils/regsvr32/makefile create mode 100644 reactos/apps/utils/regsvr32/regsvr32.c create mode 100644 reactos/apps/utils/regsvr32/regsvr32.rc diff --git a/reactos/apps/utils/regsvr32/.cvsignore b/reactos/apps/utils/regsvr32/.cvsignore new file mode 100644 index 00000000000..d63774a7353 --- /dev/null +++ b/reactos/apps/utils/regsvr32/.cvsignore @@ -0,0 +1,6 @@ +*.o +*.d +*.exe +*.coff +*.sym +*.map diff --git a/reactos/apps/utils/regsvr32/makefile b/reactos/apps/utils/regsvr32/makefile new file mode 100644 index 00000000000..2aef65ae2ed --- /dev/null +++ b/reactos/apps/utils/regsvr32/makefile @@ -0,0 +1,21 @@ +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = regsvr32 + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = kernel32.a user32.a ole32.a + +TARGET_OBJECTS = regsvr32.o + +TARGET_CFLAGS += -DUNICODE -Wall -Werror -D__USE_W32API + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/reactos/apps/utils/regsvr32/regsvr32.c b/reactos/apps/utils/regsvr32/regsvr32.c new file mode 100644 index 00000000000..4bb958e1958 --- /dev/null +++ b/reactos/apps/utils/regsvr32/regsvr32.c @@ -0,0 +1,487 @@ +/* + * ReactOS regsvr32 + * Copyright (C) 2004 ReactOS Team + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS regsvr32.exe + * FILE: apps/utils/regsvr32/regsvr32.c + * PURPOSE: Register a COM component in the registry + * PROGRAMMER: ShadowFlare (blakflare@hotmail.com) + */ + +#define WIN32_LEAN_AND_MEAN + +// Both UNICODE and _UNICODE must be either defined or undefined +// because some headers use UNICODE and others use _UNICODE +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#else +#ifdef _UNICODE +#define UNICODE +#endif +#endif + +#include +#include +#include +#include +#include +#include + +typedef HRESULT (WINAPI *DLLREGISTER)(void); +typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPWSTR lpwCmdLine); + +#define EXITCODE_SUCCESS 0 +#define EXITCODE_PARAMERROR 1 +#define EXITCODE_LOADERROR 3 +#define EXITCODE_NOENTRY 4 +#define EXITCODE_FAILURE 5 + +LPCSTR szDllRegister = "DllRegisterServer"; +LPCSTR szDllUnregister = "DllUnregisterServer"; +LPCSTR szDllInstall = "DllInstall"; +#ifdef UNICODE +LPCWSTR tszDllRegister = L"DllRegisterServer"; +LPCWSTR tszDllUnregister = L"DllUnregisterServer"; +LPCWSTR tszDllInstall = L"DllInstall"; +#else +#define tszDllRegister szDllRegister +#define tszDllUnregister szDllUnregister +#define tszDllInstall szDllInstall +#endif + +LPCTSTR ModuleTitle = _T("RegSvr32"); +LPCTSTR UsageMessage = + _T("%s\n\n") + _T("Usage: regsvr32 [/u] [/s] [/c] [/n] [/i[:cmdline]] dllname\n") + _T("/u - Unregister server\n") + _T("/s - Silent; display no message boxes\n") + _T("/c - Console output\n") + _T("/i - Call DllInstall passing it an optional [cmdline]; when used with /u calls dll uninstall\n") + _T("/n - Do not call DllRegisterServer; this option must be used with /i"); +LPCTSTR NoDllSpecified = _T("No DLL name specified."); +LPCTSTR InvalidFlag = _T("Unrecognized flag: %s"); +LPCTSTR SwitchN_NoI = _T("Unrecognized flag: /n must be used with the /i switch"); +LPCTSTR DllNotLoaded = + _T("LoadLibrary(\"%s\") failed.\n") + _T("GetLastError returns 0x%08x."); +LPCTSTR MissingEntry = + _T("%s was loaded, but the %s entry point was not found.\n\n") + _T("%s may not be exported, or a corrupt version of %s may be in memory. Consider using PView to detect and remove it."); +LPCTSTR FailureMessage = + _T("%s in %s failed.\n") + _T("Return code was: 0x%08x"); +LPCTSTR SuccessMessage = _T("%s in %s succeeded."); + +// The macro CommandLineToArgv maps to a function that converts +// a command-line string to argc and argv similar to the ones +// in the standard main function. If this code is compiled for +// unicode, the build-in Windows API function is used, otherwise +// a non-unicode non-API version is used for compatibility with +// Windows versions that have no unicode support. +#ifdef UNICODE +#define CommandLineToArgv CommandLineToArgvW +#include +#else +#define CommandLineToArgv CommandLineToArgvT + +LPTSTR *WINAPI CommandLineToArgvT(LPCTSTR lpCmdLine, int *lpArgc) +{ + HGLOBAL hargv; + LPTSTR *argv, lpSrc, lpDest, lpArg; + int argc, nBSlash; + BOOL bInQuotes; + + // If null was passed in for lpCmdLine, there are no arguments + if (!lpCmdLine) { + if (lpArgc) + *lpArgc = 0; + return 0; + } + + lpSrc = (LPTSTR)lpCmdLine; + // Skip spaces at beginning + while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) + lpSrc++; + + // If command-line starts with null, there are no arguments + if (*lpSrc == 0) { + if (lpArgc) + *lpArgc = 0; + return 0; + } + + lpArg = lpSrc; + argc = 0; + nBSlash = 0; + bInQuotes = FALSE; + + // Count the number of arguments + while (1) { + if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { + // Whitespace not enclosed in quotes signals the start of another argument + argc++; + + // Skip whitespace between arguments + while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) + lpSrc++; + if (*lpSrc == 0) + break; + nBSlash = 0; + continue; + } + else if (*lpSrc == _T('\\')) { + // Count consecutive backslashes + nBSlash++; + } + else if (*lpSrc == _T('\"') && !(nBSlash & 1)) { + // Open or close quotes + bInQuotes = !bInQuotes; + nBSlash = 0; + } + else { + // Some other character + nBSlash = 0; + } + lpSrc++; + } + + // Allocate space the same way as CommandLineToArgvW for compatibility + hargv = GlobalAlloc(0, argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR)); + argv = (LPTSTR *)GlobalLock(hargv); + + if (!argv) { + // Memory allocation failed + if (lpArgc) + *lpArgc = 0; + return 0; + } + + lpSrc = lpArg; + lpDest = lpArg = (LPTSTR)(argv + argc); + argc = 0; + nBSlash = 0; + bInQuotes = FALSE; + + // Fill the argument array + while (1) { + if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { + // Whitespace not enclosed in quotes signals the start of another argument + // Null-terminate argument + *lpDest++ = 0; + argv[argc++] = lpArg; + + // Skip whitespace between arguments + while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) + lpSrc++; + if (*lpSrc == 0) + break; + lpArg = lpDest; + nBSlash = 0; + continue; + } + else if (*lpSrc == _T('\\')) { + *lpDest++ = _T('\\'); + lpSrc++; + + // Count consecutive backslashes + nBSlash++; + } + else if (*lpSrc == _T('\"')) { + if (!(nBSlash & 1)) { + // If an even number of backslashes are before the quotes, + // the quotes don't go in the output + lpDest -= nBSlash / 2; + bInQuotes = !bInQuotes; + } + else { + // If an odd number of backslashes are before the quotes, + // output a quote + lpDest -= (nBSlash + 1) / 2; + *lpDest++ = _T('\"'); + } + lpSrc++; + nBSlash = 0; + } + else { + // Copy other characters + *lpDest++ = *lpSrc++; + nBSlash = 0; + } + } + + if (lpArgc) + *lpArgc = argc; + return argv; +} + +#endif + +// The macro ConvertToWideChar takes a tstring parameter and returns +// a pointer to a unicode string. A conversion is performed if +// neccessary. FreeConvertedWideChar string should be used on the +// return value of ConvertToWideChar when the string is no longer +// needed. The original string or the string that is returned +// should not be modified until FreeConvertedWideChar has been called. +#ifdef UNICODE +#define ConvertToWideChar(lptString) (lptString) +#define FreeConvertedWideChar(lpwString) +#else + +LPWSTR ConvertToWideChar(LPCSTR lpString) +{ + LPWSTR lpwString; + size_t nStrLen; + + nStrLen = strlen(lpString) + 1; + + lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR)); + MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen); + + return lpwString; +} + +#define FreeConvertedWideChar(lpwString) free(lpwString) +#endif + +int WINAPI WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLineA, + int nCmdShow +) +{ + int argc; + LPTSTR *argv; + LPTSTR lptDllName,lptDllCmdLine,lptMsgBuffer; + LPCTSTR lptFuncName; + LPCSTR lpFuncName; + LPWSTR lpwDllCmdLine; + BOOL bUnregister,bSilent,bConsole,bInstall,bNoRegister; + UINT nDllCount; + HMODULE hDll; + DLLREGISTER fnDllRegister; + DLLINSTALL fnDllInstall; + HRESULT hResult; + DWORD dwErr; + int nRetValue,i; + + // Get command-line in argc-argv format + argv = CommandLineToArgv(GetCommandLine(),&argc); + + // Initialize variables + lptFuncName = 0; + lptDllCmdLine = 0; + nDllCount = 0; + bUnregister = FALSE; + bSilent = FALSE; + bConsole = FALSE; + bInstall = FALSE; + bNoRegister = FALSE; + + // Find all arguments starting with a slash (/) + for (i = 1; i < argc; i++) { + if (*argv[i] == _T('/')) { + switch (argv[i][1]) { + case _T('u'): + case _T('U'): + bUnregister = TRUE; + break; + case _T('s'): + case _T('S'): + bSilent = TRUE; + break; + case _T('c'): + case _T('C'): + bConsole = TRUE; + break; + case _T('i'): + case _T('I'): + bInstall = TRUE; + if (argv[i][2] == _T(':')) + lptDllCmdLine = argv[i]+3; + else + lptDllCmdLine = _T(""); + break; + case _T('n'): + case _T('N'): + bNoRegister = TRUE; + break; + default: + if (!lptFuncName) + lptFuncName = argv[i]; + } + } + else { + nDllCount++; + } + } + + // An unrecognized flag was used, display a message and show available options + if (lptFuncName) { + if (!bSilent) { + lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(InvalidFlag) - 2 + _tcslen(lptFuncName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer + (_tcslen(UsageMessage) - 2),InvalidFlag,lptFuncName); + _stprintf(lptMsgBuffer,UsageMessage,lptMsgBuffer + (_tcslen(UsageMessage) - 2)); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + GlobalFree(argv); + return EXITCODE_PARAMERROR; + } + + // /n was used without /i, display a message and show available options + if (bNoRegister && (!bInstall)) { + if (!bSilent) { + lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(SwitchN_NoI) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,UsageMessage,SwitchN_NoI); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + GlobalFree(argv); + return EXITCODE_PARAMERROR; + } + + // No dll was specified, display a message and show available options + if (nDllCount == 0) { + if (!bSilent) { + lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(NoDllSpecified) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,UsageMessage,NoDllSpecified); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + GlobalFree(argv); + return EXITCODE_PARAMERROR; + } + + nRetValue = EXITCODE_SUCCESS; + if (!bUnregister) { + lpFuncName = szDllRegister; + lptFuncName = tszDllRegister; + } + else { + lpFuncName = szDllUnregister; + lptFuncName = tszDllUnregister; + } + + if (lptDllCmdLine) + lpwDllCmdLine = ConvertToWideChar(lptDllCmdLine); + else + lpwDllCmdLine = 0; + + // Initialize OLE32 before attempting to register the + // dll. Some dll's require this to register properly + OleInitialize(0); + + // (Un)register every dll whose filename was passed in the command-line string + for (i = 1; i < argc; i++) { + // Arguments that do not start with a slash (/) are filenames + if (*argv[i] != _T('/')) { + lptDllName = argv[i]; + + // Everything is all setup, so load the dll now + hDll = LoadLibrary(lptDllName); + if (hDll) { + if (!bNoRegister) { + // Get the address of DllRegisterServer or DllUnregisterServer + fnDllRegister = (DLLREGISTER)GetProcAddress(hDll,lpFuncName); + if (fnDllRegister) { + // If the function exists, call it + hResult = fnDllRegister(); + if (!bSilent) { + if (hResult == S_OK) { + // (Un)register succeeded, display a message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,SuccessMessage,lptFuncName,lptDllName); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); + } + else { + // (Un)register failed, display a message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,FailureMessage,lptFuncName,lptDllName,hResult); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + } + free(lptMsgBuffer); + } + if (hResult != S_OK) + nRetValue = EXITCODE_FAILURE; + } + else { + FreeLibrary(hDll); + if (!bSilent) { + // Dll(Un)register was not found, display an error message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(lptFuncName) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,MissingEntry,lptDllName,lptFuncName,lptFuncName,lptDllName); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + nRetValue = EXITCODE_NOENTRY; + } + } + + if (bInstall) { + // Get the address of DllInstall + fnDllInstall = (DLLINSTALL)GetProcAddress(hDll,szDllInstall); + if (fnDllInstall) { + // If the function exists, call it + if (!bUnregister) + hResult = fnDllInstall(1,lpwDllCmdLine); + else + hResult = fnDllInstall(0,lpwDllCmdLine); + if (!bSilent) { + if (hResult == S_OK) { + // (Un)install succeeded, display a message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,SuccessMessage,tszDllInstall,lptDllName); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); + } + else { + // (Un)install failed, display a message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,FailureMessage,tszDllInstall,lptDllName,hResult); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + } + free(lptMsgBuffer); + } + if (hResult != S_OK) + nRetValue = EXITCODE_FAILURE; + } + else { + FreeLibrary(hDll); + if (!bSilent) { + // DllInstall was not found, display an error message + lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(tszDllInstall) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,MissingEntry,lptDllName,tszDllInstall,tszDllInstall,lptDllName); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + nRetValue = EXITCODE_NOENTRY; + } + } + + // The dll function has finished executing, so unload it + FreeLibrary(hDll); + } + else { + if (!bSilent) { + // The dll could not be loaded; display an error message + dwErr = GetLastError(); + lptMsgBuffer = (LPTSTR)malloc((_tcslen(DllNotLoaded) + 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); + _stprintf(lptMsgBuffer,DllNotLoaded,lptDllName,dwErr); + MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); + free(lptMsgBuffer); + } + nRetValue = EXITCODE_LOADERROR; + } + } + } + + if (lpwDllCmdLine) + FreeConvertedWideChar(lpwDllCmdLine); + GlobalFree(argv); + OleUninitialize(); + return nRetValue; +} + diff --git a/reactos/apps/utils/regsvr32/regsvr32.rc b/reactos/apps/utils/regsvr32/regsvr32.rc new file mode 100644 index 00000000000..99c008244e8 --- /dev/null +++ b/reactos/apps/utils/regsvr32/regsvr32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Register a COM component in the registry\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "regsvr32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "regsvr32.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END +