2 * Unit tests for service functions
4 * Copyright (c) 2007 Paul Vriens
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.
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.
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
21 #define WIN32_NO_STATUS
22 #define WIN32_LEAN_AND_MEAN
36 #include "wine/test.h"
38 static const CHAR spooler
[] = "Spooler"; /* Should be available on all platforms */
39 static CHAR selfname
[MAX_PATH
];
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
,
54 static BOOL (WINAPI
*pQueryServiceObjectSecurity
)(SC_HANDLE
, SECURITY_INFORMATION
,
55 PSECURITY_DESCRIPTOR
, DWORD
, LPDWORD
);
56 static DWORD (WINAPI
*pNotifyServiceStatusChangeW
)(SC_HANDLE
,DWORD
,SERVICE_NOTIFYW
*);
58 static void init_function_pointers(void)
60 HMODULE hadvapi32
= GetModuleHandleA("advapi32.dll");
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");
73 static void test_open_scm(void)
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
);
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 */
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 */
97 /* Remote unknown host */
98 SetLastError(0xdeadbeef);
99 scm_handle
= OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
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());
106 CloseServiceHandle(scm_handle
); /* Just in case */
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
);
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
);
122 static void test_open_svc(void)
124 SC_HANDLE scm_handle
, svc_handle
;
125 CHAR displayname
[4096];
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());
134 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
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
);
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
);
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");
162 ok(svc_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
163 CloseServiceHandle(svc_handle
);
166 /* Test to show we can't open a service with the displayname */
168 /* Retrieve the needed size for the buffer */
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.
176 if (!lstrcmpiA(spooler
, displayname
))
178 skip("displayname equals servicename\n");
179 CloseServiceHandle(scm_handle
);
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());
188 CloseServiceHandle(svc_handle
);
190 CloseServiceHandle(scm_handle
);
193 static void test_create_delete_svc(void)
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
;
206 DWORD display_size
= sizeof(display
);
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
);
214 sprintf(account
, ".\\%s", username
);
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());
222 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
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());
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());
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());
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());
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());
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());
265 /* Open the Service Control Manager with minimal rights for creation
266 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
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
))
273 skip("Not enough rights to get a handle to the manager\n");
277 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
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());
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());
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());
295 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
296 * an ERROR_INVALID_PARAMETER)
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());
304 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
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)
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());
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());
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.
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());
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)
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());
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());
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());
356 /* The service already exists (check first, just in case) */
357 svc_handle1
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
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());
369 skip("Spooler service doesn't exist\n");
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.
377 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, display
, &display_size
);
380 skip("Could not retrieve a displayname for the Spooler service\n");
383 svc_handle1
= CreateServiceA(scm_handle
, servicename
, display
, 0, SERVICE_WIN32_OWN_PROCESS
,
384 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
385 ok(!svc_handle1
, "Expected failure for display name '%s'\n", display
);
386 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME
,
387 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
391 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
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.
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());
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());
409 /* Open the service with minimal rights for deletion.
410 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
412 CloseServiceHandle(svc_handle1
);
413 svc_handle1
= OpenServiceA(scm_handle
, servicename
, DELETE
);
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());
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
);
425 CloseServiceHandle(svc_handle1
);
426 CloseServiceHandle(scm_handle
);
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.
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());
442 static void test_get_displayname(void)
444 SC_HANDLE scm_handle
, svc_handle
;
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";
456 /* Having NULL for the size of the buffer will crash on W2K3 */
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());
464 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
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());
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());
481 /* Test for nonexistent service */
482 SetLastError(0xdeadbeef);
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());
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
);
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");
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");
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");
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");
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");
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");
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");
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");
568 /* Check if 'Spooler' exists */
569 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
572 skip("Spooler service doesn't exist\n");
573 CloseServiceHandle(scm_handle
);
576 CloseServiceHandle(svc_handle
);
578 /* Retrieve the needed size for the buffer */
579 SetLastError(0xdeadbeef);
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
;
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
);
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());
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.
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");
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");
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") ;
630 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
631 SetLastError(0xdeadbeef);
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());
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());
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());
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");
668 CloseServiceHandle(scm_handle
);
670 /* Test for a service without a displayname (which is valid). This should return
671 * the servicename itself.
673 SetLastError(0xdeadbeef);
674 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
675 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
677 skip("Not enough rights to get a handle to the manager\n");
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());
688 CloseServiceHandle(scm_handle
);
692 /* Retrieve the needed size for the buffer */
693 SetLastError(0xdeadbeef);
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());
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());
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
);
719 /* Delete the service */
720 ret
= DeleteService(svc_handle
);
721 ok(ret
, "Expected success (err=%d)\n", GetLastError());
723 CloseServiceHandle(svc_handle
);
724 CloseServiceHandle(scm_handle
);
726 /* Wait a while. Just in case one of the following tests does a CreateService again */
730 static void test_get_servicekeyname(void)
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
;
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};
743 /* Having NULL for the size of the buffer will crash on W2K3 */
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());
751 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
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
);
762 /* Valid handle and buffer but no displayname */
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
);
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
);
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");
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");
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");
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");
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");
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");
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");
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");
852 /* Check if 'Spooler' exists */
853 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
856 skip("Spooler service doesn't exist\n");
857 CloseServiceHandle(scm_handle
);
860 CloseServiceHandle(svc_handle
);
862 /* Get the displayname for the 'Spooler' service */
863 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
864 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
866 /* Retrieve the needed size for the buffer */
867 SetLastError(0xdeadbeef);
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());
874 /* Valid call with the correct buffersize */
875 SetLastError(0xdeadbeef);
876 tempsize
= servicesize
;
878 ret
= GetServiceKeyNameA(scm_handle
, displayname
, servicename
, &servicesize
);
879 ok(ret
, "Expected success, got error %u\n", GetLastError());
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") ;
889 MultiByteToWideChar(CP_ACP
, 0, displayname
, -1, displaynameW
, sizeof(displaynameW
)/2);
890 SetLastError(0xdeadbeef);
892 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
893 ok(ret
, "Expected success, got error %u\n", GetLastError());
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") ;
902 SetLastError(0xdeadbeef);
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");
910 CloseServiceHandle(scm_handle
);
913 static void test_query_svc(void)
915 SC_HANDLE scm_handle
, svc_handle
;
917 SERVICE_STATUS status
;
918 SERVICE_STATUS_PROCESS
*statusproc
;
919 DWORD bufsize
, needed
;
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());
928 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
930 /* Check if 'Spooler' exists.
931 * Open with not enough rights to query the status.
933 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
936 skip("Spooler service doesn't exist\n");
937 CloseServiceHandle(scm_handle
);
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());
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());
954 /* Open the service with just enough rights.
955 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
957 CloseServiceHandle(svc_handle
);
958 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
960 SetLastError(0xdeadbeef);
961 ret
= QueryServiceStatus(svc_handle
, &status
);
962 ok(ret
, "Expected success, got error %u\n", GetLastError());
964 CloseServiceHandle(svc_handle
);
966 /* More or less the same tests for QueryServiceStatusEx */
967 if (!pQueryServiceStatusEx
)
969 win_skip( "QueryServiceStatusEx not available\n" );
970 CloseServiceHandle(scm_handle
);
974 /* Open service with not enough rights to query the status */
975 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
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());
984 /* Passing a NULL parameter for the needed buffer size
985 * will crash on anything but NT4.
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
)
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());
1001 /* Pass a correct buffer and buffersize but a NULL handle */
1002 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
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
);
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
)
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());
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
);
1034 /* Open the service with just enough rights. */
1035 CloseServiceHandle(svc_handle
);
1036 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
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");
1048 ok(statusproc
->dwProcessId
== 0,
1049 "Expect no process id for this stopped service\n");
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());
1058 HeapFree(GetProcessHeap(), 0, statusproc
);
1060 CloseServiceHandle(svc_handle
);
1061 CloseServiceHandle(scm_handle
);
1064 static void test_enum_svc(void)
1066 SC_HANDLE scm_handle
;
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
;
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());
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());
1090 /* Open the service control manager with not enough rights at first */
1091 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
1244 /* Open the service control manager with the needed rights */
1245 CloseServiceHandle(scm_handle
);
1246 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
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());
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());
1271 /* Store the needed bytes */
1272 tempneeded
= needed
;
1274 /* Allocate the correct needed bytes */
1275 services
= HeapAlloc(GetProcessHeap(), 0, 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
);
1287 /* Store the number of returned services */
1288 tempreturned
= returned
;
1290 servicesW
= HeapAlloc(GetProcessHeap(), 0, 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
);
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());
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;
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());
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
);
1345 /* See if things add up */
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
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.
1354 * Both reasons make calculations for drivers not so useful
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
);
1365 servicecountactive
= returned
;
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
);
1375 servicecountinactive
= returned
;
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
);
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");
1389 /* Get all drivers and services
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).
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
);
1400 /* Loop through all those returned drivers and services */
1401 for (i
= 0; ret
&& i
< returned
; i
++)
1403 SERVICE_STATUS status
= services
[i
].ServiceStatus
;
1405 /* lpServiceName and lpDisplayName should always be filled */
1406 ok(services
[i
].lpServiceName
[0], "Expected a service name\n");
1407 ok(services
[i
].lpDisplayName
&& services
[i
].lpDisplayName
[0], "Expected a display name\n");
1409 /* Decrement the counters to see if the functions calls return the same
1410 * numbers as the contents of these structures.
1412 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1414 if (status
.dwCurrentState
== SERVICE_STOPPED
)
1415 servicecountinactive
--;
1417 servicecountactive
--;
1420 HeapFree(GetProcessHeap(), 0, services
);
1422 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1423 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1425 CloseServiceHandle(scm_handle
);
1427 /* More or less the same for EnumServicesStatusExA */
1428 if (!pEnumServicesStatusExA
)
1430 win_skip( "EnumServicesStatusExA not available\n" );
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());
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());
1448 /* Open the service control manager with not enough rights at first */
1449 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
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());
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());
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());
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());
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());
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());
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());
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());
1544 /* All parameters are correct, access rights are wrong but the
1545 * group name won't be checked yet.
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());
1559 /* Open the service control manager with the needed rights */
1560 CloseServiceHandle(scm_handle
);
1561 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
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());
1575 /* TODO: Create a test that makes sure we enumerate all services that don't
1576 * belong to a group. (specifying "").
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());
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");
1598 /* Store the needed bytes */
1599 tempneeded
= needed
;
1601 /* Allocate the correct needed bytes */
1602 exservices
= HeapAlloc(GetProcessHeap(), 0, 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
);
1614 /* Store the number of returned services */
1615 tempreturned
= returned
;
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());
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;
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());
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
);
1660 /* See if things add up */
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
);
1670 servicecountactive
= returned
;
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
);
1680 servicecountinactive
= returned
;
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
);
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");
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());
1703 /* Loop through all those returned drivers and services */
1704 for (i
= 0; i
< returned
; i
++)
1706 SERVICE_STATUS_PROCESS status
= exservices
[i
].ServiceStatusProcess
;
1708 /* lpServiceName and lpDisplayName should always be filled */
1709 ok(exservices
[i
].lpServiceName
[0], "Expected a service name\n");
1710 ok(exservices
[i
].lpDisplayName
&& exservices
[i
].lpDisplayName
[0], "Expected a display name\n");
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.
1716 if (status
.dwServiceType
& (SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_KERNEL_DRIVER
))
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");
1723 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1725 if (status
.dwCurrentState
!= SERVICE_STOPPED
)
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
);
1731 servicecountactive
--;
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
);
1739 servicecountinactive
--;
1743 HeapFree(GetProcessHeap(), 0, exservices
);
1745 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1746 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1748 CloseServiceHandle(scm_handle
);
1751 static void test_close(void)
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());
1762 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
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());
1771 static void test_sequence(void)
1773 SC_HANDLE scm_handle
, svc_handle
;
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";
1786 SetLastError(0xdeadbeef);
1787 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1789 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1791 skip("Not enough rights to get a handle to the manager\n");
1795 ok(scm_handle
!= NULL
, "Could not get a handle to the manager: %d\n", GetLastError());
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
);
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
);
1808 if (!svc_handle
&& (GetLastError() == ERROR_SERVICE_EXISTS
))
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.
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
))
1818 skip("Not enough rights to open the service\n");
1819 CloseServiceHandle(scm_handle
);
1822 ok(svc_handle
!= NULL
, "Could not open the service : %d\n", GetLastError());
1824 else if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1826 skip("Not enough rights to create the service\n");
1827 CloseServiceHandle(scm_handle
);
1832 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
1833 if ((svc_handle
!= NULL
) && (pGetSecurityInfo
!= NULL
))
1835 PSID sidOwner
, sidGroup
;
1837 PSECURITY_DESCRIPTOR pSD
;
1838 DWORD error
, n1
, n2
;
1842 /* Test using GetSecurityInfo to obtain security information */
1843 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, &sidOwner
,
1844 &sidGroup
, &dacl
, &sacl
, &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
);
1850 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
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
);
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
);
1865 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
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
);
1884 CloseServiceHandle(scm_handle
);
1889 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1890 * that the correct keys are used.
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());
1899 config
= HeapAlloc(GetProcessHeap(), 0, needed
);
1901 SetLastError(0xdeadbeef);
1902 ret
= QueryServiceConfigA(svc_handle
, config
, given
, &needed
);
1903 ok(ret
, "Expected success, got error %u\n", GetLastError());
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 */
1917 ok(!memcmp(config
->lpDependencies
, dependencies
, sizeof(dependencies
)), "Wrong string\n");
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
);
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());
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
);
1941 SetLastError(0xdeadbeef);
1942 ret
= DeleteService(svc_handle
);
1943 ok(ret
, "Expected success, got error %u\n", GetLastError());
1944 CloseServiceHandle(svc_handle
);
1946 /* Wait a while. The following test does a CreateService again */
1949 CloseServiceHandle(scm_handle
);
1950 HeapFree(GetProcessHeap(), 0, config
);
1953 static void test_queryconfig2(void)
1955 SC_HANDLE scm_handle
, svc_handle
;
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";
1968 if(!pQueryServiceConfig2A
)
1970 win_skip("function QueryServiceConfig2A not present\n");
1974 SetLastError(0xdeadbeef);
1975 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1979 if(GetLastError() == ERROR_ACCESS_DENIED
)
1980 skip("Not enough rights to get a handle to the manager\n");
1982 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
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
);
1994 if(GetLastError() == ERROR_SERVICE_EXISTS
)
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.
1999 trace("Deletion probably didn't work last time\n");
2000 SetLastError(0xdeadbeef);
2001 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2004 if(GetLastError() == ERROR_ACCESS_DENIED
)
2005 skip("Not enough rights to open the service\n");
2007 ok(FALSE
, "Could not open the service : %d\n", GetLastError());
2008 CloseServiceHandle(scm_handle
);
2012 if (GetLastError() == ERROR_ACCESS_DENIED
)
2014 skip("Not enough rights to create the service\n");
2015 CloseServiceHandle(scm_handle
);
2018 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
2021 CloseServiceHandle(scm_handle
);
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());
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());
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());
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());
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());
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
);
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
);
2065 SetLastError(0xdeadbeef);
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
);
2072 if(!pChangeServiceConfig2A
)
2074 win_skip("function ChangeServiceConfig2A not present\n");
2078 pConfig
->lpDescription
= (LPSTR
) description
;
2079 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
);
2080 ok(ret
, "ChangeServiceConfig2A failed\n");
2085 SetLastError(0xdeadbeef);
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
);
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());
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
);
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
);
2110 if(!pQueryServiceConfig2W
)
2112 win_skip("function QueryServiceConfig2W not present\n");
2115 SetLastError(0xdeadbeef);
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
);
2123 SetLastError(0xdeadbeef);
2124 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
,&needed
);
2125 ok(ret
, "expected QueryServiceConfig2W to succeed\n");
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
)
2132 /* Win2k3 and older */
2133 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
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
);
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());
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
);
2155 DeleteService(svc_handle
);
2157 CloseServiceHandle(svc_handle
);
2159 /* Wait a while. The following test does a CreateService again */
2162 CloseServiceHandle(scm_handle
);
2165 static DWORD
try_start_stop(SC_HANDLE svc_handle
, const char* name
, DWORD is_nt4
)
2169 SERVICE_STATUS status
;
2172 fprintf(stdout
, "ROSTESTS-56: Hello sysreg, I am awake\n");
2174 ret
= StartServiceA(svc_handle
, 0, NULL
);
2175 le1
= GetLastError();
2176 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2178 if (pQueryServiceStatusEx
)
2181 SERVICE_STATUS_PROCESS statusproc
;
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
);
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
);
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
);
2206 struct notify_data
{
2207 SERVICE_NOTIFYW notify
;
2211 static void CALLBACK
cb_stopped(void *user
)
2213 struct notify_data
*data
= user
;
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
);
2223 br
= StartServiceA(data
->svc
, 0, NULL
);
2224 ok(br
, "StartService failed: %u\n", GetLastError());
2227 static void CALLBACK
cb_running(void *user
)
2229 struct notify_data
*data
= user
;
2231 SERVICE_STATUS status
;
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
);
2240 br
= ControlService(data
->svc
, SERVICE_CONTROL_STOP
, &status
);
2241 ok(br
, "ControlService failed: %u\n", GetLastError());
2244 static void test_servicenotify(SC_HANDLE svc
)
2247 struct notify_data data
;
2249 if(!pNotifyServiceStatusChangeW
){
2250 win_skip("No NotifyServiceStatusChangeW\n");
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
;
2260 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2261 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2263 dr
= SleepEx(100, TRUE
);
2264 ok(dr
== WAIT_IO_COMPLETION
, "APC wasn't called\n");
2266 data
.notify
.pfnNotifyCallback
= &cb_running
;
2268 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2269 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2271 dr
= SleepEx(100, TRUE
);
2272 ok(dr
== WAIT_IO_COMPLETION
, "APC wasn't called\n");
2275 static void test_start_stop(void)
2278 SC_HANDLE scm_handle
, svc_handle
;
2280 static const char servicename
[] = "Winetest";
2281 char cmd
[MAX_PATH
+20];
2282 const char* displayname
;
2284 SetLastError(0xdeadbeef);
2285 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2288 if(GetLastError() == ERROR_ACCESS_DENIED
)
2289 skip("Not enough rights to get a handle to the manager\n");
2291 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
2296 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
2297 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
2299 /* Do some cleanup in case a previous run crashed */
2300 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2303 DeleteService(svc_handle
);
2304 CloseServiceHandle(svc_handle
);
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
);
2316 if(GetLastError() == ERROR_ACCESS_DENIED
)
2317 skip("Not enough rights to create the service\n");
2319 ok(FALSE
, "Could not create the service: %d\n", GetLastError());
2322 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2323 ok(le
== ERROR_SERVICE_DISABLED
, "%d != ERROR_SERVICE_DISABLED\n", le
);
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
);
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.
2336 win_skip("Skip some service start/stop tests on NT4\n");
2340 if (!winetest_interactive
)
2342 skip("ROSTESTS-151: Skipping service start timeout tests because they take too long. This is not a bug!\n");
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
);
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
);
2363 DeleteService(svc_handle
);
2364 CloseServiceHandle(svc_handle
);
2367 /* Wait a while. The following test does a CreateService again */
2370 CloseServiceHandle(scm_handle
);
2373 static void test_refcount(void)
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";
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
))
2385 skip("Not enough rights to get a handle to the manager\n");
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());
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());
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());
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());
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());
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());
2415 /* Delete the service */
2416 ret
= DeleteService(svc_handle4
);
2417 ok(ret
, "Expected success (err=%d)\n", GetLastError());
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.
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());
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());
2441 /* Wait a while. Doing a CreateService too soon will result again
2442 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
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());
2452 /* Delete the service */
2453 ret
= DeleteService(svc_handle5
);
2454 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2456 /* Wait a while. Just in case one of the following tests does a CreateService again */
2459 CloseServiceHandle(svc_handle5
);
2460 CloseServiceHandle(scm_handle
);
2463 static DWORD WINAPI
ctrl_handler(DWORD ctl
, DWORD type
, void *data
, void *user
)
2468 case SERVICE_CONTROL_STOP
:
2471 case SERVICE_CONTROL_INTERROGATE
:
2475 return ERROR_CALL_NOT_IMPLEMENTED
;
2478 static void WINAPI
service_main(DWORD argc
, char **argv
)
2480 SERVICE_STATUS_HANDLE st_handle
;
2482 HANDLE evt
= CreateEventW(0, FALSE
, FALSE
, 0);
2484 st_handle
= RegisterServiceCtrlHandlerExA("", &ctrl_handler
, evt
);
2486 st
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2487 st
.dwServiceSpecificExitCode
= 0;
2488 st
.dwCurrentState
= SERVICE_RUNNING
;
2489 st
.dwWin32ExitCode
= NO_ERROR
;
2491 st
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
2492 st
.dwCheckPoint
= 0;
2494 SetServiceStatus(st_handle
, &st
);
2496 WaitForSingleObject(evt
, 5000);
2498 st
.dwCurrentState
= SERVICE_STOPPED
;
2500 SetServiceStatus(st_handle
, &st
);
2503 static void run_service(void)
2506 SERVICE_TABLE_ENTRYA table
[] = {
2507 {empty
, &service_main
},
2511 StartServiceCtrlDispatcherA(table
);
2516 SC_HANDLE scm_handle
;
2520 myARGC
= winetest_get_mainargs(&myARGV
);
2521 GetFullPathNameA(myARGV
[0], sizeof(selfname
), selfname
, NULL
);
2524 if (strcmp(myARGV
[2], "serve") == 0)
2529 /* Bail out if we are on win98 */
2530 SetLastError(0xdeadbeef);
2531 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2533 if (!scm_handle
&& (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
))
2535 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2538 CloseServiceHandle(scm_handle
);
2540 init_function_pointers();
2542 /* First some parameter checking */
2545 test_create_delete_svc();
2546 test_get_displayname();
2547 test_get_servicekeyname();
2551 /* Test the creation, querying and deletion of a service */
2553 test_queryconfig2();
2555 /* The main reason for this test is to check if any refcounting is used
2556 * and what the rules are