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