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