rundll32: Restart itself if the dll is for a different architecture.

Based on the corresponding code in regsvr32.
This commit is contained in:
Alexandre Julliard 2024-11-14 11:55:31 +01:00
parent 5c597119a0
commit 9f8ef43991
2 changed files with 63 additions and 10 deletions

View file

@ -1,5 +1,5 @@
MODULE = rundll32.exe MODULE = rundll32.exe
IMPORTS = user32 IMPORTS = user32 kernelbase
EXTRADLLFLAGS = -mwindows -municode EXTRADLLFLAGS = -mwindows -municode

View file

@ -214,6 +214,49 @@ static WCHAR *parse_arguments( WCHAR *cmdline, WCHAR **dll, WCHAR **entrypoint )
return p; return p;
} }
static void reexec_self( WCHAR *args, WORD machine )
{
SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION machines[8];
WCHAR app[MAX_PATH];
WCHAR *cmdline;
HANDLE process = 0;
STARTUPINFOEXW si = {{ sizeof(si.StartupInfo) }};
PROCESS_INFORMATION pi;
SIZE_T len, size = 1024;
struct _PROC_THREAD_ATTRIBUTE_LIST *list = malloc( size );
void *cookie;
ULONG i;
NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
machines, sizeof(machines), NULL );
for (i = 0; machines[i].Machine; i++) if (machines[i].Machine == machine) break;
if (!GetSystemWow64Directory2W( app, MAX_PATH, machines[i].WoW64Container ?
machine : IMAGE_FILE_MACHINE_TARGET_HOST )) return;
wcscat( app, L"\\rundll32.exe" );
TRACE( "restarting as %s cmdline %s\n", debugstr_w(app), debugstr_w(args) );
len = wcslen(app) + wcslen(args) + 2;
cmdline = malloc( len * sizeof(WCHAR) );
swprintf( cmdline, len, L"%s %s", app, args );
InitializeProcThreadAttributeList( list, 1, 0, &size );
UpdateProcThreadAttribute( list, 0, PROC_THREAD_ATTRIBUTE_MACHINE_TYPE, &machine, sizeof(machine), NULL, NULL );
si.StartupInfo.cb = sizeof(si);
si.lpAttributeList = list;
Wow64DisableWow64FsRedirection(&cookie);
if (CreateProcessW( app, cmdline, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, &si.StartupInfo, &pi ))
{
DWORD exit_code;
WaitForSingleObject( pi.hProcess, INFINITE );
GetExitCodeProcess( pi.hProcess, &exit_code );
ExitProcess( exit_code );
}
Wow64RevertWow64FsRedirection(cookie);
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE hOldInstance, LPWSTR szCmdLine, int nCmdShow) int WINAPI wWinMain(HINSTANCE instance, HINSTANCE hOldInstance, LPWSTR szCmdLine, int nCmdShow)
{ {
HWND hWnd; HWND hWnd;
@ -256,20 +299,30 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE hOldInstance, LPWSTR szCmdLine
/* Load the library */ /* Load the library */
hDll=LoadLibraryW(szDllName); hDll=LoadLibraryW(szDllName);
if (hDll) entry_point = get_entry_point32( hDll, szEntryPoint, &unicode ); if (hDll) entry_point = get_entry_point32( hDll, szEntryPoint, &unicode );
#ifdef __i386__
else else
{ {
HINSTANCE16 dll = load_dll16( szDllName ); HMODULE module;
if (dll <= 32) if (GetLastError() == ERROR_BAD_EXE_FORMAT &&
(module = LoadLibraryExW( szDllName, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE )))
{ {
/* Windows has a MessageBox here... */ IMAGE_NT_HEADERS *nt = RtlImageNtHeader( (HMODULE)((ULONG_PTR)module & ~3) );
WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName)); reexec_self( szCmdLine, nt->FileHeader.Machine );
return 0; }
#ifdef __i386__
else
{
HINSTANCE16 dll = load_dll16( szDllName );
if (dll <= 32)
{
/* Windows has a MessageBox here... */
WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName));
return 0;
}
win16 = TRUE;
entry_point = get_entry_point16( dll, szEntryPoint );
} }
win16 = TRUE;
entry_point = get_entry_point16( dll, szEntryPoint );
}
#endif #endif
}
if (!entry_point) if (!entry_point)
{ {