ntdll: Added parsing of hash attributes in manifests.
[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_close(void)
381 {
382     SC_HANDLE handle;
383     BOOL ret;
384
385     /* NULL handle */
386     SetLastError(0xdeadbeef);
387     ret = CloseServiceHandle(NULL);
388     todo_wine
389     {
390     ok(!ret, "Expected failure\n");
391     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
392     }
393
394     /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
395
396     /* Proper call */
397     handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
398     SetLastError(0xdeadbeef);
399     ret = CloseServiceHandle(handle);
400     ok(ret, "Expected success\n");
401     ok(GetLastError() == ERROR_IO_PENDING /* W2K */ ||
402        GetLastError() == ERROR_SUCCESS    /* W2K3 */ ||
403        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */,
404        "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
405 }
406
407 static void test_sequence(void)
408 {
409     SC_HANDLE scm_handle, svc_handle;
410     BOOL ret;
411     QUERY_SERVICE_CONFIGA *config;
412     DWORD given, needed;
413     static const CHAR servicename [] = "Winetest";
414     static const CHAR displayname [] = "Winetest dummy service";
415     static const CHAR pathname    [] = "we_dont_care.exe";
416     static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0\0";
417     static const CHAR password    [] = "";
418     static const CHAR empty       [] = "";
419     static const CHAR localsystem [] = "LocalSystem";
420
421     SetLastError(0xdeadbeef);
422     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
423
424     if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
425     {
426         skip("Not enough rights to get a handle to the manager\n");
427         return;
428     }
429     else
430         ok(scm_handle != NULL, "Could not get a handle to the manager: %d\n", GetLastError());
431
432     if (!scm_handle) return;
433
434     /* Create a dummy service */
435     SetLastError(0xdeadbeef);
436     svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
437         SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
438         pathname, NULL, NULL, dependencies, NULL, password);
439
440     if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
441     {
442         /* We try and open the service and do the rest of the tests. Some could
443          * fail if the tests were changed between these runs.
444          */
445         trace("Deletion probably didn't work last time\n");
446         SetLastError(0xdeadbeef);
447         svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
448         if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
449         {
450             skip("Not enough rights to open the service\n");
451             CloseServiceHandle(scm_handle);        
452             return;
453         }
454         ok(svc_handle != NULL, "Could not open the service : %d\n", GetLastError());
455     }
456     else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
457     {
458         skip("Not enough rights to create the service\n");
459         CloseServiceHandle(scm_handle);        
460         return;
461     }
462     else
463         ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
464
465     if (!svc_handle) return;
466
467     /* TODO:
468      * Before we do a QueryServiceConfig we should check the registry. This will make sure
469      * that the correct keys are used.
470      */
471
472     /* Request the size for the buffer */
473     SetLastError(0xdeadbeef);
474     ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
475     ok(!ret, "Expected failure\n");
476     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
477
478     config = HeapAlloc(GetProcessHeap(), 0, needed);
479     given = needed;
480     SetLastError(0xdeadbeef);
481     ret = QueryServiceConfigA(svc_handle, config, given, &needed);
482     ok(ret, "Expected success\n");
483     todo_wine
484     {
485     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */||
486        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */ ||
487        GetLastError() == ERROR_IO_PENDING /* W2K */,
488         "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
489     ok(given == needed, "Expected the given (%d) and needed (%d) buffersizes to be equal\n", given, needed);
490     }
491     ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
492         config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
493     ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
494         "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType);
495     ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType);
496     ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %d\n", config->dwErrorControl);
497     ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
498     ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
499     ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId);
500     /* TODO: Show the double 0 terminated string */
501     todo_wine
502     {
503     ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
504     ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
505     }
506     ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
507     
508     SetLastError(0xdeadbeef);
509     ret = DeleteService(svc_handle);
510     ok(ret, "Expected success\n");
511     ok(GetLastError() == ERROR_SUCCESS    /* W2K3 */||
512        GetLastError() == 0xdeadbeef       /* NT4, XP, Vista */ ||
513        GetLastError() == ERROR_IO_PENDING /* W2K */,
514         "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError());
515     
516     CloseServiceHandle(svc_handle);
517     CloseServiceHandle(scm_handle);
518 }
519
520 START_TEST(service)
521 {
522     SC_HANDLE scm_handle;
523
524     /* Bail out if we are on win98 */
525     SetLastError(0xdeadbeef);
526     scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
527
528     if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
529     {
530         skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
531         return;
532     }
533     CloseServiceHandle(scm_handle);
534
535     /* First some parameter checking */
536     test_open_scm();
537     test_open_svc();
538     test_create_delete_svc();
539     test_close();
540     /* Test the creation, querying and deletion of a service */
541     test_sequence();
542 }