Based on implementation of create_surrogate_server().
This patch makes 64-bit application work with its own shipped 32-bit COM server.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/combase/rpc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/combase/rpc.c b/dlls/combase/rpc.c index 80760ca37e7..53cb32e08e2 100644 --- a/dlls/combase/rpc.c +++ b/dlls/combase/rpc.c @@ -478,6 +478,9 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process) { static const WCHAR embeddingW[] = L" -Embedding"; 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(embeddingW)]; DWORD size = (MAX_PATH+1) * sizeof(WCHAR); @@ -485,7 +488,11 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process) PROCESS_INFORMATION pinfo; LONG ret;
+ TRACE("Attempting to start server for %s\n", debugstr_guid(rclsid)); + hr = open_key_for_clsid(rclsid, L"LocalServer32", KEY_READ, &key); + if (FAILED(hr) && (arch == 64 || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))) + hr = open_key_for_clsid(rclsid, L"LocalServer32", opposite | KEY_READ, &key); if (FAILED(hr)) { ERR("class %s not registered\n", debugstr_guid(rclsid)); @@ -511,7 +518,19 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process)
/* FIXME: Win2003 supports a ServerExecutable value that is passed into * CreateProcess */ - 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, &sinfo, &pinfo)) + { + WARN("failed to run local server %s\n", debugstr_w(command)); + hr = HRESULT_FROM_WIN32(GetLastError()); + } + Wow64RevertWow64FsRedirection(cookie); + if (FAILED(hr)) return hr; + } + else if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) { WARN("failed to run local server %s\n", debugstr_w(command)); return HRESULT_FROM_WIN32(GetLastError());
On Tue, Apr 26, 2022 at 03:40:05PM +0300, Dmitry Timoshkov wrote:
@@ -485,7 +488,11 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process) PROCESS_INFORMATION pinfo; LONG ret;
- TRACE("Attempting to start server for %s\n", debugstr_guid(rclsid));
- hr = open_key_for_clsid(rclsid, L"LocalServer32", KEY_READ, &key);
- if (FAILED(hr) && (arch == 64 || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
if (FAILED(hr)) { ERR("class %s not registered\n", debugstr_guid(rclsid));hr = open_key_for_clsid(rclsid, L"LocalServer32", opposite | KEY_READ, &key);
@@ -511,7 +518,19 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process)
/* FIXME: Win2003 supports a ServerExecutable value that is passed into * CreateProcess */
- if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo))
- if (is_wow64 && arch == 64)
I'm confused, how can this condition ever be true?
Some tests for this would help. It's a bit hard to do, but not impossible.
Huw.
Hi Huw,
many thanks for the review.
Huw Davies huw@codeweavers.com wrote:
On Tue, Apr 26, 2022 at 03:40:05PM +0300, Dmitry Timoshkov wrote:
@@ -485,7 +488,11 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process) PROCESS_INFORMATION pinfo; LONG ret;
- TRACE("Attempting to start server for %s\n", debugstr_guid(rclsid));
- hr = open_key_for_clsid(rclsid, L"LocalServer32", KEY_READ, &key);
- if (FAILED(hr) && (arch == 64 || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
if (FAILED(hr)) { ERR("class %s not registered\n", debugstr_guid(rclsid));hr = open_key_for_clsid(rclsid, L"LocalServer32", opposite | KEY_READ, &key);
@@ -511,7 +518,19 @@ static HRESULT create_server(REFCLSID rclsid, HANDLE *process)
/* FIXME: Win2003 supports a ServerExecutable value that is passed into * CreateProcess */
- if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo))
- if (is_wow64 && arch == 64)
I'm confused, how can this condition ever be true?
Some tests for this would help. It's a bit hard to do, but not impossible.
Looks like this is a typo, it should be 'if (is_wow64 || arch == 64)'. Same typo slipped into create_surrogate_server().