ReactOS 0.4.16-dev-2332-g4cba65d
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 *pIsWow64Process)(HANDLE, PBOOL);
39
40static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
41static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
42static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
45static 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 pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
65 pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
66 pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
67 pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
68 pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW");
69
70 pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
71}
72
73static void test_open_scm(void)
74{
75 SC_HANDLE scm_handle;
76
77 /* No access rights */
78 SetLastError(0xdeadbeef);
80 ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
82
83 /* Unknown database name */
84 SetLastError(0xdeadbeef);
86 ok(!scm_handle, "Expected failure\n");
87 ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %ld\n", GetLastError());
88 CloseServiceHandle(scm_handle); /* Just in case */
89
90 /* MSDN says only ServiceActive is allowed, or NULL */
91 SetLastError(0xdeadbeef);
93 ok(!scm_handle, "Expected failure\n");
94 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %ld\n", GetLastError());
95 CloseServiceHandle(scm_handle); /* Just in case */
96
97 /* Remote unknown host */
98 SetLastError(0xdeadbeef);
101 {
102 ok(!scm_handle, "Expected failure\n");
104 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %ld\n", GetLastError());
105 }
106 CloseServiceHandle(scm_handle); /* Just in case */
107
108 /* Proper call with an empty hostname */
110 ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
112
113 /* Again a correct one */
114 SetLastError(0xdeadbeef);
117 "Expected ERROR_SUCCESS, got %lu\n", GetLastError());
118 ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
120}
121
122static void test_open_svc(void)
123{
124 SC_HANDLE scm_handle, svc_handle;
125 CHAR displayname[4096];
126 DWORD displaysize;
127
128 /* All NULL (invalid access rights) */
129 SetLastError(0xdeadbeef);
130 svc_handle = OpenServiceA(NULL, NULL, 0);
131 ok(!svc_handle, "Expected failure\n");
132 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
133
134 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
135
136 /* NULL service */
138 SetLastError(0xdeadbeef);
140 ok(!svc_handle, "Expected failure\n");
141 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
143 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
145
146 /* Nonexistent service */
148 SetLastError(0xdeadbeef);
149 svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
150 ok(!svc_handle, "Expected failure\n");
151 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
153
154 /* Proper SCM handle but different access rights */
156 SetLastError(0xdeadbeef);
158 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
159 skip("Not enough rights to get a handle to the service\n");
160 else
161 {
162 ok(svc_handle != NULL, "Expected success, got error %lu\n", GetLastError());
163 CloseServiceHandle(svc_handle);
164 }
165
166 /* Test to show we can't open a service with the displayname */
167
168 /* Retrieve the needed size for the buffer */
169 displaysize = 0;
171 /* Get the displayname */
172 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
173 /* Try to open the service with this displayname, unless the displayname equals
174 * the servicename as that would defeat the purpose of this test.
175 */
176 if (!lstrcmpiA(spooler, displayname))
177 {
178 skip("displayname equals servicename\n");
180 return;
181 }
182
183 SetLastError(0xdeadbeef);
184 svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
185 ok(!svc_handle, "Expected failure\n");
186 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
187 /* Just in case */
188 CloseServiceHandle(svc_handle);
189
191}
192
193static void test_create_delete_svc(void)
194{
195 SC_HANDLE scm_handle, svc_handle1, svc_handle2;
197 DWORD user_size = UNLEN + 1;
198 CHAR account[MAX_PATH + UNLEN + 1];
199 static const CHAR servicename [] = "winetest_create_delete";
200 static const CHAR pathname [] = "we_dont_care.exe";
201 static const CHAR empty [] = "";
202 static const CHAR password [] = "secret";
203 char buffer[200];
204 DWORD size;
205 BOOL ret;
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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\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 %ld\n", GetLastError());
354
355 /* Test duplicate service names */
356 svc_handle1 = CreateServiceA(scm_handle, "winetest_dupname", "winetest_display", DELETE,
358 ok(!!svc_handle1, "Failed to create service, error %lu\n", GetLastError());
359
360 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname", NULL, 0,
362 ok(!svc_handle2, "Expected failure\n");
363 ok(GetLastError() == ERROR_SERVICE_EXISTS, "Got wrong error %lu\n", GetLastError());
364
365 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_dupname", DELETE,
367 todo_wine ok(!svc_handle2, "Expected failure\n");
368 todo_wine ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %lu\n", GetLastError());
369 if (svc_handle2)
370 {
371 DeleteService(svc_handle2);
372 CloseServiceHandle(svc_handle2);
373 }
374
375 svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_display", DELETE,
377 if (svc_handle2) /* Win10 1709+ */
378 {
379 size = sizeof(buffer);
380 ret = GetServiceKeyNameA(scm_handle, "winetest_display", buffer, &size);
381 ok(ret, "Failed to get key name, error %lu\n", GetLastError());
382 ok(!strcmp(buffer, "winetest_dupname"), "Got wrong name \"%s\"\n", buffer);
383
384 ret = DeleteService(svc_handle2);
385 ok(ret, "Failed to delete service, error %lu\n", GetLastError());
386 CloseServiceHandle(svc_handle2);
387 }
388 else
389 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %lu\n", GetLastError());
390
391 ret = DeleteService(svc_handle1);
392 ok(ret, "Failed to delete service, error %lu\n", GetLastError());
393 CloseServiceHandle(svc_handle1);
394
395 /* Windows doesn't care about the access rights for creation (which makes
396 * sense as there is no service yet) as long as there are sufficient
397 * rights to the manager.
398 */
399 SetLastError(0xdeadbeef);
402 ok(svc_handle1 != NULL, "Could not create the service : %ld\n", GetLastError());
403
404 /* DeleteService however must have proper rights */
405 SetLastError(0xdeadbeef);
406 ret = DeleteService(svc_handle1);
407 ok(!ret, "Expected failure\n");
409 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
410
411 /* Open the service with minimal rights for deletion.
412 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
413 */
414 CloseServiceHandle(svc_handle1);
415 svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
416
417 /* Now that we have the proper rights, we should be able to delete */
418 SetLastError(0xdeadbeef);
419 ret = DeleteService(svc_handle1);
420 ok(ret, "Expected success, got error %lu\n", GetLastError());
421
422 /* Service is marked for delete, but handle is still open. Try to open service again. */
423 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
424 ok(svc_handle2 != NULL, "got %p, error %lu\n", svc_handle2, GetLastError());
425 CloseServiceHandle(svc_handle2);
426
427 CloseServiceHandle(svc_handle1);
429
430 /* And a final NULL check */
431 SetLastError(0xdeadbeef);
433 ok(!ret, "Expected failure\n");
435 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
436}
437
438static void test_get_displayname(void)
439{
440 SC_HANDLE scm_handle, svc_handle;
441 BOOL ret;
442 CHAR displayname[4096];
443 WCHAR displaynameW[2048];
444 DWORD displaysize, tempsize, tempsizeW;
445 static const CHAR deadbeef[] = "Deadbeef";
446 static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
447 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
448 static const WCHAR abcW[] = {'A','B','C',0};
449 static const CHAR servicename[] = "winetest_displayname";
450 static const CHAR pathname[] = "we_dont_care.exe";
451
452 /* Having NULL for the size of the buffer will crash on W2K3 */
453
454 SetLastError(0xdeadbeef);
455 ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
456 ok(!ret, "Expected failure\n");
458 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
459
461
462 SetLastError(0xdeadbeef);
463 ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
464 ok(!ret, "Expected failure\n");
465 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
467 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
468
469 SetLastError(0xdeadbeef);
470 displaysize = sizeof(displayname);
471 ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
472 ok(!ret, "Expected failure\n");
473 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
475 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
476
477 /* Test for nonexistent service */
478 SetLastError(0xdeadbeef);
479 displaysize = -1;
480 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
481 ok(!ret, "Expected failure\n");
483 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
484
485 SetLastError(0xdeadbeef);
486 ret = GetServiceDisplayNameA(scm_handle, deadbeef, NULL, &displaysize);
487 ok(!ret, "Expected failure\n");
489 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
490 todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
491
492 displaysize = 15;
493 strcpy(displayname, "ABC");
494 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
495 ok(!ret, "Expected failure\n");
497 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
498 todo_wine ok(displaysize == 15, "Service size expected 15, got %ld\n", displaysize);
499 ok(displayname[0] == 0, "Service name not empty\n");
500
501 displaysize = 15;
502 lstrcpyW( displaynameW, abcW );
503 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
504 ok(!ret, "Expected failure\n");
506 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
507 ok(displaysize == 15, "Service size expected 15, got %ld\n", displaysize);
508 ok(displaynameW[0] == 0, "Service name not empty\n");
509
510 displaysize = 0;
511 strcpy(displayname, "ABC");
512 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
513 ok(!ret, "Expected failure\n");
515 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
516 todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
517 ok(displayname[0] == 'A', "Service name changed\n");
518
519 displaysize = 0;
520 lstrcpyW( displaynameW, abcW );
521 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
522 ok(!ret, "Expected failure\n");
523 ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
525 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
526 ok(displaynameW[0] == 'A', "Service name changed\n");
527
528 displaysize = 1;
529 strcpy(displayname, "ABC");
530 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
531 ok(!ret, "Expected failure\n");
533 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
534 todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
535 ok(displayname[0] == 0, "Service name not empty\n");
536
537 displaysize = 1;
538 lstrcpyW( displaynameW, abcW );
539 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
540 ok(!ret, "Expected failure\n");
541 ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
543 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
544 ok(displaynameW[0] == 'A', "Service name changed\n");
545
546 displaysize = 2;
547 strcpy(displayname, "ABC");
548 ret = GetServiceDisplayNameA(scm_handle, deadbeef, displayname, &displaysize);
549 ok(!ret, "Expected failure\n");
551 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
552 todo_wine ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
553 ok(displayname[0] == 0, "Service name not empty\n");
554
555 displaysize = 2;
556 lstrcpyW( displaynameW, abcW );
557 ret = GetServiceDisplayNameW(scm_handle, deadbeefW, displaynameW, &displaysize);
558 ok(!ret, "Expected failure\n");
559 ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
561 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
562 ok(displaynameW[0] == 0, "Service name not empty\n");
563
564 /* Check if 'Spooler' exists */
566 if (!svc_handle)
567 {
568 skip("Spooler service doesn't exist\n");
570 return;
571 }
572 CloseServiceHandle(svc_handle);
573
574 /* Retrieve the needed size for the buffer */
575 SetLastError(0xdeadbeef);
576 displaysize = -1;
578 ok(!ret, "Expected failure\n");
580 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
581 tempsize = displaysize;
582
583 displaysize = 0;
585 ok(!ret, "Expected failure\n");
587 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
588 ok(displaysize == tempsize, "Buffer size mismatch (%ld vs %ld)\n", tempsize, displaysize);
589
590 /* Buffer is too small */
591 SetLastError(0xdeadbeef);
592 displaysize = (tempsize / 2);
593 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
594 ok(!ret, "Expected failure\n");
595 ok(displaysize == tempsize, "Expected the needed buffersize\n");
597 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
598
599 /* First try with a buffer that should be big enough to hold
600 * the ANSI string (and terminating character). This succeeds on Windows
601 * although when asked (see above 2 tests) it will return twice the needed size.
602 */
603 SetLastError(0xdeadbeef);
604 displaysize = (tempsize / 2) + 1;
605 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
606 ok(ret, "Expected success, got error %lu\n", GetLastError());
607 ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
608
609 /* Now with the original returned size */
610 SetLastError(0xdeadbeef);
611 displaysize = tempsize;
612 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
613 ok(ret, "Expected success, got error %lu\n", GetLastError());
614 ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
615
616 /* And with a bigger than needed buffer */
617 SetLastError(0xdeadbeef);
618 displaysize = tempsize * 2;
619 ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
620 ok(ret, "Expected success, got error %lu\n", GetLastError());
621 /* Test that shows that if the buffersize is enough, it's not changed */
622 ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
623 ok(strlen(displayname) == tempsize/2,
624 "Expected the buffer to be twice the length of the string\n") ;
625
626 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
627 SetLastError(0xdeadbeef);
628 displaysize = -1;
629 ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
630 ok(!ret, "Expected failure\n");
632 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
633
634 /* Buffer is too small */
635 SetLastError(0xdeadbeef);
636 tempsizeW = displaysize;
637 displaysize = tempsizeW / 2;
638 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
639 ok(!ret, "Expected failure\n");
640 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
642 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
643
644 /* Now with the original returned size */
645 SetLastError(0xdeadbeef);
646 displaysize = tempsizeW;
647 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
648 ok(!ret, "Expected failure\n");
649 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
651 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
652
653 /* And with a bigger than needed buffer */
654 SetLastError(0xdeadbeef);
655 displaysize = tempsizeW + 1; /* This caters for the null terminating character */
656 ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
657 ok(ret, "Expected success, got error %lu\n", GetLastError());
658 ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
659 ok(lstrlenW(displaynameW) == displaysize,
660 "Expected the buffer to be the length of the string\n") ;
661 ok(tempsize / 2 == tempsizeW,
662 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
663
665
666 /* Test for a service without a displayname (which is valid). This should return
667 * the servicename itself.
668 */
669 SetLastError(0xdeadbeef);
672 {
673 skip("Not enough rights to get a handle to the manager\n");
674 return;
675 }
676
677 SetLastError(0xdeadbeef);
678 svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
681 ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
682 if (!svc_handle)
683 {
685 return;
686 }
687
688 /* Retrieve the needed size for the buffer */
689 SetLastError(0xdeadbeef);
690 displaysize = -1;
691 ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
692 ok(!ret, "Expected failure\n");
693 ok(displaysize == strlen(servicename) * 2,
694 "Expected the displaysize to be twice the size of the servicename\n");
696 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
697
698 /* Buffer is too small */
699 SetLastError(0xdeadbeef);
700 tempsize = displaysize;
701 displaysize = (tempsize / 2);
702 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
703 ok(!ret, "Expected failure\n");
704 ok(displaysize == tempsize, "Expected the needed buffersize\n");
706 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
707
708 /* Get the displayname */
709 SetLastError(0xdeadbeef);
710 ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
711 ok(ret, "Expected success, got error %lu\n", GetLastError());
712 ok(!lstrcmpiA(displayname, servicename),
713 "Expected displayname to be %s, got %s\n", servicename, displayname);
714
715 /* Delete the service */
716 ret = DeleteService(svc_handle);
717 ok(ret, "Expected success (err=%ld)\n", GetLastError());
718
719 CloseServiceHandle(svc_handle);
721}
722
723static void test_get_servicekeyname(void)
724{
725 SC_HANDLE scm_handle, svc_handle;
726 CHAR servicename[4096];
727 CHAR displayname[4096];
728 WCHAR servicenameW[4096];
729 WCHAR displaynameW[4096];
730 DWORD servicesize, displaysize, tempsize;
731 BOOL ret;
732 static const CHAR deadbeef[] = "Deadbeef";
733 static const WCHAR deadbeefW[] = {'D','e','a','d','b','e','e','f',0};
734 static const WCHAR abcW[] = {'A','B','C',0};
735
736 /* Having NULL for the size of the buffer will crash on W2K3 */
737
738 SetLastError(0xdeadbeef);
739 ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
740 ok(!ret, "Expected failure\n");
742 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
743
745
746 servicesize = 200;
747 SetLastError(0xdeadbeef);
748 ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
749 ok(!ret, "Expected failure\n");
750 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
752 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
753 todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
754
755 /* Valid handle and buffer but no displayname */
756 servicesize = 200;
757 SetLastError(0xdeadbeef);
758 ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
759 ok(!ret, "Expected failure\n");
760 ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
762 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
763 todo_wine ok(servicesize == 200, "Service size expected 1, got %ld\n", servicesize);
764
765 /* Test for nonexistent displayname */
766 SetLastError(0xdeadbeef);
767 ret = GetServiceKeyNameA(scm_handle, deadbeef, NULL, &servicesize);
768 ok(!ret, "Expected failure\n");
770 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
771 todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
772
773 servicesize = 15;
774 strcpy(servicename, "ABC");
775 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
776 ok(!ret, "Expected failure\n");
778 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
779 todo_wine ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
780 ok(servicename[0] == 0, "Service name not empty\n");
781
782 servicesize = 15;
783 lstrcpyW( servicenameW, abcW );
784 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
785 ok(!ret, "Expected failure\n");
787 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
788 ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
789 ok(servicenameW[0] == 0, "Service name not empty\n");
790
791 servicesize = 0;
792 strcpy(servicename, "ABC");
793 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
794 ok(!ret, "Expected failure\n");
796 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
797 todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
798 ok(servicename[0] == 'A', "Service name changed\n");
799
800 servicesize = 0;
801 lstrcpyW( servicenameW, abcW );
802 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
803 ok(!ret, "Expected failure\n");
804 ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
806 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
807 ok(servicenameW[0] == 'A', "Service name changed\n");
808
809 servicesize = 1;
810 strcpy(servicename, "ABC");
811 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
812 ok(!ret, "Expected failure\n");
814 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
815 todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
816 ok(servicename[0] == 0, "Service name not empty\n");
817
818 servicesize = 1;
819 lstrcpyW( servicenameW, abcW );
820 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
821 ok(!ret, "Expected failure\n");
822 ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
824 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
825 ok(servicenameW[0] == 'A', "Service name changed\n");
826
827 servicesize = 2;
828 strcpy(servicename, "ABC");
829 ret = GetServiceKeyNameA(scm_handle, deadbeef, servicename, &servicesize);
830 ok(!ret, "Expected failure\n");
832 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
833 todo_wine ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
834 ok(servicename[0] == 0, "Service name not empty\n");
835
836 servicesize = 2;
837 lstrcpyW( servicenameW, abcW );
838 ret = GetServiceKeyNameW(scm_handle, deadbeefW, servicenameW, &servicesize);
839 ok(!ret, "Expected failure\n");
840 ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
842 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
843 ok(servicenameW[0] == 0, "Service name not empty\n");
844
845 /* Check if 'Spooler' exists */
847 if (!svc_handle)
848 {
849 skip("Spooler service doesn't exist\n");
851 return;
852 }
853 CloseServiceHandle(svc_handle);
854
855 /* Get the displayname for the 'Spooler' service */
857 GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
858
859 /* Retrieve the needed size for the buffer */
860 SetLastError(0xdeadbeef);
861 servicesize = 0;
862 ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
863 ok(!ret, "Expected failure\n");
864 if (strcmp(displayname, "Print Spooler") != 0 &&
866 {
867 win_skip("GetServiceKeyName() does not support localized display names: %s\n", displayname); /* Windows 7 */
869 return; /* All the tests that follow will fail too */
870 }
871
873 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
874
875 /* Valid call with the correct buffersize */
876 SetLastError(0xdeadbeef);
877 tempsize = servicesize;
878 servicesize *= 2;
879 ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
880 ok(ret, "Expected success, got error %lu\n", GetLastError());
881 if (ret)
882 {
883 ok(strlen(servicename) == tempsize/2,
884 "Expected the buffer to be twice the length of the string\n") ;
885 ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
886 ok(servicesize == (tempsize * 2),
887 "Expected servicesize not to change if buffer not insufficient\n") ;
888 }
889
890 MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
891 SetLastError(0xdeadbeef);
892 servicesize *= 2;
893 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
894 ok(ret, "Expected success, got error %lu\n", GetLastError());
895 if (ret)
896 {
897 ok(strlen(servicename) == tempsize/2,
898 "Expected the buffer to be twice the length of the string\n") ;
899 ok(servicesize == lstrlenW(servicenameW),
900 "Expected servicesize not to change if buffer not insufficient\n") ;
901 }
902
903 SetLastError(0xdeadbeef);
904 servicesize = 3;
905 ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
906 ok(!ret, "Expected failure\n");
908 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
909 ok(servicenameW[0] == 0, "Buffer not empty\n");
910
912}
913
914static void test_query_svc(void)
915{
916 SC_HANDLE scm_handle, svc_handle;
917 BOOL ret;
919 SERVICE_STATUS_PROCESS *statusproc;
920 DWORD bufsize, needed;
921
922 /* All NULL or wrong */
923 SetLastError(0xdeadbeef);
925 ok(!ret, "Expected failure\n");
927 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
928
930
931 /* Check if 'Spooler' exists.
932 * Open with not enough rights to query the status.
933 */
935 if (!svc_handle)
936 {
937 skip("Spooler service doesn't exist\n");
939 return;
940 }
941
942 SetLastError(0xdeadbeef);
943 ret = QueryServiceStatus(svc_handle, NULL);
944 ok(!ret, "Expected failure\n");
947 "Unexpected last error %ld\n", GetLastError());
948
949 SetLastError(0xdeadbeef);
950 ret = QueryServiceStatus(svc_handle, &status);
951 ok(!ret, "Expected failure\n");
953 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
954
955 /* Open the service with just enough rights.
956 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
957 */
958 CloseServiceHandle(svc_handle);
960
961 SetLastError(0xdeadbeef);
962 ret = QueryServiceStatus(svc_handle, &status);
963 ok(ret, "Expected success, got error %lu\n", GetLastError());
964
965 CloseServiceHandle(svc_handle);
966
967 /* More or less the same tests for QueryServiceStatusEx */
968 if (!pQueryServiceStatusEx)
969 {
970 win_skip( "QueryServiceStatusEx not available\n" );
972 return;
973 }
974
975 /* Open service with not enough rights to query the status */
977
978 /* All NULL or wrong, this proves that info level is checked first */
979 SetLastError(0xdeadbeef);
980 ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
981 ok(!ret, "Expected failure\n");
983 "Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
984
985 /* Passing a NULL parameter for the needed buffer size
986 * will crash on anything but NT4.
987 */
988
989 /* Only info level is correct. It looks like the buffer/size is checked second */
990 SetLastError(0xdeadbeef);
991 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
992 /* NT4 checks the handle first */
994 {
995 ok(!ret, "Expected failure\n");
996 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
997 "Needed buffersize is wrong : %ld\n", needed);
999 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1000 }
1001
1002 /* Pass a correct buffer and buffersize but a NULL handle */
1003 statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1004 bufsize = needed;
1005 SetLastError(0xdeadbeef);
1006 ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1007 ok(!ret, "Expected failure\n");
1009 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1010 free(statusproc);
1011
1012 /* Correct handle and info level */
1013 SetLastError(0xdeadbeef);
1014 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1015 /* NT4 doesn't return the needed size */
1017 {
1018 ok(!ret, "Expected failure\n");
1019 ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1020 "Needed buffersize is wrong : %ld\n", needed);
1022 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1023 }
1024
1025 /* All parameters are OK but we don't have enough rights */
1026 statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1028 SetLastError(0xdeadbeef);
1029 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1030 ok(!ret, "Expected failure\n");
1032 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1033 free(statusproc);
1034
1035 /* Open the service with just enough rights. */
1036 CloseServiceHandle(svc_handle);
1038
1039 /* Everything should be fine now. */
1040 statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1042 SetLastError(0xdeadbeef);
1043 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1044 ok(ret, "Expected success, got error %lu\n", GetLastError());
1045 if (statusproc->dwCurrentState == SERVICE_RUNNING)
1046 ok(statusproc->dwProcessId != 0,
1047 "Expect a process id for this running service\n");
1048 else
1049 ok(statusproc->dwProcessId == 0,
1050 "Expect no process id for this stopped service\n");
1051
1052 /* same call with null needed pointer */
1053 SetLastError(0xdeadbeef);
1054 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1055 ok(!ret, "Expected failure\n");
1057 GetLastError() == ERROR_INVALID_ADDRESS, "got %ld\n", GetLastError());
1058
1059 free(statusproc);
1060
1061 CloseServiceHandle(svc_handle);
1063}
1064
1065static BOOL test_enum_svc(int attempt)
1066{
1067 SC_HANDLE scm_handle;
1068 BOOL ret, alldone = FALSE;
1069 DWORD bufsize, needed, returned, resume;
1070 DWORD neededA, returnedA;
1071 DWORD tempneeded, tempreturned, missing;
1072 DWORD servicecountactive, servicecountinactive;
1073 ENUM_SERVICE_STATUSA *servicesA;
1075 UINT i;
1076
1077 /* All NULL or wrong */
1078 SetLastError(0xdeadbeef);
1079 ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1080 ok(!ret, "Expected failure\n");
1082 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1083
1084 SetLastError(0xdeadbeef);
1085 ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1086 ok(!ret, "Expected failure\n");
1088 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1089
1090 /* Open the service control manager with not enough rights at first */
1092
1093 /* Valid handle but rest is still NULL or wrong */
1094 SetLastError(0xdeadbeef);
1096 ok(!ret, "Expected failure\n");
1099 "Unexpected last error %ld\n", GetLastError());
1100
1101 SetLastError(0xdeadbeef);
1103 ok(!ret, "Expected failure\n");
1106 "Unexpected last error %ld\n", GetLastError());
1107
1108 /* Don't specify the two required pointers */
1109 returned = 0xdeadbeef;
1110 SetLastError(0xdeadbeef);
1111 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1112 ok(!ret, "Expected failure\n");
1113 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1116 "Unexpected last error %ld\n", GetLastError());
1117
1118 returned = 0xdeadbeef;
1119 SetLastError(0xdeadbeef);
1120 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1121 ok(!ret, "Expected failure\n");
1122 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1125 "Unexpected last error %ld\n", GetLastError());
1126
1127 /* Don't specify the two required pointers */
1128 needed = 0xdeadbeef;
1129 SetLastError(0xdeadbeef);
1130 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1131 ok(!ret, "Expected failure\n");
1132 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1133 "Expected no change to the needed buffer variable\n");
1136 "Unexpected last error %ld\n", GetLastError());
1137
1138 needed = 0xdeadbeef;
1139 SetLastError(0xdeadbeef);
1140 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1141 ok(!ret, "Expected failure\n");
1142 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1143 "Expected no change to the needed buffer variable\n");
1146 "Unexpected last error %ld\n", GetLastError());
1147
1148 /* No valid servicetype and servicestate */
1149 needed = 0xdeadbeef;
1150 returned = 0xdeadbeef;
1151 SetLastError(0xdeadbeef);
1152 ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1153 ok(!ret, "Expected failure\n");
1154 ok(needed == 0 || broken(needed != 0), /* nt4 */
1155 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1156 ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1158 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1159
1160 needed = 0xdeadbeef;
1161 returned = 0xdeadbeef;
1162 SetLastError(0xdeadbeef);
1163 ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1164 ok(!ret, "Expected failure\n");
1165 ok(needed == 0 || broken(needed != 0), /* nt4 */
1166 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1167 ok(returned == 0 || broken(returned != 0), /* nt4 */
1168 "Expected number of services to be set to 0, got %ld\n", returned);
1170 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1171
1172 /* No valid servicestate */
1173 needed = 0xdeadbeef;
1174 returned = 0xdeadbeef;
1175 SetLastError(0xdeadbeef);
1176 ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1177 ok(!ret, "Expected failure\n");
1178 ok(needed == 0 || broken(needed != 0), /* nt4 */
1179 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1180 ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1182 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1183
1184 needed = 0xdeadbeef;
1185 returned = 0xdeadbeef;
1186 SetLastError(0xdeadbeef);
1187 ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1188 ok(!ret, "Expected failure\n");
1189 ok(needed == 0 || broken(needed != 0), /* nt4 */
1190 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1191 ok(returned == 0 || broken(returned != 0), /* nt4 */
1192 "Expected number of services to be set to 0, got %ld\n", returned);
1194 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1195
1196 /* No valid servicetype */
1197 needed = 0xdeadbeef;
1198 returned = 0xdeadbeef;
1199 SetLastError(0xdeadbeef);
1200 ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1201 ok(!ret, "Expected failure\n");
1202 ok(needed == 0 || broken(needed != 0), /* nt4 */
1203 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1204 ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1206 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1207
1208 needed = 0xdeadbeef;
1209 returned = 0xdeadbeef;
1210 SetLastError(0xdeadbeef);
1211 ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1212 ok(!ret, "Expected failure\n");
1213 ok(needed == 0 || broken(needed != 0), /* nt4 */
1214 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1215 ok(returned == 0 || broken(returned != 0), /* nt4 */
1216 "Expected number of services to be set to 0, got %ld\n", returned);
1218 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1219
1220 /* All parameters are correct but our access rights are wrong */
1221 needed = 0xdeadbeef;
1222 returned = 0xdeadbeef;
1223 SetLastError(0xdeadbeef);
1225 ok(!ret, "Expected failure\n");
1226 ok(needed == 0 || broken(needed != 0), /* nt4 */
1227 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1228 ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1230 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1231
1232 needed = 0xdeadbeef;
1233 returned = 0xdeadbeef;
1234 SetLastError(0xdeadbeef);
1236 ok(!ret, "Expected failure\n");
1237 ok(needed == 0 || broken(needed != 0), /* nt4 */
1238 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1239 ok(returned == 0 || broken(returned != 0), /* nt4 */
1240 "Expected number of services to be set to 0, got %ld\n", returned);
1242 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1243
1244 /* Open the service control manager with the needed rights */
1247
1248 /* All parameters are correct. Request the needed buffer size */
1249 needed = 0xdeadbeef;
1250 returned = 0xdeadbeef;
1251 SetLastError(0xdeadbeef);
1253 ok(!ret, "Expected failure\n");
1254 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1255 ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1257 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1258
1259 /* Test to show we get the same needed buffer size for the A-call */
1260 neededA = 0xdeadbeef;
1261 returnedA = 0xdeadbeef;
1262 SetLastError(0xdeadbeef);
1264 ok(!ret, "Expected failure\n");
1266 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1267 ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1268 ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1269 if (neededA != needed && attempt)
1270 goto retry; /* service start|stop race condition */
1271 ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1272
1273 /* Store the needed bytes */
1274 tempneeded = needed;
1275
1276 /* Allocate the correct needed bytes */
1277 services = malloc(needed);
1278 bufsize = needed;
1279 needed = 0xdeadbeef;
1280 returned = 0xdeadbeef;
1281 SetLastError(0xdeadbeef);
1283 services, bufsize, &needed, &returned, NULL);
1284 free(services);
1285 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1286 goto retry; /* service start race condition */
1287 ok(ret, "Expected success, got error %lu\n", GetLastError());
1288 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1289 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1290
1291 /* Store the number of returned services */
1292 tempreturned = returned;
1293
1294 servicesA = malloc(neededA);
1295 bufsize = neededA;
1296 neededA = 0xdeadbeef;
1297 returnedA = 0xdeadbeef;
1298 SetLastError(0xdeadbeef);
1300 servicesA, bufsize, &neededA, &returnedA, NULL);
1301 free(servicesA);
1302 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1303 goto retry; /* service start race condition */
1305 win_skip("Skipping some tests due to EnumServicesStatusA()'s broken UTF-8 support\n");
1306 else
1307 {
1308 ok(ret, "Expected success, got error %lu\n", GetLastError());
1309 ok(neededA == 0, "Expected needed buffer to be 0 as we are done\n");
1310 ok(returnedA != 0xdeadbeef && returnedA > 0, "Expected some returned services\n");
1311 }
1312
1313 /* Allocate less than the needed bytes and don't specify a resume handle.
1314 * More than one service will be missing because of the space needed for
1315 * the strings.
1316 */
1317 services = malloc(tempneeded);
1318 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1319 needed = 0xdeadbeef;
1320 returned = 0xdeadbeef;
1321 SetLastError(0xdeadbeef);
1323 services, bufsize, &needed, &returned, NULL);
1324 if (ret && needed == 0 && attempt)
1325 {
1326 free(services);
1327 goto retry; /* service stop race condition */
1328 }
1329 ok(!ret, "Expected failure\n");
1330 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1331 todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1332 /* Experiments show bufsize + needed < tempneeded which proves the needed
1333 * buffer size is an approximation. So it's best not to probe more.
1334 */
1335 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1337 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1338
1339 /* Allocate less than the needed bytes, this time with a correct resume handle */
1340 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1341 needed = 0xdeadbeef;
1342 returned = 0xdeadbeef;
1343 resume = 0;
1344 SetLastError(0xdeadbeef);
1346 services, bufsize, &needed, &returned, &resume);
1347 if (ret && needed == 0 && attempt)
1348 {
1349 free(services);
1350 goto retry; /* service stop race condition */
1351 }
1352 ok(!ret, "Expected failure\n");
1353 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services, got %lx\n", needed);
1354 todo_wine ok(needed < tempneeded, "Expected < %lu bytes needed for the remaining services, got %lu\n", tempneeded, needed);
1355 ok(returned < tempreturned, "Expected < %lu remaining services, got %lu\n", tempreturned, returned);
1356 todo_wine ok(resume, "Expected a resume handle\n");
1358 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1359
1360 /* Fetch the missing services but pass a bigger buffer size */
1361 missing = tempreturned - returned;
1362 bufsize = tempneeded;
1363 needed = 0xdeadbeef;
1364 returned = 0xdeadbeef;
1365 SetLastError(0xdeadbeef);
1367 services, bufsize, &needed, &returned, &resume);
1368 free(services);
1369 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1370 goto retry; /* service start race condition */
1371 ok(ret, "Expected success, got error %lu\n", GetLastError());
1372 ok(needed == 0, "Expected 0 needed bytes as we are done, got %lu\n", needed);
1373 if (returned < missing && strcmp(winetest_platform, "wine") && attempt)
1374 goto retry; /* service stop race condition */
1375 todo_wine ok(returned == missing, "Expected %lu remaining services, got %lu\n", missing, returned);
1376 ok(resume == 0, "Expected the resume handle to be 0\n");
1377
1378 /* See if things add up */
1379
1380 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1381 * and doesn't count the others as inactive. This means that Vista could
1382 * show a total that is greater than the sum of active and inactive
1383 * drivers.
1384 * The number of active and inactive drivers is greatly influenced by the
1385 * time when tests are run, immediately after boot or later for example.
1386 *
1387 * Both reasons make calculations for drivers not so useful
1388 */
1389
1390 /* Get the number of active win32 services */
1392 &needed, &returned, NULL);
1393 services = malloc(needed);
1395 services, needed, &needed, &returned, NULL);
1396 free(services);
1397 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1398 goto retry; /* service start race condition */
1399
1400 servicecountactive = returned;
1401
1402 /* Get the number of inactive win32 services */
1404 &needed, &returned, NULL);
1405 services = malloc(needed);
1407 services, needed, &needed, &returned, NULL);
1408 free(services);
1409 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1410 goto retry; /* service start race condition */
1411
1412 servicecountinactive = returned;
1413
1414 /* Get the number of win32 services */
1416 &needed, &returned, NULL);
1417 services = malloc(needed);
1419 services, needed, &needed, &returned, NULL);
1420 free(services);
1421 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1422 goto retry; /* service start race condition */
1423
1424 /* Check if total is the same as active and inactive win32 services */
1425 if (returned != servicecountactive + servicecountinactive && attempt)
1426 goto retry; /* service start|stop race condition */
1427 ok(returned == servicecountactive + servicecountinactive,
1428 "Expected service count %ld == %ld + %ld\n",
1429 returned, servicecountactive, servicecountinactive);
1430
1431 /* Get all drivers and services
1432 *
1433 * Fetch the status of the last call as failing could make the following tests crash
1434 * on Wine (we don't return anything yet).
1435 */
1437 NULL, 0, &needed, &returned, NULL);
1438 services = malloc(needed);
1440 services, needed, &needed, &returned, NULL);
1441 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1442 goto retry; /* service start race condition */
1443 ok(ret, "Expected success %lu\n", GetLastError());
1444
1445 /* Loop through all those returned drivers and services */
1446 for (i = 0; ret && i < returned; i++)
1447 {
1448 SERVICE_STATUS status = services[i].ServiceStatus;
1449
1450 /* lpServiceName and lpDisplayName should always be filled */
1451 ok(services[i].lpServiceName[0], "Expected a service name\n");
1452 ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n");
1453
1454 /* Decrement the counters to see if the functions calls return the same
1455 * numbers as the contents of these structures.
1456 */
1458 {
1459 switch (status.dwCurrentState)
1460 {
1464 case SERVICE_PAUSED:
1466 trace("Got state %lx for service %s\n", status.dwCurrentState,
1467 wine_dbgstr_w(services[i].lpServiceName));
1468 /* fall through */
1469
1470 case SERVICE_RUNNING:
1471 servicecountactive--;
1472 break;
1473
1474 case SERVICE_STOPPED:
1475 servicecountinactive--;
1476 break;
1477
1478 default:
1479 ok(0, "Got unknown state %lx for service %s\n",
1480 status.dwCurrentState, wine_dbgstr_w(services[i].lpServiceName));
1481 break;
1482 }
1483 }
1484 }
1485 free(services);
1486
1487 if ((servicecountactive || servicecountinactive) && attempt)
1488 goto retry; /* service start|stop race condition */
1489 ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1490 ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1491
1492 alldone = TRUE;
1493
1494retry:
1496 return alldone;
1497}
1498
1499static BOOL test_enum_svc_ex(int attempt)
1500{
1501 SC_HANDLE scm_handle;
1502 BOOL ret, alldone = FALSE;
1503 DWORD bufsize, needed, returned, resume;
1504 DWORD neededA, returnedA;
1505 DWORD tempneeded, tempreturned, missing;
1506 DWORD servicecountactive, servicecountinactive;
1508 ENUM_SERVICE_STATUS_PROCESSW *exservices;
1509 UINT i;
1510
1511 /* More or less the same for EnumServicesStatusExA */
1512 if (!pEnumServicesStatusExA)
1513 {
1514 win_skip( "EnumServicesStatusExA not available\n" );
1515 return TRUE;
1516 }
1517
1518 /* All NULL or wrong */
1519 SetLastError(0xdeadbeef);
1520 ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1521 ok(!ret, "Expected failure\n");
1523 "Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
1524
1525 /* All NULL or wrong, just the info level is correct */
1526 SetLastError(0xdeadbeef);
1527 ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1528 ok(!ret, "Expected failure\n");
1530 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1531
1532 /* Open the service control manager with not enough rights at first */
1534
1535 /* Valid handle and info level but rest is still NULL or wrong */
1536 SetLastError(0xdeadbeef);
1537 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1538 ok(!ret, "Expected failure\n");
1541 "Unexpected last error %ld\n", GetLastError());
1542
1543 /* Don't specify the two required pointers */
1544 needed = 0xdeadbeef;
1545 SetLastError(0xdeadbeef);
1546 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1547 ok(!ret, "Expected failure\n");
1548 ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1549 "Expected no change to the needed buffer variable\n");
1552 "Unexpected last error %ld\n", GetLastError());
1553
1554 /* Don't specify the two required pointers */
1555 returned = 0xdeadbeef;
1556 SetLastError(0xdeadbeef);
1557 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1558 ok(!ret, "Expected failure\n");
1559 ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1562 "Unexpected last error %ld\n", GetLastError());
1563
1564 /* No valid servicetype and servicestate */
1565 needed = 0xdeadbeef;
1566 returned = 0xdeadbeef;
1567 SetLastError(0xdeadbeef);
1568 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1569 ok(!ret, "Expected failure\n");
1570 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1571 ok(needed == 0 || broken(needed != 0), /* nt4 */
1572 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1574 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1575
1576 /* No valid servicestate */
1577 needed = 0xdeadbeef;
1578 returned = 0xdeadbeef;
1579 SetLastError(0xdeadbeef);
1580 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1581 &needed, &returned, NULL, NULL);
1582 ok(!ret, "Expected failure\n");
1583 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1584 ok(needed == 0 || broken(needed != 0), /* nt4 */
1585 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1587 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1588
1589 /* No valid servicetype */
1590 needed = 0xdeadbeef;
1591 returned = 0xdeadbeef;
1592 SetLastError(0xdeadbeef);
1593 ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1594 &needed, &returned, NULL, NULL);
1595 ok(!ret, "Expected failure\n");
1596 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1597 ok(needed == 0 || broken(needed != 0), /* nt4 */
1598 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1600 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1601
1602 /* No valid servicetype and servicestate and unknown service group */
1603 needed = 0xdeadbeef;
1604 returned = 0xdeadbeef;
1605 SetLastError(0xdeadbeef);
1606 ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1607 &returned, NULL, "deadbeef_group");
1608 ok(!ret, "Expected failure\n");
1609 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1610 ok(needed == 0 || broken(needed != 0), /* nt4 */
1611 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1613 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1614
1615 /* All parameters are correct but our access rights are wrong */
1616 needed = 0xdeadbeef;
1617 returned = 0xdeadbeef;
1618 SetLastError(0xdeadbeef);
1619 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1620 NULL, 0, &needed, &returned, NULL, NULL);
1621 ok(!ret, "Expected failure\n");
1622 ok(needed == 0 || broken(needed != 0), /* nt4 */
1623 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1624 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1626 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1627
1628 /* All parameters are correct, access rights are wrong but the
1629 * group name won't be checked yet.
1630 */
1631 needed = 0xdeadbeef;
1632 returned = 0xdeadbeef;
1633 SetLastError(0xdeadbeef);
1634 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1635 NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1636 ok(!ret, "Expected failure\n");
1637 ok(needed == 0 || broken(needed != 0), /* nt4 */
1638 "Expected needed buffer size to be set to 0, got %ld\n", needed);
1639 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1641 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1642
1643 /* Open the service control manager with the needed rights */
1646
1647 /* All parameters are correct and the group will be checked */
1648 needed = 0xdeadbeef;
1649 returned = 0xdeadbeef;
1650 SetLastError(0xdeadbeef);
1651 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1652 NULL, 0, &needed, &returned, NULL, L"deadbeef_group");
1653 ok(!ret, "Expected failure\n");
1654 ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1655 ok(needed == 0, "Expected needed buffer size to be set to 0, got %ld\n", needed);
1657 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
1658
1659 /* TODO: Create a test that makes sure we enumerate all services that don't
1660 * belong to a group. (specifying "").
1661 */
1662
1663 /* All parameters are correct. Request the needed buffer size */
1664 needed = 0xdeadbeef;
1665 returned = 0xdeadbeef;
1666 SetLastError(0xdeadbeef);
1667 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1668 NULL, 0, &needed, &returned, NULL, NULL);
1669 ok(!ret, "Expected failure\n");
1670 ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1671 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1673 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1674
1675 /* Test to show we get the same needed buffer size for the A-call */
1676 neededA = 0xdeadbeef;
1677 returnedA = 0xdeadbeef;
1678 SetLastError(0xdeadbeef);
1679 ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1680 NULL, 0, &neededA, &returnedA, NULL, NULL);
1681 ok(!ret, "Expected failure\n");
1683 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1684 ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1685 ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1686 if (neededA != needed && attempt)
1687 goto retry; /* service start|stop race condition */
1688 ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1690 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1691
1692 /* Store the needed bytes */
1693 tempneeded = needed;
1694
1695 /* Show the Ex call returns the same service count as the regular enum */
1697 NULL, 0, &needed, &returned, NULL);
1698 services = malloc(needed);
1699 returned = 0xdeadbeef;
1701 services, needed, &needed, &returned, NULL);
1702 free(services);
1703 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1704 goto retry; /* service start race condition */
1705 ok(ret, "Expected success, got error %lu\n", GetLastError());
1706 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1707 ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1708
1709 /* Store the number of returned services */
1710 tempreturned = returned;
1711
1712 /* Allocate the correct needed bytes */
1713 exservices = malloc(tempneeded);
1714 bufsize = tempneeded;
1715 needed = 0xdeadbeef;
1716 returned = 0xdeadbeef;
1717 SetLastError(0xdeadbeef);
1718 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1719 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1720 free(exservices);
1721 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1722 goto retry; /* service start race condition */
1723 ok(ret, "Expected success, got error %lu\n", GetLastError());
1724 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1725 ok(returned == tempreturned, "Expected the same number of service from this function\n");
1726
1727 /* Store the number of returned services */
1728 tempreturned = returned;
1729
1730 /* Allocate less than the needed bytes and don't specify a resume handle.
1731 * More than one service will be missing because of the space needed for
1732 * the strings.
1733 */
1734 exservices = malloc(tempneeded);
1735 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1736 needed = 0xdeadbeef;
1737 returned = 0xdeadbeef;
1738 SetLastError(0xdeadbeef);
1739 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1740 (BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1741 if (ret && needed == 0 && attempt)
1742 {
1743 free(exservices);
1744 goto retry; /* service stop race condition */
1745 }
1746 ok(!ret, "Expected failure\n");
1747 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1748 todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1749 /* Experiments show bufsize + needed < tempneeded which proves the needed
1750 * buffer size is an approximation. So it's best not to probe more.
1751 */
1752 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1754 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1755
1756 /* Allocate less than the needed bytes, this time with a correct resume handle */
1757 bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1758 needed = 0xdeadbeef;
1759 returned = 0xdeadbeef;
1760 resume = 0;
1761 SetLastError(0xdeadbeef);
1762 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1763 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1764 if (ret && needed == 0 && attempt)
1765 {
1766 free(exservices);
1767 goto retry; /* service stop race condition */
1768 }
1769 ok(!ret, "Expected failure\n");
1770 ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1771 todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1772 ok(returned < tempreturned, "Expected fewer services to be returned\n");
1773 todo_wine ok(resume, "Expected a resume handle\n");
1775 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1776
1777 /* Fetch the missing services but pass a bigger buffer size */
1778 missing = tempreturned - returned;
1779 bufsize = tempneeded;
1780 needed = 0xdeadbeef;
1781 returned = 0xdeadbeef;
1782 SetLastError(0xdeadbeef);
1783 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1784 (BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1785 free(exservices);
1786 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1787 goto retry; /* service start race condition */
1788 ok(ret, "Expected success, got error %lu\n", GetLastError());
1789 ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1790 ok(returned == missing, "Expected %lu services to be returned\n", missing);
1791 ok(resume == 0, "Expected the resume handle to be 0\n");
1792
1793 /* See if things add up */
1794
1795 /* Get the number of active win32 services */
1796 pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1797 NULL, 0, &needed, &returned, NULL, NULL);
1798 exservices = malloc(needed);
1799 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1800 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1801 free(exservices);
1802 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1803 goto retry; /* service start race condition */
1804
1805 servicecountactive = returned;
1806
1807 /* Get the number of inactive win32 services */
1808 pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1809 NULL, 0, &needed, &returned, NULL, NULL);
1810 exservices = malloc(needed);
1811 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1812 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1813 free(exservices);
1814 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1815 goto retry; /* service start race condition */
1816
1817 servicecountinactive = returned;
1818
1819 /* Get the number of win32 services */
1820 pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1821 NULL, 0, &needed, &returned, NULL, NULL);
1822 exservices = malloc(needed);
1823 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1824 (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1825 free(exservices);
1826 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1827 goto retry; /* service start race condition */
1828
1829 /* Check if total is the same as active and inactive win32 services */
1830 if (returned != servicecountactive + servicecountinactive && attempt)
1831 goto retry; /* service start|stop race condition */
1832 ok(returned == servicecountactive + servicecountinactive,
1833 "Expected service count %ld == %ld + %ld\n",
1834 returned, servicecountactive, servicecountinactive);
1835
1836 /* Get all drivers and services */
1837 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1838 SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1839 ok(!ret, "Expected failure\n");
1840 exservices = malloc(needed);
1841 ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1842 SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1843 if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1844 goto retry; /* service start race condition */
1845 ok(ret, "Expected success %lu\n", GetLastError());
1846
1847 /* Loop through all those returned drivers and services */
1848 for (i = 0; i < returned; i++)
1849 {
1851
1852 /* lpServiceName and lpDisplayName should always be filled */
1853 ok(exservices[i].lpServiceName[0], "Expected a service name\n");
1854 ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n");
1855
1856 /* Decrement the counters to see if the functions calls return the
1857 * same numbers as the contents of these structures.
1858 * Check some process id specifics.
1859 */
1861 {
1862 /* We shouldn't have a process id for drivers */
1863 ok(status.dwProcessId == 0,
1864 "This driver shouldn't have an associated process id\n");
1865 }
1866
1868 {
1869 switch (status.dwCurrentState)
1870 {
1873 trace("Got state %lx (pid=%04lx) for service %s\n",
1874 status.dwCurrentState, status.dwProcessId,
1875 wine_dbgstr_w(exservices[i].lpServiceName));
1876 /* There may or may not be a process id */
1877 servicecountactive--;
1878 break;
1879
1881 case SERVICE_PAUSED:
1883 trace("Got state %lx (pid=%04lx) for service %s\n",
1884 status.dwCurrentState, status.dwProcessId,
1885 wine_dbgstr_w(exservices[i].lpServiceName));
1886 /* fall through */
1887
1888 case SERVICE_RUNNING:
1889 /* We expect a process id for every running service */
1890 ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1891 wine_dbgstr_w(exservices[i].lpServiceName));
1892 servicecountactive--;
1893 break;
1894
1895 case SERVICE_STOPPED:
1896 /* We shouldn't have a process id for inactive services */
1897 ok(status.dwProcessId == 0, "Service %s state %lu shouldn't have an associated process id\n",
1898 wine_dbgstr_w(exservices[i].lpServiceName), status.dwCurrentState);
1899
1900 servicecountinactive--;
1901 break;
1902
1903 default:
1904 ok(0, "Got unknown state %lx (pid=%04lx) for service %s\n",
1905 status.dwCurrentState, status.dwProcessId,
1906 wine_dbgstr_w(exservices[i].lpServiceName));
1907 break;
1908 }
1909 }
1910 }
1911 free(exservices);
1912
1913 if ((servicecountactive || servicecountinactive) && attempt)
1914 goto retry; /* service start|stop race condition */
1915 ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1916 ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1917
1918 alldone = TRUE;
1919
1920retry:
1922 return alldone;
1923}
1924
1925static void test_close(void)
1926{
1927 SC_HANDLE handle;
1928 BOOL ret;
1929
1930 /* NULL handle */
1931 SetLastError(0xdeadbeef);
1933 ok(!ret, "Expected failure\n");
1934 ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1935
1936 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1937
1938 /* Proper call */
1940 SetLastError(0xdeadbeef);
1942 ok(ret, "Expected success got error %lu\n", GetLastError());
1943}
1944
1945static void test_wow64(void)
1946{
1947 SC_HANDLE manager, service;
1948 BOOL wow64, ret;
1949 HANDLE file;
1950
1951 if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &wow64) || !wow64)
1952 {
1953 skip("Not running under WoW64.\n");
1954 return;
1955 }
1956
1958 {
1959 skip("Not enough permissions to create a service.\n");
1960 return;
1961 }
1962
1963 file = CreateFileA("C:\\windows\\syswow64\\winetestsvc.exe", GENERIC_WRITE,
1964 0, NULL, CREATE_ALWAYS, 0, NULL);
1966
1967 service = CreateServiceA(manager, "winetestsvc", "winetestsvc",
1970 "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1971 ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1972 ret = StartServiceA(service, 0, NULL);
1973 ok(!ret, "Expected failure.\n");
1974 ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
1975
1976 ret = DeleteService(service);
1977 ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
1978 CloseServiceHandle(service);
1979
1980 service = CreateServiceA(manager, "winetestsvc2", "winetestsvc2", SERVICE_START | DELETE,
1982 "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
1983 ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1984 ret = StartServiceA(service, 0, NULL);
1985 ok(!ret, "Expected failure.\n");
1986 todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
1987
1988 ret = DeleteService(service);
1989 ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
1990 CloseServiceHandle(service);
1991
1992 ret = DeleteFileA("C:\\windows\\syswow64\\winetestsvc.exe");
1993 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
1994
1995 file = CreateFileA("C:\\windows\\sysnative\\winetestsvc.exe", GENERIC_WRITE,
1996 0, NULL, CREATE_ALWAYS, 0, NULL);
1998
1999 service = CreateServiceA(manager, "winetestsvc3", "winetestsvc3", SERVICE_START | DELETE,
2001 "C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
2002 ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
2003 ret = StartServiceA(service, 0, NULL);
2004 ok(!ret, "Expected failure.\n");
2005 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
2006
2007 ret = DeleteService(service);
2008 ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2009 CloseServiceHandle(service);
2010
2011 service = CreateServiceA(manager, "winetestsvc4", "winetestsvc4", SERVICE_START | DELETE,
2013 "C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
2014 ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
2015 ret = StartServiceA(service, 0, NULL);
2016 ok(!ret, "Expected failure.\n");
2017 todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
2018
2019 ret = DeleteService(service);
2020 ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2021 CloseServiceHandle(service);
2022
2023 ret = DeleteFileA("C:\\windows\\sysnative\\winetestsvc.exe");
2024 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
2025
2026 CloseServiceHandle(manager);
2027}
2028
2029static void test_sequence(void)
2030{
2031 SC_HANDLE scm_handle, svc_handle;
2032 BOOL ret, is_nt4;
2034 DWORD given, needed;
2035 static const CHAR servicename [] = "winetest_sequence";
2036 static const CHAR displayname [] = "Winetest dummy service";
2037 static const CHAR displayname2[] = "Winetest dummy service (2)";
2038 static const CHAR pathname [] = "we_dont_care.exe";
2039 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2040 static const CHAR password [] = "";
2041 static const CHAR empty [] = "";
2042 static const CHAR localsystem [] = "LocalSystem";
2043
2044 SetLastError(0xdeadbeef);
2046
2048 {
2049 skip("Not enough rights to get a handle to the manager\n");
2050 return;
2051 }
2052 else
2053 ok(scm_handle != NULL, "Could not get a handle to the manager: %ld\n", GetLastError());
2054
2055 if (!scm_handle) return;
2056 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2057 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2058 CloseServiceHandle(svc_handle);
2059
2060 /* Create a dummy service */
2061 SetLastError(0xdeadbeef);
2062 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2064 pathname, NULL, NULL, dependencies, NULL, password);
2065
2066 if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
2067 {
2068 /* We try and open the service and do the rest of the tests. Some could
2069 * fail if the tests were changed between these runs.
2070 */
2071 trace("Deletion probably didn't work last time\n");
2072 SetLastError(0xdeadbeef);
2073 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2074 if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2075 {
2076 skip("Not enough rights to open the service\n");
2078 return;
2079 }
2080 ok(svc_handle != NULL, "Could not open the service : %ld\n", GetLastError());
2081 }
2082 else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2083 {
2084 skip("Not enough rights to create the service\n");
2086 return;
2087 }
2088 else
2089 {
2090 ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2091 if (svc_handle != NULL)
2092 {
2093 PSID sidOwner, sidGroup;
2094 PACL dacl, sacl;
2096 DWORD error, n1, n2;
2098 BOOL bret;
2099
2100 /* Test using GetSecurityInfo to obtain security information */
2102 &sidGroup, &dacl, &sacl, &pSD);
2103 LocalFree(pSD);
2104 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2106 NULL, NULL, NULL, &pSD);
2107 LocalFree(pSD);
2108 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2109 if (!is_nt4)
2110 {
2112 NULL, &dacl, NULL, &pSD);
2113 ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2114 LocalFree(pSD);
2115 SetLastError(0xdeadbeef);
2117 NULL, NULL, NULL, NULL);
2118 error = GetLastError();
2119 ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %ld\n", retval);
2120 ok(error == 0xdeadbeef, "Unexpected last error %ld\n", error);
2121 }
2122 else
2123 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
2124
2125 /* Test using QueryServiceObjectSecurity to obtain security information */
2126 SetLastError(0xdeadbeef);
2127 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
2128 error = GetLastError();
2129 ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
2132 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", error);
2133 if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
2134 pSD = LocalAlloc(0, n1);
2135 bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
2136 ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
2137 LocalFree(pSD);
2138 }
2139 }
2140
2141 if (!svc_handle) {
2143 return;
2144 }
2145
2146 /* TODO:
2147 * Before we do a QueryServiceConfig we should check the registry. This will make sure
2148 * that the correct keys are used.
2149 */
2150
2151 /* Request the size for the buffer */
2152 SetLastError(0xdeadbeef);
2153 ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2154 ok(!ret, "Expected failure\n");
2155 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2156
2157 config = malloc(needed);
2158 given = needed;
2159 SetLastError(0xdeadbeef);
2160 ret = QueryServiceConfigA(svc_handle, config, given, &needed);
2161 ok(ret, "Expected success, got error %lu\n", GetLastError());
2162
2163 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2164 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2166 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2167 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2168 ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %ld\n", config->dwErrorControl);
2169 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2170 ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
2171 ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2172 /* TODO: Show the double 0 terminated string */
2173 todo_wine
2174 {
2175 ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
2176 }
2177 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2178 ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
2179
2181 NULL, NULL, NULL, NULL, displayname2);
2182 ok(ret, "ChangeServiceConfig failed (err=%ld)\n", GetLastError());
2183
2184 QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2185 config = realloc(config, needed);
2186 ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
2187 ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2188 config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2190 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2191 ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2192 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %ld\n", config->dwErrorControl);
2193 ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2194 ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
2195 ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2196 ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2197 ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
2198
2199 SetLastError(0xdeadbeef);
2200 ret = DeleteService(svc_handle);
2201 ok(ret, "Expected success, got error %lu\n", GetLastError());
2202 CloseServiceHandle(svc_handle);
2204 free(config);
2205}
2206
2207static void test_queryconfig2(void)
2208{
2209 SC_HANDLE scm_handle, svc_handle;
2210 BOOL ret;
2211 DWORD expected, needed;
2215 SERVICE_PRESHUTDOWN_INFO preshutdown_info;
2216 SERVICE_DELAYED_AUTO_START_INFO auto_start_info;
2217 static const CHAR servicename [] = "winetest_query_config2";
2218 static const CHAR displayname [] = "Winetest dummy service";
2219 static const CHAR pathname [] = "we_dont_care.exe";
2220 static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2221 static const CHAR password [] = "";
2222 static const CHAR description [] = "Description";
2223 static const CHAR description_empty[] = "";
2224 static const WCHAR descriptionW [] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
2225 static const WCHAR descriptionW_empty[] = {0};
2226
2227 if(!pQueryServiceConfig2A)
2228 {
2229 win_skip("function QueryServiceConfig2A not present\n");
2230 return;
2231 }
2232
2233 SetLastError(0xdeadbeef);
2235
2236 if (!scm_handle)
2237 {
2239 skip("Not enough rights to get a handle to the manager\n");
2240 else
2241 ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2242 return;
2243 }
2244
2245 /* Create a dummy service */
2246 SetLastError(0xdeadbeef);
2247 svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2249 pathname, NULL, NULL, dependencies, NULL, password);
2250
2251 if (!svc_handle)
2252 {
2254 {
2255 /* We try and open the service and do the rest of the tests. Some could
2256 * fail if the tests were changed between these runs.
2257 */
2258 trace("Deletion probably didn't work last time\n");
2259 SetLastError(0xdeadbeef);
2260 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2261 if (!svc_handle)
2262 {
2264 skip("Not enough rights to open the service\n");
2265 else
2266 ok(FALSE, "Could not open the service : %ld\n", GetLastError());
2268 return;
2269 }
2270 }
2272 {
2273 skip("Not enough rights to create the service\n");
2275 return;
2276 }
2277 ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2278 if (!svc_handle)
2279 {
2281 return;
2282 }
2283 }
2284 SetLastError(0xdeadbeef);
2285 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2286 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2287 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2288
2289 SetLastError(0xdeadbeef);
2290 ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2291 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2292 ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2293
2294 SetLastError(0xdeadbeef);
2295 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2296 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2297 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2298
2299 SetLastError(0xdeadbeef);
2300 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2301 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2303 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2304
2305 SetLastError(0xdeadbeef);
2306 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2307 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2308 ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2309
2310 needed = 0;
2311 SetLastError(0xdeadbeef);
2312 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2313 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2314 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2315 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2316
2317 needed = 0;
2318 pConfig->lpDescription = (LPSTR)0xdeadbeef;
2319 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2320 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2321 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2322 ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2323
2324 SetLastError(0xdeadbeef);
2325 needed = 0;
2326 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2327 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2328 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2329 ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2330
2331 if(!pChangeServiceConfig2A)
2332 {
2333 win_skip("function ChangeServiceConfig2A not present\n");
2334 goto cleanup;
2335 }
2336
2337 pConfig->lpDescription = (LPSTR) description;
2338 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2339 ok(ret, "ChangeServiceConfig2A failed\n");
2340 if (!ret) {
2341 goto cleanup;
2342 }
2343
2344 SetLastError(0xdeadbeef);
2345 needed = 0;
2346 expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2347 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2348 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2349 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2350 ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2351
2352 SetLastError(0xdeadbeef);
2353 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2354 ok(!ret, "expected QueryServiceConfig2A to fail\n");
2355 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2356
2357 SetLastError(0xdeadbeef);
2358 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2359 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2360 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2361 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2362
2363 SetLastError(0xdeadbeef);
2364 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2365 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2366 ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2367 "expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2368
2369 if(!pQueryServiceConfig2W)
2370 {
2371 win_skip("function QueryServiceConfig2W not present\n");
2372 goto cleanup;
2373 }
2374 SetLastError(0xdeadbeef);
2375 needed = 0;
2376 expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2377 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2378 ok(!ret, "expected QueryServiceConfig2W to fail\n");
2379 ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2380 ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2381
2382 SetLastError(0xdeadbeef);
2383 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2384 ok(ret, "expected QueryServiceConfig2W to succeed\n");
2385
2386 pConfig->lpDescription = (LPSTR)description;
2387 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2388 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2389
2390 pConfig->lpDescription = NULL;
2391 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2392 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2393 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2394 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2395
2396 pConfig->lpDescription = NULL;
2397 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2398 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2399
2400 pConfig->lpDescription = NULL;
2401 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2402 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2403 ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2404 "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2405
2406 pConfig->lpDescription = (LPSTR)description_empty;
2407 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2408 ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2409
2410 pConfig->lpDescription = (void*)0xdeadbeef;
2411 ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2412 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2413 ok(!pConfig->lpDescription,
2414 "expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2415
2416 pConfigW->lpDescription = (LPWSTR)descriptionW;
2417 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2418 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2419
2420 pConfigW->lpDescription = NULL;
2421 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2422 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2423 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2424 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2425
2426 pConfigW->lpDescription = NULL;
2427 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2428 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2429
2430 pConfigW->lpDescription = NULL;
2431 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2432 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2433 ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2434 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2435
2436 pConfigW->lpDescription = (LPWSTR)descriptionW_empty;
2437 ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2438 ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2439
2440 pConfigW->lpDescription = (void*)0xdeadbeef;
2441 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2442 ok(ret, "expected QueryServiceConfig2A to succeed\n");
2443 ok(!pConfigW->lpDescription,
2444 "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2445
2446 SetLastError(0xdeadbeef);
2447 needed = 0;
2448 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2449 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2451 {
2452 /* Win2k3 and older */
2453 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2454 goto cleanup;
2455 }
2456 ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2457 ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2458 ok(preshutdown_info.dwPreshutdownTimeout == 180000
2459 || preshutdown_info.dwPreshutdownTimeout == 10000 /* Win10 1709+ */,
2460 "Default PreshutdownTimeout = %ld\n", preshutdown_info.dwPreshutdownTimeout);
2461
2462 SetLastError(0xdeadbeef);
2463 preshutdown_info.dwPreshutdownTimeout = -1;
2464 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2465 (LPVOID)&preshutdown_info);
2466 ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
2467
2468 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2469 (LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2470 ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2471 ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2472 ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %ld\n",
2473 preshutdown_info.dwPreshutdownTimeout);
2474
2475 SetLastError(0xdeadbeef);
2476 needed = 0;
2477 auto_start_info.fDelayedAutostart = 0xdeadbeef;
2478 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2479 (LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed);
2480 ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2481 ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed);
2482 ok(auto_start_info.fDelayedAutostart == 0, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2483
2484 SetLastError(0xdeadbeef);
2485 auto_start_info.fDelayedAutostart = 3;
2486 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2487 (LPBYTE)&auto_start_info);
2488 ok(!ret, "expected ChangeServiceConfig2A to fail\n");
2490
2491 SetLastError(0xdeadbeef);
2492 auto_start_info.fDelayedAutostart = 1;
2493 ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2494 (LPBYTE)&auto_start_info);
2495 ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
2496
2497 SetLastError(0xdeadbeef);
2498 needed = 0;
2499 auto_start_info.fDelayedAutostart = 0xdeadbeef;
2500 ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2501 (LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed);
2502 ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2503 ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed);
2504 ok(auto_start_info.fDelayedAutostart == 1, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2505
2506cleanup:
2507 DeleteService(svc_handle);
2508 CloseServiceHandle(svc_handle);
2510}
2511
2512static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2513{
2514 BOOL ret;
2515 DWORD le1, le2;
2517
2518 ret = StartServiceA(svc_handle, 0, NULL);
2519 le1 = GetLastError();
2520 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2521
2522 if (pQueryServiceStatusEx)
2523 {
2524 DWORD needed;
2525 SERVICE_STATUS_PROCESS statusproc;
2526
2527 ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2528 ok(ret, "%s: QueryServiceStatusEx() failed le=%lu\n", name, GetLastError());
2529 ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%lx\n", name, statusproc.dwCurrentState);
2530 ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %lx\n", name, statusproc.dwProcessId);
2531 }
2532
2533 ret = StartServiceA(svc_handle, 0, NULL);
2534 le2 = GetLastError();
2535 ok(!ret, "%s: StartServiceA() should have failed\n", name);
2536 ok(le2 == le1, "%s: the second try should yield the same error: %lu != %lu\n", name, le1, le2);
2537
2538 status.dwCurrentState = 0xdeadbeef;
2540 le2 = GetLastError();
2541 ok(!ret, "%s: ControlService() should have failed\n", name);
2542 ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %ld != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2543 ok(status.dwCurrentState == SERVICE_STOPPED ||
2544 broken(is_nt4), /* NT4 returns a random value */
2545 "%s: should be stopped state=%lx\n", name, status.dwCurrentState);
2546
2547 return le1;
2548}
2549
2550#define PHASE_STOPPED 1
2551#define PHASE_RUNNING 2
2552
2553struct notify_data {
2555 SC_HANDLE svc;
2558};
2559
2560static void CALLBACK notify_cb(void *user)
2561{
2562 struct notify_data *data = user;
2563 switch (data->phase)
2564 {
2565 case PHASE_STOPPED:
2566 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2567 "Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2568 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2569 "Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2570 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2571 "Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2572 break;
2573
2574 case PHASE_RUNNING:
2575 ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2576 "Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2577 ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2578 "Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2579 ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2580 "Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2581 break;
2582 }
2583
2584 data->was_called = TRUE;
2585}
2586
2587static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
2588{
2589 DWORD dr, dr2;
2590 struct notify_data data;
2591 struct notify_data data2;
2592 BOOL br;
2594 HANDLE svc, svc2;
2595
2596 if(!pNotifyServiceStatusChangeW){
2597 win_skip("No NotifyServiceStatusChangeW\n");
2598 return;
2599 }
2600
2601 svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2602 svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2603 ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2604 if(!svc || !svc2)
2605 return;
2606
2607 /* receive stopped notification, then start service */
2608 memset(&data.notify, 0, sizeof(data.notify));
2609 data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2610 data.notify.pfnNotifyCallback = &notify_cb;
2611 data.notify.pContext = &data;
2612 data.svc = svc;
2613 data.phase = PHASE_STOPPED;
2614 data.was_called = FALSE;
2615
2616 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2617 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2618
2619 dr = SleepEx(100, TRUE);
2620 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2621 ok(data.was_called == TRUE, "APC wasn't called\n");
2622
2623 br = StartServiceA(svc, 0, NULL);
2624 ok(br, "StartService failed: %lu\n", GetLastError());
2625
2626 /* receive running notification */
2627 data.phase = PHASE_RUNNING;
2628 data.was_called = FALSE;
2629
2630 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2631 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2632
2633 dr = SleepEx(100, TRUE);
2634 ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2635 ok(data.was_called == TRUE, "APC wasn't called\n");
2636
2637 /* cannot register two notifications on the same handle */
2638 data.phase = PHASE_STOPPED;
2639 data.was_called = FALSE;
2640
2641 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2642 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2643
2644 memset(&data2.notify, 0, sizeof(data2.notify));
2645 data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2646 data2.notify.pfnNotifyCallback = &notify_cb;
2647 data2.notify.pContext = &data2;
2648 data2.phase = PHASE_RUNNING;
2649 data2.was_called = FALSE;
2650
2651 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2652 ok(dr == ERROR_ALREADY_REGISTERED || !dr /* Win8+ */, "wrong error %lu\n", dr);
2653 if (!dr)
2654 {
2655 dr = SleepEx(100, TRUE);
2656 ok(dr == WAIT_IO_COMPLETION, "got %lu\n", dr);
2657 ok(data2.was_called, "APC was not called\n");
2658 }
2659 else
2660 {
2661 dr = SleepEx(100, TRUE);
2662 ok(!dr, "got %lu\n", dr);
2663 ok(!data2.was_called, "APC should not have been called\n");
2664 }
2665 ok(data.was_called == FALSE, "APC should not have been called\n");
2666
2667 memset(&data2.notify, 0, sizeof(data2.notify));
2668 data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2669 data2.notify.pfnNotifyCallback = &notify_cb;
2670 data2.notify.pContext = &data;
2671 data2.svc = svc2;
2672 data2.phase = PHASE_STOPPED;
2673 data2.was_called = FALSE;
2674
2675 /* it's possible to have multiple notifications using different service handles */
2676 dr = pNotifyServiceStatusChangeW(svc2, SERVICE_NOTIFY_STOPPED, &data2.notify);
2677 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW gave wrong result: %lu\n", dr);
2678
2679 /* stop service and receive notifiction */
2681 ok(br, "ControlService failed: %lu\n", GetLastError());
2682
2683 dr = SleepEx(100, TRUE);
2684 dr2 = SleepEx(100, TRUE);
2685 ok(dr == WAIT_IO_COMPLETION || dr2 == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2686 ok(data.was_called == TRUE, "APC wasn't called\n");
2687 ok(data2.was_called == TRUE, "APC wasn't called\n");
2688
2689 /* test cancelation: create notify on svc that will block until service
2690 * start; close svc; start service on svc2; verify that notification does
2691 * not happen */
2692
2693 data.phase = PHASE_RUNNING;
2694 data.was_called = FALSE;
2695 dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2696 ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2697
2699
2700 br = StartServiceA(svc2, 0, NULL);
2701 ok(br, "StartService failed: %lu\n", GetLastError());
2702
2703 dr = SleepEx(100, TRUE);
2704 ok(dr == 0, "Got wrong SleepEx result: %lu\n", dr);
2705 ok(data.was_called == FALSE, "APC should not have been called\n");
2706
2708 ok(br, "ControlService failed: %lu\n", GetLastError());
2709
2710 CloseServiceHandle(svc2);
2711}
2712
2713static void test_start_stop(void)
2714{
2715 BOOL ret;
2716 SC_HANDLE scm_handle, svc_handle;
2717 DWORD le, is_nt4;
2718 static const char servicename[] = "winetest_start_stop";
2719 char cmd[MAX_PATH+20];
2720 const char* displayname;
2721
2722 SetLastError(0xdeadbeef);
2724 if (!scm_handle)
2725 {
2727 skip("Not enough rights to get a handle to the manager\n");
2728 else
2729 ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2730 return;
2731 }
2732
2733 /* Detect NT4 */
2734 svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2735 is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2736
2737 /* Do some cleanup in case a previous run crashed */
2738 svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2739 if (svc_handle)
2740 {
2741 DeleteService(svc_handle);
2742 CloseServiceHandle(svc_handle);
2743 }
2744
2745 /* Create a dummy disabled service */
2746 sprintf(cmd, "\"%s\" service exit", selfname);
2747 displayname = "Winetest Disabled Service";
2748 svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2751 NULL, NULL, NULL, NULL);
2752 if (!svc_handle)
2753 {
2755 skip("Not enough rights to create the service\n");
2756 else
2757 ok(FALSE, "Could not create the service: %ld\n", GetLastError());
2758 goto cleanup;
2759 }
2760 le = try_start_stop(svc_handle, displayname, is_nt4);
2761 ok(le == ERROR_SERVICE_DISABLED, "%ld != ERROR_SERVICE_DISABLED\n", le);
2762
2763 /* Then one with a bad path */
2764 displayname = "Winetest Bad Path";
2765 ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2766 ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2767 try_start_stop(svc_handle, displayname, is_nt4);
2768
2769 if (is_nt4)
2770 {
2771 /* NT4 does not detect when a service fails to start and uses an
2772 * insanely long timeout: 120s. So skip the rest of the tests.
2773 */
2774 win_skip("Skip some service start/stop tests on NT4\n");
2775 goto cleanup;
2776 }
2777
2778 /* Again with a process that exits right away */
2779 displayname = "Winetest Exit Service";
2781 ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2782 le = try_start_stop(svc_handle, displayname, is_nt4);
2783 ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%ld != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2784
2785 /* create a real service and test notifications */
2786 sprintf(cmd, "%s service serve", selfname);
2787 displayname = "Winetest Service";
2789 ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2790 test_servicenotify(scm_handle, servicename);
2791
2792cleanup:
2793 if (svc_handle)
2794 {
2795 DeleteService(svc_handle);
2796 CloseServiceHandle(svc_handle);
2797 }
2799}
2800
2801static void test_refcount(void)
2802{
2803 SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2804 static const CHAR servicename [] = "winetest_refcount";
2805 static const CHAR pathname [] = "we_dont_care.exe";
2806 BOOL ret;
2807
2808 /* Get a handle to the Service Control Manager */
2809 SetLastError(0xdeadbeef);
2812 {
2813 skip("Not enough rights to get a handle to the manager\n");
2814 return;
2815 }
2816
2817 /* Create a service */
2818 svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2821 ok(svc_handle1 != NULL, "Expected success, got error %lu\n", GetLastError());
2822
2823 /* Get a handle to this new service */
2824 svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2825 ok(svc_handle2 != NULL, "Expected success, got error %lu\n", GetLastError());
2826
2827 /* Get another handle to this new service */
2828 svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2829 ok(svc_handle3 != NULL, "Expected success, got error %lu\n", GetLastError());
2830
2831 /* Check if we can close the handle to the Service Control Manager */
2833 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2834
2835 /* Get a new handle to the Service Control Manager */
2837 ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
2838
2839 /* Get a handle to this new service */
2840 svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2841 ok(svc_handle4 != NULL, "Expected success, got error %lu\n", GetLastError());
2842
2843 /* Delete the service */
2844 ret = DeleteService(svc_handle4);
2845 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2846
2847 /* We cannot create the same service again as it's still marked as 'being deleted'.
2848 * The reason is that we still have 4 open handles to this service even though we
2849 * closed the handle to the Service Control Manager in between.
2850 */
2851 SetLastError(0xdeadbeef);
2852 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2855 ok(!svc_handle5, "Expected failure\n");
2857 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %ld\n", GetLastError());
2858
2859 /* Close all the handles to the service and try again */
2860 ret = CloseServiceHandle(svc_handle4);
2861 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2862 ret = CloseServiceHandle(svc_handle3);
2863 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2864 ret = CloseServiceHandle(svc_handle2);
2865 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2866 ret = CloseServiceHandle(svc_handle1);
2867 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2868
2869 /* Wait a while. Doing a CreateService too soon will result again
2870 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2871 */
2872 Sleep(1000);
2873
2874 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2875 svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2878 ok(svc_handle5 != NULL, "Expected success, got error %lu\n", GetLastError());
2879
2880 /* Delete the service */
2881 ret = DeleteService(svc_handle5);
2882 ok(ret, "Expected success (err=%ld)\n", GetLastError());
2883 CloseServiceHandle(svc_handle5);
2885}
2886
2888{
2889 static HMODULE hkernel32 = NULL;
2890 static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
2891 static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
2892
2893 if (!hkernel32)
2894 {
2895 hkernel32 = GetModuleHandleA("kernel32.dll");
2896 pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
2897 pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
2898 }
2899 if (pGetThreadUILanguage)
2900 return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
2901 if (pGetUserDefaultUILanguage)
2902 return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
2903
2905}
2906
2907static void test_EventLog(void)
2908{
2909 SC_HANDLE scm_handle, svc_handle;
2910 DWORD size;
2911 BOOL ret;
2914
2916 ok(scm_handle != NULL, "OpenSCManager error %lu\n", GetLastError());
2917
2918 svc_handle = OpenServiceA(scm_handle, "EventLog", GENERIC_READ);
2919 ok(svc_handle != NULL, "OpenService error %lu\n", GetLastError());
2920
2921 SetLastError(0xdeadbeef);
2922 ret = QueryServiceConfigA(svc_handle, NULL, 0, &size);
2923 ok(!ret, "QueryServiceConfig should fail\n");
2925
2926 config = malloc(size);
2927 ret = QueryServiceConfigA(svc_handle, config, size, &size);
2928 ok(ret, "QueryServiceConfig error %lu\n", GetLastError());
2929
2930 ok(config->dwServiceType == SERVICE_WIN32_SHARE_PROCESS, "got %#lx\n", config->dwServiceType);
2931 ok(config->dwStartType == SERVICE_AUTO_START, "got %lu\n", config->dwStartType);
2932 ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "got %lu\n", config->dwErrorControl);
2933 ok(!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\services.exe") /* XP */ ||
2934 !strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted") /* Vista+ */ ||
2935 !strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -p") /* Win10 */,
2936 "got %s\n", config->lpBinaryPathName);
2937 todo_wine
2938 ok(!strcmpi(config->lpLoadOrderGroup, "Event Log"), "got %s\n", config->lpLoadOrderGroup);
2939 ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2940 ok(!config->lpDependencies[0], "lpDependencies is not empty\n");
2941 ok(!strcmp(config->lpServiceStartName, "LocalSystem") /* XP */ ||
2942 !strcmp(config->lpServiceStartName, "NT AUTHORITY\\LocalService"),
2943 "got %s\n", config->lpServiceStartName);
2944 ok(!is_lang_english() || /* DisplayName is often translated */
2945 !strcmp(config->lpDisplayName, "Event Log") /* XP */ ||
2946 !strcmp(config->lpDisplayName, "Windows Event Log") /* Vista+ */, "got %s\n", config->lpDisplayName);
2947
2948 free(config);
2949
2950 memset(&status, 0, sizeof(status));
2951 size = sizeof(status);
2953 ok(ret, "QueryServiceStatusEx error %lu\n", GetLastError());
2954 ok(status.dwServiceType == SERVICE_WIN32_SHARE_PROCESS ||
2955 status.dwServiceType == (SERVICE_WIN32_SHARE_PROCESS | SERVICE_WIN32_OWN_PROCESS) /* Win10 */,
2956 "got %#lx\n", status.dwServiceType);
2957 ok(status.dwServiceSpecificExitCode == 0, "got %#lx\n", status.dwServiceSpecificExitCode);
2958 ok(status.dwCheckPoint == 0, "got %#lx\n", status.dwCheckPoint);
2959 ok(status.dwWaitHint == 0, "got %#lx\n", status.dwWaitHint);
2960 ok(status.dwServiceFlags == 0 || status.dwServiceFlags == SERVICE_RUNS_IN_SYSTEM_PROCESS /* XP */,
2961 "got %#lx\n", status.dwServiceFlags);
2962 if (status.dwCurrentState == SERVICE_STOPPED &&
2963 status.dwWin32ExitCode == ERROR_PROCESS_ABORTED)
2964 win_skip("EventLog crashed!\n");
2965 else
2966 {
2967 ok(status.dwCurrentState == SERVICE_RUNNING, "got %#lx\n", status.dwCurrentState);
2968 ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ ||
2969 status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ ||
2971 "got %#lx\n", status.dwControlsAccepted);
2972 ok(status.dwWin32ExitCode == 0, "got %#lx\n", status.dwWin32ExitCode);
2973 ok(status.dwProcessId != 0, "got %#lx\n", status.dwProcessId);
2974 }
2975
2976 CloseServiceHandle(svc_handle);
2978}
2979
2980static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
2981{
2982 HANDLE evt = user;
2983
2984 switch(ctl){
2986 SetEvent(evt);
2987 break;
2989 return NO_ERROR;
2990 }
2991
2993}
2994
2995static void WINAPI service_main(DWORD argc, char **argv)
2996{
2997 SERVICE_STATUS_HANDLE st_handle;
2998 SERVICE_STATUS st;
2999 HANDLE evt = CreateEventW(0, FALSE, FALSE, 0);
3000
3001 st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt);
3002
3007 st.dwWaitHint = 0;
3009 st.dwCheckPoint = 0;
3010
3011 SetServiceStatus(st_handle, &st);
3012
3013 WaitForSingleObject(evt, 5000);
3014
3016
3017 SetServiceStatus(st_handle, &st);
3018}
3019
3020static void run_service(void)
3021{
3022 char empty[] = {0};
3024 {empty, &service_main },
3025 {0, 0}
3026 };
3027
3029}
3030
3032{
3033 SC_HANDLE scm_handle;
3034 int myARGC;
3035 char** myARGV;
3036 int attempt;
3037
3040 if (myARGC >= 3)
3041 {
3042 if (strcmp(myARGV[2], "serve") == 0)
3043 run_service();
3044 return;
3045 }
3046
3047 /* Bail out if we are on win98 */
3048 SetLastError(0xdeadbeef);
3050
3052 {
3053 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
3054 return;
3055 }
3057
3059
3060 /* First some parameter checking */
3061 test_open_scm();
3062 test_open_svc();
3067
3068 /* Services may start or stop between enumeration calls, leading to
3069 * inconsistencies and failures. So we may need a couple attempts.
3070 */
3071 for (attempt = 2; attempt >= 0; attempt--)
3072 if (test_enum_svc(attempt)) break;
3073 for (attempt = 2; attempt >= 0; attempt--)
3074 if (test_enum_svc_ex(attempt)) break;
3075
3076 test_close();
3077 test_wow64();
3078 /* Test the creation, querying and deletion of a service */
3079 test_sequence();
3082 /* The main reason for this test is to check if any refcounting is used
3083 * and what the rules are
3084 */
3085 test_refcount();
3086 test_EventLog();
3087}
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
@ SE_SERVICE
Definition: accctrl.h:161
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#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 ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#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
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
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
DWORD WINAPI GetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, PSID *ppsidOwner, PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl, PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
Definition: misc.c:1244
BOOL WINAPI GetUserNameA(LPSTR lpszName, LPDWORD lpSize)
Definition: misc.c:246
static const WCHAR empty[1]
Definition: string.c:47
#define CloseHandle
Definition: compat.h:739
#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 CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#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
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
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
UINT WINAPI GetACP(void)
Definition: locale.c:2023
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
LANGID WINAPI GetUserDefaultLangID(void)
Definition: locale.c:1182
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
static int strcmpi(const char *s1, const char *s2)
Definition: string.h:82
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
static const WCHAR displaynameW[]
Definition: sec_mgr.c:39
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
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
GLsizeiptr size
Definition: glext.h:5919
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 wine_dbgstr_w
Definition: kernel32.h:34
USHORT LANGID
Definition: mui.h:9
const char * winetest_platform
#define win_skip
Definition: minitest.h:67
#define todo_wine
Definition: minitest.h:80
#define error(str)
Definition: mkdosfs.c:1605
char pathname[512]
Definition: util.h:13
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define sprintf
Definition: sprintf.c:45
static void test_get_servicekeyname(void)
Definition: service.c:723
static const CHAR spooler[]
Definition: service.c:35
static BOOL test_enum_svc(int attempt)
Definition: service.c:1065
static void test_open_scm(void)
Definition: service.c:73
static LPBYTE
Definition: service.c:43
static void test_get_displayname(void)
Definition: service.c:438
static PSECURITY_DESCRIPTOR
Definition: service.c:53
static SECURITY_INFORMATION
Definition: service.c:52
static void test_EventLog(void)
Definition: service.c:2907
static BOOL is_lang_english(void)
Definition: service.c:2887
static void test_wow64(void)
Definition: service.c:1945
static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
Definition: service.c:2587
static BOOL test_enum_svc_ex(int attempt)
Definition: service.c:1499
static CHAR selfname[MAX_PATH]
Definition: service.c:36
static void test_open_svc(void)
Definition: service.c:122
static void test_close(void)
Definition: service.c:1925
static SC_ENUM_TYPE
Definition: service.c:42
static void CALLBACK notify_cb(void *user)
Definition: service.c:2560
static void test_query_svc(void)
Definition: service.c:914
static PBOOL
Definition: service.c:38
static void test_refcount(void)
Definition: service.c:2801
static void test_sequence(void)
Definition: service.c:2029
#define PHASE_RUNNING
Definition: service.c:2551
static DWORD try_start_stop(SC_HANDLE svc_handle, const char *name, DWORD is_nt4)
Definition: service.c:2512
static SC_STATUS_TYPE
Definition: service.c:50
static void run_service(void)
Definition: service.c:3020
static LPCWSTR
Definition: service.c:47
static void test_create_delete_svc(void)
Definition: service.c:193
static void test_start_stop(void)
Definition: service.c:2713
static LPVOID
Definition: service.c:40
static LPDWORD
Definition: service.c:43
static void test_queryconfig2(void)
Definition: service.c:2207
#define PHASE_STOPPED
Definition: service.c:2550
static LPCSTR
Definition: service.c:44
static SERVICE_NOTIFYW *static void init_function_pointers(void)
Definition: service.c:56
BOOL expected
Definition: store.c:2000
static HINSTANCE hkernel32
Definition: process.c:68
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 STANDARD_RIGHTS_READ
Definition: nt_native.h:65
#define GENERIC_ALL
Definition: nt_native.h:92
#define DELETE
Definition: nt_native.h:57
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
static BOOL wow64
Definition: psapi_main.c:44
#define SERVICE_START
Definition: winsvc.h:63
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_STATE_ALL
Definition: winsvc.h:58
struct _SERVICE_DESCRIPTIONA SERVICE_DESCRIPTIONA
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
#define SERVICE_CONFIG_DELAYED_AUTO_START_INFO
Definition: winsvc.h:73
#define SERVICE_QUERY_STATUS
Definition: winsvc.h:61
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:125
#define SERVICE_CONFIG_DESCRIPTION
Definition: winsvc.h:71
#define SERVICE_ACTIVE
Definition: winsvc.h:56
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:86
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_RUNS_IN_SYSTEM_PROCESS
Definition: winsvc.h:69
#define SERVICES_FAILED_DATABASEA
Definition: winsvc.h:9
struct _SERVICE_DESCRIPTIONW * LPSERVICE_DESCRIPTIONW
#define SERVICE_PAUSED
Definition: winsvc.h:27
#define SERVICE_NOTIFY_STATUS_CHANGE
Definition: winsvc.h:84
#define SERVICE_STOP
Definition: winsvc.h:64
struct _SERVICE_DESCRIPTIONA * LPSERVICE_DESCRIPTIONA
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:42
#define SERVICE_CONFIG_PRESHUTDOWN_INFO
Definition: winsvc.h:77
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
#define SERVICE_INACTIVE
Definition: winsvc.h:57
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
#define SERVICE_NOTIFY_RUNNING
Definition: winsvc.h:89
struct _SERVICE_STATUS_PROCESS SERVICE_STATUS_PROCESS
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:45
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
#define SERVICE_ACCEPT_TIMECHANGE
Definition: winsvc.h:37
int n2
Definition: dwarfget.c:147
int n1
Definition: dwarfget.c:147
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2884
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI StartServiceA(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCSTR *lpServiceArgVectors)
Definition: scm.c:2981
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: scm.c:2926
SC_HANDLE WINAPI OpenServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess)
Definition: scm.c:2151
BOOL WINAPI GetServiceDisplayNameW(SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
Definition: scm.c:1723
BOOL WINAPI GetServiceKeyNameA(SC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPDWORD lpcchBuffer)
Definition: scm.c:1786
BOOL WINAPI GetServiceDisplayNameA(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPDWORD lpcchBuffer)
Definition: scm.c:1665
BOOL WINAPI QueryServiceConfigA(SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA lpServiceConfig, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: scm.c:2247
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:2063
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:1845
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:1054
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext)
Definition: sctrl.c:797
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:1016
#define LANG_ENGLISH
Definition: nls.h:52
#define CP_UTF8
Definition: nls.h:20
#define PRIMARYLANGID(l)
Definition: nls.h:16
strcpy
Definition: string.h:131
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:148
LPWSTR lpDescription
Definition: winsvc.h:202
DWORD dwServiceType
Definition: winsvc.h:105
DWORD dwWin32ExitCode
Definition: winsvc.h:108
DWORD dwControlsAccepted
Definition: winsvc.h:107
DWORD dwWaitHint
Definition: winsvc.h:111
DWORD dwCurrentState
Definition: winsvc.h:106
DWORD dwCheckPoint
Definition: winsvc.h:110
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:109
Definition: ftp_var.h:139
Definition: security.c:35
Definition: tftpd.h:138
Definition: cookie.c:42
Definition: fci.c:127
Definition: name.c:39
BOOL was_called
Definition: service.c:2556
DWORD phase
Definition: service.c:2557
SERVICE_NOTIFYW notify
Definition: service.c:2554
SC_HANDLE svc
Definition: service.c:2555
Definition: ps.c:97
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:738
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
unsigned char * LPBYTE
Definition: typedefs.h:53
PVOID HANDLE
Definition: typedefs.h:73
int retval
Definition: wcstombs.cpp:91
_In_ LPCSTR _Out_writes_to_opt_ cchDisplayName LPSTR lpDisplayName
Definition: winbase.h:2544
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_IO_COMPLETION
Definition: winbase.h:388
#define WINAPI
Definition: msvc.h:6
const char * description
Definition: directx.c:2497
#define ERROR_INVALID_LEVEL
Definition: winerror.h:318
#define ERROR_SERVICE_MARKED_FOR_DELETE
Definition: winerror.h:947
#define ERROR_INVALID_SERVICE_ACCOUNT
Definition: winerror.h:932
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:937
#define ERROR_BAD_EXE_FORMAT
Definition: winerror.h:373
#define ERROR_SERVICE_DOES_NOT_EXIST
Definition: winerror.h:935
#define ERROR_DUPLICATE_SERVICE_NAME
Definition: winerror.h:953
#define ERROR_ALREADY_REGISTERED
Definition: winerror.h:1074
#define ERROR_SERVICE_EXISTS
Definition: winerror.h:948
#define ERROR_SERVICE_DISABLED
Definition: winerror.h:933
#define RPC_S_SERVER_UNAVAILABLE
Definition: winerror.h:1389
#define ERROR_SERVICE_REQUEST_TIMEOUT
Definition: winerror.h:928
#define RPC_S_INVALID_NET_ADDR
Definition: winerror.h:1374
#define ERROR_PROCESS_ABORTED
Definition: winerror.h:942
#define ERROR_DATABASE_DOES_NOT_EXIST
Definition: winerror.h:940
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193