From 2430c17202bdb0ff099519ee5345c590d899ddf0 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 18 Aug 2019 20:02:40 -0500 Subject: [PATCH] services: Don't redirect the image file path for kernel drivers. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47623 Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/advapi32/tests/service.c | 90 +++++++++++++++++++++++++++++++++++ programs/services/services.c | 2 +- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index e4ff7d79baa..9dad710490b 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -35,6 +35,8 @@ static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */ static CHAR selfname[MAX_PATH]; +static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); + static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID); static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID); static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD, @@ -67,6 +69,8 @@ static void init_function_pointers(void) pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx"); pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity"); pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW"); + + pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); } static void test_open_scm(void) @@ -1767,6 +1771,91 @@ static void test_close(void) ok(ret, "Expected success got error %u\n", GetLastError()); } +static void test_wow64(void) +{ + SC_HANDLE manager, service; + BOOL wow64, ret; + HANDLE file; + + if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &wow64) || !wow64) + { + skip("Not running under WoW64.\n"); + return; + } + + if (!(manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE))) + { + skip("Not enough permissions to create a service.\n"); + return; + } + + file = CreateFileA("C:\\windows\\syswow64\\winetestsvc.exe", GENERIC_WRITE, + 0, NULL, CREATE_ALWAYS, 0, NULL); + CloseHandle(file); + + service = CreateServiceA(manager, "winetestsvc", "winetestsvc", + SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE, + SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL); + ok(!!service, "Failed to create service, error %u.\n", GetLastError()); + ret = StartServiceA(service, 0, NULL); + ok(!ret, "Expected failure.\n"); + todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %u.\n", GetLastError()); + + ret = DeleteService(service); + ok(ret, "Failed to delete service, error %u.\n", GetLastError()); + CloseServiceHandle(service); + + service = CreateServiceA(manager, "winetestsvc", "winetestsvc", SERVICE_START | DELETE, + SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL); + ok(!!service, "Failed to create service, error %u.\n", GetLastError()); + ret = StartServiceA(service, 0, NULL); + ok(!ret, "Expected failure.\n"); + todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %u.\n", GetLastError()); + + ret = DeleteService(service); + ok(ret, "Failed to delete service, error %u.\n", GetLastError()); + CloseServiceHandle(service); + + ret = DeleteFileA("C:\\windows\\syswow64\\winetestsvc.exe"); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); + + file = CreateFileA("C:\\windows\\sysnative\\winetestsvc.exe", GENERIC_WRITE, + 0, NULL, CREATE_ALWAYS, 0, NULL); + CloseHandle(file); + + service = CreateServiceA(manager, "winetestsvc", "winetestsvc", SERVICE_START | DELETE, + SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL); + ok(!!service, "Failed to create service, error %u.\n", GetLastError()); + ret = StartServiceA(service, 0, NULL); + ok(!ret, "Expected failure.\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %u.\n", GetLastError()); + + ret = DeleteService(service); + ok(ret, "Failed to delete service, error %u.\n", GetLastError()); + CloseServiceHandle(service); + + service = CreateServiceA(manager, "winetestsvc", "winetestsvc", SERVICE_START | DELETE, + SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL); + ok(!!service, "Failed to create service, error %u.\n", GetLastError()); + ret = StartServiceA(service, 0, NULL); + ok(!ret, "Expected failure.\n"); + todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %u.\n", GetLastError()); + + ret = DeleteService(service); + ok(ret, "Failed to delete service, error %u.\n", GetLastError()); + CloseServiceHandle(service); + + ret = DeleteFileA("C:\\windows\\sysnative\\winetestsvc.exe"); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); + + CloseServiceHandle(service); + CloseServiceHandle(manager); +} + static void test_sequence(void) { SC_HANDLE scm_handle, svc_handle; @@ -2689,6 +2778,7 @@ START_TEST(service) test_query_svc(); test_enum_svc(); test_close(); + test_wow64(); /* Test the creation, querying and deletion of a service */ test_sequence(); test_queryconfig2(); diff --git a/programs/services/services.c b/programs/services/services.c index ec2a8eb05cc..5eca77777e1 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -826,7 +826,7 @@ static DWORD get_service_binary_path(const struct service_entry *service_entry, ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName, *path, size); /* if service image is configured to systemdir, redirect it to wow64 systemdir */ - if (service_entry->is_wow64) + if (service_entry->is_wow64 && !(service_entry->config.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))) { WCHAR system_dir[MAX_PATH], *redirected; DWORD len;