Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/advapi32/tests/service.c
8725 views
1
/*
2
* Unit tests for service functions
3
*
4
* Copyright (c) 2007 Paul Vriens
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
#include <stdio.h>
23
24
#include "windef.h"
25
#include "winbase.h"
26
#include "winerror.h"
27
#include "winreg.h"
28
#include "winsvc.h"
29
#include "winnls.h"
30
#include "lmcons.h"
31
#include "aclapi.h"
32
33
#include "wine/test.h"
34
35
static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */
36
static CHAR selfname[MAX_PATH];
37
38
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
39
40
static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
41
static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
42
static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
43
DWORD, LPBYTE, DWORD, LPDWORD,
44
LPDWORD, LPDWORD, LPCSTR);
45
static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
46
DWORD, LPBYTE, DWORD, LPDWORD,
47
LPDWORD, LPDWORD, LPCWSTR);
48
static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
49
static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
50
static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
51
DWORD, LPDWORD);
52
static BOOL (WINAPI *pQueryServiceObjectSecurity)(SC_HANDLE, SECURITY_INFORMATION,
53
PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
54
static DWORD (WINAPI *pNotifyServiceStatusChangeW)(SC_HANDLE,DWORD,SERVICE_NOTIFYW*);
55
56
static void init_function_pointers(void)
57
{
58
HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
59
60
pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
61
pChangeServiceConfig2W = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2W");
62
pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
63
pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
64
pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
65
pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
66
pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
67
pQueryServiceObjectSecurity = (void*)GetProcAddress(hadvapi32, "QueryServiceObjectSecurity");
68
pNotifyServiceStatusChangeW = (void*)GetProcAddress(hadvapi32, "NotifyServiceStatusChangeW");
69
70
pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
71
}
72
73
static void test_open_scm(void)
74
{
75
SC_HANDLE scm_handle;
76
77
/* No access rights */
78
SetLastError(0xdeadbeef);
79
scm_handle = OpenSCManagerA(NULL, NULL, 0);
80
ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
81
CloseServiceHandle(scm_handle);
82
83
/* Unknown database name */
84
SetLastError(0xdeadbeef);
85
scm_handle = OpenSCManagerA(NULL, "DoesNotExist", SC_MANAGER_CONNECT);
86
ok(!scm_handle, "Expected failure\n");
87
ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %ld\n", GetLastError());
88
CloseServiceHandle(scm_handle); /* Just in case */
89
90
/* MSDN says only ServiceActive is allowed, or NULL */
91
SetLastError(0xdeadbeef);
92
scm_handle = OpenSCManagerA(NULL, SERVICES_FAILED_DATABASEA, SC_MANAGER_CONNECT);
93
ok(!scm_handle, "Expected failure\n");
94
ok(GetLastError() == ERROR_DATABASE_DOES_NOT_EXIST, "Expected ERROR_DATABASE_DOES_NOT_EXIST, got %ld\n", GetLastError());
95
CloseServiceHandle(scm_handle); /* Just in case */
96
97
/* Remote unknown host */
98
SetLastError(0xdeadbeef);
99
scm_handle = OpenSCManagerA("DOESNOTEXIST", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
100
todo_wine
101
{
102
ok(!scm_handle, "Expected failure\n");
103
ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || GetLastError() == RPC_S_INVALID_NET_ADDR /* w2k8 */,
104
"Expected RPC_S_SERVER_UNAVAILABLE or RPC_S_INVALID_NET_ADDR, got %ld\n", GetLastError());
105
}
106
CloseServiceHandle(scm_handle); /* Just in case */
107
108
/* Proper call with an empty hostname */
109
scm_handle = OpenSCManagerA("", SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT);
110
ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
111
CloseServiceHandle(scm_handle);
112
113
/* Again a correct one */
114
SetLastError(0xdeadbeef);
115
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
116
ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_IO_PENDING) /* win2k */,
117
"Expected ERROR_SUCCESS, got %lu\n", GetLastError());
118
ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
119
CloseServiceHandle(scm_handle);
120
}
121
122
static void test_open_svc(void)
123
{
124
SC_HANDLE scm_handle, svc_handle;
125
CHAR displayname[4096];
126
DWORD displaysize;
127
128
/* All NULL (invalid access rights) */
129
SetLastError(0xdeadbeef);
130
svc_handle = OpenServiceA(NULL, NULL, 0);
131
ok(!svc_handle, "Expected failure\n");
132
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
133
134
/* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
135
136
/* NULL service */
137
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
138
SetLastError(0xdeadbeef);
139
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
140
ok(!svc_handle, "Expected failure\n");
141
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
142
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
143
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
144
CloseServiceHandle(scm_handle);
145
146
/* Nonexistent service */
147
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
148
SetLastError(0xdeadbeef);
149
svc_handle = OpenServiceA(scm_handle, "deadbeef", GENERIC_READ);
150
ok(!svc_handle, "Expected failure\n");
151
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
152
CloseServiceHandle(scm_handle);
153
154
/* Proper SCM handle but different access rights */
155
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
156
SetLastError(0xdeadbeef);
157
svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_WRITE);
158
if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
159
skip("Not enough rights to get a handle to the service\n");
160
else
161
{
162
ok(svc_handle != NULL, "Expected success, got error %lu\n", GetLastError());
163
CloseServiceHandle(svc_handle);
164
}
165
166
/* Test to show we can't open a service with the displayname */
167
168
/* Retrieve the needed size for the buffer */
169
displaysize = 0;
170
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
171
/* Get the displayname */
172
GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
173
/* Try to open the service with this displayname, unless the displayname equals
174
* the servicename as that would defeat the purpose of this test.
175
*/
176
if (!lstrcmpiA(spooler, displayname))
177
{
178
skip("displayname equals servicename\n");
179
CloseServiceHandle(scm_handle);
180
return;
181
}
182
183
SetLastError(0xdeadbeef);
184
svc_handle = OpenServiceA(scm_handle, displayname, GENERIC_READ);
185
ok(!svc_handle, "Expected failure\n");
186
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
187
/* Just in case */
188
CloseServiceHandle(svc_handle);
189
190
CloseServiceHandle(scm_handle);
191
}
192
193
static void test_create_delete_svc(void)
194
{
195
SC_HANDLE scm_handle, svc_handle1, svc_handle2;
196
CHAR username[UNLEN + 1], domain[MAX_PATH];
197
DWORD user_size = UNLEN + 1;
198
CHAR account[MAX_PATH + UNLEN + 1];
199
static const CHAR servicename [] = "winetest_create_delete";
200
static const CHAR pathname [] = "we_dont_care.exe";
201
static const CHAR empty [] = "";
202
static const CHAR password [] = "secret";
203
char buffer[200];
204
DWORD size;
205
BOOL ret;
206
207
/* Get the username and turn it into an account to be used in some tests */
208
GetUserNameA(username, &user_size);
209
/* Get the domainname to cater for that situation */
210
if (GetEnvironmentVariableA("USERDOMAIN", domain, MAX_PATH))
211
sprintf(account, "%s\\%s", domain, username);
212
else
213
sprintf(account, ".\\%s", username);
214
215
/* All NULL */
216
SetLastError(0xdeadbeef);
217
svc_handle1 = CreateServiceA(NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
218
ok(!svc_handle1, "Expected failure\n");
219
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
220
221
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
222
223
/* Only a valid handle to the Service Control Manager */
224
SetLastError(0xdeadbeef);
225
svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
226
ok(!svc_handle1, "Expected failure\n");
227
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
228
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
229
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
230
231
/* Now with a servicename */
232
SetLastError(0xdeadbeef);
233
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);
234
ok(!svc_handle1, "Expected failure\n");
235
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
236
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
237
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
238
239
/* Or just a binary name */
240
SetLastError(0xdeadbeef);
241
svc_handle1 = CreateServiceA(scm_handle, NULL, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
242
ok(!svc_handle1, "Expected failure\n");
243
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, W2K3, XP, Vista */ ||
244
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
245
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
246
247
/* Both servicename and binary name (We only have connect rights) */
248
SetLastError(0xdeadbeef);
249
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
250
ok(!svc_handle1, "Expected failure\n");
251
ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
252
253
/* They can even be empty at this stage of parameter checking */
254
SetLastError(0xdeadbeef);
255
svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
256
ok(!svc_handle1, "Expected failure\n");
257
ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
258
259
SetLastError(0xdeadbeef);
260
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
261
ok(!svc_handle1, "Expected failure\n");
262
ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
263
264
/* Open the Service Control Manager with minimal rights for creation
265
* (Verified with 'SC_MANAGER_ALL_ACCESS &~ SC_MANAGER_CREATE_SERVICE')
266
*/
267
CloseServiceHandle(scm_handle);
268
SetLastError(0xdeadbeef);
269
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
270
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
271
{
272
skip("Not enough rights to get a handle to the manager\n");
273
return;
274
}
275
276
/* TODO: It looks like account (ServiceStartName) and (maybe) password are checked at this place */
277
278
/* Empty strings for servicename and binary name are checked */
279
SetLastError(0xdeadbeef);
280
svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, pathname, NULL, NULL, NULL, NULL, NULL);
281
ok(!svc_handle1, "Expected failure\n");
282
ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %ld\n", GetLastError());
283
284
SetLastError(0xdeadbeef);
285
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
286
ok(!svc_handle1, "Expected failure\n");
287
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
288
289
SetLastError(0xdeadbeef);
290
svc_handle1 = CreateServiceA(scm_handle, empty, NULL, 0, 0, 0, 0, empty, NULL, NULL, NULL, NULL, NULL);
291
ok(!svc_handle1, "Expected failure\n");
292
ok(GetLastError() == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %ld\n", GetLastError());
293
294
/* Valid call (as we will see later) except for the empty binary name (to proof it's indeed
295
* an ERROR_INVALID_PARAMETER)
296
*/
297
SetLastError(0xdeadbeef);
298
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
299
SERVICE_DISABLED, 0, empty, NULL, NULL, NULL, NULL, NULL);
300
ok(!svc_handle1, "Expected failure\n");
301
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
302
303
/* Windows checks if the 'service type', 'access type' and the combination of them are valid, so let's test that */
304
305
/* Illegal (service-type, which is used as a mask can't have a mix. Except the one with
306
* SERVICE_INTERACTIVE_PROCESS which will be tested below in a valid call)
307
*/
308
SetLastError(0xdeadbeef);
309
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS,
310
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
311
ok(!svc_handle1, "Expected failure\n");
312
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
313
314
/* Illegal (SERVICE_INTERACTIVE_PROCESS is only allowed with SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS) */
315
SetLastError(0xdeadbeef);
316
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_FILE_SYSTEM_DRIVER | SERVICE_INTERACTIVE_PROCESS,
317
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
318
ok(!svc_handle1, "Expected failure\n");
319
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
320
321
/* Illegal (this combination is only allowed when the LocalSystem account (ServiceStartName) is used)
322
* Not having a correct account would have resulted in an ERROR_INVALID_SERVICE_ACCOUNT.
323
*/
324
SetLastError(0xdeadbeef);
325
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
326
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, account, password);
327
ok(!svc_handle1, "Expected failure\n");
328
ok(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_SERVICE_ACCOUNT,
329
"Expected ERROR_INVALID_PARAMETER or ERROR_INVALID_SERVICE_ACCOUNT, got %ld\n", GetLastError());
330
331
/* Illegal (start-type is not a mask and should only be one of the possibilities)
332
* Remark : 'OR'-ing them could result in a valid possibility (but doesn't make sense as
333
* it's most likely not the wanted start-type)
334
*/
335
SetLastError(0xdeadbeef);
336
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL, SERVICE_WIN32_OWN_PROCESS,
337
SERVICE_AUTO_START | SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
338
ok(!svc_handle1, "Expected failure\n");
339
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
340
341
/* Illegal (SERVICE_BOOT_START and SERVICE_SYSTEM_START are only allowed for driver services) */
342
SetLastError(0xdeadbeef);
343
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS,
344
SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
345
ok(!svc_handle1, "Expected failure\n");
346
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
347
348
/* Test if ServiceType can be a combined one for drivers */
349
SetLastError(0xdeadbeef);
350
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER,
351
SERVICE_BOOT_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
352
ok(!svc_handle1, "Expected failure\n");
353
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
354
355
/* Test duplicate service names */
356
svc_handle1 = CreateServiceA(scm_handle, "winetest_dupname", "winetest_display", DELETE,
357
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
358
ok(!!svc_handle1, "Failed to create service, error %lu\n", GetLastError());
359
360
svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname", NULL, 0,
361
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
362
ok(!svc_handle2, "Expected failure\n");
363
ok(GetLastError() == ERROR_SERVICE_EXISTS, "Got wrong error %lu\n", GetLastError());
364
365
svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_dupname", DELETE,
366
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
367
todo_wine ok(!svc_handle2, "Expected failure\n");
368
todo_wine ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %lu\n", GetLastError());
369
if (svc_handle2)
370
{
371
DeleteService(svc_handle2);
372
CloseServiceHandle(svc_handle2);
373
}
374
375
svc_handle2 = CreateServiceA(scm_handle, "winetest_dupname2", "winetest_display", DELETE,
376
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, 0, pathname, NULL, NULL, NULL, NULL, NULL);
377
if (svc_handle2) /* Win10 1709+ */
378
{
379
size = sizeof(buffer);
380
ret = GetServiceKeyNameA(scm_handle, "winetest_display", buffer, &size);
381
ok(ret, "Failed to get key name, error %lu\n", GetLastError());
382
ok(!strcmp(buffer, "winetest_dupname"), "Got wrong name \"%s\"\n", buffer);
383
384
ret = DeleteService(svc_handle2);
385
ok(ret, "Failed to delete service, error %lu\n", GetLastError());
386
CloseServiceHandle(svc_handle2);
387
}
388
else
389
ok(GetLastError() == ERROR_DUPLICATE_SERVICE_NAME, "Got wrong error %lu\n", GetLastError());
390
391
ret = DeleteService(svc_handle1);
392
ok(ret, "Failed to delete service, error %lu\n", GetLastError());
393
CloseServiceHandle(svc_handle1);
394
395
/* Windows doesn't care about the access rights for creation (which makes
396
* sense as there is no service yet) as long as there are sufficient
397
* rights to the manager.
398
*/
399
SetLastError(0xdeadbeef);
400
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, 0, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
401
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
402
ok(svc_handle1 != NULL, "Could not create the service : %ld\n", GetLastError());
403
404
/* DeleteService however must have proper rights */
405
SetLastError(0xdeadbeef);
406
ret = DeleteService(svc_handle1);
407
ok(!ret, "Expected failure\n");
408
ok(GetLastError() == ERROR_ACCESS_DENIED,
409
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
410
411
/* Open the service with minimal rights for deletion.
412
* (Verified with 'SERVICE_ALL_ACCESS &~ DELETE')
413
*/
414
CloseServiceHandle(svc_handle1);
415
svc_handle1 = OpenServiceA(scm_handle, servicename, DELETE);
416
417
/* Now that we have the proper rights, we should be able to delete */
418
SetLastError(0xdeadbeef);
419
ret = DeleteService(svc_handle1);
420
ok(ret, "Expected success, got error %lu\n", GetLastError());
421
422
/* Service is marked for delete, but handle is still open. Try to open service again. */
423
svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
424
ok(svc_handle2 != NULL, "got %p, error %lu\n", svc_handle2, GetLastError());
425
CloseServiceHandle(svc_handle2);
426
427
CloseServiceHandle(svc_handle1);
428
CloseServiceHandle(scm_handle);
429
430
/* And a final NULL check */
431
SetLastError(0xdeadbeef);
432
ret = DeleteService(NULL);
433
ok(!ret, "Expected failure\n");
434
ok(GetLastError() == ERROR_INVALID_HANDLE,
435
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
436
}
437
438
static void test_get_displayname(void)
439
{
440
SC_HANDLE scm_handle, svc_handle;
441
BOOL ret;
442
CHAR displayname[4096];
443
WCHAR displaynameW[2048];
444
DWORD displaysize, tempsize, tempsizeW;
445
static const CHAR servicename[] = "winetest_displayname";
446
static const CHAR pathname[] = "we_dont_care.exe";
447
448
/* Having NULL for the size of the buffer will crash on W2K3 */
449
450
SetLastError(0xdeadbeef);
451
ret = GetServiceDisplayNameA(NULL, NULL, NULL, &displaysize);
452
ok(!ret, "Expected failure\n");
453
ok(GetLastError() == ERROR_INVALID_HANDLE,
454
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
455
456
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
457
458
SetLastError(0xdeadbeef);
459
ret = GetServiceDisplayNameA(scm_handle, NULL, NULL, &displaysize);
460
ok(!ret, "Expected failure\n");
461
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
462
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
463
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
464
465
SetLastError(0xdeadbeef);
466
displaysize = sizeof(displayname);
467
ret = GetServiceDisplayNameA(scm_handle, NULL, displayname, &displaysize);
468
ok(!ret, "Expected failure\n");
469
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
470
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
471
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
472
473
/* Test for nonexistent service */
474
SetLastError(0xdeadbeef);
475
displaysize = -1;
476
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", NULL, &displaysize);
477
ok(!ret, "Expected failure\n");
478
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
479
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
480
481
SetLastError(0xdeadbeef);
482
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", NULL, &displaysize);
483
ok(!ret, "Expected failure\n");
484
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
485
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
486
todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
487
488
displaysize = 15;
489
strcpy(displayname, "ABC");
490
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", displayname, &displaysize);
491
ok(!ret, "Expected failure\n");
492
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
493
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
494
todo_wine ok(displaysize == 15, "Service size expected 15, got %ld\n", displaysize);
495
ok(displayname[0] == 0, "Service name not empty\n");
496
497
displaysize = 15;
498
wcscpy(displaynameW, L"ABC");
499
ret = GetServiceDisplayNameW(scm_handle, L"Deadbeef", displaynameW, &displaysize);
500
ok(!ret, "Expected failure\n");
501
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
502
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
503
ok(displaysize == 15, "Service size expected 15, got %ld\n", displaysize);
504
ok(displaynameW[0] == 0, "Service name not empty\n");
505
506
displaysize = 0;
507
strcpy(displayname, "ABC");
508
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", displayname, &displaysize);
509
ok(!ret, "Expected failure\n");
510
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
511
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
512
todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
513
ok(displayname[0] == 'A', "Service name changed\n");
514
515
displaysize = 0;
516
wcscpy(displaynameW, L"ABC");
517
ret = GetServiceDisplayNameW(scm_handle, L"Deadbeef", displaynameW, &displaysize);
518
ok(!ret, "Expected failure\n");
519
ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
520
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
521
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
522
ok(displaynameW[0] == 'A', "Service name changed\n");
523
524
displaysize = 1;
525
strcpy(displayname, "ABC");
526
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", displayname, &displaysize);
527
ok(!ret, "Expected failure\n");
528
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
529
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
530
todo_wine ok(displaysize == 1, "Service size expected 1, got %ld\n", displaysize);
531
ok(displayname[0] == 0, "Service name not empty\n");
532
533
displaysize = 1;
534
wcscpy(displaynameW, L"ABC");
535
ret = GetServiceDisplayNameW(scm_handle, L"Deadbeef", displaynameW, &displaysize);
536
ok(!ret, "Expected failure\n");
537
ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
538
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
539
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
540
ok(displaynameW[0] == 'A', "Service name changed\n");
541
542
displaysize = 2;
543
strcpy(displayname, "ABC");
544
ret = GetServiceDisplayNameA(scm_handle, "Deadbeef", displayname, &displaysize);
545
ok(!ret, "Expected failure\n");
546
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
547
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
548
todo_wine ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
549
ok(displayname[0] == 0, "Service name not empty\n");
550
551
displaysize = 2;
552
wcscpy(displaynameW, L"ABC");
553
ret = GetServiceDisplayNameW(scm_handle, L"Deadbeef", displaynameW, &displaysize);
554
ok(!ret, "Expected failure\n");
555
ok(displaysize == 2, "Service size expected 2, got %ld\n", displaysize);
556
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
557
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
558
ok(displaynameW[0] == 0, "Service name not empty\n");
559
560
/* Check if 'Spooler' exists */
561
svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
562
if (!svc_handle)
563
{
564
skip("Spooler service doesn't exist\n");
565
CloseServiceHandle(scm_handle);
566
return;
567
}
568
CloseServiceHandle(svc_handle);
569
570
/* Retrieve the needed size for the buffer */
571
SetLastError(0xdeadbeef);
572
displaysize = -1;
573
ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
574
ok(!ret, "Expected failure\n");
575
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
576
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
577
tempsize = displaysize;
578
579
displaysize = 0;
580
ret = GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
581
ok(!ret, "Expected failure\n");
582
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
583
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
584
ok(displaysize == tempsize, "Buffer size mismatch (%ld vs %ld)\n", tempsize, displaysize);
585
586
/* Buffer is too small */
587
SetLastError(0xdeadbeef);
588
displaysize = (tempsize / 2);
589
ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
590
ok(!ret, "Expected failure\n");
591
ok(displaysize == tempsize, "Expected the needed buffersize\n");
592
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
593
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
594
595
/* First try with a buffer that should be big enough to hold
596
* the ANSI string (and terminating character). This succeeds on Windows
597
* although when asked (see above 2 tests) it will return twice the needed size.
598
*/
599
SetLastError(0xdeadbeef);
600
displaysize = (tempsize / 2) + 1;
601
ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
602
ok(ret, "Expected success, got error %lu\n", GetLastError());
603
ok(displaysize == ((tempsize / 2) + 1), "Expected no change for the needed buffer size\n");
604
605
/* Now with the original returned size */
606
SetLastError(0xdeadbeef);
607
displaysize = tempsize;
608
ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
609
ok(ret, "Expected success, got error %lu\n", GetLastError());
610
ok(displaysize == tempsize, "Expected no change for the needed buffer size\n");
611
612
/* And with a bigger than needed buffer */
613
SetLastError(0xdeadbeef);
614
displaysize = tempsize * 2;
615
ret = GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
616
ok(ret, "Expected success, got error %lu\n", GetLastError());
617
/* Test that shows that if the buffersize is enough, it's not changed */
618
ok(displaysize == tempsize * 2, "Expected no change for the needed buffer size\n");
619
ok(strlen(displayname) == tempsize/2,
620
"Expected the buffer to be twice the length of the string\n") ;
621
622
/* Do the buffer(size) tests also for GetServiceDisplayNameW */
623
SetLastError(0xdeadbeef);
624
displaysize = -1;
625
ret = GetServiceDisplayNameW(scm_handle, L"Spooler", NULL, &displaysize);
626
ok(!ret, "Expected failure\n");
627
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
628
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
629
630
/* Buffer is too small */
631
SetLastError(0xdeadbeef);
632
tempsizeW = displaysize;
633
displaysize = tempsizeW / 2;
634
ret = GetServiceDisplayNameW(scm_handle, L"Spooler", displaynameW, &displaysize);
635
ok(!ret, "Expected failure\n");
636
ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
637
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
638
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
639
640
/* Now with the original returned size */
641
SetLastError(0xdeadbeef);
642
displaysize = tempsizeW;
643
ret = GetServiceDisplayNameW(scm_handle, L"Spooler", displaynameW, &displaysize);
644
ok(!ret, "Expected failure\n");
645
ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
646
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
647
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
648
649
/* And with a bigger than needed buffer */
650
SetLastError(0xdeadbeef);
651
displaysize = tempsizeW + 1; /* This caters for the null terminating character */
652
ret = GetServiceDisplayNameW(scm_handle, L"Spooler", displaynameW, &displaysize);
653
ok(ret, "Expected success, got error %lu\n", GetLastError());
654
ok(displaysize == tempsizeW, "Expected the needed buffersize\n");
655
ok(lstrlenW(displaynameW) == displaysize,
656
"Expected the buffer to be the length of the string\n") ;
657
ok(tempsize / 2 == tempsizeW,
658
"Expected the needed buffersize (in bytes) to be the same for the A and W call\n");
659
660
CloseServiceHandle(scm_handle);
661
662
/* Test for a service without a displayname (which is valid). This should return
663
* the servicename itself.
664
*/
665
SetLastError(0xdeadbeef);
666
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
667
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
668
{
669
skip("Not enough rights to get a handle to the manager\n");
670
return;
671
}
672
673
SetLastError(0xdeadbeef);
674
svc_handle = CreateServiceA(scm_handle, servicename, NULL, DELETE,
675
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
676
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
677
ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
678
if (!svc_handle)
679
{
680
CloseServiceHandle(scm_handle);
681
return;
682
}
683
684
/* Retrieve the needed size for the buffer */
685
SetLastError(0xdeadbeef);
686
displaysize = -1;
687
ret = GetServiceDisplayNameA(scm_handle, servicename, NULL, &displaysize);
688
ok(!ret, "Expected failure\n");
689
ok(displaysize == strlen(servicename) * 2,
690
"Expected the displaysize to be twice the size of the servicename\n");
691
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
692
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
693
694
/* Buffer is too small */
695
SetLastError(0xdeadbeef);
696
tempsize = displaysize;
697
displaysize = (tempsize / 2);
698
ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
699
ok(!ret, "Expected failure\n");
700
ok(displaysize == tempsize, "Expected the needed buffersize\n");
701
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
702
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
703
704
/* Get the displayname */
705
SetLastError(0xdeadbeef);
706
ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
707
ok(ret, "Expected success, got error %lu\n", GetLastError());
708
ok(!lstrcmpiA(displayname, servicename),
709
"Expected displayname to be %s, got %s\n", servicename, displayname);
710
711
/* Delete the service */
712
ret = DeleteService(svc_handle);
713
ok(ret, "Expected success (err=%ld)\n", GetLastError());
714
715
CloseServiceHandle(svc_handle);
716
717
/* Test empty DisplayName */
718
do
719
{
720
SetLastError(0xdeadbeef);
721
svc_handle = CreateServiceA(scm_handle, servicename, "", DELETE,
722
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
723
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
724
} while (!svc_handle && GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE);
725
ok(svc_handle != NULL, "CreateService() error %lu\n", GetLastError());
726
727
strcpy(displayname, "deadbeef");
728
displaysize = sizeof(displayname);
729
SetLastError(0xdeadbeef);
730
ret = GetServiceDisplayNameA(scm_handle, servicename, displayname, &displaysize);
731
ok(ret, "GetServiceDisplayName() error %lu\n", GetLastError());
732
ok(!lstrcmpiA(displayname, servicename), "got \"%s\"\n", displayname);
733
734
ret = DeleteService(svc_handle);
735
ok(ret, "DeleteService() error %lu\n", GetLastError());
736
737
CloseServiceHandle(svc_handle);
738
CloseServiceHandle(scm_handle);
739
}
740
741
static void test_get_servicekeyname(void)
742
{
743
SC_HANDLE scm_handle, svc_handle;
744
CHAR servicename[4096];
745
CHAR displayname[4096];
746
WCHAR servicenameW[4096];
747
WCHAR displaynameW[4096];
748
DWORD servicesize, displaysize, tempsize;
749
BOOL ret;
750
751
/* Having NULL for the size of the buffer will crash on W2K3 */
752
753
SetLastError(0xdeadbeef);
754
ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
755
ok(!ret, "Expected failure\n");
756
ok(GetLastError() == ERROR_INVALID_HANDLE,
757
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
758
759
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
760
761
servicesize = 200;
762
SetLastError(0xdeadbeef);
763
ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
764
ok(!ret, "Expected failure\n");
765
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
766
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
767
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
768
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
769
770
/* Valid handle and buffer but no displayname */
771
servicesize = 200;
772
SetLastError(0xdeadbeef);
773
ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
774
ok(!ret, "Expected failure\n");
775
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
776
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
777
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
778
todo_wine ok(servicesize == 200, "Service size expected 1, got %ld\n", servicesize);
779
780
/* Test for nonexistent displayname */
781
SetLastError(0xdeadbeef);
782
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", NULL, &servicesize);
783
ok(!ret, "Expected failure\n");
784
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
785
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
786
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
787
788
servicesize = 15;
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 %ld\n", GetLastError());
794
todo_wine ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
795
ok(servicename[0] == 0, "Service name not empty\n");
796
797
servicesize = 15;
798
wcscpy(servicenameW, L"ABC");
799
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
800
ok(!ret, "Expected failure\n");
801
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
802
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
803
ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
804
ok(servicenameW[0] == 0, "Service name not empty\n");
805
806
servicesize = 0;
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 %ld\n", GetLastError());
812
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
813
ok(servicename[0] == 'A', "Service name changed\n");
814
815
servicesize = 0;
816
wcscpy(servicenameW, L"ABC");
817
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
818
ok(!ret, "Expected failure\n");
819
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
820
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
821
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
822
ok(servicenameW[0] == 'A', "Service name changed\n");
823
824
servicesize = 1;
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 %ld\n", GetLastError());
830
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
831
ok(servicename[0] == 0, "Service name not empty\n");
832
833
servicesize = 1;
834
wcscpy(servicenameW, L"ABC");
835
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
836
ok(!ret, "Expected failure\n");
837
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
838
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
839
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
840
ok(servicenameW[0] == 'A', "Service name changed\n");
841
842
servicesize = 2;
843
strcpy(servicename, "ABC");
844
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", servicename, &servicesize);
845
ok(!ret, "Expected failure\n");
846
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
847
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
848
todo_wine ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
849
ok(servicename[0] == 0, "Service name not empty\n");
850
851
servicesize = 2;
852
wcscpy(servicenameW, L"ABC");
853
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
854
ok(!ret, "Expected failure\n");
855
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
856
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
857
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
858
ok(servicenameW[0] == 0, "Service name not empty\n");
859
860
/* Check if 'Spooler' exists */
861
svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
862
if (!svc_handle)
863
{
864
skip("Spooler service doesn't exist\n");
865
CloseServiceHandle(scm_handle);
866
return;
867
}
868
CloseServiceHandle(svc_handle);
869
870
/* Get the displayname for the 'Spooler' service */
871
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
872
GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
873
874
/* Retrieve the needed size for the buffer */
875
SetLastError(0xdeadbeef);
876
servicesize = 0;
877
ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
878
ok(!ret, "Expected failure\n");
879
if (strcmp(displayname, "Print Spooler") != 0 &&
880
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
881
{
882
win_skip("GetServiceKeyName() does not support localized display names: %s\n", displayname); /* Windows 7 */
883
CloseServiceHandle(scm_handle);
884
return; /* All the tests that follow will fail too */
885
}
886
887
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
888
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
889
890
/* Valid call with the correct buffersize */
891
SetLastError(0xdeadbeef);
892
tempsize = servicesize;
893
servicesize *= 2;
894
ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
895
ok(ret, "Expected success, got error %lu\n", GetLastError());
896
if (ret)
897
{
898
ok(strlen(servicename) == tempsize/2,
899
"Expected the buffer to be twice the length of the string\n") ;
900
ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
901
ok(servicesize == (tempsize * 2),
902
"Expected servicesize not to change if buffer not insufficient\n") ;
903
}
904
905
MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
906
SetLastError(0xdeadbeef);
907
servicesize *= 2;
908
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
909
ok(ret, "Expected success, got error %lu\n", GetLastError());
910
if (ret)
911
{
912
ok(strlen(servicename) == tempsize/2,
913
"Expected the buffer to be twice the length of the string\n") ;
914
ok(servicesize == lstrlenW(servicenameW),
915
"Expected servicesize not to change if buffer not insufficient\n") ;
916
}
917
918
SetLastError(0xdeadbeef);
919
servicesize = 3;
920
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
921
ok(!ret, "Expected failure\n");
922
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
923
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
924
ok(servicenameW[0] == 0, "Buffer not empty\n");
925
926
CloseServiceHandle(scm_handle);
927
}
928
929
static void test_query_svc(void)
930
{
931
SC_HANDLE scm_handle, svc_handle;
932
BOOL ret;
933
SERVICE_STATUS status;
934
SERVICE_STATUS_PROCESS *statusproc;
935
DWORD bufsize, needed;
936
937
/* All NULL or wrong */
938
SetLastError(0xdeadbeef);
939
ret = QueryServiceStatus(NULL, NULL);
940
ok(!ret, "Expected failure\n");
941
ok(GetLastError() == ERROR_INVALID_HANDLE,
942
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
943
944
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
945
946
/* Check if 'Spooler' exists.
947
* Open with not enough rights to query the status.
948
*/
949
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
950
if (!svc_handle)
951
{
952
skip("Spooler service doesn't exist\n");
953
CloseServiceHandle(scm_handle);
954
return;
955
}
956
957
SetLastError(0xdeadbeef);
958
ret = QueryServiceStatus(svc_handle, NULL);
959
ok(!ret, "Expected failure\n");
960
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
961
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
962
"Unexpected last error %ld\n", GetLastError());
963
964
SetLastError(0xdeadbeef);
965
ret = QueryServiceStatus(svc_handle, &status);
966
ok(!ret, "Expected failure\n");
967
ok(GetLastError() == ERROR_ACCESS_DENIED,
968
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
969
970
/* Open the service with just enough rights.
971
* (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
972
*/
973
CloseServiceHandle(svc_handle);
974
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
975
976
SetLastError(0xdeadbeef);
977
ret = QueryServiceStatus(svc_handle, &status);
978
ok(ret, "Expected success, got error %lu\n", GetLastError());
979
980
CloseServiceHandle(svc_handle);
981
982
/* More or less the same tests for QueryServiceStatusEx */
983
if (!pQueryServiceStatusEx)
984
{
985
win_skip( "QueryServiceStatusEx not available\n" );
986
CloseServiceHandle(scm_handle);
987
return;
988
}
989
990
/* Open service with not enough rights to query the status */
991
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
992
993
/* All NULL or wrong, this proves that info level is checked first */
994
SetLastError(0xdeadbeef);
995
ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
996
ok(!ret, "Expected failure\n");
997
ok(GetLastError() == ERROR_INVALID_LEVEL,
998
"Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
999
1000
/* Passing a NULL parameter for the needed buffer size
1001
* will crash on anything but NT4.
1002
*/
1003
1004
/* Only info level is correct. It looks like the buffer/size is checked second */
1005
SetLastError(0xdeadbeef);
1006
ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1007
/* NT4 checks the handle first */
1008
if (GetLastError() != ERROR_INVALID_HANDLE)
1009
{
1010
ok(!ret, "Expected failure\n");
1011
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1012
"Needed buffersize is wrong : %ld\n", needed);
1013
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1014
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1015
}
1016
1017
/* Pass a correct buffer and buffersize but a NULL handle */
1018
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1019
bufsize = needed;
1020
SetLastError(0xdeadbeef);
1021
ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1022
ok(!ret, "Expected failure\n");
1023
ok(GetLastError() == ERROR_INVALID_HANDLE,
1024
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1025
free(statusproc);
1026
1027
/* Correct handle and info level */
1028
SetLastError(0xdeadbeef);
1029
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1030
/* NT4 doesn't return the needed size */
1031
if (GetLastError() != ERROR_INVALID_PARAMETER)
1032
{
1033
ok(!ret, "Expected failure\n");
1034
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1035
"Needed buffersize is wrong : %ld\n", needed);
1036
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1037
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1038
}
1039
1040
/* All parameters are OK but we don't have enough rights */
1041
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1042
bufsize = sizeof(SERVICE_STATUS_PROCESS);
1043
SetLastError(0xdeadbeef);
1044
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1045
ok(!ret, "Expected failure\n");
1046
ok(GetLastError() == ERROR_ACCESS_DENIED,
1047
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1048
free(statusproc);
1049
1050
/* Open the service with just enough rights. */
1051
CloseServiceHandle(svc_handle);
1052
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
1053
1054
/* Everything should be fine now. */
1055
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1056
bufsize = sizeof(SERVICE_STATUS_PROCESS);
1057
SetLastError(0xdeadbeef);
1058
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1059
ok(ret, "Expected success, got error %lu\n", GetLastError());
1060
if (statusproc->dwCurrentState == SERVICE_RUNNING)
1061
ok(statusproc->dwProcessId != 0,
1062
"Expect a process id for this running service\n");
1063
else
1064
ok(statusproc->dwProcessId == 0,
1065
"Expect no process id for this stopped service\n");
1066
1067
/* same call with null needed pointer */
1068
SetLastError(0xdeadbeef);
1069
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1070
ok(!ret, "Expected failure\n");
1071
ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ ||
1072
GetLastError() == ERROR_INVALID_ADDRESS, "got %ld\n", GetLastError());
1073
1074
free(statusproc);
1075
1076
CloseServiceHandle(svc_handle);
1077
CloseServiceHandle(scm_handle);
1078
}
1079
1080
static BOOL test_enum_svc(int attempt)
1081
{
1082
SC_HANDLE scm_handle;
1083
BOOL ret, alldone = FALSE;
1084
DWORD bufsize, needed, returned, resume;
1085
DWORD neededA, returnedA;
1086
DWORD tempneeded, tempreturned, missing;
1087
DWORD servicecountactive, servicecountinactive;
1088
ENUM_SERVICE_STATUSA *servicesA;
1089
ENUM_SERVICE_STATUSW *services;
1090
UINT i;
1091
1092
/* All NULL or wrong */
1093
SetLastError(0xdeadbeef);
1094
ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1095
ok(!ret, "Expected failure\n");
1096
ok(GetLastError() == ERROR_INVALID_HANDLE,
1097
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1098
1099
SetLastError(0xdeadbeef);
1100
ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1101
ok(!ret, "Expected failure\n");
1102
ok(GetLastError() == ERROR_INVALID_HANDLE,
1103
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1104
1105
/* Open the service control manager with not enough rights at first */
1106
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1107
1108
/* Valid handle but rest is still NULL or wrong */
1109
SetLastError(0xdeadbeef);
1110
ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1111
ok(!ret, "Expected failure\n");
1112
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1113
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1114
"Unexpected last error %ld\n", GetLastError());
1115
1116
SetLastError(0xdeadbeef);
1117
ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1118
ok(!ret, "Expected failure\n");
1119
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1120
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1121
"Unexpected last error %ld\n", GetLastError());
1122
1123
/* Don't specify the two required pointers */
1124
returned = 0xdeadbeef;
1125
SetLastError(0xdeadbeef);
1126
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1127
ok(!ret, "Expected failure\n");
1128
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1129
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1130
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1131
"Unexpected last error %ld\n", GetLastError());
1132
1133
returned = 0xdeadbeef;
1134
SetLastError(0xdeadbeef);
1135
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1136
ok(!ret, "Expected failure\n");
1137
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1138
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1139
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1140
"Unexpected last error %ld\n", GetLastError());
1141
1142
/* Don't specify the two required pointers */
1143
needed = 0xdeadbeef;
1144
SetLastError(0xdeadbeef);
1145
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1146
ok(!ret, "Expected failure\n");
1147
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1148
"Expected no change to the needed buffer variable\n");
1149
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1150
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1151
"Unexpected last error %ld\n", GetLastError());
1152
1153
needed = 0xdeadbeef;
1154
SetLastError(0xdeadbeef);
1155
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1156
ok(!ret, "Expected failure\n");
1157
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1158
"Expected no change to the needed buffer variable\n");
1159
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1160
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1161
"Unexpected last error %ld\n", GetLastError());
1162
1163
/* No valid servicetype and servicestate */
1164
needed = 0xdeadbeef;
1165
returned = 0xdeadbeef;
1166
SetLastError(0xdeadbeef);
1167
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1168
ok(!ret, "Expected failure\n");
1169
ok(needed == 0 || broken(needed != 0), /* nt4 */
1170
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1171
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1172
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1173
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1174
1175
needed = 0xdeadbeef;
1176
returned = 0xdeadbeef;
1177
SetLastError(0xdeadbeef);
1178
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1179
ok(!ret, "Expected failure\n");
1180
ok(needed == 0 || broken(needed != 0), /* nt4 */
1181
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1182
ok(returned == 0 || broken(returned != 0), /* nt4 */
1183
"Expected number of services to be set to 0, got %ld\n", returned);
1184
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1185
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1186
1187
/* No valid servicestate */
1188
needed = 0xdeadbeef;
1189
returned = 0xdeadbeef;
1190
SetLastError(0xdeadbeef);
1191
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1192
ok(!ret, "Expected failure\n");
1193
ok(needed == 0 || broken(needed != 0), /* nt4 */
1194
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1195
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1196
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1197
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1198
1199
needed = 0xdeadbeef;
1200
returned = 0xdeadbeef;
1201
SetLastError(0xdeadbeef);
1202
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1203
ok(!ret, "Expected failure\n");
1204
ok(needed == 0 || broken(needed != 0), /* nt4 */
1205
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1206
ok(returned == 0 || broken(returned != 0), /* nt4 */
1207
"Expected number of services to be set to 0, got %ld\n", returned);
1208
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1209
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1210
1211
/* No valid servicetype */
1212
needed = 0xdeadbeef;
1213
returned = 0xdeadbeef;
1214
SetLastError(0xdeadbeef);
1215
ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1216
ok(!ret, "Expected failure\n");
1217
ok(needed == 0 || broken(needed != 0), /* nt4 */
1218
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1219
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1220
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1221
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1222
1223
needed = 0xdeadbeef;
1224
returned = 0xdeadbeef;
1225
SetLastError(0xdeadbeef);
1226
ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1227
ok(!ret, "Expected failure\n");
1228
ok(needed == 0 || broken(needed != 0), /* nt4 */
1229
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1230
ok(returned == 0 || broken(returned != 0), /* nt4 */
1231
"Expected number of services to be set to 0, got %ld\n", returned);
1232
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1233
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1234
1235
/* All parameters are correct but our access rights are wrong */
1236
needed = 0xdeadbeef;
1237
returned = 0xdeadbeef;
1238
SetLastError(0xdeadbeef);
1239
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1240
ok(!ret, "Expected failure\n");
1241
ok(needed == 0 || broken(needed != 0), /* nt4 */
1242
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1243
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1244
ok(GetLastError() == ERROR_ACCESS_DENIED,
1245
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1246
1247
needed = 0xdeadbeef;
1248
returned = 0xdeadbeef;
1249
SetLastError(0xdeadbeef);
1250
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1251
ok(!ret, "Expected failure\n");
1252
ok(needed == 0 || broken(needed != 0), /* nt4 */
1253
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1254
ok(returned == 0 || broken(returned != 0), /* nt4 */
1255
"Expected number of services to be set to 0, got %ld\n", returned);
1256
ok(GetLastError() == ERROR_ACCESS_DENIED,
1257
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1258
1259
/* Open the service control manager with the needed rights */
1260
CloseServiceHandle(scm_handle);
1261
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1262
1263
/* All parameters are correct. Request the needed buffer size */
1264
needed = 0xdeadbeef;
1265
returned = 0xdeadbeef;
1266
SetLastError(0xdeadbeef);
1267
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1268
ok(!ret, "Expected failure\n");
1269
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1270
ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1271
ok(GetLastError() == ERROR_MORE_DATA,
1272
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1273
1274
/* Test to show we get the same needed buffer size for the A-call */
1275
neededA = 0xdeadbeef;
1276
returnedA = 0xdeadbeef;
1277
SetLastError(0xdeadbeef);
1278
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededA, &returnedA, NULL);
1279
ok(!ret, "Expected failure\n");
1280
ok(GetLastError() == ERROR_MORE_DATA,
1281
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1282
ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1283
ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1284
if (neededA != needed && attempt)
1285
goto retry; /* service start|stop race condition */
1286
ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1287
1288
/* Store the needed bytes */
1289
tempneeded = needed;
1290
1291
/* Allocate the correct needed bytes */
1292
services = malloc(needed);
1293
bufsize = needed;
1294
needed = 0xdeadbeef;
1295
returned = 0xdeadbeef;
1296
SetLastError(0xdeadbeef);
1297
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1298
services, bufsize, &needed, &returned, NULL);
1299
free(services);
1300
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1301
goto retry; /* service start race condition */
1302
ok(ret, "Expected success, got error %lu\n", GetLastError());
1303
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1304
ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1305
1306
/* Store the number of returned services */
1307
tempreturned = returned;
1308
1309
servicesA = malloc(neededA);
1310
bufsize = neededA;
1311
neededA = 0xdeadbeef;
1312
returnedA = 0xdeadbeef;
1313
SetLastError(0xdeadbeef);
1314
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1315
servicesA, bufsize, &neededA, &returnedA, NULL);
1316
free(servicesA);
1317
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1318
goto retry; /* service start race condition */
1319
if (!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY && GetACP() == CP_UTF8)
1320
win_skip("Skipping some tests due to EnumServicesStatusA()'s broken UTF-8 support\n");
1321
else
1322
{
1323
ok(ret, "Expected success, got error %lu\n", GetLastError());
1324
ok(neededA == 0, "Expected needed buffer to be 0 as we are done\n");
1325
ok(returnedA != 0xdeadbeef && returnedA > 0, "Expected some returned services\n");
1326
}
1327
1328
/* Allocate less than the needed bytes and don't specify a resume handle.
1329
* More than one service will be missing because of the space needed for
1330
* the strings.
1331
*/
1332
services = malloc(tempneeded);
1333
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1334
needed = 0xdeadbeef;
1335
returned = 0xdeadbeef;
1336
SetLastError(0xdeadbeef);
1337
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1338
services, bufsize, &needed, &returned, NULL);
1339
if (ret && needed == 0 && attempt)
1340
{
1341
free(services);
1342
goto retry; /* service stop race condition */
1343
}
1344
ok(!ret, "Expected failure\n");
1345
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1346
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1347
/* Experiments show bufsize + needed < tempneeded which proves the needed
1348
* buffer size is an approximation. So it's best not to probe more.
1349
*/
1350
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1351
ok(GetLastError() == ERROR_MORE_DATA,
1352
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1353
1354
/* Allocate less than the needed bytes, this time with a correct resume handle */
1355
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1356
needed = 0xdeadbeef;
1357
returned = 0xdeadbeef;
1358
resume = 0;
1359
SetLastError(0xdeadbeef);
1360
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1361
services, bufsize, &needed, &returned, &resume);
1362
if (ret && needed == 0 && attempt)
1363
{
1364
free(services);
1365
goto retry; /* service stop race condition */
1366
}
1367
ok(!ret, "Expected failure\n");
1368
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services, got %lx\n", needed);
1369
todo_wine ok(needed < tempneeded, "Expected < %lu bytes needed for the remaining services, got %lu\n", tempneeded, needed);
1370
ok(returned < tempreturned, "Expected < %lu remaining services, got %lu\n", tempreturned, returned);
1371
todo_wine ok(resume, "Expected a resume handle\n");
1372
ok(GetLastError() == ERROR_MORE_DATA,
1373
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1374
1375
/* Fetch the missing services but pass a bigger buffer size */
1376
missing = tempreturned - returned;
1377
bufsize = tempneeded;
1378
needed = 0xdeadbeef;
1379
returned = 0xdeadbeef;
1380
SetLastError(0xdeadbeef);
1381
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1382
services, bufsize, &needed, &returned, &resume);
1383
free(services);
1384
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1385
goto retry; /* service start race condition */
1386
ok(ret, "Expected success, got error %lu\n", GetLastError());
1387
ok(needed == 0, "Expected 0 needed bytes as we are done, got %lu\n", needed);
1388
if (returned < missing && strcmp(winetest_platform, "wine") && attempt)
1389
goto retry; /* service stop race condition */
1390
todo_wine ok(returned == missing, "Expected %lu remaining services, got %lu\n", missing, returned);
1391
ok(resume == 0, "Expected the resume handle to be 0\n");
1392
1393
/* See if things add up */
1394
1395
/* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1396
* and doesn't count the others as inactive. This means that Vista could
1397
* show a total that is greater than the sum of active and inactive
1398
* drivers.
1399
* The number of active and inactive drivers is greatly influenced by the
1400
* time when tests are run, immediately after boot or later for example.
1401
*
1402
* Both reasons make calculations for drivers not so useful
1403
*/
1404
1405
/* Get the number of active win32 services */
1406
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
1407
&needed, &returned, NULL);
1408
services = malloc(needed);
1409
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE,
1410
services, needed, &needed, &returned, NULL);
1411
free(services);
1412
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1413
goto retry; /* service start race condition */
1414
1415
servicecountactive = returned;
1416
1417
/* Get the number of inactive win32 services */
1418
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
1419
&needed, &returned, NULL);
1420
services = malloc(needed);
1421
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE,
1422
services, needed, &needed, &returned, NULL);
1423
free(services);
1424
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1425
goto retry; /* service start race condition */
1426
1427
servicecountinactive = returned;
1428
1429
/* Get the number of win32 services */
1430
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
1431
&needed, &returned, NULL);
1432
services = malloc(needed);
1433
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1434
services, needed, &needed, &returned, NULL);
1435
free(services);
1436
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1437
goto retry; /* service start race condition */
1438
1439
/* Check if total is the same as active and inactive win32 services */
1440
if (returned != servicecountactive + servicecountinactive && attempt)
1441
goto retry; /* service start|stop race condition */
1442
ok(returned == servicecountactive + servicecountinactive,
1443
"Expected service count %ld == %ld + %ld\n",
1444
returned, servicecountactive, servicecountinactive);
1445
1446
/* Get all drivers and services
1447
*
1448
* Fetch the status of the last call as failing could make the following tests crash
1449
* on Wine (we don't return anything yet).
1450
*/
1451
EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1452
NULL, 0, &needed, &returned, NULL);
1453
services = malloc(needed);
1454
ret = EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1455
services, needed, &needed, &returned, NULL);
1456
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1457
goto retry; /* service start race condition */
1458
ok(ret, "Expected success %lu\n", GetLastError());
1459
1460
/* Loop through all those returned drivers and services */
1461
for (i = 0; ret && i < returned; i++)
1462
{
1463
SERVICE_STATUS status = services[i].ServiceStatus;
1464
1465
/* lpServiceName and lpDisplayName should always be filled */
1466
ok(services[i].lpServiceName[0], "Expected a service name\n");
1467
ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n");
1468
1469
/* Decrement the counters to see if the functions calls return the same
1470
* numbers as the contents of these structures.
1471
*/
1472
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1473
{
1474
switch (status.dwCurrentState)
1475
{
1476
case SERVICE_START_PENDING:
1477
case SERVICE_STOP_PENDING:
1478
case SERVICE_PAUSE_PENDING:
1479
case SERVICE_PAUSED:
1480
case SERVICE_CONTINUE_PENDING:
1481
trace("Got state %lx for service %s\n", status.dwCurrentState,
1482
wine_dbgstr_w(services[i].lpServiceName));
1483
/* fall through */
1484
1485
case SERVICE_RUNNING:
1486
servicecountactive--;
1487
break;
1488
1489
case SERVICE_STOPPED:
1490
servicecountinactive--;
1491
break;
1492
1493
default:
1494
ok(0, "Got unknown state %lx for service %s\n",
1495
status.dwCurrentState, wine_dbgstr_w(services[i].lpServiceName));
1496
break;
1497
}
1498
}
1499
}
1500
free(services);
1501
1502
if ((servicecountactive || servicecountinactive) && attempt)
1503
goto retry; /* service start|stop race condition */
1504
ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1505
ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1506
1507
alldone = TRUE;
1508
1509
retry:
1510
CloseServiceHandle(scm_handle);
1511
return alldone;
1512
}
1513
1514
static BOOL test_enum_svc_ex(int attempt)
1515
{
1516
SC_HANDLE scm_handle;
1517
BOOL ret, alldone = FALSE;
1518
DWORD bufsize, needed, returned, resume;
1519
DWORD neededA, returnedA;
1520
DWORD tempneeded, tempreturned, missing;
1521
DWORD servicecountactive, servicecountinactive;
1522
ENUM_SERVICE_STATUSW *services;
1523
ENUM_SERVICE_STATUS_PROCESSW *exservices;
1524
UINT i;
1525
1526
/* More or less the same for EnumServicesStatusExA */
1527
if (!pEnumServicesStatusExA)
1528
{
1529
win_skip( "EnumServicesStatusExA not available\n" );
1530
return TRUE;
1531
}
1532
1533
/* All NULL or wrong */
1534
SetLastError(0xdeadbeef);
1535
ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1536
ok(!ret, "Expected failure\n");
1537
ok(GetLastError() == ERROR_INVALID_LEVEL,
1538
"Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
1539
1540
/* All NULL or wrong, just the info level is correct */
1541
SetLastError(0xdeadbeef);
1542
ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1543
ok(!ret, "Expected failure\n");
1544
ok(GetLastError() == ERROR_INVALID_HANDLE,
1545
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1546
1547
/* Open the service control manager with not enough rights at first */
1548
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1549
1550
/* Valid handle and info level but rest is still NULL or wrong */
1551
SetLastError(0xdeadbeef);
1552
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1553
ok(!ret, "Expected failure\n");
1554
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1555
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1556
"Unexpected last error %ld\n", GetLastError());
1557
1558
/* Don't specify the two required pointers */
1559
needed = 0xdeadbeef;
1560
SetLastError(0xdeadbeef);
1561
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1562
ok(!ret, "Expected failure\n");
1563
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1564
"Expected no change to the needed buffer variable\n");
1565
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1566
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1567
"Unexpected last error %ld\n", GetLastError());
1568
1569
/* Don't specify the two required pointers */
1570
returned = 0xdeadbeef;
1571
SetLastError(0xdeadbeef);
1572
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1573
ok(!ret, "Expected failure\n");
1574
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1575
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1576
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1577
"Unexpected last error %ld\n", GetLastError());
1578
1579
/* No valid servicetype and servicestate */
1580
needed = 0xdeadbeef;
1581
returned = 0xdeadbeef;
1582
SetLastError(0xdeadbeef);
1583
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1584
ok(!ret, "Expected failure\n");
1585
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1586
ok(needed == 0 || broken(needed != 0), /* nt4 */
1587
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1588
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1589
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1590
1591
/* No valid servicestate */
1592
needed = 0xdeadbeef;
1593
returned = 0xdeadbeef;
1594
SetLastError(0xdeadbeef);
1595
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1596
&needed, &returned, NULL, NULL);
1597
ok(!ret, "Expected failure\n");
1598
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1599
ok(needed == 0 || broken(needed != 0), /* nt4 */
1600
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1601
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1602
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1603
1604
/* No valid servicetype */
1605
needed = 0xdeadbeef;
1606
returned = 0xdeadbeef;
1607
SetLastError(0xdeadbeef);
1608
ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1609
&needed, &returned, NULL, NULL);
1610
ok(!ret, "Expected failure\n");
1611
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1612
ok(needed == 0 || broken(needed != 0), /* nt4 */
1613
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1614
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1615
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1616
1617
/* No valid servicetype and servicestate and unknown service group */
1618
needed = 0xdeadbeef;
1619
returned = 0xdeadbeef;
1620
SetLastError(0xdeadbeef);
1621
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1622
&returned, NULL, "deadbeef_group");
1623
ok(!ret, "Expected failure\n");
1624
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1625
ok(needed == 0 || broken(needed != 0), /* nt4 */
1626
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1627
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1628
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1629
1630
/* All parameters are correct but our access rights are wrong */
1631
needed = 0xdeadbeef;
1632
returned = 0xdeadbeef;
1633
SetLastError(0xdeadbeef);
1634
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1635
NULL, 0, &needed, &returned, NULL, NULL);
1636
ok(!ret, "Expected failure\n");
1637
ok(needed == 0 || broken(needed != 0), /* nt4 */
1638
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1639
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1640
ok(GetLastError() == ERROR_ACCESS_DENIED,
1641
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1642
1643
/* All parameters are correct, access rights are wrong but the
1644
* group name won't be checked yet.
1645
*/
1646
needed = 0xdeadbeef;
1647
returned = 0xdeadbeef;
1648
SetLastError(0xdeadbeef);
1649
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1650
NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1651
ok(!ret, "Expected failure\n");
1652
ok(needed == 0 || broken(needed != 0), /* nt4 */
1653
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1654
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1655
ok(GetLastError() == ERROR_ACCESS_DENIED,
1656
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1657
1658
/* Open the service control manager with the needed rights */
1659
CloseServiceHandle(scm_handle);
1660
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1661
1662
/* All parameters are correct and the group will be checked */
1663
needed = 0xdeadbeef;
1664
returned = 0xdeadbeef;
1665
SetLastError(0xdeadbeef);
1666
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1667
NULL, 0, &needed, &returned, NULL, L"deadbeef_group");
1668
ok(!ret, "Expected failure\n");
1669
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1670
ok(needed == 0, "Expected needed buffer size to be set to 0, got %ld\n", needed);
1671
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
1672
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
1673
1674
/* TODO: Create a test that makes sure we enumerate all services that don't
1675
* belong to a group. (specifying "").
1676
*/
1677
1678
/* All parameters are correct. Request the needed buffer size */
1679
needed = 0xdeadbeef;
1680
returned = 0xdeadbeef;
1681
SetLastError(0xdeadbeef);
1682
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1683
NULL, 0, &needed, &returned, NULL, NULL);
1684
ok(!ret, "Expected failure\n");
1685
ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1686
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1687
ok(GetLastError() == ERROR_MORE_DATA,
1688
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1689
1690
/* Test to show we get the same needed buffer size for the A-call */
1691
neededA = 0xdeadbeef;
1692
returnedA = 0xdeadbeef;
1693
SetLastError(0xdeadbeef);
1694
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1695
NULL, 0, &neededA, &returnedA, NULL, NULL);
1696
ok(!ret, "Expected failure\n");
1697
ok(GetLastError() == ERROR_MORE_DATA,
1698
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1699
ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1700
ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1701
if (neededA != needed && attempt)
1702
goto retry; /* service start|stop race condition */
1703
ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1704
ok(GetLastError() == ERROR_MORE_DATA,
1705
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1706
1707
/* Store the needed bytes */
1708
tempneeded = needed;
1709
1710
/* Show the Ex call returns the same service count as the regular enum */
1711
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1712
NULL, 0, &needed, &returned, NULL);
1713
services = malloc(needed);
1714
returned = 0xdeadbeef;
1715
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1716
services, needed, &needed, &returned, NULL);
1717
free(services);
1718
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1719
goto retry; /* service start race condition */
1720
ok(ret, "Expected success, got error %lu\n", GetLastError());
1721
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1722
ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1723
1724
/* Store the number of returned services */
1725
tempreturned = returned;
1726
1727
/* Allocate the correct needed bytes */
1728
exservices = malloc(tempneeded);
1729
bufsize = tempneeded;
1730
needed = 0xdeadbeef;
1731
returned = 0xdeadbeef;
1732
SetLastError(0xdeadbeef);
1733
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1734
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1735
free(exservices);
1736
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1737
goto retry; /* service start race condition */
1738
ok(ret, "Expected success, got error %lu\n", GetLastError());
1739
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1740
ok(returned == tempreturned, "Expected the same number of service from this function\n");
1741
1742
/* Store the number of returned services */
1743
tempreturned = returned;
1744
1745
/* Allocate less than the needed bytes and don't specify a resume handle.
1746
* More than one service will be missing because of the space needed for
1747
* the strings.
1748
*/
1749
exservices = malloc(tempneeded);
1750
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1751
needed = 0xdeadbeef;
1752
returned = 0xdeadbeef;
1753
SetLastError(0xdeadbeef);
1754
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1755
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1756
if (ret && needed == 0 && attempt)
1757
{
1758
free(exservices);
1759
goto retry; /* service stop race condition */
1760
}
1761
ok(!ret, "Expected failure\n");
1762
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1763
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1764
/* Experiments show bufsize + needed < tempneeded which proves the needed
1765
* buffer size is an approximation. So it's best not to probe more.
1766
*/
1767
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1768
ok(GetLastError() == ERROR_MORE_DATA,
1769
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1770
1771
/* Allocate less than the needed bytes, this time with a correct resume handle */
1772
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1773
needed = 0xdeadbeef;
1774
returned = 0xdeadbeef;
1775
resume = 0;
1776
SetLastError(0xdeadbeef);
1777
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1778
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1779
if (ret && needed == 0 && attempt)
1780
{
1781
free(exservices);
1782
goto retry; /* service stop race condition */
1783
}
1784
ok(!ret, "Expected failure\n");
1785
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1786
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1787
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1788
todo_wine ok(resume, "Expected a resume handle\n");
1789
ok(GetLastError() == ERROR_MORE_DATA,
1790
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1791
1792
/* Fetch the missing services but pass a bigger buffer size */
1793
missing = tempreturned - returned;
1794
bufsize = tempneeded;
1795
needed = 0xdeadbeef;
1796
returned = 0xdeadbeef;
1797
SetLastError(0xdeadbeef);
1798
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1799
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1800
free(exservices);
1801
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1802
goto retry; /* service start race condition */
1803
ok(ret, "Expected success, got error %lu\n", GetLastError());
1804
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1805
ok(returned == missing, "Expected %lu services to be returned\n", missing);
1806
ok(resume == 0, "Expected the resume handle to be 0\n");
1807
1808
/* See if things add up */
1809
1810
/* Get the number of active win32 services */
1811
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1812
NULL, 0, &needed, &returned, NULL, NULL);
1813
exservices = malloc(needed);
1814
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1815
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1816
free(exservices);
1817
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1818
goto retry; /* service start race condition */
1819
1820
servicecountactive = returned;
1821
1822
/* Get the number of inactive win32 services */
1823
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1824
NULL, 0, &needed, &returned, NULL, NULL);
1825
exservices = malloc(needed);
1826
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1827
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1828
free(exservices);
1829
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1830
goto retry; /* service start race condition */
1831
1832
servicecountinactive = returned;
1833
1834
/* Get the number of win32 services */
1835
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1836
NULL, 0, &needed, &returned, NULL, NULL);
1837
exservices = malloc(needed);
1838
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1839
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1840
free(exservices);
1841
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1842
goto retry; /* service start race condition */
1843
1844
/* Check if total is the same as active and inactive win32 services */
1845
if (returned != servicecountactive + servicecountinactive && attempt)
1846
goto retry; /* service start|stop race condition */
1847
ok(returned == servicecountactive + servicecountinactive,
1848
"Expected service count %ld == %ld + %ld\n",
1849
returned, servicecountactive, servicecountinactive);
1850
1851
/* Get all drivers and services */
1852
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1853
SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1854
ok(!ret, "Expected failure\n");
1855
exservices = malloc(needed);
1856
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1857
SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1858
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1859
goto retry; /* service start race condition */
1860
ok(ret, "Expected success %lu\n", GetLastError());
1861
1862
/* Loop through all those returned drivers and services */
1863
for (i = 0; i < returned; i++)
1864
{
1865
SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
1866
1867
/* lpServiceName and lpDisplayName should always be filled */
1868
ok(exservices[i].lpServiceName[0], "Expected a service name\n");
1869
ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n");
1870
1871
/* Decrement the counters to see if the functions calls return the
1872
* same numbers as the contents of these structures.
1873
* Check some process id specifics.
1874
*/
1875
if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
1876
{
1877
/* We shouldn't have a process id for drivers */
1878
ok(status.dwProcessId == 0,
1879
"This driver shouldn't have an associated process id\n");
1880
}
1881
1882
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1883
{
1884
switch (status.dwCurrentState)
1885
{
1886
case SERVICE_START_PENDING:
1887
case SERVICE_STOP_PENDING:
1888
trace("Got state %lx (pid=%04lx) for service %s\n",
1889
status.dwCurrentState, status.dwProcessId,
1890
wine_dbgstr_w(exservices[i].lpServiceName));
1891
/* There may or may not be a process id */
1892
servicecountactive--;
1893
break;
1894
1895
case SERVICE_PAUSE_PENDING:
1896
case SERVICE_PAUSED:
1897
case SERVICE_CONTINUE_PENDING:
1898
trace("Got state %lx (pid=%04lx) for service %s\n",
1899
status.dwCurrentState, status.dwProcessId,
1900
wine_dbgstr_w(exservices[i].lpServiceName));
1901
/* fall through */
1902
1903
case SERVICE_RUNNING:
1904
/* We expect a process id for every running service */
1905
ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1906
wine_dbgstr_w(exservices[i].lpServiceName));
1907
servicecountactive--;
1908
break;
1909
1910
case SERVICE_STOPPED:
1911
/* We shouldn't have a process id for inactive services */
1912
ok(status.dwProcessId == 0, "Service %s state %lu shouldn't have an associated process id\n",
1913
wine_dbgstr_w(exservices[i].lpServiceName), status.dwCurrentState);
1914
1915
servicecountinactive--;
1916
break;
1917
1918
default:
1919
ok(0, "Got unknown state %lx (pid=%04lx) for service %s\n",
1920
status.dwCurrentState, status.dwProcessId,
1921
wine_dbgstr_w(exservices[i].lpServiceName));
1922
break;
1923
}
1924
}
1925
}
1926
free(exservices);
1927
1928
if ((servicecountactive || servicecountinactive) && attempt)
1929
goto retry; /* service start|stop race condition */
1930
ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1931
ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1932
1933
alldone = TRUE;
1934
1935
retry:
1936
CloseServiceHandle(scm_handle);
1937
return alldone;
1938
}
1939
1940
static void test_close(void)
1941
{
1942
SC_HANDLE handle;
1943
BOOL ret;
1944
1945
/* NULL handle */
1946
SetLastError(0xdeadbeef);
1947
ret = CloseServiceHandle(NULL);
1948
ok(!ret, "Expected failure\n");
1949
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1950
1951
/* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1952
1953
/* Proper call */
1954
handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1955
SetLastError(0xdeadbeef);
1956
ret = CloseServiceHandle(handle);
1957
ok(ret, "Expected success got error %lu\n", GetLastError());
1958
}
1959
1960
static void test_wow64(void)
1961
{
1962
SC_HANDLE manager, service;
1963
BOOL wow64, ret;
1964
HANDLE file;
1965
1966
if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &wow64) || !wow64)
1967
{
1968
skip("Not running under WoW64.\n");
1969
return;
1970
}
1971
1972
if (!(manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE)))
1973
{
1974
skip("Not enough permissions to create a service.\n");
1975
return;
1976
}
1977
1978
file = CreateFileA("C:\\windows\\syswow64\\winetestsvc.exe", GENERIC_WRITE,
1979
0, NULL, CREATE_ALWAYS, 0, NULL);
1980
CloseHandle(file);
1981
1982
service = CreateServiceA(manager, "winetestsvc", "winetestsvc",
1983
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE,
1984
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1985
"C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1986
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1987
ret = StartServiceA(service, 0, NULL);
1988
ok(!ret, "Expected failure.\n");
1989
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
1990
1991
ret = DeleteService(service);
1992
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
1993
CloseServiceHandle(service);
1994
1995
service = CreateServiceA(manager, "winetestsvc2", "winetestsvc2", SERVICE_START | DELETE,
1996
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1997
"C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
1998
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1999
ret = StartServiceA(service, 0, NULL);
2000
ok(!ret, "Expected failure.\n");
2001
todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
2002
2003
ret = DeleteService(service);
2004
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2005
CloseServiceHandle(service);
2006
2007
ret = DeleteFileA("C:\\windows\\syswow64\\winetestsvc.exe");
2008
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
2009
2010
file = CreateFileA("C:\\windows\\sysnative\\winetestsvc.exe", GENERIC_WRITE,
2011
0, NULL, CREATE_ALWAYS, 0, NULL);
2012
CloseHandle(file);
2013
2014
service = CreateServiceA(manager, "winetestsvc3", "winetestsvc3", SERVICE_START | DELETE,
2015
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
2016
"C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
2017
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
2018
ret = StartServiceA(service, 0, NULL);
2019
ok(!ret, "Expected failure.\n");
2020
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
2021
2022
ret = DeleteService(service);
2023
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2024
CloseServiceHandle(service);
2025
2026
service = CreateServiceA(manager, "winetestsvc4", "winetestsvc4", SERVICE_START | DELETE,
2027
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
2028
"C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
2029
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
2030
ret = StartServiceA(service, 0, NULL);
2031
ok(!ret, "Expected failure.\n");
2032
todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
2033
2034
ret = DeleteService(service);
2035
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2036
CloseServiceHandle(service);
2037
2038
ret = DeleteFileA("C:\\windows\\sysnative\\winetestsvc.exe");
2039
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
2040
2041
CloseServiceHandle(manager);
2042
}
2043
2044
static void test_sequence(void)
2045
{
2046
SC_HANDLE scm_handle, svc_handle;
2047
BOOL ret, is_nt4;
2048
QUERY_SERVICE_CONFIGA *config;
2049
DWORD given, needed;
2050
static const CHAR servicename [] = "winetest_sequence";
2051
static const CHAR displayname [] = "Winetest dummy service";
2052
static const CHAR displayname2[] = "Winetest dummy service (2)";
2053
static const CHAR pathname [] = "we_dont_care.exe";
2054
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2055
static const CHAR password [] = "";
2056
static const CHAR empty [] = "";
2057
static const CHAR localsystem [] = "LocalSystem";
2058
2059
SetLastError(0xdeadbeef);
2060
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2061
2062
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2063
{
2064
skip("Not enough rights to get a handle to the manager\n");
2065
return;
2066
}
2067
else
2068
ok(scm_handle != NULL, "Could not get a handle to the manager: %ld\n", GetLastError());
2069
2070
if (!scm_handle) return;
2071
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2072
is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2073
CloseServiceHandle(svc_handle);
2074
2075
/* Create a dummy service */
2076
SetLastError(0xdeadbeef);
2077
svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2078
SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
2079
pathname, NULL, NULL, dependencies, NULL, password);
2080
2081
if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
2082
{
2083
/* We try and open the service and do the rest of the tests. Some could
2084
* fail if the tests were changed between these runs.
2085
*/
2086
trace("Deletion probably didn't work last time\n");
2087
SetLastError(0xdeadbeef);
2088
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2089
if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2090
{
2091
skip("Not enough rights to open the service\n");
2092
CloseServiceHandle(scm_handle);
2093
return;
2094
}
2095
ok(svc_handle != NULL, "Could not open the service : %ld\n", GetLastError());
2096
}
2097
else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2098
{
2099
skip("Not enough rights to create the service\n");
2100
CloseServiceHandle(scm_handle);
2101
return;
2102
}
2103
else
2104
{
2105
ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2106
if (svc_handle != NULL)
2107
{
2108
PSID sidOwner, sidGroup;
2109
PACL dacl, sacl;
2110
PSECURITY_DESCRIPTOR pSD;
2111
DWORD error, n1, n2;
2112
HRESULT retval;
2113
BOOL bret;
2114
2115
/* Test using GetSecurityInfo to obtain security information */
2116
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
2117
&sidGroup, &dacl, &sacl, &pSD);
2118
LocalFree(pSD);
2119
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2120
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2121
NULL, NULL, NULL, &pSD);
2122
LocalFree(pSD);
2123
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2124
if (!is_nt4)
2125
{
2126
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2127
NULL, &dacl, NULL, &pSD);
2128
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2129
LocalFree(pSD);
2130
SetLastError(0xdeadbeef);
2131
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2132
NULL, NULL, NULL, NULL);
2133
error = GetLastError();
2134
ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %ld\n", retval);
2135
ok(error == 0xdeadbeef, "Unexpected last error %ld\n", error);
2136
}
2137
else
2138
win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
2139
2140
/* Test using QueryServiceObjectSecurity to obtain security information */
2141
SetLastError(0xdeadbeef);
2142
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
2143
error = GetLastError();
2144
ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
2145
ok(error == ERROR_INSUFFICIENT_BUFFER ||
2146
broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER),
2147
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", error);
2148
if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
2149
pSD = LocalAlloc(0, n1);
2150
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
2151
ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
2152
LocalFree(pSD);
2153
}
2154
}
2155
2156
if (!svc_handle) {
2157
CloseServiceHandle(scm_handle);
2158
return;
2159
}
2160
2161
/* TODO:
2162
* Before we do a QueryServiceConfig we should check the registry. This will make sure
2163
* that the correct keys are used.
2164
*/
2165
2166
/* Request the size for the buffer */
2167
SetLastError(0xdeadbeef);
2168
ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2169
ok(!ret, "Expected failure\n");
2170
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2171
2172
config = malloc(needed);
2173
given = needed;
2174
SetLastError(0xdeadbeef);
2175
ret = QueryServiceConfigA(svc_handle, config, given, &needed);
2176
ok(ret, "Expected success, got error %lu\n", GetLastError());
2177
2178
ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2179
config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2180
ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
2181
"Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2182
ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2183
ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %ld\n", config->dwErrorControl);
2184
ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2185
ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
2186
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2187
/* TODO: Show the double 0 terminated string */
2188
todo_wine
2189
{
2190
ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
2191
}
2192
ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2193
ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
2194
2195
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2",
2196
NULL, NULL, NULL, NULL, displayname2);
2197
ok(ret, "ChangeServiceConfig failed (err=%ld)\n", GetLastError());
2198
2199
QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2200
config = realloc(config, needed);
2201
ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
2202
ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2203
config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2204
ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
2205
"Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2206
ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2207
ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %ld\n", config->dwErrorControl);
2208
ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2209
ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
2210
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2211
ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2212
ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
2213
2214
SetLastError(0xdeadbeef);
2215
ret = DeleteService(svc_handle);
2216
ok(ret, "Expected success, got error %lu\n", GetLastError());
2217
CloseServiceHandle(svc_handle);
2218
CloseServiceHandle(scm_handle);
2219
free(config);
2220
}
2221
2222
static void test_queryconfig2(void)
2223
{
2224
SC_HANDLE scm_handle, svc_handle;
2225
BOOL ret;
2226
DWORD expected, needed;
2227
BYTE buffer[MAX_PATH];
2228
LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
2229
LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
2230
SERVICE_PRESHUTDOWN_INFO preshutdown_info;
2231
SERVICE_DELAYED_AUTO_START_INFO auto_start_info;
2232
static const CHAR servicename [] = "winetest_query_config2";
2233
static const CHAR displayname [] = "Winetest dummy service";
2234
static const CHAR pathname [] = "we_dont_care.exe";
2235
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2236
static const CHAR password [] = "";
2237
static const CHAR description [] = "Description";
2238
static const WCHAR descriptionW [] = L"DescriptionW";
2239
2240
if(!pQueryServiceConfig2A)
2241
{
2242
win_skip("function QueryServiceConfig2A not present\n");
2243
return;
2244
}
2245
2246
SetLastError(0xdeadbeef);
2247
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2248
2249
if (!scm_handle)
2250
{
2251
if(GetLastError() == ERROR_ACCESS_DENIED)
2252
skip("Not enough rights to get a handle to the manager\n");
2253
else
2254
ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2255
return;
2256
}
2257
2258
/* Create a dummy service */
2259
SetLastError(0xdeadbeef);
2260
svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2261
SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
2262
pathname, NULL, NULL, dependencies, NULL, password);
2263
2264
if (!svc_handle)
2265
{
2266
if(GetLastError() == ERROR_SERVICE_EXISTS)
2267
{
2268
/* We try and open the service and do the rest of the tests. Some could
2269
* fail if the tests were changed between these runs.
2270
*/
2271
trace("Deletion probably didn't work last time\n");
2272
SetLastError(0xdeadbeef);
2273
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2274
if (!svc_handle)
2275
{
2276
if(GetLastError() == ERROR_ACCESS_DENIED)
2277
skip("Not enough rights to open the service\n");
2278
else
2279
ok(FALSE, "Could not open the service : %ld\n", GetLastError());
2280
CloseServiceHandle(scm_handle);
2281
return;
2282
}
2283
}
2284
if (GetLastError() == ERROR_ACCESS_DENIED)
2285
{
2286
skip("Not enough rights to create the service\n");
2287
CloseServiceHandle(scm_handle);
2288
return;
2289
}
2290
ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2291
if (!svc_handle)
2292
{
2293
CloseServiceHandle(scm_handle);
2294
return;
2295
}
2296
}
2297
SetLastError(0xdeadbeef);
2298
ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2299
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2300
ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2301
2302
SetLastError(0xdeadbeef);
2303
ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2304
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2305
ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2306
2307
SetLastError(0xdeadbeef);
2308
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2309
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2310
ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2311
2312
SetLastError(0xdeadbeef);
2313
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2314
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2315
ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
2316
"expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2317
2318
SetLastError(0xdeadbeef);
2319
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2320
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2321
ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2322
2323
needed = 0;
2324
SetLastError(0xdeadbeef);
2325
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2326
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2327
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2328
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2329
2330
needed = 0;
2331
pConfig->lpDescription = (LPSTR)0xdeadbeef;
2332
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2333
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2334
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2335
ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2336
2337
SetLastError(0xdeadbeef);
2338
needed = 0;
2339
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2340
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2341
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2342
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2343
2344
if(!pChangeServiceConfig2A)
2345
{
2346
win_skip("function ChangeServiceConfig2A not present\n");
2347
goto cleanup;
2348
}
2349
2350
pConfig->lpDescription = (LPSTR) description;
2351
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2352
ok(ret, "ChangeServiceConfig2A failed\n");
2353
if (!ret) {
2354
goto cleanup;
2355
}
2356
2357
SetLastError(0xdeadbeef);
2358
needed = 0;
2359
expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2360
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2361
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2362
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2363
ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2364
2365
SetLastError(0xdeadbeef);
2366
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2367
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2368
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2369
2370
SetLastError(0xdeadbeef);
2371
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2372
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2373
ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2374
"expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2375
2376
SetLastError(0xdeadbeef);
2377
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2378
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2379
ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2380
"expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2381
2382
if(!pQueryServiceConfig2W)
2383
{
2384
win_skip("function QueryServiceConfig2W not present\n");
2385
goto cleanup;
2386
}
2387
SetLastError(0xdeadbeef);
2388
needed = 0;
2389
expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2390
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2391
ok(!ret, "expected QueryServiceConfig2W to fail\n");
2392
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2393
ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2394
2395
SetLastError(0xdeadbeef);
2396
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2397
ok(ret, "expected QueryServiceConfig2W to succeed\n");
2398
2399
pConfig->lpDescription = (LPSTR)description;
2400
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2401
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2402
2403
pConfig->lpDescription = NULL;
2404
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2405
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2406
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2407
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2408
2409
pConfig->lpDescription = NULL;
2410
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2411
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2412
2413
pConfig->lpDescription = NULL;
2414
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2415
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2416
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2417
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2418
2419
pConfig->lpDescription = (char*)"";
2420
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2421
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2422
2423
pConfig->lpDescription = (void*)0xdeadbeef;
2424
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2425
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2426
ok(!pConfig->lpDescription,
2427
"expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2428
2429
pConfigW->lpDescription = (LPWSTR)descriptionW;
2430
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2431
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2432
2433
pConfigW->lpDescription = NULL;
2434
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2435
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2436
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2437
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2438
2439
pConfigW->lpDescription = NULL;
2440
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2441
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2442
2443
pConfigW->lpDescription = NULL;
2444
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2445
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2446
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2447
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2448
2449
pConfigW->lpDescription = (WCHAR*)L"";
2450
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2451
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2452
2453
pConfigW->lpDescription = (void*)0xdeadbeef;
2454
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2455
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2456
ok(!pConfigW->lpDescription,
2457
"expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2458
2459
SetLastError(0xdeadbeef);
2460
needed = 0;
2461
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2462
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2463
if(!ret && GetLastError()==ERROR_INVALID_LEVEL)
2464
{
2465
/* Win2k3 and older */
2466
win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2467
goto cleanup;
2468
}
2469
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2470
ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2471
ok(preshutdown_info.dwPreshutdownTimeout == 180000
2472
|| preshutdown_info.dwPreshutdownTimeout == 10000 /* Win10 1709+ */,
2473
"Default PreshutdownTimeout = %ld\n", preshutdown_info.dwPreshutdownTimeout);
2474
2475
SetLastError(0xdeadbeef);
2476
preshutdown_info.dwPreshutdownTimeout = -1;
2477
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2478
(LPVOID)&preshutdown_info);
2479
ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
2480
2481
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2482
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2483
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2484
ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2485
ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %ld\n",
2486
preshutdown_info.dwPreshutdownTimeout);
2487
2488
SetLastError(0xdeadbeef);
2489
needed = 0;
2490
auto_start_info.fDelayedAutostart = 0xdeadbeef;
2491
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2492
(LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed);
2493
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2494
ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed);
2495
ok(auto_start_info.fDelayedAutostart == 0, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2496
2497
SetLastError(0xdeadbeef);
2498
auto_start_info.fDelayedAutostart = 3;
2499
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2500
(LPBYTE)&auto_start_info);
2501
ok(!ret, "expected ChangeServiceConfig2A to fail\n");
2502
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %ld\n", GetLastError());
2503
2504
SetLastError(0xdeadbeef);
2505
auto_start_info.fDelayedAutostart = 1;
2506
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2507
(LPBYTE)&auto_start_info);
2508
ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
2509
2510
SetLastError(0xdeadbeef);
2511
needed = 0;
2512
auto_start_info.fDelayedAutostart = 0xdeadbeef;
2513
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2514
(LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed);
2515
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2516
ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed);
2517
ok(auto_start_info.fDelayedAutostart == 1, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2518
2519
cleanup:
2520
DeleteService(svc_handle);
2521
CloseServiceHandle(svc_handle);
2522
CloseServiceHandle(scm_handle);
2523
}
2524
2525
static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2526
{
2527
BOOL ret;
2528
DWORD le1, le2;
2529
SERVICE_STATUS status;
2530
2531
ret = StartServiceA(svc_handle, 0, NULL);
2532
le1 = GetLastError();
2533
ok(!ret, "%s: StartServiceA() should have failed\n", name);
2534
2535
if (pQueryServiceStatusEx)
2536
{
2537
DWORD needed;
2538
SERVICE_STATUS_PROCESS statusproc;
2539
2540
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2541
ok(ret, "%s: QueryServiceStatusEx() failed le=%lu\n", name, GetLastError());
2542
ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%lx\n", name, statusproc.dwCurrentState);
2543
ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %lx\n", name, statusproc.dwProcessId);
2544
}
2545
2546
ret = StartServiceA(svc_handle, 0, NULL);
2547
le2 = GetLastError();
2548
ok(!ret, "%s: StartServiceA() should have failed\n", name);
2549
ok(le2 == le1, "%s: the second try should yield the same error: %lu != %lu\n", name, le1, le2);
2550
2551
status.dwCurrentState = 0xdeadbeef;
2552
ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status);
2553
le2 = GetLastError();
2554
ok(!ret, "%s: ControlService() should have failed\n", name);
2555
ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %ld != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2556
ok(status.dwCurrentState == SERVICE_STOPPED ||
2557
broken(is_nt4), /* NT4 returns a random value */
2558
"%s: should be stopped state=%lx\n", name, status.dwCurrentState);
2559
2560
return le1;
2561
}
2562
2563
#define PHASE_STOPPED 1
2564
#define PHASE_RUNNING 2
2565
2566
struct notify_data {
2567
SERVICE_NOTIFYW notify;
2568
SC_HANDLE svc;
2569
BOOL was_called;
2570
DWORD phase;
2571
};
2572
2573
static void CALLBACK notify_cb(void *user)
2574
{
2575
struct notify_data *data = user;
2576
switch (data->phase)
2577
{
2578
case PHASE_STOPPED:
2579
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2580
"Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2581
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2582
"Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2583
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2584
"Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2585
break;
2586
2587
case PHASE_RUNNING:
2588
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2589
"Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2590
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2591
"Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2592
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2593
"Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2594
break;
2595
}
2596
2597
data->was_called = TRUE;
2598
}
2599
2600
static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
2601
{
2602
DWORD dr, dr2;
2603
struct notify_data data;
2604
struct notify_data data2;
2605
BOOL br;
2606
SERVICE_STATUS status;
2607
HANDLE svc, svc2;
2608
2609
if(!pNotifyServiceStatusChangeW){
2610
win_skip("No NotifyServiceStatusChangeW\n");
2611
return;
2612
}
2613
2614
svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2615
svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2616
ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2617
if(!svc || !svc2)
2618
return;
2619
2620
/* receive stopped notification, then start service */
2621
memset(&data.notify, 0, sizeof(data.notify));
2622
data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2623
data.notify.pfnNotifyCallback = &notify_cb;
2624
data.notify.pContext = &data;
2625
data.svc = svc;
2626
data.phase = PHASE_STOPPED;
2627
data.was_called = FALSE;
2628
2629
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2630
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2631
2632
dr = SleepEx(100, TRUE);
2633
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2634
ok(data.was_called == TRUE, "APC wasn't called\n");
2635
2636
br = StartServiceA(svc, 0, NULL);
2637
ok(br, "StartService failed: %lu\n", GetLastError());
2638
2639
/* receive running notification */
2640
data.phase = PHASE_RUNNING;
2641
data.was_called = FALSE;
2642
2643
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2644
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2645
2646
dr = SleepEx(100, TRUE);
2647
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2648
ok(data.was_called == TRUE, "APC wasn't called\n");
2649
2650
/* cannot register two notifications on the same handle */
2651
data.phase = PHASE_STOPPED;
2652
data.was_called = FALSE;
2653
2654
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2655
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2656
2657
memset(&data2.notify, 0, sizeof(data2.notify));
2658
data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2659
data2.notify.pfnNotifyCallback = &notify_cb;
2660
data2.notify.pContext = &data2;
2661
data2.phase = PHASE_RUNNING;
2662
data2.was_called = FALSE;
2663
2664
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2665
ok(dr == ERROR_ALREADY_REGISTERED || !dr /* Win8+ */, "wrong error %lu\n", dr);
2666
if (!dr)
2667
{
2668
dr = SleepEx(100, TRUE);
2669
ok(dr == WAIT_IO_COMPLETION, "got %lu\n", dr);
2670
ok(data2.was_called, "APC was not called\n");
2671
}
2672
else
2673
{
2674
dr = SleepEx(100, TRUE);
2675
ok(!dr, "got %lu\n", dr);
2676
ok(!data2.was_called, "APC should not have been called\n");
2677
}
2678
ok(data.was_called == FALSE, "APC should not have been called\n");
2679
2680
memset(&data2.notify, 0, sizeof(data2.notify));
2681
data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2682
data2.notify.pfnNotifyCallback = &notify_cb;
2683
data2.notify.pContext = &data;
2684
data2.svc = svc2;
2685
data2.phase = PHASE_STOPPED;
2686
data2.was_called = FALSE;
2687
2688
/* it's possible to have multiple notifications using different service handles */
2689
dr = pNotifyServiceStatusChangeW(svc2, SERVICE_NOTIFY_STOPPED, &data2.notify);
2690
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW gave wrong result: %lu\n", dr);
2691
2692
/* stop service and receive notifiction */
2693
br = ControlService(svc, SERVICE_CONTROL_STOP, &status);
2694
ok(br, "ControlService failed: %lu\n", GetLastError());
2695
2696
dr = SleepEx(100, TRUE);
2697
dr2 = SleepEx(100, TRUE);
2698
ok(dr == WAIT_IO_COMPLETION || dr2 == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2699
ok(data.was_called == TRUE, "APC wasn't called\n");
2700
ok(data2.was_called == TRUE, "APC wasn't called\n");
2701
2702
/* test cancelation: create notify on svc that will block until service
2703
* start; close svc; start service on svc2; verify that notification does
2704
* not happen */
2705
2706
data.phase = PHASE_RUNNING;
2707
data.was_called = FALSE;
2708
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2709
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2710
2711
CloseServiceHandle(svc);
2712
2713
br = StartServiceA(svc2, 0, NULL);
2714
ok(br, "StartService failed: %lu\n", GetLastError());
2715
2716
dr = SleepEx(100, TRUE);
2717
ok(dr == 0, "Got wrong SleepEx result: %lu\n", dr);
2718
ok(data.was_called == FALSE, "APC should not have been called\n");
2719
2720
br = ControlService(svc2, SERVICE_CONTROL_STOP, &status);
2721
ok(br, "ControlService failed: %lu\n", GetLastError());
2722
2723
CloseServiceHandle(svc2);
2724
}
2725
2726
static void test_start_stop(void)
2727
{
2728
BOOL ret;
2729
SC_HANDLE scm_handle, svc_handle;
2730
DWORD le, is_nt4;
2731
static const char servicename[] = "winetest_start_stop";
2732
char cmd[MAX_PATH+20];
2733
const char* displayname;
2734
2735
SetLastError(0xdeadbeef);
2736
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2737
if (!scm_handle)
2738
{
2739
if(GetLastError() == ERROR_ACCESS_DENIED)
2740
skip("Not enough rights to get a handle to the manager\n");
2741
else
2742
ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2743
return;
2744
}
2745
2746
/* Detect NT4 */
2747
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2748
is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2749
2750
/* Do some cleanup in case a previous run crashed */
2751
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2752
if (svc_handle)
2753
{
2754
DeleteService(svc_handle);
2755
CloseServiceHandle(svc_handle);
2756
}
2757
2758
/* Create a dummy disabled service */
2759
sprintf(cmd, "\"%s\" service exit", selfname);
2760
displayname = "Winetest Disabled Service";
2761
svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2762
GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,
2763
SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL,
2764
NULL, NULL, NULL, NULL);
2765
if (!svc_handle)
2766
{
2767
if(GetLastError() == ERROR_ACCESS_DENIED)
2768
skip("Not enough rights to create the service\n");
2769
else
2770
ok(FALSE, "Could not create the service: %ld\n", GetLastError());
2771
goto cleanup;
2772
}
2773
le = try_start_stop(svc_handle, displayname, is_nt4);
2774
ok(le == ERROR_SERVICE_DISABLED, "%ld != ERROR_SERVICE_DISABLED\n", le);
2775
2776
/* Then one with a bad path */
2777
displayname = "Winetest Bad Path";
2778
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2779
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2780
try_start_stop(svc_handle, displayname, is_nt4);
2781
2782
if (is_nt4)
2783
{
2784
/* NT4 does not detect when a service fails to start and uses an
2785
* insanely long timeout: 120s. So skip the rest of the tests.
2786
*/
2787
win_skip("Skip some service start/stop tests on NT4\n");
2788
goto cleanup;
2789
}
2790
2791
/* Again with a process that exits right away */
2792
displayname = "Winetest Exit Service";
2793
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2794
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2795
le = try_start_stop(svc_handle, displayname, is_nt4);
2796
ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%ld != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2797
2798
/* create a real service and test notifications */
2799
sprintf(cmd, "%s service serve", selfname);
2800
displayname = "Winetest Service";
2801
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2802
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2803
test_servicenotify(scm_handle, servicename);
2804
2805
cleanup:
2806
if (svc_handle)
2807
{
2808
DeleteService(svc_handle);
2809
CloseServiceHandle(svc_handle);
2810
}
2811
CloseServiceHandle(scm_handle);
2812
}
2813
2814
static void test_refcount(void)
2815
{
2816
SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2817
static const CHAR servicename [] = "winetest_refcount";
2818
static const CHAR pathname [] = "we_dont_care.exe";
2819
BOOL ret;
2820
2821
/* Get a handle to the Service Control Manager */
2822
SetLastError(0xdeadbeef);
2823
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2824
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2825
{
2826
skip("Not enough rights to get a handle to the manager\n");
2827
return;
2828
}
2829
2830
/* Create a service */
2831
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2832
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2833
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2834
ok(svc_handle1 != NULL, "Expected success, got error %lu\n", GetLastError());
2835
2836
/* Get a handle to this new service */
2837
svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2838
ok(svc_handle2 != NULL, "Expected success, got error %lu\n", GetLastError());
2839
2840
/* Get another handle to this new service */
2841
svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2842
ok(svc_handle3 != NULL, "Expected success, got error %lu\n", GetLastError());
2843
2844
/* Check if we can close the handle to the Service Control Manager */
2845
ret = CloseServiceHandle(scm_handle);
2846
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2847
2848
/* Get a new handle to the Service Control Manager */
2849
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2850
ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
2851
2852
/* Get a handle to this new service */
2853
svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2854
ok(svc_handle4 != NULL, "Expected success, got error %lu\n", GetLastError());
2855
2856
/* Delete the service */
2857
ret = DeleteService(svc_handle4);
2858
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2859
2860
/* We cannot create the same service again as it's still marked as 'being deleted'.
2861
* The reason is that we still have 4 open handles to this service even though we
2862
* closed the handle to the Service Control Manager in between.
2863
*/
2864
SetLastError(0xdeadbeef);
2865
svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2866
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2867
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2868
ok(!svc_handle5, "Expected failure\n");
2869
ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
2870
"Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %ld\n", GetLastError());
2871
2872
/* Close all the handles to the service and try again */
2873
ret = CloseServiceHandle(svc_handle4);
2874
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2875
ret = CloseServiceHandle(svc_handle3);
2876
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2877
ret = CloseServiceHandle(svc_handle2);
2878
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2879
ret = CloseServiceHandle(svc_handle1);
2880
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2881
2882
/* We succeed now as all handles are closed (tested this also with a long Sleep() */
2883
do
2884
{
2885
SetLastError(0xdeadbeef);
2886
svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2887
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2888
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2889
} while (!svc_handle5 && GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE);
2890
ok(svc_handle5 != NULL, "Expected success, got error %lu\n", GetLastError());
2891
2892
/* Delete the service */
2893
ret = DeleteService(svc_handle5);
2894
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2895
CloseServiceHandle(svc_handle5);
2896
CloseServiceHandle(scm_handle);
2897
}
2898
2899
static BOOL is_lang_english(void)
2900
{
2901
static HMODULE hkernel32 = NULL;
2902
static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
2903
static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
2904
2905
if (!hkernel32)
2906
{
2907
hkernel32 = GetModuleHandleA("kernel32.dll");
2908
pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
2909
pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
2910
}
2911
if (pGetThreadUILanguage)
2912
return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
2913
if (pGetUserDefaultUILanguage)
2914
return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
2915
2916
return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
2917
}
2918
2919
static void test_EventLog(void)
2920
{
2921
SC_HANDLE scm_handle, svc_handle;
2922
DWORD size;
2923
BOOL ret;
2924
QUERY_SERVICE_CONFIGA *config;
2925
SERVICE_STATUS_PROCESS status;
2926
2927
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_READ);
2928
ok(scm_handle != NULL, "OpenSCManager error %lu\n", GetLastError());
2929
2930
svc_handle = OpenServiceA(scm_handle, "EventLog", GENERIC_READ);
2931
ok(svc_handle != NULL, "OpenService error %lu\n", GetLastError());
2932
2933
SetLastError(0xdeadbeef);
2934
ret = QueryServiceConfigA(svc_handle, NULL, 0, &size);
2935
ok(!ret, "QueryServiceConfig should fail\n");
2936
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
2937
2938
config = malloc(size);
2939
ret = QueryServiceConfigA(svc_handle, config, size, &size);
2940
ok(ret, "QueryServiceConfig error %lu\n", GetLastError());
2941
2942
ok(config->dwServiceType == SERVICE_WIN32_SHARE_PROCESS, "got %#lx\n", config->dwServiceType);
2943
ok(config->dwStartType == SERVICE_AUTO_START, "got %lu\n", config->dwStartType);
2944
ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "got %lu\n", config->dwErrorControl);
2945
ok(!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\services.exe") /* XP */ ||
2946
!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted") /* Vista+ */ ||
2947
!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -p") /* Win10 */,
2948
"got %s\n", config->lpBinaryPathName);
2949
todo_wine
2950
ok(!strcmpi(config->lpLoadOrderGroup, "Event Log"), "got %s\n", config->lpLoadOrderGroup);
2951
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2952
ok(!config->lpDependencies[0], "lpDependencies is not empty\n");
2953
ok(!strcmp(config->lpServiceStartName, "LocalSystem") /* XP */ ||
2954
!strcmp(config->lpServiceStartName, "NT AUTHORITY\\LocalService"),
2955
"got %s\n", config->lpServiceStartName);
2956
ok(!is_lang_english() || /* DisplayName is often translated */
2957
!strcmp(config->lpDisplayName, "Event Log") /* XP */ ||
2958
!strcmp(config->lpDisplayName, "Windows Event Log") /* Vista+ */, "got %s\n", config->lpDisplayName);
2959
2960
free(config);
2961
2962
memset(&status, 0, sizeof(status));
2963
size = sizeof(status);
2964
ret = QueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status, size, &size);
2965
ok(ret, "QueryServiceStatusEx error %lu\n", GetLastError());
2966
ok(status.dwServiceType == SERVICE_WIN32_SHARE_PROCESS ||
2967
status.dwServiceType == (SERVICE_WIN32_SHARE_PROCESS | SERVICE_WIN32_OWN_PROCESS) /* Win10 */,
2968
"got %#lx\n", status.dwServiceType);
2969
ok(status.dwServiceSpecificExitCode == 0, "got %#lx\n", status.dwServiceSpecificExitCode);
2970
ok(status.dwCheckPoint == 0, "got %#lx\n", status.dwCheckPoint);
2971
ok(status.dwWaitHint == 0, "got %#lx\n", status.dwWaitHint);
2972
ok(status.dwServiceFlags == 0 || status.dwServiceFlags == SERVICE_RUNS_IN_SYSTEM_PROCESS /* XP */,
2973
"got %#lx\n", status.dwServiceFlags);
2974
if (status.dwCurrentState == SERVICE_STOPPED &&
2975
status.dwWin32ExitCode == ERROR_PROCESS_ABORTED)
2976
win_skip("EventLog crashed!\n");
2977
else
2978
{
2979
ok(status.dwCurrentState == SERVICE_RUNNING, "got %#lx\n", status.dwCurrentState);
2980
ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ ||
2981
status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ ||
2982
status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_TIMECHANGE | SERVICE_ACCEPT_SHUTDOWN),
2983
"got %#lx\n", status.dwControlsAccepted);
2984
ok(status.dwWin32ExitCode == 0, "got %#lx\n", status.dwWin32ExitCode);
2985
ok(status.dwProcessId != 0, "got %#lx\n", status.dwProcessId);
2986
}
2987
2988
CloseServiceHandle(svc_handle);
2989
CloseServiceHandle(scm_handle);
2990
}
2991
2992
static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
2993
{
2994
HANDLE evt = user;
2995
2996
switch(ctl){
2997
case SERVICE_CONTROL_STOP:
2998
SetEvent(evt);
2999
break;
3000
case SERVICE_CONTROL_INTERROGATE:
3001
return NO_ERROR;
3002
}
3003
3004
return ERROR_CALL_NOT_IMPLEMENTED;
3005
}
3006
3007
static void WINAPI service_main(DWORD argc, char **argv)
3008
{
3009
SERVICE_STATUS_HANDLE st_handle;
3010
SERVICE_STATUS st;
3011
HANDLE evt = CreateEventW(0, FALSE, FALSE, 0);
3012
3013
st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt);
3014
3015
st.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3016
st.dwServiceSpecificExitCode = 0;
3017
st.dwCurrentState = SERVICE_RUNNING;
3018
st.dwWin32ExitCode = NO_ERROR;
3019
st.dwWaitHint = 0;
3020
st.dwControlsAccepted = SERVICE_ACCEPT_STOP;
3021
st.dwCheckPoint = 0;
3022
3023
SetServiceStatus(st_handle, &st);
3024
3025
WaitForSingleObject(evt, 5000);
3026
3027
st.dwCurrentState = SERVICE_STOPPED;
3028
3029
SetServiceStatus(st_handle, &st);
3030
}
3031
3032
static void run_service(void)
3033
{
3034
char empty[] = {0};
3035
SERVICE_TABLE_ENTRYA table[] = {
3036
{empty, &service_main },
3037
{0, 0}
3038
};
3039
3040
StartServiceCtrlDispatcherA(table);
3041
}
3042
3043
START_TEST(service)
3044
{
3045
SC_HANDLE scm_handle;
3046
int myARGC;
3047
char** myARGV;
3048
int attempt;
3049
3050
myARGC = winetest_get_mainargs(&myARGV);
3051
GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL);
3052
if (myARGC >= 3)
3053
{
3054
if (strcmp(myARGV[2], "serve") == 0)
3055
run_service();
3056
return;
3057
}
3058
3059
/* Bail out if we are on win98 */
3060
SetLastError(0xdeadbeef);
3061
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
3062
3063
if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3064
{
3065
win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
3066
return;
3067
}
3068
CloseServiceHandle(scm_handle);
3069
3070
init_function_pointers();
3071
3072
/* First some parameter checking */
3073
test_open_scm();
3074
test_open_svc();
3075
test_create_delete_svc();
3076
test_get_displayname();
3077
test_get_servicekeyname();
3078
test_query_svc();
3079
3080
/* Services may start or stop between enumeration calls, leading to
3081
* inconsistencies and failures. So we may need a couple attempts.
3082
*/
3083
for (attempt = 2; attempt >= 0; attempt--)
3084
if (test_enum_svc(attempt)) break;
3085
for (attempt = 2; attempt >= 0; attempt--)
3086
if (test_enum_svc_ex(attempt)) break;
3087
3088
test_close();
3089
test_wow64();
3090
/* Test the creation, querying and deletion of a service */
3091
test_sequence();
3092
test_queryconfig2();
3093
test_start_stop();
3094
/* The main reason for this test is to check if any refcounting is used
3095
* and what the rules are
3096
*/
3097
test_refcount();
3098
test_EventLog();
3099
}
3100
3101