2 * Unit tests for service functions
4 * Copyright (c) 2007 Paul Vriens
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wine/test.h"
35 static const CHAR spooler
[] = "Spooler"; /* Should be available on all platforms */
36 static CHAR selfname
[MAX_PATH
];
38 static BOOL (WINAPI
*pChangeServiceConfig2A
)(SC_HANDLE
,DWORD
,LPVOID
);
39 static BOOL (WINAPI
*pEnumServicesStatusExA
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
40 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
41 LPDWORD
, LPDWORD
, LPCSTR
);
42 static BOOL (WINAPI
*pEnumServicesStatusExW
)(SC_HANDLE
, SC_ENUM_TYPE
, DWORD
,
43 DWORD
, LPBYTE
, DWORD
, LPDWORD
,
44 LPDWORD
, LPDWORD
, LPCWSTR
);
45 static DWORD (WINAPI
*pGetSecurityInfo
)(HANDLE
, SE_OBJECT_TYPE
, SECURITY_INFORMATION
,
46 PSID
*, PSID
*, PACL
*, PACL
*, PSECURITY_DESCRIPTOR
*);
47 static BOOL (WINAPI
*pQueryServiceConfig2A
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
48 static BOOL (WINAPI
*pQueryServiceConfig2W
)(SC_HANDLE
,DWORD
,LPBYTE
,DWORD
,LPDWORD
);
49 static BOOL (WINAPI
*pQueryServiceStatusEx
)(SC_HANDLE
, SC_STATUS_TYPE
, LPBYTE
,
51 static BOOL (WINAPI
*pQueryServiceObjectSecurity
)(SC_HANDLE
, SECURITY_INFORMATION
,
52 PSECURITY_DESCRIPTOR
, DWORD
, LPDWORD
);
54 static void init_function_pointers(void)
56 HMODULE hadvapi32
= GetModuleHandleA("advapi32.dll");
58 pChangeServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "ChangeServiceConfig2A");
59 pEnumServicesStatusExA
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExA");
60 pEnumServicesStatusExW
= (void*)GetProcAddress(hadvapi32
, "EnumServicesStatusExW");
61 pGetSecurityInfo
= (void *)GetProcAddress(hadvapi32
, "GetSecurityInfo");
62 pQueryServiceConfig2A
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2A");
63 pQueryServiceConfig2W
= (void*)GetProcAddress(hadvapi32
, "QueryServiceConfig2W");
64 pQueryServiceStatusEx
= (void*)GetProcAddress(hadvapi32
, "QueryServiceStatusEx");
65 pQueryServiceObjectSecurity
= (void*)GetProcAddress(hadvapi32
, "QueryServiceObjectSecurity");
68 static void test_open_scm(void)
72 /* No access rights */
73 SetLastError(0xdeadbeef);
74 scm_handle
= OpenSCManagerA(NULL
, NULL
, 0);
75 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
76 CloseServiceHandle(scm_handle
);
78 /* Unknown database name */
79 SetLastError(0xdeadbeef);
80 scm_handle
= OpenSCManagerA(NULL
, "DoesNotExist", SC_MANAGER_CONNECT
);
81 ok(!scm_handle
, "Expected failure\n");
82 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
83 CloseServiceHandle(scm_handle
); /* Just in case */
85 /* MSDN says only ServiceActive is allowed, or NULL */
86 SetLastError(0xdeadbeef);
87 scm_handle
= OpenSCManagerA(NULL
, SERVICES_FAILED_DATABASEA
, SC_MANAGER_CONNECT
);
88 ok(!scm_handle
, "Expected failure\n");
89 ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST
, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %d\n", GetLastError());
90 CloseServiceHandle(scm_handle
); /* Just in case */
92 /* Remote unknown host */
93 SetLastError(0xdeadbeef);
94 scm_handle
= OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
97 ok(!scm_handle
, "Expected failure\n");
98 ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE
|| GetLastError() == RPC_S_INVALID_NET_ADDR
/* w2k8 */,
99 "Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %d\n", GetLastError());
101 CloseServiceHandle(scm_handle
); /* Just in case */
103 /* Proper call with an empty hostname */
104 scm_handle
= OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA
, SC_MANAGER_CONNECT
);
105 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
106 CloseServiceHandle(scm_handle
);
108 /* Again a correct one */
109 SetLastError(0xdeadbeef);
110 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
111 ok(GetLastError() == ERROR_SUCCESS
|| broken(GetLastError() == ERROR_IO_PENDING
) /* win2k */,
112 "Expected ERROR_SUCCESS, got %u\n", GetLastError());
113 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
114 CloseServiceHandle(scm_handle
);
117 static void test_open_svc(void)
119 SC_HANDLE scm_handle
, svc_handle
;
120 CHAR displayname
[4096];
123 /* All NULL (invalid access rights) */
124 SetLastError(0xdeadbeef);
125 svc_handle
= OpenServiceA(NULL
, NULL
, 0);
126 ok(!svc_handle
, "Expected failure\n");
127 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
129 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
132 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
133 SetLastError(0xdeadbeef);
134 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
135 ok(!svc_handle
, "Expected failure\n");
136 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
137 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
138 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
139 CloseServiceHandle(scm_handle
);
141 /* Nonexistent service */
142 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
143 SetLastError(0xdeadbeef);
144 svc_handle
= OpenServiceA(scm_handle
, "deadbeef", GENERIC_READ
);
145 ok(!svc_handle
, "Expected failure\n");
146 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
147 CloseServiceHandle(scm_handle
);
149 /* Proper SCM handle but different access rights */
150 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
151 SetLastError(0xdeadbeef);
152 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_WRITE
);
153 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
154 skip("Not enough rights to get a handle to the service\n");
157 ok(svc_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
158 CloseServiceHandle(svc_handle
);
161 /* Test to show we can't open a service with the displayname */
163 /* Retrieve the needed size for the buffer */
165 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
166 /* Get the displayname */
167 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
168 /* Try to open the service with this displayname, unless the displayname equals
169 * the servicename as that would defeat the purpose of this test.
171 if (!lstrcmpiA(spooler
, displayname
))
173 skip("displayname equals servicename\n");
174 CloseServiceHandle(scm_handle
);
178 SetLastError(0xdeadbeef);
179 svc_handle
= OpenServiceA(scm_handle
, displayname
, GENERIC_READ
);
180 ok(!svc_handle
, "Expected failure\n");
181 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
183 CloseServiceHandle(svc_handle
);
185 CloseServiceHandle(scm_handle
);
188 static void test_create_delete_svc(void)
190 SC_HANDLE scm_handle
, svc_handle1
;
191 CHAR username
[UNLEN
+ 1], domain
[MAX_PATH
];
192 DWORD user_size
= UNLEN
+ 1;
193 CHAR account
[UNLEN
+ 3];
194 static const CHAR servicename
[] = "Winetest";
195 static const CHAR pathname
[] = "we_dont_care.exe";
196 static const CHAR empty
[] = "";
197 static const CHAR password
[] = "secret";
198 BOOL spooler_exists
= FALSE
;
201 DWORD display_size
= sizeof(display
);
203 /* Get the username and turn it into an account to be used in some tests */
204 GetUserNameA(username
, &user_size
);
205 /* Get the domainname to cater for that situation */
206 if (GetEnvironmentVariableA("USERDOMAIN", domain
, MAX_PATH
))
207 sprintf(account
, "%s\\%s", domain
, username
);
209 sprintf(account
, ".\\%s", username
);
212 SetLastError(0xdeadbeef);
213 svc_handle1
= CreateServiceA(NULL
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
214 ok(!svc_handle1
, "Expected failure\n");
215 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
217 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
219 /* Only a valid handle to the Service Control Manager */
220 SetLastError(0xdeadbeef);
221 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
222 ok(!svc_handle1
, "Expected failure\n");
223 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
224 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
225 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
227 /* Now with a servicename */
228 SetLastError(0xdeadbeef);
229 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
230 ok(!svc_handle1
, "Expected failure\n");
231 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
232 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
233 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
235 /* Or just a binary name */
236 SetLastError(0xdeadbeef);
237 svc_handle1
= CreateServiceA(scm_handle
, NULL
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
238 ok(!svc_handle1
, "Expected failure\n");
239 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, W2K3, XP, Vista */ ||
240 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
241 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
243 /* Both servicename and binary name (We only have connect rights) */
244 SetLastError(0xdeadbeef);
245 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
246 ok(!svc_handle1
, "Expected failure\n");
247 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
249 /* They can even be empty at this stage of parameter checking */
250 SetLastError(0xdeadbeef);
251 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
252 ok(!svc_handle1
, "Expected failure\n");
253 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
255 SetLastError(0xdeadbeef);
256 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
257 ok(!svc_handle1
, "Expected failure\n");
258 ok(GetLastError() == ERROR_ACCESS_DENIED
, "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
260 /* Open the Service Control Manager with minimal rights for creation
261 * (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
263 CloseServiceHandle(scm_handle
);
264 SetLastError(0xdeadbeef);
265 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
266 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
268 skip("Not enough rights to get a handle to the manager\n");
272 /* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
274 /* Empty strings for servicename and binary name are checked */
275 SetLastError(0xdeadbeef);
276 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
277 ok(!svc_handle1
, "Expected failure\n");
278 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
280 SetLastError(0xdeadbeef);
281 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
282 ok(!svc_handle1
, "Expected failure\n");
283 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
285 SetLastError(0xdeadbeef);
286 svc_handle1
= CreateServiceA(scm_handle
, empty
, NULL
, 0, 0, 0, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
287 ok(!svc_handle1
, "Expected failure\n");
288 ok(GetLastError() == ERROR_INVALID_NAME
, "Expected ERROR_INVALID_NAME, got %d\n", GetLastError());
290 /* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
291 * an ERROR_INVALID_PARAMETER)
293 SetLastError(0xdeadbeef);
294 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
295 SERVICE_DISABLED
, 0, empty
, NULL
, NULL
, NULL
, NULL
, NULL
);
296 ok(!svc_handle1
, "Expected failure\n");
297 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
299 /* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
301 /* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
302 * SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
304 SetLastError(0xdeadbeef);
305 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
,
306 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
307 ok(!svc_handle1
, "Expected failure\n");
308 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
310 /* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
311 SetLastError(0xdeadbeef);
312 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_INTERACTIVE_PROCESS
,
313 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
314 ok(!svc_handle1
, "Expected failure\n");
315 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
317 /* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
318 * Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
320 SetLastError(0xdeadbeef);
321 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
322 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, account
, password
);
323 ok(!svc_handle1
, "Expected failure\n");
324 ok(GetLastError() == ERROR_INVALID_PARAMETER
|| GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT
,
325 "Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %d\n", GetLastError());
327 /* Illegal (start-type is not a mask and should only be one of the possibilities)
328 * Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
329 * it's most likely not the wanted start-type)
331 SetLastError(0xdeadbeef);
332 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
, SERVICE_WIN32_OWN_PROCESS
,
333 SERVICE_AUTO_START
| SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
334 ok(!svc_handle1
, "Expected failure\n");
335 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
337 /* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
338 SetLastError(0xdeadbeef);
339 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
340 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
341 ok(!svc_handle1
, "Expected failure\n");
342 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
344 /* Test if ServiceType can be a combined one for drivers */
345 SetLastError(0xdeadbeef);
346 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_KERNEL_DRIVER
| SERVICE_FILE_SYSTEM_DRIVER
,
347 SERVICE_BOOT_START
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
348 ok(!svc_handle1
, "Expected failure\n");
349 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
351 /* The service already exists (check first, just in case) */
352 svc_handle1
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
355 spooler_exists
= TRUE
;
356 CloseServiceHandle(svc_handle1
);
357 SetLastError(0xdeadbeef);
358 svc_handle1
= CreateServiceA(scm_handle
, spooler
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
,
359 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
360 ok(!svc_handle1
, "Expected failure\n");
361 ok(GetLastError() == ERROR_SERVICE_EXISTS
, "Expected ERROR_SERVICE_EXISTS, got %d\n", GetLastError());
364 skip("Spooler service doesn't exist\n");
366 /* To find an existing displayname we check the 'Spooler' service. Although the registry
367 * doesn't show DisplayName on NT4, this call will return a displayname which is equal
368 * to the servicename and can't be used as well for a new displayname.
372 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, display
, &display_size
);
375 skip("Could not retrieve a displayname for the Spooler service\n");
378 svc_handle1
= CreateServiceA(scm_handle
, servicename
, display
, 0, SERVICE_WIN32_OWN_PROCESS
,
379 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
380 ok(!svc_handle1
, "Expected failure\n");
381 ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME
,
382 "Expected ERROR_DUPLICATE_SERVICE_NAME, got %d\n", GetLastError());
386 skip("Could not retrieve a displayname (Spooler service doesn't exist)\n");
388 /* Windows doesn't care about the access rights for creation (which makes
389 * sense as there is no service yet) as long as there are sufficient
390 * rights to the manager.
392 SetLastError(0xdeadbeef);
393 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, 0, SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
394 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
395 ok(svc_handle1
!= NULL
, "Could not create the service : %d\n", GetLastError());
397 /* DeleteService however must have proper rights */
398 SetLastError(0xdeadbeef);
399 ret
= DeleteService(svc_handle1
);
400 ok(!ret
, "Expected failure\n");
401 ok(GetLastError() == ERROR_ACCESS_DENIED
,
402 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
404 /* Open the service with minimal rights for deletion.
405 * (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
407 CloseServiceHandle(svc_handle1
);
408 svc_handle1
= OpenServiceA(scm_handle
, servicename
, DELETE
);
410 /* Now that we have the proper rights, we should be able to delete */
411 SetLastError(0xdeadbeef);
412 ret
= DeleteService(svc_handle1
);
413 ok(ret
, "Expected success, got error %u\n", GetLastError());
415 CloseServiceHandle(svc_handle1
);
416 CloseServiceHandle(scm_handle
);
418 /* Wait a while. One of the following tests also does a CreateService for the
419 * same servicename and this would result in an ERROR_SERVICE_MARKED_FOR_DELETE
420 * error if we do this too quickly. Vista seems more picky than the others.
424 /* And a final NULL check */
425 SetLastError(0xdeadbeef);
426 ret
= DeleteService(NULL
);
427 ok(!ret
, "Expected failure\n");
428 ok(GetLastError() == ERROR_INVALID_HANDLE
,
429 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
432 static void test_get_displayname(void)
434 SC_HANDLE scm_handle
, svc_handle
;
436 CHAR displayname
[4096];
437 WCHAR displaynameW
[2048];
438 DWORD displaysize
, tempsize
, tempsizeW
;
439 static const CHAR deadbeef
[] = "Deadbeef";
440 static const WCHAR spoolerW
[] = {'S','p','o','o','l','e','r',0};
441 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
442 static const WCHAR abcW
[] = {'A','B','C',0};
443 static const CHAR servicename
[] = "Winetest";
444 static const CHAR pathname
[] = "we_dont_care.exe";
446 /* Having NULL for the size of the buffer will crash on W2K3 */
448 SetLastError(0xdeadbeef);
449 ret
= GetServiceDisplayNameA(NULL
, NULL
, NULL
, &displaysize
);
450 ok(!ret
, "Expected failure\n");
451 ok(GetLastError() == ERROR_INVALID_HANDLE
,
452 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
454 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
456 SetLastError(0xdeadbeef);
457 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, NULL
, &displaysize
);
458 ok(!ret
, "Expected failure\n");
459 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
460 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
461 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
463 SetLastError(0xdeadbeef);
464 displaysize
= sizeof(displayname
);
465 ret
= GetServiceDisplayNameA(scm_handle
, NULL
, displayname
, &displaysize
);
466 ok(!ret
, "Expected failure\n");
467 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
468 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
469 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
471 /* Test for nonexistent service */
472 SetLastError(0xdeadbeef);
474 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
475 ok(!ret
, "Expected failure\n");
476 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
477 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
479 SetLastError(0xdeadbeef);
480 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, NULL
, &displaysize
);
481 ok(!ret
, "Expected failure\n");
482 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
483 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
484 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
487 strcpy(displayname
, "ABC");
488 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
489 ok(!ret
, "Expected failure\n");
490 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
491 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
492 todo_wine
ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
493 ok(displayname
[0] == 0, "Service name not empty\n");
496 lstrcpyW( displaynameW
, abcW
);
497 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &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 ok(displaysize
== 15, "Service size expected 15, got %d\n", displaysize
);
502 ok(displaynameW
[0] == 0, "Service name not empty\n");
505 strcpy(displayname
, "ABC");
506 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &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 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
511 ok(displayname
[0] == 'A', "Service name changed\n");
514 lstrcpyW( displaynameW
, abcW
);
515 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
516 ok(!ret
, "Expected failure\n");
517 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
518 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
519 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
520 ok(displaynameW
[0] == 'A', "Service name changed\n");
523 strcpy(displayname
, "ABC");
524 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
525 ok(!ret
, "Expected failure\n");
526 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
527 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
528 todo_wine
ok(displaysize
== 1, "Service size expected 1, got %d\n", displaysize
);
529 ok(displayname
[0] == 0, "Service name not empty\n");
532 lstrcpyW( displaynameW
, abcW
);
533 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
534 ok(!ret
, "Expected failure\n");
535 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
536 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
537 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
538 ok(displaynameW
[0] == 'A', "Service name changed\n");
541 strcpy(displayname
, "ABC");
542 ret
= GetServiceDisplayNameA(scm_handle
, deadbeef
, displayname
, &displaysize
);
543 ok(!ret
, "Expected failure\n");
544 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
545 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
546 todo_wine
ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
547 ok(displayname
[0] == 0, "Service name not empty\n");
550 lstrcpyW( displaynameW
, abcW
);
551 ret
= GetServiceDisplayNameW(scm_handle
, deadbeefW
, displaynameW
, &displaysize
);
552 ok(!ret
, "Expected failure\n");
553 ok(displaysize
== 2, "Service size expected 2, got %d\n", displaysize
);
554 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
555 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
556 ok(displaynameW
[0] == 0, "Service name not empty\n");
558 /* Check if 'Spooler' exists */
559 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
562 skip("Spooler service doesn't exist\n");
563 CloseServiceHandle(scm_handle
);
566 CloseServiceHandle(svc_handle
);
568 /* Retrieve the needed size for the buffer */
569 SetLastError(0xdeadbeef);
571 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
572 ok(!ret
, "Expected failure\n");
573 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
574 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
575 tempsize
= displaysize
;
578 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
579 ok(!ret
, "Expected failure\n");
580 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
581 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
582 ok(displaysize
== tempsize
, "Buffer size mismatch (%d vs %d)\n", tempsize
, displaysize
);
584 /* Buffer is too small */
585 SetLastError(0xdeadbeef);
586 displaysize
= (tempsize
/ 2);
587 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
588 ok(!ret
, "Expected failure\n");
589 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
590 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
591 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
593 /* First try with a buffer that should be big enough to hold
594 * the ANSI string (and terminating character). This succeeds on Windows
595 * although when asked (see above 2 tests) it will return twice the needed size.
597 SetLastError(0xdeadbeef);
598 displaysize
= (tempsize
/ 2) + 1;
599 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
600 ok(ret
, "Expected success, got error %u\n", GetLastError());
601 ok(displaysize
== ((tempsize
/ 2) + 1), "Expected no change for the needed buffer size\n");
603 /* Now with the original returned size */
604 SetLastError(0xdeadbeef);
605 displaysize
= tempsize
;
606 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
607 ok(ret
, "Expected success, got error %u\n", GetLastError());
608 ok(displaysize
== tempsize
, "Expected no change for the needed buffer size\n");
610 /* And with a bigger than needed buffer */
611 SetLastError(0xdeadbeef);
612 displaysize
= tempsize
* 2;
613 ret
= GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
614 ok(ret
, "Expected success, got error %u\n", GetLastError());
615 /* Test that shows that if the buffersize is enough, it's not changed */
616 ok(displaysize
== tempsize
* 2, "Expected no change for the needed buffer size\n");
617 ok(strlen(displayname
) == tempsize
/2,
618 "Expected the buffer to be twice the length of the string\n") ;
620 /* Do the buffer(size) tests also for GetServiceDisplayNameW */
621 SetLastError(0xdeadbeef);
623 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, NULL
, &displaysize
);
624 ok(!ret
, "Expected failure\n");
625 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
626 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
628 /* Buffer is too small */
629 SetLastError(0xdeadbeef);
630 tempsizeW
= displaysize
;
631 displaysize
= tempsizeW
/ 2;
632 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
633 ok(!ret
, "Expected failure\n");
634 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
635 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
636 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
638 /* Now with the original returned size */
639 SetLastError(0xdeadbeef);
640 displaysize
= tempsizeW
;
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 /* And with a bigger than needed buffer */
648 SetLastError(0xdeadbeef);
649 displaysize
= tempsizeW
+ 1; /* This caters for the null terminating character */
650 ret
= GetServiceDisplayNameW(scm_handle
, spoolerW
, displaynameW
, &displaysize
);
651 ok(ret
, "Expected success, got error %u\n", GetLastError());
652 ok(displaysize
== tempsizeW
, "Expected the needed buffersize\n");
653 ok(lstrlenW(displaynameW
) == displaysize
,
654 "Expected the buffer to be the length of the string\n") ;
655 ok(tempsize
/ 2 == tempsizeW
,
656 "Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
658 CloseServiceHandle(scm_handle
);
660 /* Test for a service without a displayname (which is valid). This should return
661 * the servicename itself.
663 SetLastError(0xdeadbeef);
664 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
665 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
667 skip("Not enough rights to get a handle to the manager\n");
671 SetLastError(0xdeadbeef);
672 svc_handle
= CreateServiceA(scm_handle
, servicename
, NULL
, DELETE
,
673 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
674 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
675 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
678 CloseServiceHandle(scm_handle
);
682 /* Retrieve the needed size for the buffer */
683 SetLastError(0xdeadbeef);
685 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, NULL
, &displaysize
);
686 ok(!ret
, "Expected failure\n");
687 ok(displaysize
== strlen(servicename
) * 2,
688 "Expected the displaysize to be twice the size of the servicename\n");
689 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
690 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
692 /* Buffer is too small */
693 SetLastError(0xdeadbeef);
694 tempsize
= displaysize
;
695 displaysize
= (tempsize
/ 2);
696 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
697 ok(!ret
, "Expected failure\n");
698 ok(displaysize
== tempsize
, "Expected the needed buffersize\n");
699 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
700 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
702 /* Get the displayname */
703 SetLastError(0xdeadbeef);
704 ret
= GetServiceDisplayNameA(scm_handle
, servicename
, displayname
, &displaysize
);
705 ok(ret
, "Expected success, got error %u\n", GetLastError());
706 ok(!lstrcmpiA(displayname
, servicename
),
707 "Expected displayname to be %s, got %s\n", servicename
, displayname
);
709 /* Delete the service */
710 ret
= DeleteService(svc_handle
);
711 ok(ret
, "Expected success (err=%d)\n", GetLastError());
713 CloseServiceHandle(svc_handle
);
714 CloseServiceHandle(scm_handle
);
716 /* Wait a while. Just in case one of the following tests does a CreateService again */
720 static void test_get_servicekeyname(void)
722 SC_HANDLE scm_handle
, svc_handle
;
723 CHAR servicename
[4096];
724 CHAR displayname
[4096];
725 WCHAR servicenameW
[4096];
726 WCHAR displaynameW
[4096];
727 DWORD servicesize
, displaysize
, tempsize
;
729 static const CHAR deadbeef
[] = "Deadbeef";
730 static const WCHAR deadbeefW
[] = {'D','e','a','d','b','e','e','f',0};
731 static const WCHAR abcW
[] = {'A','B','C',0};
733 /* Having NULL for the size of the buffer will crash on W2K3 */
735 SetLastError(0xdeadbeef);
736 ret
= GetServiceKeyNameA(NULL
, NULL
, NULL
, &servicesize
);
737 ok(!ret
, "Expected failure\n");
738 ok(GetLastError() == ERROR_INVALID_HANDLE
,
739 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
741 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
744 SetLastError(0xdeadbeef);
745 ret
= GetServiceKeyNameA(scm_handle
, NULL
, NULL
, &servicesize
);
746 ok(!ret
, "Expected failure\n");
747 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
748 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
749 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
750 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
752 /* Valid handle and buffer but no displayname */
754 SetLastError(0xdeadbeef);
755 ret
= GetServiceKeyNameA(scm_handle
, NULL
, servicename
, &servicesize
);
756 ok(!ret
, "Expected failure\n");
757 ok(GetLastError() == ERROR_INVALID_ADDRESS
/* W2K, XP, W2K3, Vista */ ||
758 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
759 "Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
760 todo_wine
ok(servicesize
== 200, "Service size expected 1, got %d\n", servicesize
);
762 /* Test for nonexistent displayname */
763 SetLastError(0xdeadbeef);
764 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, NULL
, &servicesize
);
765 ok(!ret
, "Expected failure\n");
766 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
767 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
768 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
771 strcpy(servicename
, "ABC");
772 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
773 ok(!ret
, "Expected failure\n");
774 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
775 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
776 todo_wine
ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
777 ok(servicename
[0] == 0, "Service name not empty\n");
780 lstrcpyW( servicenameW
, abcW
);
781 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &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 ok(servicesize
== 15, "Service size expected 15, got %d\n", servicesize
);
786 ok(servicenameW
[0] == 0, "Service name not empty\n");
789 strcpy(servicename
, "ABC");
790 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &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 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
795 ok(servicename
[0] == 'A', "Service name changed\n");
798 lstrcpyW( servicenameW
, abcW
);
799 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
800 ok(!ret
, "Expected failure\n");
801 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
802 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
803 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
804 ok(servicenameW
[0] == 'A', "Service name changed\n");
807 strcpy(servicename
, "ABC");
808 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
809 ok(!ret
, "Expected failure\n");
810 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
811 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
812 todo_wine
ok(servicesize
== 1, "Service size expected 1, got %d\n", servicesize
);
813 ok(servicename
[0] == 0, "Service name not empty\n");
816 lstrcpyW( servicenameW
, abcW
);
817 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
818 ok(!ret
, "Expected failure\n");
819 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
820 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
821 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
822 ok(servicenameW
[0] == 'A', "Service name changed\n");
825 strcpy(servicename
, "ABC");
826 ret
= GetServiceKeyNameA(scm_handle
, deadbeef
, servicename
, &servicesize
);
827 ok(!ret
, "Expected failure\n");
828 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
829 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
830 todo_wine
ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
831 ok(servicename
[0] == 0, "Service name not empty\n");
834 lstrcpyW( servicenameW
, abcW
);
835 ret
= GetServiceKeyNameW(scm_handle
, deadbeefW
, servicenameW
, &servicesize
);
836 ok(!ret
, "Expected failure\n");
837 ok(servicesize
== 2, "Service size expected 2, got %d\n", servicesize
);
838 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
839 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
840 ok(servicenameW
[0] == 0, "Service name not empty\n");
842 /* Check if 'Spooler' exists */
843 svc_handle
= OpenServiceA(scm_handle
, spooler
, GENERIC_READ
);
846 skip("Spooler service doesn't exist\n");
847 CloseServiceHandle(scm_handle
);
850 CloseServiceHandle(svc_handle
);
852 /* Get the displayname for the 'Spooler' service */
853 GetServiceDisplayNameA(scm_handle
, spooler
, NULL
, &displaysize
);
854 GetServiceDisplayNameA(scm_handle
, spooler
, displayname
, &displaysize
);
856 /* Retrieve the needed size for the buffer */
857 SetLastError(0xdeadbeef);
859 ret
= GetServiceKeyNameA(scm_handle
, displayname
, NULL
, &servicesize
);
860 ok(!ret
, "Expected failure\n");
861 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
862 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
864 /* Valid call with the correct buffersize */
865 SetLastError(0xdeadbeef);
866 tempsize
= servicesize
;
868 ret
= GetServiceKeyNameA(scm_handle
, displayname
, servicename
, &servicesize
);
869 ok(ret
, "Expected success, got error %u\n", GetLastError());
872 ok(strlen(servicename
) == tempsize
/2,
873 "Expected the buffer to be twice the length of the string\n") ;
874 ok(!lstrcmpiA(servicename
, spooler
), "Expected %s, got %s\n", spooler
, servicename
);
875 ok(servicesize
== (tempsize
* 2),
876 "Expected servicesize not to change if buffer not insufficient\n") ;
879 MultiByteToWideChar(CP_ACP
, 0, displayname
, -1, displaynameW
, sizeof(displaynameW
)/2);
880 SetLastError(0xdeadbeef);
882 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
883 ok(ret
, "Expected success, got error %u\n", GetLastError());
886 ok(strlen(servicename
) == tempsize
/2,
887 "Expected the buffer to be twice the length of the string\n") ;
888 ok(servicesize
== lstrlenW(servicenameW
),
889 "Expected servicesize not to change if buffer not insufficient\n") ;
892 SetLastError(0xdeadbeef);
894 ret
= GetServiceKeyNameW(scm_handle
, displaynameW
, servicenameW
, &servicesize
);
895 ok(!ret
, "Expected failure\n");
896 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
897 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
898 ok(servicenameW
[0] == 0, "Buffer not empty\n");
900 CloseServiceHandle(scm_handle
);
903 static void test_query_svc(void)
905 SC_HANDLE scm_handle
, svc_handle
;
907 SERVICE_STATUS status
;
908 SERVICE_STATUS_PROCESS
*statusproc
;
909 DWORD bufsize
, needed
;
911 /* All NULL or wrong */
912 SetLastError(0xdeadbeef);
913 ret
= QueryServiceStatus(NULL
, NULL
);
914 ok(!ret
, "Expected failure\n");
915 ok(GetLastError() == ERROR_INVALID_HANDLE
,
916 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
918 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
920 /* Check if 'Spooler' exists.
921 * Open with not enough rights to query the status.
923 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
926 skip("Spooler service doesn't exist\n");
927 CloseServiceHandle(scm_handle
);
931 SetLastError(0xdeadbeef);
932 ret
= QueryServiceStatus(svc_handle
, NULL
);
933 ok(!ret
, "Expected failure\n");
934 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
935 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
936 "Unexpected last error %d\n", GetLastError());
938 SetLastError(0xdeadbeef);
939 ret
= QueryServiceStatus(svc_handle
, &status
);
940 ok(!ret
, "Expected failure\n");
941 ok(GetLastError() == ERROR_ACCESS_DENIED
,
942 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
944 /* Open the service with just enough rights.
945 * (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
947 CloseServiceHandle(svc_handle
);
948 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
950 SetLastError(0xdeadbeef);
951 ret
= QueryServiceStatus(svc_handle
, &status
);
952 ok(ret
, "Expected success, got error %u\n", GetLastError());
954 CloseServiceHandle(svc_handle
);
956 /* More or less the same tests for QueryServiceStatusEx */
957 if (!pQueryServiceStatusEx
)
959 win_skip( "QueryServiceStatusEx not available\n" );
960 CloseServiceHandle(scm_handle
);
964 /* Open service with not enough rights to query the status */
965 svc_handle
= OpenServiceA(scm_handle
, spooler
, STANDARD_RIGHTS_READ
);
967 /* All NULL or wrong, this proves that info level is checked first */
968 SetLastError(0xdeadbeef);
969 ret
= pQueryServiceStatusEx(NULL
, 1, NULL
, 0, NULL
);
970 ok(!ret
, "Expected failure\n");
971 ok(GetLastError() == ERROR_INVALID_LEVEL
,
972 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
974 /* Passing a NULL parameter for the needed buffer size
975 * will crash on anything but NT4.
978 /* Only info level is correct. It looks like the buffer/size is checked second */
979 SetLastError(0xdeadbeef);
980 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
981 /* NT4 checks the handle first */
982 if (GetLastError() != ERROR_INVALID_HANDLE
)
984 ok(!ret
, "Expected failure\n");
985 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
986 "Needed buffersize is wrong : %d\n", needed
);
987 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
988 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
991 /* Pass a correct buffer and buffersize but a NULL handle */
992 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
994 SetLastError(0xdeadbeef);
995 ret
= pQueryServiceStatusEx(NULL
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
996 ok(!ret
, "Expected failure\n");
997 ok(GetLastError() == ERROR_INVALID_HANDLE
,
998 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
999 HeapFree(GetProcessHeap(), 0, statusproc
);
1001 /* Correct handle and info level */
1002 SetLastError(0xdeadbeef);
1003 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, NULL
, 0, &needed
);
1004 /* NT4 doesn't return the needed size */
1005 if (GetLastError() != ERROR_INVALID_PARAMETER
)
1007 ok(!ret
, "Expected failure\n");
1008 ok(needed
== sizeof(SERVICE_STATUS_PROCESS
),
1009 "Needed buffersize is wrong : %d\n", needed
);
1010 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
1011 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1014 /* All parameters are OK but we don't have enough rights */
1015 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1016 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1017 SetLastError(0xdeadbeef);
1018 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1019 ok(!ret
, "Expected failure\n");
1020 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1021 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1022 HeapFree(GetProcessHeap(), 0, statusproc
);
1024 /* Open the service with just enough rights. */
1025 CloseServiceHandle(svc_handle
);
1026 svc_handle
= OpenServiceA(scm_handle
, spooler
, SERVICE_QUERY_STATUS
);
1028 /* Everything should be fine now. */
1029 statusproc
= HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_STATUS_PROCESS
));
1030 bufsize
= sizeof(SERVICE_STATUS_PROCESS
);
1031 SetLastError(0xdeadbeef);
1032 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, &needed
);
1033 ok(ret
, "Expected success, got error %u\n", GetLastError());
1034 if (statusproc
->dwCurrentState
== SERVICE_RUNNING
)
1035 ok(statusproc
->dwProcessId
!= 0,
1036 "Expect a process id for this running service\n");
1038 ok(statusproc
->dwProcessId
== 0,
1039 "Expect no process id for this stopped service\n");
1041 /* same call with null needed pointer */
1042 SetLastError(0xdeadbeef);
1043 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)statusproc
, bufsize
, NULL
);
1044 ok(!ret
, "Expected failure\n");
1045 ok(broken(GetLastError() == ERROR_INVALID_PARAMETER
) /* NT4 */ ||
1046 GetLastError() == ERROR_INVALID_ADDRESS
, "got %d\n", GetLastError());
1048 HeapFree(GetProcessHeap(), 0, statusproc
);
1050 CloseServiceHandle(svc_handle
);
1051 CloseServiceHandle(scm_handle
);
1054 static void test_enum_svc(void)
1056 SC_HANDLE scm_handle
;
1058 DWORD bufsize
, needed
, returned
, resume
;
1059 DWORD neededW
, returnedW
;
1060 DWORD tempneeded
, tempreturned
, missing
;
1061 DWORD servicecountactive
, servicecountinactive
;
1062 ENUM_SERVICE_STATUSA
*services
;
1063 ENUM_SERVICE_STATUSW
*servicesW
;
1064 ENUM_SERVICE_STATUS_PROCESSA
*exservices
;
1067 /* All NULL or wrong */
1068 SetLastError(0xdeadbeef);
1069 ret
= EnumServicesStatusA(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1070 ok(!ret
, "Expected failure\n");
1071 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1072 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1074 SetLastError(0xdeadbeef);
1075 ret
= EnumServicesStatusW(NULL
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1076 ok(!ret
, "Expected failure\n");
1077 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1078 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1080 /* Open the service control manager with not enough rights at first */
1081 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1083 /* Valid handle but rest is still NULL or wrong */
1084 SetLastError(0xdeadbeef);
1085 ret
= EnumServicesStatusA(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1086 ok(!ret
, "Expected failure\n");
1087 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1088 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1089 "Unexpected last error %d\n", GetLastError());
1091 SetLastError(0xdeadbeef);
1092 ret
= EnumServicesStatusW(scm_handle
, 1, 0, NULL
, 0, NULL
, NULL
, NULL
);
1093 ok(!ret
, "Expected failure\n");
1094 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1095 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1096 "Unexpected last error %d\n", GetLastError());
1098 /* Don't specify the two required pointers */
1099 returned
= 0xdeadbeef;
1100 SetLastError(0xdeadbeef);
1101 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, NULL
, &returned
, NULL
);
1102 ok(!ret
, "Expected failure\n");
1103 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1104 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1105 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1106 "Unexpected last error %d\n", GetLastError());
1108 returned
= 0xdeadbeef;
1109 SetLastError(0xdeadbeef);
1110 ret
= EnumServicesStatusW(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 /* Don't specify the two required pointers */
1118 needed
= 0xdeadbeef;
1119 SetLastError(0xdeadbeef);
1120 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, &needed
, NULL
, NULL
);
1121 ok(!ret
, "Expected failure\n");
1122 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1123 "Expected no change to the needed buffer variable\n");
1124 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1125 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1126 "Unexpected last error %d\n", GetLastError());
1128 needed
= 0xdeadbeef;
1129 SetLastError(0xdeadbeef);
1130 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, &needed
, NULL
, NULL
);
1131 ok(!ret
, "Expected failure\n");
1132 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1133 "Expected no change to the needed buffer variable\n");
1134 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1135 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1136 "Unexpected last error %d\n", GetLastError());
1138 /* No valid servicetype and servicestate */
1139 needed
= 0xdeadbeef;
1140 returned
= 0xdeadbeef;
1141 SetLastError(0xdeadbeef);
1142 ret
= EnumServicesStatusA(scm_handle
, 0, 0, NULL
, 0, &needed
, &returned
, NULL
);
1143 ok(!ret
, "Expected failure\n");
1144 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1145 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1146 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1147 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1148 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1150 needed
= 0xdeadbeef;
1151 returned
= 0xdeadbeef;
1152 SetLastError(0xdeadbeef);
1153 ret
= EnumServicesStatusW(scm_handle
, 0, 0, NULL
, 0, &needed
, &returned
, NULL
);
1154 ok(!ret
, "Expected failure\n");
1155 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1156 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1157 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1158 "Expected number of services to be set to 0, got %d\n", returned
);
1159 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1160 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1162 /* No valid servicestate */
1163 needed
= 0xdeadbeef;
1164 returned
= 0xdeadbeef;
1165 SetLastError(0xdeadbeef);
1166 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, 0, NULL
, 0, &needed
, &returned
, NULL
);
1167 ok(!ret
, "Expected failure\n");
1168 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1169 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1170 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1171 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1172 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1174 needed
= 0xdeadbeef;
1175 returned
= 0xdeadbeef;
1176 SetLastError(0xdeadbeef);
1177 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, 0, NULL
, 0, &needed
, &returned
, NULL
);
1178 ok(!ret
, "Expected failure\n");
1179 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1180 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1181 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1182 "Expected number of services to be set to 0, got %d\n", returned
);
1183 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1184 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1186 /* No valid servicetype */
1187 needed
= 0xdeadbeef;
1188 returned
= 0xdeadbeef;
1189 SetLastError(0xdeadbeef);
1190 ret
= EnumServicesStatusA(scm_handle
, 0, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1191 ok(!ret
, "Expected failure\n");
1192 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1193 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1194 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1195 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1196 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1198 needed
= 0xdeadbeef;
1199 returned
= 0xdeadbeef;
1200 SetLastError(0xdeadbeef);
1201 ret
= EnumServicesStatusW(scm_handle
, 0, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1202 ok(!ret
, "Expected failure\n");
1203 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1204 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1205 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1206 "Expected number of services to be set to 0, got %d\n", returned
);
1207 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1208 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1210 /* All parameters are correct but our access rights are wrong */
1211 needed
= 0xdeadbeef;
1212 returned
= 0xdeadbeef;
1213 SetLastError(0xdeadbeef);
1214 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1215 ok(!ret
, "Expected failure\n");
1216 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1217 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1218 ok(returned
== 0, "Expected number of services to be set to 0, got %d\n", returned
);
1219 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1220 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1222 needed
= 0xdeadbeef;
1223 returned
= 0xdeadbeef;
1224 SetLastError(0xdeadbeef);
1225 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1226 ok(!ret
, "Expected failure\n");
1227 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1228 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1229 ok(returned
== 0 || broken(returned
!= 0), /* nt4 */
1230 "Expected number of services to be set to 0, got %d\n", returned
);
1231 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1232 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1234 /* Open the service control manager with the needed rights */
1235 CloseServiceHandle(scm_handle
);
1236 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1238 /* All parameters are correct. Request the needed buffer size */
1239 needed
= 0xdeadbeef;
1240 returned
= 0xdeadbeef;
1241 SetLastError(0xdeadbeef);
1242 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
);
1243 ok(!ret
, "Expected failure\n");
1244 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1245 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1246 ok(GetLastError() == ERROR_MORE_DATA
,
1247 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1249 /* Test to show we get the same needed buffer size for the W-call */
1250 neededW
= 0xdeadbeef;
1251 returnedW
= 0xdeadbeef;
1252 SetLastError(0xdeadbeef);
1253 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0, &neededW
, &returnedW
, NULL
);
1254 ok(!ret
, "Expected failure\n");
1255 ok(neededW
!= 0xdeadbeef && neededW
> 0, "Expected the needed buffer size for this one service\n");
1256 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1257 ok(returnedW
== 0, "Expected no service returned, got %d\n", returnedW
);
1258 ok(GetLastError() == ERROR_MORE_DATA
,
1259 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1261 /* Store the needed bytes */
1262 tempneeded
= needed
;
1264 /* Allocate the correct needed bytes */
1265 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1267 needed
= 0xdeadbeef;
1268 returned
= 0xdeadbeef;
1269 SetLastError(0xdeadbeef);
1270 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1271 services
, bufsize
, &needed
, &returned
, NULL
);
1272 ok(ret
, "Expected success, got error %u\n", GetLastError());
1273 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1274 ok(returned
!= 0xdeadbeef && returned
> 0, "Expected some returned services\n");
1275 HeapFree(GetProcessHeap(), 0, services
);
1277 /* Store the number of returned services */
1278 tempreturned
= returned
;
1280 servicesW
= HeapAlloc(GetProcessHeap(), 0, neededW
);
1282 neededW
= 0xdeadbeef;
1283 returnedW
= 0xdeadbeef;
1284 SetLastError(0xdeadbeef);
1285 ret
= EnumServicesStatusW(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1286 servicesW
, bufsize
, &neededW
, &returnedW
, NULL
);
1287 ok(ret
, "Expected success, got error %u\n", GetLastError());
1288 ok(neededW
== 0, "Expected needed buffer to be 0 as we are done\n");
1289 ok(returnedW
!= 0xdeadbeef && returnedW
> 0, "Expected some returned services\n");
1290 HeapFree(GetProcessHeap(), 0, servicesW
);
1292 /* Allocate less than the needed bytes and don't specify a resume handle */
1293 services
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1294 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1295 needed
= 0xdeadbeef;
1296 returned
= 0xdeadbeef;
1297 SetLastError(0xdeadbeef);
1298 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1299 services
, bufsize
, &needed
, &returned
, NULL
);
1300 ok(!ret
, "Expected failure\n");
1301 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1302 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1303 ok(GetLastError() == ERROR_MORE_DATA
,
1304 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1306 /* Allocate less than the needed bytes, this time with a correct resume handle */
1307 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1308 needed
= 0xdeadbeef;
1309 returned
= 0xdeadbeef;
1311 SetLastError(0xdeadbeef);
1312 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1313 services
, bufsize
, &needed
, &returned
, &resume
);
1314 ok(!ret
, "Expected failure\n");
1315 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size for this one service\n");
1316 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1317 todo_wine
ok(resume
, "Expected a resume handle\n");
1318 ok(GetLastError() == ERROR_MORE_DATA
,
1319 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1321 /* Fetch the missing services but pass a bigger buffer size */
1322 missing
= tempreturned
- returned
;
1323 bufsize
= tempneeded
;
1324 needed
= 0xdeadbeef;
1325 returned
= 0xdeadbeef;
1326 SetLastError(0xdeadbeef);
1327 ret
= EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1328 services
, bufsize
, &needed
, &returned
, &resume
);
1329 ok(ret
, "Expected success, got error %u\n", GetLastError());
1330 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1331 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1332 ok(resume
== 0, "Expected the resume handle to be 0\n");
1333 HeapFree(GetProcessHeap(), 0, services
);
1335 /* See if things add up */
1337 /* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1338 * and doesn't count the others as inactive. This means that Vista could
1339 * show a total that is greater than the sum of active and inactive
1341 * The number of active and inactive drivers is greatly influenced by the
1342 * time when tests are run, immediately after boot or later for example.
1344 * Both reasons make calculations for drivers not so useful
1347 /* Get the number of active win32 services */
1348 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, NULL
, 0,
1349 &needed
, &returned
, NULL
);
1350 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1351 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_ACTIVE
, services
,
1352 needed
, &needed
, &returned
, NULL
);
1353 HeapFree(GetProcessHeap(), 0, services
);
1355 servicecountactive
= returned
;
1357 /* Get the number of inactive win32 services */
1358 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, NULL
, 0,
1359 &needed
, &returned
, NULL
);
1360 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1361 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_INACTIVE
, services
,
1362 needed
, &needed
, &returned
, NULL
);
1363 HeapFree(GetProcessHeap(), 0, services
);
1365 servicecountinactive
= returned
;
1367 /* Get the number of win32 services */
1368 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, NULL
, 0,
1369 &needed
, &returned
, NULL
);
1370 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1371 EnumServicesStatusA(scm_handle
, SERVICE_WIN32
, SERVICE_STATE_ALL
, services
,
1372 needed
, &needed
, &returned
, NULL
);
1373 HeapFree(GetProcessHeap(), 0, services
);
1375 /* Check if total is the same as active and inactive win32 services */
1376 ok(returned
== (servicecountactive
+ servicecountinactive
),
1377 "Something wrong in the calculation\n");
1379 /* Get all drivers and services
1381 * Fetch the status of the last call as failing could make the following tests crash
1382 * on Wine (we don't return anything yet).
1384 EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1385 NULL
, 0, &needed
, &returned
, NULL
);
1386 services
= HeapAlloc(GetProcessHeap(), 0, needed
);
1387 ret
= EnumServicesStatusA(scm_handle
, SERVICE_DRIVER
| SERVICE_WIN32
, SERVICE_STATE_ALL
,
1388 services
, needed
, &needed
, &returned
, NULL
);
1390 /* Loop through all those returned drivers and services */
1391 for (i
= 0; ret
&& i
< returned
; i
++)
1393 SERVICE_STATUS status
= services
[i
].ServiceStatus
;
1395 /* lpServiceName and lpDisplayName should always be filled */
1396 ok(lstrlenA(services
[i
].lpServiceName
) > 0, "Expected a service name\n");
1397 ok(lstrlenA(services
[i
].lpDisplayName
) > 0, "Expected a display name\n");
1399 /* Decrement the counters to see if the functions calls return the same
1400 * numbers as the contents of these structures.
1402 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1404 if (status
.dwCurrentState
== SERVICE_STOPPED
)
1405 servicecountinactive
--;
1407 servicecountactive
--;
1410 HeapFree(GetProcessHeap(), 0, services
);
1412 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1413 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1415 CloseServiceHandle(scm_handle
);
1417 /* More or less the same for EnumServicesStatusExA */
1418 if (!pEnumServicesStatusExA
)
1420 win_skip( "EnumServicesStatusExA not available\n" );
1424 /* All NULL or wrong */
1425 SetLastError(0xdeadbeef);
1426 ret
= pEnumServicesStatusExA(NULL
, 1, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1427 ok(!ret
, "Expected failure\n");
1428 ok(GetLastError() == ERROR_INVALID_LEVEL
,
1429 "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError());
1431 /* All NULL or wrong, just the info level is correct */
1432 SetLastError(0xdeadbeef);
1433 ret
= pEnumServicesStatusExA(NULL
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1434 ok(!ret
, "Expected failure\n");
1435 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1436 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1438 /* Open the service control manager with not enough rights at first */
1439 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1441 /* Valid handle and info level but rest is still NULL or wrong */
1442 SetLastError(0xdeadbeef);
1443 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1444 ok(!ret
, "Expected failure\n");
1445 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1446 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1447 "Unexpected last error %d\n", GetLastError());
1449 /* Don't specify the two required pointers */
1450 needed
= 0xdeadbeef;
1451 SetLastError(0xdeadbeef);
1452 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, NULL
, NULL
, NULL
);
1453 ok(!ret
, "Expected failure\n");
1454 ok(needed
== 0xdeadbeef || broken(needed
!= 0xdeadbeef), /* nt4 */
1455 "Expected no change to the needed buffer variable\n");
1456 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1457 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1458 "Unexpected last error %d\n", GetLastError());
1460 /* Don't specify the two required pointers */
1461 returned
= 0xdeadbeef;
1462 SetLastError(0xdeadbeef);
1463 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, NULL
, &returned
, NULL
, NULL
);
1464 ok(!ret
, "Expected failure\n");
1465 ok(returned
== 0xdeadbeef, "Expected no change to the number of services variable\n");
1466 ok(GetLastError() == ERROR_INVALID_ADDRESS
||
1467 GetLastError() == ERROR_INVALID_PARAMETER
/* NT4 */,
1468 "Unexpected last error %d\n", GetLastError());
1470 /* No valid servicetype and servicestate */
1471 needed
= 0xdeadbeef;
1472 returned
= 0xdeadbeef;
1473 SetLastError(0xdeadbeef);
1474 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1475 ok(!ret
, "Expected failure\n");
1476 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1477 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1478 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1479 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1480 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1482 /* No valid servicestate */
1483 needed
= 0xdeadbeef;
1484 returned
= 0xdeadbeef;
1485 SetLastError(0xdeadbeef);
1486 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, 0, NULL
, 0,
1487 &needed
, &returned
, NULL
, NULL
);
1488 ok(!ret
, "Expected failure\n");
1489 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1490 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1491 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1492 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1493 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1495 /* No valid servicetype */
1496 needed
= 0xdeadbeef;
1497 returned
= 0xdeadbeef;
1498 SetLastError(0xdeadbeef);
1499 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, SERVICE_STATE_ALL
, NULL
, 0,
1500 &needed
, &returned
, NULL
, NULL
);
1501 ok(!ret
, "Expected failure\n");
1502 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1503 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1504 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1505 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1506 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1508 /* No valid servicetype and servicestate and unknown service group */
1509 needed
= 0xdeadbeef;
1510 returned
= 0xdeadbeef;
1511 SetLastError(0xdeadbeef);
1512 ret
= pEnumServicesStatusExA(scm_handle
, 0, 0, 0, NULL
, 0, &needed
,
1513 &returned
, NULL
, "deadbeef_group");
1514 ok(!ret
, "Expected failure\n");
1515 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1516 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1517 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1518 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
1519 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1521 /* All parameters are correct but our access rights are wrong */
1522 needed
= 0xdeadbeef;
1523 returned
= 0xdeadbeef;
1524 SetLastError(0xdeadbeef);
1525 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1526 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1527 ok(!ret
, "Expected failure\n");
1528 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1529 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1530 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1531 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1532 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1534 /* All parameters are correct, access rights are wrong but the
1535 * group name won't be checked yet.
1537 needed
= 0xdeadbeef;
1538 returned
= 0xdeadbeef;
1539 SetLastError(0xdeadbeef);
1540 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1541 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1542 ok(!ret
, "Expected failure\n");
1543 ok(needed
== 0 || broken(needed
!= 0), /* nt4 */
1544 "Expected needed buffer size to be set to 0, got %d\n", needed
);
1545 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1546 ok(GetLastError() == ERROR_ACCESS_DENIED
,
1547 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1549 /* Open the service control manager with the needed rights */
1550 CloseServiceHandle(scm_handle
);
1551 scm_handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
1553 /* All parameters are correct and the group will be checked */
1554 needed
= 0xdeadbeef;
1555 returned
= 0xdeadbeef;
1556 SetLastError(0xdeadbeef);
1557 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1558 NULL
, 0, &needed
, &returned
, NULL
, "deadbeef_group");
1559 ok(!ret
, "Expected failure\n");
1560 ok(returned
== 0, "Expected number of service to be set to 0, got %d\n", returned
);
1561 ok(needed
== 0, "Expected needed buffer size to be set to 0, got %d\n", needed
);
1562 ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST
,
1563 "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %d\n", GetLastError());
1565 /* TODO: Create a test that makes sure we enumerate all services that don't
1566 * belong to a group. (specifying "").
1569 /* All parameters are correct. Request the needed buffer size */
1570 needed
= 0xdeadbeef;
1571 returned
= 0xdeadbeef;
1572 SetLastError(0xdeadbeef);
1573 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1574 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1575 ok(!ret
, "Expected failure\n");
1576 ok(returned
== 0, "Expected no service returned, got %d\n", returned
);
1577 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1578 ok(GetLastError() == ERROR_MORE_DATA
,
1579 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1581 /* Test to show we get the same needed buffer size for the W-call */
1582 neededW
= 0xdeadbeef;
1583 ret
= pEnumServicesStatusExW(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1584 NULL
, 0, &neededW
, &returnedW
, NULL
, NULL
);
1585 ok(!ret
, "Expected failure\n");
1586 ok(neededW
== needed
, "Expected needed buffersize to be the same for A- and W-calls\n");
1588 /* Store the needed bytes */
1589 tempneeded
= needed
;
1591 /* Allocate the correct needed bytes */
1592 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1594 needed
= 0xdeadbeef;
1595 returned
= 0xdeadbeef;
1596 SetLastError(0xdeadbeef);
1597 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1598 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1599 ok(ret
, "Expected success, got error %u\n", GetLastError());
1600 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1601 ok(returned
== tempreturned
, "Expected the same number of service from this function\n");
1602 HeapFree(GetProcessHeap(), 0, exservices
);
1604 /* Store the number of returned services */
1605 tempreturned
= returned
;
1607 /* Allocate less than the needed bytes and don't specify a resume handle */
1608 exservices
= HeapAlloc(GetProcessHeap(), 0, tempneeded
);
1609 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1610 needed
= 0xdeadbeef;
1611 returned
= 0xdeadbeef;
1612 SetLastError(0xdeadbeef);
1613 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1614 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, NULL
, NULL
);
1615 ok(!ret
, "Expected failure\n");
1616 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1617 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1618 ok(GetLastError() == ERROR_MORE_DATA
,
1619 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1621 /* Allocate less than the needed bytes, this time with a correct resume handle */
1622 bufsize
= (tempreturned
- 1) * sizeof(ENUM_SERVICE_STATUSA
);
1623 needed
= 0xdeadbeef;
1624 returned
= 0xdeadbeef;
1626 SetLastError(0xdeadbeef);
1627 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1628 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1629 ok(!ret
, "Expected failure\n");
1630 ok(needed
!= 0xdeadbeef && needed
> 0, "Expected the needed buffer size\n");
1631 ok(returned
< tempreturned
, "Expected fewer services to be returned\n");
1632 todo_wine
ok(resume
, "Expected a resume handle\n");
1633 ok(GetLastError() == ERROR_MORE_DATA
,
1634 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
1636 /* Fetch that last service but pass a bigger buffer size */
1637 missing
= tempreturned
- returned
;
1638 bufsize
= tempneeded
;
1639 needed
= 0xdeadbeef;
1640 returned
= 0xdeadbeef;
1641 SetLastError(0xdeadbeef);
1642 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1643 (BYTE
*)exservices
, bufsize
, &needed
, &returned
, &resume
, NULL
);
1644 ok(ret
, "Expected success, got error %u\n", GetLastError());
1645 ok(needed
== 0, "Expected needed buffer to be 0 as we are done\n");
1646 ok(returned
== missing
, "Expected %u services to be returned\n", missing
);
1647 ok(resume
== 0, "Expected the resume handle to be 0\n");
1648 HeapFree(GetProcessHeap(), 0, exservices
);
1650 /* See if things add up */
1652 /* Get the number of active win32 services */
1653 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1654 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1655 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1656 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_ACTIVE
,
1657 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1658 HeapFree(GetProcessHeap(), 0, exservices
);
1660 servicecountactive
= returned
;
1662 /* Get the number of inactive win32 services */
1663 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1664 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1665 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1666 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_INACTIVE
,
1667 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1668 HeapFree(GetProcessHeap(), 0, exservices
);
1670 servicecountinactive
= returned
;
1672 /* Get the number of win32 services */
1673 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1674 NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1675 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1676 pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
, SERVICE_STATE_ALL
,
1677 (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1678 HeapFree(GetProcessHeap(), 0, exservices
);
1680 /* Check if total is the same as active and inactive win32 services */
1681 ok(returned
== (servicecountactive
+ servicecountinactive
),
1682 "Something wrong in the calculation\n");
1684 /* Get all drivers and services */
1685 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1686 SERVICE_STATE_ALL
, NULL
, 0, &needed
, &returned
, NULL
, NULL
);
1687 ok(!ret
, "Expected failure\n");
1688 exservices
= HeapAlloc(GetProcessHeap(), 0, needed
);
1689 ret
= pEnumServicesStatusExA(scm_handle
, 0, SERVICE_WIN32
| SERVICE_DRIVER
,
1690 SERVICE_STATE_ALL
, (BYTE
*)exservices
, needed
, &needed
, &returned
, NULL
, NULL
);
1691 ok(ret
, "Expected success %u\n", GetLastError());
1693 /* Loop through all those returned drivers and services */
1694 for (i
= 0; i
< returned
; i
++)
1696 SERVICE_STATUS_PROCESS status
= exservices
[i
].ServiceStatusProcess
;
1698 /* lpServiceName and lpDisplayName should always be filled */
1699 ok(lstrlenA(exservices
[i
].lpServiceName
) > 0, "Expected a service name\n");
1700 ok(lstrlenA(exservices
[i
].lpDisplayName
) > 0, "Expected a display name\n");
1702 /* Decrement the counters to see if the functions calls return the
1703 * same numbers as the contents of these structures.
1704 * Check some process id specifics.
1706 if (status
.dwServiceType
& (SERVICE_FILE_SYSTEM_DRIVER
| SERVICE_KERNEL_DRIVER
))
1708 /* We shouldn't have a process id for drivers */
1709 ok(status
.dwProcessId
== 0,
1710 "This driver shouldn't have an associated process id\n");
1713 if (status
.dwServiceType
& (SERVICE_WIN32_OWN_PROCESS
| SERVICE_WIN32_SHARE_PROCESS
))
1715 if (status
.dwCurrentState
!= SERVICE_STOPPED
)
1717 /* We expect a process id for every running service */
1718 ok(status
.dwProcessId
> 0, "Expected a process id for this running service (%s)\n",
1719 exservices
[i
].lpServiceName
);
1721 servicecountactive
--;
1725 /* We shouldn't have a process id for inactive services */
1726 ok(status
.dwProcessId
== 0, "Service %s state %u shouldn't have an associated process id\n",
1727 exservices
[i
].lpServiceName
, status
.dwCurrentState
);
1729 servicecountinactive
--;
1733 HeapFree(GetProcessHeap(), 0, exservices
);
1735 ok(servicecountactive
== 0, "Active services mismatch %u\n", servicecountactive
);
1736 ok(servicecountinactive
== 0, "Inactive services mismatch %u\n", servicecountinactive
);
1738 CloseServiceHandle(scm_handle
);
1741 static void test_close(void)
1747 SetLastError(0xdeadbeef);
1748 ret
= CloseServiceHandle(NULL
);
1749 ok(!ret
, "Expected failure\n");
1750 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1752 /* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1755 handle
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_CONNECT
);
1756 SetLastError(0xdeadbeef);
1757 ret
= CloseServiceHandle(handle
);
1758 ok(ret
, "Expected success got error %u\n", GetLastError());
1761 static void test_sequence(void)
1763 SC_HANDLE scm_handle
, svc_handle
;
1765 QUERY_SERVICE_CONFIGA
*config
;
1766 DWORD given
, needed
;
1767 static const CHAR servicename
[] = "Winetest";
1768 static const CHAR displayname
[] = "Winetest dummy service";
1769 static const CHAR displayname2
[] = "Winetest dummy service (2)";
1770 static const CHAR pathname
[] = "we_dont_care.exe";
1771 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1772 static const CHAR password
[] = "";
1773 static const CHAR empty
[] = "";
1774 static const CHAR localsystem
[] = "LocalSystem";
1776 SetLastError(0xdeadbeef);
1777 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1779 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1781 skip("Not enough rights to get a handle to the manager\n");
1785 ok(scm_handle
!= NULL
, "Could not get a handle to the manager: %d\n", GetLastError());
1787 if (!scm_handle
) return;
1788 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
1789 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
1790 CloseServiceHandle(svc_handle
);
1792 /* Create a dummy service */
1793 SetLastError(0xdeadbeef);
1794 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1795 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1796 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1798 if (!svc_handle
&& (GetLastError() == ERROR_SERVICE_EXISTS
))
1800 /* We try and open the service and do the rest of the tests. Some could
1801 * fail if the tests were changed between these runs.
1803 trace("Deletion probably didn't work last time\n");
1804 SetLastError(0xdeadbeef);
1805 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
1806 if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1808 skip("Not enough rights to open the service\n");
1809 CloseServiceHandle(scm_handle
);
1812 ok(svc_handle
!= NULL
, "Could not open the service : %d\n", GetLastError());
1814 else if (!svc_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
1816 skip("Not enough rights to create the service\n");
1817 CloseServiceHandle(scm_handle
);
1822 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
1823 if ((svc_handle
!= NULL
) && (pGetSecurityInfo
!= NULL
))
1825 PSID sidOwner
, sidGroup
;
1827 PSECURITY_DESCRIPTOR pSD
;
1828 DWORD error
, n1
, n2
;
1832 /* Test using GetSecurityInfo to obtain security information */
1833 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, &sidOwner
,
1834 &sidGroup
, &dacl
, &sacl
, &pSD
);
1836 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1837 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1838 NULL
, NULL
, NULL
, &pSD
);
1840 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1843 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1844 NULL
, &dacl
, NULL
, &pSD
);
1845 ok(retval
== ERROR_SUCCESS
, "Expected GetSecurityInfo to succeed: result %d\n", retval
);
1847 SetLastError(0xdeadbeef);
1848 retval
= pGetSecurityInfo(svc_handle
, SE_SERVICE
, DACL_SECURITY_INFORMATION
, NULL
,
1849 NULL
, NULL
, NULL
, NULL
);
1850 error
= GetLastError();
1851 ok(retval
== ERROR_INVALID_PARAMETER
, "Expected GetSecurityInfo to fail: result %d\n", retval
);
1852 ok(error
== 0xdeadbeef, "Unexpected last error %d\n", error
);
1855 win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
1857 /* Test using QueryServiceObjectSecurity to obtain security information */
1858 SetLastError(0xdeadbeef);
1859 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, NULL
, 0, &n1
);
1860 error
= GetLastError();
1861 ok(!bret
, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret
);
1862 ok(error
== ERROR_INSUFFICIENT_BUFFER
||
1863 broken(error
== ERROR_INVALID_ADDRESS
) || broken(error
== ERROR_INVALID_PARAMETER
),
1864 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", error
);
1865 if (error
!= ERROR_INSUFFICIENT_BUFFER
) n1
= 1024;
1866 pSD
= LocalAlloc(0, n1
);
1867 bret
= pQueryServiceObjectSecurity(svc_handle
, DACL_SECURITY_INFORMATION
, pSD
, n1
, &n2
);
1868 ok(bret
, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret
);
1874 CloseServiceHandle(scm_handle
);
1879 * Before we do a QueryServiceConfig we should check the registry. This will make sure
1880 * that the correct keys are used.
1883 /* Request the size for the buffer */
1884 SetLastError(0xdeadbeef);
1885 ret
= QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1886 ok(!ret
, "Expected failure\n");
1887 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
1889 config
= HeapAlloc(GetProcessHeap(), 0, needed
);
1891 SetLastError(0xdeadbeef);
1892 ret
= QueryServiceConfigA(svc_handle
, config
, given
, &needed
);
1893 ok(ret
, "Expected success, got error %u\n", GetLastError());
1895 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1896 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1897 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1898 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1899 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1900 ok(config
->dwErrorControl
== SERVICE_ERROR_IGNORE
, "Expected SERVICE_ERROR_IGNORE, got %d\n", config
->dwErrorControl
);
1901 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1902 ok(!strcmp(config
->lpLoadOrderGroup
, empty
), "Expected an empty string, got '%s'\n", config
->lpLoadOrderGroup
);
1903 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1904 /* TODO: Show the double 0 terminated string */
1907 ok(!memcmp(config
->lpDependencies
, dependencies
, sizeof(dependencies
)), "Wrong string\n");
1909 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1910 ok(!strcmp(config
->lpDisplayName
, displayname
), "Expected '%s', got '%s'\n", displayname
, config
->lpDisplayName
);
1912 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_ERROR_NORMAL
, NULL
, "TestGroup2",
1913 NULL
, NULL
, NULL
, NULL
, displayname2
);
1914 ok(ret
, "ChangeServiceConfig failed (err=%d)\n", GetLastError());
1916 QueryServiceConfigA(svc_handle
, NULL
, 0, &needed
);
1917 config
= HeapReAlloc(GetProcessHeap(), 0, config
, needed
);
1918 ok(QueryServiceConfigA(svc_handle
, config
, needed
, &needed
), "QueryServiceConfig failed\n");
1919 ok(config
->lpBinaryPathName
&& config
->lpLoadOrderGroup
&& config
->lpDependencies
&& config
->lpServiceStartName
&&
1920 config
->lpDisplayName
, "Expected all string struct members to be non-NULL\n");
1921 ok(config
->dwServiceType
== (SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
),
1922 "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config
->dwServiceType
);
1923 ok(config
->dwStartType
== SERVICE_DISABLED
, "Expected SERVICE_DISABLED, got %d\n", config
->dwStartType
);
1924 ok(config
->dwErrorControl
== SERVICE_ERROR_NORMAL
, "Expected SERVICE_ERROR_NORMAL, got %d\n", config
->dwErrorControl
);
1925 ok(!strcmp(config
->lpBinaryPathName
, pathname
), "Expected '%s', got '%s'\n", pathname
, config
->lpBinaryPathName
);
1926 ok(!strcmp(config
->lpLoadOrderGroup
, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config
->lpLoadOrderGroup
);
1927 ok(config
->dwTagId
== 0, "Expected 0, got %d\n", config
->dwTagId
);
1928 ok(!strcmp(config
->lpServiceStartName
, localsystem
), "Expected 'LocalSystem', got '%s'\n", config
->lpServiceStartName
);
1929 ok(!strcmp(config
->lpDisplayName
, displayname2
), "Expected '%s', got '%s'\n", displayname2
, config
->lpDisplayName
);
1931 SetLastError(0xdeadbeef);
1932 ret
= DeleteService(svc_handle
);
1933 ok(ret
, "Expected success, got error %u\n", GetLastError());
1934 CloseServiceHandle(svc_handle
);
1936 /* Wait a while. The following test does a CreateService again */
1939 CloseServiceHandle(scm_handle
);
1940 HeapFree(GetProcessHeap(), 0, config
);
1943 static void test_queryconfig2(void)
1945 SC_HANDLE scm_handle
, svc_handle
;
1947 DWORD expected
, needed
;
1948 BYTE buffer
[MAX_PATH
];
1949 LPSERVICE_DESCRIPTIONA pConfig
= (LPSERVICE_DESCRIPTIONA
)buffer
;
1950 SERVICE_PRESHUTDOWN_INFO preshutdown_info
;
1951 static const CHAR servicename
[] = "Winetest";
1952 static const CHAR displayname
[] = "Winetest dummy service";
1953 static const CHAR pathname
[] = "we_dont_care.exe";
1954 static const CHAR dependencies
[] = "Master1\0Master2\0+MasterGroup1\0";
1955 static const CHAR password
[] = "";
1956 static const CHAR description
[] = "Description";
1958 if(!pQueryServiceConfig2A
)
1960 win_skip("function QueryServiceConfig2A not present\n");
1964 SetLastError(0xdeadbeef);
1965 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
1969 if(GetLastError() == ERROR_ACCESS_DENIED
)
1970 skip("Not enough rights to get a handle to the manager\n");
1972 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
1976 /* Create a dummy service */
1977 SetLastError(0xdeadbeef);
1978 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
, GENERIC_ALL
,
1979 SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
, SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
,
1980 pathname
, NULL
, NULL
, dependencies
, NULL
, password
);
1984 if(GetLastError() == ERROR_SERVICE_EXISTS
)
1986 /* We try and open the service and do the rest of the tests. Some could
1987 * fail if the tests were changed between these runs.
1989 trace("Deletion probably didn't work last time\n");
1990 SetLastError(0xdeadbeef);
1991 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
1994 if(GetLastError() == ERROR_ACCESS_DENIED
)
1995 skip("Not enough rights to open the service\n");
1997 ok(FALSE
, "Could not open the service : %d\n", GetLastError());
1998 CloseServiceHandle(scm_handle
);
2002 if (GetLastError() == ERROR_ACCESS_DENIED
)
2004 skip("Not enough rights to create the service\n");
2005 CloseServiceHandle(scm_handle
);
2008 ok(svc_handle
!= NULL
, "Could not create the service : %d\n", GetLastError());
2011 CloseServiceHandle(scm_handle
);
2015 SetLastError(0xdeadbeef);
2016 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2017 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2018 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2020 SetLastError(0xdeadbeef);
2021 ret
= pQueryServiceConfig2A(svc_handle
,0xfff0,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2022 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2023 ok(ERROR_INVALID_LEVEL
== GetLastError(), "expected error ERROR_INVALID_LEVEL, got %d\n", GetLastError());
2025 SetLastError(0xdeadbeef);
2026 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2027 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2028 ok(ERROR_INVALID_ADDRESS
== GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2030 SetLastError(0xdeadbeef);
2031 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2032 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2033 ok((ERROR_INVALID_ADDRESS
== GetLastError()) || (ERROR_INSUFFICIENT_BUFFER
== GetLastError()),
2034 "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2036 SetLastError(0xdeadbeef);
2037 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,sizeof(SERVICE_DESCRIPTIONA
),NULL
);
2038 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2039 ok(ERROR_INVALID_ADDRESS
== GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError());
2042 SetLastError(0xdeadbeef);
2043 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
)-1,&needed
);
2044 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2045 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2046 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2049 pConfig
->lpDescription
= (LPSTR
)0xdeadbeef;
2050 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2051 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2052 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2053 ok(!pConfig
->lpDescription
, "expected lpDescription to be NULL, got %p\n", pConfig
->lpDescription
);
2055 SetLastError(0xdeadbeef);
2057 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2058 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2059 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2060 ok(needed
== sizeof(SERVICE_DESCRIPTIONA
), "got %d\n", needed
);
2062 if(!pChangeServiceConfig2A
)
2064 win_skip("function ChangeServiceConfig2A not present\n");
2068 pConfig
->lpDescription
= (LPSTR
) description
;
2069 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
);
2070 ok(ret
, "ChangeServiceConfig2A failed\n");
2075 SetLastError(0xdeadbeef);
2077 expected
= sizeof(SERVICE_DESCRIPTIONA
) + sizeof(description
) * sizeof(WCHAR
); /* !! */
2078 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,sizeof(SERVICE_DESCRIPTIONA
),&needed
);
2079 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2080 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2081 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2083 SetLastError(0xdeadbeef);
2084 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
-1,&needed
);
2085 ok(!ret
, "expected QueryServiceConfig2A to fail\n");
2086 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2088 SetLastError(0xdeadbeef);
2089 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
,needed
,&needed
);
2090 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2091 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2092 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2094 SetLastError(0xdeadbeef);
2095 ret
= pQueryServiceConfig2A(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
+ 1,&needed
);
2096 ok(ret
, "expected QueryServiceConfig2A to succeed\n");
2097 ok(pConfig
->lpDescription
&& !strcmp(description
,pConfig
->lpDescription
),
2098 "expected lpDescription to be %s, got %s\n",description
,pConfig
->lpDescription
);
2100 if(!pQueryServiceConfig2W
)
2102 win_skip("function QueryServiceConfig2W not present\n");
2105 SetLastError(0xdeadbeef);
2107 expected
= sizeof(SERVICE_DESCRIPTIONW
) + sizeof(WCHAR
) * sizeof(description
);
2108 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,NULL
,0,&needed
);
2109 ok(!ret
, "expected QueryServiceConfig2W to fail\n");
2110 ok(ERROR_INSUFFICIENT_BUFFER
== GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
2111 ok(needed
== expected
, "expected needed to be %d, got %d\n", expected
, needed
);
2113 SetLastError(0xdeadbeef);
2114 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_DESCRIPTION
,buffer
, needed
,&needed
);
2115 ok(ret
, "expected QueryServiceConfig2W to succeed\n");
2117 SetLastError(0xdeadbeef);
2118 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2119 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2120 if(!ret
&& GetLastError()==ERROR_INVALID_LEVEL
)
2122 /* Win2k3 and older */
2123 win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2126 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2127 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2128 ok(preshutdown_info
.dwPreshutdownTimeout
== 180000, "Default PreshutdownTimeout = %d\n",
2129 preshutdown_info
.dwPreshutdownTimeout
);
2131 SetLastError(0xdeadbeef);
2132 preshutdown_info
.dwPreshutdownTimeout
= -1;
2133 ret
= pChangeServiceConfig2A(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2134 (LPVOID
)&preshutdown_info
);
2135 ok(ret
, "expected ChangeServiceConfig2A to succeed (%d)\n", GetLastError());
2137 ret
= pQueryServiceConfig2W(svc_handle
, SERVICE_CONFIG_PRESHUTDOWN_INFO
,
2138 (LPBYTE
)&preshutdown_info
, sizeof(preshutdown_info
), &needed
);
2139 ok(ret
, "expected QueryServiceConfig2W to succeed (%d)\n", GetLastError());
2140 ok(needed
== sizeof(preshutdown_info
), "needed = %d\n", needed
);
2141 ok(preshutdown_info
.dwPreshutdownTimeout
== -1, "New PreshutdownTimeout = %d\n",
2142 preshutdown_info
.dwPreshutdownTimeout
);
2145 DeleteService(svc_handle
);
2147 CloseServiceHandle(svc_handle
);
2149 /* Wait a while. The following test does a CreateService again */
2152 CloseServiceHandle(scm_handle
);
2155 static DWORD
try_start_stop(SC_HANDLE svc_handle
, const char* name
, DWORD is_nt4
)
2159 SERVICE_STATUS status
;
2161 ret
= StartServiceA(svc_handle
, 0, NULL
);
2162 le1
= GetLastError();
2163 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2165 if (pQueryServiceStatusEx
)
2168 SERVICE_STATUS_PROCESS statusproc
;
2170 ret
= pQueryServiceStatusEx(svc_handle
, SC_STATUS_PROCESS_INFO
, (BYTE
*)&statusproc
, sizeof(statusproc
), &needed
);
2171 ok(ret
, "%s: QueryServiceStatusEx() failed le=%u\n", name
, GetLastError());
2172 ok(statusproc
.dwCurrentState
== SERVICE_STOPPED
, "%s: should be stopped state=%x\n", name
, statusproc
.dwCurrentState
);
2173 ok(statusproc
.dwProcessId
== 0, "%s: ProcessId should be 0 instead of %x\n", name
, statusproc
.dwProcessId
);
2176 ret
= StartServiceA(svc_handle
, 0, NULL
);
2177 le2
= GetLastError();
2178 ok(!ret
, "%s: StartServiceA() should have failed\n", name
);
2179 ok(le2
== le1
, "%s: the second try should yield the same error: %u != %u\n", name
, le1
, le2
);
2181 status
.dwCurrentState
= 0xdeadbeef;
2182 ret
= ControlService(svc_handle
, SERVICE_CONTROL_STOP
, &status
);
2183 le2
= GetLastError();
2184 ok(!ret
, "%s: ControlService() should have failed\n", name
);
2185 ok(le2
== ERROR_SERVICE_NOT_ACTIVE
, "%s: %d != ERROR_SERVICE_NOT_ACTIVE\n", name
, le2
);
2186 ok(status
.dwCurrentState
== SERVICE_STOPPED
||
2187 broken(is_nt4
), /* NT4 returns a random value */
2188 "%s: should be stopped state=%x\n", name
, status
.dwCurrentState
);
2193 static void test_start_stop(void)
2196 SC_HANDLE scm_handle
, svc_handle
;
2198 static const char servicename
[] = "Winetest";
2199 char cmd
[MAX_PATH
+20];
2200 const char* displayname
;
2202 SetLastError(0xdeadbeef);
2203 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2206 if(GetLastError() == ERROR_ACCESS_DENIED
)
2207 skip("Not enough rights to get a handle to the manager\n");
2209 ok(FALSE
, "Could not get a handle to the manager: %d\n", GetLastError());
2214 svc_handle
= OpenServiceA(scm_handle
, NULL
, GENERIC_READ
);
2215 is_nt4
=(svc_handle
== NULL
&& GetLastError() == ERROR_INVALID_PARAMETER
);
2217 /* Do some cleanup in case a previous run crashed */
2218 svc_handle
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2221 DeleteService(svc_handle
);
2222 CloseServiceHandle(svc_handle
);
2225 /* Create a dummy disabled service */
2226 sprintf(cmd
, "\"%s\" service exit", selfname
);
2227 displayname
= "Winetest Disabled Service";
2228 svc_handle
= CreateServiceA(scm_handle
, servicename
, displayname
,
2229 GENERIC_ALL
, SERVICE_INTERACTIVE_PROCESS
| SERVICE_WIN32_OWN_PROCESS
,
2230 SERVICE_DISABLED
, SERVICE_ERROR_IGNORE
, cmd
, NULL
,
2231 NULL
, NULL
, NULL
, NULL
);
2234 if(GetLastError() == ERROR_ACCESS_DENIED
)
2235 skip("Not enough rights to create the service\n");
2237 ok(FALSE
, "Could not create the service: %d\n", GetLastError());
2240 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2241 ok(le
== ERROR_SERVICE_DISABLED
, "%d != ERROR_SERVICE_DISABLED\n", le
);
2243 /* Then one with a bad path */
2244 displayname
= "Winetest Bad Path";
2245 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_DEMAND_START
, SERVICE_NO_CHANGE
, "c:\\no_such_file.exe", NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2246 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2247 try_start_stop(svc_handle
, displayname
, is_nt4
);
2251 /* NT4 does not detect when a service fails to start and uses an
2252 * insanely long timeout: 120s. So skip the rest of the tests.
2254 win_skip("Skip some service start/stop tests on NT4\n");
2258 /* Again with a process that exits right away */
2259 displayname
= "Winetest Exit Service";
2260 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2261 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2262 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2263 ok(le
== ERROR_SERVICE_REQUEST_TIMEOUT
, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le
);
2265 /* And finally with a service that plays dead, forcing a timeout.
2266 * This time we will put no quotes. That should work too, even if there are
2267 * spaces in the path.
2269 sprintf(cmd
, "%s service sleep", selfname
);
2270 displayname
= "Winetest Sleep Service";
2271 ret
= ChangeServiceConfigA(svc_handle
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, SERVICE_NO_CHANGE
, cmd
, NULL
, NULL
, NULL
, NULL
, NULL
, displayname
);
2272 ok(ret
, "ChangeServiceConfig() failed le=%u\n", GetLastError());
2274 le
= try_start_stop(svc_handle
, displayname
, is_nt4
);
2275 ok(le
== ERROR_SERVICE_REQUEST_TIMEOUT
, "%d != ERROR_SERVICE_REQUEST_TIMEOUT\n", le
);
2280 DeleteService(svc_handle
);
2281 CloseServiceHandle(svc_handle
);
2284 /* Wait a while. The following test does a CreateService again */
2287 CloseServiceHandle(scm_handle
);
2290 static void test_refcount(void)
2292 SC_HANDLE scm_handle
, svc_handle1
, svc_handle2
, svc_handle3
, svc_handle4
, svc_handle5
;
2293 static const CHAR servicename
[] = "Winetest";
2294 static const CHAR pathname
[] = "we_dont_care.exe";
2297 /* Get a handle to the Service Control Manager */
2298 SetLastError(0xdeadbeef);
2299 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2300 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
2302 skip("Not enough rights to get a handle to the manager\n");
2306 /* Create a service */
2307 svc_handle1
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2308 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2309 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2310 ok(svc_handle1
!= NULL
, "Expected success, got error %u\n", GetLastError());
2312 /* Get a handle to this new service */
2313 svc_handle2
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2314 ok(svc_handle2
!= NULL
, "Expected success, got error %u\n", GetLastError());
2316 /* Get another handle to this new service */
2317 svc_handle3
= OpenServiceA(scm_handle
, servicename
, GENERIC_READ
);
2318 ok(svc_handle3
!= NULL
, "Expected success, got error %u\n", GetLastError());
2320 /* Check if we can close the handle to the Service Control Manager */
2321 ret
= CloseServiceHandle(scm_handle
);
2322 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2324 /* Get a new handle to the Service Control Manager */
2325 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2326 ok(scm_handle
!= NULL
, "Expected success, got error %u\n", GetLastError());
2328 /* Get a handle to this new service */
2329 svc_handle4
= OpenServiceA(scm_handle
, servicename
, GENERIC_ALL
);
2330 ok(svc_handle4
!= NULL
, "Expected success, got error %u\n", GetLastError());
2332 /* Delete the service */
2333 ret
= DeleteService(svc_handle4
);
2334 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2336 /* We cannot create the same service again as it's still marked as 'being deleted'.
2337 * The reason is that we still have 4 open handles to this service even though we
2338 * closed the handle to the Service Control Manager in between.
2340 SetLastError(0xdeadbeef);
2341 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2342 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2343 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2346 ok(!svc_handle5
, "Expected failure\n");
2347 ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE
,
2348 "Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %d\n", GetLastError());
2351 /* FIXME: Remove this when Wine is fixed */
2354 DeleteService(svc_handle5
);
2355 CloseServiceHandle(svc_handle5
);
2358 /* Close all the handles to the service and try again */
2359 ret
= CloseServiceHandle(svc_handle4
);
2360 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2361 ret
= CloseServiceHandle(svc_handle3
);
2362 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2363 ret
= CloseServiceHandle(svc_handle2
);
2364 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2365 ret
= CloseServiceHandle(svc_handle1
);
2366 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2368 /* Wait a while. Doing a CreateService too soon will result again
2369 * in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2373 /* We succeed now as all handles are closed (tested this also with a long SLeep() */
2374 svc_handle5
= CreateServiceA(scm_handle
, servicename
, NULL
, GENERIC_ALL
,
2375 SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
,
2376 SERVICE_DISABLED
, 0, pathname
, NULL
, NULL
, NULL
, NULL
, NULL
);
2377 ok(svc_handle5
!= NULL
, "Expected success, got error %u\n", GetLastError());
2379 /* Delete the service */
2380 ret
= DeleteService(svc_handle5
);
2381 ok(ret
, "Expected success (err=%d)\n", GetLastError());
2383 /* Wait a while. Just in case one of the following tests does a CreateService again */
2386 CloseServiceHandle(svc_handle5
);
2387 CloseServiceHandle(scm_handle
);
2392 SC_HANDLE scm_handle
;
2396 myARGC
= winetest_get_mainargs(&myARGV
);
2397 GetFullPathNameA(myARGV
[0], sizeof(selfname
), selfname
, NULL
);
2400 if (strcmp(myARGV
[2], "sleep") == 0)
2401 /* Cause a service startup timeout */
2403 /* then, or if myARGV[2] == "exit", just exit */
2407 /* Bail out if we are on win98 */
2408 SetLastError(0xdeadbeef);
2409 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
2411 if (!scm_handle
&& (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
))
2413 win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
2416 CloseServiceHandle(scm_handle
);
2418 init_function_pointers();
2420 /* First some parameter checking */
2423 test_create_delete_svc();
2424 test_get_displayname();
2425 test_get_servicekeyname();
2429 /* Test the creation, querying and deletion of a service */
2431 test_queryconfig2();
2433 /* The main reason for this test is to check if any refcounting is used
2434 * and what the rules are