[ADVAPI32_WINETEST] test_create_delete_svc(): Fix 'account' size (#2960)
[reactos.git] / modules / rostests / winetests / advapi32 / service.c
1 /*
2 * Unit tests for service functions
3 *
4 * Copyright (c) 2007 Paul Vriens
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
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"
32
33 #include "wine/test.h"
34
35 static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
36 static CHAR selfname[MAX_PATH];
37
38 static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
39 static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
40 static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
41 DWORD, LPBYTE, DWORD, LPDWORD,
42 LPDWORD, LPDWORD, LPCSTR);
43 static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
44 DWORD, LPBYTE, DWORD, LPDWORD,
45 LPDWORD, LPDWORD, LPCWSTR);
46 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
47 PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
48 static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
49 static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
50 static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
51 DWORD, LPDWORD);
52 static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
53 PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
54 static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*);
55
56 static void init_function_pointers(void)
57 {
58 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
59
60 pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
61 pChangeServiceConfig2W = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2W");
62 pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
63 pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
64 pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo");
65 pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
66 pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
67 pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
68 pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
69 pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW");
70 }
71
72 static void test_open_scm(void)
73 {
74 SC_HANDLE scm_handle;
75
76 /* No access rights */
77 SetLastError(0xdeadbeef);
78 scm_handle = OpenSCManagerA(NULL, NULL, 0);
79 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
80 CloseServiceHandle(scm_handle);
81
82 /* Unknown database name */
83 SetLastError(0xdeadbeef);
84 scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
85 ok(!scm_handle, "Expected failure\n");
86 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
87 CloseServiceHandle(scm_handle); /* Just in case */
88
89 /* MSDN says only ServiceActive is allowed, or NULL */
90 SetLastError(0xdeadbeef);
91 scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
92 ok(!scm_handle, "Expected failure\n");
93 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
94 CloseServiceHandle(scm_handle); /* Just in case */
95
96 /* Remote unknown host */
97 SetLastError(0xdeadbeef);
98 scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
99 todo_wine
100 {
101 ok(!scm_handle, "Expected failure\n");
102 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */,
103 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
104 }
105 CloseServiceHandle(scm_handle); /* Just in case */
106
107 /* Proper call with an empty hostname */
108 scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
109 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
110 CloseServiceHandle(scm_handle);
111
112 /* Again a correct one */
113 SetLastError(0xdeadbeef);
114 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
115 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_IO_PENDING) /* win2k */,
116 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
117 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
118 CloseServiceHandle(scm_handle);
119 }
120
121 static void test_open_svc(void)
122 {
123 SC_HANDLE scm_handle, svc_handle;
124 CHAR displayname[4096];
125 DWORD displaysize;
126
127 /* All NULL (invalid access rights) */
128 SetLastError(0xdeadbeef);
129 svc_handle = OpenServiceA(NULL, NULL, 0);
130 ok(!svc_handle, "Expected failure\n");
131 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
132
133 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
134
135 /* NULL service */
136 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
137 SetLastError(0xdeadbeef);
138 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
139 ok(!svc_handle, "Expected failure\n");
140 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
141 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
142 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
143 CloseServiceHandle(scm_handle);
144
145 /* Nonexistent service */
146 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
147 SetLastError(0xdeadbeef);
148 svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
149 ok(!svc_handle, "Expected failure\n");
150 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
151 CloseServiceHandle(scm_handle);
152
153 /* Proper SCM handle but different access rights */
154 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
155 SetLastError(0xdeadbeef);
156 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_WRITE);
157 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
158 skip("Not enough rights to get a handle to the service\n");
159 else
160 {
161 ok(svc_handle != NULL, "Expected success, got error %u\n", GetLastError());
162 CloseServiceHandle(svc_handle);
163 }
164
165 /* Test to show we can't open a service with the displayname */
166
167 /* Retrieve the needed size for the buffer */
168 displaysize = 0;
169 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
170 /* Get the displayname */
171 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
172 /* Try to open the service with this displayname, unless the displayname equals
173 * the servicename as that would defeat the purpose of this test.
174 */
175 if (!lstrcmpiA(spooler, displayname))
176 {
177 skip("displayname equals servicename\n");
178 CloseServiceHandle(scm_handle);
179 return;
180 }
181
182 SetLastError(0xdeadbeef);
183 svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
184 ok(!svc_handle, "Expected failure\n");
185 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
186 /* Just in case */
187 CloseServiceHandle(svc_handle);
188
189 CloseServiceHandle(scm_handle);
190 }
191
192 static void test_create_delete_svc(void)
193 {
194 SC_HANDLE scm_handle, svc_handle1, svc_handle2;
195 CHAR username[UNLEN + 1], domain[MAX_PATH];
196 DWORD user_size = UNLEN + 1;
197 CHAR account[MAX_PATH + UNLEN + 1];
198 static const CHAR servicename [] = "Winetest";
199 static const CHAR pathname [] = "we_dont_care.exe";
200 static const CHAR empty [] = "";
201 static const CHAR password [] = "secret";
202 BOOL spooler_exists = FALSE;
203 BOOL ret;
204 CHAR display[4096];
205 DWORD display_size = sizeof(display);
206
207 /* Get the username and turn it into an account to be used in some tests */
208 GetUserNameA(username, &user_size);
209 /* Get the domainname to cater for that situation */
210 if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH))
211 sprintf(account, "%s\\%s", domain, username);
212 else
213 sprintf(account, ".\\%s", username);
214
215 /* All NULL */
216 SetLastError(0xdeadbeef);
217 svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
218 ok(!svc_handle1, "Expected failure\n");
219 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
220
221 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
222
223 /* Only a valid handle to the Service Control Manager */
224 SetLastError(0xdeadbeef);
225 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
226 ok(!svc_handle1, "Expected failure\n");
227 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
228 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
229 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
230
231 /* Now with a servicename */
232 SetLastError(0xdeadbeef);
233 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
234 ok(!svc_handle1, "Expected failure\n");
235 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
236 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
237 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
238
239 /* Or just a binary name */
240 SetLastError(0xdeadbeef);
241 svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
242 ok(!svc_handle1, "Expected failure\n");
243 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
244 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
245 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
246
247 /* Both servicename and binary name (We only have connect rights) */
248 SetLastError(0xdeadbeef);
249 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
250 ok(!svc_handle1, "Expected failure\n");
251 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
252
253 /* They can even be empty at this stage of parameter checking */
254 SetLastError(0xdeadbeef);
255 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
256 ok(!svc_handle1, "Expected failure\n");
257 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
258
259 SetLastError(0xdeadbeef);
260 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
261 ok(!svc_handle1, "Expected failure\n");
262 ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
263
264 /* Open the Service Control Manager with minimal rights for creation
265 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
266 */
267 CloseServiceHandle(scm_handle);
268 SetLastError(0xdeadbeef);
269 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
270 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
271 {
272 skip("Not enough rights to get a handle to the manager\n");
273 return;
274 }
275
276 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
277
278 /* Empty strings for servicename and binary name are checked */
279 SetLastError(0xdeadbeef);
280 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
281 ok(!svc_handle1, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
283
284 SetLastError(0xdeadbeef);
285 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
286 ok(!svc_handle1, "Expected failure\n");
287 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
288
289 SetLastError(0xdeadbeef);
290 svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
291 ok(!svc_handle1, "Expected failure\n");
292 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
293
294 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
295 * an ERROR_INVALID_PARAMETER)
296 */
297 SetLastError(0xdeadbeef);
298 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
299 SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
300 ok(!svc_handle1, "Expected failure\n");
301 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
302
303 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
304
305 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
306 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
307 */
308 SetLastError(0xdeadbeef);
309 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
310 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
311 ok(!svc_handle1, "Expected failure\n");
312 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
313
314 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
315 SetLastError(0xdeadbeef);
316 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
317 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
318 ok(!svc_handle1, "Expected failure\n");
319 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
320
321 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
322 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
323 */
324 SetLastError(0xdeadbeef);
325 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
326 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
327 ok(!svc_handle1, "Expected failure\n");
328 ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT,
329 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
330
331 /* Illegal (start-type is not a mask and should only be one of the possibilities)
332 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
333 * it's most likely not the wanted start-type)
334 */
335 SetLastError(0xdeadbeef);
336 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
337 SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
338 ok(!svc_handle1, "Expected failure\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
340
341 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
342 SetLastError(0xdeadbeef);
343 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
344 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
345 ok(!svc_handle1, "Expected failure\n");
346 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
347
348 /* Test if ServiceType can be a combined one for drivers */
349 SetLastError(0xdeadbeef);
350 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER,
351 SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
352 ok(!svc_handle1, "Expected failure\n");
353 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
354
355 /* The service already exists (check first, just in case) */
356 svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ);
357 if (svc_handle1)
358 {
359 spooler_exists = TRUE;
360 CloseServiceHandle(svc_handle1);
361 SetLastError(0xdeadbeef);
362 svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
363 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
364 ok(!svc_handle1, "Expected failure\n");
365 ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
366 }
367 else
368 skip("Spooler service doesn't exist\n");
369
370 /* To find an existing displayname we check the 'Spooler' service. Although the registry
371 * doesn't show DisplayName on NT4, this call will return a displayname which is equal
372 * to the servicename and can't be used as well for a new displayname.
373 */
374 if (spooler_exists)
375 {
376 ret = GetServiceDisplayNameA(scm_handle, spooler, display, &display_size);
377
378 if (!ret)
379 skip("Could not retrieve a displayname for the Spooler service\n");
380 else
381 {
382 svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS,
383 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
384 ok(!svc_handle1, "Expected failure for display name '%s'\n", display);
385 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME,
386 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
387 }
388 }
389 else
390 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
391
392 /* Windows doesn't care about the access rights for creation (which makes
393 * sense as there is no service yet) as long as there are sufficient
394 * rights to the manager.
395 */
396 SetLastError(0xdeadbeef);
397 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
398 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
399 ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError());
400
401 /* DeleteService however must have proper rights */
402 SetLastError(0xdeadbeef);
403 ret = DeleteService(svc_handle1);
404 ok(!ret, "Expected failure\n");
405 ok(GetLastError() == ERROR_ACCESS_DENIED,
406 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
407
408 /* Open the service with minimal rights for deletion.
409 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
410 */
411 CloseServiceHandle(svc_handle1);
412 svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
413
414 /* Now that we have the proper rights, we should be able to delete */
415 SetLastError(0xdeadbeef);
416 ret = DeleteService(svc_handle1);
417 ok(ret, "Expected success, got error %u\n", GetLastError());
418
419 /* Service is marked for delete, but handle is still open. Try to open service again. */
420 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
421 ok(svc_handle2 != NULL, "got %p, error %u\n", svc_handle2, GetLastError());
422 CloseServiceHandle(svc_handle2);
423
424 CloseServiceHandle(svc_handle1);
425 CloseServiceHandle(scm_handle);
426
427 /* Wait a while. One of the following tests also does a CreateService for the
428 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
429 * error if we do this too quickly. Vista seems more picky than the others.
430 */
431 Sleep(1000);
432
433 /* And a final NULL check */
434 SetLastError(0xdeadbeef);
435 ret = DeleteService(NULL);
436 ok(!ret, "Expected failure\n");
437 ok(GetLastError() == ERROR_INVALID_HANDLE,
438 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
439 }
440
441 static void test_get_displayname(void)
442 {
443 SC_HANDLE scm_handle, svc_handle;
444 BOOL ret;
445 CHAR displayname[4096];
446 WCHAR displaynameW[2048];
447 DWORD displaysize, tempsize, tempsizeW;
448 static const CHAR deadbeef[] = "Deadbeef";
449 static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
450 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
451 static const WCHAR abcW[] = {'A','B','C',0};
452 static const CHAR servicename[] = "Winetest";
453 static const CHAR pathname[] = "we_dont_care.exe";
454
455 /* Having NULL for the size of the buffer will crash on W2K3 */
456
457 SetLastError(0xdeadbeef);
458 ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
459 ok(!ret, "Expected failure\n");
460 ok(GetLastError() == ERROR_INVALID_HANDLE,
461 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
462
463 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
464
465 SetLastError(0xdeadbeef);
466 ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
467 ok(!ret, "Expected failure\n");
468 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
469 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
470 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
471
472 SetLastError(0xdeadbeef);
473 displaysize = sizeof(displayname);
474 ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
475 ok(!ret, "Expected failure\n");
476 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
477 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
478 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
479
480 /* Test for nonexistent service */
481 SetLastError(0xdeadbeef);
482 displaysize = -1;
483 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
484 ok(!ret, "Expected failure\n");
485 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
486 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
487
488 SetLastError(0xdeadbeef);
489 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
490 ok(!ret, "Expected failure\n");
491 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
492 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
493 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
494
495 displaysize = 15;
496 strcpy(displayname, "ABC");
497 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
498 ok(!ret, "Expected failure\n");
499 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
500 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
501 todo_wine ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
502 ok(displayname[0] == 0, "Service name not empty\n");
503
504 displaysize = 15;
505 lstrcpyW( displaynameW, abcW );
506 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
507 ok(!ret, "Expected failure\n");
508 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
509 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
510 ok(displaysize == 15, "Service size expected 15, got %d\n", displaysize);
511 ok(displaynameW[0] == 0, "Service name not empty\n");
512
513 displaysize = 0;
514 strcpy(displayname, "ABC");
515 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
516 ok(!ret, "Expected failure\n");
517 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
518 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
519 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
520 ok(displayname[0] == 'A', "Service name changed\n");
521
522 displaysize = 0;
523 lstrcpyW( displaynameW, abcW );
524 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
525 ok(!ret, "Expected failure\n");
526 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
527 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
528 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
529 ok(displaynameW[0] == 'A', "Service name changed\n");
530
531 displaysize = 1;
532 strcpy(displayname, "ABC");
533 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
534 ok(!ret, "Expected failure\n");
535 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
536 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
537 todo_wine ok(displaysize == 1, "Service size expected 1, got %d\n", displaysize);
538 ok(displayname[0] == 0, "Service name not empty\n");
539
540 displaysize = 1;
541 lstrcpyW( displaynameW, abcW );
542 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
543 ok(!ret, "Expected failure\n");
544 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
545 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
546 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
547 ok(displaynameW[0] == 'A', "Service name changed\n");
548
549 displaysize = 2;
550 strcpy(displayname, "ABC");
551 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
552 ok(!ret, "Expected failure\n");
553 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
554 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
555 todo_wine ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
556 ok(displayname[0] == 0, "Service name not empty\n");
557
558 displaysize = 2;
559 lstrcpyW( displaynameW, abcW );
560 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
561 ok(!ret, "Expected failure\n");
562 ok(displaysize == 2, "Service size expected 2, got %d\n", displaysize);
563 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
564 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
565 ok(displaynameW[0] == 0, "Service name not empty\n");
566
567 /* Check if 'Spooler' exists */
568 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
569 if (!svc_handle)
570 {
571 skip("Spooler service doesn't exist\n");
572 CloseServiceHandle(scm_handle);
573 return;
574 }
575 CloseServiceHandle(svc_handle);
576
577 /* Retrieve the needed size for the buffer */
578 SetLastError(0xdeadbeef);
579 displaysize = -1;
580 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
581 ok(!ret, "Expected failure\n");
582 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
583 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
584 tempsize = displaysize;
585
586 displaysize = 0;
587 ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
588 ok(!ret, "Expected failure\n");
589 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
590 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
591 ok(displaysize == tempsize, "Buffer size mismatch (%d vs %d)\n", tempsize, displaysize);
592
593 /* Buffer is too small */
594 SetLastError(0xdeadbeef);
595 displaysize = (tempsize / 2);
596 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
597 ok(!ret, "Expected failure\n");
598 ok(displaysize == tempsize, "Expected the needed buffersize\n");
599 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
600 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
601
602 /* First try with a buffer that should be big enough to hold
603 * the ANSI string (and terminating character). This succeeds on Windows
604 * although when asked (see above 2 tests) it will return twice the needed size.
605 */
606 SetLastError(0xdeadbeef);
607 displaysize = (tempsize / 2) + 1;
608 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
609 ok(ret, "Expected success, got error %u\n", GetLastError());
610 ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
611
612 /* Now with the original returned size */
613 SetLastError(0xdeadbeef);
614 displaysize = tempsize;
615 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
616 ok(ret, "Expected success, got error %u\n", GetLastError());
617 ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
618
619 /* And with a bigger than needed buffer */
620 SetLastError(0xdeadbeef);
621 displaysize = tempsize * 2;
622 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
623 ok(ret, "Expected success, got error %u\n", GetLastError());
624 /* Test that shows that if the buffersize is enough, it's not changed */
625 ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
626 ok(strlen(displayname) == tempsize/2,
627 "Expected the buffer to be twice the length of the string\n") ;
628
629 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
630 SetLastError(0xdeadbeef);
631 displaysize = -1;
632 ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
633 ok(!ret, "Expected failure\n");
634 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
635 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
636
637 /* Buffer is too small */
638 SetLastError(0xdeadbeef);
639 tempsizeW = displaysize;
640 displaysize = tempsizeW / 2;
641 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
642 ok(!ret, "Expected failure\n");
643 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
644 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
645 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
646
647 /* Now with the original returned size */
648 SetLastError(0xdeadbeef);
649 displaysize = tempsizeW;
650 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
651 ok(!ret, "Expected failure\n");
652 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
653 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
654 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
655
656 /* And with a bigger than needed buffer */
657 SetLastError(0xdeadbeef);
658 displaysize = tempsizeW + 1; /* This caters for the null terminating character */
659 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
660 ok(ret, "Expected success, got error %u\n", GetLastError());
661 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
662 ok(lstrlenW(displaynameW) == displaysize,
663 "Expected the buffer to be the length of the string\n") ;
664 ok(tempsize / 2 == tempsizeW,
665 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
666
667 CloseServiceHandle(scm_handle);
668
669 /* Test for a service without a displayname (which is valid). This should return
670 * the servicename itself.
671 */
672 SetLastError(0xdeadbeef);
673 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
674 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
675 {
676 skip("Not enough rights to get a handle to the manager\n");
677 return;
678 }
679
680 SetLastError(0xdeadbeef);
681 svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
682 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
683 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
684 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
685 if (!svc_handle)
686 {
687 CloseServiceHandle(scm_handle);
688 return;
689 }
690
691 /* Retrieve the needed size for the buffer */
692 SetLastError(0xdeadbeef);
693 displaysize = -1;
694 ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
695 ok(!ret, "Expected failure\n");
696 ok(displaysize == strlen(servicename) * 2,
697 "Expected the displaysize to be twice the size of the servicename\n");
698 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
699 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
700
701 /* Buffer is too small */
702 SetLastError(0xdeadbeef);
703 tempsize = displaysize;
704 displaysize = (tempsize / 2);
705 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
706 ok(!ret, "Expected failure\n");
707 ok(displaysize == tempsize, "Expected the needed buffersize\n");
708 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
709 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
710
711 /* Get the displayname */
712 SetLastError(0xdeadbeef);
713 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
714 ok(ret, "Expected success, got error %u\n", GetLastError());
715 ok(!lstrcmpiA(displayname, servicename),
716 "Expected displayname to be %s, got %s\n", servicename, displayname);
717
718 /* Delete the service */
719 ret = DeleteService(svc_handle);
720 ok(ret, "Expected success (err=%d)\n", GetLastError());
721
722 CloseServiceHandle(svc_handle);
723 CloseServiceHandle(scm_handle);
724
725 /* Wait a while. Just in case one of the following tests does a CreateService again */
726 Sleep(1000);
727 }
728
729 static void test_get_servicekeyname(void)
730 {
731 SC_HANDLE scm_handle, svc_handle;
732 CHAR servicename[4096];
733 CHAR displayname[4096];
734 WCHAR servicenameW[4096];
735 WCHAR displaynameW[4096];
736 DWORD servicesize, displaysize, tempsize;
737 BOOL ret;
738 static const CHAR deadbeef[] = "Deadbeef";
739 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
740 static const WCHAR abcW[] = {'A','B','C',0};
741
742 /* Having NULL for the size of the buffer will crash on W2K3 */
743
744 SetLastError(0xdeadbeef);
745 ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
746 ok(!ret, "Expected failure\n");
747 ok(GetLastError() == ERROR_INVALID_HANDLE,
748 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
749
750 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
751
752 servicesize = 200;
753 SetLastError(0xdeadbeef);
754 ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &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 == 1, "Service size expected 1, got %d\n", servicesize);
760
761 /* Valid handle and buffer but no displayname */
762 servicesize = 200;
763 SetLastError(0xdeadbeef);
764 ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
765 ok(!ret, "Expected failure\n");
766 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
767 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
768 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
769 todo_wine ok(servicesize == 200, "Service size expected 1, got %d\n", servicesize);
770
771 /* Test for nonexistent displayname */
772 SetLastError(0xdeadbeef);
773 ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
774 ok(!ret, "Expected failure\n");
775 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
776 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
777 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
778
779 servicesize = 15;
780 strcpy(servicename, "ABC");
781 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
782 ok(!ret, "Expected failure\n");
783 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
784 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
785 todo_wine ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
786 ok(servicename[0] == 0, "Service name not empty\n");
787
788 servicesize = 15;
789 lstrcpyW( servicenameW, abcW );
790 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
791 ok(!ret, "Expected failure\n");
792 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
793 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
794 ok(servicesize == 15, "Service size expected 15, got %d\n", servicesize);
795 ok(servicenameW[0] == 0, "Service name not empty\n");
796
797 servicesize = 0;
798 strcpy(servicename, "ABC");
799 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
800 ok(!ret, "Expected failure\n");
801 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
802 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
803 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
804 ok(servicename[0] == 'A', "Service name changed\n");
805
806 servicesize = 0;
807 lstrcpyW( servicenameW, abcW );
808 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
809 ok(!ret, "Expected failure\n");
810 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
811 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
812 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
813 ok(servicenameW[0] == 'A', "Service name changed\n");
814
815 servicesize = 1;
816 strcpy(servicename, "ABC");
817 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
818 ok(!ret, "Expected failure\n");
819 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
820 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
821 todo_wine ok(servicesize == 1, "Service size expected 1, got %d\n", servicesize);
822 ok(servicename[0] == 0, "Service name not empty\n");
823
824 servicesize = 1;
825 lstrcpyW( servicenameW, abcW );
826 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
827 ok(!ret, "Expected failure\n");
828 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
829 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
830 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
831 ok(servicenameW[0] == 'A', "Service name changed\n");
832
833 servicesize = 2;
834 strcpy(servicename, "ABC");
835 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
836 ok(!ret, "Expected failure\n");
837 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
838 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
839 todo_wine ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
840 ok(servicename[0] == 0, "Service name not empty\n");
841
842 servicesize = 2;
843 lstrcpyW( servicenameW, abcW );
844 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
845 ok(!ret, "Expected failure\n");
846 ok(servicesize == 2, "Service size expected 2, got %d\n", servicesize);
847 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
848 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
849 ok(servicenameW[0] == 0, "Service name not empty\n");
850
851 /* Check if 'Spooler' exists */
852 svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
853 if (!svc_handle)
854 {
855 skip("Spooler service doesn't exist\n");
856 CloseServiceHandle(scm_handle);
857 return;
858 }
859 CloseServiceHandle(svc_handle);
860
861 /* Get the displayname for the 'Spooler' service */
862 GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
863 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
864
865 /* Retrieve the needed size for the buffer */
866 SetLastError(0xdeadbeef);
867 servicesize = 0;
868 ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
869 ok(!ret, "Expected failure\n");
870 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
871 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
872
873 /* Valid call with the correct buffersize */
874 SetLastError(0xdeadbeef);
875 tempsize = servicesize;
876 servicesize *= 2;
877 ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
878 ok(ret, "Expected success, got error %u\n", GetLastError());
879 if (ret)
880 {
881 ok(strlen(servicename) == tempsize/2,
882 "Expected the buffer to be twice the length of the string\n") ;
883 ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
884 ok(servicesize == (tempsize * 2),
885 "Expected servicesize not to change if buffer not insufficient\n") ;
886 }
887
888 MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
889 SetLastError(0xdeadbeef);
890 servicesize *= 2;
891 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
892 ok(ret, "Expected success, got error %u\n", GetLastError());
893 if (ret)
894 {
895 ok(strlen(servicename) == tempsize/2,
896 "Expected the buffer to be twice the length of the string\n") ;
897 ok(servicesize == lstrlenW(servicenameW),
898 "Expected servicesize not to change if buffer not insufficient\n") ;
899 }
900
901 SetLastError(0xdeadbeef);
902 servicesize = 3;
903 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
904 ok(!ret, "Expected failure\n");
905 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
906 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
907 ok(servicenameW[0] == 0, "Buffer not empty\n");
908
909 CloseServiceHandle(scm_handle);
910 }
911
912 static void test_query_svc(void)
913 {
914 SC_HANDLE scm_handle, svc_handle;
915 BOOL ret;
916 SERVICE_STATUS status;
917 SERVICE_STATUS_PROCESS *statusproc;
918 DWORD bufsize, needed;
919
920 /* All NULL or wrong */
921 SetLastError(0xdeadbeef);
922 ret = QueryServiceStatus(NULL, NULL);
923 ok(!ret, "Expected failure\n");
924 ok(GetLastError() == ERROR_INVALID_HANDLE,
925 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
926
927 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
928
929 /* Check if 'Spooler' exists.
930 * Open with not enough rights to query the status.
931 */
932 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
933 if (!svc_handle)
934 {
935 skip("Spooler service doesn't exist\n");
936 CloseServiceHandle(scm_handle);
937 return;
938 }
939
940 SetLastError(0xdeadbeef);
941 ret = QueryServiceStatus(svc_handle, NULL);
942 ok(!ret, "Expected failure\n");
943 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
944 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
945 "Unexpected last error %d\n", GetLastError());
946
947 SetLastError(0xdeadbeef);
948 ret = QueryServiceStatus(svc_handle, &status);
949 ok(!ret, "Expected failure\n");
950 ok(GetLastError() == ERROR_ACCESS_DENIED,
951 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
952
953 /* Open the service with just enough rights.
954 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
955 */
956 CloseServiceHandle(svc_handle);
957 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
958
959 SetLastError(0xdeadbeef);
960 ret = QueryServiceStatus(svc_handle, &status);
961 ok(ret, "Expected success, got error %u\n", GetLastError());
962
963 CloseServiceHandle(svc_handle);
964
965 /* More or less the same tests for QueryServiceStatusEx */
966 if (!pQueryServiceStatusEx)
967 {
968 win_skip( "QueryServiceStatusEx not available\n" );
969 CloseServiceHandle(scm_handle);
970 return;
971 }
972
973 /* Open service with not enough rights to query the status */
974 svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
975
976 /* All NULL or wrong, this proves that info level is checked first */
977 SetLastError(0xdeadbeef);
978 ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
979 ok(!ret, "Expected failure\n");
980 ok(GetLastError() == ERROR_INVALID_LEVEL,
981 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
982
983 /* Passing a NULL parameter for the needed buffer size
984 * will crash on anything but NT4.
985 */
986
987 /* Only info level is correct. It looks like the buffer/size is checked second */
988 SetLastError(0xdeadbeef);
989 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
990 /* NT4 checks the handle first */
991 if (GetLastError() != ERROR_INVALID_HANDLE)
992 {
993 ok(!ret, "Expected failure\n");
994 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
995 "Needed buffersize is wrong : %d\n", needed);
996 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
997 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
998 }
999
1000 /* Pass a correct buffer and buffersize but a NULL handle */
1001 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1002 bufsize = needed;
1003 SetLastError(0xdeadbeef);
1004 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1005 ok(!ret, "Expected failure\n");
1006 ok(GetLastError() == ERROR_INVALID_HANDLE,
1007 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1008 HeapFree(GetProcessHeap(), 0, statusproc);
1009
1010 /* Correct handle and info level */
1011 SetLastError(0xdeadbeef);
1012 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1013 /* NT4 doesn't return the needed size */
1014 if (GetLastError() != ERROR_INVALID_PARAMETER)
1015 {
1016 ok(!ret, "Expected failure\n");
1017 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1018 "Needed buffersize is wrong : %d\n", needed);
1019 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1020 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1021 }
1022
1023 /* All parameters are OK but we don't have enough rights */
1024 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1025 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1026 SetLastError(0xdeadbeef);
1027 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1028 ok(!ret, "Expected failure\n");
1029 ok(GetLastError() == ERROR_ACCESS_DENIED,
1030 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1031 HeapFree(GetProcessHeap(), 0, statusproc);
1032
1033 /* Open the service with just enough rights. */
1034 CloseServiceHandle(svc_handle);
1035 svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
1036
1037 /* Everything should be fine now. */
1038 statusproc = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS));
1039 bufsize = sizeof(SERVICE_STATUS_PROCESS);
1040 SetLastError(0xdeadbeef);
1041 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1042 ok(ret, "Expected success, got error %u\n", GetLastError());
1043 if (statusproc->dwCurrentState == SERVICE_RUNNING)
1044 ok(statusproc->dwProcessId != 0,
1045 "Expect a process id for this running service\n");
1046 else
1047 ok(statusproc->dwProcessId == 0,
1048 "Expect no process id for this stopped service\n");
1049
1050 /* same call with null needed pointer */
1051 SetLastError(0xdeadbeef);
1052 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1053 ok(!ret, "Expected failure\n");
1054 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ ||
1055 GetLastError() == ERROR_INVALID_ADDRESS, "got %d\n", GetLastError());
1056
1057 HeapFree(GetProcessHeap(), 0, statusproc);
1058
1059 CloseServiceHandle(svc_handle);
1060 CloseServiceHandle(scm_handle);
1061 }
1062
1063 static void test_enum_svc(void)
1064 {
1065 SC_HANDLE scm_handle;
1066 BOOL ret;
1067 DWORD bufsize, needed, returned, resume;
1068 DWORD neededW, returnedW;
1069 DWORD tempneeded, tempreturned, missing;
1070 DWORD servicecountactive, servicecountinactive;
1071 ENUM_SERVICE_STATUSA *services;
1072 ENUM_SERVICE_STATUSW *servicesW;
1073 ENUM_SERVICE_STATUS_PROCESSA *exservices;
1074 UINT i;
1075
1076 /* All NULL or wrong */
1077 SetLastError(0xdeadbeef);
1078 ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1079 ok(!ret, "Expected failure\n");
1080 ok(GetLastError() == ERROR_INVALID_HANDLE,
1081 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1082
1083 SetLastError(0xdeadbeef);
1084 ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1085 ok(!ret, "Expected failure\n");
1086 ok(GetLastError() == ERROR_INVALID_HANDLE,
1087 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1088
1089 /* Open the service control manager with not enough rights at first */
1090 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1091
1092 /* Valid handle but rest is still NULL or wrong */
1093 SetLastError(0xdeadbeef);
1094 ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1095 ok(!ret, "Expected failure\n");
1096 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1097 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1098 "Unexpected last error %d\n", GetLastError());
1099
1100 SetLastError(0xdeadbeef);
1101 ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1102 ok(!ret, "Expected failure\n");
1103 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1104 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1105 "Unexpected last error %d\n", GetLastError());
1106
1107 /* Don't specify the two required pointers */
1108 returned = 0xdeadbeef;
1109 SetLastError(0xdeadbeef);
1110 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1111 ok(!ret, "Expected failure\n");
1112 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1113 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1114 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1115 "Unexpected last error %d\n", GetLastError());
1116
1117 returned = 0xdeadbeef;
1118 SetLastError(0xdeadbeef);
1119 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1120 ok(!ret, "Expected failure\n");
1121 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1122 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1123 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1124 "Unexpected last error %d\n", GetLastError());
1125
1126 /* Don't specify the two required pointers */
1127 needed = 0xdeadbeef;
1128 SetLastError(0xdeadbeef);
1129 ret = EnumServicesStatusA(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());
1136
1137 needed = 0xdeadbeef;
1138 SetLastError(0xdeadbeef);
1139 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1140 ok(!ret, "Expected failure\n");
1141 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1142 "Expected no change to the needed buffer variable\n");
1143 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1144 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1145 "Unexpected last error %d\n", GetLastError());
1146
1147 /* No valid servicetype and servicestate */
1148 needed = 0xdeadbeef;
1149 returned = 0xdeadbeef;
1150 SetLastError(0xdeadbeef);
1151 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1152 ok(!ret, "Expected failure\n");
1153 ok(needed == 0 || broken(needed != 0), /* nt4 */
1154 "Expected needed buffer size to be set to 0, got %d\n", needed);
1155 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1156 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1157 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1158
1159 needed = 0xdeadbeef;
1160 returned = 0xdeadbeef;
1161 SetLastError(0xdeadbeef);
1162 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1163 ok(!ret, "Expected failure\n");
1164 ok(needed == 0 || broken(needed != 0), /* nt4 */
1165 "Expected needed buffer size to be set to 0, got %d\n", needed);
1166 ok(returned == 0 || broken(returned != 0), /* nt4 */
1167 "Expected number of services to be set to 0, got %d\n", returned);
1168 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1169 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1170
1171 /* No valid servicestate */
1172 needed = 0xdeadbeef;
1173 returned = 0xdeadbeef;
1174 SetLastError(0xdeadbeef);
1175 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1176 ok(!ret, "Expected failure\n");
1177 ok(needed == 0 || broken(needed != 0), /* nt4 */
1178 "Expected needed buffer size to be set to 0, got %d\n", needed);
1179 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1180 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1181 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1182
1183 needed = 0xdeadbeef;
1184 returned = 0xdeadbeef;
1185 SetLastError(0xdeadbeef);
1186 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1187 ok(!ret, "Expected failure\n");
1188 ok(needed == 0 || broken(needed != 0), /* nt4 */
1189 "Expected needed buffer size to be set to 0, got %d\n", needed);
1190 ok(returned == 0 || broken(returned != 0), /* nt4 */
1191 "Expected number of services to be set to 0, got %d\n", returned);
1192 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1193 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1194
1195 /* No valid servicetype */
1196 needed = 0xdeadbeef;
1197 returned = 0xdeadbeef;
1198 SetLastError(0xdeadbeef);
1199 ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1200 ok(!ret, "Expected failure\n");
1201 ok(needed == 0 || broken(needed != 0), /* nt4 */
1202 "Expected needed buffer size to be set to 0, got %d\n", needed);
1203 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1204 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1205 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1206
1207 needed = 0xdeadbeef;
1208 returned = 0xdeadbeef;
1209 SetLastError(0xdeadbeef);
1210 ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1211 ok(!ret, "Expected failure\n");
1212 ok(needed == 0 || broken(needed != 0), /* nt4 */
1213 "Expected needed buffer size to be set to 0, got %d\n", needed);
1214 ok(returned == 0 || broken(returned != 0), /* nt4 */
1215 "Expected number of services to be set to 0, got %d\n", returned);
1216 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1217 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1218
1219 /* All parameters are correct but our access rights are wrong */
1220 needed = 0xdeadbeef;
1221 returned = 0xdeadbeef;
1222 SetLastError(0xdeadbeef);
1223 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1224 ok(!ret, "Expected failure\n");
1225 ok(needed == 0 || broken(needed != 0), /* nt4 */
1226 "Expected needed buffer size to be set to 0, got %d\n", needed);
1227 ok(returned == 0, "Expected number of services to be set to 0, got %d\n", returned);
1228 ok(GetLastError() == ERROR_ACCESS_DENIED,
1229 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1230
1231 needed = 0xdeadbeef;
1232 returned = 0xdeadbeef;
1233 SetLastError(0xdeadbeef);
1234 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1235 ok(!ret, "Expected failure\n");
1236 ok(needed == 0 || broken(needed != 0), /* nt4 */
1237 "Expected needed buffer size to be set to 0, got %d\n", needed);
1238 ok(returned == 0 || broken(returned != 0), /* nt4 */
1239 "Expected number of services to be set to 0, got %d\n", returned);
1240 ok(GetLastError() == ERROR_ACCESS_DENIED,
1241 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1242
1243 /* Open the service control manager with the needed rights */
1244 CloseServiceHandle(scm_handle);
1245 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1246
1247 /* All parameters are correct. Request the needed buffer size */
1248 needed = 0xdeadbeef;
1249 returned = 0xdeadbeef;
1250 SetLastError(0xdeadbeef);
1251 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1252 ok(!ret, "Expected failure\n");
1253 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1254 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1255 ok(GetLastError() == ERROR_MORE_DATA,
1256 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1257
1258 /* Test to show we get the same needed buffer size for the W-call */
1259 neededW = 0xdeadbeef;
1260 returnedW = 0xdeadbeef;
1261 SetLastError(0xdeadbeef);
1262 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededW, &returnedW, NULL);
1263 ok(!ret, "Expected failure\n");
1264 ok(neededW != 0xdeadbeef && neededW > 0, "Expected the needed buffer size for this one service\n");
1265 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1266 ok(returnedW == 0, "Expected no service returned, got %d\n", returnedW);
1267 ok(GetLastError() == ERROR_MORE_DATA,
1268 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1269
1270 /* Store the needed bytes */
1271 tempneeded = needed;
1272
1273 /* Allocate the correct needed bytes */
1274 services = HeapAlloc(GetProcessHeap(), 0, needed);
1275 bufsize = needed;
1276 needed = 0xdeadbeef;
1277 returned = 0xdeadbeef;
1278 SetLastError(0xdeadbeef);
1279 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1280 services, bufsize, &needed, &returned, NULL);
1281 ok(ret, "Expected success, got error %u\n", GetLastError());
1282 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1283 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1284 HeapFree(GetProcessHeap(), 0, services);
1285
1286 /* Store the number of returned services */
1287 tempreturned = returned;
1288
1289 servicesW = HeapAlloc(GetProcessHeap(), 0, neededW);
1290 bufsize = neededW;
1291 neededW = 0xdeadbeef;
1292 returnedW = 0xdeadbeef;
1293 SetLastError(0xdeadbeef);
1294 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1295 servicesW, bufsize, &neededW, &returnedW, NULL);
1296 ok(ret, "Expected success, got error %u\n", GetLastError());
1297 ok(neededW == 0, "Expected needed buffer to be 0 as we are done\n");
1298 ok(returnedW != 0xdeadbeef && returnedW > 0, "Expected some returned services\n");
1299 HeapFree(GetProcessHeap(), 0, servicesW);
1300
1301 /* Allocate less than the needed bytes and don't specify a resume handle */
1302 services = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1303 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1304 needed = 0xdeadbeef;
1305 returned = 0xdeadbeef;
1306 SetLastError(0xdeadbeef);
1307 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1308 services, bufsize, &needed, &returned, NULL);
1309 ok(!ret, "Expected failure\n");
1310 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1311 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1312 ok(GetLastError() == ERROR_MORE_DATA,
1313 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1314
1315 /* Allocate less than the needed bytes, this time with a correct resume handle */
1316 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1317 needed = 0xdeadbeef;
1318 returned = 0xdeadbeef;
1319 resume = 0;
1320 SetLastError(0xdeadbeef);
1321 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1322 services, bufsize, &needed, &returned, &resume);
1323 ok(!ret, "Expected failure\n");
1324 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1325 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1326 todo_wine ok(resume, "Expected a resume handle\n");
1327 ok(GetLastError() == ERROR_MORE_DATA,
1328 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1329
1330 /* Fetch the missing services but pass a bigger buffer size */
1331 missing = tempreturned - returned;
1332 bufsize = tempneeded;
1333 needed = 0xdeadbeef;
1334 returned = 0xdeadbeef;
1335 SetLastError(0xdeadbeef);
1336 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1337 services, bufsize, &needed, &returned, &resume);
1338 ok(ret, "Expected success, got error %u\n", GetLastError());
1339 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1340 ok(returned == missing, "Expected %u services to be returned\n", missing);
1341 ok(resume == 0, "Expected the resume handle to be 0\n");
1342 HeapFree(GetProcessHeap(), 0, services);
1343
1344 /* See if things add up */
1345
1346 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1347 * and doesn't count the others as inactive. This means that Vista could
1348 * show a total that is greater than the sum of active and inactive
1349 * drivers.
1350 * The number of active and inactive drivers is greatly influenced by the
1351 * time when tests are run, immediately after boot or later for example.
1352 *
1353 * Both reasons make calculations for drivers not so useful
1354 */
1355
1356 /* Get the number of active win32 services */
1357 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
1358 &needed, &returned, NULL);
1359 services = HeapAlloc(GetProcessHeap(), 0, needed);
1360 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, services,
1361 needed, &needed, &returned, NULL);
1362 HeapFree(GetProcessHeap(), 0, services);
1363
1364 servicecountactive = returned;
1365
1366 /* Get the number of inactive win32 services */
1367 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
1368 &needed, &returned, NULL);
1369 services = HeapAlloc(GetProcessHeap(), 0, needed);
1370 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, services,
1371 needed, &needed, &returned, NULL);
1372 HeapFree(GetProcessHeap(), 0, services);
1373
1374 servicecountinactive = returned;
1375
1376 /* Get the number of win32 services */
1377 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
1378 &needed, &returned, NULL);
1379 services = HeapAlloc(GetProcessHeap(), 0, needed);
1380 EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, services,
1381 needed, &needed, &returned, NULL);
1382 HeapFree(GetProcessHeap(), 0, services);
1383
1384 /* Check if total is the same as active and inactive win32 services */
1385 ok(returned == (servicecountactive + servicecountinactive),
1386 "Something wrong in the calculation\n");
1387
1388 /* Get all drivers and services
1389 *
1390 * Fetch the status of the last call as failing could make the following tests crash
1391 * on Wine (we don't return anything yet).
1392 */
1393 EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1394 NULL, 0, &needed, &returned, NULL);
1395 services = HeapAlloc(GetProcessHeap(), 0, needed);
1396 ret = EnumServicesStatusA(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1397 services, needed, &needed, &returned, NULL);
1398
1399 /* Loop through all those returned drivers and services */
1400 for (i = 0; ret && i < returned; i++)
1401 {
1402 SERVICE_STATUS status = services[i].ServiceStatus;
1403
1404 /* lpServiceName and lpDisplayName should always be filled */
1405 ok(services[i].lpServiceName[0], "Expected a service name\n");
1406 ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n");
1407
1408 /* Decrement the counters to see if the functions calls return the same
1409 * numbers as the contents of these structures.
1410 */
1411 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1412 {
1413 if (status.dwCurrentState == SERVICE_STOPPED)
1414 servicecountinactive--;
1415 else
1416 servicecountactive--;
1417 }
1418 }
1419 HeapFree(GetProcessHeap(), 0, services);
1420
1421 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1422 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1423
1424 CloseServiceHandle(scm_handle);
1425
1426 /* More or less the same for EnumServicesStatusExA */
1427 if (!pEnumServicesStatusExA)
1428 {
1429 win_skip( "EnumServicesStatusExA not available\n" );
1430 return;
1431 }
1432
1433 /* All NULL or wrong */
1434 SetLastError(0xdeadbeef);
1435 ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1436 ok(!ret, "Expected failure\n");
1437 ok(GetLastError() == ERROR_INVALID_LEVEL,
1438 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1439
1440 /* All NULL or wrong, just the info level is correct */
1441 SetLastError(0xdeadbeef);
1442 ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1443 ok(!ret, "Expected failure\n");
1444 ok(GetLastError() == ERROR_INVALID_HANDLE,
1445 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1446
1447 /* Open the service control manager with not enough rights at first */
1448 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1449
1450 /* Valid handle and info level but rest is still NULL or wrong */
1451 SetLastError(0xdeadbeef);
1452 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1453 ok(!ret, "Expected failure\n");
1454 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1455 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1456 "Unexpected last error %d\n", GetLastError());
1457
1458 /* Don't specify the two required pointers */
1459 needed = 0xdeadbeef;
1460 SetLastError(0xdeadbeef);
1461 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1462 ok(!ret, "Expected failure\n");
1463 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1464 "Expected no change to the needed buffer variable\n");
1465 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1466 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1467 "Unexpected last error %d\n", GetLastError());
1468
1469 /* Don't specify the two required pointers */
1470 returned = 0xdeadbeef;
1471 SetLastError(0xdeadbeef);
1472 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1473 ok(!ret, "Expected failure\n");
1474 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1475 ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1476 GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1477 "Unexpected last error %d\n", GetLastError());
1478
1479 /* No valid servicetype and servicestate */
1480 needed = 0xdeadbeef;
1481 returned = 0xdeadbeef;
1482 SetLastError(0xdeadbeef);
1483 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1484 ok(!ret, "Expected failure\n");
1485 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1486 ok(needed == 0 || broken(needed != 0), /* nt4 */
1487 "Expected needed buffer size to be set to 0, got %d\n", needed);
1488 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1489 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1490
1491 /* No valid servicestate */
1492 needed = 0xdeadbeef;
1493 returned = 0xdeadbeef;
1494 SetLastError(0xdeadbeef);
1495 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1496 &needed, &returned, NULL, NULL);
1497 ok(!ret, "Expected failure\n");
1498 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1499 ok(needed == 0 || broken(needed != 0), /* nt4 */
1500 "Expected needed buffer size to be set to 0, got %d\n", needed);
1501 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1502 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1503
1504 /* No valid servicetype */
1505 needed = 0xdeadbeef;
1506 returned = 0xdeadbeef;
1507 SetLastError(0xdeadbeef);
1508 ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1509 &needed, &returned, NULL, NULL);
1510 ok(!ret, "Expected failure\n");
1511 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1512 ok(needed == 0 || broken(needed != 0), /* nt4 */
1513 "Expected needed buffer size to be set to 0, got %d\n", needed);
1514 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1515 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1516
1517 /* No valid servicetype and servicestate and unknown service group */
1518 needed = 0xdeadbeef;
1519 returned = 0xdeadbeef;
1520 SetLastError(0xdeadbeef);
1521 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1522 &returned, NULL, "deadbeef_group");
1523 ok(!ret, "Expected failure\n");
1524 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1525 ok(needed == 0 || broken(needed != 0), /* nt4 */
1526 "Expected needed buffer size to be set to 0, got %d\n", needed);
1527 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1528 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1529
1530 /* All parameters are correct but our access rights are wrong */
1531 needed = 0xdeadbeef;
1532 returned = 0xdeadbeef;
1533 SetLastError(0xdeadbeef);
1534 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1535 NULL, 0, &needed, &returned, NULL, NULL);
1536 ok(!ret, "Expected failure\n");
1537 ok(needed == 0 || broken(needed != 0), /* nt4 */
1538 "Expected needed buffer size to be set to 0, got %d\n", needed);
1539 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1540 ok(GetLastError() == ERROR_ACCESS_DENIED,
1541 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1542
1543 /* All parameters are correct, access rights are wrong but the
1544 * group name won't be checked yet.
1545 */
1546 needed = 0xdeadbeef;
1547 returned = 0xdeadbeef;
1548 SetLastError(0xdeadbeef);
1549 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1550 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1551 ok(!ret, "Expected failure\n");
1552 ok(needed == 0 || broken(needed != 0), /* nt4 */
1553 "Expected needed buffer size to be set to 0, got %d\n", needed);
1554 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1555 ok(GetLastError() == ERROR_ACCESS_DENIED,
1556 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1557
1558 /* Open the service control manager with the needed rights */
1559 CloseServiceHandle(scm_handle);
1560 scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1561
1562 /* All parameters are correct and the group will be checked */
1563 needed = 0xdeadbeef;
1564 returned = 0xdeadbeef;
1565 SetLastError(0xdeadbeef);
1566 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1567 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1568 ok(!ret, "Expected failure\n");
1569 ok(returned == 0, "Expected number of service to be set to 0, got %d\n", returned);
1570 ok(needed == 0, "Expected needed buffer size to be set to 0, got %d\n", needed);
1571 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
1572 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1573
1574 /* TODO: Create a test that makes sure we enumerate all services that don't
1575 * belong to a group. (specifying "").
1576 */
1577
1578 /* All parameters are correct. Request the needed buffer size */
1579 needed = 0xdeadbeef;
1580 returned = 0xdeadbeef;
1581 SetLastError(0xdeadbeef);
1582 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1583 NULL, 0, &needed, &returned, NULL, NULL);
1584 ok(!ret, "Expected failure\n");
1585 ok(returned == 0, "Expected no service returned, got %d\n", returned);
1586 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1587 ok(GetLastError() == ERROR_MORE_DATA,
1588 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1589
1590 /* Test to show we get the same needed buffer size for the W-call */
1591 neededW = 0xdeadbeef;
1592 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1593 NULL, 0, &neededW, &returnedW, NULL, NULL);
1594 ok(!ret, "Expected failure\n");
1595 ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1596
1597 /* Store the needed bytes */
1598 tempneeded = needed;
1599
1600 /* Allocate the correct needed bytes */
1601 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1602 bufsize = needed;
1603 needed = 0xdeadbeef;
1604 returned = 0xdeadbeef;
1605 SetLastError(0xdeadbeef);
1606 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1607 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1608 ok(ret, "Expected success, got error %u\n", GetLastError());
1609 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1610 ok(returned == tempreturned, "Expected the same number of service from this function\n");
1611 HeapFree(GetProcessHeap(), 0, exservices);
1612
1613 /* Store the number of returned services */
1614 tempreturned = returned;
1615
1616 /* Allocate less than the needed bytes and don't specify a resume handle */
1617 exservices = HeapAlloc(GetProcessHeap(), 0, tempneeded);
1618 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1619 needed = 0xdeadbeef;
1620 returned = 0xdeadbeef;
1621 SetLastError(0xdeadbeef);
1622 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1623 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1624 ok(!ret, "Expected failure\n");
1625 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1626 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1627 ok(GetLastError() == ERROR_MORE_DATA,
1628 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1629
1630 /* Allocate less than the needed bytes, this time with a correct resume handle */
1631 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSA);
1632 needed = 0xdeadbeef;
1633 returned = 0xdeadbeef;
1634 resume = 0;
1635 SetLastError(0xdeadbeef);
1636 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1637 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1638 ok(!ret, "Expected failure\n");
1639 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1640 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1641 todo_wine ok(resume, "Expected a resume handle\n");
1642 ok(GetLastError() == ERROR_MORE_DATA,
1643 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1644
1645 /* Fetch that last service but pass a bigger buffer size */
1646 missing = tempreturned - returned;
1647 bufsize = tempneeded;
1648 needed = 0xdeadbeef;
1649 returned = 0xdeadbeef;
1650 SetLastError(0xdeadbeef);
1651 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1652 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1653 ok(ret, "Expected success, got error %u\n", GetLastError());
1654 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1655 ok(returned == missing, "Expected %u services to be returned\n", missing);
1656 ok(resume == 0, "Expected the resume handle to be 0\n");
1657 HeapFree(GetProcessHeap(), 0, exservices);
1658
1659 /* See if things add up */
1660
1661 /* Get the number of active win32 services */
1662 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1663 NULL, 0, &needed, &returned, NULL, NULL);
1664 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1665 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1666 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1667 HeapFree(GetProcessHeap(), 0, exservices);
1668
1669 servicecountactive = returned;
1670
1671 /* Get the number of inactive win32 services */
1672 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1673 NULL, 0, &needed, &returned, NULL, NULL);
1674 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1675 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1676 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1677 HeapFree(GetProcessHeap(), 0, exservices);
1678
1679 servicecountinactive = returned;
1680
1681 /* Get the number of win32 services */
1682 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1683 NULL, 0, &needed, &returned, NULL, NULL);
1684 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1685 pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1686 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1687 HeapFree(GetProcessHeap(), 0, exservices);
1688
1689 /* Check if total is the same as active and inactive win32 services */
1690 ok(returned == (servicecountactive + servicecountinactive),
1691 "Something wrong in the calculation\n");
1692
1693 /* Get all drivers and services */
1694 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1695 SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1696 ok(!ret, "Expected failure\n");
1697 exservices = HeapAlloc(GetProcessHeap(), 0, needed);
1698 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1699 SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1700 ok(ret, "Expected success %u\n", GetLastError());
1701
1702 /* Loop through all those returned drivers and services */
1703 for (i = 0; i < returned; i++)
1704 {
1705 SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
1706
1707 /* lpServiceName and lpDisplayName should always be filled */
1708 ok(exservices[i].lpServiceName[0], "Expected a service name\n");
1709 ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n");
1710
1711 /* Decrement the counters to see if the functions calls return the
1712 * same numbers as the contents of these structures.
1713 * Check some process id specifics.
1714 */
1715 if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
1716 {
1717 /* We shouldn't have a process id for drivers */
1718 ok(status.dwProcessId == 0,
1719 "This driver shouldn't have an associated process id\n");
1720 }
1721
1722 if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1723 {
1724 if (status.dwCurrentState != SERVICE_STOPPED)
1725 {
1726 /* We expect a process id for every running service */
1727 ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1728 exservices[i].lpServiceName);
1729
1730 servicecountactive--;
1731 }
1732 else
1733 {
1734 /* We shouldn't have a process id for inactive services */
1735 ok(status.dwProcessId == 0, "Service %s state %u shouldn't have an associated process id\n",
1736 exservices[i].lpServiceName, status.dwCurrentState);
1737
1738 servicecountinactive--;
1739 }
1740 }
1741 }
1742 HeapFree(GetProcessHeap(), 0, exservices);
1743
1744 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1745 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1746
1747 CloseServiceHandle(scm_handle);
1748 }
1749
1750 static void test_close(void)
1751 {
1752 SC_HANDLE handle;
1753 BOOL ret;
1754
1755 /* NULL handle */
1756 SetLastError(0xdeadbeef);
1757 ret = CloseServiceHandle(NULL);
1758 ok(!ret, "Expected failure\n");
1759 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1760
1761 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1762
1763 /* Proper call */
1764 handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1765 SetLastError(0xdeadbeef);
1766 ret = CloseServiceHandle(handle);
1767 ok(ret, "Expected success got error %u\n", GetLastError());
1768 }
1769
1770 static void test_sequence(void)
1771 {
1772 SC_HANDLE scm_handle, svc_handle;
1773 BOOL ret, is_nt4;
1774 QUERY_SERVICE_CONFIGA *config;
1775 DWORD given, needed;
1776 static const CHAR servicename [] = "Winetest";
1777 static const CHAR displayname [] = "Winetest dummy service";
1778 static const CHAR displayname2[] = "Winetest dummy service (2)";
1779 static const CHAR pathname [] = "we_dont_care.exe";
1780 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
1781 static const CHAR password [] = "";
1782 static const CHAR empty [] = "";
1783 static const CHAR localsystem [] = "LocalSystem";
1784
1785 SetLastError(0xdeadbeef);
1786 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
1787
1788 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1789 {
1790 skip("Not enough rights to get a handle to the manager\n");
1791 return;
1792 }
1793 else
1794 ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
1795
1796 if (!scm_handle) return;
1797 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
1798 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
1799 CloseServiceHandle(svc_handle);
1800
1801 /* Create a dummy service */
1802 SetLastError(0xdeadbeef);
1803 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
1804 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
1805 pathname, NULL, NULL, dependencies, NULL, password);
1806
1807 if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
1808 {
1809 /* We try and open the service and do the rest of the tests. Some could
1810 * fail if the tests were changed between these runs.
1811 */
1812 trace("Deletion probably didn't work last time\n");
1813 SetLastError(0xdeadbeef);
1814 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
1815 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1816 {
1817 skip("Not enough rights to open the service\n");
1818 CloseServiceHandle(scm_handle);
1819 return;
1820 }
1821 ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
1822 }
1823 else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
1824 {
1825 skip("Not enough rights to create the service\n");
1826 CloseServiceHandle(scm_handle);
1827 return;
1828 }
1829 else
1830 {
1831 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
1832 if ((svc_handle != NULL) && (pGetSecurityInfo != NULL))
1833 {
1834 PSID sidOwner, sidGroup;
1835 PACL dacl, sacl;
1836 PSECURITY_DESCRIPTOR pSD;
1837 DWORD error, n1, n2;
1838 HRESULT retval;
1839 BOOL bret;
1840
1841 /* Test using GetSecurityInfo to obtain security information */
1842 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
1843 &sidGroup, &dacl, &sacl, &pSD);
1844 LocalFree(pSD);
1845 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1846 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1847 NULL, NULL, NULL, &pSD);
1848 LocalFree(pSD);
1849 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1850 if (!is_nt4)
1851 {
1852 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1853 NULL, &dacl, NULL, &pSD);
1854 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %d\n", retval);
1855 LocalFree(pSD);
1856 SetLastError(0xdeadbeef);
1857 retval = pGetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
1858 NULL, NULL, NULL, NULL);
1859 error = GetLastError();
1860 ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %d\n", retval);
1861 ok(error == 0xdeadbeef, "Unexpected last error %d\n", error);
1862 }
1863 else
1864 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1865
1866 /* Test using QueryServiceObjectSecurity to obtain security information */
1867 SetLastError(0xdeadbeef);
1868 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
1869 error = GetLastError();
1870 ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
1871 ok(error == ERROR_INSUFFICIENT_BUFFER ||
1872 broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER),
1873 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error);
1874 if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
1875 pSD = LocalAlloc(0, n1);
1876 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
1877 ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
1878 LocalFree(pSD);
1879 }
1880 }
1881
1882 if (!svc_handle) {
1883 CloseServiceHandle(scm_handle);
1884 return;
1885 }
1886
1887 /* TODO:
1888 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1889 * that the correct keys are used.
1890 */
1891
1892 /* Request the size for the buffer */
1893 SetLastError(0xdeadbeef);
1894 ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
1895 ok(!ret, "Expected failure\n");
1896 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1897
1898 config = HeapAlloc(GetProcessHeap(), 0, needed);
1899 given = needed;
1900 SetLastError(0xdeadbeef);
1901 ret = QueryServiceConfigA(svc_handle, config, given, &needed);
1902 ok(ret, "Expected success, got error %u\n", GetLastError());
1903
1904 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
1905 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
1906 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
1907 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
1908 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
1909 ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
1910 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
1911 ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
1912 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
1913 /* TODO: Show the double 0 terminated string */
1914 todo_wine
1915 {
1916 ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
1917 }
1918 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
1919 ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
1920
1921 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2",
1922 NULL, NULL, NULL, NULL, displayname2);
1923 ok(ret, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
1924
1925 QueryServiceConfigA(svc_handle, NULL, 0, &needed);
1926 config = HeapReAlloc(GetProcessHeap(), 0, config, needed);
1927 ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
1928 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
1929 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
1930 ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
1931 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
1932 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
1933 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %d\n", config->dwErrorControl);
1934 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
1935 ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
1936 ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
1937 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
1938 ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
1939
1940 SetLastError(0xdeadbeef);
1941 ret = DeleteService(svc_handle);
1942 ok(ret, "Expected success, got error %u\n", GetLastError());
1943 CloseServiceHandle(svc_handle);
1944
1945 /* Wait a while. The following test does a CreateService again */
1946 Sleep(1000);
1947
1948 CloseServiceHandle(scm_handle);
1949 HeapFree(GetProcessHeap(), 0, config);
1950 }
1951
1952 static void test_queryconfig2(void)
1953 {
1954 SC_HANDLE scm_handle, svc_handle;
1955 BOOL ret;
1956 DWORD expected, needed;
1957 BYTE buffer[MAX_PATH];
1958 LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
1959 LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
1960 SERVICE_PRESHUTDOWN_INFO preshutdown_info;
1961 static const CHAR servicename [] = "Winetest";
1962 static const CHAR displayname [] = "Winetest dummy service";
1963 static const CHAR pathname [] = "we_dont_care.exe";
1964 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
1965 static const CHAR password [] = "";
1966 static const CHAR description [] = "Description";
1967 static const CHAR description_empty[] = "";
1968 static const WCHAR descriptionW [] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
1969 static const WCHAR descriptionW_empty[] = {0};
1970
1971 if(!pQueryServiceConfig2A)
1972 {
1973 win_skip("function QueryServiceConfig2A not present\n");
1974 return;
1975 }
1976
1977 SetLastError(0xdeadbeef);
1978 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
1979
1980 if (!scm_handle)
1981 {
1982 if(GetLastError() == ERROR_ACCESS_DENIED)
1983 skip("Not enough rights to get a handle to the manager\n");
1984 else
1985 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
1986 return;
1987 }
1988
1989 /* Create a dummy service */
1990 SetLastError(0xdeadbeef);
1991 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
1992 SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
1993 pathname, NULL, NULL, dependencies, NULL, password);
1994
1995 if (!svc_handle)
1996 {
1997 if(GetLastError() == ERROR_SERVICE_EXISTS)
1998 {
1999 /* We try and open the service and do the rest of the tests. Some could
2000 * fail if the tests were changed between these runs.
2001 */
2002 trace("Deletion probably didn't work last time\n");
2003 SetLastError(0xdeadbeef);
2004 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2005 if (!svc_handle)
2006 {
2007 if(GetLastError() == ERROR_ACCESS_DENIED)
2008 skip("Not enough rights to open the service\n");
2009 else
2010 ok(FALSE, "Could not open the service : %d\n", GetLastError());
2011 CloseServiceHandle(scm_handle);
2012 return;
2013 }
2014 }
2015 if (GetLastError() == ERROR_ACCESS_DENIED)
2016 {
2017 skip("Not enough rights to create the service\n");
2018 CloseServiceHandle(scm_handle);
2019 return;
2020 }
2021 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
2022 if (!svc_handle)
2023 {
2024 CloseServiceHandle(scm_handle);
2025 return;
2026 }
2027 }
2028 SetLastError(0xdeadbeef);
2029 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2030 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2031 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2032
2033 SetLastError(0xdeadbeef);
2034 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2035 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2036 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2037
2038 SetLastError(0xdeadbeef);
2039 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2040 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2041 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2042
2043 SetLastError(0xdeadbeef);
2044 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2045 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2046 ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
2047 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2048
2049 SetLastError(0xdeadbeef);
2050 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2051 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2052 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2053
2054 needed = 0;
2055 SetLastError(0xdeadbeef);
2056 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2057 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2058 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2059 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2060
2061 needed = 0;
2062 pConfig->lpDescription = (LPSTR)0xdeadbeef;
2063 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2064 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2065 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2066 ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2067
2068 SetLastError(0xdeadbeef);
2069 needed = 0;
2070 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2071 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2072 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2073 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %d\n", needed);
2074
2075 if(!pChangeServiceConfig2A)
2076 {
2077 win_skip("function ChangeServiceConfig2A not present\n");
2078 goto cleanup;
2079 }
2080
2081 pConfig->lpDescription = (LPSTR) description;
2082 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2083 ok(ret, "ChangeServiceConfig2A failed\n");
2084 if (!ret) {
2085 goto cleanup;
2086 }
2087
2088 SetLastError(0xdeadbeef);
2089 needed = 0;
2090 expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2091 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2092 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2093 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2094 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2095
2096 SetLastError(0xdeadbeef);
2097 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2098 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2099 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2100
2101 SetLastError(0xdeadbeef);
2102 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2103 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2104 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2105 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2106
2107 SetLastError(0xdeadbeef);
2108 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2109 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2110 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2111 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2112
2113 if(!pQueryServiceConfig2W)
2114 {
2115 win_skip("function QueryServiceConfig2W not present\n");
2116 goto cleanup;
2117 }
2118 SetLastError(0xdeadbeef);
2119 needed = 0;
2120 expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2121 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2122 ok(!ret, "expected QueryServiceConfig2W to fail\n");
2123 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2124 ok(needed == expected, "expected needed to be %d, got %d\n", expected, needed);
2125
2126 SetLastError(0xdeadbeef);
2127 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2128 ok(ret, "expected QueryServiceConfig2W to succeed\n");
2129
2130 pConfig->lpDescription = (LPSTR)description;
2131 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2132 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2133
2134 pConfig->lpDescription = NULL;
2135 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2136 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2137 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2138 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2139
2140 pConfig->lpDescription = NULL;
2141 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2142 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2143
2144 pConfig->lpDescription = NULL;
2145 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2146 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2147 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2148 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2149
2150 pConfig->lpDescription = (LPSTR)description_empty;
2151 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2152 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2153
2154 pConfig->lpDescription = (void*)0xdeadbeef;
2155 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2156 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2157 ok(!pConfig->lpDescription,
2158 "expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2159
2160 pConfigW->lpDescription = (LPWSTR)descriptionW;
2161 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2162 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2163
2164 pConfigW->lpDescription = NULL;
2165 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2166 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2167 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2168 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2169
2170 pConfigW->lpDescription = NULL;
2171 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2172 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2173
2174 pConfigW->lpDescription = NULL;
2175 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2176 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2177 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2178 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2179
2180 pConfigW->lpDescription = (LPWSTR)descriptionW_empty;
2181 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2182 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2183
2184 pConfigW->lpDescription = (void*)0xdeadbeef;
2185 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2186 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2187 ok(!pConfigW->lpDescription,
2188 "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2189
2190 SetLastError(0xdeadbeef);
2191 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2192 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2193 if(!ret && GetLastError()==ERROR_INVALID_LEVEL)
2194 {
2195 /* Win2k3 and older */
2196 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2197 goto cleanup;
2198 }
2199 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2200 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2201 ok(preshutdown_info.dwPreshutdownTimeout == 180000, "Default PreshutdownTimeout = %d\n",
2202 preshutdown_info.dwPreshutdownTimeout);
2203
2204 SetLastError(0xdeadbeef);
2205 preshutdown_info.dwPreshutdownTimeout = -1;
2206 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2207 (LPVOID)&preshutdown_info);
2208 ok(ret, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2209
2210 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2211 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2212 ok(ret, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2213 ok(needed == sizeof(preshutdown_info), "needed = %d\n", needed);
2214 ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %d\n",
2215 preshutdown_info.dwPreshutdownTimeout);
2216
2217 cleanup:
2218 DeleteService(svc_handle);
2219
2220 CloseServiceHandle(svc_handle);
2221
2222 /* Wait a while. The following test does a CreateService again */
2223 Sleep(1000);
2224
2225 CloseServiceHandle(scm_handle);
2226 }
2227
2228 static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2229 {
2230 BOOL ret;
2231 DWORD le1, le2;
2232 SERVICE_STATUS status;
2233
2234 #ifdef __REACTOS__
2235 fprintf(stdout, "ROSTESTS-56: Hello sysreg, I am awake\n");
2236 #endif
2237 ret = StartServiceA(svc_handle, 0, NULL);
2238 le1 = GetLastError();
2239 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2240
2241 if (pQueryServiceStatusEx)
2242 {
2243 DWORD needed;
2244 SERVICE_STATUS_PROCESS statusproc;
2245
2246 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2247 ok(ret, "%s: QueryServiceStatusEx() failed le=%u\n", name, GetLastError());
2248 ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%x\n", name, statusproc.dwCurrentState);
2249 ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %x\n", name, statusproc.dwProcessId);
2250 }
2251
2252 ret = StartServiceA(svc_handle, 0, NULL);
2253 le2 = GetLastError();
2254 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2255 ok(le2 == le1, "%s: the second try should yield the same error: %u != %u\n", name, le1, le2);
2256
2257 status.dwCurrentState = 0xdeadbeef;
2258 ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status);
2259 le2 = GetLastError();
2260 ok(!ret, "%s: ControlService() should have failed\n", name);
2261 ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2262 ok(status.dwCurrentState == SERVICE_STOPPED ||
2263 broken(is_nt4), /* NT4 returns a random value */
2264 "%s: should be stopped state=%x\n", name, status.dwCurrentState);
2265
2266 return le1;
2267 }
2268
2269 #define PHASE_STOPPED 1
2270 #define PHASE_RUNNING 2
2271
2272 struct notify_data {
2273 SERVICE_NOTIFYW notify;
2274 SC_HANDLE svc;
2275 BOOL was_called;
2276 DWORD phase;
2277 };
2278
2279 static void CALLBACK notify_cb(void *user)
2280 {
2281 struct notify_data *data = user;
2282 switch (data->phase)
2283 {
2284 case PHASE_STOPPED:
2285 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2286 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2287 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2288 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2289 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2290 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2291 break;
2292
2293 case PHASE_RUNNING:
2294 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2295 "Got wrong notification status: %u\n", data->notify.dwNotificationStatus);
2296 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2297 "Got wrong service state: 0x%x\n", data->notify.ServiceStatus.dwCurrentState);
2298 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2299 "Got wrong notification triggered: 0x%x\n", data->notify.dwNotificationTriggered);
2300 break;
2301 }
2302
2303 data->was_called = TRUE;
2304 }
2305
2306 static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
2307 {
2308 DWORD dr, dr2;
2309 struct notify_data data;
2310 struct notify_data data2;
2311 BOOL br;
2312 SERVICE_STATUS status;
2313 HANDLE svc, svc2;
2314
2315 if(!pNotifyServiceStatusChangeW){
2316 win_skip("No NotifyServiceStatusChangeW\n");
2317 return;
2318 }
2319
2320 svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2321 svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2322 ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2323 if(!svc || !svc2)
2324 return;
2325
2326 /* receive stopped notification, then start service */
2327 memset(&data.notify, 0, sizeof(data.notify));
2328 data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2329 data.notify.pfnNotifyCallback = &notify_cb;
2330 data.notify.pContext = &data;
2331 data.svc = svc;
2332 data.phase = PHASE_STOPPED;
2333 data.was_called = FALSE;
2334
2335 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2336 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2337
2338 dr = SleepEx(100, TRUE);
2339 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2340 ok(data.was_called == TRUE, "APC wasn't called\n");
2341
2342 br = StartServiceA(svc, 0, NULL);
2343 ok(br, "StartService failed: %u\n", GetLastError());
2344
2345 /* receive running notification */
2346 data.phase = PHASE_RUNNING;
2347 data.was_called = FALSE;
2348
2349 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2350 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2351
2352 dr = SleepEx(100, TRUE);
2353 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2354 ok(data.was_called == TRUE, "APC wasn't called\n");
2355
2356 /* cannot register two notifications */
2357 data.phase = PHASE_STOPPED;
2358 data.was_called = FALSE;
2359
2360 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2361 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2362
2363 memset(&data2.notify, 0, sizeof(data2.notify));
2364 data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2365 data2.notify.pfnNotifyCallback = &notify_cb;
2366 data2.notify.pContext = &data2;
2367
2368 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2369 ok(dr == ERROR_SUCCESS || /* win8+ */
2370 dr == ERROR_ALREADY_REGISTERED, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr);
2371
2372 /* should receive no notification because status has not changed.
2373 * on win8+, SleepEx quits early but the callback is still not invoked. */
2374 dr2 = SleepEx(100, TRUE);
2375 ok((dr == ERROR_SUCCESS && dr2 == WAIT_IO_COMPLETION) || /* win8+ */
2376 (dr == ERROR_ALREADY_REGISTERED && dr2 == 0), "Got wrong SleepEx result: %u\n", dr);
2377 ok(data.was_called == FALSE, "APC should not have been called\n");
2378
2379 /* stop service and receive notifiction */
2380 br = ControlService(svc, SERVICE_CONTROL_STOP, &status);
2381 ok(br, "ControlService failed: %u\n", GetLastError());
2382
2383 dr = SleepEx(100, TRUE);
2384 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
2385 ok(data.was_called == TRUE, "APC wasn't called\n");
2386
2387 /* test cancelation: create notify on svc that will block until service
2388 * start; close svc; start service on svc2; verify that notification does
2389 * not happen */
2390
2391 data.phase = PHASE_RUNNING;
2392 data.was_called = FALSE;
2393 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2394 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %u\n", dr);
2395
2396 CloseServiceHandle(svc);
2397
2398 br = StartServiceA(svc2, 0, NULL);
2399 ok(br, "StartService failed: %u\n", GetLastError());
2400
2401 dr = SleepEx(100, TRUE);
2402 ok(dr == 0, "Got wrong SleepEx result: %u\n", dr);
2403 ok(data.was_called == FALSE, "APC should not have been called\n");
2404
2405 br = ControlService(svc2, SERVICE_CONTROL_STOP, &status);
2406 ok(br, "ControlService failed: %u\n", GetLastError());
2407
2408 CloseServiceHandle(svc2);
2409 }
2410
2411 static void test_start_stop(void)
2412 {
2413 BOOL ret;
2414 SC_HANDLE scm_handle, svc_handle;
2415 DWORD le, is_nt4;
2416 static const char servicename[] = "Winetest";
2417 char cmd[MAX_PATH+20];
2418 const char* displayname;
2419
2420 SetLastError(0xdeadbeef);
2421 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2422 if (!scm_handle)
2423 {
2424 if(GetLastError() == ERROR_ACCESS_DENIED)
2425 skip("Not enough rights to get a handle to the manager\n");
2426 else
2427 ok(FALSE, "Could not get a handle to the manager: %d\n", GetLastError());
2428 return;
2429 }
2430
2431 /* Detect NT4 */
2432 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2433 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2434
2435 /* Do some cleanup in case a previous run crashed */
2436 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2437 if (svc_handle)
2438 {
2439 DeleteService(svc_handle);
2440 CloseServiceHandle(svc_handle);
2441 }
2442
2443 /* Create a dummy disabled service */
2444 sprintf(cmd, "\"%s\" service exit", selfname);
2445 displayname = "Winetest Disabled Service";
2446 svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2447 GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,
2448 SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL,
2449 NULL, NULL, NULL, NULL);
2450 if (!svc_handle)
2451 {
2452 if(GetLastError() == ERROR_ACCESS_DENIED)
2453 skip("Not enough rights to create the service\n");
2454 else
2455 ok(FALSE, "Could not create the service: %d\n", GetLastError());
2456 goto cleanup;
2457 }
2458 le = try_start_stop(svc_handle, displayname, is_nt4);
2459 ok(le == ERROR_SERVICE_DISABLED, "%d != ERROR_SERVICE_DISABLED\n", le);
2460
2461 /* Then one with a bad path */
2462 displayname = "Winetest Bad Path";
2463 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2464 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2465 try_start_stop(svc_handle, displayname, is_nt4);
2466
2467 if (is_nt4)
2468 {
2469 /* NT4 does not detect when a service fails to start and uses an
2470 * insanely long timeout: 120s. So skip the rest of the tests.
2471 */
2472 win_skip("Skip some service start/stop tests on NT4\n");
2473 goto cleanup;
2474 }
2475
2476 if (!winetest_interactive)
2477 {
2478 skip("ROSTESTS-151: Skipping service start timeout tests because they take too long. This is not a bug!\n");
2479 goto cleanup;
2480 }
2481
2482 /* Again with a process that exits right away */
2483 displayname = "Winetest Exit Service";
2484 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2485 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2486 le = try_start_stop(svc_handle, displayname, is_nt4);
2487 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2488
2489 /* create a real service and test notifications */
2490 sprintf(cmd, "%s service serve", selfname);
2491 displayname = "Winetest Service";
2492 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2493 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2494 test_servicenotify(scm_handle, servicename);
2495
2496 cleanup:
2497 if (svc_handle)
2498 {
2499 DeleteService(svc_handle);
2500 CloseServiceHandle(svc_handle);
2501 }
2502
2503 /* Wait a while. The following test does a CreateService again */
2504 Sleep(1000);
2505
2506 CloseServiceHandle(scm_handle);
2507 }
2508
2509 static void test_refcount(void)
2510 {
2511 SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2512 static const CHAR servicename [] = "Winetest";
2513 static const CHAR pathname [] = "we_dont_care.exe";
2514 BOOL ret;
2515
2516 /* Get a handle to the Service Control Manager */
2517 SetLastError(0xdeadbeef);
2518 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2519 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2520 {
2521 skip("Not enough rights to get a handle to the manager\n");
2522 return;
2523 }
2524
2525 /* Create a service */
2526 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2527 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2528 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2529 ok(svc_handle1 != NULL, "Expected success, got error %u\n", GetLastError());
2530
2531 /* Get a handle to this new service */
2532 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2533 ok(svc_handle2 != NULL, "Expected success, got error %u\n", GetLastError());
2534
2535 /* Get another handle to this new service */
2536 svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2537 ok(svc_handle3 != NULL, "Expected success, got error %u\n", GetLastError());
2538
2539 /* Check if we can close the handle to the Service Control Manager */
2540 ret = CloseServiceHandle(scm_handle);
2541 ok(ret, "Expected success (err=%d)\n", GetLastError());
2542
2543 /* Get a new handle to the Service Control Manager */
2544 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2545 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
2546
2547 /* Get a handle to this new service */
2548 svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2549 ok(svc_handle4 != NULL, "Expected success, got error %u\n", GetLastError());
2550
2551 /* Delete the service */
2552 ret = DeleteService(svc_handle4);
2553 ok(ret, "Expected success (err=%d)\n", GetLastError());
2554
2555 /* We cannot create the same service again as it's still marked as 'being deleted'.
2556 * The reason is that we still have 4 open handles to this service even though we
2557 * closed the handle to the Service Control Manager in between.
2558 */
2559 SetLastError(0xdeadbeef);
2560 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2561 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2562 SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2563 ok(!svc_handle5, "Expected failure\n");
2564 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
2565 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2566
2567 /* Close all the handles to the service and try again */
2568 ret = CloseServiceHandle(svc_handle4);
2569 ok(ret, "Expected success (err=%d)\n", GetLastError());
2570 ret = CloseServiceHandle(svc_handle3);
2571 ok(ret, "Expected success (err=%d)\n", GetLastError());
2572 ret = CloseServiceHandle(svc_handle2);
2573 ok(ret, "Expected success (err=%d)\n", GetLastError());
2574 ret = CloseServiceHandle(svc_handle1);