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
33 #include "wine/test.h"
35 static const CHAR spooler
[] = "Spooler"; /* Should be available on all platforms */
36 static CHAR selfname
[MAX_PATH
];
38 static BOOL (WINAPI
*pChangeServiceConfig2A
)(SC_HANDLE
,DWORD
,LPVOID
);
39 static BOOL (WINAPI
*pEnumServicesStatusExA
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
40 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
41 LPDWORD
, LPDWORD
, LPCSTR
);
42 static BOOL (WINAPI
*pEnumServicesStatusExW
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
43 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
44 LPDWORD
, LPDWORD
, LPCWSTR
);
45 static DWORD (WINAPI
*pGetSecurityInfo
)(HANDLE
, SE_OBJECT_TYPE
, SECURITY_INFORMATION
,
46 PSID
*, PSID
*, PACL
*, PACL
*, PSECURITY_DESCRIPTOR
*);
47 static BOOL (WINAPI
*pQueryServiceConfig2A
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
48 static BOOL (WINAPI
*pQueryServiceConfig2W
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
49 static BOOL (WINAPI
*pQueryServiceStatusEx
)(SC_HANDLE
, SC_STATUS_TYPE
, LPBYTE
,
51 static BOOL (WINAPI
*pQueryServiceObjectSecurity
)(SC_HANDLE
, SECURITY_INFORMATION
,
52 PSECURITY_DESCRIPTOR
, DWORD
, LPDWORD
);
54 static void init_function_pointers(void)
56 HMODULE hadvapi32
= GetModuleHandleA("advapi32.dll");
58 pChangeServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "ChangeServiceConfig2A");
59 pEnumServicesStatusExA
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExA");
60 pEnumServicesStatusExW
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExW");
61 pGetSecurityInfo
= (void *)GetProcAddress(hadvapi32
, "GetSecurityInfo");
62 pQueryServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2A");
63 pQueryServiceConfig2W
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2W");
64 pQueryServiceStatusEx
= (void*)GetProcAddress(hadvapi32
, "QueryServiceStatusEx");
65 pQueryServiceObjectSecurity
= (void*)GetProcAddress(hadvapi32
, "QueryServiceObjectSecurity");
68 static void test_open_scm(void)
72 /* No access rights */
73 SetLastError(0xdeadbeef);
74 scm_handle
= OpenSCManagerA(NULL
, NULL
, 0);
75 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
76 CloseServiceHandle(scm_handle
);
78 /* Unknown database name */
79 SetLastError(0xdeadbeef);
80 scm_handle
= OpenSCManagerA(NULL
, "DoesNotExist", SC_MANAGER_CONNECT
);
81 ok(!scm_handle
, "Expected failure\n");
82 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
83 CloseServiceHandle(scm_handle
); /* Just in case */
85 /* MSDN says only ServiceActive is allowed, or NULL */
86 SetLastError(0xdeadbeef);
87 scm_handle
= OpenSCManagerA(NULL
, SERVICES_FAILED_DATABASEA
, SC_MANAGER_CONNECT
);
88 ok(!scm_handle
, "Expected failure\n");
89 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST
, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
90 CloseServiceHandle(scm_handle
); /* Just in case */
92 /* Remote unknown host */
93 SetLastError(0xdeadbeef);
94 scm_handle
= OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
97 ok(!scm_handle
, "Expected failure\n");
98 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE
|| GetLastError() == RPC_S_INVALID_NET_ADDR
/* w2k8 */,
99 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
101 CloseServiceHandle(scm_handle
); /* Just in case */
103 /* Proper call with an empty hostname */
104 scm_handle
= OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
105 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
106 CloseServiceHandle(scm_handle
);
108 /* Again a correct one */
109 SetLastError(0xdeadbeef);
110 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
111 ok(GetLastError() == ERROR_SUCCESS
|| broken(GetLastError() == ERROR_IO_PENDING
) /* win2k */,
112 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
113 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
114 CloseServiceHandle(scm_handle
);
117 static void test_open_svc(void)
119 SC_HANDLE scm_handle
, svc_handle
;
120 CHAR displayname
[4096];
123 /* All NULL (invalid access rights) */
124 SetLastError(0xdeadbeef);
125 svc_handle
= OpenServiceA(NULL
, NULL
, 0);
126 ok(!svc_handle
, "Expected failure\n");
127 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
129 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
132 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
133 SetLastError(0xdeadbeef);
134 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
135 ok(!svc_handle
, "Expected failure\n");
136 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
137 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
138 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
140 /* Nonexistent service */
141 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
142 SetLastError(0xdeadbeef);
143 svc_handle
= OpenServiceA(scm_handle
, "deadbeef", GENERIC_READ
);
144 ok(!svc_handle
, "Expected failure\n");
145 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
146 CloseServiceHandle(scm_handle
);
148 /* Proper SCM handle but different access rights */
149 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
150 SetLastError(0xdeadbeef);
151 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_WRITE
);
152 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
153 skip("Not enough rights to get a handle to the service\n");
156 ok(svc_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
157 CloseServiceHandle(svc_handle
);
160 /* Test to show we can't open a service with the displayname */
162 /* Retrieve the needed size for the buffer */
164 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
165 /* Get the displayname */
166 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
167 /* Try to open the service with this displayname, unless the displayname equals
168 * the servicename as that would defeat the purpose of this test.
170 if (!lstrcmpiA(spooler
, displayname
))
172 skip("displayname equals servicename\n");
173 CloseServiceHandle(scm_handle
);
177 SetLastError(0xdeadbeef);
178 svc_handle
= OpenServiceA(scm_handle
, displayname
, GENERIC_READ
);
179 ok(!svc_handle
, "Expected failure\n");
180 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
182 CloseServiceHandle(svc_handle
);
184 CloseServiceHandle(scm_handle
);
187 static void test_create_delete_svc(void)
189 SC_HANDLE scm_handle
, svc_handle1
;
190 CHAR username
[UNLEN
+ 1], domain
[MAX_PATH
];
191 DWORD user_size
= UNLEN
+ 1;
192 CHAR account
[UNLEN
+ 3];
193 static const CHAR servicename
[] = "Winetest";
194 static const CHAR pathname
[] = "we_dont_care.exe";
195 static const CHAR empty
[] = "";
196 static const CHAR password
[] = "secret";
197 BOOL spooler_exists
= FALSE
;
200 DWORD display_size
= sizeof(display
);
202 /* Get the username and turn it into an account to be used in some tests */
203 GetUserNameA(username
, &user_size
);
204 /* Get the domainname to cater for that situation */
205 if (GetEnvironmentVariableA("USERDOMAIN", domain
, MAX_PATH
))
206 sprintf(account
, "%s\\%s", domain
, username
);
208 sprintf(account
, ".\\%s", username
);
211 SetLastError(0xdeadbeef);
212 svc_handle1
= CreateServiceA(NULL
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
213 ok(!svc_handle1
, "Expected failure\n");
214 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
216 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
218 /* Only a valid handle to the Service Control Manager */
219 SetLastError(0xdeadbeef);
220 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
221 ok(!svc_handle1
, "Expected failure\n");
222 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
223 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
224 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
226 /* Now with a servicename */
227 SetLastError(0xdeadbeef);
228 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
229 ok(!svc_handle1
, "Expected failure\n");
230 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
231 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
232 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
234 /* Or just a binary name */
235 SetLastError(0xdeadbeef);
236 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
237 ok(!svc_handle1
, "Expected failure\n");
238 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
239 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
240 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
242 /* Both servicename and binary name (We only have connect rights) */
243 SetLastError(0xdeadbeef);
244 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
245 ok(!svc_handle1
, "Expected failure\n");
246 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
248 /* They can even be empty at this stage of parameter checking */
249 SetLastError(0xdeadbeef);
250 svc_handle1
= CreateServiceA(scm_handle
, empty
, 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 SetLastError(0xdeadbeef);
255 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
256 ok(!svc_handle1
, "Expected failure\n");
257 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
259 /* Open the Service Control Manager with minimal rights for creation
260 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
262 CloseServiceHandle(scm_handle
);
263 SetLastError(0xdeadbeef);
264 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
265 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
267 skip("Not enough rights to get a handle to the manager\n");
271 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
273 /* Empty strings for servicename and binary name are checked */
274 SetLastError(0xdeadbeef);
275 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
276 ok(!svc_handle1
, "Expected failure\n");
277 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
279 SetLastError(0xdeadbeef);
280 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
281 ok(!svc_handle1
, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
286 ok(!svc_handle1
, "Expected failure\n");
287 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
289 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
290 * an ERROR_INVALID_PARAMETER)
292 SetLastError(0xdeadbeef);
293 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
294 SERVICE_DISABLED
, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
295 ok(!svc_handle1
, "Expected failure\n");
296 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
298 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
300 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
301 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
303 SetLastError(0xdeadbeef);
304 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
,
305 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
306 ok(!svc_handle1
, "Expected failure\n");
307 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
309 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
310 SetLastError(0xdeadbeef);
311 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_INTERACTIVE_PROCESS
,
312 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
313 ok(!svc_handle1
, "Expected failure\n");
314 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
316 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
317 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
319 SetLastError(0xdeadbeef);
320 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
321 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, account
, password
);
322 ok(!svc_handle1
, "Expected failure\n");
323 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT
,
324 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
326 /* Illegal (start-type is not a mask and should only be one of the possibilities)
327 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
328 * it's most likely not the wanted start-type)
330 SetLastError(0xdeadbeef);
331 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
,
332 SERVICE_AUTO_START
| SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
333 ok(!svc_handle1
, "Expected failure\n");
334 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
336 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
337 SetLastError(0xdeadbeef);
338 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
339 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
340 ok(!svc_handle1
, "Expected failure\n");
341 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
343 /* Test if ServiceType can be a combined one for drivers */
344 SetLastError(0xdeadbeef);
345 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_KERNEL_DRIVER
| SERVICE_FILE_SYSTEM_DRIVER
,
346 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
347 ok(!svc_handle1
, "Expected failure\n");
348 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
350 /* The service already exists (check first, just in case) */
351 svc_handle1
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
354 spooler_exists
= TRUE
;
355 CloseServiceHandle(svc_handle1
);
356 SetLastError(0xdeadbeef);
357 svc_handle1
= CreateServiceA(scm_handle
, spooler
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
358 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
359 ok(!svc_handle1
, "Expected failure\n");
360 ok(GetLastError() == ERROR_SERVICE_EXISTS
, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
363 skip("Spooler service doesn't exist\n");
365 /* To find an existing displayname we check the 'Spooler' service. Although the registry
366 * doesn't show DisplayName on NT4, this call will return a displayname which is equal
367 * to the servicename and can't be used as well for a new displayname.
371 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, display
, &display_size
);
374 skip("Could not retrieve a displayname for the Spooler service\n");
377 svc_handle1
= CreateServiceA(scm_handle
, servicename
, display
, 0, SERVICE_WIN32_OWN_PROCESS
,
378 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
379 ok(!svc_handle1
, "Expected failure\n");
380 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME
,
381 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
385 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
387 /* Windows doesn't care about the access rights for creation (which makes
388 * sense as there is no service yet) as long as there are sufficient
389 * rights to the manager.
391 SetLastError(0xdeadbeef);
392 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
393 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
394 ok(svc_handle1
!= NULL
, "Could not create the service : %d\n", GetLastError());
396 /* DeleteService however must have proper rights */
397 SetLastError(0xdeadbeef);
398 ret
= DeleteService(svc_handle1
);
399 ok(!ret
, "Expected failure\n");
400 ok(GetLastError() == ERROR_ACCESS_DENIED
,
401 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
403 /* Open the service with minimal rights for deletion.
404 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
406 CloseServiceHandle(svc_handle1
);
407 svc_handle1
= OpenServiceA(scm_handle
, servicename
, DELETE
);
409 /* Now that we have the proper rights, we should be able to delete */
410 SetLastError(0xdeadbeef);
411 ret
= DeleteService(svc_handle1
);
412 ok(ret
, "Expected success, got error %u\n", GetLastError());
414 CloseServiceHandle(svc_handle1
);
415 CloseServiceHandle(scm_handle
);
417 /* Wait a while. One of the following tests also does a CreateService for the
418 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
419 * error if we do this too quickly. Vista seems more picky than the others.
423 /* And a final NULL check */
424 SetLastError(0xdeadbeef);
425 ret
= DeleteService(NULL
);
426 ok(!ret
, "Expected failure\n");
427 ok(GetLastError() == ERROR_INVALID_HANDLE
,
428 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
431 static void test_get_displayname(void)
433 SC_HANDLE scm_handle
, svc_handle
;
435 CHAR displayname
[4096];
436 WCHAR displaynameW
[2048];
437 DWORD displaysize
, tempsize
, tempsizeW
;
438 static const CHAR deadbeef
[] = "Deadbeef";
439 static const WCHAR spoolerW
[] = {'S','p','o','o','l','e','r',0};
440 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
441 static const WCHAR abcW
[] = {'A','B','C',0};
442 static const CHAR servicename
[] = "Winetest";
443 static const CHAR pathname
[] = "we_dont_care.exe";
445 /* Having NULL for the size of the buffer will crash on W2K3 */
447 SetLastError(0xdeadbeef);
448 ret
= GetServiceDisplayNameA(NULL
, NULL
, NULL
, &displaysize
);
449 ok(!ret
, "Expected failure\n");
450 ok(GetLastError() == ERROR_INVALID_HANDLE
,
451 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
453 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
455 SetLastError(0xdeadbeef);
456 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, NULL
, &displaysize
);
457 ok(!ret
, "Expected failure\n");
458 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
459 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
460 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
462 SetLastError(0xdeadbeef);
463 displaysize
= sizeof(displayname
);
464 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, displayname
, &displaysize
);
465 ok(!ret
, "Expected failure\n");
466 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
467 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
468 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
470 /* Test for nonexistent service */
471 SetLastError(0xdeadbeef);
473 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
474 ok(!ret
, "Expected failure\n");
475 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
476 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
478 SetLastError(0xdeadbeef);
479 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
480 ok(!ret
, "Expected failure\n");
481 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
482 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
483 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
486 strcpy(displayname
, "ABC");
487 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
488 ok(!ret
, "Expected failure\n");
489 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
490 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
491 todo_wine
ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
492 ok(displayname
[0] == 0, "Service name not empty\n");
495 lstrcpyW( displaynameW
, abcW
);
496 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
497 ok(!ret
, "Expected failure\n");
498 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
499 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
500 ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
501 ok(displaynameW
[0] == 0, "Service name not empty\n");
504 strcpy(displayname
, "ABC");
505 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
506 ok(!ret
, "Expected failure\n");
507 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
508 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
509 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
510 ok(displayname
[0] == 'A', "Service name changed\n");
513 lstrcpyW( displaynameW
, abcW
);
514 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
515 ok(!ret
, "Expected failure\n");
516 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
517 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
518 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
519 ok(displaynameW
[0] == 'A', "Service name changed\n");
522 strcpy(displayname
, "ABC");
523 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
524 ok(!ret
, "Expected failure\n");
525 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
526 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
527 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
528 ok(displayname
[0] == 0, "Service name not empty\n");
531 lstrcpyW( displaynameW
, abcW
);
532 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
533 ok(!ret
, "Expected failure\n");
534 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
535 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
536 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
537 ok(displaynameW
[0] == 'A', "Service name changed\n");
540 strcpy(displayname
, "ABC");
541 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
542 ok(!ret
, "Expected failure\n");
543 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
544 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
545 todo_wine
ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
546 ok(displayname
[0] == 0, "Service name not empty\n");
549 lstrcpyW( displaynameW
, abcW
);
550 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
551 ok(!ret
, "Expected failure\n");
552 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
553 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
554 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
555 ok(displaynameW
[0] == 0, "Service name not empty\n");
557 /* Check if 'Spooler' exists */
558 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
561 skip("Spooler service doesn't exist\n");
562 CloseServiceHandle(scm_handle
);
565 CloseServiceHandle(svc_handle
);
567 /* Retrieve the needed size for the buffer */
568 SetLastError(0xdeadbeef);
570 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
571 ok(!ret
, "Expected failure\n");
572 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
573 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
574 tempsize
= displaysize
;
577 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
578 ok(!ret
, "Expected failure\n");
579 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
580 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
581 ok(displaysize
== tempsize
, "Buffer size mismatch (%d vs %d)\n", tempsize
, displaysize
);
583 /* Buffer is too small */
584 SetLastError(0xdeadbeef);
585 displaysize
= (tempsize
/ 2);
586 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
587 ok(!ret
, "Expected failure\n");
588 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
589 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
590 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
592 /* First try with a buffer that should be big enough to hold
593 * the ANSI string (and terminating character). This succeeds on Windows
594 * although when asked (see above 2 tests) it will return twice the needed size.
596 SetLastError(0xdeadbeef);
597 displaysize
= (tempsize
/ 2) + 1;
598 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
599 ok(ret
, "Expected success, got error %u\n", GetLastError());
600 ok(displaysize
== ((tempsize
/ 2) + 1), "Expected no change for the needed buffer size\n");
602 /* Now with the original returned size */
603 SetLastError(0xdeadbeef);
604 displaysize
= tempsize
;
605 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
606 ok(ret
, "Expected success, got error %u\n", GetLastError());
607 ok(displaysize
== tempsize
, "Expected no change for the needed buffer size\n");
609 /* And with a bigger than needed buffer */
610 SetLastError(0xdeadbeef);
611 displaysize
= tempsize
* 2;
612 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
613 ok(ret
, "Expected success, got error %u\n", GetLastError());
614 /* Test that shows that if the buffersize is enough, it's not changed */
615 ok(displaysize
== tempsize
* 2, "Expected no change for the needed buffer size\n");
616 ok(strlen(displayname
) == tempsize
/2,
617 "Expected the buffer to be twice the length of the string\n") ;
619 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
620 SetLastError(0xdeadbeef);
622 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, NULL
, &displaysize
);
623 ok(!ret
, "Expected failure\n");
624 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
625 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
627 /* Buffer is too small */
628 SetLastError(0xdeadbeef);
629 tempsizeW
= displaysize
;
630 displaysize
= tempsizeW
/ 2;
631 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
632 ok(!ret
, "Expected failure\n");
633 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
634 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
635 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
637 /* Now with the original returned size */
638 SetLastError(0xdeadbeef);
639 displaysize
= tempsizeW
;
640 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
641 ok(!ret
, "Expected failure\n");
642 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
643 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
644 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
646 /* And with a bigger than needed buffer */
647 SetLastError(0xdeadbeef);
648 displaysize
= tempsizeW
+ 1; /* This caters for the null terminating character */
649 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
650 ok(ret
, "Expected success, got error %u\n", GetLastError());
651 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
652 ok(lstrlenW(displaynameW
) == displaysize
,
653 "Expected the buffer to be the length of the string\n") ;
654 ok(tempsize
/ 2 == tempsizeW
,
655 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
657 CloseServiceHandle(scm_handle
);
659 /* Test for a service without a displayname (which is valid). This should return
660 * the servicename itself.
662 SetLastError(0xdeadbeef);
663 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
664 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
666 skip("Not enough rights to get a handle to the manager\n");
670 SetLastError(0xdeadbeef);
671 svc_handle
= CreateServiceA(scm_handle
, servicename
, NULL
, DELETE
,
672 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
673 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
674 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
677 CloseServiceHandle(scm_handle
);
681 /* Retrieve the needed size for the buffer */
682 SetLastError(0xdeadbeef);
684 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, NULL
, &displaysize
);
685 ok(!ret
, "Expected failure\n");
686 ok(displaysize
== strlen(servicename
) * 2,
687 "Expected the displaysize to be twice the size of the servicename\n");
688 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
689 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
691 /* Buffer is too small */
692 SetLastError(0xdeadbeef);
693 tempsize
= displaysize
;
694 displaysize
= (tempsize
/ 2);
695 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
696 ok(!ret
, "Expected failure\n");
697 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
698 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
699 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
701 /* Get the displayname */
702 SetLastError(0xdeadbeef);
703 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
704 ok(ret
, "Expected success, got error %u\n", GetLastError());
705 ok(!lstrcmpiA(displayname
, servicename
),
706 "Expected displayname to be %s, got %s\n", servicename
, displayname
);
708 /* Delete the service */
709 ret
= DeleteService(svc_handle
);
710 ok(ret
, "Expected success (err=%d)\n", GetLastError());
712 CloseServiceHandle(svc_handle
);
713 CloseServiceHandle(scm_handle
);
715 /* Wait a while. Just in case one of the following tests does a CreateService again */
719 static void test_get_servicekeyname(void)
721 SC_HANDLE scm_handle
, svc_handle
;
722 CHAR servicename
[4096];
723 CHAR displayname
[4096];
724 WCHAR servicenameW
[4096];
725 WCHAR displaynameW
[4096];
726 DWORD servicesize
, displaysize
, tempsize
;
728 static const CHAR deadbeef
[] = "Deadbeef";
729 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
730 static const WCHAR abcW
[] = {'A','B','C',0};
732 /* Having NULL for the size of the buffer will crash on W2K3 */
734 SetLastError(0xdeadbeef);
735 ret
= GetServiceKeyNameA(NULL
, NULL
, NULL
, &servicesize
);
736 ok(!ret
, "Expected failure\n");
737 ok(GetLastError() == ERROR_INVALID_HANDLE
,
738 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
740 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
743 SetLastError(0xdeadbeef);
744 ret
= GetServiceKeyNameA(scm_handle
, NULL
, NULL
, &servicesize
);
745 ok(!ret
, "Expected failure\n");
746 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
747 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
748 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
749 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
751 /* Valid handle and buffer but no displayname */
753 SetLastError(0xdeadbeef);
754 ret
= GetServiceKeyNameA(scm_handle
, NULL
, servicename
, &servicesize
);
755 ok(!ret
, "Expected failure\n");
756 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
757 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
758 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
759 todo_wine
ok(servicesize
== 200, "Service size expected 1, got %d\n", servicesize
);
761 /* Test for nonexistent displayname */
762 SetLastError(0xdeadbeef);
763 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, NULL
, &servicesize
);
764 ok(!ret
, "Expected failure\n");
765 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
766 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
767 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
770 strcpy(servicename
, "ABC");
771 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
772 ok(!ret
, "Expected failure\n");
773 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
774 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
775 todo_wine
ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
776 ok(servicename
[0] == 0, "Service name not empty\n");
779 lstrcpyW( servicenameW
, abcW
);
780 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
781 ok(!ret
, "Expected failure\n");
782 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
783 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
784 ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
785 ok(servicenameW
[0] == 0, "Service name not empty\n");
788 strcpy(servicename
, "ABC");
789 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
790 ok(!ret
, "Expected failure\n");
791 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
792 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
793 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
794 ok(servicename
[0] == 'A', "Service name changed\n");
797 lstrcpyW( servicenameW
, abcW
);
798 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
799 ok(!ret
, "Expected failure\n");
800 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
801 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
802 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
803 ok(servicenameW
[0] == 'A', "Service name changed\n");
806 strcpy(servicename
, "ABC");
807 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
808 ok(!ret
, "Expected failure\n");
809 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
810 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
811 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
812 ok(servicename
[0] == 0, "Service name not empty\n");
815 lstrcpyW( servicenameW
, abcW
);
816 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
817 ok(!ret
, "Expected failure\n");
818 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
819 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
820 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
821 ok(servicenameW
[0] == 'A', "Service name changed\n");
824 strcpy(servicename
, "ABC");
825 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
826 ok(!ret
, "Expected failure\n");
827 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
828 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
829 todo_wine
ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
830 ok(servicename
[0] == 0, "Service name not empty\n");
833 lstrcpyW( servicenameW
, abcW
);
834 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
835 ok(!ret
, "Expected failure\n");
836 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
837 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
838 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
839 ok(servicenameW
[0] == 0, "Service name not empty\n");
841 /* Check if 'Spooler' exists */
842 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
845 skip("Spooler service doesn't exist\n");
846 CloseServiceHandle(scm_handle
);
849 CloseServiceHandle(svc_handle
);
851 /* Get the displayname for the 'Spooler' service */
852 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
853 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
855 /* Retrieve the needed size for the buffer */
856 SetLastError(0xdeadbeef);
858 ret
= GetServiceKeyNameA(scm_handle
, displayname
, NULL
, &servicesize
);
859 ok(!ret
, "Expected failure\n");
860 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
861 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
863 /* Valid call with the correct buffersize */
864 SetLastError(0xdeadbeef);
865 tempsize
= servicesize
;
867 ret
= GetServiceKeyNameA(scm_handle
, displayname
, servicename
, &servicesize
);
868 ok(ret
, "Expected success, got error %u\n", GetLastError());
871 ok(strlen(servicename
) == tempsize
/2,
872 "Expected the buffer to be twice the length of the string\n") ;
873 ok(!lstrcmpiA(servicename
, spooler
), "Expected %s, got %s\n", spooler
, servicename
);
874 ok(servicesize
== (tempsize
* 2),
875 "Expected servicesize not to change if buffer not insufficient\n") ;
878 MultiByteToWideChar(CP_ACP
, 0, displayname
, -1, displaynameW
, sizeof(displaynameW
)/2);
879 SetLastError(0xdeadbeef);
881 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
882 ok(ret
, "Expected success, got error %u\n", GetLastError());
885 ok(strlen(servicename
) == tempsize
/2,
886 "Expected the buffer to be twice the length of the string\n") ;
887 ok(servicesize
== lstrlenW(servicenameW
),
888 "Expected servicesize not to change if buffer not insufficient\n") ;
891 SetLastError(0xdeadbeef);
893 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
894 ok(!ret
, "Expected failure\n");
895 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
896 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
897 ok(servicenameW
[0] == 0, "Buffer not empty\n");
899 CloseServiceHandle(scm_handle
);
902 static void test_query_svc(void)
904 SC_HANDLE scm_handle
, svc_handle
;
906 SERVICE_STATUS status
;
907 SERVICE_STATUS_PROCESS
*statusproc
;
908 DWORD bufsize
, needed
;
910 /* All NULL or wrong */
911 SetLastError(0xdeadbeef);
912 ret
= QueryServiceStatus(NULL
, NULL
);
913 ok(!ret
, "Expected failure\n");
914 ok(GetLastError() == ERROR_INVALID_HANDLE
,
915 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
917 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
919 /* Check if 'Spooler' exists.
920 * Open with not enough rights to query the status.
922 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
925 skip("Spooler service doesn't exist\n");
926 CloseServiceHandle(scm_handle
);
930 SetLastError(0xdeadbeef);
931 ret
= QueryServiceStatus(svc_handle
, NULL
);
932 ok(!ret
, "Expected failure\n");
933 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
934 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
935 "Unexpected last error %d\n", GetLastError());
937 SetLastError(0xdeadbeef);
938 ret
= QueryServiceStatus(svc_handle
, &status
);
939 ok(!ret
, "Expected failure\n");
940 ok(GetLastError() == ERROR_ACCESS_DENIED
,
941 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
943 /* Open the service with just enough rights.
944 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
946 CloseServiceHandle(svc_handle
);
947 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
949 SetLastError(0xdeadbeef);
950 ret
= QueryServiceStatus(svc_handle
, &status
);
951 ok(ret
, "Expected success, got error %u\n", GetLastError());
953 CloseServiceHandle(svc_handle
);
955 /* More or less the same tests for QueryServiceStatusEx */
956 if (!pQueryServiceStatusEx
)
958 win_skip( "QueryServiceStatusEx not available\n" );
959 CloseServiceHandle(scm_handle
);
963 /* Open service with not enough rights to query the status */
964 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
966 /* All NULL or wrong, this proves that info level is checked first */
967 SetLastError(0xdeadbeef);
968 ret
= pQueryServiceStatusEx(NULL
, 1, NULL
, 0, NULL
);
969 ok(!ret
, "Expected failure\n");
970 ok(GetLastError() == ERROR_INVALID_LEVEL
,
971 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
973 /* Passing a NULL parameter for the needed buffer size
974 * will crash on anything but NT4.
977 /* Only info level is correct. It looks like the buffer/size is checked second */
978 SetLastError(0xdeadbeef);
979 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
980 /* NT4 checks the handle first */
981 if (GetLastError() != ERROR_INVALID_HANDLE
)
983 ok(!ret
, "Expected failure\n");
984 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
985 "Needed buffersize is wrong : %d\n", needed
);
986 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
987 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
990 /* Pass a correct buffer and buffersize but a NULL handle */
991 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
993 SetLastError(0xdeadbeef);
994 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
995 ok(!ret
, "Expected failure\n");
996 ok(GetLastError() == ERROR_INVALID_HANDLE
,
997 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
998 HeapFree(GetProcessHeap(), 0, statusproc
);
1000 /* Correct handle and info level */
1001 SetLastError(0xdeadbeef);
1002 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
1003 /* NT4 doesn't return the needed size */
1004 if (GetLastError() != ERROR_INVALID_PARAMETER
)
1006 ok(!ret
, "Expected failure\n");
1007 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
1008 "Needed buffersize is wrong : %d\n", needed
);
1009 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1010 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1013 /* All parameters are OK but we don't have enough rights */
1014 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1015 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1016 SetLastError(0xdeadbeef);
1017 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1018 ok(!ret
, "Expected failure\n");
1019 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1020 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1021 HeapFree(GetProcessHeap(), 0, statusproc
);
1023 /* Open the service with just enough rights. */
1024 CloseServiceHandle(svc_handle
);
1025 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
1027 /* Everything should be fine now. */
1028 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1029 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1030 SetLastError(0xdeadbeef);
1031 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1032 ok(ret
, "Expected success, got error %u\n", GetLastError());
1033 if (statusproc
->dwCurrentState
== SERVICE_RUNNING
)
1034 ok(statusproc
->dwProcessId
!= 0,
1035 "Expect a process id for this running service\n");
1037 ok(statusproc
->dwProcessId
== 0,
1038 "Expect no process id for this stopped service\n");
1040 /* same call with null needed pointer */
1041 SetLastError(0xdeadbeef);
1042 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, NULL
);
1043 ok(!ret
, "Expected failure\n");
1044 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* NT4 */ ||
1045 GetLastError() == ERROR_INVALID_ADDRESS
, "got %d\n", GetLastError());
1047 HeapFree(GetProcessHeap(), 0, statusproc
);
1049 CloseServiceHandle(svc_handle
);
1050 CloseServiceHandle(scm_handle
);
1053 static void test_enum_svc(void)
1055 SC_HANDLE scm_handle
;
1057 DWORD bufsize
, needed
, returned
, resume
;
1058 DWORD neededW
, returnedW
;
1059 DWORD tempneeded
, tempreturned
, missing
;
1060 DWORD servicecountactive
, servicecountinactive
;
1061 ENUM_SERVICE_STATUSA
*services
;
1062 ENUM_SERVICE_STATUSW
*servicesW
;
1063 ENUM_SERVICE_STATUS_PROCESSA
*exservices
;
1066 /* All NULL or wrong */
1067 SetLastError(0xdeadbeef);
1068 ret
= EnumServicesStatusA(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1069 ok(!ret
, "Expected failure\n");
1070 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1071 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1073 SetLastError(0xdeadbeef);
1074 ret
= EnumServicesStatusW(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1075 ok(!ret
, "Expected failure\n");
1076 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1077 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1079 /* Open the service control manager with not enough rights at first */
1080 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1082 /* Valid handle but rest is still NULL or wrong */
1083 SetLastError(0xdeadbeef);
1084 ret
= EnumServicesStatusA(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1085 ok(!ret
, "Expected failure\n");
1086 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1087 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1088 "Unexpected last error %d\n", GetLastError());
1090 SetLastError(0xdeadbeef);
1091 ret
= EnumServicesStatusW(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1092 ok(!ret
, "Expected failure\n");
1093 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1094 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1095 "Unexpected last error %d\n", GetLastError());
1097 /* Don't specify the two required pointers */
1098 returned
= 0xdeadbeef;
1099 SetLastError(0xdeadbeef);
1100 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, NULL
, &returned
, NULL
);
1101 ok(!ret
, "Expected failure\n");
1102 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1103 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1104 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1105 "Unexpected last error %d\n", GetLastError());
1107 returned
= 0xdeadbeef;
1108 SetLastError(0xdeadbeef);
1109 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, NULL
, &returned
, NULL
);
1110 ok(!ret
, "Expected failure\n");
1111 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1112 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1113 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1114 "Unexpected last error %d\n", GetLastError());
1116 /* Don't specify the two required pointers */
1117 needed
= 0xdeadbeef;
1118 SetLastError(0xdeadbeef);
1119 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, &needed
, NULL
, NULL
);
1120 ok(!ret
, "Expected failure\n");
1121 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1122 "Expected no change to the needed buffer variable\n");
1123 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1124 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1125 "Unexpected last error %d\n", GetLastError());
1127 needed
= 0xdeadbeef;
1128 SetLastError(0xdeadbeef);
1129 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, &needed
, NULL
, NULL
);
1130 ok(!ret
, "Expected failure\n");
1131 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1132 "Expected no change to the needed buffer variable\n");
1133 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1134 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1135 "Unexpected last error %d\n", GetLastError());
1137 /* No valid servicetype and servicestate */
1138 needed
= 0xdeadbeef;
1139 returned
= 0xdeadbeef;
1140 SetLastError(0xdeadbeef);
1141 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, &needed
, &returned
, NULL
);
1142 ok(!ret
, "Expected failure\n");
1143 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1144 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1145 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1146 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1147 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1149 needed
= 0xdeadbeef;
1150 returned
= 0xdeadbeef;
1151 SetLastError(0xdeadbeef);
1152 ret
= EnumServicesStatusW(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 || broken(returned
!= 0), /* nt4 */
1157 "Expected number of services to be set to 0, got %d\n", returned
);
1158 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1159 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1161 /* No valid servicestate */
1162 needed
= 0xdeadbeef;
1163 returned
= 0xdeadbeef;
1164 SetLastError(0xdeadbeef);
1165 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, 0, NULL
, 0, &needed
, &returned
, NULL
);
1166 ok(!ret
, "Expected failure\n");
1167 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1168 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1169 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1170 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1171 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1173 needed
= 0xdeadbeef;
1174 returned
= 0xdeadbeef;
1175 SetLastError(0xdeadbeef);
1176 ret
= EnumServicesStatusW(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 || broken(returned
!= 0), /* nt4 */
1181 "Expected number of services to be set to 0, got %d\n", returned
);
1182 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1183 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1185 /* No valid servicetype */
1186 needed
= 0xdeadbeef;
1187 returned
= 0xdeadbeef;
1188 SetLastError(0xdeadbeef);
1189 ret
= EnumServicesStatusA(scm_handle
, 0, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1190 ok(!ret
, "Expected failure\n");
1191 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1192 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1193 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1194 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1195 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1197 needed
= 0xdeadbeef;
1198 returned
= 0xdeadbeef;
1199 SetLastError(0xdeadbeef);
1200 ret
= EnumServicesStatusW(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 || broken(returned
!= 0), /* nt4 */
1205 "Expected number of services to be set to 0, got %d\n", returned
);
1206 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1207 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1209 /* All parameters are correct but our access rights are wrong */
1210 needed
= 0xdeadbeef;
1211 returned
= 0xdeadbeef;
1212 SetLastError(0xdeadbeef);
1213 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1214 ok(!ret
, "Expected failure\n");
1215 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1216 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1217 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1218 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1219 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1221 needed
= 0xdeadbeef;
1222 returned
= 0xdeadbeef;
1223 SetLastError(0xdeadbeef);
1224 ret
= EnumServicesStatusW(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 || broken(returned
!= 0), /* nt4 */
1229 "Expected number of services to be set to 0, got %d\n", returned
);
1230 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1231 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1233 /* Open the service control manager with the needed rights */
1234 CloseServiceHandle(scm_handle
);
1235 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1237 /* All parameters are correct. Request the needed buffer size */
1238 needed
= 0xdeadbeef;
1239 returned
= 0xdeadbeef;
1240 SetLastError(0xdeadbeef);
1241 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1242 ok(!ret
, "Expected failure\n");
1243 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1244 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1245 ok(GetLastError() == ERROR_MORE_DATA
,
1246 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1248 /* Test to show we get the same needed buffer size for the W-call */
1249 neededW
= 0xdeadbeef;
1250 returnedW
= 0xdeadbeef;
1251 SetLastError(0xdeadbeef);
1252 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &neededW
, &returnedW
, NULL
);
1253 ok(!ret
, "Expected failure\n");
1254 ok(neededW
!= 0xdeadbeef && neededW
> 0, "Expected the needed buffer size for this one service\n");
1255 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1256 ok(returnedW
== 0, "Expected no service returned, got %d\n", returnedW
);
1257 ok(GetLastError() == ERROR_MORE_DATA
,
1258 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1260 /* Store the needed bytes */
1261 tempneeded
= needed
;
1263 /* Allocate the correct needed bytes */
1264 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1266 needed
= 0xdeadbeef;
1267 returned
= 0xdeadbeef;
1268 SetLastError(0xdeadbeef);
1269 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1270 services
, bufsize
, &needed
, &returned
, NULL
);
1271 ok(ret
, "Expected success, got error %u\n", GetLastError());
1272 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1273 ok(returned
!= 0xdeadbeef && returned
> 0, "Expected some returned services\n");
1274 HeapFree(GetProcessHeap(), 0, services
);
1276 /* Store the number of returned services */
1277 tempreturned
= returned
;
1279 servicesW
= HeapAlloc(GetProcessHeap(), 0, neededW
);
1281 neededW
= 0xdeadbeef;
1282 returnedW
= 0xdeadbeef;
1283 SetLastError(0xdeadbeef);
1284 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1285 servicesW
, bufsize
, &neededW
, &returnedW
, NULL
);
1286 ok(ret
, "Expected success, got error %u\n", GetLastError());
1287 ok(neededW
== 0, "Expected needed buffer to be 0 as we are done\n");
1288 ok(returnedW
!= 0xdeadbeef && returnedW
> 0, "Expected some returned services\n");
1289 HeapFree(GetProcessHeap(), 0, servicesW
);
1291 /* Allocate less than the needed bytes and don't specify a resume handle */
1292 services
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1293 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1294 needed
= 0xdeadbeef;
1295 returned
= 0xdeadbeef;
1296 SetLastError(0xdeadbeef);
1297 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1298 services
, bufsize
, &needed
, &returned
, NULL
);
1299 ok(!ret
, "Expected failure\n");
1300 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1301 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1302 ok(GetLastError() == ERROR_MORE_DATA
,
1303 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1305 /* Allocate less than the needed bytes, this time with a correct resume handle */
1306 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1307 needed
= 0xdeadbeef;
1308 returned
= 0xdeadbeef;
1310 SetLastError(0xdeadbeef);
1311 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1312 services
, bufsize
, &needed
, &returned
, &resume
);
1313 ok(!ret
, "Expected failure\n");
1314 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1315 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1316 todo_wine
ok(resume
, "Expected a resume handle\n");
1317 ok(GetLastError() == ERROR_MORE_DATA
,
1318 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1320 /* Fetch the missing services but pass a bigger buffer size */
1321 missing
= tempreturned
- returned
;
1322 bufsize
= tempneeded
;
1323 needed
= 0xdeadbeef;
1324 returned
= 0xdeadbeef;
1325 SetLastError(0xdeadbeef);
1326 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1327 services
, bufsize
, &needed
, &returned
, &resume
);
1328 ok(ret
, "Expected success, got error %u\n", GetLastError());
1329 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1330 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1331 ok(resume
== 0, "Expected the resume handle to be 0\n");
1332 HeapFree(GetProcessHeap(), 0, services
);
1334 /* See if things add up */
1336 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1337 * and doesn't count the others as inactive. This means that Vista could
1338 * show a total that is greater than the sum of active and inactive
1340 * The number of active and inactive drivers is greatly influenced by the
1341 * time when tests are run, immediately after boot or later for example.
1343 * Both reasons make calculations for drivers not so useful
1346 /* Get the number of active win32 services */
1347 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, NULL
, 0,
1348 &needed
, &returned
, NULL
);
1349 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1350 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, services
,
1351 needed
, &needed
, &returned
, NULL
);
1352 HeapFree(GetProcessHeap(), 0, services
);
1354 servicecountactive
= returned
;
1356 /* Get the number of inactive win32 services */
1357 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, NULL
, 0,
1358 &needed
, &returned
, NULL
);
1359 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1360 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, services
,
1361 needed
, &needed
, &returned
, NULL
);
1362 HeapFree(GetProcessHeap(), 0, services
);
1364 servicecountinactive
= returned
;
1366 /* Get the number of win32 services */
1367 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0,
1368 &needed
, &returned
, NULL
);
1369 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1370 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, services
,
1371 needed
, &needed
, &returned
, NULL
);
1372 HeapFree(GetProcessHeap(), 0, services
);
1374 /* Check if total is the same as active and inactive win32 services */
1375 ok(returned
== (servicecountactive
+ servicecountinactive
),
1376 "Something wrong in the calculation\n");
1378 /* Get all drivers and services
1380 * Fetch the status of the last call as failing could make the following tests crash
1381 * on Wine (we don't return anything yet).
1383 EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1384 NULL
, 0, &needed
, &returned
, NULL
);
1385 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1386 ret
= EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1387 services
, needed
, &needed
, &returned
, NULL
);
1389 /* Loop through all those returned drivers and services */
1390 for (i
= 0; ret
&& i
< returned
; i
++)
1392 SERVICE_STATUS status
= services
[i
].ServiceStatus
;
1394 /* lpServiceName and lpDisplayName should always be filled */
1395 ok(lstrlenA(services
[i
].lpServiceName
) > 0, "Expected a service name\n");
1396 ok(lstrlenA(services
[i
].lpDisplayName
) > 0, "Expected a display name\n");
1398 /* Decrement the counters to see if the functions calls return the same
1399 * numbers as the contents of these structures.
1401 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1403 if (status
.dwCurrentState
== SERVICE_STOPPED
)
1404 servicecountinactive
--;
1406 servicecountactive
--;
1409 HeapFree(GetProcessHeap(), 0, services
);
1411 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1412 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1414 CloseServiceHandle(scm_handle
);
1416 /* More or less the same for EnumServicesStatusExA */
1417 if (!pEnumServicesStatusExA
)
1419 win_skip( "EnumServicesStatusExA not available\n" );
1423 /* All NULL or wrong */
1424 SetLastError(0xdeadbeef);
1425 ret
= pEnumServicesStatusExA(NULL
, 1, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1426 ok(!ret
, "Expected failure\n");
1427 ok(GetLastError() == ERROR_INVALID_LEVEL
,
1428 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1430 /* All NULL or wrong, just the info level is correct */
1431 SetLastError(0xdeadbeef);
1432 ret
= pEnumServicesStatusExA(NULL
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1433 ok(!ret
, "Expected failure\n");
1434 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1435 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1437 /* Open the service control manager with not enough rights at first */
1438 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1440 /* Valid handle and info level but rest is still NULL or wrong */
1441 SetLastError(0xdeadbeef);
1442 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1443 ok(!ret
, "Expected failure\n");
1444 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1445 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1446 "Unexpected last error %d\n", GetLastError());
1448 /* Don't specify the two required pointers */
1449 needed
= 0xdeadbeef;
1450 SetLastError(0xdeadbeef);
1451 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, NULL
, NULL
, NULL
);
1452 ok(!ret
, "Expected failure\n");
1453 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1454 "Expected no change to the needed buffer variable\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 returned
= 0xdeadbeef;
1461 SetLastError(0xdeadbeef);
1462 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, &returned
, NULL
, NULL
);
1463 ok(!ret
, "Expected failure\n");
1464 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1465 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1466 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1467 "Unexpected last error %d\n", GetLastError());
1469 /* No valid servicetype and servicestate */
1470 needed
= 0xdeadbeef;
1471 returned
= 0xdeadbeef;
1472 SetLastError(0xdeadbeef);
1473 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1474 ok(!ret
, "Expected failure\n");
1475 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1476 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1477 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1478 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1479 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1481 /* No valid servicestate */
1482 needed
= 0xdeadbeef;
1483 returned
= 0xdeadbeef;
1484 SetLastError(0xdeadbeef);
1485 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, 0, NULL
, 0,
1486 &needed
, &returned
, NULL
, NULL
);
1487 ok(!ret
, "Expected failure\n");
1488 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1489 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1490 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1491 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1492 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1494 /* No valid servicetype */
1495 needed
= 0xdeadbeef;
1496 returned
= 0xdeadbeef;
1497 SetLastError(0xdeadbeef);
1498 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, SERVICE_STATE_ALL
, NULL
, 0,
1499 &needed
, &returned
, NULL
, NULL
);
1500 ok(!ret
, "Expected failure\n");
1501 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1502 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1503 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1504 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1505 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1507 /* No valid servicetype and servicestate and unknown service group */
1508 needed
= 0xdeadbeef;
1509 returned
= 0xdeadbeef;
1510 SetLastError(0xdeadbeef);
1511 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
,
1512 &returned
, NULL
, "deadbeef_group");
1513 ok(!ret
, "Expected failure\n");
1514 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1515 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1516 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1517 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1518 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1520 /* All parameters are correct but our access rights are wrong */
1521 needed
= 0xdeadbeef;
1522 returned
= 0xdeadbeef;
1523 SetLastError(0xdeadbeef);
1524 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1525 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1526 ok(!ret
, "Expected failure\n");
1527 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1528 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1529 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1530 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1531 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1533 /* All parameters are correct, access rights are wrong but the
1534 * group name won't be checked yet.
1536 needed
= 0xdeadbeef;
1537 returned
= 0xdeadbeef;
1538 SetLastError(0xdeadbeef);
1539 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1540 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1541 ok(!ret
, "Expected failure\n");
1542 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1543 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1544 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1545 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1546 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1548 /* Open the service control manager with the needed rights */
1549 CloseServiceHandle(scm_handle
);
1550 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1552 /* All parameters are correct and the group will be checked */
1553 needed
= 0xdeadbeef;
1554 returned
= 0xdeadbeef;
1555 SetLastError(0xdeadbeef);
1556 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1557 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1558 ok(!ret
, "Expected failure\n");
1559 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1560 ok(needed
== 0, "Expected needed buffer size to be set to 0, got %d\n", needed
);
1561 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
1562 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1564 /* TODO: Create a test that makes sure we enumerate all services that don't
1565 * belong to a group. (specifying "").
1568 /* All parameters are correct. Request the needed buffer size */
1569 needed
= 0xdeadbeef;
1570 returned
= 0xdeadbeef;
1571 SetLastError(0xdeadbeef);
1572 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1573 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1574 ok(!ret
, "Expected failure\n");
1575 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1576 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1577 ok(GetLastError() == ERROR_MORE_DATA
,
1578 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1580 /* Test to show we get the same needed buffer size for the W-call */
1581 neededW
= 0xdeadbeef;
1582 ret
= pEnumServicesStatusExW(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1583 NULL
, 0, &neededW
, &returnedW
, NULL
, NULL
);
1584 ok(!ret
, "Expected failure\n");
1585 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1587 /* Store the needed bytes */
1588 tempneeded
= needed
;
1590 /* Allocate the correct needed bytes */
1591 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1593 needed
= 0xdeadbeef;
1594 returned
= 0xdeadbeef;
1595 SetLastError(0xdeadbeef);
1596 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1597 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1598 ok(ret
, "Expected success, got error %u\n", GetLastError());
1599 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1600 ok(returned
== tempreturned
, "Expected the same number of service from this function\n");
1601 HeapFree(GetProcessHeap(), 0, exservices
);
1603 /* Store the number of returned services */
1604 tempreturned
= returned
;
1606 /* Allocate less than the needed bytes and don't specify a resume handle */
1607 exservices
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1608 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1609 needed
= 0xdeadbeef;
1610 returned
= 0xdeadbeef;
1611 SetLastError(0xdeadbeef);
1612 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1613 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1614 ok(!ret
, "Expected failure\n");
1615 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1616 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1617 ok(GetLastError() == ERROR_MORE_DATA
,
1618 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1620 /* Allocate less than the needed bytes, this time with a correct resume handle */
1621 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1622 needed
= 0xdeadbeef;
1623 returned
= 0xdeadbeef;
1625 SetLastError(0xdeadbeef);
1626 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1627 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1628 ok(!ret
, "Expected failure\n");
1629 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1630 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1631 todo_wine
ok(resume
, "Expected a resume handle\n");
1632 ok(GetLastError() == ERROR_MORE_DATA
,
1633 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1635 /* Fetch that last service but pass a bigger buffer size */
1636 missing
= tempreturned
- returned
;
1637 bufsize
= tempneeded
;
1638 needed
= 0xdeadbeef;
1639 returned
= 0xdeadbeef;
1640 SetLastError(0xdeadbeef);
1641 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1642 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1643 ok(ret
, "Expected success, got error %u\n", GetLastError());
1644 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1645 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1646 ok(resume
== 0, "Expected the resume handle to be 0\n");
1647 HeapFree(GetProcessHeap(), 0, exservices
);
1649 /* See if things add up */
1651 /* Get the number of active win32 services */
1652 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1653 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1654 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1655 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1656 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1657 HeapFree(GetProcessHeap(), 0, exservices
);
1659 servicecountactive
= returned
;
1661 /* Get the number of inactive win32 services */
1662 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1663 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1664 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1665 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1666 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1667 HeapFree(GetProcessHeap(), 0, exservices
);
1669 servicecountinactive
= returned
;
1671 /* Get the number of win32 services */
1672 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1673 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1674 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1675 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1676 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1677 HeapFree(GetProcessHeap(), 0, exservices
);
1679 /* Check if total is the same as active and inactive win32 services */
1680 ok(returned
== (servicecountactive
+ servicecountinactive
),
1681 "Something wrong in the calculation\n");
1683 /* Get all drivers and services */
1684 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1685 SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1686 ok(!ret
, "Expected failure\n");
1687 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1688 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1689 SERVICE_STATE_ALL
, (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1690 ok(ret
, "Expected success %u\n", GetLastError());
1692 /* Loop through all those returned drivers and services */
1693 for (i
= 0; i
< returned
; i
++)
1695 SERVICE_STATUS_PROCESS status
= exservices
[i
].ServiceStatusProcess
;
1697 /* lpServiceName and lpDisplayName should always be filled */
1698 ok(lstrlenA(exservices
[i
].lpServiceName
) > 0, "Expected a service name\n");
1699 ok(lstrlenA(exservices
[i
].lpDisplayName
) > 0, "Expected a display name\n");
1701 /* Decrement the counters to see if the functions calls return the
1702 * same numbers as the contents of these structures.
1703 * Check some process id specifics.
1705 if (status
.dwServiceType
& (SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_KERNEL_DRIVER
))
1707 /* We shouldn't have a process id for drivers */
1708 ok(status
.dwProcessId
== 0,
1709 "This driver shouldn't have an associated process id\n");
1712 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1714 if (status
.dwCurrentState
!= SERVICE_STOPPED
)
1716 /* We expect a process id for every running service */
1717 ok(status
.dwProcessId
> 0, "Expected a process id for this running service (%s)\n",
1718 exservices
[i
].lpServiceName
);
1720 servicecountactive
--;
1724 /* We shouldn't have a process id for inactive services */
1725 ok(status
.dwProcessId
== 0, "Service %s state %u shouldn't have an associated process id\n",
1726 exservices
[i
].lpServiceName
, status
.dwCurrentState
);
1728 servicecountinactive
--;
1732 HeapFree(GetProcessHeap(), 0, exservices
);
1734 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1735 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1737 CloseServiceHandle(scm_handle
);
1740 static void test_close(void)
1746 SetLastError(0xdeadbeef);
1747 ret
= CloseServiceHandle(NULL
);
1748 ok(!ret
, "Expected failure\n");
1749 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1751 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1754 handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1755 SetLastError(0xdeadbeef);
1756 ret
= CloseServiceHandle(handle
);
1757 ok(ret
, "Expected success got error %u\n", GetLastError());
1760 static void test_sequence(void)
1762 SC_HANDLE scm_handle
, svc_handle
;
1764 QUERY_SERVICE_CONFIGA
*config
;
1765 DWORD given
, needed
;
1766 static const CHAR servicename
[] = "Winetest";
1767 static const CHAR displayname
[] = "Winetest dummy service";
1768 static const CHAR displayname2
[] = "Winetest dummy service (2)";
1769 static const CHAR pathname
[] = "we_dont_care.exe";
1770 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1771 static const CHAR password
[] = "";
1772 static const CHAR empty
[] = "";
1773 static const CHAR localsystem
[] = "LocalSystem";
1775 SetLastError(0xdeadbeef);
1776 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1778 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1780 skip("Not enough rights to get a handle to the manager\n");
1784 ok(scm_handle
!= NULL
, "Could not get a handle to the manager: %d\n", GetLastError());
1786 if (!scm_handle
) return;
1787 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
1788 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
1789 CloseServiceHandle(svc_handle
);
1791 /* Create a dummy service */
1792 SetLastError(0xdeadbeef);
1793 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1794 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1795 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1797 if (!svc_handle
&& (GetLastError() == ERROR_SERVICE_EXISTS
))
1799 /* We try and open the service and do the rest of the tests. Some could
1800 * fail if the tests were changed between these runs.
1802 trace("Deletion probably didn't work last time\n");
1803 SetLastError(0xdeadbeef);
1804 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
1805 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1807 skip("Not enough rights to open the service\n");
1808 CloseServiceHandle(scm_handle
);
1811 ok(svc_handle
!= NULL
, "Could not open the service : %d\n", GetLastError());
1813 else if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1815 skip("Not enough rights to create the service\n");
1816 CloseServiceHandle(scm_handle
);
1821 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
1822 if ((svc_handle
!= NULL
) && (pGetSecurityInfo
!= NULL
))
1824 PSID sidOwner
, sidGroup
;
1826 PSECURITY_DESCRIPTOR pSD
;
1827 DWORD error
, n1
, n2
;
1831 /* Test using GetSecurityInfo to obtain security information */
1832 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, &sidOwner
,
1833 &sidGroup
, &dacl
, &sacl
, &pSD
);
1835 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1836 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1837 NULL
, NULL
, NULL
, &pSD
);
1839 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1842 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1843 NULL
, &dacl
, NULL
, NULL
);
1844 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1845 SetLastError(0xdeadbeef);
1846 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1847 NULL
, NULL
, NULL
, NULL
);
1848 error
= GetLastError();
1849 ok(retval
== ERROR_INVALID_PARAMETER
, "Expected GetSecurityInfo to fail: result %d\n", retval
);
1850 ok(error
== 0xdeadbeef, "Unexpected last error %d\n", error
);
1853 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1855 /* Test using QueryServiceObjectSecurity to obtain security information */
1856 SetLastError(0xdeadbeef);
1857 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, NULL
, 0, &n1
);
1858 error
= GetLastError();
1859 ok(!bret
, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret
);
1860 ok(error
== ERROR_INSUFFICIENT_BUFFER
||
1861 broken(error
== ERROR_INVALID_ADDRESS
) || broken(error
== ERROR_INVALID_PARAMETER
),
1862 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error
);
1863 if (error
!= ERROR_INSUFFICIENT_BUFFER
) n1
= 1024;
1864 pSD
= LocalAlloc(0, n1
);
1865 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, pSD
, n1
, &n2
);
1866 ok(bret
, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret
);
1872 CloseServiceHandle(scm_handle
);
1877 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1878 * that the correct keys are used.
1881 /* Request the size for the buffer */
1882 SetLastError(0xdeadbeef);
1883 ret
= QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1884 ok(!ret
, "Expected failure\n");
1885 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1887 config
= HeapAlloc(GetProcessHeap(), 0, needed
);
1889 SetLastError(0xdeadbeef);
1890 ret
= QueryServiceConfigA(svc_handle
, config
, given
, &needed
);
1891 ok(ret
, "Expected success, got error %u\n", GetLastError());
1893 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1894 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1895 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1896 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1897 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1898 ok(config
->dwErrorControl
== SERVICE_ERROR_IGNORE
, "Expected SERVICE_ERROR_IGNORE, got %d\n", config
->dwErrorControl
);
1899 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1900 ok(!strcmp(config
->lpLoadOrderGroup
, empty
), "Expected an empty string, got '%s'\n", config
->lpLoadOrderGroup
);
1901 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1902 /* TODO: Show the double 0 terminated string */
1905 ok(!memcmp(config
->lpDependencies
, dependencies
, sizeof(dependencies
)), "Wrong string\n");
1907 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1908 ok(!strcmp(config
->lpDisplayName
, displayname
), "Expected '%s', got '%s'\n", displayname
, config
->lpDisplayName
);
1910 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_ERROR_NORMAL
, NULL
, "TestGroup2",
1911 NULL
, NULL
, NULL
, NULL
, displayname2
);
1912 ok(ret
, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
1914 QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1915 config
= HeapReAlloc(GetProcessHeap(), 0, config
, needed
);
1916 ok(QueryServiceConfigA(svc_handle
, config
, needed
, &needed
), "QueryServiceConfig failed\n");
1917 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1918 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1919 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1920 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1921 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1922 ok(config
->dwErrorControl
== SERVICE_ERROR_NORMAL
, "Expected SERVICE_ERROR_NORMAL, got %d\n", config
->dwErrorControl
);
1923 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1924 ok(!strcmp(config
->lpLoadOrderGroup
, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config
->lpLoadOrderGroup
);
1925 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1926 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1927 ok(!strcmp(config
->lpDisplayName
, displayname2
), "Expected '%s', got '%s'\n", displayname2
, config
->lpDisplayName
);
1929 SetLastError(0xdeadbeef);
1930 ret
= DeleteService(svc_handle
);
1931 ok(ret
, "Expected success, got error %u\n", GetLastError());
1932 CloseServiceHandle(svc_handle
);
1934 /* Wait a while. The following test does a CreateService again */
1937 CloseServiceHandle(scm_handle
);
1938 HeapFree(GetProcessHeap(), 0, config
);
1941 static void test_queryconfig2(void)
1943 SC_HANDLE scm_handle
, svc_handle
;
1945 DWORD expected
, needed
;
1946 BYTE buffer
[MAX_PATH
];
1947 LPSERVICE_DESCRIPTIONA pConfig
= (LPSERVICE_DESCRIPTIONA
)buffer
;
1948 SERVICE_PRESHUTDOWN_INFO preshutdown_info
;
1949 static const CHAR servicename
[] = "Winetest";
1950 static const CHAR displayname
[] = "Winetest dummy service";
1951 static const CHAR pathname
[] = "we_dont_care.exe";
1952 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1953 static const CHAR password
[] = "";
1954 static const CHAR description
[] = "Description";
1956 if(!pQueryServiceConfig2A
)
1958 win_skip("function QueryServiceConfig2A not present\n");
1962 SetLastError(0xdeadbeef);
1963 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1967 if(GetLastError() == ERROR_ACCESS_DENIED
)
1968 skip("Not enough rights to get a handle to the manager\n");
1970 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
1974 /* Create a dummy service */
1975 SetLastError(0xdeadbeef);
1976 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1977 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1978 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1982 if(GetLastError() == ERROR_SERVICE_EXISTS
)
1984 /* We try and open the service and do the rest of the tests. Some could
1985 * fail if the tests were changed between these runs.
1987 trace("Deletion probably didn't work last time\n");
1988 SetLastError(0xdeadbeef);
1989 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
1992 if(GetLastError() == ERROR_ACCESS_DENIED
)
1993 skip("Not enough rights to open the service\n");
1995 ok(FALSE
, "Could not open the service : %d\n", GetLastError());
1996 CloseServiceHandle(scm_handle
);
2000 if (GetLastError() == ERROR_ACCESS_DENIED
)
2002 skip("Not enough rights to create the service\n");
2003 CloseServiceHandle(scm_handle
);
2006 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
2009 CloseServiceHandle(scm_handle
);
2013 SetLastError(0xdeadbeef);
2014 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2015 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2016 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2018 SetLastError(0xdeadbeef);
2019 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2020 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2021 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2023 SetLastError(0xdeadbeef);
2024 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2025 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2026 ok(ERROR_INVALID_ADDRESS
== GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2028 SetLastError(0xdeadbeef);
2029 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2030 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2031 ok((ERROR_INVALID_ADDRESS
== GetLastError()) || (ERROR_INSUFFICIENT_BUFFER
== GetLastError()),
2032 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2034 SetLastError(0xdeadbeef);
2035 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2036 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2037 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
,buffer
,sizeof(SERVICE_DESCRIPTIONA
)-1,&needed
);
2042 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2043 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2044 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2047 pConfig
->lpDescription
= (LPSTR
)0xdeadbeef;
2048 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2049 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2050 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2051 ok(!pConfig
->lpDescription
, "expected lpDescription to be NULL, got %p\n", pConfig
->lpDescription
);
2053 SetLastError(0xdeadbeef);
2055 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2056 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2057 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2058 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2060 if(!pChangeServiceConfig2A
)
2062 win_skip("function ChangeServiceConfig2A not present\n");
2066 pConfig
->lpDescription
= (LPSTR
) description
;
2067 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
);
2068 ok(ret
, "ChangeServiceConfig2A failed\n");
2073 SetLastError(0xdeadbeef);
2075 expected
= sizeof(SERVICE_DESCRIPTIONA
) + sizeof(description
) * sizeof(WCHAR
); /* !! */
2076 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2077 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2078 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2079 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2081 SetLastError(0xdeadbeef);
2082 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
-1,&needed
);
2083 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2084 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2086 SetLastError(0xdeadbeef);
2087 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
,&needed
);
2088 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2089 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2090 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2092 SetLastError(0xdeadbeef);
2093 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
+ 1,&needed
);
2094 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2095 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2096 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2098 if(!pQueryServiceConfig2W
)
2100 win_skip("function QueryServiceConfig2W not present\n");
2103 SetLastError(0xdeadbeef);
2105 expected
= sizeof(SERVICE_DESCRIPTIONW
) + sizeof(WCHAR
) * sizeof(description
);
2106 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2107 ok(!ret
, "expected QueryServiceConfig2W to fail\n");
2108 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2109 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2111 SetLastError(0xdeadbeef);
2112 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
,&needed
);
2113 ok(ret
, "expected QueryServiceConfig2W to succeed\n");
2115 SetLastError(0xdeadbeef);
2116 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2117 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2118 if(!ret
&& GetLastError()==ERROR_INVALID_LEVEL
)
2120 /* Win2k3 and older */
2121 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2124 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2125 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2126 ok(preshutdown_info
.dwPreshutdownTimeout
== 180000, "Default PreshutdownTimeout = %d\n",
2127 preshutdown_info
.dwPreshutdownTimeout
);
2129 SetLastError(0xdeadbeef);
2130 preshutdown_info
.dwPreshutdownTimeout
= -1;
2131 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2132 (LPVOID
)&preshutdown_info
);
2133 ok(ret
, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2135 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2136 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2137 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2138 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2139 ok(preshutdown_info
.dwPreshutdownTimeout
== -1, "New PreshutdownTimeout = %d\n",
2140 preshutdown_info
.dwPreshutdownTimeout
);
2143 DeleteService(svc_handle
);
2145 CloseServiceHandle(svc_handle
);
2147 /* Wait a while. The following test does a CreateService again */
2150 CloseServiceHandle(scm_handle
);
2153 static DWORD
try_start_stop(SC_HANDLE svc_handle
, const char* name
, DWORD is_nt4
)
2157 SERVICE_STATUS status
;
2159 ret
= StartServiceA(svc_handle
, 0, NULL
);
2160 le1
= GetLastError();
2161 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2163 if (pQueryServiceStatusEx
)
2166 SERVICE_STATUS_PROCESS statusproc
;
2168 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&statusproc
, sizeof(statusproc
), &needed
);
2169 ok(ret
, "%s: QueryServiceStatusEx() failed le=%u\n", name
, GetLastError());
2170 ok(statusproc
.dwCurrentState
== SERVICE_STOPPED
, "%s: should be stopped state=%x\n", name
, statusproc
.dwCurrentState
);
2171 ok(statusproc
.dwProcessId
== 0, "%s: ProcessId should be 0 instead of %x\n", name
, statusproc
.dwProcessId
);
2174 ret
= StartServiceA(svc_handle
, 0, NULL
);
2175 le2
= GetLastError();
2176 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2177 ok(le2
== le1
, "%s: the second try should yield the same error: %u != %u\n", name
, le1
, le2
);
2179 status
.dwCurrentState
= 0xdeadbeef;
2180 ret
= ControlService(svc_handle
, SERVICE_CONTROL_STOP
, &status
);
2181 le2
= GetLastError();
2182 ok(!ret
, "%s: ControlService() should have failed\n", name
);
2183 ok(le2
== ERROR_SERVICE_NOT_ACTIVE
, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name
, le2
);
2184 ok(status
.dwCurrentState
== SERVICE_STOPPED
||
2185 broken(is_nt4
), /* NT4 returns a random value */
2186 "%s: should be stopped state=%x\n", name
, status
.dwCurrentState
);
2191 static void test_start_stop(void)
2194 SC_HANDLE scm_handle
, svc_handle
;
2196 static const char servicename
[] = "Winetest";
2197 char cmd
[MAX_PATH
+20];
2198 const char* displayname
;
2200 SetLastError(0xdeadbeef);
2201 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2204 if(GetLastError() == ERROR_ACCESS_DENIED
)
2205 skip("Not enough rights to get a handle to the manager\n");
2207 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
2212 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
2213 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
2215 /* Do some cleanup in case a previous run crashed */
2216 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2219 DeleteService(svc_handle
);
2220 CloseServiceHandle(svc_handle
);
2223 /* Create a dummy disabled service */
2224 sprintf(cmd
, "\"%s\" service exit", selfname
);
2225 displayname
= "Winetest Disabled Service";
2226 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
,
2227 GENERIC_ALL
, SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
,
2228 SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
, cmd
, NULL
,
2229 NULL
, NULL
, NULL
, NULL
);
2232 if(GetLastError() == ERROR_ACCESS_DENIED
)
2233 skip("Not enough rights to create the service\n");
2235 ok(FALSE
, "Could not create the service: %d\n", GetLastError());
2238 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2239 ok(le
== ERROR_SERVICE_DISABLED
, "%d != ERROR_SERVICE_DISABLED\n", le
);
2241 /* Then one with a bad path */
2242 displayname
= "Winetest Bad Path";
2243 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_DEMAND_START
, SERVICE_NO_CHANGE
, "c:\\no_such_file.exe", NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2244 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2245 try_start_stop(svc_handle
, displayname
, is_nt4
);
2249 /* NT4 does not detect when a service fails to start and uses an
2250 * insanely long timeout: 120s. So skip the rest of the tests.
2252 win_skip("Skip some service start/stop tests on NT4\n");
2256 /* Again with a process that exits right away */
2257 displayname
= "Winetest Exit Service";
2258 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2259 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2260 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2261 ok(le
== ERROR_SERVICE_REQUEST_TIMEOUT
, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le
);
2263 /* And finally with a service that plays dead, forcing a timeout.
2264 * This time we will put no quotes. That should work too, even if there are
2265 * spaces in the path.
2267 sprintf(cmd
, "%s service sleep", selfname
);
2268 displayname
= "Winetest Sleep Service";
2269 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2270 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2272 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2273 ok(le
== ERROR_SERVICE_REQUEST_TIMEOUT
, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le
);
2278 DeleteService(svc_handle
);
2279 CloseServiceHandle(svc_handle
);
2282 /* Wait a while. The following test does a CreateService again */
2285 CloseServiceHandle(scm_handle
);
2288 static void test_refcount(void)
2290 SC_HANDLE scm_handle
, svc_handle1
, svc_handle2
, svc_handle3
, svc_handle4
, svc_handle5
;
2291 static const CHAR servicename
[] = "Winetest";
2292 static const CHAR pathname
[] = "we_dont_care.exe";
2295 /* Get a handle to the Service Control Manager */
2296 SetLastError(0xdeadbeef);
2297 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2298 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
2300 skip("Not enough rights to get a handle to the manager\n");
2304 /* Create a service */
2305 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2306 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2307 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2308 ok(svc_handle1
!= NULL
, "Expected success, got error %u\n", GetLastError());
2310 /* Get a handle to this new service */
2311 svc_handle2
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2312 ok(svc_handle2
!= NULL
, "Expected success, got error %u\n", GetLastError());
2314 /* Get another handle to this new service */
2315 svc_handle3
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2316 ok(svc_handle3
!= NULL
, "Expected success, got error %u\n", GetLastError());
2318 /* Check if we can close the handle to the Service Control Manager */
2319 ret
= CloseServiceHandle(scm_handle
);
2320 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2322 /* Get a new handle to the Service Control Manager */
2323 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2324 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
2326 /* Get a handle to this new service */
2327 svc_handle4
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2328 ok(svc_handle4
!= NULL
, "Expected success, got error %u\n", GetLastError());
2330 /* Delete the service */
2331 ret
= DeleteService(svc_handle4
);
2332 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2334 /* We cannot create the same service again as it's still marked as 'being deleted'.
2335 * The reason is that we still have 4 open handles to this service even though we
2336 * closed the handle to the Service Control Manager in between.
2338 SetLastError(0xdeadbeef);
2339 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2340 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2341 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2344 ok(!svc_handle5
, "Expected failure\n");
2345 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE
,
2346 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2349 /* FIXME: Remove this when Wine is fixed */
2352 DeleteService(svc_handle5
);
2353 CloseServiceHandle(svc_handle5
);
2356 /* Close all the handles to the service and try again */
2357 ret
= CloseServiceHandle(svc_handle4
);
2358 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2359 ret
= CloseServiceHandle(svc_handle3
);
2360 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2361 ret
= CloseServiceHandle(svc_handle2
);
2362 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2363 ret
= CloseServiceHandle(svc_handle1
);
2364 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2366 /* Wait a while. Doing a CreateService too soon will result again
2367 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2371 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2372 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2373 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2374 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2375 ok(svc_handle5
!= NULL
, "Expected success, got error %u\n", GetLastError());
2377 /* Delete the service */
2378 ret
= DeleteService(svc_handle5
);
2379 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2381 /* Wait a while. Just in case one of the following tests does a CreateService again */
2384 CloseServiceHandle(svc_handle5
);
2385 CloseServiceHandle(scm_handle
);
2390 SC_HANDLE scm_handle
;
2394 myARGC
= winetest_get_mainargs(&myARGV
);
2395 GetFullPathNameA(myARGV
[0], sizeof(selfname
), selfname
, NULL
);
2398 if (strcmp(myARGV
[2], "sleep") == 0)
2399 /* Cause a service startup timeout */
2401 /* then, or if myARGV[2] == "exit", just exit */
2405 /* Bail out if we are on win98 */
2406 SetLastError(0xdeadbeef);
2407 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2409 if (!scm_handle
&& (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
))
2411 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2414 CloseServiceHandle(scm_handle
);
2416 init_function_pointers();
2418 /* First some parameter checking */
2421 test_create_delete_svc();
2422 test_get_displayname();
2423 test_get_servicekeyname();
2427 /* Test the creation, querying and deletion of a service */
2429 test_queryconfig2();
2431 /* The main reason for this test is to check if any refcounting is used
2432 * and what the rules are