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