From 13064f991408ea5fa5e999705b13bda7bbd50e5b Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Wed, 16 Mar 2022 13:14:47 +0300 Subject: [PATCH] combase: Execute dllhost.exe for correct architecture in a WoW64 setup. Signed-off-by: Dmitry Timoshkov Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/combase/rpc.c | 48 +++++++++++++++++++++++++++++--------- programs/dllhost/dllhost.c | 2 ++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/dlls/combase/rpc.c b/dlls/combase/rpc.c index 40f900175dd..f620339f19e 100644 --- a/dlls/combase/rpc.c +++ b/dlls/combase/rpc.c @@ -526,18 +526,24 @@ static HRESULT create_surrogate_server(REFCLSID rclsid, HANDLE *process) { static const WCHAR processidW[] = L" /PROCESSID:"; HKEY key; + int arch = (sizeof(void *) > sizeof(int)) ? 64 : 32; + REGSAM opposite = (arch == 64) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY; + BOOL is_wow64 = FALSE; HRESULT hr; WCHAR command[MAX_PATH + ARRAY_SIZE(processidW) + CHARS_IN_GUID]; DWORD size; - STARTUPINFOW sinfo; - PROCESS_INFORMATION pinfo; + STARTUPINFOW si; + PROCESS_INFORMATION pi; LONG ret; TRACE("Attempting to start surrogate server for %s\n", debugstr_guid(rclsid)); hr = open_appidkey_from_clsid(rclsid, KEY_READ, &key); - if (FAILED(hr)) - return hr; + if (FAILED(hr) && (arch == 64 || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))) + { + hr = open_appidkey_from_clsid(rclsid, opposite | KEY_READ, &key); + if (FAILED(hr)) return hr; + } size = (MAX_PATH + 1) * sizeof(WCHAR); ret = RegQueryValueExW(key, L"DllSurrogate", NULL, NULL, (LPBYTE)command, &size); @@ -545,25 +551,45 @@ static HRESULT create_surrogate_server(REFCLSID rclsid, HANDLE *process) if (ret || !size || !command[0]) { TRACE("No value for DllSurrogate key\n"); - wcscpy(command, L"dllhost.exe"); + + if ((sizeof(void *) == 8 || is_wow64) && opposite == KEY_WOW64_32KEY) + GetSystemWow64DirectoryW(command, MAX_PATH - ARRAY_SIZE(L"\\dllhost.exe")); + else + GetSystemDirectoryW(command, MAX_PATH - ARRAY_SIZE(L"\\dllhost.exe")); + + wcscat(command, L"\\dllhost.exe"); } /* Surrogate EXE servers are started with the /PROCESSID:{GUID} switch. */ wcscat(command, processidW); StringFromGUID2(rclsid, command + wcslen(command), CHARS_IN_GUID); - memset(&sinfo, 0, sizeof(sinfo)); - sinfo.cb = sizeof(sinfo); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); TRACE("Activating surrogate local server %s\n", debugstr_w(command)); - if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) + if (is_wow64 && arch == 64) + { + void *cookie; + Wow64DisableWow64FsRedirection(&cookie); + if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi)) + { + WARN("failed to run surrogate local server %s\n", debugstr_w(command)); + hr = HRESULT_FROM_WIN32(GetLastError()); + } + Wow64RevertWow64FsRedirection(cookie); + } + else if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi)) { WARN("failed to run surrogate local server %s\n", debugstr_w(command)); - return HRESULT_FROM_WIN32(GetLastError()); + hr = HRESULT_FROM_WIN32(GetLastError()); } - *process = pinfo.hProcess; - CloseHandle(pinfo.hThread); + + if (FAILED(hr)) return hr; + + *process = pi.hProcess; + CloseHandle(pi.hThread); return S_OK; } diff --git a/programs/dllhost/dllhost.c b/programs/dllhost/dllhost.c index dc89c978510..83700826f8b 100644 --- a/programs/dllhost/dllhost.c +++ b/programs/dllhost/dllhost.c @@ -327,6 +327,8 @@ int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE previnst, LPWSTR cmdline, int sho CLSID clsid; struct surrogate surrogate; + TRACE("Running as %u-bit\n", (int)sizeof(void *) * 8); + if (wcsnicmp(cmdline, L"/PROCESSID:", 11)) return 0;