- Fixed line endings

- Updated regsvr32 to latest version by ShadowFlare.

svn path=/trunk/; revision=8265
This commit is contained in:
Filip Navara 2004-02-19 19:26:52 +00:00
parent bb25722258
commit e4340278d7
2 changed files with 947 additions and 954 deletions

View file

@ -1,487 +1,480 @@
/* /*
* ReactOS regsvr32 * ReactOS regsvr32
* Copyright (C) 2004 ReactOS Team * Copyright (C) 2004 ReactOS Team
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS regsvr32.exe * PROJECT: ReactOS regsvr32.exe
* FILE: apps/utils/regsvr32/regsvr32.c * FILE: apps/utils/regsvr32/regsvr32.c
* PURPOSE: Register a COM component in the registry * PURPOSE: Register a COM component in the registry
* PROGRAMMER: ShadowFlare (blakflare@hotmail.com) * PROGRAMMER: ShadowFlare (blakflare@hotmail.com)
*/ */
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
// Both UNICODE and _UNICODE must be either defined or undefined // Both UNICODE and _UNICODE must be either defined or undefined
// because some headers use UNICODE and others use _UNICODE // because some headers use UNICODE and others use _UNICODE
#ifdef UNICODE #ifdef UNICODE
#ifndef _UNICODE #ifndef _UNICODE
#define _UNICODE #define _UNICODE
#endif #endif
#else #else
#ifdef _UNICODE #ifdef _UNICODE
#define UNICODE #define UNICODE
#endif #endif
#endif #endif
#include <windows.h> #include <windows.h>
#include <ole2.h> #include <ole2.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <tchar.h> #include <tchar.h>
typedef HRESULT (WINAPI *DLLREGISTER)(void); typedef HRESULT (WINAPI *DLLREGISTER)(void);
typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPWSTR lpwCmdLine); typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPWSTR lpwCmdLine);
#define EXITCODE_SUCCESS 0 #define EXITCODE_SUCCESS 0
#define EXITCODE_PARAMERROR 1 #define EXITCODE_PARAMERROR 1
#define EXITCODE_LOADERROR 3 #define EXITCODE_LOADERROR 3
#define EXITCODE_NOENTRY 4 #define EXITCODE_NOENTRY 4
#define EXITCODE_FAILURE 5 #define EXITCODE_FAILURE 5
LPCSTR szDllRegister = "DllRegisterServer"; LPCSTR szDllRegister = "DllRegisterServer";
LPCSTR szDllUnregister = "DllUnregisterServer"; LPCSTR szDllUnregister = "DllUnregisterServer";
LPCSTR szDllInstall = "DllInstall"; LPCSTR szDllInstall = "DllInstall";
#ifdef UNICODE #ifdef UNICODE
LPCWSTR tszDllRegister = L"DllRegisterServer"; LPCWSTR tszDllRegister = L"DllRegisterServer";
LPCWSTR tszDllUnregister = L"DllUnregisterServer"; LPCWSTR tszDllUnregister = L"DllUnregisterServer";
LPCWSTR tszDllInstall = L"DllInstall"; LPCWSTR tszDllInstall = L"DllInstall";
#else #else
#define tszDllRegister szDllRegister #define tszDllRegister szDllRegister
#define tszDllUnregister szDllUnregister #define tszDllUnregister szDllUnregister
#define tszDllInstall szDllInstall #define tszDllInstall szDllInstall
#endif #endif
LPCTSTR ModuleTitle = _T("RegSvr32"); LPCTSTR ModuleTitle = _T("RegSvr32");
LPCTSTR UsageMessage = LPCTSTR UsageMessage =
_T("%s\n\n") _T("%s\n\n")
_T("Usage: regsvr32 [/u] [/s] [/c] [/n] [/i[:cmdline]] dllname\n") _T("Usage: regsvr32 [/u] [/s] [/c] [/n] [/i[:cmdline]] dllname\n")
_T("/u - Unregister server\n") _T("/u - Unregister server\n")
_T("/s - Silent; display no message boxes\n") _T("/s - Silent; display no message boxes\n")
_T("/c - Console output\n") _T("/c - Console output\n")
_T("/i - Call DllInstall passing it an optional [cmdline]; when used with /u calls dll uninstall\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"); _T("/n - Do not call DllRegisterServer; this option must be used with /i");
LPCTSTR NoDllSpecified = _T("No DLL name specified."); LPCTSTR NoDllSpecified = _T("No DLL name specified.");
LPCTSTR InvalidFlag = _T("Unrecognized flag: %s"); LPCTSTR InvalidFlag = _T("Unrecognized flag: %s");
LPCTSTR SwitchN_NoI = _T("Unrecognized flag: /n must be used with the /i switch"); LPCTSTR SwitchN_NoI = _T("Unrecognized flag: /n must be used with the /i switch");
LPCTSTR DllNotLoaded = LPCTSTR DllNotLoaded =
_T("LoadLibrary(\"%s\") failed.\n") _T("LoadLibrary(\"%s\") failed.\n")
_T("GetLastError returns 0x%08x."); _T("GetLastError returns 0x%08x.");
LPCTSTR MissingEntry = LPCTSTR MissingEntry =
_T("%s was loaded, but the %s entry point was not found.\n\n") _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."); _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 = LPCTSTR FailureMessage =
_T("%s in %s failed.\n") _T("%s in %s failed.\n")
_T("Return code was: 0x%08x"); _T("Return code was: 0x%08x");
LPCTSTR SuccessMessage = _T("%s in %s succeeded."); LPCTSTR SuccessMessage = _T("%s in %s succeeded.");
// The macro CommandLineToArgv maps to a function that converts // The macro CommandLineToArgv maps to a function that converts
// a command-line string to argc and argv similar to the ones // a command-line string to argc and argv similar to the ones
// in the standard main function. If this code is compiled for // in the standard main function. If this code is compiled for
// unicode, the build-in Windows API function is used, otherwise // unicode, the build-in Windows API function is used, otherwise
// a non-unicode non-API version is used for compatibility with // a non-unicode non-API version is used for compatibility with
// Windows versions that have no unicode support. // Windows versions that have no unicode support.
#ifdef UNICODE #ifdef UNICODE
#define CommandLineToArgv CommandLineToArgvW #define CommandLineToArgv CommandLineToArgvW
#include <shellapi.h> #include <shellapi.h>
#else #else
#define CommandLineToArgv CommandLineToArgvT #define CommandLineToArgv CommandLineToArgvT
LPTSTR *WINAPI CommandLineToArgvT(LPCTSTR lpCmdLine, int *lpArgc) LPTSTR *WINAPI CommandLineToArgvT(LPCTSTR lpCmdLine, int *lpArgc)
{ {
HGLOBAL hargv; HGLOBAL hargv;
LPTSTR *argv, lpSrc, lpDest, lpArg; LPTSTR *argv, lpSrc, lpDest, lpArg;
int argc, nBSlash; int argc, nBSlash;
BOOL bInQuotes; BOOL bInQuotes;
// If null was passed in for lpCmdLine, there are no arguments // If null was passed in for lpCmdLine, there are no arguments
if (!lpCmdLine) { if (!lpCmdLine) {
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpSrc = (LPTSTR)lpCmdLine; lpSrc = (LPTSTR)lpCmdLine;
// Skip spaces at beginning // Skip spaces at beginning
while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) while (*lpSrc == _T(' ') || *lpSrc == _T('\t'))
lpSrc++; lpSrc++;
// If command-line starts with null, there are no arguments // If command-line starts with null, there are no arguments
if (*lpSrc == 0) { if (*lpSrc == 0) {
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpArg = lpSrc; lpArg = lpSrc;
argc = 0; argc = 0;
nBSlash = 0; nBSlash = 0;
bInQuotes = FALSE; bInQuotes = FALSE;
// Count the number of arguments // Count the number of arguments
while (1) { while (1) {
if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
// Whitespace not enclosed in quotes signals the start of another argument // Whitespace not enclosed in quotes signals the start of another argument
argc++; argc++;
// Skip whitespace between arguments // Skip whitespace between arguments
while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) while (*lpSrc == _T(' ') || *lpSrc == _T('\t'))
lpSrc++; lpSrc++;
if (*lpSrc == 0) if (*lpSrc == 0)
break; break;
nBSlash = 0; nBSlash = 0;
continue; continue;
} }
else if (*lpSrc == _T('\\')) { else if (*lpSrc == _T('\\')) {
// Count consecutive backslashes // Count consecutive backslashes
nBSlash++; nBSlash++;
} }
else if (*lpSrc == _T('\"') && !(nBSlash & 1)) { else if (*lpSrc == _T('\"') && !(nBSlash & 1)) {
// Open or close quotes // Open or close quotes
bInQuotes = !bInQuotes; bInQuotes = !bInQuotes;
nBSlash = 0; nBSlash = 0;
} }
else { else {
// Some other character // Some other character
nBSlash = 0; nBSlash = 0;
} }
lpSrc++; lpSrc++;
} }
// Allocate space the same way as CommandLineToArgvW for compatibility // Allocate space the same way as CommandLineToArgvW for compatibility
hargv = GlobalAlloc(0, argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR)); hargv = GlobalAlloc(0, argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR));
argv = (LPTSTR *)GlobalLock(hargv); argv = (LPTSTR *)GlobalLock(hargv);
if (!argv) { if (!argv) {
// Memory allocation failed // Memory allocation failed
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpSrc = lpArg; lpSrc = lpArg;
lpDest = lpArg = (LPTSTR)(argv + argc); lpDest = lpArg = (LPTSTR)(argv + argc);
argc = 0; argc = 0;
nBSlash = 0; nBSlash = 0;
bInQuotes = FALSE; bInQuotes = FALSE;
// Fill the argument array // Fill the argument array
while (1) { while (1) {
if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { if (*lpSrc == 0 || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
// Whitespace not enclosed in quotes signals the start of another argument // Whitespace not enclosed in quotes signals the start of another argument
// Null-terminate argument // Null-terminate argument
*lpDest++ = 0; *lpDest++ = 0;
argv[argc++] = lpArg; argv[argc++] = lpArg;
// Skip whitespace between arguments // Skip whitespace between arguments
while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) while (*lpSrc == _T(' ') || *lpSrc == _T('\t'))
lpSrc++; lpSrc++;
if (*lpSrc == 0) if (*lpSrc == 0)
break; break;
lpArg = lpDest; lpArg = lpDest;
nBSlash = 0; nBSlash = 0;
continue; continue;
} }
else if (*lpSrc == _T('\\')) { else if (*lpSrc == _T('\\')) {
*lpDest++ = _T('\\'); *lpDest++ = _T('\\');
lpSrc++; lpSrc++;
// Count consecutive backslashes // Count consecutive backslashes
nBSlash++; nBSlash++;
} }
else if (*lpSrc == _T('\"')) { else if (*lpSrc == _T('\"')) {
if (!(nBSlash & 1)) { if (!(nBSlash & 1)) {
// If an even number of backslashes are before the quotes, // If an even number of backslashes are before the quotes,
// the quotes don't go in the output // the quotes don't go in the output
lpDest -= nBSlash / 2; lpDest -= nBSlash / 2;
bInQuotes = !bInQuotes; bInQuotes = !bInQuotes;
} }
else { else {
// If an odd number of backslashes are before the quotes, // If an odd number of backslashes are before the quotes,
// output a quote // output a quote
lpDest -= (nBSlash + 1) / 2; lpDest -= (nBSlash + 1) / 2;
*lpDest++ = _T('\"'); *lpDest++ = _T('\"');
} }
lpSrc++; lpSrc++;
nBSlash = 0; nBSlash = 0;
} }
else { else {
// Copy other characters // Copy other characters
*lpDest++ = *lpSrc++; *lpDest++ = *lpSrc++;
nBSlash = 0; nBSlash = 0;
} }
} }
if (lpArgc) if (lpArgc)
*lpArgc = argc; *lpArgc = argc;
return argv; return argv;
} }
#endif #endif
// The macro ConvertToWideChar takes a tstring parameter and returns // The macro ConvertToWideChar takes a tstring parameter and returns
// a pointer to a unicode string. A conversion is performed if // a pointer to a unicode string. A conversion is performed if
// neccessary. FreeConvertedWideChar string should be used on the // neccessary. FreeConvertedWideChar string should be used on the
// return value of ConvertToWideChar when the string is no longer // return value of ConvertToWideChar when the string is no longer
// needed. The original string or the string that is returned // needed. The original string or the string that is returned
// should not be modified until FreeConvertedWideChar has been called. // should not be modified until FreeConvertedWideChar has been called.
#ifdef UNICODE #ifdef UNICODE
#define ConvertToWideChar(lptString) (lptString) #define ConvertToWideChar(lptString) (lptString)
#define FreeConvertedWideChar(lpwString) #define FreeConvertedWideChar(lpwString)
#else #else
LPWSTR ConvertToWideChar(LPCSTR lpString) LPWSTR ConvertToWideChar(LPCSTR lpString)
{ {
LPWSTR lpwString; LPWSTR lpwString;
size_t nStrLen; size_t nStrLen;
nStrLen = strlen(lpString) + 1; nStrLen = strlen(lpString) + 1;
lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR)); lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR));
MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen); MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen);
return lpwString; return lpwString;
} }
#define FreeConvertedWideChar(lpwString) free(lpwString) #define FreeConvertedWideChar(lpwString) free(lpwString)
#endif #endif
int WINAPI WinMain( void DisplayMessage(BOOL bConsole, BOOL bSilent, LPCTSTR lpMessage, LPCTSTR lpTitle, UINT uType)
HINSTANCE hInstance, {
HINSTANCE hPrevInstance, if (!bSilent)
LPSTR lpCmdLineA, MessageBox(0,lpMessage,lpTitle,uType);
int nCmdShow if (bConsole)
) _tprintf(_T("%s: %s\n\n"),lpTitle,lpMessage);
{ }
int argc;
LPTSTR *argv; int WINAPI WinMain(
LPTSTR lptDllName,lptDllCmdLine,lptMsgBuffer; HINSTANCE hInstance,
LPCTSTR lptFuncName; HINSTANCE hPrevInstance,
LPCSTR lpFuncName; LPSTR lpCmdLineA,
LPWSTR lpwDllCmdLine; int nCmdShow
BOOL bUnregister,bSilent,bConsole,bInstall,bNoRegister; )
UINT nDllCount; {
HMODULE hDll; int argc;
DLLREGISTER fnDllRegister; LPTSTR *argv;
DLLINSTALL fnDllInstall; LPTSTR lptDllName,lptDllCmdLine,lptMsgBuffer;
HRESULT hResult; LPCTSTR lptFuncName;
DWORD dwErr; LPCSTR lpFuncName;
int nRetValue,i; LPWSTR lpwDllCmdLine;
BOOL bUnregister,bSilent,bConsole,bInstall,bNoRegister;
// Get command-line in argc-argv format UINT nDllCount;
argv = CommandLineToArgv(GetCommandLine(),&argc); HMODULE hDll;
DLLREGISTER fnDllRegister;
// Initialize variables DLLINSTALL fnDllInstall;
lptFuncName = 0; HRESULT hResult;
lptDllCmdLine = 0; DWORD dwErr;
nDllCount = 0; int nRetValue,i;
bUnregister = FALSE;
bSilent = FALSE; // Get command-line in argc-argv format
bConsole = FALSE; argv = CommandLineToArgv(GetCommandLine(),&argc);
bInstall = FALSE;
bNoRegister = FALSE; // Initialize variables
lptFuncName = 0;
// Find all arguments starting with a slash (/) lptDllCmdLine = 0;
for (i = 1; i < argc; i++) { nDllCount = 0;
if (*argv[i] == _T('/')) { bUnregister = FALSE;
switch (argv[i][1]) { bSilent = FALSE;
case _T('u'): bConsole = FALSE;
case _T('U'): bInstall = FALSE;
bUnregister = TRUE; bNoRegister = FALSE;
break;
case _T('s'): // Find all arguments starting with a slash (/)
case _T('S'): for (i = 1; i < argc; i++) {
bSilent = TRUE; if (*argv[i] == _T('/')) {
break; switch (argv[i][1]) {
case _T('c'): case _T('u'):
case _T('C'): case _T('U'):
bConsole = TRUE; bUnregister = TRUE;
break; break;
case _T('i'): case _T('s'):
case _T('I'): case _T('S'):
bInstall = TRUE; bSilent = TRUE;
if (argv[i][2] == _T(':')) break;
lptDllCmdLine = argv[i]+3; case _T('c'):
else case _T('C'):
lptDllCmdLine = _T(""); bConsole = TRUE;
break; break;
case _T('n'): case _T('i'):
case _T('N'): case _T('I'):
bNoRegister = TRUE; bInstall = TRUE;
break; lptDllCmdLine = argv[i];
default: while (*lptDllCmdLine != 0 && *lptDllCmdLine != _T(':'))
if (!lptFuncName) lptDllCmdLine++;
lptFuncName = argv[i]; if (*lptDllCmdLine == _T(':'))
} lptDllCmdLine++;
} break;
else { case _T('n'):
nDllCount++; case _T('N'):
} bNoRegister = TRUE;
} break;
default:
// An unrecognized flag was used, display a message and show available options if (!lptFuncName)
if (lptFuncName) { lptFuncName = argv[i];
if (!bSilent) { }
lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(InvalidFlag) - 2 + _tcslen(lptFuncName) + 1) * sizeof(TCHAR)); }
_stprintf(lptMsgBuffer + (_tcslen(UsageMessage) - 2),InvalidFlag,lptFuncName); else {
_stprintf(lptMsgBuffer,UsageMessage,lptMsgBuffer + (_tcslen(UsageMessage) - 2)); nDllCount++;
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); }
free(lptMsgBuffer); }
}
GlobalFree(argv); // An unrecognized flag was used, display a message and show available options
return EXITCODE_PARAMERROR; if (lptFuncName) {
} lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(InvalidFlag) - 2 + _tcslen(lptFuncName) + 1) * sizeof(TCHAR));
_stprintf(lptMsgBuffer + (_tcslen(UsageMessage) - 2),InvalidFlag,lptFuncName);
// /n was used without /i, display a message and show available options _stprintf(lptMsgBuffer,UsageMessage,lptMsgBuffer + (_tcslen(UsageMessage) - 2));
if (bNoRegister && (!bInstall)) { DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
if (!bSilent) { free(lptMsgBuffer);
lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(SwitchN_NoI) + 1) * sizeof(TCHAR)); GlobalFree(argv);
_stprintf(lptMsgBuffer,UsageMessage,SwitchN_NoI); return EXITCODE_PARAMERROR;
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); }
free(lptMsgBuffer);
} // /n was used without /i, display a message and show available options
GlobalFree(argv); if (bNoRegister && (!bInstall)) {
return EXITCODE_PARAMERROR; lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(SwitchN_NoI) + 1) * sizeof(TCHAR));
} _stprintf(lptMsgBuffer,UsageMessage,SwitchN_NoI);
DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
// No dll was specified, display a message and show available options free(lptMsgBuffer);
if (nDllCount == 0) { GlobalFree(argv);
if (!bSilent) { return EXITCODE_PARAMERROR;
lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(NoDllSpecified) + 1) * sizeof(TCHAR)); }
_stprintf(lptMsgBuffer,UsageMessage,NoDllSpecified);
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); // No dll was specified, display a message and show available options
free(lptMsgBuffer); if (nDllCount == 0) {
} lptMsgBuffer = (LPTSTR)malloc((_tcslen(UsageMessage) - 2 + _tcslen(NoDllSpecified) + 1) * sizeof(TCHAR));
GlobalFree(argv); _stprintf(lptMsgBuffer,UsageMessage,NoDllSpecified);
return EXITCODE_PARAMERROR; DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
} free(lptMsgBuffer);
GlobalFree(argv);
nRetValue = EXITCODE_SUCCESS; return EXITCODE_PARAMERROR;
if (!bUnregister) { }
lpFuncName = szDllRegister;
lptFuncName = tszDllRegister; nRetValue = EXITCODE_SUCCESS;
} if (!bUnregister) {
else { lpFuncName = szDllRegister;
lpFuncName = szDllUnregister; lptFuncName = tszDllRegister;
lptFuncName = tszDllUnregister; }
} else {
lpFuncName = szDllUnregister;
if (lptDllCmdLine) lptFuncName = tszDllUnregister;
lpwDllCmdLine = ConvertToWideChar(lptDllCmdLine); }
else
lpwDllCmdLine = 0; if (lptDllCmdLine)
lpwDllCmdLine = ConvertToWideChar(lptDllCmdLine);
// Initialize OLE32 before attempting to register the else
// dll. Some dll's require this to register properly lpwDllCmdLine = 0;
OleInitialize(0);
// Initialize OLE32 before attempting to register the
// (Un)register every dll whose filename was passed in the command-line string // dll. Some dll's require this to register properly
for (i = 1; i < argc; i++) { OleInitialize(0);
// Arguments that do not start with a slash (/) are filenames
if (*argv[i] != _T('/')) { // (Un)register every dll whose filename was passed in the command-line string
lptDllName = argv[i]; for (i = 1; i < argc; i++) {
// Arguments that do not start with a slash (/) are filenames
// Everything is all setup, so load the dll now if (*argv[i] != _T('/')) {
hDll = LoadLibrary(lptDllName); lptDllName = argv[i];
if (hDll) {
if (!bNoRegister) { // Everything is all setup, so load the dll now
// Get the address of DllRegisterServer or DllUnregisterServer hDll = LoadLibraryEx(lptDllName,0,LOAD_WITH_ALTERED_SEARCH_PATH);
fnDllRegister = (DLLREGISTER)GetProcAddress(hDll,lpFuncName); if (hDll) {
if (fnDllRegister) { if (!bNoRegister) {
// If the function exists, call it // Get the address of DllRegisterServer or DllUnregisterServer
hResult = fnDllRegister(); fnDllRegister = (DLLREGISTER)GetProcAddress(hDll,lpFuncName);
if (!bSilent) { if (fnDllRegister) {
if (hResult == S_OK) { // If the function exists, call it
// (Un)register succeeded, display a message hResult = fnDllRegister();
lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); if (hResult == S_OK) {
_stprintf(lptMsgBuffer,SuccessMessage,lptFuncName,lptDllName); // (Un)register succeeded, display a message
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
} _stprintf(lptMsgBuffer,SuccessMessage,lptFuncName,lptDllName);
else { DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION);
// (Un)register failed, display a message }
lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); else {
_stprintf(lptMsgBuffer,FailureMessage,lptFuncName,lptDllName,hResult); // (Un)register failed, display a message
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
} _stprintf(lptMsgBuffer,FailureMessage,lptFuncName,lptDllName,hResult);
free(lptMsgBuffer); DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
} }
if (hResult != S_OK) free(lptMsgBuffer);
nRetValue = EXITCODE_FAILURE; if (hResult != S_OK)
} nRetValue = EXITCODE_FAILURE;
else { }
FreeLibrary(hDll); else {
if (!bSilent) { FreeLibrary(hDll);
// Dll(Un)register was not found, display an error message // 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)); lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(lptFuncName) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR));
_stprintf(lptMsgBuffer,MissingEntry,lptDllName,lptFuncName,lptFuncName,lptDllName); _stprintf(lptMsgBuffer,MissingEntry,lptDllName,lptFuncName,lptFuncName,lptDllName);
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
free(lptMsgBuffer); free(lptMsgBuffer);
} nRetValue = EXITCODE_NOENTRY;
nRetValue = EXITCODE_NOENTRY; }
} }
}
if (bInstall) {
if (bInstall) { // Get the address of DllInstall
// Get the address of DllInstall fnDllInstall = (DLLINSTALL)GetProcAddress(hDll,szDllInstall);
fnDllInstall = (DLLINSTALL)GetProcAddress(hDll,szDllInstall); if (fnDllInstall) {
if (fnDllInstall) { // If the function exists, call it
// If the function exists, call it if (!bUnregister)
if (!bUnregister) hResult = fnDllInstall(1,lpwDllCmdLine);
hResult = fnDllInstall(1,lpwDllCmdLine); else
else hResult = fnDllInstall(0,lpwDllCmdLine);
hResult = fnDllInstall(0,lpwDllCmdLine); if (hResult == S_OK) {
if (!bSilent) { // (Un)install succeeded, display a message
if (hResult == S_OK) { lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
// (Un)install succeeded, display a message _stprintf(lptMsgBuffer,SuccessMessage,tszDllInstall,lptDllName);
lptMsgBuffer = (LPTSTR)malloc((_tcslen(SuccessMessage) - 4 + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION);
_stprintf(lptMsgBuffer,SuccessMessage,tszDllInstall,lptDllName); }
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONINFORMATION); else {
} // (Un)install failed, display a message
else { lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
// (Un)install failed, display a message _stprintf(lptMsgBuffer,FailureMessage,tszDllInstall,lptDllName,hResult);
lptMsgBuffer = (LPTSTR)malloc((_tcslen(FailureMessage) + _tcslen(tszDllInstall) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
_stprintf(lptMsgBuffer,FailureMessage,tszDllInstall,lptDllName,hResult); }
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); free(lptMsgBuffer);
} if (hResult != S_OK)
free(lptMsgBuffer); nRetValue = EXITCODE_FAILURE;
} }
if (hResult != S_OK) else {
nRetValue = EXITCODE_FAILURE; FreeLibrary(hDll);
} // DllInstall was not found, display an error message
else { lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(tszDllInstall) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR));
FreeLibrary(hDll); _stprintf(lptMsgBuffer,MissingEntry,lptDllName,tszDllInstall,tszDllInstall,lptDllName);
if (!bSilent) { DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
// DllInstall was not found, display an error message free(lptMsgBuffer);
lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 8 + _tcslen(tszDllInstall) * 2 + _tcslen(lptDllName) * 2 + 1) * sizeof(TCHAR)); nRetValue = EXITCODE_NOENTRY;
_stprintf(lptMsgBuffer,MissingEntry,lptDllName,tszDllInstall,tszDllInstall,lptDllName); }
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION); }
free(lptMsgBuffer);
} // The dll function has finished executing, so unload it
nRetValue = EXITCODE_NOENTRY; FreeLibrary(hDll);
} }
} else {
// The dll could not be loaded; display an error message
// The dll function has finished executing, so unload it dwErr = GetLastError();
FreeLibrary(hDll); lptMsgBuffer = (LPTSTR)malloc((_tcslen(DllNotLoaded) + 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
} _stprintf(lptMsgBuffer,DllNotLoaded,lptDllName,dwErr);
else { DisplayMessage(bConsole,bSilent,lptMsgBuffer,ModuleTitle,MB_ICONEXCLAMATION);
if (!bSilent) { free(lptMsgBuffer);
// The dll could not be loaded; display an error message nRetValue = EXITCODE_LOADERROR;
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); if (lpwDllCmdLine)
} FreeConvertedWideChar(lpwDllCmdLine);
nRetValue = EXITCODE_LOADERROR; GlobalFree(argv);
} OleUninitialize();
} return nRetValue;
} }
if (lpwDllCmdLine)
FreeConvertedWideChar(lpwDllCmdLine);
GlobalFree(argv);
OleUninitialize();
return nRetValue;
}

