ReactOS 0.4.15-dev-7788-g1ad9096
service.c
Go to the documentation of this file.
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
35static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
37
38static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
39static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
40static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
43static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
48static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
49static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
50static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
51 DWORD, LPDWORD);
52static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
54static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*);
55
56static 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
72static void test_open_scm(void)
73{
74 SC_HANDLE scm_handle;
75
76 /* No access rights */
77 SetLastError(0xdeadbeef);
79 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
81
82 /* Unknown database name */
83 SetLastError(0xdeadbeef);
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);
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);
100 {
101 ok(!scm_handle, "Expected failure\n");
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 */
109 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
111
112 /* Again a correct one */
113 SetLastError(0xdeadbeef);
116 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
117 ok(scm_handle != NULL, "Expected success, got error %u\n", GetLastError());
119}
120
121static 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 */
137 SetLastError(0xdeadbeef);
139 ok(!svc_handle, "Expected failure\n");
140 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
142 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
144
145 /* Nonexistent service */
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());
152
153 /* Proper SCM handle but different access rights */
155 SetLastError(0xdeadbeef);
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;
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");
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
190}
191
192static void test_create_delete_svc(void)
193{
194 SC_HANDLE scm_handle, svc_handle1, svc_handle2;
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
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 */ ||
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 */ ||
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 */ ||
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 */
268 SetLastError(0xdeadbeef);
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,
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);
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);
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);
327 ok(!svc_handle1, "Expected failure\n");
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);
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,
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);
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) */
357 if (svc_handle1)
358 {
359 spooler_exists = TRUE;
360 CloseServiceHandle(svc_handle1);
361 SetLastError(0xdeadbeef);
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 {
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,
384 ok(!svc_handle1, "Expected failure for display name '%s'\n", display);
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);
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");
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);
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);
436 ok(!ret, "Expected failure\n");
438 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
439}
440
441static 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");
461 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
462
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 */ ||
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 */ ||
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");
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");
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");
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");
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");
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);
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");
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);
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");
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);
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 */
569 if (!svc_handle)
570 {
571 skip("Spooler service doesn't exist\n");
573 return;
574 }
575 CloseServiceHandle(svc_handle);
576
577 /* Retrieve the needed size for the buffer */
578 SetLastError(0xdeadbeef);
579 displaysize = -1;
581 ok(!ret, "Expected failure\n");
583 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
584 tempsize = displaysize;
585
586 displaysize = 0;
588 ok(!ret, "Expected failure\n");
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");
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");
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");
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");
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
668
669 /* Test for a service without a displayname (which is valid). This should return
670 * the servicename itself.
671 */
672 SetLastError(0xdeadbeef);
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,
684 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
685 if (!svc_handle)
686 {
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");
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");
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);
724
725 /* Wait a while. Just in case one of the following tests does a CreateService again */
726 Sleep(1000);
727}
728
729static 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");
748 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
749
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 */ ||
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 */ ||
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");
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");
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");
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");
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);
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");
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);
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");
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);
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 */
853 if (!svc_handle)
854 {
855 skip("Spooler service doesn't exist\n");
857 return;
858 }
859 CloseServiceHandle(svc_handle);
860
861 /* Get the displayname for the 'Spooler' service */
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");
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");
906 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
907 ok(servicenameW[0] == 0, "Buffer not empty\n");
908
910}
911
912static void test_query_svc(void)
913{
914 SC_HANDLE scm_handle, svc_handle;
915 BOOL ret;
917 SERVICE_STATUS_PROCESS *statusproc;
918 DWORD bufsize, needed;
919
920 /* All NULL or wrong */
921 SetLastError(0xdeadbeef);
923 ok(!ret, "Expected failure\n");
925 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
926
928
929 /* Check if 'Spooler' exists.
930 * Open with not enough rights to query the status.
931 */
933 if (!svc_handle)
934 {
935 skip("Spooler service doesn't exist\n");
937 return;
938 }
939
940 SetLastError(0xdeadbeef);
941 ret = QueryServiceStatus(svc_handle, NULL);
942 ok(!ret, "Expected failure\n");
945 "Unexpected last error %d\n", GetLastError());
946
947 SetLastError(0xdeadbeef);
948 ret = QueryServiceStatus(svc_handle, &status);
949 ok(!ret, "Expected failure\n");
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);
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" );
970 return;
971 }
972
973 /* Open service with not enough rights to query the status */
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");
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 */
992 {
993 ok(!ret, "Expected failure\n");
994 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
995 "Needed buffersize is wrong : %d\n", needed);
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");
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 */
1015 {
1016 ok(!ret, "Expected failure\n");
1017 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1018 "Needed buffersize is wrong : %d\n", needed);
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));
1026 SetLastError(0xdeadbeef);
1027 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1028 ok(!ret, "Expected failure\n");
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);
1036
1037 /* Everything should be fine now. */
1038 statusproc = HeapAlloc(GetProcessHeap(), 0, 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");
1055 GetLastError() == ERROR_INVALID_ADDRESS, "got %d\n", GetLastError());
1056
1057 HeapFree(GetProcessHeap(), 0, statusproc);
1058
1059 CloseServiceHandle(svc_handle);
1061}
1062
1063static 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;
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");
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");
1087 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1088
1089 /* Open the service control manager with not enough rights at first */
1091
1092 /* Valid handle but rest is still NULL or wrong */
1093 SetLastError(0xdeadbeef);
1095 ok(!ret, "Expected failure\n");
1098 "Unexpected last error %d\n", GetLastError());
1099
1100 SetLastError(0xdeadbeef);
1102 ok(!ret, "Expected failure\n");
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");
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");
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");
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");
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);
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);
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);
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);
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);
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);
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);
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);
1229 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1230
1231 needed = 0xdeadbeef;
1232 returned = 0xdeadbeef;
1233 SetLastError(0xdeadbeef);
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);
1241 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1242
1243 /* Open the service control manager with the needed rights */
1246
1247 /* All parameters are correct. Request the needed buffer size */
1248 needed = 0xdeadbeef;
1249 returned = 0xdeadbeef;
1250 SetLastError(0xdeadbeef);
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);
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);
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);
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);
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");
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);
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);
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");
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);
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");
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);
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");
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 */
1358 &needed, &returned, NULL);
1359 services = HeapAlloc(GetProcessHeap(), 0, needed);
1361 needed, &needed, &returned, NULL);
1363
1364 servicecountactive = returned;
1365
1366 /* Get the number of inactive win32 services */
1368 &needed, &returned, NULL);
1369 services = HeapAlloc(GetProcessHeap(), 0, needed);
1371 needed, &needed, &returned, NULL);
1373
1374 servicecountinactive = returned;
1375
1376 /* Get the number of win32 services */
1378 &needed, &returned, NULL);
1379 services = HeapAlloc(GetProcessHeap(), 0, needed);
1381 needed, &needed, &returned, NULL);
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 */
1394 NULL, 0, &needed, &returned, NULL);
1395 services = HeapAlloc(GetProcessHeap(), 0, needed);
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 */
1412 {
1413 if (status.dwCurrentState == SERVICE_STOPPED)
1414 servicecountinactive--;
1415 else
1416 servicecountactive--;
1417 }
1418 }
1420
1421 ok(servicecountactive == 0, "Active services mismatch %u\n", servicecountactive);
1422 ok(servicecountinactive == 0, "Inactive services mismatch %u\n", servicecountinactive);
1423
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");
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");
1445 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1446
1447 /* Open the service control manager with not enough rights at first */
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");
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");
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");
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);
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);
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);
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);
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);
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);
1556 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1557
1558 /* Open the service control manager with the needed rights */
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);
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");
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");
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");
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 {
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 */
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
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
1748}
1749
1750static void test_close(void)
1751{
1752 SC_HANDLE handle;
1753 BOOL ret;
1754
1755 /* NULL handle */
1756 SetLastError(0xdeadbeef);
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 */
1765 SetLastError(0xdeadbeef);
1767 ok(ret, "Expected success got error %u\n", GetLastError());
1768}
1769
1770static void test_sequence(void)
1771{
1772 SC_HANDLE scm_handle, svc_handle;
1773 BOOL ret, is_nt4;
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);
1787
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,
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");
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");
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;
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);
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) {
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");
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
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");
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
1950}
1951
1952static void test_queryconfig2(void)
1953{
1954 SC_HANDLE scm_handle, svc_handle;
1955 BOOL ret;
1956 DWORD expected, needed;
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);
1979
1980 if (!scm_handle)
1981 {
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,
1993 pathname, NULL, NULL, dependencies, NULL, password);
1994
1995 if (!svc_handle)
1996 {
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 {
2008 skip("Not enough rights to open the service\n");
2009 else
2010 ok(FALSE, "Could not open the service : %d\n", GetLastError());
2012 return;
2013 }
2014 }
2016 {
2017 skip("Not enough rights to create the service\n");
2019 return;
2020 }
2021 ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
2022 if (!svc_handle)
2023 {
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");
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);
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
2217cleanup:
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
2226}
2227
2228static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2229{
2230 BOOL ret;
2231 DWORD le1, le2;
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;
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
2272struct notify_data {
2274 SC_HANDLE svc;
2277};
2278
2279static 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
2306static 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;
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 */
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
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
2406 ok(br, "ControlService failed: %u\n", GetLastError());
2407
2408 CloseServiceHandle(svc2);
2409}
2410
2411static 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);
2422 if (!scm_handle)
2423 {
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,
2449 NULL, NULL, NULL, NULL);
2450 if (!svc_handle)
2451 {
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
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";
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";
2493 ok(ret, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2494 test_servicenotify(scm_handle, servicename);
2495
2496cleanup:
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
2507}
2508
2509static 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);
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,
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 */
2541 ok(ret, "Expected success (err=%d)\n", GetLastError());
2542
2543 /* Get a new handle to the Service Control Manager */
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,
2563 ok(!svc_handle5, "Expected failure\n");
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);
2575 ok(ret, "Expected success (err=%d)\n", GetLastError());
2576
2577 /* Wait a while. Doing a CreateService too soon will result again
2578 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2579 */
2580 Sleep(1000);
2581
2582 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2583 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2586 ok(svc_handle5 != NULL, "Expected success, got error %u\n", GetLastError());
2587
2588 /* Delete the service */
2589 ret = DeleteService(svc_handle5);
2590 ok(ret, "Expected success (err=%d)\n", GetLastError());
2591
2592 /* Wait a while. Just in case one of the following tests does a CreateService again */
2593 Sleep(1000);
2594
2595 CloseServiceHandle(svc_handle5);
2597}
2598
2599static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
2600{
2601 HANDLE evt = user;
2602
2603 switch(ctl){
2605 SetEvent(evt);
2606 break;
2608 return NO_ERROR;
2609 }
2610
2612}
2613
2614static void WINAPI service_main(DWORD argc, char **argv)
2615{
2616 SERVICE_STATUS_HANDLE st_handle;
2617 SERVICE_STATUS st;
2618 HANDLE evt = CreateEventW(0, FALSE, FALSE, 0);
2619
2620 st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt);
2621
2626 st.dwWaitHint = 0;
2628 st.dwCheckPoint = 0;
2629
2630 SetServiceStatus(st_handle, &st);
2631
2632 WaitForSingleObject(evt, 5000);
2633
2635
2636 SetServiceStatus(st_handle, &st);
2637}
2638
2639static void run_service(void)
2640{
2641 char empty[] = {0};
2643 {empty, &service_main },
2644 {0, 0}
2645 };
2646
2648}
2649
2651{
2652 SC_HANDLE scm_handle;
2653 int myARGC;
2654 char** myARGV;
2655
2658 if (myARGC >= 3)
2659 {
2660 if (strcmp(myARGV[2], "serve") == 0)
2661 run_service();
2662 return;
2663 }
2664
2665 /* Bail out if we are on win98 */
2666 SetLastError(0xdeadbeef);
2668
2670 {
2671 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2672 return;
2673 }
2675
2677
2678 /* First some parameter checking */
2679 test_open_scm();
2680 test_open_svc();
2685 test_enum_svc();
2686 test_close();
2687 /* Test the creation, querying and deletion of a service */
2688 test_sequence();
2691 /* The main reason for this test is to check if any refcounting is used
2692 * and what the rules are
2693 */
2694 test_refcount();
2695}
static INT myARGC
Definition: FindFiles.c:29
static LPSTR * myARGV
Definition: FindFiles.c:30
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
static SC_HANDLE scm_handle
Definition: ServiceArgs.c:20
static int argc
Definition: ServiceArgs.c:12
#define broken(x)
Definition: _sntprintf.h:21
@ SE_SERVICE
Definition: accctrl.h:161
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
void account(int argc, const char *argv[])
Definition: cmds.c:1690
void user(int argc, const char *argv[])
Definition: cmds.c:1350
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
Definition: service.c:132
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_IO_PENDING
Definition: dderror.h:15
struct config_s config
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI GetUserNameA(LPSTR lpszName, LPDWORD lpSize)
Definition: misc.c:246
static const WCHAR empty[]
Definition: main.c:47
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_ADDRESS
Definition: compat.h:106
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define GetEnvironmentVariableA(x, y, z)
Definition: compat.h:754
#define MultiByteToWideChar
Definition: compat.h:110
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define ERROR_INVALID_NAME
Definition: compat.h:103
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
static const WCHAR descriptionW[]
Definition: error.c:32
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
static const WCHAR displaynameW[]
Definition: sec_mgr.c:39
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define stdout
Definition: stdio.h:99
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define wine_dbgstr_w
Definition: kernel32.h:34
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define error(str)
Definition: mkdosfs.c:1605
char pathname[512]
Definition: util.h:13
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static void test_get_servicekeyname(void)
Definition: service.c:729
static const CHAR spooler[]
Definition: service.c:35
static void test_open_scm(void)
Definition: service.c:72
static LPBYTE
Definition: service.c:41
static void test_get_displayname(void)
Definition: service.c:441
static PSECURITY_DESCRIPTOR
Definition: service.c:53
static SECURITY_INFORMATION
Definition: service.c:46
static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
Definition: service.c:2306
static CHAR selfname[MAX_PATH]
Definition: service.c:36
static void test_open_svc(void)
Definition: service.c:121
static void test_close(void)
Definition: service.c:1750
static SC_ENUM_TYPE
Definition: service.c:40
static void CALLBACK notify_cb(void *user)
Definition: service.c:2279
static SE_OBJECT_TYPE
Definition: service.c:46
static void test_query_svc(void)
Definition: service.c:912
static void test_refcount(void)
Definition: service.c:2509
static void test_sequence(void)
Definition: service.c:1770
#define PHASE_RUNNING
Definition: service.c:2270
static DWORD try_start_stop(SC_HANDLE svc_handle, const char *name, DWORD is_nt4)
Definition: service.c:2228
static SC_STATUS_TYPE
Definition: service.c:50
static void run_service(void)
Definition: service.c:2639
static LPCWSTR
Definition: service.c:45
static void test_create_delete_svc(void)
Definition: service.c:192
static void test_start_stop(void)
Definition: service.c:2411
static void test_enum_svc(void)
Definition: service.c:1063
static LPVOID
Definition: service.c:38
static LPDWORD
Definition: service.c:41
static void test_queryconfig2(void)
Definition: service.c:1952
#define PHASE_STOPPED
Definition: service.c:2269
static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
Definition: service.c:2599
static LPCSTR
Definition: service.c:42
static SERVICE_NOTIFYW *static void init_function_pointers(void)
Definition: service.c:56
BOOL expected
Definition: store.c:2063
#define todo_wine
Definition: custom.c:79
static WCHAR password[]
Definition: url.c:33
static WCHAR username[]
Definition: url.c:32
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define GENERIC_ALL
Definition: nt_native.h:92
#define DELETE
Definition: nt_native.h:57
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
int n2
Definition: dwarfget.c:147
int n1
Definition: dwarfget.c:147
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2845
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI StartServiceA(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCSTR *lpServiceArgVectors)
Definition: scm.c:2942
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
SC_HANDLE WINAPI OpenServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess)
Definition: scm.c:2112
BOOL WINAPI GetServiceDisplayNameW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
Definition: scm.c:1684
BOOL WINAPI GetServiceKeyNameA(SC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPDWORD lpcchBuffer)
Definition: scm.c:1747
BOOL WINAPI GetServiceDisplayNameA(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPDWORD lpcchBuffer)
Definition: scm.c:1626
BOOL WINAPI QueryServiceConfigA(SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA lpServiceConfig, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: scm.c:2208
BOOL WINAPI ChangeServiceConfigA(SC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
Definition: scm.c:363
BOOL WINAPI EnumServicesStatusA(SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle)
Definition: scm.c:1222
SC_HANDLE WINAPI CreateServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword)
Definition: scm.c:680
SC_HANDLE WINAPI OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2024
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
BOOL WINAPI GetServiceKeyNameW(SC_HANDLE hSCManager, LPCWSTR lpDisplayName, LPWSTR lpServiceName, LPDWORD lpcchBuffer)
Definition: scm.c:1806
BOOL WINAPI EnumServicesStatusW(SC_HANDLE hSCManager, DWORD dwServiceType, DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle)
Definition: scm.c:1316
BOOL WINAPI StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
Definition: sctrl.c:1035
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext)
Definition: sctrl.c:778
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:997
#define win_skip
Definition: test.h:160
int winetest_interactive
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define UNLEN
Definition: sspi.c:28
SERVICE_STATUS_PROCESS ServiceStatusProcess
Definition: winsvc.h:137
LPWSTR lpDescription
Definition: winsvc.h:196
DWORD dwServiceType
Definition: winsvc.h:99
DWORD dwWin32ExitCode
Definition: winsvc.h:102
DWORD dwControlsAccepted
Definition: winsvc.h:101
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
Definition: ftp_var.h:139
Definition: security.c:35
Definition: tftpd.h:138
Definition: cookie.c:42
Definition: name.c:39
BOOL was_called
Definition: service.c:2275
DWORD phase
Definition: service.c:2276
SERVICE_NOTIFYW notify
Definition: service.c:2273
SC_HANDLE svc
Definition: service.c:2274
Definition: ps.c:97
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
unsigned char * LPBYTE
Definition: typedefs.h:53
PVOID HANDLE
Definition: typedefs.h:73
int ret
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2790
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_IO_COMPLETION
Definition: winbase.h:411
#define WINAPI
Definition: msvc.h:6
const char * description
Definition: directx.c:2497
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
#define ERROR_SERVICE_MARKED_FOR_DELETE
Definition: winerror.h:623
#define ERROR_INVALID_SERVICE_ACCOUNT
Definition: winerror.h:608
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
#define ERROR_SERVICE_DOES_NOT_EXIST
Definition: winerror.h:611
#define ERROR_DUPLICATE_SERVICE_NAME
Definition: winerror.h:629
#define ERROR_ALREADY_REGISTERED
Definition: winerror.h:745
#define ERROR_SERVICE_EXISTS
Definition: winerror.h:624
#define ERROR_SERVICE_DISABLED
Definition: winerror.h:609
#define RPC_S_SERVER_UNAVAILABLE
Definition: winerror.h:1033
#define ERROR_SERVICE_REQUEST_TIMEOUT
Definition: winerror.h:604
#define RPC_S_INVALID_NET_ADDR
Definition: winerror.h:1018
#define ERROR_DATABASE_DOES_NOT_EXIST
Definition: winerror.h:616
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_STATE_ALL
Definition: winsvc.h:52
struct _SERVICE_DESCRIPTIONA SERVICE_DESCRIPTIONA
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_QUERY_STATUS
Definition: winsvc.h:55
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:119
#define SERVICE_CONFIG_DESCRIPTION
Definition: winsvc.h:65
#define SERVICE_ACTIVE
Definition: winsvc.h:50
struct _SERVICE_DESCRIPTIONW SERVICE_DESCRIPTIONW
#define SC_MANAGER_ENUMERATE_SERVICE
Definition: winsvc.h:16
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define SERVICES_ACTIVE_DATABASEA
Definition: winsvc.h:7
#define SC_MANAGER_CONNECT
Definition: winsvc.h:14
#define SERVICE_NOTIFY_STOPPED
Definition: winsvc.h:80
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
#define SERVICES_FAILED_DATABASEA
Definition: winsvc.h:9
struct _SERVICE_DESCRIPTIONW * LPSERVICE_DESCRIPTIONW
#define SERVICE_NOTIFY_STATUS_CHANGE
Definition: winsvc.h:78
struct _SERVICE_DESCRIPTIONA * LPSERVICE_DESCRIPTIONA
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_CONFIG_PRESHUTDOWN_INFO
Definition: winsvc.h:71
#define SERVICE_INACTIVE
Definition: winsvc.h:51
#define SERVICE_NOTIFY_RUNNING
Definition: winsvc.h:83
struct _SERVICE_STATUS_PROCESS SERVICE_STATUS_PROCESS
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39
int * display
Definition: x11stubs.c:12
#define SERVICE_DEMAND_START
Definition: cmtypes.h:978
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define SERVICE_WIN32_SHARE_PROCESS
Definition: cmtypes.h:963
#define SERVICE_INTERACTIVE_PROCESS
Definition: cmtypes.h:967
#define SERVICE_DISABLED
Definition: cmtypes.h:979
#define SERVICE_AUTO_START
Definition: cmtypes.h:977
#define SERVICE_BOOT_START
Definition: cmtypes.h:975
#define SERVICE_DRIVER
Definition: cmtypes.h:958
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:962
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:954
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:981
#define SERVICE_WIN32
Definition: cmtypes.h:964
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193