advapi32/tests: Mark a test result on Windows 2000 as broken.
[wine/wine-gecko.git] / dlls / advapi32 / tests / service.c
blob9b6c1cfc5ac6203cb547c0c58dac4b089da86d1e
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 *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
39 static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
40 DWORD, LPBYTE, DWORD, LPDWORD,
41 LPDWORD, LPDWORD, LPCSTR);
42 static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
43 DWORD, LPBYTE, DWORD, LPDWORD,
44 LPDWORD, LPDWORD, LPCWSTR);
45 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
46 PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
47 static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
48 static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
49 static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
50 DWORD, LPDWORD);
51 static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
52 PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
54 static void init_function_pointers(void)
56 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
58 pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
59 pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
60 pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
61 pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo");
62 pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
63 pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
64 pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
65 pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
68 static void test_open_scm(void)
70 SC_HANDLE scm_handle;
72 /* No access rights */
73 SetLastError(0xdeadbeef);
74 scm_handle = OpenSCManagerA(NULL, NULL, 0);
75 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
76 CloseServiceHandle(scm_handle);
78 /* Unknown database name */
79 SetLastError(0xdeadbeef);
80 scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
81 ok(!scm_handle, "Expected failure\n");
82 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
83 CloseServiceHandle(scm_handle); /* Just in case */
85 /* MSDN says only ServiceActive is allowed, or NULL */
86 SetLastError(0xdeadbeef);
87 scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
88 ok(!scm_handle, "Expected failure\n");
89 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
90 CloseServiceHandle(scm_handle); /* Just in case */
92 /* Remote unknown host */
93 SetLastError(0xdeadbeef);
94 scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
95 todo_wine
97 ok(!scm_handle, "Expected failure\n");
98 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */,
99 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
101 CloseServiceHandle(scm_handle); /* Just in case */
103 /* Proper call with an empty hostname */
104 scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
105 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
106 CloseServiceHandle(scm_handle);
108 /* Again a correct one */
109 SetLastError(0xdeadbeef);
110 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
111 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_IO_PENDING) /* win2k */,
112 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
113 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
114 CloseServiceHandle(scm_handle);
117 static void test_open_svc(void)
119 SC_HANDLE scm_handle, svc_handle;
120 CHAR displayname[4096];
121 DWORD displaysize;
123 /* All NULL (invalid access rights) */
124 SetLastError(0xdeadbeef);
125 svc_handle = OpenServiceA(NULL, NULL, 0);
126 ok(!svc_handle, "Expected failure\n");
127 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
129 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
131 /* NULL service */
132 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
133 SetLastError(0xdeadbeef);
134 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
135 ok(!svc_handle, "Expected failure\n");
136 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
137 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
138 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
140 /* Nonexistent service */
141 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
142 SetLastError(0xdeadbeef);
143 svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
144 ok(!svc_handle, "Expected failure\n");
145 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
146 CloseServiceHandle(scm_handle);
148 /* Proper SCM handle but different access rights */
149 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
150 SetLastError(0xdeadbeef);
151 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_WRITE);
152 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
153 skip("Not enough rights to get a handle to the service\n");
154 else
156 ok(svc_handle != NULL, "Expected success, got error %u\n", GetLastError());
157 CloseServiceHandle(svc_handle);
160 /* Test to show we can't open a service with the displayname */
162 /* Retrieve the needed size for the buffer */
163 displaysize = 0;
164 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
165 /* Get the displayname */
166 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
167 /* Try to open the service with this displayname, unless the displayname equals
168 * the servicename as that would defeat the purpose of this test.
170 if (!lstrcmpiA(spooler, displayname))
172 skip("displayname equals servicename\n");
173 CloseServiceHandle(scm_handle);
174 return;
177 SetLastError(0xdeadbeef);
178 svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
179 ok(!svc_handle, "Expected failure\n");
180 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
181 /* Just in case */
182 CloseServiceHandle(svc_handle);
184 CloseServiceHandle(scm_handle);
187 static void test_create_delete_svc(void)
189 SC_HANDLE scm_handle, svc_handle1;
190 CHAR username[UNLEN + 1], domain[MAX_PATH];
191 DWORD user_size = UNLEN + 1;
192 CHAR account[UNLEN + 3];
193 static const CHAR servicename [] = "Winetest";
194 static const CHAR pathname [] = "we_dont_care.exe";
195 static const CHAR empty [] = "";
196 static const CHAR password [] = "secret";
197 BOOL spooler_exists = FALSE;
198 BOOL ret;
199 CHAR display[4096];
200 DWORD display_size = sizeof(display);
202 /* Get the username and turn it into an account to be used in some tests */
203 GetUserNameA(username, &user_size);
204 /* Get the domainname to cater for that situation */
205 if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH))
206 sprintf(account, "%s\\%s", domain, username);
207 else
208 sprintf(account, ".\\%s", username);
210 /* All NULL */
211 SetLastError(0xdeadbeef);
212 svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
213 ok(!svc_handle1, "Expected failure\n");
214 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
216 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
218 /* Only a valid handle to the Service Control Manager */
219 SetLastError(0xdeadbeef);
220 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
221 ok(!svc_handle1, "Expected failure\n");
222 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
223 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
224 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
226 /* Now with a servicename */
227 SetLastError(0xdeadbeef);
228 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
229 ok(!svc_handle1, "Expected failure\n");
230 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
231 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
232 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
234 /* Or just a binary name */
235 SetLastError(0xdeadbeef);
236 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
237 ok(!svc_handle1, "Expected failure\n");
238 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
239 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
240 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
242 /* Both servicename and binary name (We only have connect rights) */
243 SetLastError(0xdeadbeef);
244 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
245 ok(!svc_handle1, "Expected failure\n");
246 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
248 /* They can even be empty at this stage of parameter checking */
249 SetLastError(0xdeadbeef);
250 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
251 ok(!svc_handle1, "Expected failure\n");
252 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
254 SetLastError(0xdeadbeef);
255 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, 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 /* Open the Service Control Manager with minimal rights for creation
260 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
262 CloseServiceHandle(scm_handle);
263 SetLastError(0xdeadbeef);
264 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
265 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
267 skip("Not enough rights to get a handle to the manager\n");
268 return;
271 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
273 /* Empty strings for servicename and binary name are checked */
274 SetLastError(0xdeadbeef);
275 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
276 ok(!svc_handle1, "Expected failure\n");
277 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
279 SetLastError(0xdeadbeef);
280 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
281 ok(!svc_handle1, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
286 ok(!svc_handle1, "Expected failure\n");
287 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
289 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
290 * an ERROR_INVALID_PARAMETER)
292 SetLastError(0xdeadbeef);
293 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
294 SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
295 ok(!svc_handle1, "Expected failure\n");
296 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
298 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
300 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
301 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
303 SetLastError(0xdeadbeef);
304 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
305 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
306 ok(!svc_handle1, "Expected failure\n");
307 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
309 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
310 SetLastError(0xdeadbeef);
311 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
312 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
313 ok(!svc_handle1, "Expected failure\n");
314 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
316 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
317 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
319 SetLastError(0xdeadbeef);
320 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
321 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
322 ok(!svc_handle1, "Expected failure\n");
323 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT,
324 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
326 /* Illegal (start-type is not a mask and should only be one of the possibilities)
327 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
328 * it's most likely not the wanted start-type)
330 SetLastError(0xdeadbeef);
331 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
332 SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
333 ok(!svc_handle1, "Expected failure\n");
334 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
336 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
337 SetLastError(0xdeadbeef);
338 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
339 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
340 ok(!svc_handle1, "Expected failure\n");
341 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
343 /* Test if ServiceType can be a combined one for drivers */
344 SetLastError(0xdeadbeef);
345 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER,
346 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
347 ok(!svc_handle1, "Expected failure\n");
348 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
350 /* The service already exists (check first, just in case) */
351 svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ);
352 if (svc_handle1)
354 spooler_exists = TRUE;
355 CloseServiceHandle(svc_handle1);
356 SetLastError(0xdeadbeef);
357 svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
358 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
359 ok(!svc_handle1, "Expected failure\n");
360 ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
362 else
363 skip("Spooler service doesn't exist\n");
365 /* To find an existing displayname we check the 'Spooler' service. Although the registry
366 * doesn't show DisplayName on NT4, this call will return a displayname which is equal
367 * to the servicename and can't be used as well for a new displayname.
369 if (spooler_exists)
371 ret = GetServiceDisplayNameA(scm_handle, spooler, display, &display_size);
373 if (!ret)
374 skip("Could not retrieve a displayname for the Spooler service\n");
375 else
377 svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS,
378 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
379 ok(!svc_handle1, "Expected failure\n");
380 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME,
381 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
384 else
385 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
387 /* Windows doesn't care about the access rights for creation (which makes
388 * sense as there is no service yet) as long as there are sufficient
389 * rights to the manager.
391 SetLastError(0xdeadbeef);
392 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
393 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
394 ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError());
396 /* DeleteService however must have proper rights */
397 SetLastError(0xdeadbeef);
398 ret = DeleteService(svc_handle1);
399 ok(!ret, "Expected failure\n");
400 ok(GetLastError() == ERROR_ACCESS_DENIED,
401 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
403 /* Open the service with minimal rights for deletion.
404 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
406 CloseServiceHandle(svc_handle1);
407 svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
409 /* Now that we have the proper rights, we should be able to delete */
410 SetLastError(0xdeadbeef);
411 ret = DeleteService(svc_handle1);
412 ok(ret, "Expected success, got error %u\n", GetLastError());
414 CloseServiceHandle(svc_handle1);
415 CloseServiceHandle(scm_handle);
417 /* Wait a while. One of the following tests also does a CreateService for the
418 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
419 * error if we do this too quickly. Vista seems more picky than the others.
421 Sleep(1000);
423 /* And a final NULL check */
424 SetLastError(0xdeadbeef);
425 ret = DeleteService(NULL);
426 ok(!ret, "Expected failure\n");
427 ok(GetLastError() == ERROR_INVALID_HANDLE,
428 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
431 static void test_get_displayname(void)
433 SC_HANDLE scm_handle, svc_handle;
434 BOOL ret;
435 CHAR displayname[4096];
436 WCHAR displaynameW[2048];
437 DWORD displaysize, tempsize, tempsizeW;
438 static const CHAR deadbeef[] = "Deadbeef";
439 static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
440 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
441 static const WCHAR abcW[] = {'A','B','C',0};
442 static const CHAR servicename[] = "Winetest";
443 static const CHAR pathname[] = "we_dont_care.exe";
445 /* Having NULL for the size of the buffer will crash on W2K3 */
447 SetLastError(0xdeadbeef);
448 ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
449 ok(!ret, "Expected failure\n");
450 ok(GetLastError() == ERROR_INVALID_HANDLE,
451 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
453 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
455 SetLastError(0xdeadbeef);
456 ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
457 ok(!ret, "Expected failure\n");
458 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
459 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
460 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
462 SetLastError(0xdeadbeef);
463 displaysize = sizeof(displayname);
464 ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
465 ok(!ret, "Expected failure\n");
466 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
467 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
468 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
470 /* Test for nonexistent service */
471 SetLastError(0xdeadbeef);
472 displaysize = -1;
473 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
474 ok(!ret, "Expected failure\n");
475 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
476 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
478 SetLastError(0xdeadbeef);
479 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
480 ok(!ret, "Expected failure\n");
481 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
482 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
483 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
485 displaysize = 15;
486 strcpy(displayname, "ABC");
487 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
488 ok(!ret, "Expected failure\n");
489 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
490 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
491 todo_wine ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
492 ok(displayname[0] == 0, "Service name not empty\n");
494 displaysize = 15;
495 lstrcpyW( displaynameW, abcW );
496 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
497 ok(!ret, "Expected failure\n");
498 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
499 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
500 ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
501 ok(displaynameW[0] == 0, "Service name not empty\n");
503 displaysize = 0;
504 strcpy(displayname, "ABC");
505 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
506 ok(!ret, "Expected failure\n");
507 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
508 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
509 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
510 ok(displayname[0] == 'A', "Service name changed\n");
512 displaysize = 0;
513 lstrcpyW( displaynameW, abcW );
514 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
515 ok(!ret, "Expected failure\n");
516 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
517 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
518 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
519 ok(displaynameW[0] == 'A', "Service name changed\n");
521 displaysize = 1;
522 strcpy(displayname, "ABC");
523 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
524 ok(!ret, "Expected failure\n");
525 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
526 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
527 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
528 ok(displayname[0] == 0, "Service name not empty\n");
530 displaysize = 1;
531 lstrcpyW( displaynameW, abcW );
532 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
533 ok(!ret, "Expected failure\n");
534 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
535 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
536 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
537 ok(displaynameW[0] == 'A', "Service name changed\n");
539 displaysize = 2;
540 strcpy(displayname, "ABC");
541 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
542 ok(!ret, "Expected failure\n");
543 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
544 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
545 todo_wine ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
546 ok(displayname[0] == 0, "Service name not empty\n");
548 displaysize = 2;
549 lstrcpyW( displaynameW, abcW );
550 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
551 ok(!ret, "Expected failure\n");
552 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
553 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
554 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
555 ok(displaynameW[0] == 0, "Service name not empty\n");
557 /* Check if 'Spooler' exists */
558 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
559 if (!svc_handle)
561 skip("Spooler service doesn't exist\n");
562 CloseServiceHandle(scm_handle);
563 return;
565 CloseServiceHandle(svc_handle);
567 /* Retrieve the needed size for the buffer */
568 SetLastError(0xdeadbeef);
569 displaysize = -1;
570 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
571 ok(!ret, "Expected failure\n");
572 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
573 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
574 tempsize = displaysize;
576 displaysize = 0;
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 ok(displaysize == tempsize, "Buffer size mismatch (%d vs %d)\n", tempsize, displaysize);
583 /* Buffer is too small */
584 SetLastError(0xdeadbeef);
585 displaysize = (tempsize / 2);
586 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
587 ok(!ret, "Expected failure\n");
588 ok(displaysize == tempsize, "Expected the needed buffersize\n");
589 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
590 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
592 /* First try with a buffer that should be big enough to hold
593 * the ANSI string (and terminating character). This succeeds on Windows
594 * although when asked (see above 2 tests) it will return twice the needed size.
596 SetLastError(0xdeadbeef);
597 displaysize = (tempsize / 2) + 1;
598 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
599 ok(ret, "Expected success, got error %u\n", GetLastError());
600 ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
602 /* Now with the original returned size */
603 SetLastError(0xdeadbeef);
604 displaysize = tempsize;
605 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
606 ok(ret, "Expected success, got error %u\n", GetLastError());
607 ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
609 /* And with a bigger than needed buffer */
610 SetLastError(0xdeadbeef);
611 displaysize = tempsize * 2;
612 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
613 ok(ret, "Expected success, got error %u\n", GetLastError());
614 /* Test that shows that if the buffersize is enough, it's not changed */
615 ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
616 ok(strlen(displayname) == tempsize/2,
617 "Expected the buffer to be twice the length of the string\n") ;
619 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
620 SetLastError(0xdeadbeef);
621 displaysize = -1;
622 ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
623 ok(!ret, "Expected failure\n");
624 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
625 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
627 /* Buffer is too small */
628 SetLastError(0xdeadbeef);
629 tempsizeW = displaysize;
630 displaysize = tempsizeW / 2;
631 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
632 ok(!ret, "Expected failure\n");
633 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
634 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
635 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
637 /* Now with the original returned size */
638 SetLastError(0xdeadbeef);
639 displaysize = tempsizeW;
640 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
641 ok(!ret, "Expected failure\n");
642 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
643 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
644 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
646 /* And with a bigger than needed buffer */
647 SetLastError(0xdeadbeef);
648 displaysize = tempsizeW + 1; /* This caters for the null terminating character */
649 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
650 ok(ret, "Expected success, got error %u\n", GetLastError());
651 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
652 ok(lstrlenW(displaynameW) == displaysize,
653 "Expected the buffer to be the length of the string\n") ;
654 ok(tempsize / 2 == tempsizeW,
655 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
657 CloseServiceHandle(scm_handle);
659 /* Test for a service without a displayname (which is valid). This should return
660 * the servicename itself.
662 SetLastError(0xdeadbeef);
663 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
664 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
666 skip("Not enough rights to get a handle to the manager\n");
667 return;
670 SetLastError(0xdeadbeef);
671 svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
672 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
673 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
674 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
675 if (!svc_handle)
677 CloseServiceHandle(scm_handle);
678 return;
681 /* Retrieve the needed size for the buffer */
682 SetLastError(0xdeadbeef);
683 displaysize = -1;
684 ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
685 ok(!ret, "Expected failure\n");
686 ok(displaysize == strlen(servicename) * 2,
687 "Expected the displaysize to be twice the size of the servicename\n");
688 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
689 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
691 /* Buffer is too small */
692 SetLastError(0xdeadbeef);
693 tempsize = displaysize;
694 displaysize = (tempsize / 2);
695 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
696 ok(!ret, "Expected failure\n");
697 ok(displaysize == tempsize, "Expected the needed buffersize\n");
698 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
699 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
701 /* Get the displayname */
702 SetLastError(0xdeadbeef);
703 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
704 ok(ret, "Expected success, got error %u\n", GetLastError());
705 ok(!lstrcmpiA(displayname, servicename),
706 "Expected displayname to be %s, got %s\n", servicename, displayname);
708 /* Delete the service */
709 ret = DeleteService(svc_handle);
710 ok(ret, "Expected success (err=%d)\n", GetLastError());
712 CloseServiceHandle(svc_handle);
713 CloseServiceHandle(scm_handle);
715 /* Wait a while. Just in case one of the following tests does a CreateService again */
716 Sleep(1000);
719 static void test_get_servicekeyname(void)
721 SC_HANDLE scm_handle, svc_handle;
722 CHAR servicename[4096];
723 CHAR displayname[4096];
724 WCHAR servicenameW[4096];
725 WCHAR displaynameW[4096];
726 DWORD servicesize, displaysize, tempsize;
727 BOOL ret;
728 static const CHAR deadbeef[] = "Deadbeef";
729 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
730 static const WCHAR abcW[] = {'A','B','C',0};
732 /* Having NULL for the size of the buffer will crash on W2K3 */
734 SetLastError(0xdeadbeef);
735 ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
736 ok(!ret, "Expected failure\n");
737 ok(GetLastError() == ERROR_INVALID_HANDLE,
738 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
740 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
742 servicesize = 200;
743 SetLastError(0xdeadbeef);
744 ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
745 ok(!ret, "Expected failure\n");
746 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
747 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
748 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
749 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
751 /* Valid handle and buffer but no displayname */
752 servicesize = 200;
753 SetLastError(0xdeadbeef);
754 ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
755 ok(!ret, "Expected failure\n");
756 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
757 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
758 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
759 todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize);
761 /* Test for nonexistent displayname */
762 SetLastError(0xdeadbeef);
763 ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
764 ok(!ret, "Expected failure\n");
765 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
766 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
767 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
769 servicesize = 15;
770 strcpy(servicename, "ABC");
771 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
772 ok(!ret, "Expected failure\n");
773 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
774 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
775 todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
776 ok(servicename[0] == 0, "Service name not empty\n");
778 servicesize = 15;
779 lstrcpyW( servicenameW, abcW );
780 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
781 ok(!ret, "Expected failure\n");
782 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
783 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
784 ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
785 ok(servicenameW[0] == 0, "Service name not empty\n");
787 servicesize = 0;
788 strcpy(servicename, "ABC");
789 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
790 ok(!ret, "Expected failure\n");
791 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
792 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
793 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
794 ok(servicename[0] == 'A', "Service name changed\n");
796 servicesize = 0;
797 lstrcpyW( servicenameW, abcW );
798 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
799 ok(!ret, "Expected failure\n");
800 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
801 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
802 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
803 ok(servicenameW[0] == 'A', "Service name changed\n");
805 servicesize = 1;
806 strcpy(servicename, "ABC");
807 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
808 ok(!ret, "Expected failure\n");
809 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
810 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
811 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
812 ok(servicename[0] == 0, "Service name not empty\n");
814 servicesize = 1;
815 lstrcpyW( servicenameW, abcW );
816 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
817 ok(!ret, "Expected failure\n");
818 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
819 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
820 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
821 ok(servicenameW[0] == 'A', "Service name changed\n");
823 servicesize = 2;
824 strcpy(servicename, "ABC");
825 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
826 ok(!ret, "Expected failure\n");
827 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
828 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
829 todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
830 ok(servicename[0] == 0, "Service name not empty\n");
832 servicesize = 2;
833 lstrcpyW( servicenameW, abcW );
834 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
835 ok(!ret, "Expected failure\n");
836 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
837 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
838 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
839 ok(servicenameW[0] == 0, "Service name not empty\n");
841 /* Check if 'Spooler' exists */
842 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
843 if (!svc_handle)
845 skip("Spooler service doesn't exist\n");
846 CloseServiceHandle(scm_handle);
847 return;
849 CloseServiceHandle(svc_handle);
851 /* Get the displayname for the 'Spooler' service */
852 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
853 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
855 /* Retrieve the needed size for the buffer */
856 SetLastError(0xdeadbeef);
857 servicesize = 0;
858 ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
859 ok(!ret, "Expected failure\n");
860 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
861 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
863 /* Valid call with the correct buffersize */
864 SetLastError(0xdeadbeef);
865 tempsize = servicesize;
866 servicesize *= 2;
867 ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
868 ok(ret, "Expected success, got error %u\n", GetLastError());
869 if (ret)
871 ok(strlen(servicename) == tempsize/2,
872 "Expected the buffer to be twice the length of the string\n") ;
873 ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
874 ok(servicesize == (tempsize * 2),
875 "Expected servicesize not to change if buffer not insufficient\n") ;
878 MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
879 SetLastError(0xdeadbeef);
880 servicesize *= 2;
881 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
882 ok(ret, "Expected success, got error %u\n", GetLastError());
883 if (ret)
885 ok(strlen(servicename) == tempsize/2,
886 "Expected the buffer to be twice the length of the string\n") ;
887 ok(servicesize == lstrlenW(servicenameW),
888 "Expected servicesize not to change if buffer not insufficient\n") ;
891 SetLastError(0xdeadbeef);
892 servicesize = 3;
893 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
894 ok(!ret, "Expected failure\n");
895 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
896 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
897 ok(servicenameW[0] == 0, "Buffer not empty\n");
899 CloseServiceHandle(scm_handle);
902 static void test_query_svc(void)
904 SC_HANDLE scm_handle, svc_handle;
905 BOOL ret;
906 SERVICE_STATUS status;
907 SERVICE_STATUS_PROCESS *statusproc;
908 DWORD bufsize, needed;
910 /* All NULL or wrong */
911 SetLastError(0xdeadbeef);
912 ret = QueryServiceStatus(NULL, NULL);
913 ok(!ret, "Expected failure\n");
914 ok(GetLastError() == ERROR_INVALID_HANDLE,
915 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
917 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
919 /* Check if 'Spooler' exists.
920 * Open with not enough rights to query the status.
922 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
923 if (!svc_handle)
925 skip("Spooler service doesn't exist\n");
926 CloseServiceHandle(scm_handle);
927 return;
930 SetLastError(0xdeadbeef);
931 ret = QueryServiceStatus(svc_handle, NULL);
932 ok(!ret, "Expected failure\n");
933 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
934 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
935 "Unexpected last error %d\n", GetLastError());
937 SetLastError(0xdeadbeef);
938 ret = QueryServiceStatus(svc_handle, &status);
939 ok(!ret, "Expected failure\n");
940 ok(GetLastError() == ERROR_ACCESS_DENIED,
941 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
943 /* Open the service with just enough rights.
944 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
946 CloseServiceHandle(svc_handle);
947 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
949 SetLastError(0xdeadbeef);
950 ret = QueryServiceStatus(svc_handle, &status);
951 ok(ret, "Expected success, got error %u\n", GetLastError());
953 CloseServiceHandle(svc_handle);
955 /* More or less the same tests for QueryServiceStatusEx */
956 if (!pQueryServiceStatusEx)
958 win_skip( "QueryServiceStatusEx not available\n" );
959 CloseServiceHandle(scm_handle);
960 return;
963 /* Open service with not enough rights to query the status */
964 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
966 /* All NULL or wrong, this proves that info level is checked first */
967 SetLastError(0xdeadbeef);
968 ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
969 ok(!ret, "Expected failure\n");
970 ok(GetLastError() == ERROR_INVALID_LEVEL,
971 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
973 /* Passing a NULL parameter for the needed buffer size
974 * will crash on anything but NT4.
977 /* Only info level is correct. It looks like the buffer/size is checked second */
978 SetLastError(0xdeadbeef);
979 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
980 /* NT4 checks the handle first */
981 if (GetLastError() != ERROR_INVALID_HANDLE)
983 ok(!ret, "Expected failure\n");
984 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
985 "Needed buffersize is wrong : %d\n", needed);
986 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
987 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
990 /* Pass a correct buffer and buffersize but a NULL handle */
991 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
992 bufsize = needed;
993 SetLastError(0xdeadbeef);
994 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
995 ok(!ret, "Expected failure\n");
996 ok(GetLastError() == ERROR_INVALID_HANDLE,
997 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
998 HeapFree(GetProcessHeap(), 0, statusproc);
1000 /* Correct handle and info level */
1001 SetLastError(0xdeadbeef);
1002 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1003 /* NT4 doesn't return the needed size */
1004 if (GetLastError() != ERROR_INVALID_PARAMETER)
1006 ok(!ret, "Expected failure\n");
1007 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1008 "Needed buffersize is wrong : %d\n", needed);
1009 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1010 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1013 /* All parameters are OK but we don't have enough rights */
1014 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1015 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1016 SetLastError(0xdeadbeef);
1017 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1018 ok(!ret, "Expected failure\n");
1019 ok(GetLastError() == ERROR_ACCESS_DENIED,
1020 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1021 HeapFree(GetProcessHeap(), 0, statusproc);
1023 /* Open the service with just enough rights. */
1024 CloseServiceHandle(svc_handle);
1025 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
1027 /* Everything should be fine now. */
1028 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1029 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1030 SetLastError(0xdeadbeef);
1031 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1032 ok(ret, "Expected success, got error %u\n", GetLastError());
1033 if (statusproc->dwCurrentState == SERVICE_RUNNING)
1034 ok(statusproc->dwProcessId != 0,
1035 "Expect a process id for this running service\n");
1036 else
1037 ok(statusproc->dwProcessId == 0,
1038 "Expect no process id for this stopped service\n");
1040 /* same call with null needed pointer */
1041 SetLastError(0xdeadbeef);
1042 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1043 ok(!ret, "Expected failure\n");
1044 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ ||
1045 GetLastError() == ERROR_INVALID_ADDRESS, "got %d\n", GetLastError());
1047 HeapFree(GetProcessHeap(), 0, statusproc);
1049 CloseServiceHandle(svc_handle);
1050 CloseServiceHandle(scm_handle);
1053 static void test_enum_svc(void)
1055 SC_HANDLE scm_handle;
1056 BOOL ret;
1057 DWORD bufsize, needed, returned, resume;
1058 DWORD neededW, returnedW;
1059 DWORD tempneeded, tempreturned, missing;
1060 DWORD servicecountactive, servicecountinactive;
1061 ENUM_SERVICE_STATUSA *services;
1062 ENUM_SERVICE_STATUSW *servicesW;
1063 ENUM_SERVICE_STATUS_PROCESSA *exservices;
1064 UINT i;
1066 /* All NULL or wrong */
1067 SetLastError(0xdeadbeef);
1068 ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1069 ok(!ret, "Expected failure\n");
1070 ok(GetLastError() == ERROR_INVALID_HANDLE,
1071 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1073 SetLastError(0xdeadbeef);
1074 ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1075 ok(!ret, "Expected failure\n");
1076 ok(GetLastError() == ERROR_INVALID_HANDLE,
1077 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1079 /* Open the service control manager with not enough rights at first */
1080 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1082 /* Valid handle but rest is still NULL or wrong */
1083 SetLastError(0xdeadbeef);
1084 ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1085 ok(!ret, "Expected failure\n");
1086 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1087 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1088 "Unexpected last error %d\n", GetLastError());
1090 SetLastError(0xdeadbeef);
1091 ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1092 ok(!ret, "Expected failure\n");
1093 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1094 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1095 "Unexpected last error %d\n", GetLastError());
1097 /* Don't specify the two required pointers */
1098 returned = 0xdeadbeef;
1099 SetLastError(0xdeadbeef);
1100 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1101 ok(!ret, "Expected failure\n");
1102 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1103 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1104 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1105 "Unexpected last error %d\n", GetLastError());
1107 returned = 0xdeadbeef;
1108 SetLastError(0xdeadbeef);
1109 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1110 ok(!ret, "Expected failure\n");
1111 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1112 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1113 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1114 "Unexpected last error %d\n", GetLastError());
1116 /* Don't specify the two required pointers */
1117 needed = 0xdeadbeef;
1118 SetLastError(0xdeadbeef);
1119 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1120 ok(!ret, "Expected failure\n");
1121 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1122 "Expected no change to the needed buffer variable\n");
1123 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1124 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1125 "Unexpected last error %d\n", GetLastError());
1127 needed = 0xdeadbeef;
1128 SetLastError(0xdeadbeef);
1129 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1130 ok(!ret, "Expected failure\n");
1131 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1132 "Expected no change to the needed buffer variable\n");
1133 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1134 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1135 "Unexpected last error %d\n", GetLastError());
1137 /* No valid servicetype and servicestate */
1138 needed = 0xdeadbeef;
1139 returned = 0xdeadbeef;
1140 SetLastError(0xdeadbeef);
1141 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1142 ok(!ret, "Expected failure\n");
1143 ok(needed == 0 || broken(needed != 0), /* nt4 */
1144 "Expected needed buffer size to be set to 0, got %d\n", needed);
1145 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1146 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1147 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1149 needed = 0xdeadbeef;
1150 returned = 0xdeadbeef;
1151 SetLastError(0xdeadbeef);
1152 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1153 ok(!ret, "Expected failure\n");
1154 ok(needed == 0 || broken(needed != 0), /* nt4 */
1155 "Expected needed buffer size to be set to 0, got %d\n", needed);
1156 ok(returned == 0 || broken(returned != 0), /* nt4 */
1157 "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 /* No valid servicestate */
1162 needed = 0xdeadbeef;
1163 returned = 0xdeadbeef;
1164 SetLastError(0xdeadbeef);
1165 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1166 ok(!ret, "Expected failure\n");
1167 ok(needed == 0 || broken(needed != 0), /* nt4 */
1168 "Expected needed buffer size to be set to 0, got %d\n", needed);
1169 ok(returned == 0, "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 needed = 0xdeadbeef;
1174 returned = 0xdeadbeef;
1175 SetLastError(0xdeadbeef);
1176 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1177 ok(!ret, "Expected failure\n");
1178 ok(needed == 0 || broken(needed != 0), /* nt4 */
1179 "Expected needed buffer size to be set to 0, got %d\n", needed);
1180 ok(returned == 0 || broken(returned != 0), /* nt4 */
1181 "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 /* No valid servicetype */
1186 needed = 0xdeadbeef;
1187 returned = 0xdeadbeef;
1188 SetLastError(0xdeadbeef);
1189 ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1190 ok(!ret, "Expected failure\n");
1191 ok(needed == 0 || broken(needed != 0), /* nt4 */
1192 "Expected needed buffer size to be set to 0, got %d\n", needed);
1193 ok(returned == 0, "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 needed = 0xdeadbeef;
1198 returned = 0xdeadbeef;
1199 SetLastError(0xdeadbeef);
1200 ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1201 ok(!ret, "Expected failure\n");
1202 ok(needed == 0 || broken(needed != 0), /* nt4 */
1203 "Expected needed buffer size to be set to 0, got %d\n", needed);
1204 ok(returned == 0 || broken(returned != 0), /* nt4 */
1205 "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 /* All parameters are correct but our access rights are wrong */
1210 needed = 0xdeadbeef;
1211 returned = 0xdeadbeef;
1212 SetLastError(0xdeadbeef);
1213 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1214 ok(!ret, "Expected failure\n");
1215 ok(needed == 0 || broken(needed != 0), /* nt4 */
1216 "Expected needed buffer size to be set to 0, got %d\n", needed);
1217 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1218 ok(GetLastError() == ERROR_ACCESS_DENIED,
1219 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1221 needed = 0xdeadbeef;
1222 returned = 0xdeadbeef;
1223 SetLastError(0xdeadbeef);
1224 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1225 ok(!ret, "Expected failure\n");
1226 ok(needed == 0 || broken(needed != 0), /* nt4 */
1227 "Expected needed buffer size to be set to 0, got %d\n", needed);
1228 ok(returned == 0 || broken(returned != 0), /* nt4 */
1229 "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 /* Open the service control manager with the needed rights */
1234 CloseServiceHandle(scm_handle);
1235 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1237 /* All parameters are correct. Request the needed buffer size */
1238 needed = 0xdeadbeef;
1239 returned = 0xdeadbeef;
1240 SetLastError(0xdeadbeef);
1241 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1242 ok(!ret, "Expected failure\n");
1243 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1244 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1245 ok(GetLastError() == ERROR_MORE_DATA,
1246 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1248 /* Test to show we get the same needed buffer size for the W-call */
1249 neededW = 0xdeadbeef;
1250 returnedW = 0xdeadbeef;
1251 SetLastError(0xdeadbeef);
1252 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL);
1253 ok(!ret, "Expected failure\n");
1254 ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n");
1255 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1256 ok(returnedW == 0, "Expected no service returned, got %d\n", returnedW);
1257 ok(GetLastError() == ERROR_MORE_DATA,
1258 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1260 /* Store the needed bytes */
1261 tempneeded = needed;
1263 /* Allocate the correct needed bytes */
1264 services = HeapAlloc(GetProcessHeap(), 0, needed);
1265 bufsize = needed;
1266 needed = 0xdeadbeef;
1267 returned = 0xdeadbeef;
1268 SetLastError(0xdeadbeef);
1269 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1270 services, bufsize, &needed, &returned, NULL);
1271 ok(ret, "Expected success, got error %u\n", GetLastError());
1272 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1273 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1274 HeapFree(GetProcessHeap(), 0, services);
1276 /* Store the number of returned services */
1277 tempreturned = returned;
1279 servicesW = HeapAlloc(GetProcessHeap(), 0, neededW);
1280 bufsize = neededW;
1281 neededW = 0xdeadbeef;
1282 returnedW = 0xdeadbeef;
1283 SetLastError(0xdeadbeef);
1284 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1285 servicesW, bufsize, &neededW, &returnedW, NULL);
1286 ok(ret, "Expected success, got error %u\n", GetLastError());
1287 ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n");
1288 ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n");
1289 HeapFree(GetProcessHeap(), 0, servicesW);
1291 /* Allocate less than the needed bytes and don't specify a resume handle */
1292 services = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1293 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1294 needed = 0xdeadbeef;
1295 returned = 0xdeadbeef;
1296 SetLastError(0xdeadbeef);
1297 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1298 services, bufsize, &needed, &returned, NULL);
1299 ok(!ret, "Expected failure\n");
1300 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1301 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1302 ok(GetLastError() == ERROR_MORE_DATA,
1303 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1305 /* Allocate less than the needed bytes, this time with a correct resume handle */
1306 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1307 needed = 0xdeadbeef;
1308 returned = 0xdeadbeef;
1309 resume = 0;
1310 SetLastError(0xdeadbeef);
1311 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1312 services, bufsize, &needed, &returned, &resume);
1313 ok(!ret, "Expected failure\n");
1314 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1315 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1316 todo_wine ok(resume, "Expected a resume handle\n");
1317 ok(GetLastError() == ERROR_MORE_DATA,
1318 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1320 /* Fetch the missing services but pass a bigger buffer size */
1321 missing = tempreturned - returned;
1322 bufsize = tempneeded;
1323 needed = 0xdeadbeef;
1324 returned = 0xdeadbeef;
1325 SetLastError(0xdeadbeef);
1326 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1327 services, bufsize, &needed, &returned, &resume);
1328 ok(ret, "Expected success, got error %u\n", GetLastError());
1329 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1330 ok(returned == missing, "Expected %u services to be returned\n", missing);
1331 ok(resume == 0, "Expected the resume handle to be 0\n");
1332 HeapFree(GetProcessHeap(), 0, services);
1334 /* See if things add up */
1336 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1337 * and doesn't count the others as inactive. This means that Vista could
1338 * show a total that is greater than the sum of active and inactive
1339 * drivers.
1340 * The number of active and inactive drivers is greatly influenced by the
1341 * time when tests are run, immediately after boot or later for example.
1343 * Both reasons make calculations for drivers not so useful
1346 /* Get the number of active win32 services */
1347 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
1348 &needed, &returned, NULL);
1349 services = HeapAlloc(GetProcessHeap(), 0, needed);
1350 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services,
1351 needed, &needed, &returned, NULL);
1352 HeapFree(GetProcessHeap(), 0, services);
1354 servicecountactive = returned;
1356 /* Get the number of inactive win32 services */
1357 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
1358 &needed, &returned, NULL);
1359 services = HeapAlloc(GetProcessHeap(), 0, needed);
1360 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services,
1361 needed, &needed, &returned, NULL);
1362 HeapFree(GetProcessHeap(), 0, services);
1364 servicecountinactive = returned;
1366 /* Get the number of win32 services */
1367 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
1368 &needed, &returned, NULL);
1369 services = HeapAlloc(GetProcessHeap(), 0, needed);
1370 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services,
1371 needed, &needed, &returned, NULL);
1372 HeapFree(GetProcessHeap(), 0, services);
1374 /* Check if total is the same as active and inactive win32 services */
1375 ok(returned == (servicecountactive + servicecountinactive),
1376 "Something wrong in the calculation\n");
1378 /* Get all drivers and services
1380 * Fetch the status of the last call as failing could make the following tests crash
1381 * on Wine (we don't return anything yet).
1383 EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1384 NULL, 0, &needed, &returned, NULL);
1385 services = HeapAlloc(GetProcessHeap(), 0, needed);
1386 ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1387 services, needed, &needed, &returned, NULL);
1389 /* Loop through all those returned drivers and services */
1390 for (i = 0; ret && i < returned; i++)
1392 SERVICE_STATUS status = services[i].ServiceStatus;
1394 /* lpServiceName and lpDisplayName should always be filled */
1395 ok(lstrlenA(services[i].lpServiceName) > 0, "Expected a service name\n");
1396 ok(lstrlenA(services[i].lpDisplayName) > 0, "Expected a display name\n");
1398 /* Decrement the counters to see if the functions calls return the same
1399 * numbers as the contents of these structures.
1401 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1403 if (status.dwCurrentState == SERVICE_STOPPED)
1404 servicecountinactive--;
1405 else
1406 servicecountactive--;
1409 HeapFree(GetProcessHeap(), 0, services);
1411 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1412 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1414 CloseServiceHandle(scm_handle);
1416 /* More or less the same for EnumServicesStatusExA */
1417 if (!pEnumServicesStatusExA)
1419 win_skip( "EnumServicesStatusExA not available\n" );
1420 return;
1423 /* All NULL or wrong */
1424 SetLastError(0xdeadbeef);
1425 ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1426 ok(!ret, "Expected failure\n");
1427 ok(GetLastError() == ERROR_INVALID_LEVEL,
1428 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1430 /* All NULL or wrong, just the info level is correct */
1431 SetLastError(0xdeadbeef);
1432 ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1433 ok(!ret, "Expected failure\n");
1434 ok(GetLastError() == ERROR_INVALID_HANDLE,
1435 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1437 /* Open the service control manager with not enough rights at first */
1438 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1440 /* Valid handle and info level but rest is still NULL or wrong */
1441 SetLastError(0xdeadbeef);
1442 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1443 ok(!ret, "Expected failure\n");
1444 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1445 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1446 "Unexpected last error %d\n", GetLastError());
1448 /* Don't specify the two required pointers */
1449 needed = 0xdeadbeef;
1450 SetLastError(0xdeadbeef);
1451 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1452 ok(!ret, "Expected failure\n");
1453 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1454 "Expected no change to the needed buffer variable\n");
1455 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1456 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1457 "Unexpected last error %d\n", GetLastError());
1459 /* Don't specify the two required pointers */
1460 returned = 0xdeadbeef;
1461 SetLastError(0xdeadbeef);
1462 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1463 ok(!ret, "Expected failure\n");
1464 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1465 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1466 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1467 "Unexpected last error %d\n", GetLastError());
1469 /* No valid servicetype and servicestate */
1470 needed = 0xdeadbeef;
1471 returned = 0xdeadbeef;
1472 SetLastError(0xdeadbeef);
1473 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1474 ok(!ret, "Expected failure\n");
1475 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1476 ok(needed == 0 || broken(needed != 0), /* nt4 */
1477 "Expected needed buffer size to be set to 0, got %d\n", needed);
1478 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1479 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1481 /* No valid servicestate */
1482 needed = 0xdeadbeef;
1483 returned = 0xdeadbeef;
1484 SetLastError(0xdeadbeef);
1485 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1486 &needed, &returned, NULL, NULL);
1487 ok(!ret, "Expected failure\n");
1488 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1489 ok(needed == 0 || broken(needed != 0), /* nt4 */
1490 "Expected needed buffer size to be set to 0, got %d\n", needed);
1491 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1492 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1494 /* No valid servicetype */
1495 needed = 0xdeadbeef;
1496 returned = 0xdeadbeef;
1497 SetLastError(0xdeadbeef);
1498 ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1499 &needed, &returned, NULL, NULL);
1500 ok(!ret, "Expected failure\n");
1501 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1502 ok(needed == 0 || broken(needed != 0), /* nt4 */
1503 "Expected needed buffer size to be set to 0, got %d\n", needed);
1504 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1505 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1507 /* No valid servicetype and servicestate and unknown service group */
1508 needed = 0xdeadbeef;
1509 returned = 0xdeadbeef;
1510 SetLastError(0xdeadbeef);
1511 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1512 &returned, NULL, "deadbeef_group");
1513 ok(!ret, "Expected failure\n");
1514 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1515 ok(needed == 0 || broken(needed != 0), /* nt4 */
1516 "Expected needed buffer size to be set to 0, got %d\n", needed);
1517 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1518 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1520 /* All parameters are correct but our access rights are wrong */
1521 needed = 0xdeadbeef;
1522 returned = 0xdeadbeef;
1523 SetLastError(0xdeadbeef);
1524 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1525 NULL, 0, &needed, &returned, NULL, NULL);
1526 ok(!ret, "Expected failure\n");
1527 ok(needed == 0 || broken(needed != 0), /* nt4 */
1528 "Expected needed buffer size to be set to 0, got %d\n", needed);
1529 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1530 ok(GetLastError() == ERROR_ACCESS_DENIED,
1531 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1533 /* All parameters are correct, access rights are wrong but the
1534 * group name won't be checked yet.
1536 needed = 0xdeadbeef;
1537 returned = 0xdeadbeef;
1538 SetLastError(0xdeadbeef);
1539 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1540 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1541 ok(!ret, "Expected failure\n");
1542 ok(needed == 0 || broken(needed != 0), /* nt4 */
1543 "Expected needed buffer size to be set to 0, got %d\n", needed);
1544 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1545 ok(GetLastError() == ERROR_ACCESS_DENIED,
1546 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1548 /* Open the service control manager with the needed rights */
1549 CloseServiceHandle(scm_handle);
1550 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1552 /* All parameters are correct and the group will be checked */
1553 needed = 0xdeadbeef;
1554 returned = 0xdeadbeef;
1555 SetLastError(0xdeadbeef);
1556 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1557 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1558 ok(!ret, "Expected failure\n");
1559 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1560 ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
1561 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
1562 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1564 /* TODO: Create a test that makes sure we enumerate all services that don't
1565 * belong to a group. (specifying "").
1568 /* All parameters are correct. Request the needed buffer size */
1569 needed = 0xdeadbeef;
1570 returned = 0xdeadbeef;
1571 SetLastError(0xdeadbeef);
1572 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1573 NULL, 0, &needed, &returned, NULL, NULL);
1574 ok(!ret, "Expected failure\n");
1575 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1576 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1577 ok(GetLastError() == ERROR_MORE_DATA,
1578 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1580 /* Test to show we get the same needed buffer size for the W-call */
1581 neededW = 0xdeadbeef;
1582 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1583 NULL, 0, &neededW, &returnedW, NULL, NULL);
1584 ok(!ret, "Expected failure\n");
1585 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1587 /* Store the needed bytes */
1588 tempneeded = needed;
1590 /* Allocate the correct needed bytes */
1591 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1592 bufsize = needed;
1593 needed = 0xdeadbeef;
1594 returned = 0xdeadbeef;
1595 SetLastError(0xdeadbeef);
1596 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1597 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1598 ok(ret, "Expected success, got error %u\n", GetLastError());
1599 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1600 ok(returned == tempreturned, "Expected the same number of service from this function\n");
1601 HeapFree(GetProcessHeap(), 0, exservices);
1603 /* Store the number of returned services */
1604 tempreturned = returned;
1606 /* Allocate less than the needed bytes and don't specify a resume handle */
1607 exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1608 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1609 needed = 0xdeadbeef;
1610 returned = 0xdeadbeef;
1611 SetLastError(0xdeadbeef);
1612 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1613 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1614 ok(!ret, "Expected failure\n");
1615 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1616 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1617 ok(GetLastError() == ERROR_MORE_DATA,
1618 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1620 /* Allocate less than the needed bytes, this time with a correct resume handle */
1621 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1622 needed = 0xdeadbeef;
1623 returned = 0xdeadbeef;
1624 resume = 0;
1625 SetLastError(0xdeadbeef);
1626 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1627 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1628 ok(!ret, "Expected failure\n");
1629 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1630 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1631 todo_wine ok(resume, "Expected a resume handle\n");
1632 ok(GetLastError() == ERROR_MORE_DATA,
1633 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1635 /* Fetch that last service but pass a bigger buffer size */
1636 missing = tempreturned - returned;
1637 bufsize = tempneeded;
1638 needed = 0xdeadbeef;
1639 returned = 0xdeadbeef;
1640 SetLastError(0xdeadbeef);
1641 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1642 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1643 ok(ret, "Expected success, got error %u\n", GetLastError());
1644 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1645 ok(returned == missing, "Expected %u services to be returned\n", missing);
1646 ok(resume == 0, "Expected the resume handle to be 0\n");
1647 HeapFree(GetProcessHeap(), 0, exservices);
1649 /* See if things add up */
1651 /* Get the number of active win32 services */
1652 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1653 NULL, 0, &needed, &returned, NULL, NULL);
1654 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1655 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1656 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1657 HeapFree(GetProcessHeap(), 0, exservices);
1659 servicecountactive = returned;
1661 /* Get the number of inactive win32 services */
1662 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1663 NULL, 0, &needed, &returned, NULL, NULL);
1664 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1665 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1666 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1667 HeapFree(GetProcessHeap(), 0, exservices);
1669 servicecountinactive = returned;
1671 /* Get the number of win32 services */
1672 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1673 NULL, 0, &needed, &returned, NULL, NULL);
1674 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1675 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1676 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1677 HeapFree(GetProcessHeap(), 0, exservices);
1679 /* Check if total is the same as active and inactive win32 services */
1680 ok(returned == (servicecountactive + servicecountinactive),
1681 "Something wrong in the calculation\n");
1683 /* Get all drivers and services */
1684 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1685 SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1686 ok(!ret, "Expected failure\n");
1687 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1688 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1689 SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1690 ok(ret, "Expected success %u\n", GetLastError());
1692 /* Loop through all those returned drivers and services */
1693 for (i = 0; i < returned; i++)
1695 SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
1697 /* lpServiceName and lpDisplayName should always be filled */
1698 ok(lstrlenA(exservices[i].lpServiceName) > 0, "Expected a service name\n");
1699 ok(lstrlenA(exservices[i].lpDisplayName) > 0, "Expected a display name\n");
1701 /* Decrement the counters to see if the functions calls return the
1702 * same numbers as the contents of these structures.
1703 * Check some process id specifics.
1705 if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
1707 /* We shouldn't have a process id for drivers */
1708 ok(status.dwProcessId == 0,
1709 "This driver shouldn't have an associated process id\n");
1712 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1714 if (status.dwCurrentState != SERVICE_STOPPED)
1716 /* We expect a process id for every running service */
1717 ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1718 exservices[i].lpServiceName);
1720 servicecountactive--;
1722 else
1724 /* We shouldn't have a process id for inactive services */
1725 ok(status.dwProcessId == 0, "Service %s state %u shouldn't have an associated process id\n",
1726 exservices[i].lpServiceName, status.dwCurrentState);
1728 servicecountinactive--;
1732 HeapFree(GetProcessHeap(), 0, exservices);
1734 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1735 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1737 CloseServiceHandle(scm_handle);
1740 static void test_close(void)
1742 SC_HANDLE handle;
1743 BOOL ret;
1745 /* NULL handle */
1746 SetLastError(0xdeadbeef);
1747 ret = CloseServiceHandle(NULL);
1748 ok(!ret, "Expected failure\n");
1749 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1751 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1753 /* Proper call */
1754 handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1755 SetLastError(0xdeadbeef);
1756 ret = CloseServiceHandle(handle);
1757 ok(ret, "Expected success got error %u\n", GetLastError());
1760 static void test_sequence(void)
1762 SC_HANDLE scm_handle, svc_handle;
1763 BOOL ret, is_nt4;
1764 QUERY_SERVICE_CONFIGA *config;
1765 DWORD given, needed;
1766 static const CHAR servicename [] = "Winetest";
1767 static const CHAR displayname [] = "Winetest dummy service";
1768 static const CHAR displayname2[] = "Winetest dummy service (2)";
1769 static const CHAR pathname [] = "we_dont_care.exe";
1770 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
1771 static const CHAR password [] = "";
1772 static const CHAR empty [] = "";
1773 static const CHAR localsystem [] = "LocalSystem";
1775 SetLastError(0xdeadbeef);
1776 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
1778 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1780 skip("Not enough rights to get a handle to the manager\n");
1781 return;
1783 else
1784 ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
1786 if (!scm_handle) return;
1787 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
1788 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
1789 CloseServiceHandle(svc_handle);
1791 /* Create a dummy service */
1792 SetLastError(0xdeadbeef);
1793 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
1794 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
1795 pathname, NULL, NULL, dependencies, NULL, password);
1797 if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
1799 /* We try and open the service and do the rest of the tests. Some could
1800 * fail if the tests were changed between these runs.
1802 trace("Deletion probably didn't work last time\n");
1803 SetLastError(0xdeadbeef);
1804 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
1805 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1807 skip("Not enough rights to open the service\n");
1808 CloseServiceHandle(scm_handle);
1809 return;
1811 ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
1813 else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1815 skip("Not enough rights to create the service\n");
1816 CloseServiceHandle(scm_handle);
1817 return;
1819 else
1821 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
1822 if ((svc_handle != NULL) && (pGetSecurityInfo != NULL))
1824 PSID sidOwner, sidGroup;
1825 PACL dacl, sacl;
1826 PSECURITY_DESCRIPTOR pSD;
1827 DWORD error, n1, n2;
1828 HRESULT retval;
1829 BOOL bret;
1831 /* Test using GetSecurityInfo to obtain security information */
1832 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
1833 &sidGroup, &dacl, &sacl, &pSD);
1834 LocalFree(pSD);
1835 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1836 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1837 NULL, NULL, NULL, &pSD);
1838 LocalFree(pSD);
1839 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1840 if (!is_nt4)
1842 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1843 NULL, &dacl, NULL, NULL);
1844 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1845 SetLastError(0xdeadbeef);
1846 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1847 NULL, NULL, NULL, NULL);
1848 error = GetLastError();
1849 ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval);
1850 ok(error == 0xdeadbeef, "Unexpected last error %d\n", error);
1852 else
1853 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1855 /* Test using QueryServiceObjectSecurity to obtain security information */
1856 SetLastError(0xdeadbeef);
1857 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
1858 error = GetLastError();
1859 ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
1860 ok(error == ERROR_INSUFFICIENT_BUFFER ||
1861 broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER),
1862 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error);
1863 if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
1864 pSD = LocalAlloc(0, n1);
1865 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
1866 ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
1867 LocalFree(pSD);
1871 if (!svc_handle) {
1872 CloseServiceHandle(scm_handle);
1873 return;
1876 /* TODO:
1877 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1878 * that the correct keys are used.
1881 /* Request the size for the buffer */
1882 SetLastError(0xdeadbeef);
1883 ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
1884 ok(!ret, "Expected failure\n");
1885 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1887 config = HeapAlloc(GetProcessHeap(), 0, needed);
1888 given = needed;
1889 SetLastError(0xdeadbeef);
1890 ret = QueryServiceConfigA(svc_handle, config, given, &needed);
1891 ok(ret, "Expected success, got error %u\n", GetLastError());
1893 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
1894 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
1895 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
1896 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
1897 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
1898 ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
1899 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
1900 ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
1901 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
1902 /* TODO: Show the double 0 terminated string */
1903 todo_wine
1905 ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
1907 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
1908 ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
1910 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2",
1911 NULL, NULL, NULL, NULL, displayname2);
1912 ok(ret, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
1914 QueryServiceConfigA(svc_handle, NULL, 0, &needed);
1915 config = HeapReAlloc(GetProcessHeap(), 0, config, needed);
1916 ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
1917 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
1918 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
1919 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
1920 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
1921 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
1922 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl);
1923 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
1924 ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
1925 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
1926 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
1927 ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
1929 SetLastError(0xdeadbeef);
1930 ret = DeleteService(svc_handle);
1931 ok(ret, "Expected success, got error %u\n", GetLastError());
1932 CloseServiceHandle(svc_handle);
1934 /* Wait a while. The following test does a CreateService again */
1935 Sleep(1000);
1937 CloseServiceHandle(scm_handle);
1938 HeapFree(GetProcessHeap(), 0, config);
1941 static void test_queryconfig2(void)
1943 SC_HANDLE scm_handle, svc_handle;
1944 BOOL ret;
1945 DWORD expected, needed;
1946 BYTE buffer[MAX_PATH];
1947 LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
1948 SERVICE_PRESHUTDOWN_INFO preshutdown_info;
1949 static const CHAR servicename [] = "Winetest";
1950 static const CHAR displayname [] = "Winetest dummy service";
1951 static const CHAR pathname [] = "we_dont_care.exe";
1952 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
1953 static const CHAR password [] = "";
1954 static const CHAR description [] = "Description";
1956 if(!pQueryServiceConfig2A)
1958 win_skip("function QueryServiceConfig2A not present\n");
1959 return;
1962 SetLastError(0xdeadbeef);
1963 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
1965 if (!scm_handle)
1967 if(GetLastError() == ERROR_ACCESS_DENIED)
1968 skip("Not enough rights to get a handle to the manager\n");
1969 else
1970 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
1971 return;
1974 /* Create a dummy service */
1975 SetLastError(0xdeadbeef);
1976 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
1977 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
1978 pathname, NULL, NULL, dependencies, NULL, password);
1980 if (!svc_handle)
1982 if(GetLastError() == ERROR_SERVICE_EXISTS)
1984 /* We try and open the service and do the rest of the tests. Some could
1985 * fail if the tests were changed between these runs.
1987 trace("Deletion probably didn't work last time\n");
1988 SetLastError(0xdeadbeef);
1989 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
1990 if (!svc_handle)
1992 if(GetLastError() == ERROR_ACCESS_DENIED)
1993 skip("Not enough rights to open the service\n");
1994 else
1995 ok(FALSE, "Could not open the service : %d\n", GetLastError());
1996 CloseServiceHandle(scm_handle);
1997 return;
2000 if (GetLastError() == ERROR_ACCESS_DENIED)
2002 skip("Not enough rights to create the service\n");
2003 CloseServiceHandle(scm_handle);
2004 return;
2006 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
2007 if (!svc_handle)
2009 CloseServiceHandle(scm_handle);
2010 return;
2013 SetLastError(0xdeadbeef);
2014 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2015 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2016 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2018 SetLastError(0xdeadbeef);
2019 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2020 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2021 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2023 SetLastError(0xdeadbeef);
2024 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2025 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2026 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2028 SetLastError(0xdeadbeef);
2029 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2030 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2031 ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
2032 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2034 SetLastError(0xdeadbeef);
2035 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2036 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2037 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2039 needed = 0;
2040 SetLastError(0xdeadbeef);
2041 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2042 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2043 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2044 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2046 needed = 0;
2047 pConfig->lpDescription = (LPSTR)0xdeadbeef;
2048 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2049 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2050 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2051 ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2053 SetLastError(0xdeadbeef);
2054 needed = 0;
2055 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2056 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2057 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2058 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2060 if(!pChangeServiceConfig2A)
2062 win_skip("function ChangeServiceConfig2A not present\n");
2063 goto cleanup;
2066 pConfig->lpDescription = (LPSTR) description;
2067 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2068 ok(ret, "ChangeServiceConfig2A failed\n");
2069 if (!ret) {
2070 goto cleanup;
2073 SetLastError(0xdeadbeef);
2074 needed = 0;
2075 expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2076 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2077 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2078 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2079 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2081 SetLastError(0xdeadbeef);
2082 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2083 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2084 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2086 SetLastError(0xdeadbeef);
2087 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2088 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2089 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2090 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2092 SetLastError(0xdeadbeef);
2093 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2094 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2095 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2096 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2098 if(!pQueryServiceConfig2W)
2100 win_skip("function QueryServiceConfig2W not present\n");
2101 goto cleanup;
2103 SetLastError(0xdeadbeef);
2104 needed = 0;
2105 expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2106 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2107 ok(!ret, "expected QueryServiceConfig2W to fail\n");
2108 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2109 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2111 SetLastError(0xdeadbeef);
2112 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2113 ok(ret, "expected QueryServiceConfig2W to succeed\n");
2115 SetLastError(0xdeadbeef);
2116 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2117 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2118 if(!ret && GetLastError()==ERROR_INVALID_LEVEL)
2120 /* Win2k3 and older */
2121 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2122 goto cleanup;
2124 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2125 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2126 ok(preshutdown_info.dwPreshutdownTimeout == 180000, "Default PreshutdownTimeout = %d\n",
2127 preshutdown_info.dwPreshutdownTimeout);
2129 SetLastError(0xdeadbeef);
2130 preshutdown_info.dwPreshutdownTimeout = -1;
2131 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2132 (LPVOID)&preshutdown_info);
2133 ok(ret, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2135 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2136 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2137 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2138 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2139 ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %d\n",
2140 preshutdown_info.dwPreshutdownTimeout);
2142 cleanup:
2143 DeleteService(svc_handle);
2145 CloseServiceHandle(svc_handle);
2147 /* Wait a while. The following test does a CreateService again */
2148 Sleep(1000);
2150 CloseServiceHandle(scm_handle);
2153 static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2155 BOOL ret;
2156 DWORD le1, le2;
2157 SERVICE_STATUS status;
2159 ret = StartServiceA(svc_handle, 0, NULL);
2160 le1 = GetLastError();
2161 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2163 if (pQueryServiceStatusEx)
2165 DWORD needed;
2166 SERVICE_STATUS_PROCESS statusproc;
2168 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2169 ok(ret, "%s: QueryServiceStatusEx() failed le=%u\n", name, GetLastError());
2170 ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%x\n", name, statusproc.dwCurrentState);
2171 ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %x\n", name, statusproc.dwProcessId);
2174 ret = StartServiceA(svc_handle, 0, NULL);
2175 le2 = GetLastError();
2176 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2177 ok(le2 == le1, "%s: the second try should yield the same error: %u != %u\n", name, le1, le2);
2179 status.dwCurrentState = 0xdeadbeef;
2180 ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status);
2181 le2 = GetLastError();
2182 ok(!ret, "%s: ControlService() should have failed\n", name);
2183 ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2184 ok(status.dwCurrentState == SERVICE_STOPPED ||
2185 broken(is_nt4), /* NT4 returns a random value */
2186 "%s: should be stopped state=%x\n", name, status.dwCurrentState);
2188 return le1;
2191 static void test_start_stop(void)
2193 BOOL ret;
2194 SC_HANDLE scm_handle, svc_handle;
2195 DWORD le, is_nt4;
2196 static const char servicename[] = "Winetest";
2197 char cmd[MAX_PATH+20];
2198 const char* displayname;
2200 SetLastError(0xdeadbeef);
2201 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2202 if (!scm_handle)
2204 if(GetLastError() == ERROR_ACCESS_DENIED)
2205 skip("Not enough rights to get a handle to the manager\n");
2206 else
2207 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
2208 return;
2211 /* Detect NT4 */
2212 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2213 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2215 /* Do some cleanup in case a previous run crashed */
2216 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2217 if (svc_handle)
2219 DeleteService(svc_handle);
2220 CloseServiceHandle(svc_handle);
2223 /* Create a dummy disabled service */
2224 sprintf(cmd, "\"%s\" service exit", selfname);
2225 displayname = "Winetest Disabled Service";
2226 svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2227 GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,
2228 SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL,
2229 NULL, NULL, NULL, NULL);
2230 if (!svc_handle)
2232 if(GetLastError() == ERROR_ACCESS_DENIED)
2233 skip("Not enough rights to create the service\n");
2234 else
2235 ok(FALSE, "Could not create the service: %d\n", GetLastError());
2236 goto cleanup;
2238 le = try_start_stop(svc_handle, displayname, is_nt4);
2239 ok(le == ERROR_SERVICE_DISABLED, "%d != ERROR_SERVICE_DISABLED\n", le);
2241 /* Then one with a bad path */
2242 displayname = "Winetest Bad Path";
2243 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2244 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2245 try_start_stop(svc_handle, displayname, is_nt4);
2247 if (is_nt4)
2249 /* NT4 does not detect when a service fails to start and uses an
2250 * insanely long timeout: 120s. So skip the rest of the tests.
2252 win_skip("Skip some service start/stop tests on NT4\n");
2253 goto cleanup;
2256 /* Again with a process that exits right away */
2257 displayname = "Winetest Exit Service";
2258 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2259 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2260 le = try_start_stop(svc_handle, displayname, is_nt4);
2261 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2263 /* And finally with a service that plays dead, forcing a timeout.
2264 * This time we will put no quotes. That should work too, even if there are
2265 * spaces in the path.
2267 sprintf(cmd, "%s service sleep", selfname);
2268 displayname = "Winetest Sleep Service";
2269 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2270 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2272 le = try_start_stop(svc_handle, displayname, is_nt4);
2273 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2275 cleanup:
2276 if (svc_handle)
2278 DeleteService(svc_handle);
2279 CloseServiceHandle(svc_handle);
2282 /* Wait a while. The following test does a CreateService again */
2283 Sleep(1000);
2285 CloseServiceHandle(scm_handle);
2288 static void test_refcount(void)
2290 SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2291 static const CHAR servicename [] = "Winetest";
2292 static const CHAR pathname [] = "we_dont_care.exe";
2293 BOOL ret;
2295 /* Get a handle to the Service Control Manager */
2296 SetLastError(0xdeadbeef);
2297 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2298 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2300 skip("Not enough rights to get a handle to the manager\n");
2301 return;
2304 /* Create a service */
2305 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2306 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2307 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2308 ok(svc_handle1 != NULL, "Expected success, got error %u\n", GetLastError());
2310 /* Get a handle to this new service */
2311 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2312 ok(svc_handle2 != NULL, "Expected success, got error %u\n", GetLastError());
2314 /* Get another handle to this new service */
2315 svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2316 ok(svc_handle3 != NULL, "Expected success, got error %u\n", GetLastError());
2318 /* Check if we can close the handle to the Service Control Manager */
2319 ret = CloseServiceHandle(scm_handle);
2320 ok(ret, "Expected success (err=%d)\n", GetLastError());
2322 /* Get a new handle to the Service Control Manager */
2323 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2324 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
2326 /* Get a handle to this new service */
2327 svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2328 ok(svc_handle4 != NULL, "Expected success, got error %u\n", GetLastError());
2330 /* Delete the service */
2331 ret = DeleteService(svc_handle4);
2332 ok(ret, "Expected success (err=%d)\n", GetLastError());
2334 /* We cannot create the same service again as it's still marked as 'being deleted'.
2335 * The reason is that we still have 4 open handles to this service even though we
2336 * closed the handle to the Service Control Manager in between.
2338 SetLastError(0xdeadbeef);
2339 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2340 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2341 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2342 todo_wine
2344 ok(!svc_handle5, "Expected failure\n");
2345 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
2346 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2349 /* FIXME: Remove this when Wine is fixed */
2350 if (svc_handle5)
2352 DeleteService(svc_handle5);
2353 CloseServiceHandle(svc_handle5);
2356 /* Close all the handles to the service and try again */
2357 ret = CloseServiceHandle(svc_handle4);
2358 ok(ret, "Expected success (err=%d)\n", GetLastError());
2359 ret = CloseServiceHandle(svc_handle3);
2360 ok(ret, "Expected success (err=%d)\n", GetLastError());
2361 ret = CloseServiceHandle(svc_handle2);
2362 ok(ret, "Expected success (err=%d)\n", GetLastError());
2363 ret = CloseServiceHandle(svc_handle1);
2364 ok(ret, "Expected success (err=%d)\n", GetLastError());
2366 /* Wait a while. Doing a CreateService too soon will result again
2367 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2369 Sleep(1000);
2371 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2372 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2373 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2374 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2375 ok(svc_handle5 != NULL, "Expected success, got error %u\n", GetLastError());
2377 /* Delete the service */
2378 ret = DeleteService(svc_handle5);
2379 ok(ret, "Expected success (err=%d)\n", GetLastError());
2381 /* Wait a while. Just in case one of the following tests does a CreateService again */
2382 Sleep(1000);
2384 CloseServiceHandle(svc_handle5);
2385 CloseServiceHandle(scm_handle);
2388 START_TEST(service)
2390 SC_HANDLE scm_handle;
2391 int myARGC;
2392 char** myARGV;
2394 myARGC = winetest_get_mainargs(&myARGV);
2395 GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL);
2396 if (myARGC >= 3)
2398 if (strcmp(myARGV[2], "sleep") == 0)
2399 /* Cause a service startup timeout */
2400 Sleep(90000);
2401 /* then, or if myARGV[2] == "exit", just exit */
2402 return;
2405 /* Bail out if we are on win98 */
2406 SetLastError(0xdeadbeef);
2407 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2409 if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2411 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2412 return;
2414 CloseServiceHandle(scm_handle);
2416 init_function_pointers();
2418 /* First some parameter checking */
2419 test_open_scm();
2420 test_open_svc();
2421 test_create_delete_svc();
2422 test_get_displayname();
2423 test_get_servicekeyname();
2424 test_query_svc();
2425 test_enum_svc();
2426 test_close();
2427 /* Test the creation, querying and deletion of a service */
2428 test_sequence();
2429 test_queryconfig2();
2430 test_start_stop();
2431 /* The main reason for this test is to check if any refcounting is used
2432 * and what the rules are
2434 test_refcount();