From f8f6340a692afc199f171edd03fd295fe3fb0a7f Mon Sep 17 00:00:00 2001 From: Paul Vriens Date: Wed, 18 Jul 2007 20:17:35 +0200 Subject: [PATCH] advapi32/service: Check for duplicate displayname. --- dlls/advapi32/service.c | 55 +++++++++++++++++++++++++++++++---- dlls/advapi32/tests/service.c | 10 ------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 3fbd2421b5..76f8290025 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -1309,6 +1309,9 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, struct reg_value val[10]; int n = 0; DWORD new_mask = dwDesiredAccess; + DWORD index = 0; + WCHAR buffer[MAX_PATH]; + BOOL displayname_exists = FALSE; TRACE("%p %s %s\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName)); @@ -1385,15 +1388,57 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, return NULL; } + /* Loop through the registry to check if the service already exists and to + * check if we can use the given displayname. + * FIXME: Should we use EnumServicesStatusEx? + */ + len = sizeof(buffer); + while (RegEnumKeyExW(hscm->hkey, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + HKEY service_key; + + /* The service already exists, so bail out */ + if(!lstrcmpiW(lpServiceName, buffer)) + { + SetLastError(ERROR_SERVICE_EXISTS); + return NULL; + } + + /* The given displayname matches the found servicename. We don't bail out + * as servicename is checked before a duplicate displayname + */ + if(!lstrcmpiW(lpDisplayName, buffer)) + displayname_exists = TRUE; + + if (RegOpenKeyExW(hscm->hkey, buffer, 0, KEY_READ, &service_key) == ERROR_SUCCESS) + { + WCHAR name[MAX_PATH]; + DWORD size = sizeof(name); + + if (RegQueryValueExW(service_key, szDisplayName, NULL, NULL, (LPBYTE)name, &size) == ERROR_SUCCESS) + { + /* The given displayname matches the found displayname */ + if (!lstrcmpiW(lpDisplayName, name)) + displayname_exists = TRUE; + } + RegCloseKey(service_key); + } + index++; + len = sizeof(buffer); + } + + if (lpDisplayName && displayname_exists) + { + SetLastError(ERROR_DUPLICATE_SERVICE_NAME); + return NULL; + } + r = RegCreateKeyExW(hscm->hkey, lpServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp); if (r!=ERROR_SUCCESS) - return NULL; - - if (dp != REG_CREATED_NEW_KEY) { - SetLastError(ERROR_SERVICE_EXISTS); - goto error; + /* FIXME: Should we set an error? */ + return NULL; } if( lpDisplayName ) diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index ff38d79d57..05476863e6 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -315,24 +315,14 @@ static void test_create_delete_svc(void) { svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL); - todo_wine - { ok(!svc_handle1, "Expected failure\n"); ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError()); - } } } else skip("Could not retrieve a displayname (Spooler service doesn't exist)\n"); - /* FIXME: Remove this when Wine is fixed */ - if (svc_handle1) - { - DeleteService(svc_handle1); - CloseServiceHandle(svc_handle1); - } - CloseServiceHandle(scm_handle); }