From 4175fdb7c6319931d0555eb81971247d3545b678 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 3 Dec 2003 20:29:24 +0000 Subject: [PATCH] Added support for loading 16-bit dlls. --- programs/rundll32/Makefile.in | 2 +- programs/rundll32/rundll32.c | 193 ++++++++++++++++++++-------------- 2 files changed, 113 insertions(+), 82 deletions(-) diff --git a/programs/rundll32/Makefile.in b/programs/rundll32/Makefile.in index 6b06679cae9..b718513418c 100644 --- a/programs/rundll32/Makefile.in +++ b/programs/rundll32/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = rundll32.exe APPMODE = cui -IMPORTS = user32 kernel32 +IMPORTS = shell32 user32 kernel32 C_SRCS = \ rundll32.c diff --git a/programs/rundll32/rundll32.c b/programs/rundll32/rundll32.c index 0d5ce9b1d28..907b5c18490 100644 --- a/programs/rundll32/rundll32.c +++ b/programs/rundll32/rundll32.c @@ -35,12 +35,17 @@ /* Exclude rarely-used stuff from Windows headers */ #define WIN32_LEAN_AND_MEAN -#include -#include +#include "windows.h" +#include "wine/winbase16.h" +#include "wine/unicode.h" +#include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(rundll32); +extern void WINAPI RunDLL_CallEntry16( FARPROC proc, HWND hwnd, HINSTANCE inst, + LPCSTR cmdline, INT cmdshow ); + /* * Control_RunDLL has these parameters */ @@ -75,9 +80,57 @@ static ATOM MyRegisterClass(HINSTANCE hInstance) return RegisterClassEx(&wcex); } -static LPWSTR GetNextArg(LPCWSTR *cmdline) +static HINSTANCE16 load_dll16( LPCWSTR dll ) { - LPCWSTR s; + HINSTANCE16 ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, dll, -1, NULL, 0, NULL, NULL ); + char *dllA = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, dll, -1, dllA, len, NULL, NULL ); + ret = LoadLibrary16( dllA ); + HeapFree( GetProcessHeap(), 0, dllA ); + return ret; +} + +static FARPROC16 get_entry_point16( HINSTANCE16 inst, LPCWSTR entry ) +{ + FARPROC16 ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL ); + char *entryA = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, entry, -1, entryA, len, NULL, NULL ); + ret = GetProcAddress16( inst, entryA ); + HeapFree( GetProcessHeap(), 0, entryA ); + return ret; +} + +static void *get_entry_point32( HMODULE module, LPCWSTR entry, BOOL *unicode ) +{ + void *ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL ); + char *entryA = HeapAlloc( GetProcessHeap(), 0, len + 1 ); + WideCharToMultiByte( CP_ACP, 0, entry, -1, entryA, len, NULL, NULL ); + + /* first try the W version */ + *unicode = TRUE; + strcat( entryA, "W" ); + if (!(ret = GetProcAddress( module, entryA ))) + { + /* now the A version */ + *unicode = FALSE; + entryA[strlen(entryA)-1] = 'A'; + if (!(ret = GetProcAddress( module, entryA ))) + { + /* now the version without suffix */ + entryA[strlen(entryA)-1] = 0; + ret = GetProcAddress( module, entryA ); + } + } + HeapFree( GetProcessHeap(), 0, entryA ); + return ret; +} + +static LPWSTR GetNextArg(LPWSTR *cmdline) +{ + LPWSTR s; LPWSTR arg,d; int in_quotes,bcount,len=0; @@ -157,18 +210,16 @@ static LPWSTR GetNextArg(LPCWSTR *cmdline) int main(int argc, char* argv[]) { HWND hWnd; - LPCWSTR szCmdLine; + LPWSTR szCmdLine; LPWSTR szDllName,szEntryPoint; - char* szProcName; - HMODULE hDll; - EntryPointW pEntryPointW; - EntryPointA pEntryPointA; - int len; + void *entry_point; + BOOL unicode, win16; + STARTUPINFOW info; + HMODULE hDll, instance; hWnd=NULL; hDll=NULL; szDllName=NULL; - szProcName=NULL; /* Initialize the rundll32 class */ MyRegisterClass( NULL ); @@ -189,86 +240,68 @@ int main(int argc, char* argv[]) if (!szDllName || *szDllName==0) goto CLEANUP; WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName)); - szEntryPoint=szDllName; - while (*szEntryPoint!=0 && *szEntryPoint!=0x002c /* ',' */) - szEntryPoint++; - if (*szEntryPoint==0) - goto CLEANUP; + if (!(szEntryPoint = strchrW( szDllName, ',' ))) goto CLEANUP; *szEntryPoint++=0; WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint)); /* Load the library */ hDll=LoadLibraryW(szDllName); - if (!hDll) + if (hDll) { - /* Windows has a MessageBox here... */ - WINE_WARN("Unable to load %s\n",wine_dbgstr_w(szDllName)); - goto CLEANUP; - } - - /* Try the Unicode entrypoint. Note that GetProcAddress only takes ascii - * names. - */ - len=WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,NULL,0,NULL,NULL); - szProcName=HeapAlloc(GetProcessHeap(),0,len); - if (!szProcName) - goto CLEANUP; - WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,szProcName,len,NULL,NULL); - szProcName[len-1]=0x0057; - szProcName[len]=0; - pEntryPointW=(void*)GetProcAddress(hDll,szProcName); - if (pEntryPointW) - { - WCHAR* szArguments=NULL; - - /* Make a copy of the arguments so they are writable */ - len=lstrlenW(szCmdLine); - if (len>0) - { - szArguments=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR)); - if (!szArguments) - goto CLEANUP; - lstrcpyW(szArguments,szCmdLine); - } - WINE_TRACE("Calling %s, arguments=%s\n", - szProcName,wine_dbgstr_w(szArguments)); - pEntryPointW(hWnd,hDll,szArguments,SW_SHOWDEFAULT); - if (szArguments) - HeapFree(GetProcessHeap(),0,szArguments); + win16 = FALSE; + entry_point = get_entry_point32( hDll, szEntryPoint, &unicode ); } else { - /* Then try to append 'A' and finally nothing */ - szProcName[len-1]=0x0041; - pEntryPointA=(void*)GetProcAddress(hDll,szProcName); - if (!pEntryPointA) - { - szProcName[len-1]=0; - pEntryPointA=(void*)GetProcAddress(hDll,szProcName); - } - if (pEntryPointA) - { - char* szArguments=NULL; - /* Convert the command line to ascii */ - WINE_TRACE("Calling %s, arguments=%s\n", - szProcName,wine_dbgstr_a(szArguments)); - len=WideCharToMultiByte(CP_ACP,0,szCmdLine,-1,NULL,0,NULL,NULL); - if (len>1) - { - szArguments=HeapAlloc(GetProcessHeap(),0,len); - if (!szArguments) - goto CLEANUP; - WideCharToMultiByte(CP_ACP,0,szCmdLine,-1,szArguments,len,NULL,NULL); - } - pEntryPointA(hWnd,hDll,szArguments,SW_SHOWDEFAULT); - if (szArguments) - HeapFree(GetProcessHeap(),0,szArguments); - } - else + HINSTANCE16 dll = load_dll16( szDllName ); + if (dll <= 32) { /* Windows has a MessageBox here... */ - WINE_WARN("Unable to find the entry point: %s\n",szProcName); + WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName)); + goto CLEANUP; } + win16 = TRUE; + unicode = FALSE; + entry_point = get_entry_point16( dll, szEntryPoint ); + } + + if (!entry_point) + { + /* Windows has a MessageBox here... */ + WINE_ERR( "Unable to find the entry point %s in %s\n", + wine_dbgstr_w(szEntryPoint), wine_dbgstr_w(szDllName) ); + goto CLEANUP; + } + + GetStartupInfoW( &info ); + if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWDEFAULT; + instance = GetModuleHandleW(NULL); /* Windows always uses that, not hDll */ + + if (unicode) + { + EntryPointW pEntryPointW = entry_point; + + WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint), + hWnd, instance, wine_dbgstr_w(szCmdLine), info.wShowWindow ); + + pEntryPointW( hWnd, instance, szCmdLine, info.wShowWindow ); + } + else + { + DWORD len = WideCharToMultiByte( CP_ACP, 0, szCmdLine, -1, NULL, 0, NULL, NULL ); + char *cmdline = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, szCmdLine, -1, cmdline, len, NULL, NULL ); + + WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint), + hWnd, instance, wine_dbgstr_a(cmdline), info.wShowWindow ); + + if (win16) RunDLL_CallEntry16( entry_point, hWnd, instance, cmdline, info.wShowWindow ); + else + { + EntryPointA pEntryPointA = entry_point; + pEntryPointA( hWnd, instance, cmdline, info.wShowWindow ); + } + HeapFree( GetProcessHeap(), 0, cmdline ); } CLEANUP: @@ -278,7 +311,5 @@ CLEANUP: FreeLibrary(hDll); if (szDllName) HeapFree(GetProcessHeap(),0,szDllName); - if (szProcName) - HeapFree(GetProcessHeap(),0,szProcName); return 0; /* rundll32 always returns 0! */ }