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