[PATCH 6/6] combase: Execute dllhost.exe for correct architecture in a WoW64 setup.

Dmitry Timoshkov dmitry at baikal.ru
Wed Mar 9 01:46:02 CST 2022


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/combase/combase.c     |  2 +-
 dlls/combase/rpc.c         | 48 +++++++++++++++++++++++++++++---------
 programs/dllhost/dllhost.c |  2 ++
 3 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c
index fb8f453661f..376f270fdf1 100644
--- a/dlls/combase/combase.c
+++ b/dlls/combase/combase.c
@@ -350,7 +350,7 @@ HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey)
     HRESULT hr;
 
     /* read the AppID value under the class's key */
-    hr = open_key_for_clsid(clsid, NULL, KEY_READ, &hkey);
+    hr = open_key_for_clsid(clsid, NULL, access, &hkey);
     if (FAILED(hr))
         return hr;
 
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;
 
-- 
2.35.1




More information about the wine-devel mailing list