View file

@ -1,467 +1,467 @@
/* /*
* ReactOS rundll32 * ReactOS rundll32
* Copyright (C) 2003-2004 ReactOS Team * Copyright (C) 2003-2004 ReactOS Team
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS rundll32.exe * PROJECT: ReactOS rundll32.exe
* FILE: apps/utils/rundll32/rundll32.c * FILE: apps/utils/rundll32/rundll32.c
* PURPOSE: Run a DLL as a program * PURPOSE: Run a DLL as a program
* PROGRAMMER: ShadowFlare (blakflare@hotmail.com) * PROGRAMMER: ShadowFlare (blakflare@hotmail.com)
*/ */
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
// Both UNICODE and _UNICODE must be either defined or undefined // Both UNICODE and _UNICODE must be either defined or undefined
// because some headers use UNICODE and others use _UNICODE // because some headers use UNICODE and others use _UNICODE
#ifdef UNICODE #ifdef UNICODE
#ifndef _UNICODE #ifndef _UNICODE
#define _UNICODE #define _UNICODE
#endif #endif
#else #else
#ifdef _UNICODE #ifdef _UNICODE
#define UNICODE #define UNICODE
#endif #endif
#endif #endif
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <tchar.h> #include <tchar.h>
typedef int (WINAPI *DllWinMainW)( typedef int (WINAPI *DllWinMainW)(
HWND hWnd, HWND hWnd,
HINSTANCE hInstance, HINSTANCE hInstance,
LPWSTR lpwCmdLine, LPWSTR lpwCmdLine,
int nCmdShow int nCmdShow
); );
typedef int (WINAPI *DllWinMainA)( typedef int (WINAPI *DllWinMainA)(
HWND hWnd, HWND hWnd,
HINSTANCE hInstance, HINSTANCE hInstance,
LPSTR lpCmdLine, LPSTR lpCmdLine,
int nCmdShow int nCmdShow
); );
LPCTSTR DllNotLoaded = _T("LoadLibrary failed to load \"%s\""); LPCTSTR DllNotLoaded = _T("LoadLibrary failed to load \"%s\"");
LPCTSTR MissingEntry = _T("Missing entry point:%s\nIn %s"); LPCTSTR MissingEntry = _T("Missing entry point:%s\nIn %s");
LPCTSTR rundll32_wtitle = _T("rundll32"); LPCTSTR rundll32_wtitle = _T("rundll32");
LPCTSTR rundll32_wclass = _T("rundll32_window"); LPCTSTR rundll32_wclass = _T("rundll32_window");
TCHAR ModuleFileName[MAX_PATH+1]; TCHAR ModuleFileName[MAX_PATH+1];
LPTSTR ModuleTitle; LPTSTR ModuleTitle;
// CommandLineToArgv converts a command-line string to argc and // CommandLineToArgv converts a command-line string to argc and
// argv similar to the ones in the standard main function. // argv similar to the ones in the standard main function.
// This is a specialized version coded specifically for rundll32 // This is a specialized version coded specifically for rundll32
// and is not intended to be used in any other program. // and is not intended to be used in any other program.
LPTSTR *WINAPI CommandLineToArgv(LPCTSTR lpCmdLine, int *lpArgc) LPTSTR *WINAPI CommandLineToArgv(LPCTSTR lpCmdLine, int *lpArgc)
{ {
LPTSTR *argv, lpSrc, lpDest, lpArg; LPTSTR *argv, lpSrc, lpDest, lpArg;
int argc, nBSlash, nNames; int argc, nBSlash, nNames;
BOOL bInQuotes, bFirstChar; BOOL bInQuotes, bFirstChar;
// If null was passed in for lpCmdLine, there are no arguments // If null was passed in for lpCmdLine, there are no arguments
if (!lpCmdLine) { if (!lpCmdLine) {
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpSrc = (LPTSTR)lpCmdLine; lpSrc = (LPTSTR)lpCmdLine;
// Skip spaces at beginning // Skip spaces at beginning
while (*lpSrc == _T(' ') || *lpSrc == _T('\t')) while (*lpSrc == _T(' ') || *lpSrc == _T('\t'))
lpSrc++; lpSrc++;
// If command-line starts with null, there are no arguments // If command-line starts with null, there are no arguments
if (*lpSrc == 0) { if (*lpSrc == 0) {
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpArg = lpSrc; lpArg = lpSrc;
argc = 0; argc = 0;
nBSlash = 0; nBSlash = 0;
bInQuotes = FALSE; bInQuotes = FALSE;
bFirstChar = TRUE; bFirstChar = TRUE;
nNames = 0; nNames = 0;
// Count the number of arguments // Count the number of arguments
while (nNames < 4) { while (nNames < 4) {
if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
// Whitespace not enclosed in quotes signals the start of another argument // Whitespace not enclosed in quotes signals the start of another argument
argc++; argc++;
// Skip whitespace between arguments // Skip whitespace between arguments
while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2)) while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2))
lpSrc++; lpSrc++;
if (*lpSrc == 0) if (*lpSrc == 0)
break; break;
if (nNames >= 3) { if (nNames >= 3) {
// Increment the count for the last argument // Increment the count for the last argument
argc++; argc++;
break; break;
} }
nBSlash = 0; nBSlash = 0;
bFirstChar = TRUE; bFirstChar = TRUE;
continue; continue;
} }
else if (*lpSrc == _T('\\')) { else if (*lpSrc == _T('\\')) {
// Count consecutive backslashes // Count consecutive backslashes
nBSlash++; nBSlash++;
bFirstChar = FALSE; bFirstChar = FALSE;
} }
else if (*lpSrc == _T('\"') && !(nBSlash & 1)) { else if (*lpSrc == _T('\"') && !(nBSlash & 1)) {
// Open or close quotes // Open or close quotes
bInQuotes = !bInQuotes; bInQuotes = !bInQuotes;
nBSlash = 0; nBSlash = 0;
} }
else { else {
// Some other character // Some other character
nBSlash = 0; nBSlash = 0;
if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1)) if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1))
nNames++; nNames++;
bFirstChar = FALSE; bFirstChar = FALSE;
} }
lpSrc++; lpSrc++;
} }
// Allocate space for the pointers in argv and the strings in one block // Allocate space for the pointers in argv and the strings in one block
argv = (LPTSTR *)malloc(argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR)); argv = (LPTSTR *)malloc(argc * sizeof(LPTSTR) + (_tcslen(lpArg) + 1) * sizeof(TCHAR));
if (!argv) { if (!argv) {
// Memory allocation failed // Memory allocation failed
if (lpArgc) if (lpArgc)
*lpArgc = 0; *lpArgc = 0;
return 0; return 0;
} }
lpSrc = lpArg; lpSrc = lpArg;
lpDest = lpArg = (LPTSTR)(argv + argc); lpDest = lpArg = (LPTSTR)(argv + argc);
argc = 0; argc = 0;
nBSlash = 0; nBSlash = 0;
bInQuotes = FALSE; bInQuotes = FALSE;
bFirstChar = TRUE; bFirstChar = TRUE;
nNames = 0; nNames = 0;
// Fill the argument array // Fill the argument array
while (nNames < 4) { while (nNames < 4) {
if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) { if (*lpSrc == 0 || (*lpSrc == _T(',') && nNames == 2) || ((*lpSrc == _T(' ') || *lpSrc == _T('\t')) && !bInQuotes)) {
// Whitespace not enclosed in quotes signals the start of another argument // Whitespace not enclosed in quotes signals the start of another argument
// Null-terminate argument // Null-terminate argument
*lpDest++ = 0; *lpDest++ = 0;
argv[argc++] = lpArg; argv[argc++] = lpArg;
// Skip whitespace between arguments // Skip whitespace between arguments
while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2)) while (*lpSrc == _T(' ') || *lpSrc == _T('\t') || (*lpSrc == _T(',') && nNames == 2))
lpSrc++; lpSrc++;
if (*lpSrc == 0) if (*lpSrc == 0)
break; break;
lpArg = lpDest; lpArg = lpDest;
if (nNames >= 3) { if (nNames >= 3) {
// Copy the rest of the command-line to the last argument // Copy the rest of the command-line to the last argument
argv[argc++] = lpArg; argv[argc++] = lpArg;
_tcscpy(lpArg,lpSrc); _tcscpy(lpArg,lpSrc);
break; break;
} }
nBSlash = 0; nBSlash = 0;
bFirstChar = TRUE; bFirstChar = TRUE;
continue; continue;
} }
else if (*lpSrc == _T('\\')) { else if (*lpSrc == _T('\\')) {
*lpDest++ = _T('\\'); *lpDest++ = _T('\\');
lpSrc++; lpSrc++;
// Count consecutive backslashes // Count consecutive backslashes
nBSlash++; nBSlash++;
bFirstChar = FALSE; bFirstChar = FALSE;
} }
else if (*lpSrc == _T('\"')) { else if (*lpSrc == _T('\"')) {
if (!(nBSlash & 1)) { if (!(nBSlash & 1)) {
// If an even number of backslashes are before the quotes, // If an even number of backslashes are before the quotes,
// the quotes don't go in the output // the quotes don't go in the output
lpDest -= nBSlash / 2; lpDest -= nBSlash / 2;
bInQuotes = !bInQuotes; bInQuotes = !bInQuotes;
} }
else { else {
// If an odd number of backslashes are before the quotes, // If an odd number of backslashes are before the quotes,
// output a quote // output a quote
lpDest -= (nBSlash + 1) / 2; lpDest -= (nBSlash + 1) / 2;
*lpDest++ = _T('\"'); *lpDest++ = _T('\"');
bFirstChar = FALSE; bFirstChar = FALSE;
} }
lpSrc++; lpSrc++;
nBSlash = 0; nBSlash = 0;
} }
else { else {
// Copy other characters // Copy other characters
if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1)) if (bFirstChar && ((*lpSrc != _T('/') && nNames <= 1) || nNames > 1))
nNames++; nNames++;
*lpDest++ = *lpSrc++; *lpDest++ = *lpSrc++;
nBSlash = 0; nBSlash = 0;
bFirstChar = FALSE; bFirstChar = FALSE;
} }
} }
if (lpArgc) if (lpArgc)
*lpArgc = argc; *lpArgc = argc;
return argv; return argv;
} }
void GetModuleTitle(void) void GetModuleTitle(void)
{ {
LPTSTR lpStr; LPTSTR lpStr;
GetModuleFileName(0,ModuleFileName,MAX_PATH); GetModuleFileName(0,ModuleFileName,MAX_PATH);
ModuleTitle = ModuleFileName; ModuleTitle = ModuleFileName;
for (lpStr = ModuleFileName;*lpStr;lpStr++) { for (lpStr = ModuleFileName;*lpStr;lpStr++) {
if (*lpStr == _T('\\')) if (*lpStr == _T('\\'))
ModuleTitle = lpStr+1; ModuleTitle = lpStr+1;
} }
for (lpStr = ModuleTitle;*lpStr;lpStr++) { for (lpStr = ModuleTitle;*lpStr;lpStr++) {
if (_tcsicmp(lpStr,_T(".exe"))==0) if (_tcsicmp(lpStr,_T(".exe"))==0)
break; break;
} }
*lpStr = 0; *lpStr = 0;
} }
// The macro ConvertToWideChar takes a tstring parameter and returns // The macro ConvertToWideChar takes a tstring parameter and returns
// a pointer to a unicode string. A conversion is performed if // a pointer to a unicode string. A conversion is performed if
// neccessary. FreeConvertedWideChar string should be used on the // neccessary. FreeConvertedWideChar string should be used on the
// return value of ConvertToWideChar when the string is no longer // return value of ConvertToWideChar when the string is no longer
// needed. The original string or the string that is returned // needed. The original string or the string that is returned
// should not be modified until FreeConvertedWideChar has been called. // should not be modified until FreeConvertedWideChar has been called.
#ifdef UNICODE #ifdef UNICODE
#define ConvertToWideChar(lptString) (lptString) #define ConvertToWideChar(lptString) (lptString)
#define FreeConvertedWideChar(lpwString) #define FreeConvertedWideChar(lpwString)
#else #else
LPWSTR ConvertToWideChar(LPCSTR lpString) LPWSTR ConvertToWideChar(LPCSTR lpString)
{ {
LPWSTR lpwString; LPWSTR lpwString;
size_t nStrLen; size_t nStrLen;
nStrLen = strlen(lpString) + 1; nStrLen = strlen(lpString) + 1;
lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR)); lpwString = (LPWSTR)malloc(nStrLen * sizeof(WCHAR));
MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen); MultiByteToWideChar(0,0,lpString,nStrLen,lpwString,nStrLen);
return lpwString; return lpwString;
} }
#define FreeConvertedWideChar(lpwString) free(lpwString) #define FreeConvertedWideChar(lpwString) free(lpwString)
#endif #endif
// The macro ConvertToMultiByte takes a tstring parameter and returns // The macro ConvertToMultiByte takes a tstring parameter and returns
// a pointer to an ansi string. A conversion is performed if // a pointer to an ansi string. A conversion is performed if
// neccessary. FreeConvertedMultiByte string should be used on the // neccessary. FreeConvertedMultiByte string should be used on the
// return value of ConvertToMultiByte when the string is no longer // return value of ConvertToMultiByte when the string is no longer
// needed. The original string or the string that is returned // needed. The original string or the string that is returned
// should not be modified until FreeConvertedMultiByte has been called. // should not be modified until FreeConvertedMultiByte has been called.
#ifdef UNICODE #ifdef UNICODE
#define ConvertToMultiByte(lptString) DuplicateToMultiByte(lptString,0) #define ConvertToMultiByte(lptString) DuplicateToMultiByte(lptString,0)
#define FreeConvertedMultiByte(lpaString) free(lpaString) #define FreeConvertedMultiByte(lpaString) free(lpaString)
#else #else
#define ConvertToMultiByte(lptString) (lptString) #define ConvertToMultiByte(lptString) (lptString)
#define FreeConvertedMultiByte(lpaString) #define FreeConvertedMultiByte(lpaString)
#endif #endif
// DuplicateToMultiByte takes a tstring parameter and always returns // DuplicateToMultiByte takes a tstring parameter and always returns
// a pointer to a duplicate ansi string. If nBufferSize is zero, // a pointer to a duplicate ansi string. If nBufferSize is zero,
// the buffer length is the exact size of the string plus the // the buffer length is the exact size of the string plus the
// terminating null. If nBufferSize is nonzero, the buffer length // terminating null. If nBufferSize is nonzero, the buffer length
// is equal to nBufferSize. As with strdup, free should be called // is equal to nBufferSize. As with strdup, free should be called
// for the returned string when it is no longer needed. // for the returned string when it is no longer needed.
LPSTR DuplicateToMultiByte(LPCTSTR lptString, size_t nBufferSize) LPSTR DuplicateToMultiByte(LPCTSTR lptString, size_t nBufferSize)
{ {
LPSTR lpString; LPSTR lpString;
size_t nStrLen; size_t nStrLen;
nStrLen = _tcslen(lptString) + 1; nStrLen = _tcslen(lptString) + 1;
if (nBufferSize == 0) nBufferSize = nStrLen; if (nBufferSize == 0) nBufferSize = nStrLen;
lpString = (LPSTR)malloc(nBufferSize); lpString = (LPSTR)malloc(nBufferSize);
#ifdef UNICODE #ifdef UNICODE
WideCharToMultiByte(0,0,lptString,nStrLen,lpString,nBufferSize,0,0); WideCharToMultiByte(0,0,lptString,nStrLen,lpString,nBufferSize,0,0);
#else #else
strncpy(lpString,lptString,nBufferSize); strncpy(lpString,lptString,nBufferSize);
#endif #endif
return lpString; return lpString;
} }
LRESULT CALLBACK EmptyWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK EmptyWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
return DefWindowProc(hWnd, uMsg, wParam, lParam); return DefWindowProc(hWnd, uMsg, wParam, lParam);
} }
// Registers a minimal window class for passing to the dll function // Registers a minimal window class for passing to the dll function
ATOM RegisterBlankClass(HINSTANCE hInstance) ATOM RegisterBlankClass(HINSTANCE hInstance)
{ {
WNDCLASSEX wcex; WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0; wcex.style = 0;
wcex.lpfnWndProc = EmptyWindowProc; wcex.lpfnWndProc = EmptyWindowProc;
wcex.cbClsExtra = 0; wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0; wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; wcex.hInstance = hInstance;
wcex.hIcon = 0; wcex.hIcon = 0;
wcex.hCursor = 0; wcex.hCursor = 0;
wcex.hbrBackground = 0; wcex.hbrBackground = 0;
wcex.lpszMenuName = 0; wcex.lpszMenuName = 0;
wcex.lpszClassName = rundll32_wclass; wcex.lpszClassName = rundll32_wclass;
wcex.hIconSm = 0; wcex.hIconSm = 0;
return RegisterClassEx(&wcex); return RegisterClassEx(&wcex);
} }
int WINAPI WinMain( int WINAPI WinMain(
HINSTANCE hInstance, HINSTANCE hInstance,
HINSTANCE hPrevInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLineA, LPSTR lpCmdLineA,
int nCmdShow int nCmdShow
) )
{ {
int argc; int argc;
LPTSTR *argv; LPTSTR *argv;
LPTSTR lptCmdLine,lptDllName,lptFuncName,lptMsgBuffer; LPTSTR lptCmdLine,lptDllName,lptFuncName,lptMsgBuffer;
LPSTR lpFuncName,lpaCmdLine; LPSTR lpFuncName,lpaCmdLine;
LPWSTR lpwCmdLine; LPWSTR lpwCmdLine;
HMODULE hDll; HMODULE hDll;
DllWinMainW fnDllWinMainW; DllWinMainW fnDllWinMainW;
DllWinMainA fnDllWinMainA; DllWinMainA fnDllWinMainA;
HWND hWindow; HWND hWindow;
int nRetVal,i; int nRetVal,i;
size_t nStrLen; size_t nStrLen;
// Get command-line in argc-argv format // Get command-line in argc-argv format
argv = CommandLineToArgv(GetCommandLine(),&argc); argv = CommandLineToArgv(GetCommandLine(),&argc);
// Skip all beginning arguments starting with a slash (/) // Skip all beginning arguments starting with a slash (/)
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
if (*argv[i] != _T('/')) break; if (*argv[i] != _T('/')) break;
// If no dll was specified, there is nothing to do // If no dll was specified, there is nothing to do
if (i >= argc) { if (i >= argc) {
if (argv) free(argv); if (argv) free(argv);
return 0; return 0;
} }
lptDllName = argv[i++]; lptDllName = argv[i++];
// The next argument, which specifies the name of the dll function, // The next argument, which specifies the name of the dll function,
// can either have a comma between it and the dll filename or a space. // can either have a comma between it and the dll filename or a space.
// Using a comma here is the preferred method // Using a comma here is the preferred method
if (i < argc) if (i < argc)
lptFuncName = argv[i++]; lptFuncName = argv[i++];
else else
lptFuncName = _T(""); lptFuncName = _T("");
// If no function name was specified, nothing needs to be done // If no function name was specified, nothing needs to be done
if (!*lptFuncName) { if (!*lptFuncName) {
if (argv) free(argv); if (argv) free(argv);
return 0; return 0;
} }
// The rest of the arguments will be passed to dll function // The rest of the arguments will be passed to dll function
if (i < argc) if (i < argc)
lptCmdLine = argv[i]; lptCmdLine = argv[i];
else else
lptCmdLine = _T(""); lptCmdLine = _T("");
nRetVal = 0; nRetVal = 0;
// Everything is all setup, so load the dll now // Everything is all setup, so load the dll now
hDll = LoadLibrary(lptDllName); hDll = LoadLibrary(lptDllName);
if (hDll) { if (hDll) {
nStrLen = _tcslen(lptFuncName); nStrLen = _tcslen(lptFuncName);
// Make a non-unicode version of the function name, // Make a non-unicode version of the function name,
// since that is all GetProcAddress accepts // since that is all GetProcAddress accepts
lpFuncName = DuplicateToMultiByte(lptFuncName,nStrLen + 2); lpFuncName = DuplicateToMultiByte(lptFuncName,nStrLen + 2);
#ifdef UNICODE #ifdef UNICODE
lpFuncName[nStrLen] = 'W'; lpFuncName[nStrLen] = 'W';
lpFuncName[nStrLen+1] = 0; lpFuncName[nStrLen+1] = 0;
// Get address of unicode version of the dll function if it exists // Get address of unicode version of the dll function if it exists
fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName); fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName);
fnDllWinMainA = 0; fnDllWinMainA = 0;
if (!fnDllWinMainW) { if (!fnDllWinMainW) {
// If no unicode function was found, get the address of the non-unicode function // If no unicode function was found, get the address of the non-unicode function
lpFuncName[nStrLen] = 'A'; lpFuncName[nStrLen] = 'A';
fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
if (!fnDllWinMainA) { if (!fnDllWinMainA) {
// If first non-unicode function was not found, get the address // If first non-unicode function was not found, get the address
// of the other non-unicode function // of the other non-unicode function
lpFuncName[nStrLen] = 0; lpFuncName[nStrLen] = 0;
fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
} }
} }
#else #else
// Get address of non-unicode version of the dll function if it exists // Get address of non-unicode version of the dll function if it exists
fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
fnDllWinMainW = 0; fnDllWinMainW = 0;
if (!fnDllWinMainA) { if (!fnDllWinMainA) {
// If first non-unicode function was not found, get the address // If first non-unicode function was not found, get the address
// of the other non-unicode function // of the other non-unicode function
lpFuncName[nStrLen] = 'A'; lpFuncName[nStrLen] = 'A';
lpFuncName[nStrLen+1] = 0; lpFuncName[nStrLen+1] = 0;
fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName); fnDllWinMainA = (DllWinMainA)GetProcAddress(hDll,lpFuncName);
if (!fnDllWinMainA) { if (!fnDllWinMainA) {
// If non-unicode function was not found, get the address of the unicode function // If non-unicode function was not found, get the address of the unicode function
lpFuncName[nStrLen] = 'W'; lpFuncName[nStrLen] = 'W';
fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName); fnDllWinMainW = (DllWinMainW)GetProcAddress(hDll,lpFuncName);
} }
} }
#endif #endif
free(lpFuncName); free(lpFuncName);
RegisterBlankClass(hInstance); RegisterBlankClass(hInstance);
// Create a window so we can pass a window handle to // Create a window so we can pass a window handle to
// the dll function; this is required // the dll function; this is required
hWindow = CreateWindowEx(0,rundll32_wclass,rundll32_wtitle,0,CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,hInstance,0); hWindow = CreateWindowEx(0,rundll32_wclass,rundll32_wtitle,0,CW_USEDEFAULT,0,CW_USEDEFAULT,0,0,0,hInstance,0);
if (fnDllWinMainW) { if (fnDllWinMainW) {
// Convert the command-line string to unicode and call the dll function // Convert the command-line string to unicode and call the dll function
lpwCmdLine = ConvertToWideChar(lptCmdLine); lpwCmdLine = ConvertToWideChar(lptCmdLine);
nRetVal = fnDllWinMainW(hWindow,hInstance,lpwCmdLine,nCmdShow); nRetVal = fnDllWinMainW(hWindow,hInstance,lpwCmdLine,nCmdShow);
FreeConvertedWideChar(lpwCmdLine); FreeConvertedWideChar(lpwCmdLine);
} }
else if (fnDllWinMainA) { else if (fnDllWinMainA) {
// Convert the command-line string to ansi and call the dll function // Convert the command-line string to ansi and call the dll function
lpaCmdLine = ConvertToMultiByte(lptCmdLine); lpaCmdLine = ConvertToMultiByte(lptCmdLine);
nRetVal = fnDllWinMainA(hWindow,hInstance,lpaCmdLine,nCmdShow); nRetVal = fnDllWinMainA(hWindow,hInstance,lpaCmdLine,nCmdShow);
FreeConvertedMultiByte(lpaCmdLine); FreeConvertedMultiByte(lpaCmdLine);
} }
else { else {
// The specified dll function was not found; display an error message // The specified dll function was not found; display an error message
GetModuleTitle(); GetModuleTitle();
lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); lptMsgBuffer = (LPTSTR)malloc((_tcslen(MissingEntry) - 4 + _tcslen(lptFuncName) + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
_stprintf(lptMsgBuffer,MissingEntry,lptFuncName,lptDllName); _stprintf(lptMsgBuffer,MissingEntry,lptFuncName,lptDllName);
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR); MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR);
free(lptMsgBuffer); free(lptMsgBuffer);
} }
DestroyWindow(hWindow); DestroyWindow(hWindow);
UnregisterClass(rundll32_wclass,hInstance); UnregisterClass(rundll32_wclass,hInstance);
// The dll function has finished executing, so unload it // The dll function has finished executing, so unload it
FreeLibrary(hDll); FreeLibrary(hDll);
} }
else { else {
// The dll could not be loaded; display an error message // The dll could not be loaded; display an error message
GetModuleTitle(); GetModuleTitle();
lptMsgBuffer = (LPTSTR)malloc((_tcslen(DllNotLoaded) - 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR)); lptMsgBuffer = (LPTSTR)malloc((_tcslen(DllNotLoaded) - 2 + _tcslen(lptDllName) + 1) * sizeof(TCHAR));
_stprintf(lptMsgBuffer,DllNotLoaded,lptDllName); _stprintf(lptMsgBuffer,DllNotLoaded,lptDllName);
MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR); MessageBox(0,lptMsgBuffer,ModuleTitle,MB_ICONERROR);
free(lptMsgBuffer); free(lptMsgBuffer);
} }
if (argv) free(argv); if (argv) free(argv);
return nRetVal; return nRetVal;
} }