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