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
*pChangeServiceConfig2W
)(SC_HANDLE
,DWORD
,LPVOID
);
40 static BOOL (WINAPI
*pEnumServicesStatusExA
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
41 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
42 LPDWORD
, LPDWORD
, LPCSTR
);
43 static BOOL (WINAPI
*pEnumServicesStatusExW
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
44 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
45 LPDWORD
, LPDWORD
, LPCWSTR
);
46 static DWORD (WINAPI
*pGetSecurityInfo
)(HANDLE
, SE_OBJECT_TYPE
, SECURITY_INFORMATION
,
47 PSID
*, PSID
*, PACL
*, PACL
*, PSECURITY_DESCRIPTOR
*);
48 static BOOL (WINAPI
*pQueryServiceConfig2A
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
49 static BOOL (WINAPI
*pQueryServiceConfig2W
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
50 static BOOL (WINAPI
*pQueryServiceStatusEx
)(SC_HANDLE
, SC_STATUS_TYPE
, LPBYTE
,
52 static BOOL (WINAPI
*pQueryServiceObjectSecurity
)(SC_HANDLE
, SECURITY_INFORMATION
,
53 PSECURITY_DESCRIPTOR
, DWORD
, LPDWORD
);
54 static DWORD (WINAPI
*pNotifyServiceStatusChangeW
)(SC_HANDLE
,DWORD
,SERVICE_NOTIFYW
*);
56 static void init_function_pointers(void)
58 HMODULE hadvapi32
= GetModuleHandleA("advapi32.dll");
60 pChangeServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "ChangeServiceConfig2A");
61 pChangeServiceConfig2W
= (void*)GetProcAddress(hadvapi32
, "ChangeServiceConfig2W");
62 pEnumServicesStatusExA
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExA");
63 pEnumServicesStatusExW
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExW");
64 pGetSecurityInfo
= (void *)GetProcAddress(hadvapi32
, "GetSecurityInfo");
65 pQueryServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2A");
66 pQueryServiceConfig2W
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2W");
67 pQueryServiceStatusEx
= (void*)GetProcAddress(hadvapi32
, "QueryServiceStatusEx");
68 pQueryServiceObjectSecurity
= (void*)GetProcAddress(hadvapi32
, "QueryServiceObjectSecurity");
69 pNotifyServiceStatusChangeW
= (void*)GetProcAddress(hadvapi32
, "NotifyServiceStatusChangeW");
72 static void test_open_scm(void)
76 /* No access rights */
77 SetLastError(0xdeadbeef);
78 scm_handle
= OpenSCManagerA(NULL
, NULL
, 0);
79 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
80 CloseServiceHandle(scm_handle
);
82 /* Unknown database name */
83 SetLastError(0xdeadbeef);
84 scm_handle
= OpenSCManagerA(NULL
, "DoesNotExist", SC_MANAGER_CONNECT
);
85 ok(!scm_handle
, "Expected failure\n");
86 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
87 CloseServiceHandle(scm_handle
); /* Just in case */
89 /* MSDN says only ServiceActive is allowed, or NULL */
90 SetLastError(0xdeadbeef);
91 scm_handle
= OpenSCManagerA(NULL
, SERVICES_FAILED_DATABASEA
, SC_MANAGER_CONNECT
);
92 ok(!scm_handle
, "Expected failure\n");
93 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST
, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
94 CloseServiceHandle(scm_handle
); /* Just in case */
96 /* Remote unknown host */
97 SetLastError(0xdeadbeef);
98 scm_handle
= OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
101 ok(!scm_handle
, "Expected failure\n");
102 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE
|| GetLastError() == RPC_S_INVALID_NET_ADDR
/* w2k8 */,
103 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
105 CloseServiceHandle(scm_handle
); /* Just in case */
107 /* Proper call with an empty hostname */
108 scm_handle
= OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
109 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
110 CloseServiceHandle(scm_handle
);
112 /* Again a correct one */
113 SetLastError(0xdeadbeef);
114 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
115 ok(GetLastError() == ERROR_SUCCESS
|| broken(GetLastError() == ERROR_IO_PENDING
) /* win2k */,
116 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
117 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
118 CloseServiceHandle(scm_handle
);
121 static void test_open_svc(void)
123 SC_HANDLE scm_handle
, svc_handle
;
124 CHAR displayname
[4096];
127 /* All NULL (invalid access rights) */
128 SetLastError(0xdeadbeef);
129 svc_handle
= OpenServiceA(NULL
, NULL
, 0);
130 ok(!svc_handle
, "Expected failure\n");
131 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
133 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
136 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
137 SetLastError(0xdeadbeef);
138 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
139 ok(!svc_handle
, "Expected failure\n");
140 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
141 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
142 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
143 CloseServiceHandle(scm_handle
);
145 /* Nonexistent service */
146 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
147 SetLastError(0xdeadbeef);
148 svc_handle
= OpenServiceA(scm_handle
, "deadbeef", GENERIC_READ
);
149 ok(!svc_handle
, "Expected failure\n");
150 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
151 CloseServiceHandle(scm_handle
);
153 /* Proper SCM handle but different access rights */
154 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
155 SetLastError(0xdeadbeef);
156 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_WRITE
);
157 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
158 skip("Not enough rights to get a handle to the service\n");
161 ok(svc_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
162 CloseServiceHandle(svc_handle
);
165 /* Test to show we can't open a service with the displayname */
167 /* Retrieve the needed size for the buffer */
169 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
170 /* Get the displayname */
171 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
172 /* Try to open the service with this displayname, unless the displayname equals
173 * the servicename as that would defeat the purpose of this test.
175 if (!lstrcmpiA(spooler
, displayname
))
177 skip("displayname equals servicename\n");
178 CloseServiceHandle(scm_handle
);
182 SetLastError(0xdeadbeef);
183 svc_handle
= OpenServiceA(scm_handle
, displayname
, GENERIC_READ
);
184 ok(!svc_handle
, "Expected failure\n");
185 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
187 CloseServiceHandle(svc_handle
);
189 CloseServiceHandle(scm_handle
);
192 static void test_create_delete_svc(void)
194 SC_HANDLE scm_handle
, svc_handle1
, svc_handle2
;
195 CHAR username
[UNLEN
+ 1], domain
[MAX_PATH
];
196 DWORD user_size
= UNLEN
+ 1;
197 CHAR account
[UNLEN
+ 3];
198 static const CHAR servicename
[] = "Winetest";
199 static const CHAR pathname
[] = "we_dont_care.exe";
200 static const CHAR empty
[] = "";
201 static const CHAR password
[] = "secret";
202 BOOL spooler_exists
= FALSE
;
205 DWORD display_size
= sizeof(display
);
207 /* Get the username and turn it into an account to be used in some tests */
208 GetUserNameA(username
, &user_size
);
209 /* Get the domainname to cater for that situation */
210 if (GetEnvironmentVariableA("USERDOMAIN", domain
, MAX_PATH
))
211 sprintf(account
, "%s\\%s", domain
, username
);
213 sprintf(account
, ".\\%s", username
);
216 SetLastError(0xdeadbeef);
217 svc_handle1
= CreateServiceA(NULL
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
218 ok(!svc_handle1
, "Expected failure\n");
219 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
221 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
223 /* Only a valid handle to the Service Control Manager */
224 SetLastError(0xdeadbeef);
225 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
226 ok(!svc_handle1
, "Expected failure\n");
227 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
228 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
229 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
231 /* Now with a servicename */
232 SetLastError(0xdeadbeef);
233 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
234 ok(!svc_handle1
, "Expected failure\n");
235 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
236 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
237 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
239 /* Or just a binary name */
240 SetLastError(0xdeadbeef);
241 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
242 ok(!svc_handle1
, "Expected failure\n");
243 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
244 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
245 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
247 /* Both servicename and binary name (We only have connect rights) */
248 SetLastError(0xdeadbeef);
249 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
250 ok(!svc_handle1
, "Expected failure\n");
251 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
253 /* They can even be empty at this stage of parameter checking */
254 SetLastError(0xdeadbeef);
255 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, pathname
, 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 SetLastError(0xdeadbeef);
260 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
261 ok(!svc_handle1
, "Expected failure\n");
262 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
264 /* Open the Service Control Manager with minimal rights for creation
265 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
267 CloseServiceHandle(scm_handle
);
268 SetLastError(0xdeadbeef);
269 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
270 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
272 skip("Not enough rights to get a handle to the manager\n");
276 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
278 /* Empty strings for servicename and binary name are checked */
279 SetLastError(0xdeadbeef);
280 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
281 ok(!svc_handle1
, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
284 SetLastError(0xdeadbeef);
285 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
286 ok(!svc_handle1
, "Expected failure\n");
287 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
289 SetLastError(0xdeadbeef);
290 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
291 ok(!svc_handle1
, "Expected failure\n");
292 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
294 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
295 * an ERROR_INVALID_PARAMETER)
297 SetLastError(0xdeadbeef);
298 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
299 SERVICE_DISABLED
, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
300 ok(!svc_handle1
, "Expected failure\n");
301 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
303 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
305 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
306 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
308 SetLastError(0xdeadbeef);
309 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
,
310 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
311 ok(!svc_handle1
, "Expected failure\n");
312 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
314 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
315 SetLastError(0xdeadbeef);
316 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_INTERACTIVE_PROCESS
,
317 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
318 ok(!svc_handle1
, "Expected failure\n");
319 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
321 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
322 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
324 SetLastError(0xdeadbeef);
325 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
326 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, account
, password
);
327 ok(!svc_handle1
, "Expected failure\n");
328 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT
,
329 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
331 /* Illegal (start-type is not a mask and should only be one of the possibilities)
332 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
333 * it's most likely not the wanted start-type)
335 SetLastError(0xdeadbeef);
336 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
,
337 SERVICE_AUTO_START
| SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
338 ok(!svc_handle1
, "Expected failure\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
341 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
342 SetLastError(0xdeadbeef);
343 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
344 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
345 ok(!svc_handle1
, "Expected failure\n");
346 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
348 /* Test if ServiceType can be a combined one for drivers */
349 SetLastError(0xdeadbeef);
350 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_KERNEL_DRIVER
| SERVICE_FILE_SYSTEM_DRIVER
,
351 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
352 ok(!svc_handle1
, "Expected failure\n");
353 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
355 /* The service already exists (check first, just in case) */
356 svc_handle1
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
359 spooler_exists
= TRUE
;
360 CloseServiceHandle(svc_handle1
);
361 SetLastError(0xdeadbeef);
362 svc_handle1
= CreateServiceA(scm_handle
, spooler
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
363 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
364 ok(!svc_handle1
, "Expected failure\n");
365 ok(GetLastError() == ERROR_SERVICE_EXISTS
, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
368 skip("Spooler service doesn't exist\n");
370 /* To find an existing displayname we check the 'Spooler' service. Although the registry
371 * doesn't show DisplayName on NT4, this call will return a displayname which is equal
372 * to the servicename and can't be used as well for a new displayname.
376 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, display
, &display_size
);
379 skip("Could not retrieve a displayname for the Spooler service\n");
382 svc_handle1
= CreateServiceA(scm_handle
, servicename
, display
, 0, SERVICE_WIN32_OWN_PROCESS
,
383 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
384 ok(!svc_handle1
, "Expected failure for display name '%s'\n", display
);
385 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME
,
386 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
390 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
392 /* Windows doesn't care about the access rights for creation (which makes
393 * sense as there is no service yet) as long as there are sufficient
394 * rights to the manager.
396 SetLastError(0xdeadbeef);
397 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
398 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
399 ok(svc_handle1
!= NULL
, "Could not create the service : %d\n", GetLastError());
401 /* DeleteService however must have proper rights */
402 SetLastError(0xdeadbeef);
403 ret
= DeleteService(svc_handle1
);
404 ok(!ret
, "Expected failure\n");
405 ok(GetLastError() == ERROR_ACCESS_DENIED
,
406 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
408 /* Open the service with minimal rights for deletion.
409 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
411 CloseServiceHandle(svc_handle1
);
412 svc_handle1
= OpenServiceA(scm_handle
, servicename
, DELETE
);
414 /* Now that we have the proper rights, we should be able to delete */
415 SetLastError(0xdeadbeef);
416 ret
= DeleteService(svc_handle1
);
417 ok(ret
, "Expected success, got error %u\n", GetLastError());
419 /* Service is marked for delete, but handle is still open. Try to open service again. */
420 svc_handle2
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
421 ok(svc_handle2
!= NULL
, "got %p, error %u\n", svc_handle2
, GetLastError());
422 CloseServiceHandle(svc_handle2
);
424 CloseServiceHandle(svc_handle1
);
425 CloseServiceHandle(scm_handle
);
427 /* Wait a while. One of the following tests also does a CreateService for the
428 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
429 * error if we do this too quickly. Vista seems more picky than the others.
433 /* And a final NULL check */
434 SetLastError(0xdeadbeef);
435 ret
= DeleteService(NULL
);
436 ok(!ret
, "Expected failure\n");
437 ok(GetLastError() == ERROR_INVALID_HANDLE
,
438 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
441 static void test_get_displayname(void)
443 SC_HANDLE scm_handle
, svc_handle
;
445 CHAR displayname
[4096];
446 WCHAR displaynameW
[2048];
447 DWORD displaysize
, tempsize
, tempsizeW
;
448 static const CHAR deadbeef
[] = "Deadbeef";
449 static const WCHAR spoolerW
[] = {'S','p','o','o','l','e','r',0};
450 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
451 static const WCHAR abcW
[] = {'A','B','C',0};
452 static const CHAR servicename
[] = "Winetest";
453 static const CHAR pathname
[] = "we_dont_care.exe";
455 /* Having NULL for the size of the buffer will crash on W2K3 */
457 SetLastError(0xdeadbeef);
458 ret
= GetServiceDisplayNameA(NULL
, NULL
, NULL
, &displaysize
);
459 ok(!ret
, "Expected failure\n");
460 ok(GetLastError() == ERROR_INVALID_HANDLE
,
461 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
463 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
465 SetLastError(0xdeadbeef);
466 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, NULL
, &displaysize
);
467 ok(!ret
, "Expected failure\n");
468 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
469 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
470 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
472 SetLastError(0xdeadbeef);
473 displaysize
= sizeof(displayname
);
474 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, displayname
, &displaysize
);
475 ok(!ret
, "Expected failure\n");
476 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
477 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
478 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
480 /* Test for nonexistent service */
481 SetLastError(0xdeadbeef);
483 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
484 ok(!ret
, "Expected failure\n");
485 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
486 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
488 SetLastError(0xdeadbeef);
489 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
490 ok(!ret
, "Expected failure\n");
491 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
492 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
493 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
496 strcpy(displayname
, "ABC");
497 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
498 ok(!ret
, "Expected failure\n");
499 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
500 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
501 todo_wine
ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
502 ok(displayname
[0] == 0, "Service name not empty\n");
505 lstrcpyW( displaynameW
, abcW
);
506 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
507 ok(!ret
, "Expected failure\n");
508 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
509 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
510 ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
511 ok(displaynameW
[0] == 0, "Service name not empty\n");
514 strcpy(displayname
, "ABC");
515 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
516 ok(!ret
, "Expected failure\n");
517 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
518 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
519 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
520 ok(displayname
[0] == 'A', "Service name changed\n");
523 lstrcpyW( displaynameW
, abcW
);
524 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
525 ok(!ret
, "Expected failure\n");
526 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
527 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
528 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
529 ok(displaynameW
[0] == 'A', "Service name changed\n");
532 strcpy(displayname
, "ABC");
533 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
534 ok(!ret
, "Expected failure\n");
535 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
536 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
537 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
538 ok(displayname
[0] == 0, "Service name not empty\n");
541 lstrcpyW( displaynameW
, abcW
);
542 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
543 ok(!ret
, "Expected failure\n");
544 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
545 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
546 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
547 ok(displaynameW
[0] == 'A', "Service name changed\n");
550 strcpy(displayname
, "ABC");
551 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
552 ok(!ret
, "Expected failure\n");
553 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
554 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
555 todo_wine
ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
556 ok(displayname
[0] == 0, "Service name not empty\n");
559 lstrcpyW( displaynameW
, abcW
);
560 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
561 ok(!ret
, "Expected failure\n");
562 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
563 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
564 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
565 ok(displaynameW
[0] == 0, "Service name not empty\n");
567 /* Check if 'Spooler' exists */
568 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
571 skip("Spooler service doesn't exist\n");
572 CloseServiceHandle(scm_handle
);
575 CloseServiceHandle(svc_handle
);
577 /* Retrieve the needed size for the buffer */
578 SetLastError(0xdeadbeef);
580 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
581 ok(!ret
, "Expected failure\n");
582 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
583 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
584 tempsize
= displaysize
;
587 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
588 ok(!ret
, "Expected failure\n");
589 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
590 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
591 ok(displaysize
== tempsize
, "Buffer size mismatch (%d vs %d)\n", tempsize
, displaysize
);
593 /* Buffer is too small */
594 SetLastError(0xdeadbeef);
595 displaysize
= (tempsize
/ 2);
596 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
597 ok(!ret
, "Expected failure\n");
598 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
599 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
600 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
602 /* First try with a buffer that should be big enough to hold
603 * the ANSI string (and terminating character). This succeeds on Windows
604 * although when asked (see above 2 tests) it will return twice the needed size.
606 SetLastError(0xdeadbeef);
607 displaysize
= (tempsize
/ 2) + 1;
608 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
609 ok(ret
, "Expected success, got error %u\n", GetLastError());
610 ok(displaysize
== ((tempsize
/ 2) + 1), "Expected no change for the needed buffer size\n");
612 /* Now with the original returned size */
613 SetLastError(0xdeadbeef);
614 displaysize
= tempsize
;
615 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
616 ok(ret
, "Expected success, got error %u\n", GetLastError());
617 ok(displaysize
== tempsize
, "Expected no change for the needed buffer size\n");
619 /* And with a bigger than needed buffer */
620 SetLastError(0xdeadbeef);
621 displaysize
= tempsize
* 2;
622 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
623 ok(ret
, "Expected success, got error %u\n", GetLastError());
624 /* Test that shows that if the buffersize is enough, it's not changed */
625 ok(displaysize
== tempsize
* 2, "Expected no change for the needed buffer size\n");
626 ok(strlen(displayname
) == tempsize
/2,
627 "Expected the buffer to be twice the length of the string\n") ;
629 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
630 SetLastError(0xdeadbeef);
632 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, NULL
, &displaysize
);
633 ok(!ret
, "Expected failure\n");
634 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
635 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
637 /* Buffer is too small */
638 SetLastError(0xdeadbeef);
639 tempsizeW
= displaysize
;
640 displaysize
= tempsizeW
/ 2;
641 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
642 ok(!ret
, "Expected failure\n");
643 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
644 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
645 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
647 /* Now with the original returned size */
648 SetLastError(0xdeadbeef);
649 displaysize
= tempsizeW
;
650 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
651 ok(!ret
, "Expected failure\n");
652 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
653 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
654 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
656 /* And with a bigger than needed buffer */
657 SetLastError(0xdeadbeef);
658 displaysize
= tempsizeW
+ 1; /* This caters for the null terminating character */
659 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
660 ok(ret
, "Expected success, got error %u\n", GetLastError());
661 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
662 ok(lstrlenW(displaynameW
) == displaysize
,
663 "Expected the buffer to be the length of the string\n") ;
664 ok(tempsize
/ 2 == tempsizeW
,
665 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
667 CloseServiceHandle(scm_handle
);
669 /* Test for a service without a displayname (which is valid). This should return
670 * the servicename itself.
672 SetLastError(0xdeadbeef);
673 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
674 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
676 skip("Not enough rights to get a handle to the manager\n");
680 SetLastError(0xdeadbeef);
681 svc_handle
= CreateServiceA(scm_handle
, servicename
, NULL
, DELETE
,
682 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
683 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
684 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
687 CloseServiceHandle(scm_handle
);
691 /* Retrieve the needed size for the buffer */
692 SetLastError(0xdeadbeef);
694 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, NULL
, &displaysize
);
695 ok(!ret
, "Expected failure\n");
696 ok(displaysize
== strlen(servicename
) * 2,
697 "Expected the displaysize to be twice the size of the servicename\n");
698 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
699 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
701 /* Buffer is too small */
702 SetLastError(0xdeadbeef);
703 tempsize
= displaysize
;
704 displaysize
= (tempsize
/ 2);
705 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
706 ok(!ret
, "Expected failure\n");
707 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
708 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
709 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
711 /* Get the displayname */
712 SetLastError(0xdeadbeef);
713 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
714 ok(ret
, "Expected success, got error %u\n", GetLastError());
715 ok(!lstrcmpiA(displayname
, servicename
),
716 "Expected displayname to be %s, got %s\n", servicename
, displayname
);
718 /* Delete the service */
719 ret
= DeleteService(svc_handle
);
720 ok(ret
, "Expected success (err=%d)\n", GetLastError());
722 CloseServiceHandle(svc_handle
);
723 CloseServiceHandle(scm_handle
);
725 /* Wait a while. Just in case one of the following tests does a CreateService again */
729 static void test_get_servicekeyname(void)
731 SC_HANDLE scm_handle
, svc_handle
;
732 CHAR servicename
[4096];
733 CHAR displayname
[4096];
734 WCHAR servicenameW
[4096];
735 WCHAR displaynameW
[4096];
736 DWORD servicesize
, displaysize
, tempsize
;
738 static const CHAR deadbeef
[] = "Deadbeef";
739 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
740 static const WCHAR abcW
[] = {'A','B','C',0};
742 /* Having NULL for the size of the buffer will crash on W2K3 */
744 SetLastError(0xdeadbeef);
745 ret
= GetServiceKeyNameA(NULL
, NULL
, NULL
, &servicesize
);
746 ok(!ret
, "Expected failure\n");
747 ok(GetLastError() == ERROR_INVALID_HANDLE
,
748 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
750 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
753 SetLastError(0xdeadbeef);
754 ret
= GetServiceKeyNameA(scm_handle
, NULL
, NULL
, &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
== 1, "Service size expected 1, got %d\n", servicesize
);
761 /* Valid handle and buffer but no displayname */
763 SetLastError(0xdeadbeef);
764 ret
= GetServiceKeyNameA(scm_handle
, NULL
, servicename
, &servicesize
);
765 ok(!ret
, "Expected failure\n");
766 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
767 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
768 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
769 todo_wine
ok(servicesize
== 200, "Service size expected 1, got %d\n", servicesize
);
771 /* Test for nonexistent displayname */
772 SetLastError(0xdeadbeef);
773 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, NULL
, &servicesize
);
774 ok(!ret
, "Expected failure\n");
775 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
776 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
777 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
780 strcpy(servicename
, "ABC");
781 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
782 ok(!ret
, "Expected failure\n");
783 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
784 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
785 todo_wine
ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
786 ok(servicename
[0] == 0, "Service name not empty\n");
789 lstrcpyW( servicenameW
, abcW
);
790 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
791 ok(!ret
, "Expected failure\n");
792 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
793 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
794 ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
795 ok(servicenameW
[0] == 0, "Service name not empty\n");
798 strcpy(servicename
, "ABC");
799 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
800 ok(!ret
, "Expected failure\n");
801 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
802 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
803 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
804 ok(servicename
[0] == 'A', "Service name changed\n");
807 lstrcpyW( servicenameW
, abcW
);
808 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
809 ok(!ret
, "Expected failure\n");
810 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
811 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
812 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
813 ok(servicenameW
[0] == 'A', "Service name changed\n");
816 strcpy(servicename
, "ABC");
817 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
818 ok(!ret
, "Expected failure\n");
819 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
820 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
821 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
822 ok(servicename
[0] == 0, "Service name not empty\n");
825 lstrcpyW( servicenameW
, abcW
);
826 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
827 ok(!ret
, "Expected failure\n");
828 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
829 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
830 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
831 ok(servicenameW
[0] == 'A', "Service name changed\n");
834 strcpy(servicename
, "ABC");
835 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
836 ok(!ret
, "Expected failure\n");
837 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
838 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
839 todo_wine
ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
840 ok(servicename
[0] == 0, "Service name not empty\n");
843 lstrcpyW( servicenameW
, abcW
);
844 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
845 ok(!ret
, "Expected failure\n");
846 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
847 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
848 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
849 ok(servicenameW
[0] == 0, "Service name not empty\n");
851 /* Check if 'Spooler' exists */
852 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
855 skip("Spooler service doesn't exist\n");
856 CloseServiceHandle(scm_handle
);
859 CloseServiceHandle(svc_handle
);
861 /* Get the displayname for the 'Spooler' service */
862 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
863 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
865 /* Retrieve the needed size for the buffer */
866 SetLastError(0xdeadbeef);
868 ret
= GetServiceKeyNameA(scm_handle
, displayname
, NULL
, &servicesize
);
869 ok(!ret
, "Expected failure\n");
870 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
871 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
873 /* Valid call with the correct buffersize */
874 SetLastError(0xdeadbeef);
875 tempsize
= servicesize
;
877 ret
= GetServiceKeyNameA(scm_handle
, displayname
, servicename
, &servicesize
);
878 ok(ret
, "Expected success, got error %u\n", GetLastError());
881 ok(strlen(servicename
) == tempsize
/2,
882 "Expected the buffer to be twice the length of the string\n") ;
883 ok(!lstrcmpiA(servicename
, spooler
), "Expected %s, got %s\n", spooler
, servicename
);
884 ok(servicesize
== (tempsize
* 2),
885 "Expected servicesize not to change if buffer not insufficient\n") ;
888 MultiByteToWideChar(CP_ACP
, 0, displayname
, -1, displaynameW
, sizeof(displaynameW
)/2);
889 SetLastError(0xdeadbeef);
891 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
892 ok(ret
, "Expected success, got error %u\n", GetLastError());
895 ok(strlen(servicename
) == tempsize
/2,
896 "Expected the buffer to be twice the length of the string\n") ;
897 ok(servicesize
== lstrlenW(servicenameW
),
898 "Expected servicesize not to change if buffer not insufficient\n") ;
901 SetLastError(0xdeadbeef);
903 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
904 ok(!ret
, "Expected failure\n");
905 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
906 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
907 ok(servicenameW
[0] == 0, "Buffer not empty\n");
909 CloseServiceHandle(scm_handle
);
912 static void test_query_svc(void)
914 SC_HANDLE scm_handle
, svc_handle
;
916 SERVICE_STATUS status
;
917 SERVICE_STATUS_PROCESS
*statusproc
;
918 DWORD bufsize
, needed
;
920 /* All NULL or wrong */
921 SetLastError(0xdeadbeef);
922 ret
= QueryServiceStatus(NULL
, NULL
);
923 ok(!ret
, "Expected failure\n");
924 ok(GetLastError() == ERROR_INVALID_HANDLE
,
925 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
927 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
929 /* Check if 'Spooler' exists.
930 * Open with not enough rights to query the status.
932 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
935 skip("Spooler service doesn't exist\n");
936 CloseServiceHandle(scm_handle
);
940 SetLastError(0xdeadbeef);
941 ret
= QueryServiceStatus(svc_handle
, NULL
);
942 ok(!ret
, "Expected failure\n");
943 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
944 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
945 "Unexpected last error %d\n", GetLastError());
947 SetLastError(0xdeadbeef);
948 ret
= QueryServiceStatus(svc_handle
, &status
);
949 ok(!ret
, "Expected failure\n");
950 ok(GetLastError() == ERROR_ACCESS_DENIED
,
951 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
953 /* Open the service with just enough rights.
954 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
956 CloseServiceHandle(svc_handle
);
957 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
959 SetLastError(0xdeadbeef);
960 ret
= QueryServiceStatus(svc_handle
, &status
);
961 ok(ret
, "Expected success, got error %u\n", GetLastError());
963 CloseServiceHandle(svc_handle
);
965 /* More or less the same tests for QueryServiceStatusEx */
966 if (!pQueryServiceStatusEx
)
968 win_skip( "QueryServiceStatusEx not available\n" );
969 CloseServiceHandle(scm_handle
);
973 /* Open service with not enough rights to query the status */
974 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
976 /* All NULL or wrong, this proves that info level is checked first */
977 SetLastError(0xdeadbeef);
978 ret
= pQueryServiceStatusEx(NULL
, 1, NULL
, 0, NULL
);
979 ok(!ret
, "Expected failure\n");
980 ok(GetLastError() == ERROR_INVALID_LEVEL
,
981 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
983 /* Passing a NULL parameter for the needed buffer size
984 * will crash on anything but NT4.
987 /* Only info level is correct. It looks like the buffer/size is checked second */
988 SetLastError(0xdeadbeef);
989 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
990 /* NT4 checks the handle first */
991 if (GetLastError() != ERROR_INVALID_HANDLE
)
993 ok(!ret
, "Expected failure\n");
994 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
995 "Needed buffersize is wrong : %d\n", needed
);
996 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
997 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1000 /* Pass a correct buffer and buffersize but a NULL handle */
1001 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1003 SetLastError(0xdeadbeef);
1004 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1005 ok(!ret
, "Expected failure\n");
1006 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1007 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1008 HeapFree(GetProcessHeap(), 0, statusproc
);
1010 /* Correct handle and info level */
1011 SetLastError(0xdeadbeef);
1012 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
1013 /* NT4 doesn't return the needed size */
1014 if (GetLastError() != ERROR_INVALID_PARAMETER
)
1016 ok(!ret
, "Expected failure\n");
1017 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
1018 "Needed buffersize is wrong : %d\n", needed
);
1019 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1020 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1023 /* All parameters are OK but we don't have enough rights */
1024 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1025 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1026 SetLastError(0xdeadbeef);
1027 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1028 ok(!ret
, "Expected failure\n");
1029 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1030 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1031 HeapFree(GetProcessHeap(), 0, statusproc
);
1033 /* Open the service with just enough rights. */
1034 CloseServiceHandle(svc_handle
);
1035 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
1037 /* Everything should be fine now. */
1038 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1039 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1040 SetLastError(0xdeadbeef);
1041 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1042 ok(ret
, "Expected success, got error %u\n", GetLastError());
1043 if (statusproc
->dwCurrentState
== SERVICE_RUNNING
)
1044 ok(statusproc
->dwProcessId
!= 0,
1045 "Expect a process id for this running service\n");
1047 ok(statusproc
->dwProcessId
== 0,
1048 "Expect no process id for this stopped service\n");
1050 /* same call with null needed pointer */
1051 SetLastError(0xdeadbeef);
1052 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, NULL
);
1053 ok(!ret
, "Expected failure\n");
1054 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* NT4 */ ||
1055 GetLastError() == ERROR_INVALID_ADDRESS
, "got %d\n", GetLastError());
1057 HeapFree(GetProcessHeap(), 0, statusproc
);
1059 CloseServiceHandle(svc_handle
);
1060 CloseServiceHandle(scm_handle
);
1063 static void test_enum_svc(void)
1065 SC_HANDLE scm_handle
;
1067 DWORD bufsize
, needed
, returned
, resume
;
1068 DWORD neededW
, returnedW
;
1069 DWORD tempneeded
, tempreturned
, missing
;
1070 DWORD servicecountactive
, servicecountinactive
;
1071 ENUM_SERVICE_STATUSA
*services
;
1072 ENUM_SERVICE_STATUSW
*servicesW
;
1073 ENUM_SERVICE_STATUS_PROCESSA
*exservices
;
1076 /* All NULL or wrong */
1077 SetLastError(0xdeadbeef);
1078 ret
= EnumServicesStatusA(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1079 ok(!ret
, "Expected failure\n");
1080 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1081 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1083 SetLastError(0xdeadbeef);
1084 ret
= EnumServicesStatusW(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1085 ok(!ret
, "Expected failure\n");
1086 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1087 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1089 /* Open the service control manager with not enough rights at first */
1090 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1092 /* Valid handle but rest is still NULL or wrong */
1093 SetLastError(0xdeadbeef);
1094 ret
= EnumServicesStatusA(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1095 ok(!ret
, "Expected failure\n");
1096 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1097 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1098 "Unexpected last error %d\n", GetLastError());
1100 SetLastError(0xdeadbeef);
1101 ret
= EnumServicesStatusW(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1102 ok(!ret
, "Expected failure\n");
1103 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1104 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1105 "Unexpected last error %d\n", GetLastError());
1107 /* Don't specify the two required pointers */
1108 returned
= 0xdeadbeef;
1109 SetLastError(0xdeadbeef);
1110 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, NULL
, &returned
, NULL
);
1111 ok(!ret
, "Expected failure\n");
1112 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1113 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1114 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1115 "Unexpected last error %d\n", GetLastError());
1117 returned
= 0xdeadbeef;
1118 SetLastError(0xdeadbeef);
1119 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, NULL
, &returned
, NULL
);
1120 ok(!ret
, "Expected failure\n");
1121 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1122 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1123 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1124 "Unexpected last error %d\n", GetLastError());
1126 /* Don't specify the two required pointers */
1127 needed
= 0xdeadbeef;
1128 SetLastError(0xdeadbeef);
1129 ret
= EnumServicesStatusA(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 needed
= 0xdeadbeef;
1138 SetLastError(0xdeadbeef);
1139 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, &needed
, NULL
, NULL
);
1140 ok(!ret
, "Expected failure\n");
1141 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1142 "Expected no change to the needed buffer variable\n");
1143 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1144 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1145 "Unexpected last error %d\n", GetLastError());
1147 /* No valid servicetype and servicestate */
1148 needed
= 0xdeadbeef;
1149 returned
= 0xdeadbeef;
1150 SetLastError(0xdeadbeef);
1151 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, &needed
, &returned
, NULL
);
1152 ok(!ret
, "Expected failure\n");
1153 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1154 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1155 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1156 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1157 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1159 needed
= 0xdeadbeef;
1160 returned
= 0xdeadbeef;
1161 SetLastError(0xdeadbeef);
1162 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, &needed
, &returned
, NULL
);
1163 ok(!ret
, "Expected failure\n");
1164 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1165 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1166 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1167 "Expected number of services to be set to 0, got %d\n", returned
);
1168 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1169 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1171 /* No valid servicestate */
1172 needed
= 0xdeadbeef;
1173 returned
= 0xdeadbeef;
1174 SetLastError(0xdeadbeef);
1175 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, 0, NULL
, 0, &needed
, &returned
, NULL
);
1176 ok(!ret
, "Expected failure\n");
1177 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1178 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1179 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1180 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1181 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1183 needed
= 0xdeadbeef;
1184 returned
= 0xdeadbeef;
1185 SetLastError(0xdeadbeef);
1186 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, 0, NULL
, 0, &needed
, &returned
, NULL
);
1187 ok(!ret
, "Expected failure\n");
1188 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1189 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1190 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1191 "Expected number of services to be set to 0, got %d\n", returned
);
1192 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1193 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1195 /* No valid servicetype */
1196 needed
= 0xdeadbeef;
1197 returned
= 0xdeadbeef;
1198 SetLastError(0xdeadbeef);
1199 ret
= EnumServicesStatusA(scm_handle
, 0, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1200 ok(!ret
, "Expected failure\n");
1201 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1202 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1203 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1204 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1205 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1207 needed
= 0xdeadbeef;
1208 returned
= 0xdeadbeef;
1209 SetLastError(0xdeadbeef);
1210 ret
= EnumServicesStatusW(scm_handle
, 0, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1211 ok(!ret
, "Expected failure\n");
1212 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1213 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1214 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1215 "Expected number of services to be set to 0, got %d\n", returned
);
1216 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1217 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1219 /* All parameters are correct but our access rights are wrong */
1220 needed
= 0xdeadbeef;
1221 returned
= 0xdeadbeef;
1222 SetLastError(0xdeadbeef);
1223 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1224 ok(!ret
, "Expected failure\n");
1225 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1226 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1227 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1228 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1229 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1231 needed
= 0xdeadbeef;
1232 returned
= 0xdeadbeef;
1233 SetLastError(0xdeadbeef);
1234 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1235 ok(!ret
, "Expected failure\n");
1236 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1237 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1238 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1239 "Expected number of services to be set to 0, got %d\n", returned
);
1240 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1241 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1243 /* Open the service control manager with the needed rights */
1244 CloseServiceHandle(scm_handle
);
1245 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1247 /* All parameters are correct. Request the needed buffer size */
1248 needed
= 0xdeadbeef;
1249 returned
= 0xdeadbeef;
1250 SetLastError(0xdeadbeef);
1251 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1252 ok(!ret
, "Expected failure\n");
1253 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1254 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1255 ok(GetLastError() == ERROR_MORE_DATA
,
1256 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1258 /* Test to show we get the same needed buffer size for the W-call */
1259 neededW
= 0xdeadbeef;
1260 returnedW
= 0xdeadbeef;
1261 SetLastError(0xdeadbeef);
1262 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &neededW
, &returnedW
, NULL
);
1263 ok(!ret
, "Expected failure\n");
1264 ok(neededW
!= 0xdeadbeef && neededW
> 0, "Expected the needed buffer size for this one service\n");
1265 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1266 ok(returnedW
== 0, "Expected no service returned, got %d\n", returnedW
);
1267 ok(GetLastError() == ERROR_MORE_DATA
,
1268 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1270 /* Store the needed bytes */
1271 tempneeded
= needed
;
1273 /* Allocate the correct needed bytes */
1274 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1276 needed
= 0xdeadbeef;
1277 returned
= 0xdeadbeef;
1278 SetLastError(0xdeadbeef);
1279 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1280 services
, bufsize
, &needed
, &returned
, NULL
);
1281 ok(ret
, "Expected success, got error %u\n", GetLastError());
1282 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1283 ok(returned
!= 0xdeadbeef && returned
> 0, "Expected some returned services\n");
1284 HeapFree(GetProcessHeap(), 0, services
);
1286 /* Store the number of returned services */
1287 tempreturned
= returned
;
1289 servicesW
= HeapAlloc(GetProcessHeap(), 0, neededW
);
1291 neededW
= 0xdeadbeef;
1292 returnedW
= 0xdeadbeef;
1293 SetLastError(0xdeadbeef);
1294 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1295 servicesW
, bufsize
, &neededW
, &returnedW
, NULL
);
1296 ok(ret
, "Expected success, got error %u\n", GetLastError());
1297 ok(neededW
== 0, "Expected needed buffer to be 0 as we are done\n");
1298 ok(returnedW
!= 0xdeadbeef && returnedW
> 0, "Expected some returned services\n");
1299 HeapFree(GetProcessHeap(), 0, servicesW
);
1301 /* Allocate less than the needed bytes and don't specify a resume handle */
1302 services
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1303 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1304 needed
= 0xdeadbeef;
1305 returned
= 0xdeadbeef;
1306 SetLastError(0xdeadbeef);
1307 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1308 services
, bufsize
, &needed
, &returned
, NULL
);
1309 ok(!ret
, "Expected failure\n");
1310 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1311 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1312 ok(GetLastError() == ERROR_MORE_DATA
,
1313 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1315 /* Allocate less than the needed bytes, this time with a correct resume handle */
1316 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1317 needed
= 0xdeadbeef;
1318 returned
= 0xdeadbeef;
1320 SetLastError(0xdeadbeef);
1321 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1322 services
, bufsize
, &needed
, &returned
, &resume
);
1323 ok(!ret
, "Expected failure\n");
1324 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1325 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1326 todo_wine
ok(resume
, "Expected a resume handle\n");
1327 ok(GetLastError() == ERROR_MORE_DATA
,
1328 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1330 /* Fetch the missing services but pass a bigger buffer size */
1331 missing
= tempreturned
- returned
;
1332 bufsize
= tempneeded
;
1333 needed
= 0xdeadbeef;
1334 returned
= 0xdeadbeef;
1335 SetLastError(0xdeadbeef);
1336 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1337 services
, bufsize
, &needed
, &returned
, &resume
);
1338 ok(ret
, "Expected success, got error %u\n", GetLastError());
1339 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1340 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1341 ok(resume
== 0, "Expected the resume handle to be 0\n");
1342 HeapFree(GetProcessHeap(), 0, services
);
1344 /* See if things add up */
1346 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1347 * and doesn't count the others as inactive. This means that Vista could
1348 * show a total that is greater than the sum of active and inactive
1350 * The number of active and inactive drivers is greatly influenced by the
1351 * time when tests are run, immediately after boot or later for example.
1353 * Both reasons make calculations for drivers not so useful
1356 /* Get the number of active win32 services */
1357 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, NULL
, 0,
1358 &needed
, &returned
, NULL
);
1359 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1360 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, services
,
1361 needed
, &needed
, &returned
, NULL
);
1362 HeapFree(GetProcessHeap(), 0, services
);
1364 servicecountactive
= returned
;
1366 /* Get the number of inactive win32 services */
1367 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, NULL
, 0,
1368 &needed
, &returned
, NULL
);
1369 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1370 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, services
,
1371 needed
, &needed
, &returned
, NULL
);
1372 HeapFree(GetProcessHeap(), 0, services
);
1374 servicecountinactive
= returned
;
1376 /* Get the number of win32 services */
1377 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0,
1378 &needed
, &returned
, NULL
);
1379 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1380 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, services
,
1381 needed
, &needed
, &returned
, NULL
);
1382 HeapFree(GetProcessHeap(), 0, services
);
1384 /* Check if total is the same as active and inactive win32 services */
1385 ok(returned
== (servicecountactive
+ servicecountinactive
),
1386 "Something wrong in the calculation\n");
1388 /* Get all drivers and services
1390 * Fetch the status of the last call as failing could make the following tests crash
1391 * on Wine (we don't return anything yet).
1393 EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1394 NULL
, 0, &needed
, &returned
, NULL
);
1395 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1396 ret
= EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1397 services
, needed
, &needed
, &returned
, NULL
);
1399 /* Loop through all those returned drivers and services */
1400 for (i
= 0; ret
&& i
< returned
; i
++)
1402 SERVICE_STATUS status
= services
[i
].ServiceStatus
;
1404 /* lpServiceName and lpDisplayName should always be filled */
1405 ok(services
[i
].lpServiceName
[0], "Expected a service name\n");
1406 ok(services
[i
].lpDisplayName
&& services
[i
].lpDisplayName
[0], "Expected a display name\n");
1408 /* Decrement the counters to see if the functions calls return the same
1409 * numbers as the contents of these structures.
1411 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1413 if (status
.dwCurrentState
== SERVICE_STOPPED
)
1414 servicecountinactive
--;
1416 servicecountactive
--;
1419 HeapFree(GetProcessHeap(), 0, services
);
1421 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1422 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1424 CloseServiceHandle(scm_handle
);
1426 /* More or less the same for EnumServicesStatusExA */
1427 if (!pEnumServicesStatusExA
)
1429 win_skip( "EnumServicesStatusExA not available\n" );
1433 /* All NULL or wrong */
1434 SetLastError(0xdeadbeef);
1435 ret
= pEnumServicesStatusExA(NULL
, 1, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1436 ok(!ret
, "Expected failure\n");
1437 ok(GetLastError() == ERROR_INVALID_LEVEL
,
1438 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1440 /* All NULL or wrong, just the info level is correct */
1441 SetLastError(0xdeadbeef);
1442 ret
= pEnumServicesStatusExA(NULL
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1443 ok(!ret
, "Expected failure\n");
1444 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1445 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1447 /* Open the service control manager with not enough rights at first */
1448 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1450 /* Valid handle and info level but rest is still NULL or wrong */
1451 SetLastError(0xdeadbeef);
1452 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1453 ok(!ret
, "Expected failure\n");
1454 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1455 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1456 "Unexpected last error %d\n", GetLastError());
1458 /* Don't specify the two required pointers */
1459 needed
= 0xdeadbeef;
1460 SetLastError(0xdeadbeef);
1461 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, NULL
, NULL
, NULL
);
1462 ok(!ret
, "Expected failure\n");
1463 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1464 "Expected no change to the needed buffer variable\n");
1465 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1466 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1467 "Unexpected last error %d\n", GetLastError());
1469 /* Don't specify the two required pointers */
1470 returned
= 0xdeadbeef;
1471 SetLastError(0xdeadbeef);
1472 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, &returned
, NULL
, NULL
);
1473 ok(!ret
, "Expected failure\n");
1474 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1475 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1476 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1477 "Unexpected last error %d\n", GetLastError());
1479 /* No valid servicetype and servicestate */
1480 needed
= 0xdeadbeef;
1481 returned
= 0xdeadbeef;
1482 SetLastError(0xdeadbeef);
1483 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1484 ok(!ret
, "Expected failure\n");
1485 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1486 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1487 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1488 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1489 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1491 /* No valid servicestate */
1492 needed
= 0xdeadbeef;
1493 returned
= 0xdeadbeef;
1494 SetLastError(0xdeadbeef);
1495 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, 0, NULL
, 0,
1496 &needed
, &returned
, NULL
, NULL
);
1497 ok(!ret
, "Expected failure\n");
1498 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1499 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1500 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1501 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1502 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1504 /* No valid servicetype */
1505 needed
= 0xdeadbeef;
1506 returned
= 0xdeadbeef;
1507 SetLastError(0xdeadbeef);
1508 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, SERVICE_STATE_ALL
, NULL
, 0,
1509 &needed
, &returned
, NULL
, NULL
);
1510 ok(!ret
, "Expected failure\n");
1511 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1512 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1513 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1514 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1515 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1517 /* No valid servicetype and servicestate and unknown service group */
1518 needed
= 0xdeadbeef;
1519 returned
= 0xdeadbeef;
1520 SetLastError(0xdeadbeef);
1521 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
,
1522 &returned
, NULL
, "deadbeef_group");
1523 ok(!ret
, "Expected failure\n");
1524 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1525 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1526 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1527 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1528 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1530 /* All parameters are correct but our access rights are wrong */
1531 needed
= 0xdeadbeef;
1532 returned
= 0xdeadbeef;
1533 SetLastError(0xdeadbeef);
1534 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1535 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1536 ok(!ret
, "Expected failure\n");
1537 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1538 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1539 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1540 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1541 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1543 /* All parameters are correct, access rights are wrong but the
1544 * group name won't be checked yet.
1546 needed
= 0xdeadbeef;
1547 returned
= 0xdeadbeef;
1548 SetLastError(0xdeadbeef);
1549 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1550 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1551 ok(!ret
, "Expected failure\n");
1552 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1553 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1554 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1555 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1556 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1558 /* Open the service control manager with the needed rights */
1559 CloseServiceHandle(scm_handle
);
1560 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1562 /* All parameters are correct and the group will be checked */
1563 needed
= 0xdeadbeef;
1564 returned
= 0xdeadbeef;
1565 SetLastError(0xdeadbeef);
1566 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1567 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1568 ok(!ret
, "Expected failure\n");
1569 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1570 ok(needed
== 0, "Expected needed buffer size to be set to 0, got %d\n", needed
);
1571 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
1572 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1574 /* TODO: Create a test that makes sure we enumerate all services that don't
1575 * belong to a group. (specifying "").
1578 /* All parameters are correct. Request the needed buffer size */
1579 needed
= 0xdeadbeef;
1580 returned
= 0xdeadbeef;
1581 SetLastError(0xdeadbeef);
1582 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1583 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1584 ok(!ret
, "Expected failure\n");
1585 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1586 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1587 ok(GetLastError() == ERROR_MORE_DATA
,
1588 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1590 /* Test to show we get the same needed buffer size for the W-call */
1591 neededW
= 0xdeadbeef;
1592 ret
= pEnumServicesStatusExW(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1593 NULL
, 0, &neededW
, &returnedW
, NULL
, NULL
);
1594 ok(!ret
, "Expected failure\n");
1595 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1597 /* Store the needed bytes */
1598 tempneeded
= needed
;
1600 /* Allocate the correct needed bytes */
1601 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1603 needed
= 0xdeadbeef;
1604 returned
= 0xdeadbeef;
1605 SetLastError(0xdeadbeef);
1606 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1607 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1608 ok(ret
, "Expected success, got error %u\n", GetLastError());
1609 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1610 ok(returned
== tempreturned
, "Expected the same number of service from this function\n");
1611 HeapFree(GetProcessHeap(), 0, exservices
);
1613 /* Store the number of returned services */
1614 tempreturned
= returned
;
1616 /* Allocate less than the needed bytes and don't specify a resume handle */
1617 exservices
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1618 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1619 needed
= 0xdeadbeef;
1620 returned
= 0xdeadbeef;
1621 SetLastError(0xdeadbeef);
1622 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1623 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1624 ok(!ret
, "Expected failure\n");
1625 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1626 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1627 ok(GetLastError() == ERROR_MORE_DATA
,
1628 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1630 /* Allocate less than the needed bytes, this time with a correct resume handle */
1631 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1632 needed
= 0xdeadbeef;
1633 returned
= 0xdeadbeef;
1635 SetLastError(0xdeadbeef);
1636 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1637 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1638 ok(!ret
, "Expected failure\n");
1639 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1640 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1641 todo_wine
ok(resume
, "Expected a resume handle\n");
1642 ok(GetLastError() == ERROR_MORE_DATA
,
1643 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1645 /* Fetch that last service but pass a bigger buffer size */
1646 missing
= tempreturned
- returned
;
1647 bufsize
= tempneeded
;
1648 needed
= 0xdeadbeef;
1649 returned
= 0xdeadbeef;
1650 SetLastError(0xdeadbeef);
1651 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1652 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1653 ok(ret
, "Expected success, got error %u\n", GetLastError());
1654 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1655 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1656 ok(resume
== 0, "Expected the resume handle to be 0\n");
1657 HeapFree(GetProcessHeap(), 0, exservices
);
1659 /* See if things add up */
1661 /* Get the number of active win32 services */
1662 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1663 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1664 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1665 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1666 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1667 HeapFree(GetProcessHeap(), 0, exservices
);
1669 servicecountactive
= returned
;
1671 /* Get the number of inactive win32 services */
1672 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1673 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1674 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1675 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1676 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1677 HeapFree(GetProcessHeap(), 0, exservices
);
1679 servicecountinactive
= returned
;
1681 /* Get the number of win32 services */
1682 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1683 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1684 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1685 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1686 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1687 HeapFree(GetProcessHeap(), 0, exservices
);
1689 /* Check if total is the same as active and inactive win32 services */
1690 ok(returned
== (servicecountactive
+ servicecountinactive
),
1691 "Something wrong in the calculation\n");
1693 /* Get all drivers and services */
1694 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1695 SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1696 ok(!ret
, "Expected failure\n");
1697 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1698 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1699 SERVICE_STATE_ALL
, (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1700 ok(ret
, "Expected success %u\n", GetLastError());
1702 /* Loop through all those returned drivers and services */
1703 for (i
= 0; i
< returned
; i
++)
1705 SERVICE_STATUS_PROCESS status
= exservices
[i
].ServiceStatusProcess
;
1707 /* lpServiceName and lpDisplayName should always be filled */
1708 ok(exservices
[i
].lpServiceName
[0], "Expected a service name\n");
1709 ok(exservices
[i
].lpDisplayName
&& exservices
[i
].lpDisplayName
[0], "Expected a display name\n");
1711 /* Decrement the counters to see if the functions calls return the
1712 * same numbers as the contents of these structures.
1713 * Check some process id specifics.
1715 if (status
.dwServiceType
& (SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_KERNEL_DRIVER
))
1717 /* We shouldn't have a process id for drivers */
1718 ok(status
.dwProcessId
== 0,
1719 "This driver shouldn't have an associated process id\n");
1722 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1724 if (status
.dwCurrentState
!= SERVICE_STOPPED
)
1726 /* We expect a process id for every running service */
1727 ok(status
.dwProcessId
> 0, "Expected a process id for this running service (%s)\n",
1728 exservices
[i
].lpServiceName
);
1730 servicecountactive
--;
1734 /* We shouldn't have a process id for inactive services */
1735 ok(status
.dwProcessId
== 0, "Service %s state %u shouldn't have an associated process id\n",
1736 exservices
[i
].lpServiceName
, status
.dwCurrentState
);
1738 servicecountinactive
--;
1742 HeapFree(GetProcessHeap(), 0, exservices
);
1744 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1745 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1747 CloseServiceHandle(scm_handle
);
1750 static void test_close(void)
1756 SetLastError(0xdeadbeef);
1757 ret
= CloseServiceHandle(NULL
);
1758 ok(!ret
, "Expected failure\n");
1759 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1761 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1764 handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1765 SetLastError(0xdeadbeef);
1766 ret
= CloseServiceHandle(handle
);
1767 ok(ret
, "Expected success got error %u\n", GetLastError());
1770 static void test_sequence(void)
1772 SC_HANDLE scm_handle
, svc_handle
;
1774 QUERY_SERVICE_CONFIGA
*config
;
1775 DWORD given
, needed
;
1776 static const CHAR servicename
[] = "Winetest";
1777 static const CHAR displayname
[] = "Winetest dummy service";
1778 static const CHAR displayname2
[] = "Winetest dummy service (2)";
1779 static const CHAR pathname
[] = "we_dont_care.exe";
1780 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1781 static const CHAR password
[] = "";
1782 static const CHAR empty
[] = "";
1783 static const CHAR localsystem
[] = "LocalSystem";
1785 SetLastError(0xdeadbeef);
1786 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1788 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1790 skip("Not enough rights to get a handle to the manager\n");
1794 ok(scm_handle
!= NULL
, "Could not get a handle to the manager: %d\n", GetLastError());
1796 if (!scm_handle
) return;
1797 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
1798 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
1799 CloseServiceHandle(svc_handle
);
1801 /* Create a dummy service */
1802 SetLastError(0xdeadbeef);
1803 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1804 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1805 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1807 if (!svc_handle
&& (GetLastError() == ERROR_SERVICE_EXISTS
))
1809 /* We try and open the service and do the rest of the tests. Some could
1810 * fail if the tests were changed between these runs.
1812 trace("Deletion probably didn't work last time\n");
1813 SetLastError(0xdeadbeef);
1814 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
1815 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1817 skip("Not enough rights to open the service\n");
1818 CloseServiceHandle(scm_handle
);
1821 ok(svc_handle
!= NULL
, "Could not open the service : %d\n", GetLastError());
1823 else if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1825 skip("Not enough rights to create the service\n");
1826 CloseServiceHandle(scm_handle
);
1831 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
1832 if ((svc_handle
!= NULL
) && (pGetSecurityInfo
!= NULL
))
1834 PSID sidOwner
, sidGroup
;
1836 PSECURITY_DESCRIPTOR pSD
;
1837 DWORD error
, n1
, n2
;
1841 /* Test using GetSecurityInfo to obtain security information */
1842 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, &sidOwner
,
1843 &sidGroup
, &dacl
, &sacl
, &pSD
);
1845 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1846 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1847 NULL
, NULL
, NULL
, &pSD
);
1849 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1852 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1853 NULL
, &dacl
, NULL
, &pSD
);
1854 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1856 SetLastError(0xdeadbeef);
1857 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1858 NULL
, NULL
, NULL
, NULL
);
1859 error
= GetLastError();
1860 ok(retval
== ERROR_INVALID_PARAMETER
, "Expected GetSecurityInfo to fail: result %d\n", retval
);
1861 ok(error
== 0xdeadbeef, "Unexpected last error %d\n", error
);
1864 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1866 /* Test using QueryServiceObjectSecurity to obtain security information */
1867 SetLastError(0xdeadbeef);
1868 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, NULL
, 0, &n1
);
1869 error
= GetLastError();
1870 ok(!bret
, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret
);
1871 ok(error
== ERROR_INSUFFICIENT_BUFFER
||
1872 broken(error
== ERROR_INVALID_ADDRESS
) || broken(error
== ERROR_INVALID_PARAMETER
),
1873 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error
);
1874 if (error
!= ERROR_INSUFFICIENT_BUFFER
) n1
= 1024;
1875 pSD
= LocalAlloc(0, n1
);
1876 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, pSD
, n1
, &n2
);
1877 ok(bret
, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret
);
1883 CloseServiceHandle(scm_handle
);
1888 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1889 * that the correct keys are used.
1892 /* Request the size for the buffer */
1893 SetLastError(0xdeadbeef);
1894 ret
= QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1895 ok(!ret
, "Expected failure\n");
1896 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1898 config
= HeapAlloc(GetProcessHeap(), 0, needed
);
1900 SetLastError(0xdeadbeef);
1901 ret
= QueryServiceConfigA(svc_handle
, config
, given
, &needed
);
1902 ok(ret
, "Expected success, got error %u\n", GetLastError());
1904 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1905 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1906 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1907 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1908 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1909 ok(config
->dwErrorControl
== SERVICE_ERROR_IGNORE
, "Expected SERVICE_ERROR_IGNORE, got %d\n", config
->dwErrorControl
);
1910 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1911 ok(!strcmp(config
->lpLoadOrderGroup
, empty
), "Expected an empty string, got '%s'\n", config
->lpLoadOrderGroup
);
1912 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1913 /* TODO: Show the double 0 terminated string */
1916 ok(!memcmp(config
->lpDependencies
, dependencies
, sizeof(dependencies
)), "Wrong string\n");
1918 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1919 ok(!strcmp(config
->lpDisplayName
, displayname
), "Expected '%s', got '%s'\n", displayname
, config
->lpDisplayName
);
1921 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_ERROR_NORMAL
, NULL
, "TestGroup2",
1922 NULL
, NULL
, NULL
, NULL
, displayname2
);
1923 ok(ret
, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
1925 QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1926 config
= HeapReAlloc(GetProcessHeap(), 0, config
, needed
);
1927 ok(QueryServiceConfigA(svc_handle
, config
, needed
, &needed
), "QueryServiceConfig failed\n");
1928 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1929 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1930 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1931 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1932 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1933 ok(config
->dwErrorControl
== SERVICE_ERROR_NORMAL
, "Expected SERVICE_ERROR_NORMAL, got %d\n", config
->dwErrorControl
);
1934 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1935 ok(!strcmp(config
->lpLoadOrderGroup
, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config
->lpLoadOrderGroup
);
1936 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1937 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1938 ok(!strcmp(config
->lpDisplayName
, displayname2
), "Expected '%s', got '%s'\n", displayname2
, config
->lpDisplayName
);
1940 SetLastError(0xdeadbeef);
1941 ret
= DeleteService(svc_handle
);
1942 ok(ret
, "Expected success, got error %u\n", GetLastError());
1943 CloseServiceHandle(svc_handle
);
1945 /* Wait a while. The following test does a CreateService again */
1948 CloseServiceHandle(scm_handle
);
1949 HeapFree(GetProcessHeap(), 0, config
);
1952 static void test_queryconfig2(void)
1954 SC_HANDLE scm_handle
, svc_handle
;
1956 DWORD expected
, needed
;
1957 BYTE buffer
[MAX_PATH
];
1958 LPSERVICE_DESCRIPTIONA pConfig
= (LPSERVICE_DESCRIPTIONA
)buffer
;
1959 LPSERVICE_DESCRIPTIONW pConfigW
= (LPSERVICE_DESCRIPTIONW
)buffer
;
1960 SERVICE_PRESHUTDOWN_INFO preshutdown_info
;
1961 static const CHAR servicename
[] = "Winetest";
1962 static const CHAR displayname
[] = "Winetest dummy service";
1963 static const CHAR pathname
[] = "we_dont_care.exe";
1964 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1965 static const CHAR password
[] = "";
1966 static const CHAR description
[] = "Description";
1967 static const CHAR description_empty
[] = "";
1968 static const WCHAR descriptionW
[] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
1969 static const WCHAR descriptionW_empty
[] = {0};
1971 if(!pQueryServiceConfig2A
)
1973 win_skip("function QueryServiceConfig2A not present\n");
1977 SetLastError(0xdeadbeef);
1978 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1982 if(GetLastError() == ERROR_ACCESS_DENIED
)
1983 skip("Not enough rights to get a handle to the manager\n");
1985 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
1989 /* Create a dummy service */
1990 SetLastError(0xdeadbeef);
1991 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1992 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1993 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1997 if(GetLastError() == ERROR_SERVICE_EXISTS
)
1999 /* We try and open the service and do the rest of the tests. Some could
2000 * fail if the tests were changed between these runs.
2002 trace("Deletion probably didn't work last time\n");
2003 SetLastError(0xdeadbeef);
2004 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2007 if(GetLastError() == ERROR_ACCESS_DENIED
)
2008 skip("Not enough rights to open the service\n");
2010 ok(FALSE
, "Could not open the service : %d\n", GetLastError());
2011 CloseServiceHandle(scm_handle
);
2015 if (GetLastError() == ERROR_ACCESS_DENIED
)
2017 skip("Not enough rights to create the service\n");
2018 CloseServiceHandle(scm_handle
);
2021 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
2024 CloseServiceHandle(scm_handle
);
2028 SetLastError(0xdeadbeef);
2029 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2030 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2031 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2033 SetLastError(0xdeadbeef);
2034 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2035 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2036 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2038 SetLastError(0xdeadbeef);
2039 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2040 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2041 ok(ERROR_INVALID_ADDRESS
== GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2043 SetLastError(0xdeadbeef);
2044 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2045 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2046 ok((ERROR_INVALID_ADDRESS
== GetLastError()) || (ERROR_INSUFFICIENT_BUFFER
== GetLastError()),
2047 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2049 SetLastError(0xdeadbeef);
2050 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2051 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2052 ok(ERROR_INVALID_ADDRESS
== GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2055 SetLastError(0xdeadbeef);
2056 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
)-1,&needed
);
2057 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2058 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2059 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2062 pConfig
->lpDescription
= (LPSTR
)0xdeadbeef;
2063 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2064 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2065 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2066 ok(!pConfig
->lpDescription
, "expected lpDescription to be NULL, got %p\n", pConfig
->lpDescription
);
2068 SetLastError(0xdeadbeef);
2070 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2071 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2072 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2073 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2075 if(!pChangeServiceConfig2A
)
2077 win_skip("function ChangeServiceConfig2A not present\n");
2081 pConfig
->lpDescription
= (LPSTR
) description
;
2082 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
);
2083 ok(ret
, "ChangeServiceConfig2A failed\n");
2088 SetLastError(0xdeadbeef);
2090 expected
= sizeof(SERVICE_DESCRIPTIONA
) + sizeof(description
) * sizeof(WCHAR
); /* !! */
2091 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2092 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2093 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2094 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2096 SetLastError(0xdeadbeef);
2097 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
-1,&needed
);
2098 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2099 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2101 SetLastError(0xdeadbeef);
2102 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
,&needed
);
2103 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2104 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2105 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2107 SetLastError(0xdeadbeef);
2108 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
+ 1,&needed
);
2109 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2110 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2111 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2113 if(!pQueryServiceConfig2W
)
2115 win_skip("function QueryServiceConfig2W not present\n");
2118 SetLastError(0xdeadbeef);
2120 expected
= sizeof(SERVICE_DESCRIPTIONW
) + sizeof(WCHAR
) * sizeof(description
);
2121 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2122 ok(!ret
, "expected QueryServiceConfig2W to fail\n");
2123 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2124 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2126 SetLastError(0xdeadbeef);
2127 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
,&needed
);
2128 ok(ret
, "expected QueryServiceConfig2W to succeed\n");
2130 pConfig
->lpDescription
= (LPSTR
)description
;
2131 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2132 ok(ret
, "expected ChangeServiceConfig2A to succeed\n");
2134 pConfig
->lpDescription
= NULL
;
2135 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2136 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2137 ok(pConfig
->lpDescription
&& !strcmp(description
, pConfig
->lpDescription
),
2138 "expected lpDescription to be %s, got %s\n", description
, pConfig
->lpDescription
);
2140 pConfig
->lpDescription
= NULL
;
2141 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2142 ok(ret
, "expected ChangeServiceConfig2A to succeed\n");
2144 pConfig
->lpDescription
= NULL
;
2145 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2146 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2147 ok(pConfig
->lpDescription
&& !strcmp(description
, pConfig
->lpDescription
),
2148 "expected lpDescription to be %s, got %s\n", description
, pConfig
->lpDescription
);
2150 pConfig
->lpDescription
= (LPSTR
)description_empty
;
2151 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2152 ok(ret
, "expected ChangeServiceConfig2A to succeed\n");
2154 pConfig
->lpDescription
= (void*)0xdeadbeef;
2155 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2156 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2157 ok(!pConfig
->lpDescription
,
2158 "expected lpDescription to be null, got %s\n", pConfig
->lpDescription
);
2160 pConfigW
->lpDescription
= (LPWSTR
)descriptionW
;
2161 ret
= pChangeServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2162 ok(ret
, "expected ChangeServiceConfig2W to succeed\n");
2164 pConfigW
->lpDescription
= NULL
;
2165 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2166 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2167 ok(pConfigW
->lpDescription
&& !lstrcmpW(descriptionW
, pConfigW
->lpDescription
),
2168 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW
), wine_dbgstr_w(pConfigW
->lpDescription
));
2170 pConfigW
->lpDescription
= NULL
;
2171 ret
= pChangeServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2172 ok(ret
, "expected ChangeServiceConfig2W to succeed\n");
2174 pConfigW
->lpDescription
= NULL
;
2175 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2176 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2177 ok(pConfigW
->lpDescription
&& !lstrcmpW(descriptionW
, pConfigW
->lpDescription
),
2178 "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW
), wine_dbgstr_w(pConfigW
->lpDescription
));
2180 pConfigW
->lpDescription
= (LPWSTR
)descriptionW_empty
;
2181 ret
= pChangeServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, &buffer
);
2182 ok(ret
, "expected ChangeServiceConfig2W to succeed\n");
2184 pConfigW
->lpDescription
= (void*)0xdeadbeef;
2185 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
, buffer
, sizeof(buffer
), &needed
);
2186 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2187 ok(!pConfigW
->lpDescription
,
2188 "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW
->lpDescription
));
2190 SetLastError(0xdeadbeef);
2191 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2192 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2193 if(!ret
&& GetLastError()==ERROR_INVALID_LEVEL
)
2195 /* Win2k3 and older */
2196 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2199 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2200 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2201 ok(preshutdown_info
.dwPreshutdownTimeout
== 180000, "Default PreshutdownTimeout = %d\n",
2202 preshutdown_info
.dwPreshutdownTimeout
);
2204 SetLastError(0xdeadbeef);
2205 preshutdown_info
.dwPreshutdownTimeout
= -1;
2206 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2207 (LPVOID
)&preshutdown_info
);
2208 ok(ret
, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2210 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2211 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2212 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2213 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2214 ok(preshutdown_info
.dwPreshutdownTimeout
== -1, "New PreshutdownTimeout = %d\n",
2215 preshutdown_info
.dwPreshutdownTimeout
);
2218 DeleteService(svc_handle
);
2220 CloseServiceHandle(svc_handle
);
2222 /* Wait a while. The following test does a CreateService again */
2225 CloseServiceHandle(scm_handle
);
2228 static DWORD
try_start_stop(SC_HANDLE svc_handle
, const char* name
, DWORD is_nt4
)
2232 SERVICE_STATUS status
;
2234 ret
= StartServiceA(svc_handle
, 0, NULL
);
2235 le1
= GetLastError();
2236 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2238 if (pQueryServiceStatusEx
)
2241 SERVICE_STATUS_PROCESS statusproc
;
2243 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&statusproc
, sizeof(statusproc
), &needed
);
2244 ok(ret
, "%s: QueryServiceStatusEx() failed le=%u\n", name
, GetLastError());
2245 ok(statusproc
.dwCurrentState
== SERVICE_STOPPED
, "%s: should be stopped state=%x\n", name
, statusproc
.dwCurrentState
);
2246 ok(statusproc
.dwProcessId
== 0, "%s: ProcessId should be 0 instead of %x\n", name
, statusproc
.dwProcessId
);
2249 ret
= StartServiceA(svc_handle
, 0, NULL
);
2250 le2
= GetLastError();
2251 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2252 ok(le2
== le1
, "%s: the second try should yield the same error: %u != %u\n", name
, le1
, le2
);
2254 status
.dwCurrentState
= 0xdeadbeef;
2255 ret
= ControlService(svc_handle
, SERVICE_CONTROL_STOP
, &status
);
2256 le2
= GetLastError();
2257 ok(!ret
, "%s: ControlService() should have failed\n", name
);
2258 ok(le2
== ERROR_SERVICE_NOT_ACTIVE
, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name
, le2
);
2259 ok(status
.dwCurrentState
== SERVICE_STOPPED
||
2260 broken(is_nt4
), /* NT4 returns a random value */
2261 "%s: should be stopped state=%x\n", name
, status
.dwCurrentState
);
2266 #define PHASE_STOPPED 1
2267 #define PHASE_RUNNING 2
2269 struct notify_data
{
2270 SERVICE_NOTIFYW notify
;
2276 static void CALLBACK
notify_cb(void *user
)
2278 struct notify_data
*data
= user
;
2279 switch (data
->phase
)
2282 ok(data
->notify
.dwNotificationStatus
== ERROR_SUCCESS
,
2283 "Got wrong notification status: %u\n", data
->notify
.dwNotificationStatus
);
2284 ok(data
->notify
.ServiceStatus
.dwCurrentState
== SERVICE_STOPPED
,
2285 "Got wrong service state: 0x%x\n", data
->notify
.ServiceStatus
.dwCurrentState
);
2286 ok(data
->notify
.dwNotificationTriggered
== SERVICE_NOTIFY_STOPPED
,
2287 "Got wrong notification triggered: 0x%x\n", data
->notify
.dwNotificationTriggered
);
2291 ok(data
->notify
.dwNotificationStatus
== ERROR_SUCCESS
,
2292 "Got wrong notification status: %u\n", data
->notify
.dwNotificationStatus
);
2293 ok(data
->notify
.ServiceStatus
.dwCurrentState
== SERVICE_RUNNING
,
2294 "Got wrong service state: 0x%x\n", data
->notify
.ServiceStatus
.dwCurrentState
);
2295 ok(data
->notify
.dwNotificationTriggered
== SERVICE_NOTIFY_RUNNING
,
2296 "Got wrong notification triggered: 0x%x\n", data
->notify
.dwNotificationTriggered
);
2300 data
->was_called
= TRUE
;
2303 static void test_servicenotify(SC_HANDLE scm_handle
, const char *servicename
)
2306 struct notify_data data
;
2307 struct notify_data data2
;
2309 SERVICE_STATUS status
;
2312 if(!pNotifyServiceStatusChangeW
){
2313 win_skip("No NotifyServiceStatusChangeW\n");
2317 svc
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2318 svc2
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2319 ok(svc
!= NULL
&& svc2
!= NULL
, "Failed to open service\n");
2323 /* receive stopped notification, then start service */
2324 memset(&data
.notify
, 0, sizeof(data
.notify
));
2325 data
.notify
.dwVersion
= SERVICE_NOTIFY_STATUS_CHANGE
;
2326 data
.notify
.pfnNotifyCallback
= ¬ify_cb
;
2327 data
.notify
.pContext
= &data
;
2329 data
.phase
= PHASE_STOPPED
;
2330 data
.was_called
= FALSE
;
2332 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2333 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2335 dr
= SleepEx(100, TRUE
);
2336 ok(dr
== WAIT_IO_COMPLETION
, "Got wrong SleepEx result: %u\n", dr
);
2337 ok(data
.was_called
== TRUE
, "APC wasn't called\n");
2339 br
= StartServiceA(svc
, 0, NULL
);
2340 ok(br
, "StartService failed: %u\n", GetLastError());
2342 /* receive running notification */
2343 data
.phase
= PHASE_RUNNING
;
2344 data
.was_called
= FALSE
;
2346 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2347 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2349 dr
= SleepEx(100, TRUE
);
2350 ok(dr
== WAIT_IO_COMPLETION
, "Got wrong SleepEx result: %u\n", dr
);
2351 ok(data
.was_called
== TRUE
, "APC wasn't called\n");
2353 /* cannot register two notifications on the same handle */
2354 data
.phase
= PHASE_STOPPED
;
2355 data
.was_called
= FALSE
;
2357 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2358 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2360 memset(&data2
.notify
, 0, sizeof(data2
.notify
));
2361 data2
.notify
.dwVersion
= SERVICE_NOTIFY_STATUS_CHANGE
;
2362 data2
.notify
.pfnNotifyCallback
= ¬ify_cb
;
2363 data2
.notify
.pContext
= &data2
;
2365 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data2
.notify
);
2366 ok(dr
== ERROR_SUCCESS
|| /* win8+ */
2367 dr
== ERROR_ALREADY_REGISTERED
, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr
);
2369 /* should receive no notification because status has not changed.
2370 * on win8+, SleepEx quits early but the callback is still not invoked. */
2371 dr2
= SleepEx(100, TRUE
);
2372 ok((dr
== ERROR_SUCCESS
&& dr2
== WAIT_IO_COMPLETION
) || /* win8+ */
2373 (dr
== ERROR_ALREADY_REGISTERED
&& dr2
== 0), "Got wrong SleepEx result: %u\n", dr
);
2374 ok(data
.was_called
== FALSE
, "APC should not have been called\n");
2376 memset(&data2
.notify
, 0, sizeof(data2
.notify
));
2377 data2
.notify
.dwVersion
= SERVICE_NOTIFY_STATUS_CHANGE
;
2378 data2
.notify
.pfnNotifyCallback
= ¬ify_cb
;
2379 data2
.notify
.pContext
= &data
;
2381 data2
.phase
= PHASE_STOPPED
;
2382 data2
.was_called
= FALSE
;
2384 /* it's possible to have multiple notifications using different service handles */
2385 dr
= pNotifyServiceStatusChangeW(svc2
, SERVICE_NOTIFY_STOPPED
, &data2
.notify
);
2386 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr
);
2388 /* stop service and receive notifiction */
2389 br
= ControlService(svc
, SERVICE_CONTROL_STOP
, &status
);
2390 ok(br
, "ControlService failed: %u\n", GetLastError());
2392 dr
= SleepEx(100, TRUE
);
2393 dr2
= SleepEx(100, TRUE
);
2394 ok(dr
== WAIT_IO_COMPLETION
|| dr2
== WAIT_IO_COMPLETION
, "Got wrong SleepEx result: %u\n", dr
);
2395 ok(data
.was_called
== TRUE
, "APC wasn't called\n");
2396 ok(data2
.was_called
== TRUE
, "APC wasn't called\n");
2398 /* test cancelation: create notify on svc that will block until service
2399 * start; close svc; start service on svc2; verify that notification does
2402 data
.phase
= PHASE_RUNNING
;
2403 data
.was_called
= FALSE
;
2404 dr
= pNotifyServiceStatusChangeW(svc
, SERVICE_NOTIFY_STOPPED
| SERVICE_NOTIFY_RUNNING
, &data
.notify
);
2405 ok(dr
== ERROR_SUCCESS
, "NotifyServiceStatusChangeW failed: %u\n", dr
);
2407 CloseServiceHandle(svc
);
2409 br
= StartServiceA(svc2
, 0, NULL
);
2410 ok(br
, "StartService failed: %u\n", GetLastError());
2412 dr
= SleepEx(100, TRUE
);
2413 ok(dr
== 0, "Got wrong SleepEx result: %u\n", dr
);
2414 ok(data
.was_called
== FALSE
, "APC should not have been called\n");
2416 br
= ControlService(svc2
, SERVICE_CONTROL_STOP
, &status
);
2417 ok(br
, "ControlService failed: %u\n", GetLastError());
2419 CloseServiceHandle(svc2
);
2422 static void test_start_stop(void)
2425 SC_HANDLE scm_handle
, svc_handle
;
2427 static const char servicename
[] = "Winetest";
2428 char cmd
[MAX_PATH
+20];
2429 const char* displayname
;
2431 SetLastError(0xdeadbeef);
2432 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2435 if(GetLastError() == ERROR_ACCESS_DENIED
)
2436 skip("Not enough rights to get a handle to the manager\n");
2438 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
2443 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
2444 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
2446 /* Do some cleanup in case a previous run crashed */
2447 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2450 DeleteService(svc_handle
);
2451 CloseServiceHandle(svc_handle
);
2454 /* Create a dummy disabled service */
2455 sprintf(cmd
, "\"%s\" service exit", selfname
);
2456 displayname
= "Winetest Disabled Service";
2457 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
,
2458 GENERIC_ALL
, SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
,
2459 SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
, cmd
, NULL
,
2460 NULL
, NULL
, NULL
, NULL
);
2463 if(GetLastError() == ERROR_ACCESS_DENIED
)
2464 skip("Not enough rights to create the service\n");
2466 ok(FALSE
, "Could not create the service: %d\n", GetLastError());
2469 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2470 ok(le
== ERROR_SERVICE_DISABLED
, "%d != ERROR_SERVICE_DISABLED\n", le
);
2472 /* Then one with a bad path */
2473 displayname
= "Winetest Bad Path";
2474 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_DEMAND_START
, SERVICE_NO_CHANGE
, "c:\\no_such_file.exe", NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2475 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2476 try_start_stop(svc_handle
, displayname
, is_nt4
);
2480 /* NT4 does not detect when a service fails to start and uses an
2481 * insanely long timeout: 120s. So skip the rest of the tests.
2483 win_skip("Skip some service start/stop tests on NT4\n");
2487 /* Again with a process that exits right away */
2488 displayname
= "Winetest Exit Service";
2489 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2490 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2491 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2492 ok(le
== ERROR_SERVICE_REQUEST_TIMEOUT
, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le
);
2494 /* create a real service and test notifications */
2495 sprintf(cmd
, "%s service serve", selfname
);
2496 displayname
= "Winetest Service";
2497 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2498 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2499 test_servicenotify(scm_handle
, servicename
);
2504 DeleteService(svc_handle
);
2505 CloseServiceHandle(svc_handle
);
2508 /* Wait a while. The following test does a CreateService again */
2511 CloseServiceHandle(scm_handle
);
2514 static void test_refcount(void)
2516 SC_HANDLE scm_handle
, svc_handle1
, svc_handle2
, svc_handle3
, svc_handle4
, svc_handle5
;
2517 static const CHAR servicename
[] = "Winetest";
2518 static const CHAR pathname
[] = "we_dont_care.exe";
2521 /* Get a handle to the Service Control Manager */
2522 SetLastError(0xdeadbeef);
2523 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2524 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
2526 skip("Not enough rights to get a handle to the manager\n");
2530 /* Create a service */
2531 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2532 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2533 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2534 ok(svc_handle1
!= NULL
, "Expected success, got error %u\n", GetLastError());
2536 /* Get a handle to this new service */
2537 svc_handle2
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2538 ok(svc_handle2
!= NULL
, "Expected success, got error %u\n", GetLastError());
2540 /* Get another handle to this new service */
2541 svc_handle3
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2542 ok(svc_handle3
!= NULL
, "Expected success, got error %u\n", GetLastError());
2544 /* Check if we can close the handle to the Service Control Manager */
2545 ret
= CloseServiceHandle(scm_handle
);
2546 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2548 /* Get a new handle to the Service Control Manager */
2549 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2550 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
2552 /* Get a handle to this new service */
2553 svc_handle4
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2554 ok(svc_handle4
!= NULL
, "Expected success, got error %u\n", GetLastError());
2556 /* Delete the service */
2557 ret
= DeleteService(svc_handle4
);
2558 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2560 /* We cannot create the same service again as it's still marked as 'being deleted'.
2561 * The reason is that we still have 4 open handles to this service even though we
2562 * closed the handle to the Service Control Manager in between.
2564 SetLastError(0xdeadbeef);
2565 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2566 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2567 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2568 ok(!svc_handle5
, "Expected failure\n");
2569 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE
,
2570 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2572 /* Close all the handles to the service and try again */
2573 ret
= CloseServiceHandle(svc_handle4
);
2574 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2575 ret
= CloseServiceHandle(svc_handle3
);
2576 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2577 ret
= CloseServiceHandle(svc_handle2
);
2578 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2579 ret
= CloseServiceHandle(svc_handle1
);
2580 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2582 /* Wait a while. Doing a CreateService too soon will result again
2583 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2587 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2588 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2589 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2590 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2591 ok(svc_handle5
!= NULL
, "Expected success, got error %u\n", GetLastError());
2593 /* Delete the service */
2594 ret
= DeleteService(svc_handle5
);
2595 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2597 /* Wait a while. Just in case one of the following tests does a CreateService again */
2600 CloseServiceHandle(svc_handle5
);
2601 CloseServiceHandle(scm_handle
);
2604 static DWORD WINAPI
ctrl_handler(DWORD ctl
, DWORD type
, void *data
, void *user
)
2609 case SERVICE_CONTROL_STOP
:
2612 case SERVICE_CONTROL_INTERROGATE
:
2616 return ERROR_CALL_NOT_IMPLEMENTED
;
2619 static void WINAPI
service_main(DWORD argc
, char **argv
)
2621 SERVICE_STATUS_HANDLE st_handle
;
2623 HANDLE evt
= CreateEventW(0, FALSE
, FALSE
, 0);
2625 st_handle
= RegisterServiceCtrlHandlerExA("", &ctrl_handler
, evt
);
2627 st
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2628 st
.dwServiceSpecificExitCode
= 0;
2629 st
.dwCurrentState
= SERVICE_RUNNING
;
2630 st
.dwWin32ExitCode
= NO_ERROR
;
2632 st
.dwControlsAccepted
= SERVICE_ACCEPT_STOP
;
2633 st
.dwCheckPoint
= 0;
2635 SetServiceStatus(st_handle
, &st
);
2637 WaitForSingleObject(evt
, 5000);
2639 st
.dwCurrentState
= SERVICE_STOPPED
;
2641 SetServiceStatus(st_handle
, &st
);
2644 static void run_service(void)
2647 SERVICE_TABLE_ENTRYA table
[] = {
2648 {empty
, &service_main
},
2652 StartServiceCtrlDispatcherA(table
);
2657 SC_HANDLE scm_handle
;
2661 myARGC
= winetest_get_mainargs(&myARGV
);
2662 GetFullPathNameA(myARGV
[0], sizeof(selfname
), selfname
, NULL
);
2665 if (strcmp(myARGV
[2], "serve") == 0)
2670 /* Bail out if we are on win98 */
2671 SetLastError(0xdeadbeef);
2672 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2674 if (!scm_handle
&& (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
))
2676 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2679 CloseServiceHandle(scm_handle
);
2681 init_function_pointers();
2683 /* First some parameter checking */
2686 test_create_delete_svc();
2687 test_get_displayname();
2688 test_get_servicekeyname();
2692 /* Test the creation, querying and deletion of a service */
2694 test_queryconfig2();
2696 /* The main reason for this test is to check if any refcounting is used
2697 * and what the rules are