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