Nikolay Sivov : services: Locate service image in proper system dir for WOW64 case.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Mar 2 08:51:51 CST 2015
Module: wine
Branch: master
Commit: 38bba54f325880a35acc98d1c5c408beb629414b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=38bba54f325880a35acc98d1c5c408beb629414b
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun Mar 1 02:24:02 2015 +0300
services: Locate service image in proper system dir for WOW64 case.
---
programs/services/services.c | 106 +++++++++++++++++++++++++++++--------------
1 file changed, 71 insertions(+), 35 deletions(-)
diff --git a/programs/services/services.c b/programs/services/services.c
index dd79770..1335837 100644
--- a/programs/services/services.c
+++ b/programs/services/services.c
@@ -621,35 +621,15 @@ static LPWSTR service_get_pipe_name(void)
return name;
}
-static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process)
+static DWORD get_service_binary_path(const struct service_entry *service_entry, WCHAR **path)
{
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
- LPWSTR path = NULL;
- DWORD size;
- BOOL r;
-
- service_lock_exclusive(service_entry);
-
- if (!env)
- {
- HANDLE htok;
-
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok))
- CreateEnvironmentBlock(&env, htok, FALSE);
-
- if (!env)
- WINE_ERR("failed to create services environment\n");
- }
+ DWORD size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName, NULL, 0);
- size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,NULL,0);
- path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
- if (!path)
- {
- service_unlock(service_entry);
+ *path = HeapAlloc(GetProcessHeap(), 0, size*sizeof(WCHAR));
+ if (!*path)
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
- }
- ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,path,size);
+
+ ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName, *path, size);
if (service_entry->config.dwServiceType == SERVICE_KERNEL_DRIVER)
{
@@ -660,25 +640,81 @@ static DWORD service_start_process(struct service_entry *service_entry, HANDLE *
GetSystemDirectoryW( system_dir, MAX_PATH );
if (is_win64)
{
- if (!GetBinaryTypeW( path, &type ))
+ if (!GetBinaryTypeW( *path, &type ))
{
- HeapFree( GetProcessHeap(), 0, path );
- service_unlock(service_entry);
+ HeapFree( GetProcessHeap(), 0, *path );
return GetLastError();
}
if (type == SCS_32BIT_BINARY) GetSystemWow64DirectoryW( system_dir, MAX_PATH );
}
len = strlenW( system_dir ) + sizeof(winedeviceW)/sizeof(WCHAR) + strlenW(service_entry->name);
- HeapFree( GetProcessHeap(), 0, path );
- if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+ HeapFree( GetProcessHeap(), 0, *path );
+ if (!(*path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
+ return ERROR_NOT_ENOUGH_SERVER_MEMORY;
+
+ lstrcpyW( *path, system_dir );
+ lstrcatW( *path, winedeviceW );
+ lstrcatW( *path, service_entry->name );
+ return ERROR_SUCCESS;
+ }
+
+ /* if service image is configured to systemdir, redirect it to wow64 systemdir */
+ if (service_entry->is_wow64)
+ {
+ WCHAR system_dir[MAX_PATH], *redirected;
+ DWORD len;
+
+ GetSystemDirectoryW( system_dir, MAX_PATH );
+ len = strlenW( system_dir );
+
+ if (strncmpiW( system_dir, *path, len ))
+ return ERROR_SUCCESS;
+
+ GetSystemWow64DirectoryW( system_dir, MAX_PATH );
+
+ redirected = HeapAlloc( GetProcessHeap(), 0, (strlenW( *path ) + strlenW( system_dir ))*sizeof(WCHAR));
+ if (!redirected)
{
- service_unlock(service_entry);
+ HeapFree( GetProcessHeap(), 0, *path );
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
}
- lstrcpyW( path, system_dir );
- lstrcatW( path, winedeviceW );
- lstrcatW( path, service_entry->name );
+
+ strcpyW( redirected, system_dir );
+ strcatW( redirected, &(*path)[len] );
+ HeapFree( GetProcessHeap(), 0, *path );
+ *path = redirected;
+ TRACE("redirected to %s\n", debugstr_w(redirected));
+ }
+
+ return ERROR_SUCCESS;
+}
+
+static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process)
+{
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+ LPWSTR path = NULL;
+ DWORD err;
+ BOOL r;
+
+ service_lock_exclusive(service_entry);
+
+ if (!env)
+ {
+ HANDLE htok;
+
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok))
+ CreateEnvironmentBlock(&env, htok, FALSE);
+
+ if (!env)
+ WINE_ERR("failed to create services environment\n");
+ }
+
+ if ((err = get_service_binary_path(service_entry, &path)))
+ {
+ service_unlock(service_entry);
+ return err;
}
ZeroMemory(&si, sizeof(STARTUPINFOW));
More information about the wine-cvs
mailing list