Module: wine Branch: master Commit: 38bba54f325880a35acc98d1c5c408beb629414b URL: http://source.winehq.org/git/wine.git/?a=commit;h=38bba54f325880a35acc98d1c5...
Author: Nikolay Sivov nsivov@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));