Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/advapi32/tests/service.c
4389 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
CloseServiceHandle(scm_handle);
717
}
718
719
static void test_get_servicekeyname(void)
720
{
721
SC_HANDLE scm_handle, svc_handle;
722
CHAR servicename[4096];
723
CHAR displayname[4096];
724
WCHAR servicenameW[4096];
725
WCHAR displaynameW[4096];
726
DWORD servicesize, displaysize, tempsize;
727
BOOL ret;
728
729
/* Having NULL for the size of the buffer will crash on W2K3 */
730
731
SetLastError(0xdeadbeef);
732
ret = GetServiceKeyNameA(NULL, NULL, NULL, &servicesize);
733
ok(!ret, "Expected failure\n");
734
ok(GetLastError() == ERROR_INVALID_HANDLE,
735
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
736
737
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
738
739
servicesize = 200;
740
SetLastError(0xdeadbeef);
741
ret = GetServiceKeyNameA(scm_handle, NULL, NULL, &servicesize);
742
ok(!ret, "Expected failure\n");
743
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
744
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
745
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
746
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
747
748
/* Valid handle and buffer but no displayname */
749
servicesize = 200;
750
SetLastError(0xdeadbeef);
751
ret = GetServiceKeyNameA(scm_handle, NULL, servicename, &servicesize);
752
ok(!ret, "Expected failure\n");
753
ok(GetLastError() == ERROR_INVALID_ADDRESS /* W2K, XP, W2K3, Vista */ ||
754
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
755
"Expected ERROR_INVALID_ADDRESS or ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
756
todo_wine ok(servicesize == 200, "Service size expected 1, got %ld\n", servicesize);
757
758
/* Test for nonexistent displayname */
759
SetLastError(0xdeadbeef);
760
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", NULL, &servicesize);
761
ok(!ret, "Expected failure\n");
762
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
763
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
764
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
765
766
servicesize = 15;
767
strcpy(servicename, "ABC");
768
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", servicename, &servicesize);
769
ok(!ret, "Expected failure\n");
770
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
771
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
772
todo_wine ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
773
ok(servicename[0] == 0, "Service name not empty\n");
774
775
servicesize = 15;
776
wcscpy(servicenameW, L"ABC");
777
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
778
ok(!ret, "Expected failure\n");
779
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
780
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
781
ok(servicesize == 15, "Service size expected 15, got %ld\n", servicesize);
782
ok(servicenameW[0] == 0, "Service name not empty\n");
783
784
servicesize = 0;
785
strcpy(servicename, "ABC");
786
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", servicename, &servicesize);
787
ok(!ret, "Expected failure\n");
788
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
789
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
790
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
791
ok(servicename[0] == 'A', "Service name changed\n");
792
793
servicesize = 0;
794
wcscpy(servicenameW, L"ABC");
795
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
796
ok(!ret, "Expected failure\n");
797
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
798
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
799
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
800
ok(servicenameW[0] == 'A', "Service name changed\n");
801
802
servicesize = 1;
803
strcpy(servicename, "ABC");
804
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", servicename, &servicesize);
805
ok(!ret, "Expected failure\n");
806
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
807
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
808
todo_wine ok(servicesize == 1, "Service size expected 1, got %ld\n", servicesize);
809
ok(servicename[0] == 0, "Service name not empty\n");
810
811
servicesize = 1;
812
wcscpy(servicenameW, L"ABC");
813
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
814
ok(!ret, "Expected failure\n");
815
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
816
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
817
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
818
ok(servicenameW[0] == 'A', "Service name changed\n");
819
820
servicesize = 2;
821
strcpy(servicename, "ABC");
822
ret = GetServiceKeyNameA(scm_handle, "Deadbeef", servicename, &servicesize);
823
ok(!ret, "Expected failure\n");
824
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
825
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
826
todo_wine ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
827
ok(servicename[0] == 0, "Service name not empty\n");
828
829
servicesize = 2;
830
wcscpy(servicenameW, L"ABC");
831
ret = GetServiceKeyNameW(scm_handle, L"Deadbeef", servicenameW, &servicesize);
832
ok(!ret, "Expected failure\n");
833
ok(servicesize == 2, "Service size expected 2, got %ld\n", servicesize);
834
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
835
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
836
ok(servicenameW[0] == 0, "Service name not empty\n");
837
838
/* Check if 'Spooler' exists */
839
svc_handle = OpenServiceA(scm_handle, spooler, GENERIC_READ);
840
if (!svc_handle)
841
{
842
skip("Spooler service doesn't exist\n");
843
CloseServiceHandle(scm_handle);
844
return;
845
}
846
CloseServiceHandle(svc_handle);
847
848
/* Get the displayname for the 'Spooler' service */
849
GetServiceDisplayNameA(scm_handle, spooler, NULL, &displaysize);
850
GetServiceDisplayNameA(scm_handle, spooler, displayname, &displaysize);
851
852
/* Retrieve the needed size for the buffer */
853
SetLastError(0xdeadbeef);
854
servicesize = 0;
855
ret = GetServiceKeyNameA(scm_handle, displayname, NULL, &servicesize);
856
ok(!ret, "Expected failure\n");
857
if (strcmp(displayname, "Print Spooler") != 0 &&
858
GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
859
{
860
win_skip("GetServiceKeyName() does not support localized display names: %s\n", displayname); /* Windows 7 */
861
CloseServiceHandle(scm_handle);
862
return; /* All the tests that follow will fail too */
863
}
864
865
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
866
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
867
868
/* Valid call with the correct buffersize */
869
SetLastError(0xdeadbeef);
870
tempsize = servicesize;
871
servicesize *= 2;
872
ret = GetServiceKeyNameA(scm_handle, displayname, servicename, &servicesize);
873
ok(ret, "Expected success, got error %lu\n", GetLastError());
874
if (ret)
875
{
876
ok(strlen(servicename) == tempsize/2,
877
"Expected the buffer to be twice the length of the string\n") ;
878
ok(!lstrcmpiA(servicename, spooler), "Expected %s, got %s\n", spooler, servicename);
879
ok(servicesize == (tempsize * 2),
880
"Expected servicesize not to change if buffer not insufficient\n") ;
881
}
882
883
MultiByteToWideChar(CP_ACP, 0, displayname, -1, displaynameW, sizeof(displaynameW)/2);
884
SetLastError(0xdeadbeef);
885
servicesize *= 2;
886
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
887
ok(ret, "Expected success, got error %lu\n", GetLastError());
888
if (ret)
889
{
890
ok(strlen(servicename) == tempsize/2,
891
"Expected the buffer to be twice the length of the string\n") ;
892
ok(servicesize == lstrlenW(servicenameW),
893
"Expected servicesize not to change if buffer not insufficient\n") ;
894
}
895
896
SetLastError(0xdeadbeef);
897
servicesize = 3;
898
ret = GetServiceKeyNameW(scm_handle, displaynameW, servicenameW, &servicesize);
899
ok(!ret, "Expected failure\n");
900
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
901
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
902
ok(servicenameW[0] == 0, "Buffer not empty\n");
903
904
CloseServiceHandle(scm_handle);
905
}
906
907
static void test_query_svc(void)
908
{
909
SC_HANDLE scm_handle, svc_handle;
910
BOOL ret;
911
SERVICE_STATUS status;
912
SERVICE_STATUS_PROCESS *statusproc;
913
DWORD bufsize, needed;
914
915
/* All NULL or wrong */
916
SetLastError(0xdeadbeef);
917
ret = QueryServiceStatus(NULL, NULL);
918
ok(!ret, "Expected failure\n");
919
ok(GetLastError() == ERROR_INVALID_HANDLE,
920
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
921
922
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
923
924
/* Check if 'Spooler' exists.
925
* Open with not enough rights to query the status.
926
*/
927
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
928
if (!svc_handle)
929
{
930
skip("Spooler service doesn't exist\n");
931
CloseServiceHandle(scm_handle);
932
return;
933
}
934
935
SetLastError(0xdeadbeef);
936
ret = QueryServiceStatus(svc_handle, NULL);
937
ok(!ret, "Expected failure\n");
938
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
939
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
940
"Unexpected last error %ld\n", GetLastError());
941
942
SetLastError(0xdeadbeef);
943
ret = QueryServiceStatus(svc_handle, &status);
944
ok(!ret, "Expected failure\n");
945
ok(GetLastError() == ERROR_ACCESS_DENIED,
946
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
947
948
/* Open the service with just enough rights.
949
* (Verified with 'SERVICE_ALL_ACCESS &~ SERVICE_QUERY_STATUS')
950
*/
951
CloseServiceHandle(svc_handle);
952
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
953
954
SetLastError(0xdeadbeef);
955
ret = QueryServiceStatus(svc_handle, &status);
956
ok(ret, "Expected success, got error %lu\n", GetLastError());
957
958
CloseServiceHandle(svc_handle);
959
960
/* More or less the same tests for QueryServiceStatusEx */
961
if (!pQueryServiceStatusEx)
962
{
963
win_skip( "QueryServiceStatusEx not available\n" );
964
CloseServiceHandle(scm_handle);
965
return;
966
}
967
968
/* Open service with not enough rights to query the status */
969
svc_handle = OpenServiceA(scm_handle, spooler, STANDARD_RIGHTS_READ);
970
971
/* All NULL or wrong, this proves that info level is checked first */
972
SetLastError(0xdeadbeef);
973
ret = pQueryServiceStatusEx(NULL, 1, NULL, 0, NULL);
974
ok(!ret, "Expected failure\n");
975
ok(GetLastError() == ERROR_INVALID_LEVEL,
976
"Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
977
978
/* Passing a NULL parameter for the needed buffer size
979
* will crash on anything but NT4.
980
*/
981
982
/* Only info level is correct. It looks like the buffer/size is checked second */
983
SetLastError(0xdeadbeef);
984
ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
985
/* NT4 checks the handle first */
986
if (GetLastError() != ERROR_INVALID_HANDLE)
987
{
988
ok(!ret, "Expected failure\n");
989
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
990
"Needed buffersize is wrong : %ld\n", needed);
991
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
992
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
993
}
994
995
/* Pass a correct buffer and buffersize but a NULL handle */
996
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
997
bufsize = needed;
998
SetLastError(0xdeadbeef);
999
ret = pQueryServiceStatusEx(NULL, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1000
ok(!ret, "Expected failure\n");
1001
ok(GetLastError() == ERROR_INVALID_HANDLE,
1002
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1003
free(statusproc);
1004
1005
/* Correct handle and info level */
1006
SetLastError(0xdeadbeef);
1007
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, NULL, 0, &needed);
1008
/* NT4 doesn't return the needed size */
1009
if (GetLastError() != ERROR_INVALID_PARAMETER)
1010
{
1011
ok(!ret, "Expected failure\n");
1012
ok(needed == sizeof(SERVICE_STATUS_PROCESS),
1013
"Needed buffersize is wrong : %ld\n", needed);
1014
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1015
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
1016
}
1017
1018
/* All parameters are OK but we don't have enough rights */
1019
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1020
bufsize = sizeof(SERVICE_STATUS_PROCESS);
1021
SetLastError(0xdeadbeef);
1022
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1023
ok(!ret, "Expected failure\n");
1024
ok(GetLastError() == ERROR_ACCESS_DENIED,
1025
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1026
free(statusproc);
1027
1028
/* Open the service with just enough rights. */
1029
CloseServiceHandle(svc_handle);
1030
svc_handle = OpenServiceA(scm_handle, spooler, SERVICE_QUERY_STATUS);
1031
1032
/* Everything should be fine now. */
1033
statusproc = malloc(sizeof(SERVICE_STATUS_PROCESS));
1034
bufsize = sizeof(SERVICE_STATUS_PROCESS);
1035
SetLastError(0xdeadbeef);
1036
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, &needed);
1037
ok(ret, "Expected success, got error %lu\n", GetLastError());
1038
if (statusproc->dwCurrentState == SERVICE_RUNNING)
1039
ok(statusproc->dwProcessId != 0,
1040
"Expect a process id for this running service\n");
1041
else
1042
ok(statusproc->dwProcessId == 0,
1043
"Expect no process id for this stopped service\n");
1044
1045
/* same call with null needed pointer */
1046
SetLastError(0xdeadbeef);
1047
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)statusproc, bufsize, NULL);
1048
ok(!ret, "Expected failure\n");
1049
ok(broken(GetLastError() == ERROR_INVALID_PARAMETER) /* NT4 */ ||
1050
GetLastError() == ERROR_INVALID_ADDRESS, "got %ld\n", GetLastError());
1051
1052
free(statusproc);
1053
1054
CloseServiceHandle(svc_handle);
1055
CloseServiceHandle(scm_handle);
1056
}
1057
1058
static BOOL test_enum_svc(int attempt)
1059
{
1060
SC_HANDLE scm_handle;
1061
BOOL ret, alldone = FALSE;
1062
DWORD bufsize, needed, returned, resume;
1063
DWORD neededA, returnedA;
1064
DWORD tempneeded, tempreturned, missing;
1065
DWORD servicecountactive, servicecountinactive;
1066
ENUM_SERVICE_STATUSA *servicesA;
1067
ENUM_SERVICE_STATUSW *services;
1068
UINT i;
1069
1070
/* All NULL or wrong */
1071
SetLastError(0xdeadbeef);
1072
ret = EnumServicesStatusA(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1073
ok(!ret, "Expected failure\n");
1074
ok(GetLastError() == ERROR_INVALID_HANDLE,
1075
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1076
1077
SetLastError(0xdeadbeef);
1078
ret = EnumServicesStatusW(NULL, 1, 0, NULL, 0, NULL, NULL, NULL);
1079
ok(!ret, "Expected failure\n");
1080
ok(GetLastError() == ERROR_INVALID_HANDLE,
1081
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1082
1083
/* Open the service control manager with not enough rights at first */
1084
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1085
1086
/* Valid handle but rest is still NULL or wrong */
1087
SetLastError(0xdeadbeef);
1088
ret = EnumServicesStatusA(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1089
ok(!ret, "Expected failure\n");
1090
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1091
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1092
"Unexpected last error %ld\n", GetLastError());
1093
1094
SetLastError(0xdeadbeef);
1095
ret = EnumServicesStatusW(scm_handle, 1, 0, NULL, 0, NULL, NULL, NULL);
1096
ok(!ret, "Expected failure\n");
1097
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1098
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1099
"Unexpected last error %ld\n", GetLastError());
1100
1101
/* Don't specify the two required pointers */
1102
returned = 0xdeadbeef;
1103
SetLastError(0xdeadbeef);
1104
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1105
ok(!ret, "Expected failure\n");
1106
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1107
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1108
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1109
"Unexpected last error %ld\n", GetLastError());
1110
1111
returned = 0xdeadbeef;
1112
SetLastError(0xdeadbeef);
1113
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, NULL, &returned, NULL);
1114
ok(!ret, "Expected failure\n");
1115
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1116
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1117
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1118
"Unexpected last error %ld\n", GetLastError());
1119
1120
/* Don't specify the two required pointers */
1121
needed = 0xdeadbeef;
1122
SetLastError(0xdeadbeef);
1123
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1124
ok(!ret, "Expected failure\n");
1125
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1126
"Expected no change to the needed buffer variable\n");
1127
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1128
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1129
"Unexpected last error %ld\n", GetLastError());
1130
1131
needed = 0xdeadbeef;
1132
SetLastError(0xdeadbeef);
1133
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, NULL, NULL);
1134
ok(!ret, "Expected failure\n");
1135
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1136
"Expected no change to the needed buffer variable\n");
1137
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1138
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1139
"Unexpected last error %ld\n", GetLastError());
1140
1141
/* No valid servicetype and servicestate */
1142
needed = 0xdeadbeef;
1143
returned = 0xdeadbeef;
1144
SetLastError(0xdeadbeef);
1145
ret = EnumServicesStatusA(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1146
ok(!ret, "Expected failure\n");
1147
ok(needed == 0 || broken(needed != 0), /* nt4 */
1148
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1149
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1150
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1151
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1152
1153
needed = 0xdeadbeef;
1154
returned = 0xdeadbeef;
1155
SetLastError(0xdeadbeef);
1156
ret = EnumServicesStatusW(scm_handle, 0, 0, NULL, 0, &needed, &returned, NULL);
1157
ok(!ret, "Expected failure\n");
1158
ok(needed == 0 || broken(needed != 0), /* nt4 */
1159
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1160
ok(returned == 0 || broken(returned != 0), /* nt4 */
1161
"Expected number of services to be set to 0, got %ld\n", returned);
1162
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1163
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1164
1165
/* No valid servicestate */
1166
needed = 0xdeadbeef;
1167
returned = 0xdeadbeef;
1168
SetLastError(0xdeadbeef);
1169
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1170
ok(!ret, "Expected failure\n");
1171
ok(needed == 0 || broken(needed != 0), /* nt4 */
1172
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1173
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1174
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1175
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1176
1177
needed = 0xdeadbeef;
1178
returned = 0xdeadbeef;
1179
SetLastError(0xdeadbeef);
1180
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, 0, NULL, 0, &needed, &returned, NULL);
1181
ok(!ret, "Expected failure\n");
1182
ok(needed == 0 || broken(needed != 0), /* nt4 */
1183
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1184
ok(returned == 0 || broken(returned != 0), /* nt4 */
1185
"Expected number of services to be set to 0, got %ld\n", returned);
1186
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1187
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1188
1189
/* No valid servicetype */
1190
needed = 0xdeadbeef;
1191
returned = 0xdeadbeef;
1192
SetLastError(0xdeadbeef);
1193
ret = EnumServicesStatusA(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1194
ok(!ret, "Expected failure\n");
1195
ok(needed == 0 || broken(needed != 0), /* nt4 */
1196
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1197
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1198
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1199
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1200
1201
needed = 0xdeadbeef;
1202
returned = 0xdeadbeef;
1203
SetLastError(0xdeadbeef);
1204
ret = EnumServicesStatusW(scm_handle, 0, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1205
ok(!ret, "Expected failure\n");
1206
ok(needed == 0 || broken(needed != 0), /* nt4 */
1207
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1208
ok(returned == 0 || broken(returned != 0), /* nt4 */
1209
"Expected number of services to be set to 0, got %ld\n", returned);
1210
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1211
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1212
1213
/* All parameters are correct but our access rights are wrong */
1214
needed = 0xdeadbeef;
1215
returned = 0xdeadbeef;
1216
SetLastError(0xdeadbeef);
1217
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1218
ok(!ret, "Expected failure\n");
1219
ok(needed == 0 || broken(needed != 0), /* nt4 */
1220
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1221
ok(returned == 0, "Expected number of services to be set to 0, got %ld\n", returned);
1222
ok(GetLastError() == ERROR_ACCESS_DENIED,
1223
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1224
1225
needed = 0xdeadbeef;
1226
returned = 0xdeadbeef;
1227
SetLastError(0xdeadbeef);
1228
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1229
ok(!ret, "Expected failure\n");
1230
ok(needed == 0 || broken(needed != 0), /* nt4 */
1231
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1232
ok(returned == 0 || broken(returned != 0), /* nt4 */
1233
"Expected number of services to be set to 0, got %ld\n", returned);
1234
ok(GetLastError() == ERROR_ACCESS_DENIED,
1235
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1236
1237
/* Open the service control manager with the needed rights */
1238
CloseServiceHandle(scm_handle);
1239
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1240
1241
/* All parameters are correct. Request the needed buffer size */
1242
needed = 0xdeadbeef;
1243
returned = 0xdeadbeef;
1244
SetLastError(0xdeadbeef);
1245
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL);
1246
ok(!ret, "Expected failure\n");
1247
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for this one service\n");
1248
ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1249
ok(GetLastError() == ERROR_MORE_DATA,
1250
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1251
1252
/* Test to show we get the same needed buffer size for the A-call */
1253
neededA = 0xdeadbeef;
1254
returnedA = 0xdeadbeef;
1255
SetLastError(0xdeadbeef);
1256
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &neededA, &returnedA, NULL);
1257
ok(!ret, "Expected failure\n");
1258
ok(GetLastError() == ERROR_MORE_DATA,
1259
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1260
ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1261
ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1262
if (neededA != needed && attempt)
1263
goto retry; /* service start|stop race condition */
1264
ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1265
1266
/* Store the needed bytes */
1267
tempneeded = needed;
1268
1269
/* Allocate the correct needed bytes */
1270
services = malloc(needed);
1271
bufsize = needed;
1272
needed = 0xdeadbeef;
1273
returned = 0xdeadbeef;
1274
SetLastError(0xdeadbeef);
1275
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1276
services, bufsize, &needed, &returned, NULL);
1277
free(services);
1278
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1279
goto retry; /* service start race condition */
1280
ok(ret, "Expected success, got error %lu\n", GetLastError());
1281
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1282
ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1283
1284
/* Store the number of returned services */
1285
tempreturned = returned;
1286
1287
servicesA = malloc(neededA);
1288
bufsize = neededA;
1289
neededA = 0xdeadbeef;
1290
returnedA = 0xdeadbeef;
1291
SetLastError(0xdeadbeef);
1292
ret = EnumServicesStatusA(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1293
servicesA, bufsize, &neededA, &returnedA, NULL);
1294
free(servicesA);
1295
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1296
goto retry; /* service start race condition */
1297
if (!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY && GetACP() == CP_UTF8)
1298
win_skip("Skipping some tests due to EnumServicesStatusA()'s broken UTF-8 support\n");
1299
else
1300
{
1301
ok(ret, "Expected success, got error %lu\n", GetLastError());
1302
ok(neededA == 0, "Expected needed buffer to be 0 as we are done\n");
1303
ok(returnedA != 0xdeadbeef && returnedA > 0, "Expected some returned services\n");
1304
}
1305
1306
/* Allocate less than the needed bytes and don't specify a resume handle.
1307
* More than one service will be missing because of the space needed for
1308
* the strings.
1309
*/
1310
services = malloc(tempneeded);
1311
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1312
needed = 0xdeadbeef;
1313
returned = 0xdeadbeef;
1314
SetLastError(0xdeadbeef);
1315
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1316
services, bufsize, &needed, &returned, NULL);
1317
if (ret && needed == 0 && attempt)
1318
{
1319
free(services);
1320
goto retry; /* service stop race condition */
1321
}
1322
ok(!ret, "Expected failure\n");
1323
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1324
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1325
/* Experiments show bufsize + needed < tempneeded which proves the needed
1326
* buffer size is an approximation. So it's best not to probe more.
1327
*/
1328
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1329
ok(GetLastError() == ERROR_MORE_DATA,
1330
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1331
1332
/* Allocate less than the needed bytes, this time with a correct resume handle */
1333
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1334
needed = 0xdeadbeef;
1335
returned = 0xdeadbeef;
1336
resume = 0;
1337
SetLastError(0xdeadbeef);
1338
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1339
services, bufsize, &needed, &returned, &resume);
1340
if (ret && needed == 0 && attempt)
1341
{
1342
free(services);
1343
goto retry; /* service stop race condition */
1344
}
1345
ok(!ret, "Expected failure\n");
1346
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services, got %lx\n", needed);
1347
todo_wine ok(needed < tempneeded, "Expected < %lu bytes needed for the remaining services, got %lu\n", tempneeded, needed);
1348
ok(returned < tempreturned, "Expected < %lu remaining services, got %lu\n", tempreturned, returned);
1349
todo_wine ok(resume, "Expected a resume handle\n");
1350
ok(GetLastError() == ERROR_MORE_DATA,
1351
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1352
1353
/* Fetch the missing services but pass a bigger buffer size */
1354
missing = tempreturned - returned;
1355
bufsize = tempneeded;
1356
needed = 0xdeadbeef;
1357
returned = 0xdeadbeef;
1358
SetLastError(0xdeadbeef);
1359
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1360
services, bufsize, &needed, &returned, &resume);
1361
free(services);
1362
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1363
goto retry; /* service start race condition */
1364
ok(ret, "Expected success, got error %lu\n", GetLastError());
1365
ok(needed == 0, "Expected 0 needed bytes as we are done, got %lu\n", needed);
1366
if (returned < missing && strcmp(winetest_platform, "wine") && attempt)
1367
goto retry; /* service stop race condition */
1368
todo_wine ok(returned == missing, "Expected %lu remaining services, got %lu\n", missing, returned);
1369
ok(resume == 0, "Expected the resume handle to be 0\n");
1370
1371
/* See if things add up */
1372
1373
/* Vista only shows the drivers with a state of SERVICE_RUNNING as active
1374
* and doesn't count the others as inactive. This means that Vista could
1375
* show a total that is greater than the sum of active and inactive
1376
* drivers.
1377
* The number of active and inactive drivers is greatly influenced by the
1378
* time when tests are run, immediately after boot or later for example.
1379
*
1380
* Both reasons make calculations for drivers not so useful
1381
*/
1382
1383
/* Get the number of active win32 services */
1384
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0,
1385
&needed, &returned, NULL);
1386
services = malloc(needed);
1387
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_ACTIVE,
1388
services, needed, &needed, &returned, NULL);
1389
free(services);
1390
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1391
goto retry; /* service start race condition */
1392
1393
servicecountactive = returned;
1394
1395
/* Get the number of inactive win32 services */
1396
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0,
1397
&needed, &returned, NULL);
1398
services = malloc(needed);
1399
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_INACTIVE,
1400
services, needed, &needed, &returned, NULL);
1401
free(services);
1402
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1403
goto retry; /* service start race condition */
1404
1405
servicecountinactive = returned;
1406
1407
/* Get the number of win32 services */
1408
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0,
1409
&needed, &returned, NULL);
1410
services = malloc(needed);
1411
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1412
services, needed, &needed, &returned, NULL);
1413
free(services);
1414
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1415
goto retry; /* service start race condition */
1416
1417
/* Check if total is the same as active and inactive win32 services */
1418
if (returned != servicecountactive + servicecountinactive && attempt)
1419
goto retry; /* service start|stop race condition */
1420
ok(returned == servicecountactive + servicecountinactive,
1421
"Expected service count %ld == %ld + %ld\n",
1422
returned, servicecountactive, servicecountinactive);
1423
1424
/* Get all drivers and services
1425
*
1426
* Fetch the status of the last call as failing could make the following tests crash
1427
* on Wine (we don't return anything yet).
1428
*/
1429
EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1430
NULL, 0, &needed, &returned, NULL);
1431
services = malloc(needed);
1432
ret = EnumServicesStatusW(scm_handle, SERVICE_DRIVER | SERVICE_WIN32, SERVICE_STATE_ALL,
1433
services, needed, &needed, &returned, NULL);
1434
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1435
goto retry; /* service start race condition */
1436
ok(ret, "Expected success %lu\n", GetLastError());
1437
1438
/* Loop through all those returned drivers and services */
1439
for (i = 0; ret && i < returned; i++)
1440
{
1441
SERVICE_STATUS status = services[i].ServiceStatus;
1442
1443
/* lpServiceName and lpDisplayName should always be filled */
1444
ok(services[i].lpServiceName[0], "Expected a service name\n");
1445
ok(services[i].lpDisplayName && services[i].lpDisplayName[0], "Expected a display name\n");
1446
1447
/* Decrement the counters to see if the functions calls return the same
1448
* numbers as the contents of these structures.
1449
*/
1450
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1451
{
1452
switch (status.dwCurrentState)
1453
{
1454
case SERVICE_START_PENDING:
1455
case SERVICE_STOP_PENDING:
1456
case SERVICE_PAUSE_PENDING:
1457
case SERVICE_PAUSED:
1458
case SERVICE_CONTINUE_PENDING:
1459
trace("Got state %lx for service %s\n", status.dwCurrentState,
1460
wine_dbgstr_w(services[i].lpServiceName));
1461
/* fall through */
1462
1463
case SERVICE_RUNNING:
1464
servicecountactive--;
1465
break;
1466
1467
case SERVICE_STOPPED:
1468
servicecountinactive--;
1469
break;
1470
1471
default:
1472
ok(0, "Got unknown state %lx for service %s\n",
1473
status.dwCurrentState, wine_dbgstr_w(services[i].lpServiceName));
1474
break;
1475
}
1476
}
1477
}
1478
free(services);
1479
1480
if ((servicecountactive || servicecountinactive) && attempt)
1481
goto retry; /* service start|stop race condition */
1482
ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1483
ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1484
1485
alldone = TRUE;
1486
1487
retry:
1488
CloseServiceHandle(scm_handle);
1489
return alldone;
1490
}
1491
1492
static BOOL test_enum_svc_ex(int attempt)
1493
{
1494
SC_HANDLE scm_handle;
1495
BOOL ret, alldone = FALSE;
1496
DWORD bufsize, needed, returned, resume;
1497
DWORD neededA, returnedA;
1498
DWORD tempneeded, tempreturned, missing;
1499
DWORD servicecountactive, servicecountinactive;
1500
ENUM_SERVICE_STATUSW *services;
1501
ENUM_SERVICE_STATUS_PROCESSW *exservices;
1502
UINT i;
1503
1504
/* More or less the same for EnumServicesStatusExA */
1505
if (!pEnumServicesStatusExA)
1506
{
1507
win_skip( "EnumServicesStatusExA not available\n" );
1508
return TRUE;
1509
}
1510
1511
/* All NULL or wrong */
1512
SetLastError(0xdeadbeef);
1513
ret = pEnumServicesStatusExA(NULL, 1, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1514
ok(!ret, "Expected failure\n");
1515
ok(GetLastError() == ERROR_INVALID_LEVEL,
1516
"Expected ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
1517
1518
/* All NULL or wrong, just the info level is correct */
1519
SetLastError(0xdeadbeef);
1520
ret = pEnumServicesStatusExA(NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1521
ok(!ret, "Expected failure\n");
1522
ok(GetLastError() == ERROR_INVALID_HANDLE,
1523
"Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1524
1525
/* Open the service control manager with not enough rights at first */
1526
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1527
1528
/* Valid handle and info level but rest is still NULL or wrong */
1529
SetLastError(0xdeadbeef);
1530
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1531
ok(!ret, "Expected failure\n");
1532
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1533
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1534
"Unexpected last error %ld\n", GetLastError());
1535
1536
/* Don't specify the two required pointers */
1537
needed = 0xdeadbeef;
1538
SetLastError(0xdeadbeef);
1539
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, NULL, NULL, NULL);
1540
ok(!ret, "Expected failure\n");
1541
ok(needed == 0xdeadbeef || broken(needed != 0xdeadbeef), /* nt4 */
1542
"Expected no change to the needed buffer variable\n");
1543
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1544
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1545
"Unexpected last error %ld\n", GetLastError());
1546
1547
/* Don't specify the two required pointers */
1548
returned = 0xdeadbeef;
1549
SetLastError(0xdeadbeef);
1550
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, NULL, &returned, NULL, NULL);
1551
ok(!ret, "Expected failure\n");
1552
ok(returned == 0xdeadbeef, "Expected no change to the number of services variable\n");
1553
ok(GetLastError() == ERROR_INVALID_ADDRESS ||
1554
GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */,
1555
"Unexpected last error %ld\n", GetLastError());
1556
1557
/* No valid servicetype and servicestate */
1558
needed = 0xdeadbeef;
1559
returned = 0xdeadbeef;
1560
SetLastError(0xdeadbeef);
1561
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed, &returned, NULL, NULL);
1562
ok(!ret, "Expected failure\n");
1563
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1564
ok(needed == 0 || broken(needed != 0), /* nt4 */
1565
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1566
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1567
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1568
1569
/* No valid servicestate */
1570
needed = 0xdeadbeef;
1571
returned = 0xdeadbeef;
1572
SetLastError(0xdeadbeef);
1573
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, 0, NULL, 0,
1574
&needed, &returned, NULL, NULL);
1575
ok(!ret, "Expected failure\n");
1576
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1577
ok(needed == 0 || broken(needed != 0), /* nt4 */
1578
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1579
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1580
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1581
1582
/* No valid servicetype */
1583
needed = 0xdeadbeef;
1584
returned = 0xdeadbeef;
1585
SetLastError(0xdeadbeef);
1586
ret = pEnumServicesStatusExA(scm_handle, 0, 0, SERVICE_STATE_ALL, NULL, 0,
1587
&needed, &returned, NULL, NULL);
1588
ok(!ret, "Expected failure\n");
1589
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1590
ok(needed == 0 || broken(needed != 0), /* nt4 */
1591
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1592
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1593
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1594
1595
/* No valid servicetype and servicestate and unknown service group */
1596
needed = 0xdeadbeef;
1597
returned = 0xdeadbeef;
1598
SetLastError(0xdeadbeef);
1599
ret = pEnumServicesStatusExA(scm_handle, 0, 0, 0, NULL, 0, &needed,
1600
&returned, NULL, "deadbeef_group");
1601
ok(!ret, "Expected failure\n");
1602
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1603
ok(needed == 0 || broken(needed != 0), /* nt4 */
1604
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1605
ok(GetLastError() == ERROR_INVALID_PARAMETER,
1606
"Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
1607
1608
/* All parameters are correct but our access rights are wrong */
1609
needed = 0xdeadbeef;
1610
returned = 0xdeadbeef;
1611
SetLastError(0xdeadbeef);
1612
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1613
NULL, 0, &needed, &returned, NULL, NULL);
1614
ok(!ret, "Expected failure\n");
1615
ok(needed == 0 || broken(needed != 0), /* nt4 */
1616
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1617
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1618
ok(GetLastError() == ERROR_ACCESS_DENIED,
1619
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1620
1621
/* All parameters are correct, access rights are wrong but the
1622
* group name won't be checked yet.
1623
*/
1624
needed = 0xdeadbeef;
1625
returned = 0xdeadbeef;
1626
SetLastError(0xdeadbeef);
1627
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1628
NULL, 0, &needed, &returned, NULL, "deadbeef_group");
1629
ok(!ret, "Expected failure\n");
1630
ok(needed == 0 || broken(needed != 0), /* nt4 */
1631
"Expected needed buffer size to be set to 0, got %ld\n", needed);
1632
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1633
ok(GetLastError() == ERROR_ACCESS_DENIED,
1634
"Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1635
1636
/* Open the service control manager with the needed rights */
1637
CloseServiceHandle(scm_handle);
1638
scm_handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
1639
1640
/* All parameters are correct and the group will be checked */
1641
needed = 0xdeadbeef;
1642
returned = 0xdeadbeef;
1643
SetLastError(0xdeadbeef);
1644
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1645
NULL, 0, &needed, &returned, NULL, L"deadbeef_group");
1646
ok(!ret, "Expected failure\n");
1647
ok(returned == 0, "Expected number of service to be set to 0, got %ld\n", returned);
1648
ok(needed == 0, "Expected needed buffer size to be set to 0, got %ld\n", needed);
1649
ok(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST,
1650
"Expected ERROR_SERVICE_DOES_NOT_EXIST, got %ld\n", GetLastError());
1651
1652
/* TODO: Create a test that makes sure we enumerate all services that don't
1653
* belong to a group. (specifying "").
1654
*/
1655
1656
/* All parameters are correct. Request the needed buffer size */
1657
needed = 0xdeadbeef;
1658
returned = 0xdeadbeef;
1659
SetLastError(0xdeadbeef);
1660
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1661
NULL, 0, &needed, &returned, NULL, NULL);
1662
ok(!ret, "Expected failure\n");
1663
ok(returned == 0, "Expected no service returned, got %ld\n", returned);
1664
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size\n");
1665
ok(GetLastError() == ERROR_MORE_DATA,
1666
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1667
1668
/* Test to show we get the same needed buffer size for the A-call */
1669
neededA = 0xdeadbeef;
1670
returnedA = 0xdeadbeef;
1671
SetLastError(0xdeadbeef);
1672
ret = pEnumServicesStatusExA(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1673
NULL, 0, &neededA, &returnedA, NULL, NULL);
1674
ok(!ret, "Expected failure\n");
1675
ok(GetLastError() == ERROR_MORE_DATA,
1676
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1677
ok(neededA != 0xdeadbeef && neededA > 0, "Expected the needed buffer size for this one service\n");
1678
ok(returnedA == 0, "Expected no service returned, got %ld\n", returnedA);
1679
if (neededA != needed && attempt)
1680
goto retry; /* service start|stop race condition */
1681
ok(neededA == needed, "Expected needed buffersize to be the same for A- and W-calls\n");
1682
ok(GetLastError() == ERROR_MORE_DATA,
1683
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1684
1685
/* Store the needed bytes */
1686
tempneeded = needed;
1687
1688
/* Show the Ex call returns the same service count as the regular enum */
1689
EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1690
NULL, 0, &needed, &returned, NULL);
1691
services = malloc(needed);
1692
returned = 0xdeadbeef;
1693
ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL,
1694
services, needed, &needed, &returned, NULL);
1695
free(services);
1696
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1697
goto retry; /* service start race condition */
1698
ok(ret, "Expected success, got error %lu\n", GetLastError());
1699
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1700
ok(returned != 0xdeadbeef && returned > 0, "Expected some returned services\n");
1701
1702
/* Store the number of returned services */
1703
tempreturned = returned;
1704
1705
/* Allocate the correct needed bytes */
1706
exservices = malloc(tempneeded);
1707
bufsize = tempneeded;
1708
needed = 0xdeadbeef;
1709
returned = 0xdeadbeef;
1710
SetLastError(0xdeadbeef);
1711
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1712
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1713
free(exservices);
1714
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1715
goto retry; /* service start race condition */
1716
ok(ret, "Expected success, got error %lu\n", GetLastError());
1717
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1718
ok(returned == tempreturned, "Expected the same number of service from this function\n");
1719
1720
/* Store the number of returned services */
1721
tempreturned = returned;
1722
1723
/* Allocate less than the needed bytes and don't specify a resume handle.
1724
* More than one service will be missing because of the space needed for
1725
* the strings.
1726
*/
1727
exservices = malloc(tempneeded);
1728
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1729
needed = 0xdeadbeef;
1730
returned = 0xdeadbeef;
1731
SetLastError(0xdeadbeef);
1732
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1733
(BYTE*)exservices, bufsize, &needed, &returned, NULL, NULL);
1734
if (ret && needed == 0 && attempt)
1735
{
1736
free(exservices);
1737
goto retry; /* service stop race condition */
1738
}
1739
ok(!ret, "Expected failure\n");
1740
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1741
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1742
/* Experiments show bufsize + needed < tempneeded which proves the needed
1743
* buffer size is an approximation. So it's best not to probe more.
1744
*/
1745
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1746
ok(GetLastError() == ERROR_MORE_DATA,
1747
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1748
1749
/* Allocate less than the needed bytes, this time with a correct resume handle */
1750
bufsize = (tempreturned - 1) * sizeof(ENUM_SERVICE_STATUSW);
1751
needed = 0xdeadbeef;
1752
returned = 0xdeadbeef;
1753
resume = 0;
1754
SetLastError(0xdeadbeef);
1755
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1756
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1757
if (ret && needed == 0 && attempt)
1758
{
1759
free(exservices);
1760
goto retry; /* service stop race condition */
1761
}
1762
ok(!ret, "Expected failure\n");
1763
ok(needed != 0xdeadbeef && needed > 0, "Expected the needed buffer size for the missing services\n");
1764
todo_wine ok(needed < tempneeded, "Expected a smaller needed buffer size for the missing services\n");
1765
ok(returned < tempreturned, "Expected fewer services to be returned\n");
1766
todo_wine ok(resume, "Expected a resume handle\n");
1767
ok(GetLastError() == ERROR_MORE_DATA,
1768
"Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
1769
1770
/* Fetch the missing services but pass a bigger buffer size */
1771
missing = tempreturned - returned;
1772
bufsize = tempneeded;
1773
needed = 0xdeadbeef;
1774
returned = 0xdeadbeef;
1775
SetLastError(0xdeadbeef);
1776
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1777
(BYTE*)exservices, bufsize, &needed, &returned, &resume, NULL);
1778
free(exservices);
1779
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1780
goto retry; /* service start race condition */
1781
ok(ret, "Expected success, got error %lu\n", GetLastError());
1782
ok(needed == 0, "Expected needed buffer to be 0 as we are done\n");
1783
ok(returned == missing, "Expected %lu services to be returned\n", missing);
1784
ok(resume == 0, "Expected the resume handle to be 0\n");
1785
1786
/* See if things add up */
1787
1788
/* Get the number of active win32 services */
1789
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1790
NULL, 0, &needed, &returned, NULL, NULL);
1791
exservices = malloc(needed);
1792
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_ACTIVE,
1793
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1794
free(exservices);
1795
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1796
goto retry; /* service start race condition */
1797
1798
servicecountactive = returned;
1799
1800
/* Get the number of inactive win32 services */
1801
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1802
NULL, 0, &needed, &returned, NULL, NULL);
1803
exservices = malloc(needed);
1804
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_INACTIVE,
1805
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1806
free(exservices);
1807
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1808
goto retry; /* service start race condition */
1809
1810
servicecountinactive = returned;
1811
1812
/* Get the number of win32 services */
1813
pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1814
NULL, 0, &needed, &returned, NULL, NULL);
1815
exservices = malloc(needed);
1816
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL,
1817
(BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1818
free(exservices);
1819
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1820
goto retry; /* service start race condition */
1821
1822
/* Check if total is the same as active and inactive win32 services */
1823
if (returned != servicecountactive + servicecountinactive && attempt)
1824
goto retry; /* service start|stop race condition */
1825
ok(returned == servicecountactive + servicecountinactive,
1826
"Expected service count %ld == %ld + %ld\n",
1827
returned, servicecountactive, servicecountinactive);
1828
1829
/* Get all drivers and services */
1830
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1831
SERVICE_STATE_ALL, NULL, 0, &needed, &returned, NULL, NULL);
1832
ok(!ret, "Expected failure\n");
1833
exservices = malloc(needed);
1834
ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32 | SERVICE_DRIVER,
1835
SERVICE_STATE_ALL, (BYTE*)exservices, needed, &needed, &returned, NULL, NULL);
1836
if (!ret && GetLastError() == ERROR_MORE_DATA && attempt)
1837
goto retry; /* service start race condition */
1838
ok(ret, "Expected success %lu\n", GetLastError());
1839
1840
/* Loop through all those returned drivers and services */
1841
for (i = 0; i < returned; i++)
1842
{
1843
SERVICE_STATUS_PROCESS status = exservices[i].ServiceStatusProcess;
1844
1845
/* lpServiceName and lpDisplayName should always be filled */
1846
ok(exservices[i].lpServiceName[0], "Expected a service name\n");
1847
ok(exservices[i].lpDisplayName && exservices[i].lpDisplayName[0], "Expected a display name\n");
1848
1849
/* Decrement the counters to see if the functions calls return the
1850
* same numbers as the contents of these structures.
1851
* Check some process id specifics.
1852
*/
1853
if (status.dwServiceType & (SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER))
1854
{
1855
/* We shouldn't have a process id for drivers */
1856
ok(status.dwProcessId == 0,
1857
"This driver shouldn't have an associated process id\n");
1858
}
1859
1860
if (status.dwServiceType & (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS))
1861
{
1862
switch (status.dwCurrentState)
1863
{
1864
case SERVICE_START_PENDING:
1865
case SERVICE_STOP_PENDING:
1866
trace("Got state %lx (pid=%04lx) for service %s\n",
1867
status.dwCurrentState, status.dwProcessId,
1868
wine_dbgstr_w(exservices[i].lpServiceName));
1869
/* There may or may not be a process id */
1870
servicecountactive--;
1871
break;
1872
1873
case SERVICE_PAUSE_PENDING:
1874
case SERVICE_PAUSED:
1875
case SERVICE_CONTINUE_PENDING:
1876
trace("Got state %lx (pid=%04lx) for service %s\n",
1877
status.dwCurrentState, status.dwProcessId,
1878
wine_dbgstr_w(exservices[i].lpServiceName));
1879
/* fall through */
1880
1881
case SERVICE_RUNNING:
1882
/* We expect a process id for every running service */
1883
ok(status.dwProcessId > 0, "Expected a process id for this running service (%s)\n",
1884
wine_dbgstr_w(exservices[i].lpServiceName));
1885
servicecountactive--;
1886
break;
1887
1888
case SERVICE_STOPPED:
1889
/* We shouldn't have a process id for inactive services */
1890
ok(status.dwProcessId == 0, "Service %s state %lu shouldn't have an associated process id\n",
1891
wine_dbgstr_w(exservices[i].lpServiceName), status.dwCurrentState);
1892
1893
servicecountinactive--;
1894
break;
1895
1896
default:
1897
ok(0, "Got unknown state %lx (pid=%04lx) for service %s\n",
1898
status.dwCurrentState, status.dwProcessId,
1899
wine_dbgstr_w(exservices[i].lpServiceName));
1900
break;
1901
}
1902
}
1903
}
1904
free(exservices);
1905
1906
if ((servicecountactive || servicecountinactive) && attempt)
1907
goto retry; /* service start|stop race condition */
1908
ok(servicecountactive == 0, "Active services mismatch %lu\n", servicecountactive);
1909
ok(servicecountinactive == 0, "Inactive services mismatch %lu\n", servicecountinactive);
1910
1911
alldone = TRUE;
1912
1913
retry:
1914
CloseServiceHandle(scm_handle);
1915
return alldone;
1916
}
1917
1918
static void test_close(void)
1919
{
1920
SC_HANDLE handle;
1921
BOOL ret;
1922
1923
/* NULL handle */
1924
SetLastError(0xdeadbeef);
1925
ret = CloseServiceHandle(NULL);
1926
ok(!ret, "Expected failure\n");
1927
ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1928
1929
/* TODO: Add some tests with invalid handles. These produce errors on Windows but crash on Wine */
1930
1931
/* Proper call */
1932
handle = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
1933
SetLastError(0xdeadbeef);
1934
ret = CloseServiceHandle(handle);
1935
ok(ret, "Expected success got error %lu\n", GetLastError());
1936
}
1937
1938
static void test_wow64(void)
1939
{
1940
SC_HANDLE manager, service;
1941
BOOL wow64, ret;
1942
HANDLE file;
1943
1944
if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &wow64) || !wow64)
1945
{
1946
skip("Not running under WoW64.\n");
1947
return;
1948
}
1949
1950
if (!(manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE)))
1951
{
1952
skip("Not enough permissions to create a service.\n");
1953
return;
1954
}
1955
1956
file = CreateFileA("C:\\windows\\syswow64\\winetestsvc.exe", GENERIC_WRITE,
1957
0, NULL, CREATE_ALWAYS, 0, NULL);
1958
CloseHandle(file);
1959
1960
service = CreateServiceA(manager, "winetestsvc", "winetestsvc",
1961
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE,
1962
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1963
"C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1964
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1965
ret = StartServiceA(service, 0, NULL);
1966
ok(!ret, "Expected failure.\n");
1967
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
1968
1969
ret = DeleteService(service);
1970
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
1971
CloseServiceHandle(service);
1972
1973
service = CreateServiceA(manager, "winetestsvc2", "winetestsvc2", SERVICE_START | DELETE,
1974
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1975
"C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
1976
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1977
ret = StartServiceA(service, 0, NULL);
1978
ok(!ret, "Expected failure.\n");
1979
todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
1980
1981
ret = DeleteService(service);
1982
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
1983
CloseServiceHandle(service);
1984
1985
ret = DeleteFileA("C:\\windows\\syswow64\\winetestsvc.exe");
1986
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
1987
1988
file = CreateFileA("C:\\windows\\sysnative\\winetestsvc.exe", GENERIC_WRITE,
1989
0, NULL, CREATE_ALWAYS, 0, NULL);
1990
CloseHandle(file);
1991
1992
service = CreateServiceA(manager, "winetestsvc3", "winetestsvc3", SERVICE_START | DELETE,
1993
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
1994
"C:\\windows\\system32\\winetestsvc.exe service serve", NULL, NULL, NULL, NULL, NULL);
1995
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
1996
ret = StartServiceA(service, 0, NULL);
1997
ok(!ret, "Expected failure.\n");
1998
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Got error %lu.\n", GetLastError());
1999
2000
ret = DeleteService(service);
2001
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2002
CloseServiceHandle(service);
2003
2004
service = CreateServiceA(manager, "winetestsvc4", "winetestsvc4", SERVICE_START | DELETE,
2005
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
2006
"C:\\windows\\system32\\winetestsvc.exe", NULL, NULL, NULL, NULL, NULL);
2007
ok(!!service, "Failed to create service, error %lu.\n", GetLastError());
2008
ret = StartServiceA(service, 0, NULL);
2009
ok(!ret, "Expected failure.\n");
2010
todo_wine ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Got error %lu.\n", GetLastError());
2011
2012
ret = DeleteService(service);
2013
ok(ret, "Failed to delete service, error %lu.\n", GetLastError());
2014
CloseServiceHandle(service);
2015
2016
ret = DeleteFileA("C:\\windows\\sysnative\\winetestsvc.exe");
2017
ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
2018
2019
CloseServiceHandle(manager);
2020
}
2021
2022
static void test_sequence(void)
2023
{
2024
SC_HANDLE scm_handle, svc_handle;
2025
BOOL ret, is_nt4;
2026
QUERY_SERVICE_CONFIGA *config;
2027
DWORD given, needed;
2028
static const CHAR servicename [] = "winetest_sequence";
2029
static const CHAR displayname [] = "Winetest dummy service";
2030
static const CHAR displayname2[] = "Winetest dummy service (2)";
2031
static const CHAR pathname [] = "we_dont_care.exe";
2032
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2033
static const CHAR password [] = "";
2034
static const CHAR empty [] = "";
2035
static const CHAR localsystem [] = "LocalSystem";
2036
2037
SetLastError(0xdeadbeef);
2038
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2039
2040
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2041
{
2042
skip("Not enough rights to get a handle to the manager\n");
2043
return;
2044
}
2045
else
2046
ok(scm_handle != NULL, "Could not get a handle to the manager: %ld\n", GetLastError());
2047
2048
if (!scm_handle) return;
2049
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2050
is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2051
CloseServiceHandle(svc_handle);
2052
2053
/* Create a dummy service */
2054
SetLastError(0xdeadbeef);
2055
svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2056
SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
2057
pathname, NULL, NULL, dependencies, NULL, password);
2058
2059
if (!svc_handle && (GetLastError() == ERROR_SERVICE_EXISTS))
2060
{
2061
/* We try and open the service and do the rest of the tests. Some could
2062
* fail if the tests were changed between these runs.
2063
*/
2064
trace("Deletion probably didn't work last time\n");
2065
SetLastError(0xdeadbeef);
2066
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2067
if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2068
{
2069
skip("Not enough rights to open the service\n");
2070
CloseServiceHandle(scm_handle);
2071
return;
2072
}
2073
ok(svc_handle != NULL, "Could not open the service : %ld\n", GetLastError());
2074
}
2075
else if (!svc_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2076
{
2077
skip("Not enough rights to create the service\n");
2078
CloseServiceHandle(scm_handle);
2079
return;
2080
}
2081
else
2082
{
2083
ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2084
if (svc_handle != NULL)
2085
{
2086
PSID sidOwner, sidGroup;
2087
PACL dacl, sacl;
2088
PSECURITY_DESCRIPTOR pSD;
2089
DWORD error, n1, n2;
2090
HRESULT retval;
2091
BOOL bret;
2092
2093
/* Test using GetSecurityInfo to obtain security information */
2094
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, &sidOwner,
2095
&sidGroup, &dacl, &sacl, &pSD);
2096
LocalFree(pSD);
2097
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2098
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2099
NULL, NULL, NULL, &pSD);
2100
LocalFree(pSD);
2101
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2102
if (!is_nt4)
2103
{
2104
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2105
NULL, &dacl, NULL, &pSD);
2106
ok(retval == ERROR_SUCCESS, "Expected GetSecurityInfo to succeed: result %ld\n", retval);
2107
LocalFree(pSD);
2108
SetLastError(0xdeadbeef);
2109
retval = GetSecurityInfo(svc_handle, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL,
2110
NULL, NULL, NULL, NULL);
2111
error = GetLastError();
2112
ok(retval == ERROR_INVALID_PARAMETER, "Expected GetSecurityInfo to fail: result %ld\n", retval);
2113
ok(error == 0xdeadbeef, "Unexpected last error %ld\n", error);
2114
}
2115
else
2116
win_skip("A NULL security descriptor in GetSecurityInfo results in an exception on NT4.\n");
2117
2118
/* Test using QueryServiceObjectSecurity to obtain security information */
2119
SetLastError(0xdeadbeef);
2120
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, NULL, 0, &n1);
2121
error = GetLastError();
2122
ok(!bret, "Expected QueryServiceObjectSecurity to fail: result %d\n", bret);
2123
ok(error == ERROR_INSUFFICIENT_BUFFER ||
2124
broken(error == ERROR_INVALID_ADDRESS) || broken(error == ERROR_INVALID_PARAMETER),
2125
"Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", error);
2126
if (error != ERROR_INSUFFICIENT_BUFFER) n1 = 1024;
2127
pSD = LocalAlloc(0, n1);
2128
bret = pQueryServiceObjectSecurity(svc_handle, DACL_SECURITY_INFORMATION, pSD, n1, &n2);
2129
ok(bret, "Expected QueryServiceObjectSecurity to succeed: result %d\n", bret);
2130
LocalFree(pSD);
2131
}
2132
}
2133
2134
if (!svc_handle) {
2135
CloseServiceHandle(scm_handle);
2136
return;
2137
}
2138
2139
/* TODO:
2140
* Before we do a QueryServiceConfig we should check the registry. This will make sure
2141
* that the correct keys are used.
2142
*/
2143
2144
/* Request the size for the buffer */
2145
SetLastError(0xdeadbeef);
2146
ret = QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2147
ok(!ret, "Expected failure\n");
2148
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2149
2150
config = malloc(needed);
2151
given = needed;
2152
SetLastError(0xdeadbeef);
2153
ret = QueryServiceConfigA(svc_handle, config, given, &needed);
2154
ok(ret, "Expected success, got error %lu\n", GetLastError());
2155
2156
ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2157
config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2158
ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
2159
"Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2160
ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2161
ok(config->dwErrorControl == SERVICE_ERROR_IGNORE, "Expected SERVICE_ERROR_IGNORE, got %ld\n", config->dwErrorControl);
2162
ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2163
ok(!strcmp(config->lpLoadOrderGroup, empty), "Expected an empty string, got '%s'\n", config->lpLoadOrderGroup);
2164
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2165
/* TODO: Show the double 0 terminated string */
2166
todo_wine
2167
{
2168
ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n");
2169
}
2170
ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2171
ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName);
2172
2173
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_ERROR_NORMAL, NULL, "TestGroup2",
2174
NULL, NULL, NULL, NULL, displayname2);
2175
ok(ret, "ChangeServiceConfig failed (err=%ld)\n", GetLastError());
2176
2177
QueryServiceConfigA(svc_handle, NULL, 0, &needed);
2178
config = realloc(config, needed);
2179
ok(QueryServiceConfigA(svc_handle, config, needed, &needed), "QueryServiceConfig failed\n");
2180
ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName &&
2181
config->lpDisplayName, "Expected all string struct members to be non-NULL\n");
2182
ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS),
2183
"Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %ld\n", config->dwServiceType);
2184
ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %ld\n", config->dwStartType);
2185
ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "Expected SERVICE_ERROR_NORMAL, got %ld\n", config->dwErrorControl);
2186
ok(!strcmp(config->lpBinaryPathName, pathname), "Expected '%s', got '%s'\n", pathname, config->lpBinaryPathName);
2187
ok(!strcmp(config->lpLoadOrderGroup, "TestGroup2"), "Expected 'TestGroup2', got '%s'\n", config->lpLoadOrderGroup);
2188
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2189
ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName);
2190
ok(!strcmp(config->lpDisplayName, displayname2), "Expected '%s', got '%s'\n", displayname2, config->lpDisplayName);
2191
2192
SetLastError(0xdeadbeef);
2193
ret = DeleteService(svc_handle);
2194
ok(ret, "Expected success, got error %lu\n", GetLastError());
2195
CloseServiceHandle(svc_handle);
2196
CloseServiceHandle(scm_handle);
2197
free(config);
2198
}
2199
2200
static void test_queryconfig2(void)
2201
{
2202
SC_HANDLE scm_handle, svc_handle;
2203
BOOL ret;
2204
DWORD expected, needed;
2205
BYTE buffer[MAX_PATH];
2206
LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
2207
LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
2208
SERVICE_PRESHUTDOWN_INFO preshutdown_info;
2209
SERVICE_DELAYED_AUTO_START_INFO auto_start_info;
2210
static const CHAR servicename [] = "winetest_query_config2";
2211
static const CHAR displayname [] = "Winetest dummy service";
2212
static const CHAR pathname [] = "we_dont_care.exe";
2213
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
2214
static const CHAR password [] = "";
2215
static const CHAR description [] = "Description";
2216
static const WCHAR descriptionW [] = L"DescriptionW";
2217
2218
if(!pQueryServiceConfig2A)
2219
{
2220
win_skip("function QueryServiceConfig2A not present\n");
2221
return;
2222
}
2223
2224
SetLastError(0xdeadbeef);
2225
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2226
2227
if (!scm_handle)
2228
{
2229
if(GetLastError() == ERROR_ACCESS_DENIED)
2230
skip("Not enough rights to get a handle to the manager\n");
2231
else
2232
ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2233
return;
2234
}
2235
2236
/* Create a dummy service */
2237
SetLastError(0xdeadbeef);
2238
svc_handle = CreateServiceA(scm_handle, servicename, displayname, GENERIC_ALL,
2239
SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, SERVICE_DISABLED, SERVICE_ERROR_IGNORE,
2240
pathname, NULL, NULL, dependencies, NULL, password);
2241
2242
if (!svc_handle)
2243
{
2244
if(GetLastError() == ERROR_SERVICE_EXISTS)
2245
{
2246
/* We try and open the service and do the rest of the tests. Some could
2247
* fail if the tests were changed between these runs.
2248
*/
2249
trace("Deletion probably didn't work last time\n");
2250
SetLastError(0xdeadbeef);
2251
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2252
if (!svc_handle)
2253
{
2254
if(GetLastError() == ERROR_ACCESS_DENIED)
2255
skip("Not enough rights to open the service\n");
2256
else
2257
ok(FALSE, "Could not open the service : %ld\n", GetLastError());
2258
CloseServiceHandle(scm_handle);
2259
return;
2260
}
2261
}
2262
if (GetLastError() == ERROR_ACCESS_DENIED)
2263
{
2264
skip("Not enough rights to create the service\n");
2265
CloseServiceHandle(scm_handle);
2266
return;
2267
}
2268
ok(svc_handle != NULL, "Could not create the service : %ld\n", GetLastError());
2269
if (!svc_handle)
2270
{
2271
CloseServiceHandle(scm_handle);
2272
return;
2273
}
2274
}
2275
SetLastError(0xdeadbeef);
2276
ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2277
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2278
ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2279
2280
SetLastError(0xdeadbeef);
2281
ret = pQueryServiceConfig2A(svc_handle,0xfff0,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2282
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2283
ok(ERROR_INVALID_LEVEL == GetLastError(), "expected error ERROR_INVALID_LEVEL, got %ld\n", GetLastError());
2284
2285
SetLastError(0xdeadbeef);
2286
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),NULL);
2287
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2288
ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2289
2290
SetLastError(0xdeadbeef);
2291
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed);
2292
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2293
ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()),
2294
"expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2295
2296
SetLastError(0xdeadbeef);
2297
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL);
2298
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2299
ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %ld\n", GetLastError());
2300
2301
needed = 0;
2302
SetLastError(0xdeadbeef);
2303
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA)-1,&needed);
2304
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2305
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2306
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2307
2308
needed = 0;
2309
pConfig->lpDescription = (LPSTR)0xdeadbeef;
2310
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2311
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2312
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2313
ok(!pConfig->lpDescription, "expected lpDescription to be NULL, got %p\n", pConfig->lpDescription);
2314
2315
SetLastError(0xdeadbeef);
2316
needed = 0;
2317
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2318
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2319
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2320
ok(needed == sizeof(SERVICE_DESCRIPTIONA), "got %ld\n", needed);
2321
2322
if(!pChangeServiceConfig2A)
2323
{
2324
win_skip("function ChangeServiceConfig2A not present\n");
2325
goto cleanup;
2326
}
2327
2328
pConfig->lpDescription = (LPSTR) description;
2329
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer);
2330
ok(ret, "ChangeServiceConfig2A failed\n");
2331
if (!ret) {
2332
goto cleanup;
2333
}
2334
2335
SetLastError(0xdeadbeef);
2336
needed = 0;
2337
expected = sizeof(SERVICE_DESCRIPTIONA) + sizeof(description) * sizeof(WCHAR); /* !! */
2338
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,sizeof(SERVICE_DESCRIPTIONA),&needed);
2339
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2340
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2341
ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2342
2343
SetLastError(0xdeadbeef);
2344
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed-1,&needed);
2345
ok(!ret, "expected QueryServiceConfig2A to fail\n");
2346
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2347
2348
SetLastError(0xdeadbeef);
2349
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer,needed,&needed);
2350
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2351
ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2352
"expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2353
2354
SetLastError(0xdeadbeef);
2355
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed + 1,&needed);
2356
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2357
ok(pConfig->lpDescription && !strcmp(description,pConfig->lpDescription),
2358
"expected lpDescription to be %s, got %s\n",description ,pConfig->lpDescription);
2359
2360
if(!pQueryServiceConfig2W)
2361
{
2362
win_skip("function QueryServiceConfig2W not present\n");
2363
goto cleanup;
2364
}
2365
SetLastError(0xdeadbeef);
2366
needed = 0;
2367
expected = sizeof(SERVICE_DESCRIPTIONW) + sizeof(WCHAR) * sizeof(description);
2368
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,0,&needed);
2369
ok(!ret, "expected QueryServiceConfig2W to fail\n");
2370
ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(), "expected error ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError());
2371
ok(needed == expected, "expected needed to be %ld, got %ld\n", expected, needed);
2372
2373
SetLastError(0xdeadbeef);
2374
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
2375
ok(ret, "expected QueryServiceConfig2W to succeed\n");
2376
2377
pConfig->lpDescription = (LPSTR)description;
2378
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2379
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2380
2381
pConfig->lpDescription = NULL;
2382
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2383
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2384
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2385
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2386
2387
pConfig->lpDescription = NULL;
2388
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2389
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2390
2391
pConfig->lpDescription = NULL;
2392
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2393
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2394
ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
2395
"expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
2396
2397
pConfig->lpDescription = (char*)"";
2398
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2399
ok(ret, "expected ChangeServiceConfig2A to succeed\n");
2400
2401
pConfig->lpDescription = (void*)0xdeadbeef;
2402
ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2403
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2404
ok(!pConfig->lpDescription,
2405
"expected lpDescription to be null, got %s\n", pConfig->lpDescription);
2406
2407
pConfigW->lpDescription = (LPWSTR)descriptionW;
2408
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2409
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2410
2411
pConfigW->lpDescription = NULL;
2412
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2413
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2414
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2415
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2416
2417
pConfigW->lpDescription = NULL;
2418
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2419
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2420
2421
pConfigW->lpDescription = NULL;
2422
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2423
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2424
ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
2425
"expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
2426
2427
pConfigW->lpDescription = (WCHAR*)L"";
2428
ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
2429
ok(ret, "expected ChangeServiceConfig2W to succeed\n");
2430
2431
pConfigW->lpDescription = (void*)0xdeadbeef;
2432
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
2433
ok(ret, "expected QueryServiceConfig2A to succeed\n");
2434
ok(!pConfigW->lpDescription,
2435
"expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
2436
2437
SetLastError(0xdeadbeef);
2438
needed = 0;
2439
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2440
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2441
if(!ret && GetLastError()==ERROR_INVALID_LEVEL)
2442
{
2443
/* Win2k3 and older */
2444
win_skip("SERVICE_CONFIG_PRESHUTDOWN_INFO not supported\n");
2445
goto cleanup;
2446
}
2447
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2448
ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2449
ok(preshutdown_info.dwPreshutdownTimeout == 180000
2450
|| preshutdown_info.dwPreshutdownTimeout == 10000 /* Win10 1709+ */,
2451
"Default PreshutdownTimeout = %ld\n", preshutdown_info.dwPreshutdownTimeout);
2452
2453
SetLastError(0xdeadbeef);
2454
preshutdown_info.dwPreshutdownTimeout = -1;
2455
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2456
(LPVOID)&preshutdown_info);
2457
ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
2458
2459
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
2460
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
2461
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2462
ok(needed == sizeof(preshutdown_info), "needed = %ld\n", needed);
2463
ok(preshutdown_info.dwPreshutdownTimeout == -1, "New PreshutdownTimeout = %ld\n",
2464
preshutdown_info.dwPreshutdownTimeout);
2465
2466
SetLastError(0xdeadbeef);
2467
needed = 0;
2468
auto_start_info.fDelayedAutostart = 0xdeadbeef;
2469
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2470
(LPBYTE)&auto_start_info, sizeof(auto_start_info), &needed);
2471
ok(ret, "expected QueryServiceConfig2W to succeed (%ld)\n", GetLastError());
2472
ok(needed == sizeof(auto_start_info), "needed = %ld\n", needed);
2473
ok(auto_start_info.fDelayedAutostart == 0, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2474
2475
SetLastError(0xdeadbeef);
2476
auto_start_info.fDelayedAutostart = 3;
2477
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2478
(LPBYTE)&auto_start_info);
2479
ok(!ret, "expected ChangeServiceConfig2A to fail\n");
2480
ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %ld\n", GetLastError());
2481
2482
SetLastError(0xdeadbeef);
2483
auto_start_info.fDelayedAutostart = 1;
2484
ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
2485
(LPBYTE)&auto_start_info);
2486
ok(ret, "expected ChangeServiceConfig2A to succeed (%ld)\n", GetLastError());
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 == 1, "fDelayedAutostart = %d\n", auto_start_info.fDelayedAutostart);
2496
2497
cleanup:
2498
DeleteService(svc_handle);
2499
CloseServiceHandle(svc_handle);
2500
CloseServiceHandle(scm_handle);
2501
}
2502
2503
static DWORD try_start_stop(SC_HANDLE svc_handle, const char* name, DWORD is_nt4)
2504
{
2505
BOOL ret;
2506
DWORD le1, le2;
2507
SERVICE_STATUS status;
2508
2509
ret = StartServiceA(svc_handle, 0, NULL);
2510
le1 = GetLastError();
2511
ok(!ret, "%s: StartServiceA() should have failed\n", name);
2512
2513
if (pQueryServiceStatusEx)
2514
{
2515
DWORD needed;
2516
SERVICE_STATUS_PROCESS statusproc;
2517
2518
ret = pQueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE*)&statusproc, sizeof(statusproc), &needed);
2519
ok(ret, "%s: QueryServiceStatusEx() failed le=%lu\n", name, GetLastError());
2520
ok(statusproc.dwCurrentState == SERVICE_STOPPED, "%s: should be stopped state=%lx\n", name, statusproc.dwCurrentState);
2521
ok(statusproc.dwProcessId == 0, "%s: ProcessId should be 0 instead of %lx\n", name, statusproc.dwProcessId);
2522
}
2523
2524
ret = StartServiceA(svc_handle, 0, NULL);
2525
le2 = GetLastError();
2526
ok(!ret, "%s: StartServiceA() should have failed\n", name);
2527
ok(le2 == le1, "%s: the second try should yield the same error: %lu != %lu\n", name, le1, le2);
2528
2529
status.dwCurrentState = 0xdeadbeef;
2530
ret = ControlService(svc_handle, SERVICE_CONTROL_STOP, &status);
2531
le2 = GetLastError();
2532
ok(!ret, "%s: ControlService() should have failed\n", name);
2533
ok(le2 == ERROR_SERVICE_NOT_ACTIVE, "%s: %ld != ERROR_SERVICE_NOT_ACTIVE\n", name, le2);
2534
ok(status.dwCurrentState == SERVICE_STOPPED ||
2535
broken(is_nt4), /* NT4 returns a random value */
2536
"%s: should be stopped state=%lx\n", name, status.dwCurrentState);
2537
2538
return le1;
2539
}
2540
2541
#define PHASE_STOPPED 1
2542
#define PHASE_RUNNING 2
2543
2544
struct notify_data {
2545
SERVICE_NOTIFYW notify;
2546
SC_HANDLE svc;
2547
BOOL was_called;
2548
DWORD phase;
2549
};
2550
2551
static void CALLBACK notify_cb(void *user)
2552
{
2553
struct notify_data *data = user;
2554
switch (data->phase)
2555
{
2556
case PHASE_STOPPED:
2557
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2558
"Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2559
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_STOPPED,
2560
"Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2561
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_STOPPED,
2562
"Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2563
break;
2564
2565
case PHASE_RUNNING:
2566
ok(data->notify.dwNotificationStatus == ERROR_SUCCESS,
2567
"Got wrong notification status: %lu\n", data->notify.dwNotificationStatus);
2568
ok(data->notify.ServiceStatus.dwCurrentState == SERVICE_RUNNING,
2569
"Got wrong service state: 0x%lx\n", data->notify.ServiceStatus.dwCurrentState);
2570
ok(data->notify.dwNotificationTriggered == SERVICE_NOTIFY_RUNNING,
2571
"Got wrong notification triggered: 0x%lx\n", data->notify.dwNotificationTriggered);
2572
break;
2573
}
2574
2575
data->was_called = TRUE;
2576
}
2577
2578
static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
2579
{
2580
DWORD dr, dr2;
2581
struct notify_data data;
2582
struct notify_data data2;
2583
BOOL br;
2584
SERVICE_STATUS status;
2585
HANDLE svc, svc2;
2586
2587
if(!pNotifyServiceStatusChangeW){
2588
win_skip("No NotifyServiceStatusChangeW\n");
2589
return;
2590
}
2591
2592
svc = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2593
svc2 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2594
ok(svc != NULL && svc2 != NULL, "Failed to open service\n");
2595
if(!svc || !svc2)
2596
return;
2597
2598
/* receive stopped notification, then start service */
2599
memset(&data.notify, 0, sizeof(data.notify));
2600
data.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2601
data.notify.pfnNotifyCallback = &notify_cb;
2602
data.notify.pContext = &data;
2603
data.svc = svc;
2604
data.phase = PHASE_STOPPED;
2605
data.was_called = FALSE;
2606
2607
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2608
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2609
2610
dr = SleepEx(100, TRUE);
2611
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2612
ok(data.was_called == TRUE, "APC wasn't called\n");
2613
2614
br = StartServiceA(svc, 0, NULL);
2615
ok(br, "StartService failed: %lu\n", GetLastError());
2616
2617
/* receive running notification */
2618
data.phase = PHASE_RUNNING;
2619
data.was_called = FALSE;
2620
2621
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2622
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2623
2624
dr = SleepEx(100, TRUE);
2625
ok(dr == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2626
ok(data.was_called == TRUE, "APC wasn't called\n");
2627
2628
/* cannot register two notifications on the same handle */
2629
data.phase = PHASE_STOPPED;
2630
data.was_called = FALSE;
2631
2632
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2633
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2634
2635
memset(&data2.notify, 0, sizeof(data2.notify));
2636
data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2637
data2.notify.pfnNotifyCallback = &notify_cb;
2638
data2.notify.pContext = &data2;
2639
data2.phase = PHASE_RUNNING;
2640
data2.was_called = FALSE;
2641
2642
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data2.notify);
2643
ok(dr == ERROR_ALREADY_REGISTERED || !dr /* Win8+ */, "wrong error %lu\n", dr);
2644
if (!dr)
2645
{
2646
dr = SleepEx(100, TRUE);
2647
ok(dr == WAIT_IO_COMPLETION, "got %lu\n", dr);
2648
ok(data2.was_called, "APC was not called\n");
2649
}
2650
else
2651
{
2652
dr = SleepEx(100, TRUE);
2653
ok(!dr, "got %lu\n", dr);
2654
ok(!data2.was_called, "APC should not have been called\n");
2655
}
2656
ok(data.was_called == FALSE, "APC should not have been called\n");
2657
2658
memset(&data2.notify, 0, sizeof(data2.notify));
2659
data2.notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
2660
data2.notify.pfnNotifyCallback = &notify_cb;
2661
data2.notify.pContext = &data;
2662
data2.svc = svc2;
2663
data2.phase = PHASE_STOPPED;
2664
data2.was_called = FALSE;
2665
2666
/* it's possible to have multiple notifications using different service handles */
2667
dr = pNotifyServiceStatusChangeW(svc2, SERVICE_NOTIFY_STOPPED, &data2.notify);
2668
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW gave wrong result: %lu\n", dr);
2669
2670
/* stop service and receive notifiction */
2671
br = ControlService(svc, SERVICE_CONTROL_STOP, &status);
2672
ok(br, "ControlService failed: %lu\n", GetLastError());
2673
2674
dr = SleepEx(100, TRUE);
2675
dr2 = SleepEx(100, TRUE);
2676
ok(dr == WAIT_IO_COMPLETION || dr2 == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %lu\n", dr);
2677
ok(data.was_called == TRUE, "APC wasn't called\n");
2678
ok(data2.was_called == TRUE, "APC wasn't called\n");
2679
2680
/* test cancelation: create notify on svc that will block until service
2681
* start; close svc; start service on svc2; verify that notification does
2682
* not happen */
2683
2684
data.phase = PHASE_RUNNING;
2685
data.was_called = FALSE;
2686
dr = pNotifyServiceStatusChangeW(svc, SERVICE_NOTIFY_STOPPED | SERVICE_NOTIFY_RUNNING, &data.notify);
2687
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW failed: %lu\n", dr);
2688
2689
CloseServiceHandle(svc);
2690
2691
br = StartServiceA(svc2, 0, NULL);
2692
ok(br, "StartService failed: %lu\n", GetLastError());
2693
2694
dr = SleepEx(100, TRUE);
2695
ok(dr == 0, "Got wrong SleepEx result: %lu\n", dr);
2696
ok(data.was_called == FALSE, "APC should not have been called\n");
2697
2698
br = ControlService(svc2, SERVICE_CONTROL_STOP, &status);
2699
ok(br, "ControlService failed: %lu\n", GetLastError());
2700
2701
CloseServiceHandle(svc2);
2702
}
2703
2704
static void test_start_stop(void)
2705
{
2706
BOOL ret;
2707
SC_HANDLE scm_handle, svc_handle;
2708
DWORD le, is_nt4;
2709
static const char servicename[] = "winetest_start_stop";
2710
char cmd[MAX_PATH+20];
2711
const char* displayname;
2712
2713
SetLastError(0xdeadbeef);
2714
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2715
if (!scm_handle)
2716
{
2717
if(GetLastError() == ERROR_ACCESS_DENIED)
2718
skip("Not enough rights to get a handle to the manager\n");
2719
else
2720
ok(FALSE, "Could not get a handle to the manager: %ld\n", GetLastError());
2721
return;
2722
}
2723
2724
/* Detect NT4 */
2725
svc_handle = OpenServiceA(scm_handle, NULL, GENERIC_READ);
2726
is_nt4=(svc_handle == NULL && GetLastError() == ERROR_INVALID_PARAMETER);
2727
2728
/* Do some cleanup in case a previous run crashed */
2729
svc_handle = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2730
if (svc_handle)
2731
{
2732
DeleteService(svc_handle);
2733
CloseServiceHandle(svc_handle);
2734
}
2735
2736
/* Create a dummy disabled service */
2737
sprintf(cmd, "\"%s\" service exit", selfname);
2738
displayname = "Winetest Disabled Service";
2739
svc_handle = CreateServiceA(scm_handle, servicename, displayname,
2740
GENERIC_ALL, SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS,
2741
SERVICE_DISABLED, SERVICE_ERROR_IGNORE, cmd, NULL,
2742
NULL, NULL, NULL, NULL);
2743
if (!svc_handle)
2744
{
2745
if(GetLastError() == ERROR_ACCESS_DENIED)
2746
skip("Not enough rights to create the service\n");
2747
else
2748
ok(FALSE, "Could not create the service: %ld\n", GetLastError());
2749
goto cleanup;
2750
}
2751
le = try_start_stop(svc_handle, displayname, is_nt4);
2752
ok(le == ERROR_SERVICE_DISABLED, "%ld != ERROR_SERVICE_DISABLED\n", le);
2753
2754
/* Then one with a bad path */
2755
displayname = "Winetest Bad Path";
2756
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, "c:\\no_such_file.exe", NULL, NULL, NULL, NULL, NULL, displayname);
2757
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2758
try_start_stop(svc_handle, displayname, is_nt4);
2759
2760
if (is_nt4)
2761
{
2762
/* NT4 does not detect when a service fails to start and uses an
2763
* insanely long timeout: 120s. So skip the rest of the tests.
2764
*/
2765
win_skip("Skip some service start/stop tests on NT4\n");
2766
goto cleanup;
2767
}
2768
2769
/* Again with a process that exits right away */
2770
displayname = "Winetest Exit Service";
2771
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2772
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2773
le = try_start_stop(svc_handle, displayname, is_nt4);
2774
ok(le == ERROR_SERVICE_REQUEST_TIMEOUT, "%ld != ERROR_SERVICE_REQUEST_TIMEOUT\n", le);
2775
2776
/* create a real service and test notifications */
2777
sprintf(cmd, "%s service serve", selfname);
2778
displayname = "Winetest Service";
2779
ret = ChangeServiceConfigA(svc_handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, cmd, NULL, NULL, NULL, NULL, NULL, displayname);
2780
ok(ret, "ChangeServiceConfig() failed le=%lu\n", GetLastError());
2781
test_servicenotify(scm_handle, servicename);
2782
2783
cleanup:
2784
if (svc_handle)
2785
{
2786
DeleteService(svc_handle);
2787
CloseServiceHandle(svc_handle);
2788
}
2789
CloseServiceHandle(scm_handle);
2790
}
2791
2792
static void test_refcount(void)
2793
{
2794
SC_HANDLE scm_handle, svc_handle1, svc_handle2, svc_handle3, svc_handle4, svc_handle5;
2795
static const CHAR servicename [] = "winetest_refcount";
2796
static const CHAR pathname [] = "we_dont_care.exe";
2797
BOOL ret;
2798
2799
/* Get a handle to the Service Control Manager */
2800
SetLastError(0xdeadbeef);
2801
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2802
if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
2803
{
2804
skip("Not enough rights to get a handle to the manager\n");
2805
return;
2806
}
2807
2808
/* Create a service */
2809
svc_handle1 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2810
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2811
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2812
ok(svc_handle1 != NULL, "Expected success, got error %lu\n", GetLastError());
2813
2814
/* Get a handle to this new service */
2815
svc_handle2 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2816
ok(svc_handle2 != NULL, "Expected success, got error %lu\n", GetLastError());
2817
2818
/* Get another handle to this new service */
2819
svc_handle3 = OpenServiceA(scm_handle, servicename, GENERIC_READ);
2820
ok(svc_handle3 != NULL, "Expected success, got error %lu\n", GetLastError());
2821
2822
/* Check if we can close the handle to the Service Control Manager */
2823
ret = CloseServiceHandle(scm_handle);
2824
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2825
2826
/* Get a new handle to the Service Control Manager */
2827
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
2828
ok(scm_handle != NULL, "Expected success, got error %lu\n", GetLastError());
2829
2830
/* Get a handle to this new service */
2831
svc_handle4 = OpenServiceA(scm_handle, servicename, GENERIC_ALL);
2832
ok(svc_handle4 != NULL, "Expected success, got error %lu\n", GetLastError());
2833
2834
/* Delete the service */
2835
ret = DeleteService(svc_handle4);
2836
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2837
2838
/* We cannot create the same service again as it's still marked as 'being deleted'.
2839
* The reason is that we still have 4 open handles to this service even though we
2840
* closed the handle to the Service Control Manager in between.
2841
*/
2842
SetLastError(0xdeadbeef);
2843
svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2844
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2845
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2846
ok(!svc_handle5, "Expected failure\n");
2847
ok(GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE,
2848
"Expected ERROR_SERVICE_MARKED_FOR_DELETE, got %ld\n", GetLastError());
2849
2850
/* Close all the handles to the service and try again */
2851
ret = CloseServiceHandle(svc_handle4);
2852
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2853
ret = CloseServiceHandle(svc_handle3);
2854
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2855
ret = CloseServiceHandle(svc_handle2);
2856
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2857
ret = CloseServiceHandle(svc_handle1);
2858
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2859
2860
/* Wait a while. Doing a CreateService too soon will result again
2861
* in an ERROR_SERVICE_MARKED_FOR_DELETE error.
2862
*/
2863
Sleep(1000);
2864
2865
/* We succeed now as all handles are closed (tested this also with a long SLeep() */
2866
svc_handle5 = CreateServiceA(scm_handle, servicename, NULL, GENERIC_ALL,
2867
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
2868
SERVICE_DISABLED, 0, pathname, NULL, NULL, NULL, NULL, NULL);
2869
ok(svc_handle5 != NULL, "Expected success, got error %lu\n", GetLastError());
2870
2871
/* Delete the service */
2872
ret = DeleteService(svc_handle5);
2873
ok(ret, "Expected success (err=%ld)\n", GetLastError());
2874
CloseServiceHandle(svc_handle5);
2875
CloseServiceHandle(scm_handle);
2876
}
2877
2878
static BOOL is_lang_english(void)
2879
{
2880
static HMODULE hkernel32 = NULL;
2881
static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL;
2882
static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL;
2883
2884
if (!hkernel32)
2885
{
2886
hkernel32 = GetModuleHandleA("kernel32.dll");
2887
pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage");
2888
pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
2889
}
2890
if (pGetThreadUILanguage)
2891
return PRIMARYLANGID(pGetThreadUILanguage()) == LANG_ENGLISH;
2892
if (pGetUserDefaultUILanguage)
2893
return PRIMARYLANGID(pGetUserDefaultUILanguage()) == LANG_ENGLISH;
2894
2895
return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH;
2896
}
2897
2898
static void test_EventLog(void)
2899
{
2900
SC_HANDLE scm_handle, svc_handle;
2901
DWORD size;
2902
BOOL ret;
2903
QUERY_SERVICE_CONFIGA *config;
2904
SERVICE_STATUS_PROCESS status;
2905
2906
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_READ);
2907
ok(scm_handle != NULL, "OpenSCManager error %lu\n", GetLastError());
2908
2909
svc_handle = OpenServiceA(scm_handle, "EventLog", GENERIC_READ);
2910
ok(svc_handle != NULL, "OpenService error %lu\n", GetLastError());
2911
2912
SetLastError(0xdeadbeef);
2913
ret = QueryServiceConfigA(svc_handle, NULL, 0, &size);
2914
ok(!ret, "QueryServiceConfig should fail\n");
2915
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
2916
2917
config = malloc(size);
2918
ret = QueryServiceConfigA(svc_handle, config, size, &size);
2919
ok(ret, "QueryServiceConfig error %lu\n", GetLastError());
2920
2921
ok(config->dwServiceType == SERVICE_WIN32_SHARE_PROCESS, "got %#lx\n", config->dwServiceType);
2922
ok(config->dwStartType == SERVICE_AUTO_START, "got %lu\n", config->dwStartType);
2923
ok(config->dwErrorControl == SERVICE_ERROR_NORMAL, "got %lu\n", config->dwErrorControl);
2924
ok(!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\services.exe") /* XP */ ||
2925
!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted") /* Vista+ */ ||
2926
!strcmpi(config->lpBinaryPathName, "C:\\windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -p") /* Win10 */,
2927
"got %s\n", config->lpBinaryPathName);
2928
todo_wine
2929
ok(!strcmpi(config->lpLoadOrderGroup, "Event Log"), "got %s\n", config->lpLoadOrderGroup);
2930
ok(config->dwTagId == 0, "Expected 0, got %ld\n", config->dwTagId);
2931
ok(!config->lpDependencies[0], "lpDependencies is not empty\n");
2932
ok(!strcmp(config->lpServiceStartName, "LocalSystem") /* XP */ ||
2933
!strcmp(config->lpServiceStartName, "NT AUTHORITY\\LocalService"),
2934
"got %s\n", config->lpServiceStartName);
2935
ok(!is_lang_english() || /* DisplayName is often translated */
2936
!strcmp(config->lpDisplayName, "Event Log") /* XP */ ||
2937
!strcmp(config->lpDisplayName, "Windows Event Log") /* Vista+ */, "got %s\n", config->lpDisplayName);
2938
2939
free(config);
2940
2941
memset(&status, 0, sizeof(status));
2942
size = sizeof(status);
2943
ret = QueryServiceStatusEx(svc_handle, SC_STATUS_PROCESS_INFO, (BYTE *)&status, size, &size);
2944
ok(ret, "QueryServiceStatusEx error %lu\n", GetLastError());
2945
ok(status.dwServiceType == SERVICE_WIN32_SHARE_PROCESS ||
2946
status.dwServiceType == (SERVICE_WIN32_SHARE_PROCESS | SERVICE_WIN32_OWN_PROCESS) /* Win10 */,
2947
"got %#lx\n", status.dwServiceType);
2948
ok(status.dwServiceSpecificExitCode == 0, "got %#lx\n", status.dwServiceSpecificExitCode);
2949
ok(status.dwCheckPoint == 0, "got %#lx\n", status.dwCheckPoint);
2950
ok(status.dwWaitHint == 0, "got %#lx\n", status.dwWaitHint);
2951
ok(status.dwServiceFlags == 0 || status.dwServiceFlags == SERVICE_RUNS_IN_SYSTEM_PROCESS /* XP */,
2952
"got %#lx\n", status.dwServiceFlags);
2953
if (status.dwCurrentState == SERVICE_STOPPED &&
2954
status.dwWin32ExitCode == ERROR_PROCESS_ABORTED)
2955
win_skip("EventLog crashed!\n");
2956
else
2957
{
2958
ok(status.dwCurrentState == SERVICE_RUNNING, "got %#lx\n", status.dwCurrentState);
2959
ok(status.dwControlsAccepted == SERVICE_ACCEPT_SHUTDOWN /* XP */ ||
2960
status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN) /* 2008 */ ||
2961
status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_TIMECHANGE | SERVICE_ACCEPT_SHUTDOWN),
2962
"got %#lx\n", status.dwControlsAccepted);
2963
ok(status.dwWin32ExitCode == 0, "got %#lx\n", status.dwWin32ExitCode);
2964
ok(status.dwProcessId != 0, "got %#lx\n", status.dwProcessId);
2965
}
2966
2967
CloseServiceHandle(svc_handle);
2968
CloseServiceHandle(scm_handle);
2969
}
2970
2971
static DWORD WINAPI ctrl_handler(DWORD ctl, DWORD type, void *data, void *user)
2972
{
2973
HANDLE evt = user;
2974
2975
switch(ctl){
2976
case SERVICE_CONTROL_STOP:
2977
SetEvent(evt);
2978
break;
2979
case SERVICE_CONTROL_INTERROGATE:
2980
return NO_ERROR;
2981
}
2982
2983
return ERROR_CALL_NOT_IMPLEMENTED;
2984
}
2985
2986
static void WINAPI service_main(DWORD argc, char **argv)
2987
{
2988
SERVICE_STATUS_HANDLE st_handle;
2989
SERVICE_STATUS st;
2990
HANDLE evt = CreateEventW(0, FALSE, FALSE, 0);
2991
2992
st_handle = RegisterServiceCtrlHandlerExA("", &ctrl_handler, evt);
2993
2994
st.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2995
st.dwServiceSpecificExitCode = 0;
2996
st.dwCurrentState = SERVICE_RUNNING;
2997
st.dwWin32ExitCode = NO_ERROR;
2998
st.dwWaitHint = 0;
2999
st.dwControlsAccepted = SERVICE_ACCEPT_STOP;
3000
st.dwCheckPoint = 0;
3001
3002
SetServiceStatus(st_handle, &st);
3003
3004
WaitForSingleObject(evt, 5000);
3005
3006
st.dwCurrentState = SERVICE_STOPPED;
3007
3008
SetServiceStatus(st_handle, &st);
3009
}
3010
3011
static void run_service(void)
3012
{
3013
char empty[] = {0};
3014
SERVICE_TABLE_ENTRYA table[] = {
3015
{empty, &service_main },
3016
{0, 0}
3017
};
3018
3019
StartServiceCtrlDispatcherA(table);
3020
}
3021
3022
START_TEST(service)
3023
{
3024
SC_HANDLE scm_handle;
3025
int myARGC;
3026
char** myARGV;
3027
int attempt;
3028
3029
myARGC = winetest_get_mainargs(&myARGV);
3030
GetFullPathNameA(myARGV[0], sizeof(selfname), selfname, NULL);
3031
if (myARGC >= 3)
3032
{
3033
if (strcmp(myARGV[2], "serve") == 0)
3034
run_service();
3035
return;
3036
}
3037
3038
/* Bail out if we are on win98 */
3039
SetLastError(0xdeadbeef);
3040
scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
3041
3042
if (!scm_handle && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
3043
{
3044
win_skip("OpenSCManagerA is not implemented, we are most likely on win9x\n");
3045
return;
3046
}
3047
CloseServiceHandle(scm_handle);
3048
3049
init_function_pointers();
3050
3051
/* First some parameter checking */
3052
test_open_scm();
3053
test_open_svc();
3054
test_create_delete_svc();
3055
test_get_displayname();
3056
test_get_servicekeyname();
3057
test_query_svc();
3058
3059
/* Services may start or stop between enumeration calls, leading to
3060
* inconsistencies and failures. So we may need a couple attempts.
3061
*/
3062
for (attempt = 2; attempt >= 0; attempt--)
3063
if (test_enum_svc(attempt)) break;
3064
for (attempt = 2; attempt >= 0; attempt--)
3065
if (test_enum_svc_ex(attempt)) break;
3066
3067
test_close();
3068
test_wow64();
3069
/* Test the creation, querying and deletion of a service */
3070
test_sequence();
3071
test_queryconfig2();
3072
test_start_stop();
3073
/* The main reason for this test is to check if any refcounting is used
3074
* and what the rules are
3075
*/
3076
test_refcount();
3077
test_EventLog();
3078
}
3079
3080