mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / advapi32 / tests / service.c
blobcbe7fffbc7ae941154d9219fb1b268b099cf2aad
1 /*
2 * Unit tests for service functions
4 * Copyright (c) 2007 Paul Vriens
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "winsvc.h"
29 #include "winnls.h"
30 #include "lmcons.h"
31 #include "aclapi.h"
33 #include "wine/test.h"
35 static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
36 static CHAR selfname[MAX_PATH];
38 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
40 static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
41 static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
42 static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
43 DWORD, LPBYTE, DWORD, LPDWORD,
44 LPDWORD, LPDWORD, LPCSTR);
45 static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
46 DWORD, LPBYTE, DWORD, LPDWORD,
47 LPDWORD, LPDWORD, LPCWSTR);
48 static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
49 static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
50 static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
51 DWORD, LPDWORD);
52 static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
53 PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
54 static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*);
56 static void init_function_pointers(void)
58 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
60 pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
61 pChangeServiceConfig2W = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2W");
62 pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
63 pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
64 pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
65 pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
66 pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
67 pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
68 pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW");
70 pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
73 static void test_open_scm(void)
75 SC_HANDLE scm_handle;
77 /* No access rights */
78 SetLastError(0xdeadbeef);
79 scm_handle = OpenSCManagerA(NULL, NULL, 0);
80 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
81 CloseServiceHandle(scm_handle);
83 /* Unknown database name */
84 SetLastError(0xdeadbeef);
85 scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
86 ok(!scm_handle, "Expected failure\n");
87 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
88 CloseServiceHandle(scm_handle); /* Just in case */
90 /* MSDN says only ServiceActive is allowed, or NULL */
91 SetLastError(0xdeadbeef);
92 scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
93 ok(!scm_handle, "Expected failure\n");
94 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
95 CloseServiceHandle(scm_handle); /* Just in case */
97 /* Remote unknown host */
98 SetLastError(0xdeadbeef);
99 scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
100 todo_wine
102 ok(!scm_handle, "Expected failure\n");
103 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */,
104 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
106 CloseServiceHandle(scm_handle); /* Just in case */
108 /* Proper call with an empty hostname */
109 scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
110 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
111 CloseServiceHandle(scm_handle);
113 /* Again a correct one */
114 SetLastError(0xdeadbeef);
115 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
116 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_IO_PENDING) /* win2k */,
117 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
118 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
119 CloseServiceHandle(scm_handle);
122 static void test_open_svc(void)
124 SC_HANDLE scm_handle, svc_handle;
125 CHAR displayname[4096];
126 DWORD displaysize;
128 /* All NULL (invalid access rights) */
129 SetLastError(0xdeadbeef);
130 svc_handle = OpenServiceA(NULL, NULL, 0);
131 ok(!svc_handle, "Expected failure\n");
132 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
134 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
136 /* NULL service */
137 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
138 SetLastError(0xdeadbeef);
139 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
140 ok(!svc_handle, "Expected failure\n");
141 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
142 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
143 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
144 CloseServiceHandle(scm_handle);
146 /* Nonexistent service */
147 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
148 SetLastError(0xdeadbeef);
149 svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
150 ok(!svc_handle, "Expected failure\n");
151 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
152 CloseServiceHandle(scm_handle);
154 /* Proper SCM handle but different access rights */
155 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
156 SetLastError(0xdeadbeef);
157 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_WRITE);
158 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
159 skip("Not enough rights to get a handle to the service\n");
160 else
162 ok(svc_handle != NULL, "Expected success, got error %u\n", GetLastError());
163 CloseServiceHandle(svc_handle);
166 /* Test to show we can't open a service with the displayname */
168 /* Retrieve the needed size for the buffer */
169 displaysize = 0;
170 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
171 /* Get the displayname */
172 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
173 /* Try to open the service with this displayname, unless the displayname equals
174 * the servicename as that would defeat the purpose of this test.
176 if (!lstrcmpiA(spooler, displayname))
178 skip("displayname equals servicename\n");
179 CloseServiceHandle(scm_handle);
180 return;
183 SetLastError(0xdeadbeef);
184 svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
185 ok(!svc_handle, "Expected failure\n");
186 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
187 /* Just in case */
188 CloseServiceHandle(svc_handle);
190 CloseServiceHandle(scm_handle);
193 static void test_create_delete_svc(void)
195 SC_HANDLE scm_handle, svc_handle1, svc_handle2;
196 CHAR username[UNLEN + 1], domain[MAX_PATH];
197 DWORD user_size = UNLEN + 1;
198 CHAR account[MAX_PATH + UNLEN + 1];
199 static const CHAR servicename [] = "winetest_create_delete";
200 static const CHAR pathname [] = "we_dont_care.exe";
201 static const CHAR empty [] = "";
202 static const CHAR password [] = "secret";
203 char buffer[200];
204 DWORD size;
205 BOOL ret;
207 /* Get the username and turn it into an account to be used in some tests */
208 GetUserNameA(username, &user_size);
209 /* Get the domainname to cater for that situation */
210 if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH))
211 sprintf(account, "%s\\%s", domain, username);
212 else
213 sprintf(account, ".\\%s", username);
215 /* All NULL */
216 SetLastError(0xdeadbeef);
217 svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
218 ok(!svc_handle1, "Expected failure\n");
219 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
221 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
223 /* Only a valid handle to the Service Control Manager */
224 SetLastError(0xdeadbeef);
225 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
226 ok(!svc_handle1, "Expected failure\n");
227 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
228 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
229 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
231 /* Now with a servicename */
232 SetLastError(0xdeadbeef);
233 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
234 ok(!svc_handle1, "Expected failure\n");
235 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
236 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
237 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
239 /* Or just a binary name */
240 SetLastError(0xdeadbeef);
241 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
242 ok(!svc_handle1, "Expected failure\n");
243 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
244 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
245 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
247 /* Both servicename and binary name (We only have connect rights) */
248 SetLastError(0xdeadbeef);
249 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
250 ok(!svc_handle1, "Expected failure\n");
251 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
253 /* They can even be empty at this stage of parameter checking */
254 SetLastError(0xdeadbeef);
255 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
256 ok(!svc_handle1, "Expected failure\n");
257 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
259 SetLastError(0xdeadbeef);
260 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
261 ok(!svc_handle1, "Expected failure\n");
262 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
264 /* Open the Service Control Manager with minimal rights for creation
265 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
267 CloseServiceHandle(scm_handle);
268 SetLastError(0xdeadbeef);
269 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
270 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
272 skip("Not enough rights to get a handle to the manager\n");
273 return;
276 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
278 /* Empty strings for servicename and binary name are checked */
279 SetLastError(0xdeadbeef);
280 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
281 ok(!svc_handle1, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
286 ok(!svc_handle1, "Expected failure\n");
287 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
289 SetLastError(0xdeadbeef);
290 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
291 ok(!svc_handle1, "Expected failure\n");
292 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
294 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
295 * an ERROR_INVALID_PARAMETER)
297 SetLastError(0xdeadbeef);
298 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
299 SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
300 ok(!svc_handle1, "Expected failure\n");
301 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
303 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
305 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
306 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
308 SetLastError(0xdeadbeef);
309 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
310 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
311 ok(!svc_handle1, "Expected failure\n");
312 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
314 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
315 SetLastError(0xdeadbeef);
316 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
317 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
318 ok(!svc_handle1, "Expected failure\n");
319 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
321 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
322 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
324 SetLastError(0xdeadbeef);
325 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
326 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
327 ok(!svc_handle1, "Expected failure\n");
328 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT,
329 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
331 /* Illegal (start-type is not a mask and should only be one of the possibilities)
332 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
333 * it's most likely not the wanted start-type)
335 SetLastError(0xdeadbeef);
336 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
337 SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
338 ok(!svc_handle1, "Expected failure\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
341 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
342 SetLastError(0xdeadbeef);
343 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
344 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
345 ok(!svc_handle1, "Expected failure\n");
346 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
348 /* Test if ServiceType can be a combined one for drivers */
349 SetLastError(0xdeadbeef);
350 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER,
351 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
352 ok(!svc_handle1, "Expected failure\n");
353 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
355 /* Test duplicate service names */
356 svc_handle1 = CreateServiceA(scm_handle, "winetest_dupname", "winetest_display", DELETE,
357 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
358 ok(!!svc_handle1, "Failed to create service, error %u\n", GetLastError());
360 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname", NULL, 0,
361 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
362 ok(!svc_handle2, "Expected failure\n");
363 ok(GetLastError() == ERROR_SERVICE_EXISTS, "Got wrong error %u\n", GetLastError());
365 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_dupname", DELETE,
366 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
367 todo_wine ok(!svc_handle2, "Expected failure\n");
368 todo_wine ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %u\n", GetLastError());
369 if (svc_handle2)
371 DeleteService(svc_handle2);
372 CloseServiceHandle(svc_handle2);
375 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_display", DELETE,
376 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
377 if (svc_handle2) /* Win10 1709+ */
379 size = sizeof(buffer);
380 ret = GetServiceKeyNameA(scm_handle, "winetest_display", buffer, &size);
381 ok(ret, "Failed to get key name, error %u\n", GetLastError());
382 ok(!strcmp(buffer, "winetest_dupname"), "Got wrong name \"%s\"\n", buffer);
384 ret = DeleteService(svc_handle2);
385 ok(ret, "Failed to delete service, error %u\n", GetLastError());
386 CloseServiceHandle(svc_handle2);
388 else
389 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %u\n", GetLastError());
391 ret = DeleteService(svc_handle1);
392 ok(ret, "Failed to delete service, error %u\n", GetLastError());
393 CloseServiceHandle(svc_handle1);
395 /* Windows doesn't care about the access rights for creation (which makes
396 * sense as there is no service yet) as long as there are sufficient
397 * rights to the manager.
399 SetLastError(0xdeadbeef);
400 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
401 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
402 ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError());
404 /* DeleteService however must have proper rights */
405 SetLastError(0xdeadbeef);
406 ret = DeleteService(svc_handle1);
407 ok(!ret, "Expected failure\n");
408 ok(GetLastError() == ERROR_ACCESS_DENIED,
409 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
411 /* Open the service with minimal rights for deletion.
412 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
414 CloseServiceHandle(svc_handle1);
415 svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
417 /* Now that we have the proper rights, we should be able to delete */
418 SetLastError(0xdeadbeef);
419 ret = DeleteService(svc_handle1);
420 ok(ret, "Expected success, got error %u\n", GetLastError());
422 /* Service is marked for delete, but handle is still open. Try to open service again. */
423 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
424 ok(svc_handle2 != NULL, "got %p, error %u\n", svc_handle2, GetLastError());
425 CloseServiceHandle(svc_handle2);
427 CloseServiceHandle(svc_handle1);
428 CloseServiceHandle(scm_handle);
430 /* And a final NULL check */
431 SetLastError(0xdeadbeef);
432 ret = DeleteService(NULL);
433 ok(!ret, "Expected failure\n");
434 ok(GetLastError() == ERROR_INVALID_HANDLE,
435 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
438 static void test_get_displayname(void)
440 SC_HANDLE scm_handle, svc_handle;
441 BOOL ret;
442 CHAR displayname[4096];
443 WCHAR displaynameW[2048];
444 DWORD displaysize, tempsize, tempsizeW;
445 static const CHAR deadbeef[] = "Deadbeef";
446 static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
447 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
448 static const WCHAR abcW[] = {'A','B','C',0};
449 static const CHAR servicename[] = "winetest_displayname";
450 static const CHAR pathname[] = "we_dont_care.exe";
452 /* Having NULL for the size of the buffer will crash on W2K3 */
454 SetLastError(0xdeadbeef);
455 ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
456 ok(!ret, "Expected failure\n");
457 ok(GetLastError() == ERROR_INVALID_HANDLE,
458 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
460 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
462 SetLastError(0xdeadbeef);
463 ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
464 ok(!ret, "Expected failure\n");
465 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
466 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
467 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
469 SetLastError(0xdeadbeef);
470 displaysize = sizeof(displayname);
471 ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
472 ok(!ret, "Expected failure\n");
473 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
474 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
475 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
477 /* Test for nonexistent service */
478 SetLastError(0xdeadbeef);
479 displaysize = -1;
480 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
481 ok(!ret, "Expected failure\n");
482 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
483 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
485 SetLastError(0xdeadbeef);
486 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
487 ok(!ret, "Expected failure\n");
488 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
489 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
490 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
492 displaysize = 15;
493 strcpy(displayname, "ABC");
494 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
495 ok(!ret, "Expected failure\n");
496 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
497 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
498 todo_wine ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
499 ok(displayname[0] == 0, "Service name not empty\n");
501 displaysize = 15;
502 lstrcpyW( displaynameW, abcW );
503 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
504 ok(!ret, "Expected failure\n");
505 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
506 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
507 ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
508 ok(displaynameW[0] == 0, "Service name not empty\n");
510 displaysize = 0;
511 strcpy(displayname, "ABC");
512 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
513 ok(!ret, "Expected failure\n");
514 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
515 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
516 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
517 ok(displayname[0] == 'A', "Service name changed\n");
519 displaysize = 0;
520 lstrcpyW( displaynameW, abcW );
521 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
522 ok(!ret, "Expected failure\n");
523 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
524 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
525 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
526 ok(displaynameW[0] == 'A', "Service name changed\n");
528 displaysize = 1;
529 strcpy(displayname, "ABC");
530 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
531 ok(!ret, "Expected failure\n");
532 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
533 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
534 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
535 ok(displayname[0] == 0, "Service name not empty\n");
537 displaysize = 1;
538 lstrcpyW( displaynameW, abcW );
539 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
540 ok(!ret, "Expected failure\n");
541 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
542 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
543 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
544 ok(displaynameW[0] == 'A', "Service name changed\n");
546 displaysize = 2;
547 strcpy(displayname, "ABC");
548 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
549 ok(!ret, "Expected failure\n");
550 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
551 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
552 todo_wine ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
553 ok(displayname[0] == 0, "Service name not empty\n");
555 displaysize = 2;
556 lstrcpyW( displaynameW, abcW );
557 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
558 ok(!ret, "Expected failure\n");
559 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
560 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
561 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
562 ok(displaynameW[0] == 0, "Service name not empty\n");
564 /* Check if 'Spooler' exists */
565 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
566 if (!svc_handle)
568 skip("Spooler service doesn't exist\n");
569 CloseServiceHandle(scm_handle);
570 return;
572 CloseServiceHandle(svc_handle);
574 /* Retrieve the needed size for the buffer */
575 SetLastError(0xdeadbeef);
576 displaysize = -1;
577 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
578 ok(!ret, "Expected failure\n");
579 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
580 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
581 tempsize = displaysize;
583 displaysize = 0;
584 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
585 ok(!ret, "Expected failure\n");
586 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
587 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
588 ok(displaysize == tempsize, "Buffer size mismatch (%d vs %d)\n", tempsize, displaysize);
590 /* Buffer is too small */
591 SetLastError(0xdeadbeef);
592 displaysize = (tempsize / 2);
593 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
594 ok(!ret, "Expected failure\n");
595 ok(displaysize == tempsize, "Expected the needed buffersize\n");
596 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
597 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
599 /* First try with a buffer that should be big enough to hold
600 * the ANSI string (and terminating character). This succeeds on Windows
601 * although when asked (see above 2 tests) it will return twice the needed size.
603 SetLastError(0xdeadbeef);
604 displaysize = (tempsize / 2) + 1;
605 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
606 ok(ret, "Expected success, got error %u\n", GetLastError());
607 ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
609 /* Now with the original returned size */
610 SetLastError(0xdeadbeef);
611 displaysize = tempsize;
612 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
613 ok(ret, "Expected success, got error %u\n", GetLastError());
614 ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
616 /* And with a bigger than needed buffer */
617 SetLastError(0xdeadbeef);
618 displaysize = tempsize * 2;
619 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
620 ok(ret, "Expected success, got error %u\n", GetLastError());
621 /* Test that shows that if the buffersize is enough, it's not changed */
622 ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
623 ok(strlen(displayname) == tempsize/2,
624 "Expected the buffer to be twice the length of the string\n") ;
626 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
627 SetLastError(0xdeadbeef);
628 displaysize = -1;
629 ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
630 ok(!ret, "Expected failure\n");
631 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
632 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
634 /* Buffer is too small */
635 SetLastError(0xdeadbeef);
636 tempsizeW = displaysize;
637 displaysize = tempsizeW / 2;
638 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
639 ok(!ret, "Expected failure\n");
640 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
641 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
642 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
644 /* Now with the original returned size */
645 SetLastError(0xdeadbeef);
646 displaysize = tempsizeW;
647 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
648 ok(!ret, "Expected failure\n");
649 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
650 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
651 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
653 /* And with a bigger than needed buffer */
654 SetLastError(0xdeadbeef);
655 displaysize = tempsizeW + 1; /* This caters for the null terminating character */
656 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
657 ok(ret, "Expected success, got error %u\n", GetLastError());
658 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
659 ok(lstrlenW(displaynameW) == displaysize,
660 "Expected the buffer to be the length of the string\n") ;
661 ok(tempsize / 2 == tempsizeW,
662 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
664 CloseServiceHandle(scm_handle);
666 /* Test for a service without a displayname (which is valid). This should return
667 * the servicename itself.
669 SetLastError(0xdeadbeef);
670 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
671 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
673 skip("Not enough rights to get a handle to the manager\n");
674 return;
677 SetLastError(0xdeadbeef);
678 svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
679 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
680 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
681 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
682 if (!svc_handle)
684 CloseServiceHandle(scm_handle);
685 return;
688 /* Retrieve the needed size for the buffer */
689 SetLastError(0xdeadbeef);
690 displaysize = -1;
691 ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
692 ok(!ret, "Expected failure\n");
693 ok(displaysize == strlen(servicename) * 2,
694 "Expected the displaysize to be twice the size of the servicename\n");
695 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
696 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
698 /* Buffer is too small */
699 SetLastError(0xdeadbeef);
700 tempsize = displaysize;
701 displaysize = (tempsize / 2);
702 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
703 ok(!ret, "Expected failure\n");
704 ok(displaysize == tempsize, "Expected the needed buffersize\n");
705 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
706 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
708 /* Get the displayname */
709 SetLastError(0xdeadbeef);
710 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
711 ok(ret, "Expected success, got error %u\n", GetLastError());
712 ok(!lstrcmpiA(displayname, servicename),
713 "Expected displayname to be %s, got %s\n", servicename, displayname);
715 /* Delete the service */
716 ret = DeleteService(svc_handle);
717 ok(ret, "Expected success (err=%d)\n", GetLastError());
719 CloseServiceHandle(svc_handle);
720 CloseServiceHandle(scm_handle);
723 static void test_get_servicekeyname(void)
725 SC_HANDLE scm_handle, svc_handle;
726 CHAR servicename[4096];
727 CHAR displayname[4096];
728 WCHAR servicenameW[4096];
729 WCHAR displaynameW[4096];
730 DWORD servicesize, displaysize, tempsize;
731 BOOL ret;
732 static const CHAR deadbeef[] = "Deadbeef";
733 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
734 static const WCHAR abcW[] = {'A','B','C',0};
736 /* Having NULL for the size of the buffer will crash on W2K3 */
738 SetLastError(0xdeadbeef);
739 ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
740 ok(!ret, "Expected failure\n");
741 ok(GetLastError() == ERROR_INVALID_HANDLE,
742 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
744 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
746 servicesize = 200;
747 SetLastError(0xdeadbeef);
748 ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
749 ok(!ret, "Expected failure\n");
750 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
751 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
752 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
753 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
755 /* Valid handle and buffer but no displayname */
756 servicesize = 200;
757 SetLastError(0xdeadbeef);
758 ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
759 ok(!ret, "Expected failure\n");
760 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
761 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
762 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
763 todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize);
765 /* Test for nonexistent displayname */
766 SetLastError(0xdeadbeef);
767 ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
768 ok(!ret, "Expected failure\n");
769 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
770 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
771 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
773 servicesize = 15;
774 strcpy(servicename, "ABC");
775 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
776 ok(!ret, "Expected failure\n");
777 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
778 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
779 todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
780 ok(servicename[0] == 0, "Service name not empty\n");
782 servicesize = 15;
783 lstrcpyW( servicenameW, abcW );
784 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
785 ok(!ret, "Expected failure\n");
786 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
787 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
788 ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
789 ok(servicenameW[0] == 0, "Service name not empty\n");
791 servicesize = 0;
792 strcpy(servicename, "ABC");
793 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
794 ok(!ret, "Expected failure\n");
795 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
796 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
797 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
798 ok(servicename[0] == 'A', "Service name changed\n");
800 servicesize = 0;
801 lstrcpyW( servicenameW, abcW );
802 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
803 ok(!ret, "Expected failure\n");
804 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
805 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
806 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
807 ok(servicenameW[0] == 'A', "Service name changed\n");
809 servicesize = 1;
810 strcpy(servicename, "ABC");
811 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
812 ok(!ret, "Expected failure\n");
813 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
814 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
815 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
816 ok(servicename[0] == 0, "Service name not empty\n");
818 servicesize = 1;
819 lstrcpyW( servicenameW, abcW );
820 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
821 ok(!ret, "Expected failure\n");
822 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
823 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
824 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
825 ok(servicenameW[0] == 'A', "Service name changed\n");
827 servicesize = 2;
828 strcpy(servicename, "ABC");
829 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
830 ok(!ret, "Expected failure\n");
831 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
832 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
833 todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
834 ok(servicename[0] == 0, "Service name not empty\n");
836 servicesize = 2;
837 lstrcpyW( servicenameW, abcW );
838 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
839 ok(!ret, "Expected failure\n");
840 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
841 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
842 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
843 ok(servicenameW[0] == 0, "Service name not empty\n");
845 /* Check if 'Spooler' exists */
846 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
847 if (!svc_handle)
849 skip("Spooler service doesn't exist\n");
850 CloseServiceHandle(scm_handle);
851 return;
853 CloseServiceHandle(svc_handle);
855 /* Get the displayname for the 'Spooler' service */
856 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
857 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
859 /* Retrieve the needed size for the buffer */
860 SetLastError(0xdeadbeef);
861 servicesize = 0;
862 ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
863 ok(!ret, "Expected failure\n");
864 if (strcmp(displayname, "Print Spooler") != 0 &&
865 GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
867 win_skip("GetServiceKeyName() does not support localized display names: %s\n", displayname); /* Windows 7 */
868 CloseServiceHandle(scm_handle);
869 return; /* All the tests that follow will fail too */
872 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
873 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
875 /* Valid call with the correct buffersize */
876 SetLastError(0xdeadbeef);
877 tempsize = servicesize;
878 servicesize *= 2;
879 ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
880 ok(ret, "Expected success, got error %u\n", GetLastError());
881 if (ret)
883 ok(strlen(servicename) == tempsize/2,
884 "Expected the buffer to be twice the length of the string\n") ;
885 ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
886 ok(servicesize == (tempsize * 2),
887 "Expected servicesize not to change if buffer not insufficient\n") ;
890 MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
891 SetLastError(0xdeadbeef);
892 servicesize *= 2;
893 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
894 ok(ret, "Expected success, got error %u\n", GetLastError());
895 if (ret)
897 ok(strlen(servicename) == tempsize/2,
898 "Expected the buffer to be twice the length of the string\n") ;
899 ok(servicesize == lstrlenW(servicenameW),
900 "Expected servicesize not to change if buffer not insufficient\n") ;
903 SetLastError(0xdeadbeef);
904 servicesize = 3;
905 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
906 ok(!ret, "Expected failure\n");
907 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
908 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
909 ok(servicenameW[0] == 0, "Buffer not empty\n");
911 CloseServiceHandle(scm_handle);
914 static void test_query_svc(void)
916 SC_HANDLE scm_handle, svc_handle;
917 BOOL ret;
918 SERVICE_STATUS status;
919 SERVICE_STATUS_PROCESS *statusproc;
920 DWORD bufsize, needed;
922 /* All NULL or wrong */
923 SetLastError(0xdeadbeef);
924 ret = QueryServiceStatus(NULL, NULL);
925 ok(!ret, "Expected failure\n");
926 ok(GetLastError() == ERROR_INVALID_HANDLE,
927 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
929 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
931 /* Check if 'Spooler' exists.
932 * Open with not enough rights to query the status.
934 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
935 if (!svc_handle)
937 skip("Spooler service doesn't exist\n");
938 CloseServiceHandle(scm_handle);
939 return;
942 SetLastError(0xdeadbeef);
943 ret = QueryServiceStatus(svc_handle, NULL);
944 ok(!ret, "Expected failure\n");
945 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
946 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
947 "Unexpected last error %d\n", GetLastError());
949 SetLastError(0xdeadbeef);
950 ret = QueryServiceStatus(svc_handle, &status);
951 ok(!ret, "Expected failure\n");
952 ok(GetLastError() == ERROR_ACCESS_DENIED,
953 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
955 /* Open the service with just enough rights.
956 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
958 CloseServiceHandle(svc_handle);
959 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
961 SetLastError(0xdeadbeef);
962 ret = QueryServiceStatus(svc_handle, &status);
963 ok(ret, "Expected success, got error %u\n", GetLastError());
965 CloseServiceHandle(svc_handle);
967 /* More or less the same tests for QueryServiceStatusEx */
968 if (!pQueryServiceStatusEx)
970 win_skip( "QueryServiceStatusEx not available\n" );
971 CloseServiceHandle(scm_handle);
972 return;
975 /* Open service with not enough rights to query the status */
976 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
978 /* All NULL or wrong, this proves that info level is checked first */
979 SetLastError(0xdeadbeef);
980 ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
981 ok(!ret, "Expected failure\n");
982 ok(GetLastError() == ERROR_INVALID_LEVEL,
983 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
985 /* Passing a NULL parameter for the needed buffer size
986 * will crash on anything but NT4.
989 /* Only info level is correct. It looks like the buffer/size is checked second */
990 SetLastError(0xdeadbeef);
991 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
992 /* NT4 checks the handle first */
993 if (GetLastError() != ERROR_INVALID_HANDLE)
995 ok(!ret, "Expected failure\n");
996 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
997 "Needed buffersize is wrong : %d\n", needed);
998 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
999 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1002 /* Pass a correct buffer and buffersize but a NULL handle */
1003 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1004 bufsize = needed;
1005 SetLastError(0xdeadbeef);
1006 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1007 ok(!ret, "Expected failure\n");
1008 ok(GetLastError() == ERROR_INVALID_HANDLE,
1009 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1010 HeapFree(GetProcessHeap(), 0, statusproc);
1012 /* Correct handle and info level */
1013 SetLastError(0xdeadbeef);
1014 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1015 /* NT4 doesn't return the needed size */
1016 if (GetLastError() != ERROR_INVALID_PARAMETER)
1018 ok(!ret, "Expected failure\n");
1019 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1020 "Needed buffersize is wrong : %d\n", needed);
1021 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1022 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1025 /* All parameters are OK but we don't have enough rights */
1026 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1027 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1028 SetLastError(0xdeadbeef);
1029 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1030 ok(!ret, "Expected failure\n");
1031 ok(GetLastError() == ERROR_ACCESS_DENIED,
1032 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1033 HeapFree(GetProcessHeap(), 0, statusproc);
1035 /* Open the service with just enough rights. */
1036 CloseServiceHandle(svc_handle);
1037 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
1039 /* Everything should be fine now. */
1040 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1041 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1042 SetLastError(0xdeadbeef);
1043 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1044 ok(ret, "Expected success, got error %u\n", GetLastError());
1045 if (statusproc->dwCurrentState == SERVICE_RUNNING)
1046 ok(statusproc->dwProcessId != 0,
1047 "Expect a process id for this running service\n");
1048 else
1049 ok(statusproc->dwProcessId == 0,
1050 "Expect no process id for this stopped service\n");
1052 /* same call with null needed pointer */
1053 SetLastError(0xdeadbeef);
1054 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1055 ok(!ret, "Expected failure\n");
1056 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ ||
1057 GetLastError() == ERROR_INVALID_ADDRESS, "got %d\n", GetLastError());
1059 HeapFree(GetProcessHeap(), 0, statusproc);
1061 CloseServiceHandle(svc_handle);
1062 CloseServiceHandle(scm_handle);
1065 static void test_enum_svc(void)
1067 SC_HANDLE scm_handle;
1068 BOOL ret;
1069 DWORD bufsize, needed, returned, resume;
1070 DWORD neededW, returnedW;
1071 DWORD tempneeded, tempreturned, missing;
1072 DWORD servicecountactive, servicecountinactive;
1073 ENUM_SERVICE_STATUSA *services;
1074 ENUM_SERVICE_STATUSW *servicesW;
1075 ENUM_SERVICE_STATUS_PROCESSA *exservices;
1076 UINT i;
1078 /* All NULL or wrong */
1079 SetLastError(0xdeadbeef);
1080 ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1081 ok(!ret, "Expected failure\n");
1082 ok(GetLastError() == ERROR_INVALID_HANDLE,
1083 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1085 SetLastError(0xdeadbeef);
1086 ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1087 ok(!ret, "Expected failure\n");
1088 ok(GetLastError() == ERROR_INVALID_HANDLE,
1089 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1091 /* Open the service control manager with not enough rights at first */
1092 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1094 /* Valid handle but rest is still NULL or wrong */
1095 SetLastError(0xdeadbeef);
1096 ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1097 ok(!ret, "Expected failure\n");
1098 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1099 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1100 "Unexpected last error %d\n", GetLastError());
1102 SetLastError(0xdeadbeef);
1103 ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1104 ok(!ret, "Expected failure\n");
1105 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1106 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1107 "Unexpected last error %d\n", GetLastError());
1109 /* Don't specify the two required pointers */
1110 returned = 0xdeadbeef;
1111 SetLastError(0xdeadbeef);
1112 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1113 ok(!ret, "Expected failure\n");
1114 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1115 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1116 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1117 "Unexpected last error %d\n", GetLastError());
1119 returned = 0xdeadbeef;
1120 SetLastError(0xdeadbeef);
1121 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1122 ok(!ret, "Expected failure\n");
1123 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1124 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1125 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1126 "Unexpected last error %d\n", GetLastError());
1128 /* Don't specify the two required pointers */
1129 needed = 0xdeadbeef;
1130 SetLastError(0xdeadbeef);
1131 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1132 ok(!ret, "Expected failure\n");
1133 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1134 "Expected no change to the needed buffer variable\n");
1135 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1136 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1137 "Unexpected last error %d\n", GetLastError());
1139 needed = 0xdeadbeef;
1140 SetLastError(0xdeadbeef);
1141 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1142 ok(!ret, "Expected failure\n");
1143 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1144 "Expected no change to the needed buffer variable\n");
1145 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1146 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1147 "Unexpected last error %d\n", GetLastError());
1149 /* No valid servicetype and servicestate */
1150 needed = 0xdeadbeef;
1151 returned = 0xdeadbeef;
1152 SetLastError(0xdeadbeef);
1153 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1154 ok(!ret, "Expected failure\n");
1155 ok(needed == 0 || broken(needed != 0), /* nt4 */
1156 "Expected needed buffer size to be set to 0, got %d\n", needed);
1157 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1158 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1159 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1161 needed = 0xdeadbeef;
1162 returned = 0xdeadbeef;
1163 SetLastError(0xdeadbeef);
1164 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1165 ok(!ret, "Expected failure\n");
1166 ok(needed == 0 || broken(needed != 0), /* nt4 */
1167 "Expected needed buffer size to be set to 0, got %d\n", needed);
1168 ok(returned == 0 || broken(returned != 0), /* nt4 */
1169 "Expected number of services to be set to 0, got %d\n", returned);
1170 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1171 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1173 /* No valid servicestate */
1174 needed = 0xdeadbeef;
1175 returned = 0xdeadbeef;
1176 SetLastError(0xdeadbeef);
1177 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1178 ok(!ret, "Expected failure\n");
1179 ok(needed == 0 || broken(needed != 0), /* nt4 */
1180 "Expected needed buffer size to be set to 0, got %d\n", needed);
1181 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1182 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1183 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1185 needed = 0xdeadbeef;
1186 returned = 0xdeadbeef;
1187 SetLastError(0xdeadbeef);
1188 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1189 ok(!ret, "Expected failure\n");
1190 ok(needed == 0 || broken(needed != 0), /* nt4 */
1191 "Expected needed buffer size to be set to 0, got %d\n", needed);
1192 ok(returned == 0 || broken(returned != 0), /* nt4 */
1193 "Expected number of services to be set to 0, got %d\n", returned);
1194 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1195 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1197 /* No valid servicetype */
1198 needed = 0xdeadbeef;
1199 returned = 0xdeadbeef;
1200 SetLastError(0xdeadbeef);
1201 ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1202 ok(!ret, "Expected failure\n");
1203 ok(needed == 0 || broken(needed != 0), /* nt4 */
1204 "Expected needed buffer size to be set to 0, got %d\n", needed);
1205 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1206 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1207 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1209 needed = 0xdeadbeef;
1210 returned = 0xdeadbeef;
1211 SetLastError(0xdeadbeef);
1212 ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1213 ok(!ret, "Expected failure\n");
1214 ok(needed == 0 || broken(needed != 0), /* nt4 */
1215 "Expected needed buffer size to be set to 0, got %d\n", needed);
1216 ok(returned == 0 || broken(returned != 0), /* nt4 */
1217 "Expected number of services to be set to 0, got %d\n", returned);
1218 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1219 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1221 /* All parameters are correct but our access rights are wrong */
1222 needed = 0xdeadbeef;
1223 returned = 0xdeadbeef;
1224 SetLastError(0xdeadbeef);
1225 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1226 ok(!ret, "Expected failure\n");
1227 ok(needed == 0 || broken(needed != 0), /* nt4 */
1228 "Expected needed buffer size to be set to 0, got %d\n", needed);
1229 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1230 ok(GetLastError() == ERROR_ACCESS_DENIED,
1231 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1233 needed = 0xdeadbeef;
1234 returned = 0xdeadbeef;
1235 SetLastError(0xdeadbeef);
1236 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1237 ok(!ret, "Expected failure\n");
1238 ok(needed == 0 || broken(needed != 0), /* nt4 */
1239 "Expected needed buffer size to be set to 0, got %d\n", needed);
1240 ok(returned == 0 || broken(returned != 0), /* nt4 */
1241 "Expected number of services to be set to 0, got %d\n", returned);
1242 ok(GetLastError() == ERROR_ACCESS_DENIED,
1243 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1245 /* Open the service control manager with the needed rights */
1246 CloseServiceHandle(scm_handle);
1247 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1249 /* All parameters are correct. Request the needed buffer size */
1250 needed = 0xdeadbeef;
1251 returned = 0xdeadbeef;
1252 SetLastError(0xdeadbeef);
1253 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1254 ok(!ret, "Expected failure\n");
1255 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1256 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1257 ok(GetLastError() == ERROR_MORE_DATA,
1258 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1260 /* Test to show we get the same needed buffer size for the W-call */
1261 neededW = 0xdeadbeef;
1262 returnedW = 0xdeadbeef;
1263 SetLastError(0xdeadbeef);
1264 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL);
1265 ok(!ret, "Expected failure\n");
1266 ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n");
1267 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1268 ok(returnedW == 0, "Expected no service returned, got %d\n", returnedW);
1269 ok(GetLastError() == ERROR_MORE_DATA,
1270 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1272 /* Store the needed bytes */
1273 tempneeded = needed;
1275 /* Allocate the correct needed bytes */
1276 services = HeapAlloc(GetProcessHeap(), 0, needed);
1277 bufsize = needed;
1278 needed = 0xdeadbeef;
1279 returned = 0xdeadbeef;
1280 SetLastError(0xdeadbeef);
1281 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1282 services, bufsize, &needed, &returned, NULL);
1283 ok(ret, "Expected success, got error %u\n", GetLastError());
1284 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1285 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1286 HeapFree(GetProcessHeap(), 0, services);
1288 /* Store the number of returned services */
1289 tempreturned = returned;
1291 servicesW = HeapAlloc(GetProcessHeap(), 0, neededW);
1292 bufsize = neededW;
1293 neededW = 0xdeadbeef;
1294 returnedW = 0xdeadbeef;
1295 SetLastError(0xdeadbeef);
1296 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1297 servicesW, bufsize, &neededW, &returnedW, NULL);
1298 ok(ret, "Expected success, got error %u\n", GetLastError());
1299 ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n");
1300 ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n");
1301 HeapFree(GetProcessHeap(), 0, servicesW);
1303 /* Allocate less than the needed bytes and don't specify a resume handle */
1304 services = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1305 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1306 needed = 0xdeadbeef;
1307 returned = 0xdeadbeef;
1308 SetLastError(0xdeadbeef);
1309 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1310 services, bufsize, &needed, &returned, NULL);
1311 ok(!ret, "Expected failure\n");
1312 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1313 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1314 ok(GetLastError() == ERROR_MORE_DATA,
1315 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1317 /* Allocate less than the needed bytes, this time with a correct resume handle */
1318 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1319 needed = 0xdeadbeef;
1320 returned = 0xdeadbeef;
1321 resume = 0;
1322 SetLastError(0xdeadbeef);
1323 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1324 services, bufsize, &needed, &returned, &resume);
1325 ok(!ret, "Expected failure\n");
1326 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1327 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1328 todo_wine ok(resume, "Expected a resume handle\n");
1329 ok(GetLastError() == ERROR_MORE_DATA,
1330 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1332 /* Fetch the missing services but pass a bigger buffer size */
1333 missing = tempreturned - returned;
1334 bufsize = tempneeded;
1335 needed = 0xdeadbeef;
1336 returned = 0xdeadbeef;
1337 SetLastError(0xdeadbeef);
1338 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1339 services, bufsize, &needed, &returned, &resume);
1340 ok(ret, "Expected success, got error %u\n", GetLastError());
1341 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1342 todo_wine ok(returned == missing, "Expected %u services to be returned\n", missing);
1343 ok(resume == 0, "Expected the resume handle to be 0\n");
1344 HeapFree(GetProcessHeap(), 0, services);
1346 /* See if things add up */
1348 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1349 * and doesn't count the others as inactive. This means that Vista could
1350 * show a total that is greater than the sum of active and inactive
1351 * drivers.
1352 * The number of active and inactive drivers is greatly influenced by the
1353 * time when tests are run, immediately after boot or later for example.
1355 * Both reasons make calculations for drivers not so useful
1358 /* Get the number of active win32 services */
1359 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
1360 &needed, &returned, NULL);
1361 services = HeapAlloc(GetProcessHeap(), 0, needed);
1362 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services,
1363 needed, &needed, &returned, NULL);
1364 HeapFree(GetProcessHeap(), 0, services);
1366 servicecountactive = returned;
1368 /* Get the number of inactive win32 services */
1369 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
1370 &needed, &returned, NULL);
1371 services = HeapAlloc(GetProcessHeap(), 0, needed);
1372 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services,
1373 needed, &needed, &returned, NULL);
1374 HeapFree(GetProcessHeap(), 0, services);
1376 servicecountinactive = returned;
1378 /* Get the number of win32 services */
1379 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
1380 &needed, &returned, NULL);
1381 services = HeapAlloc(GetProcessHeap(), 0, needed);
1382 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services,
1383 needed, &needed, &returned, NULL);
1384 HeapFree(GetProcessHeap(), 0, services);
1386 /* Check if total is the same as active and inactive win32 services */
1387 ok(returned == (servicecountactive + servicecountinactive),
1388 "Something wrong in the calculation\n");
1390 /* Get all drivers and services
1392 * Fetch the status of the last call as failing could make the following tests crash
1393 * on Wine (we don't return anything yet).
1395 EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1396 NULL, 0, &needed, &returned, NULL);
1397 services = HeapAlloc(GetProcessHeap(), 0, needed);
1398 ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1399 services, needed, &needed, &returned, NULL);
1401 /* Loop through all those returned drivers and services */
1402 for (i = 0; ret && i < returned; i++)
1404 SERVICE_STATUS status = services[i].ServiceStatus;
1406 /* lpServiceName and lpDisplayName should always be filled */
1407 ok(services[i].lpServiceName[0], "Expected a service name\n");
1408 ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n");
1410 /* Decrement the counters to see if the functions calls return the same
1411 * numbers as the contents of these structures.
1413 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1415 if (status.dwCurrentState == SERVICE_STOPPED)
1416 servicecountinactive--;
1417 else
1418 servicecountactive--;
1421 HeapFree(GetProcessHeap(), 0, services);
1423 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1424 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1426 CloseServiceHandle(scm_handle);
1428 /* More or less the same for EnumServicesStatusExA */
1429 if (!pEnumServicesStatusExA)
1431 win_skip( "EnumServicesStatusExA not available\n" );
1432 return;
1435 /* All NULL or wrong */
1436 SetLastError(0xdeadbeef);
1437 ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1438 ok(!ret, "Expected failure\n");
1439 ok(GetLastError() == ERROR_INVALID_LEVEL,
1440 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1442 /* All NULL or wrong, just the info level is correct */
1443 SetLastError(0xdeadbeef);
1444 ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1445 ok(!ret, "Expected failure\n");
1446 ok(GetLastError() == ERROR_INVALID_HANDLE,
1447 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1449 /* Open the service control manager with not enough rights at first */
1450 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1452 /* Valid handle and info level but rest is still NULL or wrong */
1453 SetLastError(0xdeadbeef);
1454 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1455 ok(!ret, "Expected failure\n");
1456 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1457 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1458 "Unexpected last error %d\n", GetLastError());
1460 /* Don't specify the two required pointers */
1461 needed = 0xdeadbeef;
1462 SetLastError(0xdeadbeef);
1463 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1464 ok(!ret, "Expected failure\n");
1465 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1466 "Expected no change to the needed buffer variable\n");
1467 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1468 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1469 "Unexpected last error %d\n", GetLastError());
1471 /* Don't specify the two required pointers */
1472 returned = 0xdeadbeef;
1473 SetLastError(0xdeadbeef);
1474 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1475 ok(!ret, "Expected failure\n");
1476 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1477 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1478 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1479 "Unexpected last error %d\n", GetLastError());
1481 /* No valid servicetype and servicestate */
1482 needed = 0xdeadbeef;
1483 returned = 0xdeadbeef;
1484 SetLastError(0xdeadbeef);
1485 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1486 ok(!ret, "Expected failure\n");
1487 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1488 ok(needed == 0 || broken(needed != 0), /* nt4 */
1489 "Expected needed buffer size to be set to 0, got %d\n", needed);
1490 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1491 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1493 /* No valid servicestate */
1494 needed = 0xdeadbeef;
1495 returned = 0xdeadbeef;
1496 SetLastError(0xdeadbeef);
1497 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1498 &needed, &returned, NULL, NULL);
1499 ok(!ret, "Expected failure\n");
1500 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1501 ok(needed == 0 || broken(needed != 0), /* nt4 */
1502 "Expected needed buffer size to be set to 0, got %d\n", needed);
1503 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1504 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1506 /* No valid servicetype */
1507 needed = 0xdeadbeef;
1508 returned = 0xdeadbeef;
1509 SetLastError(0xdeadbeef);
1510 ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1511 &needed, &returned, NULL, NULL);
1512 ok(!ret, "Expected failure\n");
1513 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1514 ok(needed == 0 || broken(needed != 0), /* nt4 */
1515 "Expected needed buffer size to be set to 0, got %d\n", needed);
1516 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1517 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1519 /* No valid servicetype and servicestate and unknown service group */
1520 needed = 0xdeadbeef;
1521 returned = 0xdeadbeef;
1522 SetLastError(0xdeadbeef);
1523 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1524 &returned, NULL, "deadbeef_group");
1525 ok(!ret, "Expected failure\n");
1526 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1527 ok(needed == 0 || broken(needed != 0), /* nt4 */
1528 "Expected needed buffer size to be set to 0, got %d\n", needed);
1529 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1530 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1532 /* All parameters are correct but our access rights are wrong */
1533 needed = 0xdeadbeef;
1534 returned = 0xdeadbeef;
1535 SetLastError(0xdeadbeef);
1536 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1537 NULL, 0, &needed, &returned, NULL, NULL);
1538 ok(!ret, "Expected failure\n");
1539 ok(needed == 0 || broken(needed != 0), /* nt4 */
1540 "Expected needed buffer size to be set to 0, got %d\n", needed);
1541 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1542 ok(GetLastError() == ERROR_ACCESS_DENIED,
1543 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1545 /* All parameters are correct, access rights are wrong but the
1546 * group name won't be checked yet.
1548 needed = 0xdeadbeef;
1549 returned = 0xdeadbeef;
1550 SetLastError(0xdeadbeef);
1551 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1552 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1553 ok(!ret, "Expected failure\n");
1554 ok(needed == 0 || broken(needed != 0), /* nt4 */
1555 "Expected needed buffer size to be set to 0, got %d\n", needed);
1556 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1557 ok(GetLastError() == ERROR_ACCESS_DENIED,
1558 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1560 /* Open the service control manager with the needed rights */
1561 CloseServiceHandle(scm_handle);
1562 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1564 /* All parameters are correct and the group will be checked */
1565 needed = 0xdeadbeef;
1566 returned = 0xdeadbeef;
1567 SetLastError(0xdeadbeef);
1568 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1569 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1570 ok(!ret, "Expected failure\n");
1571 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1572 ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
1573 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
1574 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1576 /* TODO: Create a test that makes sure we enumerate all services that don't
1577 * belong to a group. (specifying "").
1580 /* All parameters are correct. Request the needed buffer size */
1581 needed = 0xdeadbeef;
1582 returned = 0xdeadbeef;
1583 SetLastError(0xdeadbeef);
1584 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1585 NULL, 0, &needed, &returned, NULL, NULL);
1586 ok(!ret, "Expected failure\n");
1587 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1588 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1589 ok(GetLastError() == ERROR_MORE_DATA,
1590 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1592 /* Test to show we get the same needed buffer size for the W-call */
1593 neededW = 0xdeadbeef;
1594 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1595 NULL, 0, &neededW, &returnedW, NULL, NULL);
1596 ok(!ret, "Expected failure\n");
1597 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1599 /* Store the needed bytes */
1600 tempneeded = needed;
1602 /* Allocate the correct needed bytes */
1603 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1604 bufsize = needed;
1605 needed = 0xdeadbeef;
1606 returned = 0xdeadbeef;
1607 SetLastError(0xdeadbeef);
1608 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1609 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1610 ok(ret, "Expected success, got error %u\n", GetLastError());
1611 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1612 ok(returned == tempreturned, "Expected the same number of service from this function\n");
1613 HeapFree(GetProcessHeap(), 0, exservices);
1615 /* Store the number of returned services */
1616 tempreturned = returned;
1618 /* Allocate less than the needed bytes and don't specify a resume handle */
1619 exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1620 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1621 needed = 0xdeadbeef;
1622 returned = 0xdeadbeef;
1623 SetLastError(0xdeadbeef);
1624 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1625 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1626 ok(!ret, "Expected failure\n");
1627 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1628 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1629 ok(GetLastError() == ERROR_MORE_DATA,
1630 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1632 /* Allocate less than the needed bytes, this time with a correct resume handle */
1633 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1634 needed = 0xdeadbeef;
1635 returned = 0xdeadbeef;
1636 resume = 0;
1637 SetLastError(0xdeadbeef);
1638 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1639 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1640 ok(!ret, "Expected failure\n");
1641 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1642 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1643 todo_wine ok(resume, "Expected a resume handle\n");
1644 ok(GetLastError() == ERROR_MORE_DATA,
1645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1647 /* Fetch that last service but pass a bigger buffer size */
1648 missing = tempreturned - returned;
1649 bufsize = tempneeded;
1650 needed = 0xdeadbeef;
1651 returned = 0xdeadbeef;
1652 SetLastError(0xdeadbeef);
1653 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1654 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1655 ok(ret, "Expected success, got error %u\n", GetLastError());
1656 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1657 ok(returned == missing, "Expected %u services to be returned\n", missing);
1658 ok(resume == 0, "Expected the resume handle to be 0\n");
1659 HeapFree(GetProcessHeap(), 0, exservices);
1661 /* See if things add up */
1663 /* Get the number of active win32 services */
1664 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1665 NULL, 0, &needed, &returned, NULL, NULL);
1666 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1667 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1668 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1669 HeapFree(GetProcessHeap(), 0, exservices);
1671 servicecountactive = returned;
1673 /* Get the number of inactive win32 services */
1674 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1675 NULL, 0, &needed, &returned, NULL, NULL);
1676 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1677 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1678 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1679 HeapFree(GetProcessHeap(), 0, exservices);
1681 servicecountinactive = returned;
1683 /* Get the number of win32 services */
1684 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1685 NULL, 0, &needed, &returned, NULL, NULL);
1686 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1687 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1688 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1689 HeapFree(GetProcessHeap(), 0, exservices);
1691 /* Check if total is the same as active and inactive win32 services */
1692 ok(returned == (servicecountactive + servicecountinactive),
1693 "Something wrong in the calculation\n");
1695 /* Get all drivers and services */
1696 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1697 SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1698 ok(!ret, "Expected failure\n");
1699 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1700 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1701 SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1702 ok(ret, "Expected success %u\n", GetLastError());
1704 /* Loop through all those returned drivers and services */
1705 for (i = 0; i < returned; i++)
1707 SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
1709 /* lpServiceName and lpDisplayName should always be filled */
1710 ok(exservices[i].lpServiceName[0], "Expected a service name\n");
1711 ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n");
1713 /* Decrement the counters to see if the functions calls return the
1714 * same numbers as the contents of these structures.
1715 * Check some process id specifics.
1717 if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
1719 /* We shouldn't have a process id for drivers */
1720 ok(status.dwProcessId == 0,
1721 "This driver shouldn't have an associated process id\n");
1724 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1726 if (status.dwCurrentState != SERVICE_STOPPED)
1728 /* We expect a process id for every running service */
1729 ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1730 exservices[i].lpServiceName);
1732 servicecountactive--;
1734 else
1736 /* We shouldn't have a process id for inactive services */
1737 ok(status.dwProcessId == 0, "Service %s state %u shouldn't have an associated process id\n",
1738 exservices[i].lpServiceName, status.dwCurrentState);
1740 servicecountinactive--;
1744 HeapFree(GetProcessHeap(), 0, exservices);
1746 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1747 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1749 CloseServiceHandle(scm_handle);
1752 static void test_close(void)
1754 SC_HANDLE handle;
1755 BOOL ret;
1757 /* NULL handle */
1758 SetLastError(0xdeadbeef);
1759 ret = CloseServiceHandle(NULL);
1760 ok(!ret, "Expected failure\n");
1761 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1763 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1765 /* Proper call */
1766 handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1767 SetLastError(0xdeadbeef);
1768 ret = CloseServiceHandle(handle);
1769 ok(ret, "Expected success got error %u\n", GetLastError());
1772 static void test_wow64(void)
1774 SC_HANDLE manager, service;
1775 BOOL wow64, ret;
1776 HANDLE file;
1778 if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &wow64) || !wow64)
1780 skip("Not running under WoW64.\n");
1781 return;
1784 if (!(manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE)))
1786 skip("Not enough permissions to create a service.\n");
1787 return;
1790 file = CreateFileA("C:\\windows\\syswow64\\winetestsvc.exe", GENERIC_WRITE,
1791 0, NULL, CREATE_ALWAYS, 0, NULL);
1792 CloseHandle(file);
1794 service = CreateServiceA(manager, "winetestsvc", "winetestsvc",
1795 SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE,
1796 SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1797 "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1798 ok(!!service, "Failed to create service, error %u.\n", GetLastError());
1799 ret = StartServiceA(service, 0, NULL);
1800 ok(!ret, "Expected failure.\n");
1801 ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %u.\n", GetLastError());
1803 ret = DeleteService(service);
1804 ok(ret, "Failed to delete service, error %u.\n", GetLastError());
1805 CloseServiceHandle(service);
1807 service = CreateServiceA(manager, "winetestsvc2", "winetestsvc2", SERVICE_START | DELETE,
1808 SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1809 "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
1810 ok(!!service, "Failed to create service, error %u.\n", GetLastError());
1811 ret = StartServiceA(service, 0, NULL);
1812 ok(!ret, "Expected failure.\n");
1813 todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %u.\n", GetLastError());
1815 ret = DeleteService(service);
1816 ok(ret, "Failed to delete service, error %u.\n", GetLastError());
1817 CloseServiceHandle(service);
1819 ret = DeleteFileA("C:\\windows\\syswow64\\winetestsvc.exe");
1820 ok(ret, "Failed to delete file, error %u.\n", GetLastError());
1822 file = CreateFileA("C:\\windows\\sysnative\\winetestsvc.exe", GENERIC_WRITE,
1823 0, NULL, CREATE_ALWAYS, 0, NULL);
1824 CloseHandle(file);
1826 service = CreateServiceA(manager, "winetestsvc3", "winetestsvc3", SERVICE_START | DELETE,
1827 SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1828 "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1829 ok(!!service, "Failed to create service, error %u.\n", GetLastError());
1830 ret = StartServiceA(service, 0, NULL);
1831 ok(!ret, "Expected failure.\n");
1832 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %u.\n", GetLastError());
1834 ret = DeleteService(service);
1835 ok(ret, "Failed to delete service, error %u.\n", GetLastError());
1836 CloseServiceHandle(service);
1838 service = CreateServiceA(manager, "winetestsvc4", "winetestsvc4", SERVICE_START | DELETE,
1839 SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1840 "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
1841 ok(!!service, "Failed to create service, error %u.\n", GetLastError());
1842 ret = StartServiceA(service, 0, NULL);
1843 ok(!ret, "Expected failure.\n");
1844 todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %u.\n", GetLastError());
1846 ret = DeleteService(service);
1847 ok(ret, "Failed to delete service, error %u.\n", GetLastError());
1848 CloseServiceHandle(service);
1850 ret = DeleteFileA("C:\\windows\\sysnative\\winetestsvc.exe");
1851 ok(ret, "Failed to delete file, error %u.\n", GetLastError());
1853 CloseServiceHandle(manager);
1856 static void test_sequence(void)
1858 SC_HANDLE scm_handle, svc_handle;
1859 BOOL ret, is_nt4;
1860 QUERY_SERVICE_CONFIGA *config;
1861 DWORD given, needed;
1862 static const CHAR servicename [] = "winetest_sequence";
1863 static const CHAR displayname [] = "Winetest dummy service";
1864 static const CHAR displayname2[] = "Winetest dummy service (2)";
1865 static const CHAR pathname [] = "we_dont_care.exe";
1866 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
1867 static const CHAR password [] = "";
1868 static const CHAR empty [] = "";
1869 static const CHAR localsystem [] = "LocalSystem";
1871 SetLastError(0xdeadbeef);
1872 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
1874 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1876 skip("Not enough rights to get a handle to the manager\n");
1877 return;
1879 else
1880 ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
1882 if (!scm_handle) return;
1883 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
1884 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
1885 CloseServiceHandle(svc_handle);
1887 /* Create a dummy service */
1888 SetLastError(0xdeadbeef);
1889 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
1890 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
1891 pathname, NULL, NULL, dependencies, NULL, password);
1893 if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
1895 /* We try and open the service and do the rest of the tests. Some could
1896 * fail if the tests were changed between these runs.
1898 trace("Deletion probably didn't work last time\n");
1899 SetLastError(0xdeadbeef);
1900 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
1901 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1903 skip("Not enough rights to open the service\n");
1904 CloseServiceHandle(scm_handle);
1905 return;
1907 ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
1909 else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1911 skip("Not enough rights to create the service\n");
1912 CloseServiceHandle(scm_handle);
1913 return;
1915 else
1917 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
1918 if (svc_handle != NULL)
1920 PSID sidOwner, sidGroup;
1921 PACL dacl, sacl;
1922 PSECURITY_DESCRIPTOR pSD;
1923 DWORD error, n1, n2;
1924 HRESULT retval;
1925 BOOL bret;
1927 /* Test using GetSecurityInfo to obtain security information */
1928 retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
1929 &sidGroup, &dacl, &sacl, &pSD);
1930 LocalFree(pSD);
1931 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1932 retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1933 NULL, NULL, NULL, &pSD);
1934 LocalFree(pSD);
1935 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1936 if (!is_nt4)
1938 retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1939 NULL, &dacl, NULL, &pSD);
1940 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1941 LocalFree(pSD);
1942 SetLastError(0xdeadbeef);
1943 retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1944 NULL, NULL, NULL, NULL);
1945 error = GetLastError();
1946 ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval);
1947 ok(error == 0xdeadbeef, "Unexpected last error %d\n", error);
1949 else
1950 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1952 /* Test using QueryServiceObjectSecurity to obtain security information */
1953 SetLastError(0xdeadbeef);
1954 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
1955 error = GetLastError();
1956 ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
1957 ok(error == ERROR_INSUFFICIENT_BUFFER ||
1958 broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER),
1959 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error);
1960 if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
1961 pSD = LocalAlloc(0, n1);
1962 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
1963 ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
1964 LocalFree(pSD);
1968 if (!svc_handle) {
1969 CloseServiceHandle(scm_handle);
1970 return;
1973 /* TODO:
1974 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1975 * that the correct keys are used.
1978 /* Request the size for the buffer */
1979 SetLastError(0xdeadbeef);
1980 ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
1981 ok(!ret, "Expected failure\n");
1982 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1984 config = HeapAlloc(GetProcessHeap(), 0, needed);
1985 given = needed;
1986 SetLastError(0xdeadbeef);
1987 ret = QueryServiceConfigA(svc_handle, config, given, &needed);
1988 ok(ret, "Expected success, got error %u\n", GetLastError());
1990 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
1991 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
1992 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
1993 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
1994 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
1995 ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
1996 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
1997 ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
1998 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
1999 /* TODO: Show the double 0 terminated string */
2000 todo_wine
2002 ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
2004 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2005 ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
2007 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2",
2008 NULL, NULL, NULL, NULL, displayname2);
2009 ok(ret, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
2011 QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2012 config = HeapReAlloc(GetProcessHeap(), 0, config, needed);
2013 ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
2014 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2015 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2016 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
2017 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
2018 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
2019 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl);
2020 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2021 ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
2022 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
2023 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2024 ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
2026 SetLastError(0xdeadbeef);
2027 ret = DeleteService(svc_handle);
2028 ok(ret, "Expected success, got error %u\n", GetLastError());
2029 CloseServiceHandle(svc_handle);
2030 CloseServiceHandle(scm_handle);
2031 HeapFree(GetProcessHeap(), 0, config);
2034 static void test_queryconfig2(void)
2036 SC_HANDLE scm_handle, svc_handle;
2037 BOOL ret;
2038 DWORD expected, needed;
2039 BYTE buffer[MAX_PATH];
2040 LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
2041 LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
2042 SERVICE_PRESHUTDOWN_INFO preshutdown_info;
2043 static const CHAR servicename [] = "winetest_query_config2";
2044 static const CHAR displayname [] = "Winetest dummy service";
2045 static const CHAR pathname [] = "we_dont_care.exe";
2046 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2047 static const CHAR password [] = "";
2048 static const CHAR description [] = "Description";
2049 static const CHAR description_empty[] = "";
2050 static const WCHAR descriptionW [] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
2051 static const WCHAR descriptionW_empty[] = {0};
2053 if(!pQueryServiceConfig2A)
2055 win_skip("function QueryServiceConfig2A not present\n");
2056 return;
2059 SetLastError(0xdeadbeef);
2060 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2062 if (!scm_handle)
2064 if(GetLastError() == ERROR_ACCESS_DENIED)
2065 skip("Not enough rights to get a handle to the manager\n");
2066 else
2067 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
2068 return;
2071 /* Create a dummy service */
2072 SetLastError(0xdeadbeef);
2073 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2074 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
2075 pathname, NULL, NULL, dependencies, NULL, password);
2077 if (!svc_handle)
2079 if(GetLastError() == ERROR_SERVICE_EXISTS)
2081 /* We try and open the service and do the rest of the tests. Some could
2082 * fail if the tests were changed between these runs.
2084 trace("Deletion probably didn't work last time\n");
2085 SetLastError(0xdeadbeef);
2086 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2087 if (!svc_handle)
2089 if(GetLastError() == ERROR_ACCESS_DENIED)
2090 skip("Not enough rights to open the service\n");
2091 else
2092 ok(FALSE, "Could not open the service : %d\n", GetLastError());
2093 CloseServiceHandle(scm_handle);
2094 return;
2097 if (GetLastError() == ERROR_ACCESS_DENIED)
2099 skip("Not enough rights to create the service\n");
2100 CloseServiceHandle(scm_handle);
2101 return;
2103 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
2104 if (!svc_handle)
2106 CloseServiceHandle(scm_handle);
2107 return;
2110 SetLastError(0xdeadbeef);
2111 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2112 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2113 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2115 SetLastError(0xdeadbeef);
2116 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2117 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2118 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2120 SetLastError(0xdeadbeef);
2121 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2122 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2123 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2125 SetLastError(0xdeadbeef);
2126 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2127 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2128 ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
2129 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2131 SetLastError(0xdeadbeef);
2132 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2133 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2134 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2136 needed = 0;
2137 SetLastError(0xdeadbeef);
2138 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2139 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2140 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2141 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2143 needed = 0;
2144 pConfig->lpDescription = (LPSTR)0xdeadbeef;
2145 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2146 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2147 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2148 ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2150 SetLastError(0xdeadbeef);
2151 needed = 0;
2152 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2153 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2154 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2155 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2157 if(!pChangeServiceConfig2A)
2159 win_skip("function ChangeServiceConfig2A not present\n");
2160 goto cleanup;
2163 pConfig->lpDescription = (LPSTR) description;
2164 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2165 ok(ret, "ChangeServiceConfig2A failed\n");
2166 if (!ret) {
2167 goto cleanup;
2170 SetLastError(0xdeadbeef);
2171 needed = 0;
2172 expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2173 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2174 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2175 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2176 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2178 SetLastError(0xdeadbeef);
2179 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2180 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2181 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2183 SetLastError(0xdeadbeef);
2184 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2185 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2186 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2187 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2189 SetLastError(0xdeadbeef);
2190 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2191 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2192 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2193 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2195 if(!pQueryServiceConfig2W)
2197 win_skip("function QueryServiceConfig2W not present\n");
2198 goto cleanup;
2200 SetLastError(0xdeadbeef);
2201 needed = 0;
2202 expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2203 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2204 ok(!ret, "expected QueryServiceConfig2W to fail\n");
2205 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2206 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2208 SetLastError(0xdeadbeef);
2209 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2210 ok(ret, "expected QueryServiceConfig2W to succeed\n");
2212 pConfig->lpDescription = (LPSTR)description;
2213 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2214 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2216 pConfig->lpDescription = NULL;
2217 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2218 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2219 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2220 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2222 pConfig->lpDescription = NULL;
2223 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2224 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2226 pConfig->lpDescription = NULL;
2227 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2228 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2229 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2230 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2232 pConfig->lpDescription = (LPSTR)description_empty;
2233 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2234 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2236 pConfig->lpDescription = (void*)0xdeadbeef;
2237 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2238 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2239 ok(!pConfig->lpDescription,
2240 "expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2242 pConfigW->lpDescription = (LPWSTR)descriptionW;
2243 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2244 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2246 pConfigW->lpDescription = NULL;
2247 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2248 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2249 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2250 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2252 pConfigW->lpDescription = NULL;
2253 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2254 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2256 pConfigW->lpDescription = NULL;
2257 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2258 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2259 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2260 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2262 pConfigW->lpDescription = (LPWSTR)descriptionW_empty;
2263 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2264 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2266 pConfigW->lpDescription = (void*)0xdeadbeef;
2267 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2268 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2269 ok(!pConfigW->lpDescription,
2270 "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2272 SetLastError(0xdeadbeef);
2273 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2274 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2275 if(!ret && GetLastError()==ERROR_INVALID_LEVEL)
2277 /* Win2k3 and older */
2278 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2279 goto cleanup;
2281 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2282 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2283 ok(preshutdown_info.dwPreshutdownTimeout == 180000
2284 || preshutdown_info.dwPreshutdownTimeout == 10000 /* Win10 1709+ */,
2285 "Default PreshutdownTimeout = %d\n", preshutdown_info.dwPreshutdownTimeout);
2287 SetLastError(0xdeadbeef);
2288 preshutdown_info.dwPreshutdownTimeout = -1;
2289 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2290 (LPVOID)&preshutdown_info);
2291 ok(ret, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2293 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2294 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2295 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2296 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2297 ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %d\n",
2298 preshutdown_info.dwPreshutdownTimeout);
2300 cleanup:
2301 DeleteService(svc_handle);
2302 CloseServiceHandle(svc_handle);
2303 CloseServiceHandle(scm_handle);
2306 static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2308 BOOL ret;
2309 DWORD le1, le2;
2310 SERVICE_STATUS status;
2312 ret = StartServiceA(svc_handle, 0, NULL);
2313 le1 = GetLastError();
2314 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2316 if (pQueryServiceStatusEx)
2318 DWORD needed;
2319 SERVICE_STATUS_PROCESS statusproc;
2321 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2322 ok(ret, "%s: QueryServiceStatusEx() failed le=%u\n", name, GetLastError());
2323 ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%x\n", name, statusproc.dwCurrentState);
2324 ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %x\n", name, statusproc.dwProcessId);
2327 ret = StartServiceA(svc_handle, 0, NULL);
2328 le2 = GetLastError();
2329 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2330 ok(le2 == le1, "%s: the second try should yield the same error: %u != %u\n", name, le1, le2);
2332 status.dwCurrentState = 0xdeadbeef;
2333 ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status);
2334 le2 = GetLastError();
2335 ok(!ret, "%s: ControlService() should have failed\n", name);
2336 ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2337 ok(status.dwCurrentState == SERVICE_STOPPED ||
2338 broken(is_nt4), /* NT4 returns a random value */
2339 "%s: should be stopped state=%x\n", name, status.dwCurrentState);
2341 return le1;
2344 #define PHASE_STOPPED 1
2345 #define PHASE_RUNNING 2
2347 struct notify_data {
2348 SERVICE_NOTIFYW notify;
2349 SC_HANDLE svc;
2350 BOOL was_called;
2351 DWORD phase;
2354 static void CALLBACK notify_cb(void *user)
2356 struct notify_data *data = user;
2357 switch (data->phase)
2359 case PHASE_STOPPED:
2360 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2361 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2362 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2363 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2364 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2365 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2366 break;
2368 case PHASE_RUNNING:
2369 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2370 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2371 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2372 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2373 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2374 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2375 break;
2378 data->was_called = TRUE;
2381 static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
2383 DWORD dr, dr2;
2384 struct notify_data data;
2385 struct notify_data data2;
2386 BOOL br;
2387 SERVICE_STATUS status;
2388 HANDLE svc, svc2;
2390 if(!pNotifyServiceStatusChangeW){
2391 win_skip("No NotifyServiceStatusChangeW\n");
2392 return;
2395 svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2396 svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2397 ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2398 if(!svc || !svc2)
2399 return;
2401 /* receive stopped notification, then start service */
2402 memset(&data.notify, 0, sizeof(data.notify));
2403 data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2404 data.notify.pfnNotifyCallback = &notify_cb;
2405 data.notify.pContext = &data;
2406 data.svc = svc;
2407 data.phase = PHASE_STOPPED;
2408 data.was_called = FALSE;
2410 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2411 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2413 dr = SleepEx(100, TRUE);
2414 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2415 ok(data.was_called == TRUE, "APC wasn't called\n");
2417 br = StartServiceA(svc, 0, NULL);
2418 ok(br, "StartService failed: %u\n", GetLastError());
2420 /* receive running notification */
2421 data.phase = PHASE_RUNNING;
2422 data.was_called = FALSE;
2424 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2425 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2427 dr = SleepEx(100, TRUE);
2428 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2429 ok(data.was_called == TRUE, "APC wasn't called\n");
2431 /* cannot register two notifications on the same handle */
2432 data.phase = PHASE_STOPPED;
2433 data.was_called = FALSE;
2435 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2436 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2438 memset(&data2.notify, 0, sizeof(data2.notify));
2439 data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2440 data2.notify.pfnNotifyCallback = &notify_cb;
2441 data2.notify.pContext = &data2;
2442 data2.phase = PHASE_RUNNING;
2443 data2.was_called = FALSE;
2445 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2446 ok(dr == ERROR_ALREADY_REGISTERED || !dr /* Win8+ */, "wrong error %u\n", dr);
2447 if (!dr)
2449 dr = SleepEx(100, TRUE);
2450 ok(dr == WAIT_IO_COMPLETION, "got %u\n", dr);
2451 ok(data2.was_called, "APC was not called\n");
2453 else
2455 dr = SleepEx(100, TRUE);
2456 ok(!dr, "got %u\n", dr);
2457 ok(!data2.was_called, "APC should not have been called\n");
2459 ok(data.was_called == FALSE, "APC should not have been called\n");
2461 memset(&data2.notify, 0, sizeof(data2.notify));
2462 data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2463 data2.notify.pfnNotifyCallback = &notify_cb;
2464 data2.notify.pContext = &data;
2465 data2.svc = svc2;
2466 data2.phase = PHASE_STOPPED;
2467 data2.was_called = FALSE;
2469 /* it's possible to have multiple notifications using different service handles */
2470 dr = pNotifyServiceStatusChangeW(svc2, SERVICE_NOTIFY_STOPPED, &data2.notify);
2471 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr);
2473 /* stop service and receive notifiction */
2474 br = ControlService(svc, SERVICE_CONTROL_STOP, &status);
2475 ok(br, "ControlService failed: %u\n", GetLastError());
2477 dr = SleepEx(100, TRUE);
2478 dr2 = SleepEx(100, TRUE);
2479 ok(dr == WAIT_IO_COMPLETION || dr2 == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2480 ok(data.was_called == TRUE, "APC wasn't called\n");
2481 ok(data2.was_called == TRUE, "APC wasn't called\n");
2483 /* test cancelation: create notify on svc that will block until service
2484 * start; close svc; start service on svc2; verify that notification does
2485 * not happen */
2487 data.phase = PHASE_RUNNING;
2488 data.was_called = FALSE;
2489 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2490 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2492 CloseServiceHandle(svc);
2494 br = StartServiceA(svc2, 0, NULL);
2495 ok(br, "StartService failed: %u\n", GetLastError());
2497 dr = SleepEx(100, TRUE);
2498 ok(dr == 0, "Got wrong SleepEx result: %u\n", dr);
2499 ok(data.was_called == FALSE, "APC should not have been called\n");
2501 br = ControlService(svc2, SERVICE_CONTROL_STOP, &status);
2502 ok(br, "ControlService failed: %u\n", GetLastError());
2504 CloseServiceHandle(svc2);
2507 static void test_start_stop(void)
2509 BOOL ret;
2510 SC_HANDLE scm_handle, svc_handle;
2511 DWORD le, is_nt4;
2512 static const char servicename[] = "winetest_start_stop";
2513 char cmd[MAX_PATH+20];
2514 const char* displayname;
2516 SetLastError(0xdeadbeef);
2517 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2518 if (!scm_handle)
2520 if(GetLastError() == ERROR_ACCESS_DENIED)
2521 skip("Not enough rights to get a handle to the manager\n");
2522 else
2523 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
2524 return;
2527 /* Detect NT4 */
2528 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2529 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2531 /* Do some cleanup in case a previous run crashed */
2532 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2533 if (svc_handle)
2535 DeleteService(svc_handle);
2536 CloseServiceHandle(svc_handle);
2539 /* Create a dummy disabled service */
2540 sprintf(cmd, "\"%s\" service exit", selfname);
2541 displayname = "Winetest Disabled Service";
2542 svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2543 GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,
2544 SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL,
2545 NULL, NULL, NULL, NULL);
2546 if (!svc_handle)
2548 if(GetLastError() == ERROR_ACCESS_DENIED)
2549 skip("Not enough rights to create the service\n");
2550 else
2551 ok(FALSE, "Could not create the service: %d\n", GetLastError());
2552 goto cleanup;
2554 le = try_start_stop(svc_handle, displayname, is_nt4);
2555 ok(le == ERROR_SERVICE_DISABLED, "%d != ERROR_SERVICE_DISABLED\n", le);
2557 /* Then one with a bad path */
2558 displayname = "Winetest Bad Path";
2559 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2560 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2561 try_start_stop(svc_handle, displayname, is_nt4);
2563 if (is_nt4)
2565 /* NT4 does not detect when a service fails to start and uses an
2566 * insanely long timeout: 120s. So skip the rest of the tests.
2568 win_skip("Skip some service start/stop tests on NT4\n");
2569 goto cleanup;
2572 /* Again with a process that exits right away */
2573 displayname = "Winetest Exit Service";
2574 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2575 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2576 le = try_start_stop(svc_handle, displayname, is_nt4);
2577 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2579 /* create a real service and test notifications */
2580 sprintf(cmd, "%s service serve", selfname);
2581 displayname = "Winetest Service";
2582 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2583 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2584 test_servicenotify(scm_handle, servicename);
2586 cleanup:
2587 if (svc_handle)
2589 DeleteService(svc_handle);
2590 CloseServiceHandle(svc_handle);
2592 CloseServiceHandle(scm_handle);
2595 static void test_refcount(void)
2597 SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2598 static const CHAR servicename [] = "winetest_refcount";
2599 static const CHAR pathname [] = "we_dont_care.exe";
2600 BOOL ret;
2602 /* Get a handle to the Service Control Manager */
2603 SetLastError(0xdeadbeef);
2604 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2605 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2607 skip("Not enough rights to get a handle to the manager\n");
2608 return;
2611 /* Create a service */
2612 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2613 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2614 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2615 ok(svc_handle1 != NULL, "Expected success, got error %u\n", GetLastError());
2617 /* Get a handle to this new service */
2618 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2619 ok(svc_handle2 != NULL, "Expected success, got error %u\n", GetLastError());
2621 /* Get another handle to this new service */
2622 svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2623 ok(svc_handle3 != NULL, "Expected success, got error %u\n", GetLastError());
2625 /* Check if we can close the handle to the Service Control Manager */
2626 ret = CloseServiceHandle(scm_handle);
2627 ok(ret, "Expected success (err=%d)\n", GetLastError());
2629 /* Get a new handle to the Service Control Manager */
2630 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2631 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
2633 /* Get a handle to this new service */
2634 svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2635 ok(svc_handle4 != NULL, "Expected success, got error %u\n", GetLastError());
2637 /* Delete the service */
2638 ret = DeleteService(svc_handle4);
2639 ok(ret, "Expected success (err=%d)\n", GetLastError());
2641 /* We cannot create the same service again as it's still marked as 'being deleted'.
2642 * The reason is that we still have 4 open handles to this service even though we
2643 * closed the handle to the Service Control Manager in between.
2645 SetLastError(0xdeadbeef);
2646 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2647 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2648 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2649 ok(!svc_handle5, "Expected failure\n");
2650 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
2651 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2653 /* Close all the handles to the service and try again */
2654 ret = CloseServiceHandle(svc_handle4);
2655 ok(ret, "Expected success (err=%d)\n", GetLastError());
2656 ret = CloseServiceHandle(svc_handle3);
2657 ok(ret, "Expected success (err=%d)\n", GetLastError());
2658 ret = CloseServiceHandle(svc_handle2);
2659 ok(ret, "Expected success (err=%d)\n", GetLastError());
2660 ret = CloseServiceHandle(svc_handle1);
2661 ok(ret, "Expected success (err=%d)\n", GetLastError());
2663 /* Wait a while. Doing a CreateService too soon will result again
2664 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2666 Sleep(1000);
2668 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2669 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2670 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2671 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2672 ok(svc_handle5 != NULL, "Expected success, got error %u\n", GetLastError());
2674 /* Delete the service */
2675 ret = DeleteService(svc_handle5);
2676 ok(ret, "Expected success (err=%d)\n", GetLastError());
2677 CloseServiceHandle(svc_handle5);
2678 CloseServiceHandle(scm_handle);
2681 static BOOL is_lang_english(void)
2683 static HMODULE hkernel32 = NULL;
2684 static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
2685 static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
2687 if (!hkernel32)
2689 hkernel32 = GetModuleHandleA("kernel32.dll");
2690 pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
2691 pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
2693 if (pGetThreadUILanguage)
2694 return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
2695 if (pGetUserDefaultUILanguage)
2696 return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
2698 return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
2701 static void test_EventLog(void)
2703 SC_HANDLE scm_handle, svc_handle;
2704 DWORD size;
2705 BOOL ret;
2706 QUERY_SERVICE_CONFIGA *config;
2707 SERVICE_STATUS_PROCESS status;
2709 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_READ);
2710 ok(scm_handle != NULL, "OpenSCManager error %u\n", GetLastError());
2712 svc_handle = OpenServiceA(scm_handle, "EventLog", GENERIC_READ);
2713 ok(svc_handle != NULL, "OpenService error %u\n", GetLastError());
2715 SetLastError(0xdeadbeef);
2716 ret = QueryServiceConfigA(svc_handle, NULL, 0, &size);
2717 ok(!ret, "QueryServiceConfig should fail\n");
2718 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2720 config = HeapAlloc(GetProcessHeap(), 0, size);
2721 ret = QueryServiceConfigA(svc_handle, config, size, &size);
2722 ok(ret, "QueryServiceConfig error %u\n", GetLastError());
2724 ok(config->dwServiceType == SERVICE_WIN32_SHARE_PROCESS, "got %#x\n", config->dwServiceType);
2725 ok(config->dwStartType == SERVICE_AUTO_START, "got %u\n", config->dwStartType);
2726 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "got %u\n", config->dwErrorControl);
2727 ok(!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\services.exe") /* XP */ ||
2728 !strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted") /* Vista+ */ ||
2729 !strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -p") /* Win10 */,
2730 "got %s\n", config->lpBinaryPathName);
2731 todo_wine
2732 ok(!strcmpi(config->lpLoadOrderGroup, "Event Log"), "got %s\n", config->lpLoadOrderGroup);
2733 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
2734 ok(!config->lpDependencies[0], "lpDependencies is not empty\n");
2735 ok(!strcmp(config->lpServiceStartName, "LocalSystem") /* XP */ ||
2736 !strcmp(config->lpServiceStartName, "NT AUTHORITY\\LocalService"),
2737 "got %s\n", config->lpServiceStartName);
2738 ok(!is_lang_english() || /* DisplayName is often translated */
2739 !strcmp(config->lpDisplayName, "Event Log") /* XP */ ||
2740 !strcmp(config->lpDisplayName, "Windows Event Log") /* Vista+ */, "got %s\n", config->lpDisplayName);
2742 HeapFree(GetProcessHeap(), 0, config);
2744 memset(&status, 0, sizeof(status));
2745 size = sizeof(status);
2746 ret = QueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status, size, &size);
2747 ok(ret, "QueryServiceStatusEx error %u\n", GetLastError());
2748 ok(status.dwServiceType == SERVICE_WIN32_SHARE_PROCESS ||
2749 status.dwServiceType == (SERVICE_WIN32_SHARE_PROCESS | SERVICE_WIN32_OWN_PROCESS) /* Win10 */,
2750 "got %#x\n", status.dwServiceType);
2751 ok(status.dwCurrentState == SERVICE_RUNNING, "got %#x\n", status.dwCurrentState);
2752 todo_wine
2753 ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ ||
2754 status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ ||
2755 status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_TIMECHANGE | SERVICE_ACCEPT_SHUTDOWN),
2756 "got %#x\n", status.dwControlsAccepted);
2757 ok(status.dwWin32ExitCode == 0, "got %#x\n", status.dwWin32ExitCode);
2758 ok(status.dwServiceSpecificExitCode == 0, "got %#x\n", status.dwServiceSpecificExitCode);
2759 ok(status.dwCheckPoint == 0, "got %#x\n", status.dwCheckPoint);
2760 ok(status.dwWaitHint == 0, "got %#x\n", status.dwWaitHint);
2761 ok(status.dwProcessId != 0, "got %#x\n", status.dwProcessId);
2762 ok(status.dwServiceFlags == 0 || status.dwServiceFlags == SERVICE_RUNS_IN_SYSTEM_PROCESS /* XP */,
2763 "got %#x\n", status.dwServiceFlags);
2765 CloseServiceHandle(svc_handle);
2766 CloseServiceHandle(scm_handle);
2769 static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
2771 HANDLE evt = user;
2773 switch(ctl){
2774 case SERVICE_CONTROL_STOP:
2775 SetEvent(evt);
2776 break;
2777 case SERVICE_CONTROL_INTERROGATE:
2778 return NO_ERROR;
2781 return ERROR_CALL_NOT_IMPLEMENTED;
2784 static void WINAPI service_main(DWORD argc, char **argv)
2786 SERVICE_STATUS_HANDLE st_handle;
2787 SERVICE_STATUS st;
2788 HANDLE evt = CreateEventW(0, FALSE, FALSE, 0);
2790 st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt);
2792 st.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2793 st.dwServiceSpecificExitCode = 0;
2794 st.dwCurrentState = SERVICE_RUNNING;
2795 st.dwWin32ExitCode = NO_ERROR;
2796 st.dwWaitHint = 0;
2797 st.dwControlsAccepted = SERVICE_ACCEPT_STOP;
2798 st.dwCheckPoint = 0;
2800 SetServiceStatus(st_handle, &st);
2802 WaitForSingleObject(evt, 5000);
2804 st.dwCurrentState = SERVICE_STOPPED;
2806 SetServiceStatus(st_handle, &st);
2809 static void run_service(void)
2811 char empty[] = {0};
2812 SERVICE_TABLE_ENTRYA table[] = {
2813 {empty, &service_main },
2814 {0, 0}
2817 StartServiceCtrlDispatcherA(table);
2820 START_TEST(service)
2822 SC_HANDLE scm_handle;
2823 int myARGC;
2824 char** myARGV;
2826 myARGC = winetest_get_mainargs(&myARGV);
2827 GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL);
2828 if (myARGC >= 3)
2830 if (strcmp(myARGV[2], "serve") == 0)
2831 run_service();
2832 return;
2835 /* Bail out if we are on win98 */
2836 SetLastError(0xdeadbeef);
2837 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2839 if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2841 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2842 return;
2844 CloseServiceHandle(scm_handle);
2846 init_function_pointers();
2848 /* First some parameter checking */
2849 test_open_scm();
2850 test_open_svc();
2851 test_create_delete_svc();
2852 test_get_displayname();
2853 test_get_servicekeyname();
2854 test_query_svc();
2855 test_enum_svc();
2856 test_close();
2857 test_wow64();
2858 /* Test the creation, querying and deletion of a service */
2859 test_sequence();
2860 test_queryconfig2();
2861 test_start_stop();
2862 /* The main reason for this test is to check if any refcounting is used
2863 * and what the rules are
2865 test_refcount();
2866 test_EventLog();