crypt32: Introduce function to encode an array of items as a set.
[wine] / dlls / advapi32 / tests / service.c
1 /*
2  * Unit tests for service functions
3  *
4  * Copyright (c) 2007 Paul Vriens
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winreg.h"
27 #include "winsvc.h"
28 #include "lmcons.h"
29
30 #include "wine/test.h"
31
32 static void test_open_scm(void)
33 {
34     SC_HANDLE scm_handle;
35
36     /* No access rights */
37     SetLastError(0xdeadbeef);
38     scm_handle = OpenSCManagerA(NULL, NULL, 0);
39     ok(scm_handle != NULL, "Expected success\n");
40     ok(GetLastError() == ERROR_SUCCESS    /* W2K3, Vista */ ||
41        GetLastError() == 0xdeadbeef       /* NT4, XP */ ||
42        GetLastError() == ERROR_IO_PENDING /* W2K */,
43        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
44     CloseServiceHandle(scm_handle);
45
46     /* Unknown database name */
47     SetLastError(0xdeadbeef);
48     scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
49     ok(!scm_handle, "Expected failure\n");
50     ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
51     CloseServiceHandle(scm_handle); /* Just in case */
52
53     /* MSDN says only ServiceActive is allowed, or NULL */
54     SetLastError(0xdeadbeef);
55     scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
56     ok(!scm_handle, "Expected failure\n");
57     ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
58     CloseServiceHandle(scm_handle); /* Just in case */
59
60     /* Remote unknown host */
61     SetLastError(0xdeadbeef);
62     scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
63     ok(!scm_handle, "Expected failure\n");
64     todo_wine
65     ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE, "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError());
66     CloseServiceHandle(scm_handle); /* Just in case */
67
68     /* Proper call with an empty hostname */
69     SetLastError(0xdeadbeef);
70     scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
71     ok(scm_handle != NULL, "Expected success\n");
72     ok(GetLastError() == ERROR_SUCCESS          /* W2K3, Vista */ ||
73        GetLastError() == ERROR_ENVVAR_NOT_FOUND /* NT4 */ ||
74        GetLastError() == 0xdeadbeef             /* XP */ ||
75        GetLastError() == ERROR_IO_PENDING       /* W2K */,
76        "Expected ERROR_SUCCESS, ERROR_IO_PENDING, ERROR_ENVVAR_NOT_FOUND or 0xdeadbeef, got %d\n", GetLastError());
77     CloseServiceHandle(scm_handle);
78
79     /* Again a correct one */
80     SetLastError(0xdeadbeef);
81     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
82     ok(scm_handle != NULL, "Expected success\n");
83     ok(GetLastError() == ERROR_SUCCESS    /* W2K3, Vista */ ||
84        GetLastError() == 0xdeadbeef       /* NT4, XP */ ||
85        GetLastError() == ERROR_IO_PENDING /* W2K */,
86        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
87     CloseServiceHandle(scm_handle);
88 }
89
90 static void test_open_svc(void)
91 {
92     SC_HANDLE scm_handle, svc_handle;
93
94     /* All NULL (invalid access rights) */
95     SetLastError(0xdeadbeef);
96     svc_handle = OpenServiceA(NULL, NULL, 0);
97     ok(!svc_handle, "Expected failure\n");
98     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
99
100     /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
101
102     /* NULL service */
103     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
104     SetLastError(0xdeadbeef);
105     svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
106     ok(!svc_handle, "Expected failure\n");
107     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, XP, W2K3, Vista */ ||
108        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
109        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
110
111     /* Non-existent service */
112     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
113     SetLastError(0xdeadbeef);
114     svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
115     ok(!svc_handle, "Expected failure\n");
116     ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
117     CloseServiceHandle(scm_handle);
118
119     /* Proper SCM handle but different access rights */
120     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
121     SetLastError(0xdeadbeef);
122     svc_handle = OpenServiceA(scm_handle, "Spooler", GENERIC_WRITE);
123     if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
124         skip("Not enough rights to get a handle to the service\n");
125     else
126     {
127         ok(svc_handle != NULL, "Expected success\n");
128         ok(GetLastError() == ERROR_SUCCESS    /* W2K3, Vista */ ||
129            GetLastError() == ERROR_IO_PENDING /* W2K */ ||
130            GetLastError() == 0xdeadbeef       /* XP, NT4 */,
131            "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
132         CloseServiceHandle(svc_handle);
133     }
134     CloseServiceHandle(scm_handle);
135 }
136
137 static void test_create_delete_svc(void)
138 {
139     SC_HANDLE scm_handle, svc_handle1;
140     CHAR username[UNLEN + 1];
141     DWORD user_size = UNLEN + 1;
142     CHAR account[UNLEN + 3];
143     static const CHAR servicename         [] = "Winetest";
144     static const CHAR pathname            [] = "we_dont_care.exe";
145     static const CHAR empty               [] = "";
146     static const CHAR spooler             [] = "Spooler";           /* Should be available on all platforms */
147     static const CHAR password            [] = "secret";
148     BOOL spooler_exists = FALSE;
149     BOOL ret;
150     CHAR display[4096];
151     DWORD display_size = sizeof(display);
152
153     /* Get the username and turn it into an account to be used in some tests */
154     GetUserNameA(username, &user_size);
155     lstrcpy(account, ".\\");
156     lstrcat(account, username);
157
158     /* All NULL */
159     SetLastError(0xdeadbeef);
160     svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
161     ok(!svc_handle1, "Expected failure\n");
162     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
163
164     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
165
166     /* Only a valid handle to the Service Control Manager */
167     SetLastError(0xdeadbeef);
168     svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
169     ok(!svc_handle1, "Expected failure\n");
170     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, W2K3, XP, Vista */ ||
171        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
172        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
173
174     /* Now with a servicename */
175     SetLastError(0xdeadbeef);
176     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
177     ok(!svc_handle1, "Expected failure\n");
178     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, W2K3, XP, Vista */ ||
179        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
180        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
181
182     /* Or just a binary name */
183     SetLastError(0xdeadbeef);
184     svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
185     ok(!svc_handle1, "Expected failure\n");
186     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, W2K3, XP, Vista */ ||
187        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
188        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
189
190     /* Both servicename and binary name (We only have connect rights) */
191     SetLastError(0xdeadbeef);
192     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
193     ok(!svc_handle1, "Expected failure\n");
194     ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
195
196     /* They can even be empty at this stage of parameter checking */
197     SetLastError(0xdeadbeef);
198     svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
199     ok(!svc_handle1, "Expected failure\n");
200     ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
201
202     SetLastError(0xdeadbeef);
203     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
204     ok(!svc_handle1, "Expected failure\n");
205     ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
206
207     /* Open the Service Control Manager with minimal rights for creation
208      * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
209      */
210     CloseServiceHandle(scm_handle);
211     SetLastError(0xdeadbeef);
212     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
213     if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
214     {
215         skip("Not enough rights to get a handle to the manager\n");
216         return;
217     }
218
219     /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
220
221     /* Empty strings for servicename and binary name are checked */
222     SetLastError(0xdeadbeef);
223     svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
224     ok(!svc_handle1, "Expected failure\n");
225     ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
226
227     SetLastError(0xdeadbeef);
228     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
229     ok(!svc_handle1, "Expected failure\n");
230     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
231
232     SetLastError(0xdeadbeef);
233     svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
234     ok(!svc_handle1, "Expected failure\n");
235     ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
236
237     /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
238      * an ERROR_INVALID_PARAMETER)
239      */
240     SetLastError(0xdeadbeef);
241     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
242                                  SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
243     ok(!svc_handle1, "Expected failure\n");
244     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
245
246     /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
247
248     /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
249      * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
250      */
251     SetLastError(0xdeadbeef);
252     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
253                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
254     ok(!svc_handle1, "Expected failure\n");
255     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
256
257     /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
258     SetLastError(0xdeadbeef);
259     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
260                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
261     ok(!svc_handle1, "Expected failure\n");
262     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
263
264     /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
265      * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
266      */
267     SetLastError(0xdeadbeef);
268     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
269                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
270     ok(!svc_handle1, "Expected failure\n");
271     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
272
273     /* Illegal (start-type is not a mask and should only be one of the possibilities)
274      * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
275      * it's most likely not the wanted start-type)
276      */
277     SetLastError(0xdeadbeef);
278     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
279                                  SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
280     ok(!svc_handle1, "Expected failure\n");
281     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
282
283     /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
284     SetLastError(0xdeadbeef);
285     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
286                                  SERVICE_BOOT_START, 0, pathname, 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     /* The service already exists (check first, just in case) */
291     svc_handle1 = OpenServiceA(scm_handle, spooler, GENERIC_READ);
292     if (svc_handle1)
293     {
294         spooler_exists = TRUE;
295         CloseServiceHandle(svc_handle1);
296         SetLastError(0xdeadbeef);
297         svc_handle1 = CreateServiceA(scm_handle, spooler, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
298                                      SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
299         ok(!svc_handle1, "Expected failure\n");
300         ok(GetLastError() == ERROR_SERVICE_EXISTS, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
301     }
302     else
303         skip("Spooler service doesn't exist\n");
304
305     /* To find an existing displayname we check the 'Spooler' service. Although the registry
306      * doesn't show DisplayName on NT4, this call will return a displayname which is equal
307      * to the servicename and can't be used as well for a new displayname.
308      */
309     if (spooler_exists)
310     {
311         ret = GetServiceDisplayNameA(scm_handle, spooler, display, &display_size);
312
313         if (!ret)
314             skip("Could not retrieve a displayname for the Spooler service\n");
315         else
316         {
317             svc_handle1 = CreateServiceA(scm_handle, servicename, display, 0, SERVICE_WIN32_OWN_PROCESS,
318                                          SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
319             ok(!svc_handle1, "Expected failure\n");
320             ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME,
321                "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
322         }
323     }
324     else
325         skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
326
327     /* Windows doesn't care about the access rights for creation (which makes
328      * sense as there is no service yet) as long as there are sufficient
329      * rights to the manager.
330      */
331     SetLastError(0xdeadbeef);
332     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
333                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
334     ok(svc_handle1 != NULL, "Could not create the service : %d\n", GetLastError());
335     ok(GetLastError() == ERROR_SUCCESS    /* W2K3, Vista */ ||
336        GetLastError() == 0xdeadbeef       /* NT4, XP */ ||
337        GetLastError() == ERROR_IO_PENDING /* W2K */,
338        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
339
340     /* DeleteService however must have proper rights */
341     SetLastError(0xdeadbeef);
342     ret = DeleteService(svc_handle1);
343     ok(!ret, "Expected failure\n");
344     ok(GetLastError() == ERROR_ACCESS_DENIED,
345        "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
346
347     /* Open the service with minimal rights for deletion.
348      * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
349      */
350     CloseServiceHandle(svc_handle1);
351     svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
352
353     /* Now that we have the proper rights, we should be able to delete */
354     SetLastError(0xdeadbeef);
355     ret = DeleteService(svc_handle1);
356     ok(ret, "Expected success\n");
357     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */ ||
358        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */ ||
359        GetLastError() == ERROR_IO_PENDING /* W2K */,
360        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
361
362     CloseServiceHandle(svc_handle1);
363
364     CloseServiceHandle(scm_handle);
365
366     /* Wait a while. One of the following tests also does a CreateService for the
367      * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
368      * error if we do this to quick. Vista seems more picky then the others.
369      */
370     Sleep(1000);
371
372     /* And a final NULL check */
373     SetLastError(0xdeadbeef);
374     ret = DeleteService(NULL);
375     ok(!ret, "Expected failure\n");
376     ok(GetLastError() == ERROR_INVALID_HANDLE,
377         "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
378 }
379
380 static void test_get_displayname(void)
381 {
382     SC_HANDLE scm_handle, svc_handle;
383     BOOL ret;
384     CHAR displayname[4096];
385     WCHAR displaynameW[2048];
386     DWORD displaysize, tempsize, tempsizeW;
387     static const CHAR spooler[] = "Spooler";
388     static const WCHAR spoolerW[] = {'S','p','o','o','l','e','r',0};
389
390     /* Having NULL for the size of the buffer will crash on W2K3 */
391
392     SetLastError(0xdeadbeef);
393     ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
394     ok(!ret, "Expected failure\n");
395     ok(GetLastError() == ERROR_INVALID_HANDLE,
396        "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
397
398     scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
399
400     SetLastError(0xdeadbeef);
401     ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
402     ok(!ret, "Expected failure\n");
403     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, XP, W2K3, Vista */ ||
404        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
405        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
406
407     SetLastError(0xdeadbeef);
408     displaysize = sizeof(displayname);
409     ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
410     ok(!ret, "Expected failure\n");
411     ok(GetLastError() == ERROR_INVALID_ADDRESS   /* W2K, XP, W2K3, Vista */ ||
412        GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
413        "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
414
415     /* Check if 'Spooler' exists */
416     svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
417     if (!svc_handle)
418     {
419         skip("Spooler service doesn't exist\n");
420         return;
421     }
422     CloseServiceHandle(svc_handle);
423
424     /* Retrieve the needed size for the buffer */
425     SetLastError(0xdeadbeef);
426     displaysize = -1;
427     ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
428     ok(!ret, "Expected failure\n");
429     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
430        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
431
432     SetLastError(0xdeadbeef);
433     tempsize = displaysize;
434     displaysize *= 2;
435     ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
436     ok(ret, "Expected success\n");
437     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */ ||
438        GetLastError() == ERROR_IO_PENDING /* W2K */ ||
439        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */,
440        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
441     /* Test that shows that if the buffersize is enough, it's not changed */
442     ok(displaysize == tempsize * 2, "Didn't expect a change in the needed size of the buffer\n");
443     todo_wine
444     ok(lstrlen(displayname) == tempsize/2,
445        "Expected the buffer to be twice the length of the string\n") ;
446
447     /* Do the last 2 tests also for GetServiceDisplayNameW */
448     SetLastError(0xdeadbeef);
449     displaysize = -1;
450     ret = GetServiceDisplayNameW(scm_handle, spoolerW, NULL, &displaysize);
451     ok(!ret, "Expected failure\n");
452     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
453        "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
454
455     SetLastError(0xdeadbeef);
456     tempsizeW = displaysize;
457     displaysize *= 2;
458     ret = GetServiceDisplayNameW(scm_handle, spoolerW, displaynameW, &displaysize);
459     ok(ret, "Expected success\n");
460     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */ ||
461        GetLastError() == ERROR_IO_PENDING /* W2K */ ||
462        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */,
463        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
464     /* Test that shows that the buffersize is changed to the needed size */
465     todo_wine
466     {
467     ok(displaysize == tempsizeW, "Did expect a change in the needed size of the buffer\n");
468     ok(lstrlenW(displaynameW) == displaysize,
469        "Expected the buffer to be the length of the string\n") ;
470     ok(tempsize / 2 == tempsizeW,
471        "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
472     }
473
474     CloseServiceHandle(scm_handle);
475 }
476
477 static void test_close(void)
478 {
479     SC_HANDLE handle;
480     BOOL ret;
481
482     /* NULL handle */
483     SetLastError(0xdeadbeef);
484     ret = CloseServiceHandle(NULL);
485     todo_wine
486     {
487     ok(!ret, "Expected failure\n");
488     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
489     }
490
491     /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
492
493     /* Proper call */
494     handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
495     SetLastError(0xdeadbeef);
496     ret = CloseServiceHandle(handle);
497     ok(ret, "Expected success\n");
498     ok(GetLastError() == ERROR_IO_PENDING /* W2K */ ||
499        GetLastError() == ERROR_SUCCESS    /* W2K3 */ ||
500        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */,
501        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
502 }
503
504 static void test_sequence(void)
505 {
506     SC_HANDLE scm_handle, svc_handle;
507     BOOL ret;
508     QUERY_SERVICE_CONFIGA *config;
509     DWORD given, needed;
510     static const CHAR servicename [] = "Winetest";
511     static const CHAR displayname [] = "Winetest dummy service";
512     static const CHAR pathname    [] = "we_dont_care.exe";
513     static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0\0";
514     static const CHAR password    [] = "";
515     static const CHAR empty       [] = "";
516     static const CHAR localsystem [] = "LocalSystem";
517
518     SetLastError(0xdeadbeef);
519     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
520
521     if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
522     {
523         skip("Not enough rights to get a handle to the manager\n");
524         return;
525     }
526     else
527         ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
528
529     if (!scm_handle) return;
530
531     /* Create a dummy service */
532     SetLastError(0xdeadbeef);
533     svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
534         SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
535         pathname, NULL, NULL, dependencies, NULL, password);
536
537     if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
538     {
539         /* We try and open the service and do the rest of the tests. Some could
540          * fail if the tests were changed between these runs.
541          */
542         trace("Deletion probably didn't work last time\n");
543         SetLastError(0xdeadbeef);
544         svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
545         if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
546         {
547             skip("Not enough rights to open the service\n");
548             CloseServiceHandle(scm_handle);        
549             return;
550         }
551         ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
552     }
553     else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
554     {
555         skip("Not enough rights to create the service\n");
556         CloseServiceHandle(scm_handle);        
557         return;
558     }
559     else
560         ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
561
562     if (!svc_handle) return;
563
564     /* TODO:
565      * Before we do a QueryServiceConfig we should check the registry. This will make sure
566      * that the correct keys are used.
567      */
568
569     /* Request the size for the buffer */
570     SetLastError(0xdeadbeef);
571     ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
572     ok(!ret, "Expected failure\n");
573     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
574
575     config = HeapAlloc(GetProcessHeap(), 0, needed);
576     given = needed;
577     SetLastError(0xdeadbeef);
578     ret = QueryServiceConfigA(svc_handle, config, given, &needed);
579     ok(ret, "Expected success\n");
580     todo_wine
581     {
582     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */||
583        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */ ||
584        GetLastError() == ERROR_IO_PENDING /* W2K */,
585         "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
586     ok(given == needed, "Expected the given (%d) and needed (%d) buffersizes to be equal\n", given, needed);
587     }
588     ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
589         config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
590     ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
591         "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
592     ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
593     ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
594     ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
595     ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
596     ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
597     /* TODO: Show the double 0 terminated string */
598     todo_wine
599     {
600     ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
601     ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
602     }
603     ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
604     
605     SetLastError(0xdeadbeef);
606     ret = DeleteService(svc_handle);
607     ok(ret, "Expected success\n");
608     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */||
609        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */ ||
610        GetLastError() == ERROR_IO_PENDING /* W2K */,
611         "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
612     
613     CloseServiceHandle(svc_handle);
614
615     /* Wait a while. The following test does a CreateService again */
616     Sleep(1000);
617
618     CloseServiceHandle(scm_handle);
619 }
620
621 static void test_refcount(void)
622 {
623     SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
624     static const CHAR servicename         [] = "Winetest";
625     static const CHAR pathname            [] = "we_dont_care.exe";
626     BOOL ret;
627
628     /* Get a handle to the Service Control Manager */
629     SetLastError(0xdeadbeef);
630     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
631     if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
632     {
633         skip("Not enough rights to get a handle to the manager\n");
634         return;
635     }
636
637     /* Create a service */
638     svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
639                                  SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
640                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
641     ok(svc_handle1 != NULL, "Expected success\n");
642
643     /* Get a handle to this new service */
644     svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
645     ok(svc_handle2 != NULL, "Expected success\n");
646
647     /* Get another handle to this new service */
648     svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
649     ok(svc_handle3 != NULL, "Expected success\n");
650
651     /* Check if we can close the handle to the Service Control Manager */
652     ret = CloseServiceHandle(scm_handle);
653     ok(ret, "Expected success\n");
654
655     /* Get a new handle to the Service Control Manager */
656     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
657     ok(scm_handle != NULL, "Expected success\n");
658
659     /* Get a handle to this new service */
660     svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
661     ok(svc_handle4 != NULL, "Expected success\n");
662
663     /* Delete the service */
664     ret = DeleteService(svc_handle4);
665     ok(ret, "Expected success\n");
666
667     /* We cannot create the same service again as it's still marked as 'being deleted'.
668      * The reason is that we still have 4 open handles to this service eventhough we
669      * closed the handle to the Service Control Manager in between.
670      */
671     SetLastError(0xdeadbeef);
672     svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
673                                  SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
674                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
675     todo_wine
676     {
677     ok(!svc_handle5, "Expected failure\n");
678     ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
679        "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
680     }
681
682     /* FIXME: Remove this when Wine is fixed */
683     if (svc_handle5)
684     {
685         DeleteService(svc_handle5);
686         CloseServiceHandle(svc_handle5);
687     }
688
689     /* Close all the handles to the service and try again */
690     ret = CloseServiceHandle(svc_handle4);
691     ok(ret, "Expected success\n");
692     ret = CloseServiceHandle(svc_handle3);
693     ok(ret, "Expected success\n");
694     ret = CloseServiceHandle(svc_handle2);
695     ok(ret, "Expected success\n");
696     ret = CloseServiceHandle(svc_handle1);
697     ok(ret, "Expected success\n");
698
699     /* Wait a while. Doing a CreateService to soon will result again
700      * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
701      */
702     Sleep(1000);
703
704     /* We succeed now as all handles are closed (tested this also with a long SLeep() */
705     svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
706                                  SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
707                                  SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
708     ok(svc_handle5 != NULL, "Expected success\n");
709
710     /* Delete the service */
711     ret = DeleteService(svc_handle5);
712     ok(ret, "Expected success\n");
713
714     /* Wait a while. Just in case one of the following tests does a CreateService again */
715     Sleep(1000);
716
717     CloseServiceHandle(svc_handle5);
718     CloseServiceHandle(scm_handle);
719 }
720
721 START_TEST(service)
722 {
723     SC_HANDLE scm_handle;
724
725     /* Bail out if we are on win98 */
726     SetLastError(0xdeadbeef);
727     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
728
729     if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
730     {
731         skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
732         return;
733     }
734     CloseServiceHandle(scm_handle);
735
736     /* First some parameter checking */
737     test_open_scm();
738     test_open_svc();
739     test_create_delete_svc();
740     test_get_displayname();
741     test_close();
742     /* Test the creation, querying and deletion of a service */
743     test_sequence();
744     /* The main reason for this test is to check if any refcounting is used
745      * and what the rules are
746      */
747     test_refcount();
748 }