1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Tests for Lock/UnlockServiceDatabase and QueryServiceLockStatusA/W
5  * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO
6  */
7 
8 #include "precomp.h"
9 
10 #define TESTING_SERVICE     L"Spooler"
11 
12 static void Test_LockUnlockServiceDatabase(void)
13 {
14     BOOL bError = FALSE;
15 
16     SC_HANDLE hScm  = NULL;
17     SC_LOCK   hLock = NULL;
18 
19     /* First of all, try to lock / unlock the services database with invalid handles */
20     SetLastError(0xdeadbeef);
21     hScm  = NULL;
22     hLock = LockServiceDatabase(hScm);
23     ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
24     ok_err(ERROR_INVALID_HANDLE);
25 
26     SetLastError(0xdeadbeef);
27     hScm  = (SC_HANDLE)(ULONG_PTR)0xdeadbeefdeadbeefull;
28     hLock = LockServiceDatabase(hScm);
29     ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
30     ok_err(ERROR_INVALID_HANDLE);
31 
32 /** This test seems to make this application crash on Windows 7... I do not know why... **/
33     SetLastError(0xdeadbeef);
34     hLock = NULL;
35     bError = UnlockServiceDatabase(hLock);
36     ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
37     ok_err(ERROR_INVALID_SERVICE_LOCK);
38 /*****************************************************************************************/
39 
40     SetLastError(0xdeadbeef);
41     hLock = (SC_LOCK)(ULONG_PTR)0xdeadbeefdeadbeefull;
42     bError = UnlockServiceDatabase(hLock);
43     ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
44     ok_err(ERROR_INVALID_SERVICE_LOCK);
45 
46 
47     /* Then, try to lock the services database without having rights */
48     SetLastError(0xdeadbeef);
49     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
50     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
51     if (!hScm)
52     {
53         skip("No service control manager; cannot proceed with LockUnlockServiceDatabase test\n");
54         goto cleanup;
55     }
56     ok_err(ERROR_SUCCESS);
57 
58     SetLastError(0xdeadbeef);
59     hLock = LockServiceDatabase(hScm);
60     ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
61     ok_err(ERROR_ACCESS_DENIED);
62 
63     if (hLock)
64         UnlockServiceDatabase(hLock);
65     CloseServiceHandle(hScm);
66 
67     /* Try to lock the services database with good rights */
68     SetLastError(0xdeadbeef);
69     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK);
70     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
71     if (!hScm)
72     {
73         skip("No service control manager; cannot proceed with LockUnlockServiceDatabase test\n");
74         goto cleanup;
75     }
76     ok_err(ERROR_SUCCESS);
77 
78     SetLastError(0xdeadbeef);
79     hLock = LockServiceDatabase(hScm);
80     ok_err(ERROR_SUCCESS);
81     ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
82 
83     /* Now unlock it */
84     if (hLock)
85     {
86         SetLastError(0xdeadbeef);
87         bError = UnlockServiceDatabase(hLock);
88         ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
89         ok_err(ERROR_SUCCESS);
90     }
91 
92 
93 cleanup:
94     if (hScm)
95         CloseServiceHandle(hScm);
96 
97     return;
98 }
99 
100 static void Test_LockUnlockServiceDatabaseWithServiceStart(void)
101 {
102     BOOL bError = FALSE;
103 
104     SC_HANDLE hScm  = NULL;
105     SC_HANDLE hSvc  = NULL;
106     SC_LOCK   hLock = NULL;
107 
108     LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
109     DWORD dwRequiredSize = 0;
110     SERVICE_STATUS status;
111     BOOL bWasRunning = FALSE;
112     DWORD dwOldStartType = 0;
113 
114     /* Open the services database */
115     SetLastError(0xdeadbeef);
116     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK);
117     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
118     if (!hScm)
119     {
120         skip("No service control manager; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n");
121         goto cleanup;
122     }
123     ok_err(ERROR_SUCCESS);
124 
125     /* Grab a handle to the testing service */
126     SetLastError(0xdeadbeef);
127     hSvc = OpenServiceW(hScm, TESTING_SERVICE, SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
128     ok(hSvc != NULL, "hSvc = 0x%p, expected non-null, error=0x%08lx\n", hSvc, GetLastError());
129     if (!hSvc)
130     {
131         skip("Cannot open a handle to service %S; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n", TESTING_SERVICE);
132         goto cleanup;
133     }
134     ok_err(ERROR_SUCCESS);
135 
136     /* Lock the services database */
137     SetLastError(0xdeadbeef);
138     hLock = LockServiceDatabase(hScm);
139     ok(hLock != NULL, "hLock = 0x%p, expected non-zero, error=0x%08lx\n", hLock, GetLastError());
140     if (!hLock)
141     {
142         skip("Cannot lock the services database; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n");
143         goto cleanup;
144     }
145     ok_err(ERROR_SUCCESS);
146 
147     /* To proceed further, firstly attempt to stop the testing service */
148     QueryServiceConfigW(hSvc, NULL, 0, &dwRequiredSize);
149     lpConfig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
150     QueryServiceConfigW(hSvc, lpConfig, dwRequiredSize, &dwRequiredSize);
151     dwOldStartType = lpConfig->dwStartType;
152     HeapFree(GetProcessHeap(), 0, lpConfig);
153     if (dwOldStartType == SERVICE_DISABLED)
154     {
155         ChangeServiceConfigW(hSvc,
156                              SERVICE_NO_CHANGE,
157                              SERVICE_DEMAND_START,
158                              SERVICE_NO_CHANGE,
159                              NULL,
160                              NULL,
161                              NULL,
162                              NULL,
163                              NULL,
164                              NULL,
165                              NULL);
166     }
167     QueryServiceStatus(hSvc, &status);
168     bWasRunning = (status.dwCurrentState != SERVICE_STOPPED);
169     if (bWasRunning)
170     {
171         ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
172         Sleep(1000); /* Wait 1 second for the service to stop */
173     }
174 
175     /* Now try to start it (this test won't work under Windows Vista / 7 / 8) */
176     SetLastError(0xdeadbeef);
177     bError = StartServiceW(hSvc, 0, NULL);
178     ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
179     ok_err(ERROR_SERVICE_DATABASE_LOCKED);
180     Sleep(1000); /* Wait 1 second for the service to start */
181 
182     /* Stop the testing service */
183     ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
184     Sleep(1000); /* Wait 1 second for the service to stop */
185 
186     /* Now unlock the services database */
187     SetLastError(0xdeadbeef);
188     bError = UnlockServiceDatabase(hLock);
189     ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
190     ok_err(ERROR_SUCCESS);
191 
192     /* Try to start again the service, this time the database unlocked */
193     SetLastError(0xdeadbeef);
194     bError = StartServiceW(hSvc, 0, NULL);
195     ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
196     ok_err(ERROR_SUCCESS);
197     Sleep(1000); /* Wait 1 second for the service to start */
198 
199     /* Stop the testing service */
200     ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
201     Sleep(1000); /* Wait 1 second for the service to stop */
202 
203     /* Restore its original state */
204     if (bWasRunning)
205     {
206         StartServiceW(hSvc, 0, NULL);
207     }
208 
209     if (dwOldStartType == SERVICE_DISABLED)
210     {
211         ChangeServiceConfigW(hSvc,
212                              SERVICE_NO_CHANGE,
213                              SERVICE_DISABLED,
214                              SERVICE_NO_CHANGE,
215                              NULL,
216                              NULL,
217                              NULL,
218                              NULL,
219                              NULL,
220                              NULL,
221                              NULL);
222     }
223 
224 
225 cleanup:
226     if (hSvc)
227         CloseServiceHandle(hSvc);
228 
229     if (hScm)
230         CloseServiceHandle(hScm);
231 
232     return;
233 }
234 
235 static void Test_QueryLockStatusW(void)
236 {
237     BOOL bError = FALSE;
238 
239     SC_HANDLE hScm  = NULL;
240     SC_LOCK   hLock = NULL;
241     LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus = NULL;
242     DWORD dwRequiredSize = 0;
243 
244     /* Firstly try to get lock status with invalid handles */
245     SetLastError(0xdeadbeef);
246     bError = QueryServiceLockStatusW(hScm,
247                                      NULL,
248                                      0,
249                                      &dwRequiredSize);
250     ok(bError == FALSE && GetLastError() == ERROR_INVALID_HANDLE, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INVALID_HANDLE);
251     ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
252 
253     /* Open the services database without having rights */
254     SetLastError(0xdeadbeef);
255     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
256     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
257     if (!hScm)
258     {
259         skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
260         goto cleanup;
261     }
262     ok_err(ERROR_SUCCESS);
263 
264     /* Try to get lock status */
265     SetLastError(0xdeadbeef);
266     bError = QueryServiceLockStatusW(hScm,
267                                      NULL,
268                                      0,
269                                      &dwRequiredSize);
270     ok(bError == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_ACCESS_DENIED);
271     ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
272 
273     CloseServiceHandle(hScm);
274 
275 
276     /*
277      * Query only the lock status.
278      */
279 
280     SetLastError(0xdeadbeef);
281     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_QUERY_LOCK_STATUS);
282     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
283     if (!hScm)
284     {
285         skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
286         goto cleanup;
287     }
288     ok_err(ERROR_SUCCESS);
289 
290     /* Get the needed size */
291     SetLastError(0xdeadbeef);
292     bError = QueryServiceLockStatusW(hScm,
293                                      NULL,
294                                      0,
295                                      &dwRequiredSize);
296     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
297     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
298     if (dwRequiredSize == 0)
299     {
300         skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
301         goto cleanup;
302     }
303 
304     /* Allocate memory */
305     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
306     if (lpLockStatus == NULL)
307     {
308         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
309         goto cleanup;
310     }
311 
312     /* Get the actual value */
313     SetLastError(0xdeadbeef);
314     bError = QueryServiceLockStatusW(hScm,
315                                      lpLockStatus,
316                                      dwRequiredSize,
317                                      &dwRequiredSize);
318     ok(bError, "bError = %u, expected TRUE\n", bError);
319 
320     /* These conditions must be verified iff the services database wasn't previously locked */
321     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
322     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
323     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
324     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
325 
326     HeapFree(GetProcessHeap(), 0, lpLockStatus);
327 
328     CloseServiceHandle(hScm);
329 
330 
331     /*
332      * Now, try to lock the database and check its lock status.
333      */
334 
335     SetLastError(0xdeadbeef);
336     hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS);
337     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
338     if (!hScm)
339     {
340         skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
341         goto cleanup;
342     }
343     ok_err(ERROR_SUCCESS);
344 
345     /* Get the needed size */
346     SetLastError(0xdeadbeef);
347     bError = QueryServiceLockStatusW(hScm,
348                                      NULL,
349                                      0,
350                                      &dwRequiredSize);
351     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
352     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
353     if (dwRequiredSize == 0)
354     {
355         skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
356         goto cleanup;
357     }
358 
359     /* Allocate memory */
360     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
361     if (lpLockStatus == NULL)
362     {
363         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
364         goto cleanup;
365     }
366 
367     /* Get the actual value */
368     SetLastError(0xdeadbeef);
369     bError = QueryServiceLockStatusW(hScm,
370                                      lpLockStatus,
371                                      dwRequiredSize,
372                                      &dwRequiredSize);
373     ok(bError, "bError = %u, expected TRUE\n", bError);
374 
375     /* These conditions must be verified iff the services database wasn't previously locked */
376     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
377     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
378     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
379     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
380 
381     HeapFree(GetProcessHeap(), 0, lpLockStatus);
382 
383 
384     /*
385      * Try again, this time with the database locked.
386      */
387 
388     SetLastError(0xdeadbeef);
389     hLock = LockServiceDatabase(hScm);
390     ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
391     ok_err(ERROR_SUCCESS);
392 
393     Sleep(1000); /* Wait 1 second to let lpLockStatus->dwLockDuration increment */
394 
395     /* Get the needed size */
396     SetLastError(0xdeadbeef);
397     bError = QueryServiceLockStatusW(hScm,
398                                      NULL,
399                                      0,
400                                      &dwRequiredSize);
401     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
402     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
403     if (dwRequiredSize == 0)
404     {
405         skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
406         goto cleanup;
407     }
408 
409     /* Allocate memory */
410     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
411     if (lpLockStatus == NULL)
412     {
413         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
414         goto cleanup;
415     }
416 
417     /* Get the actual value */
418     SetLastError(0xdeadbeef);
419     bError = QueryServiceLockStatusW(hScm,
420                                      lpLockStatus,
421                                      dwRequiredSize,
422                                      &dwRequiredSize);
423     ok(bError, "bError = %u, expected TRUE\n", bError);
424 
425     /* These conditions must be verified iff the services database is locked */
426     ok(lpLockStatus->fIsLocked != 0, "lpLockStatus->fIsLocked = %lu, expected non-zero\n", lpLockStatus->fIsLocked);
427     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
428     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner != 0, "*lpLockStatus->lpLockOwner = \"\\0\", expected non-zero\n");
429     ok(lpLockStatus->dwLockDuration != 0, "lpLockStatus->dwLockDuration = %lu, expected non-zero\n", lpLockStatus->dwLockDuration);
430 
431     HeapFree(GetProcessHeap(), 0, lpLockStatus);
432 
433 
434     /*
435      * Last try, with the database again unlocked.
436      */
437 
438     SetLastError(0xdeadbeef);
439     bError = UnlockServiceDatabase(hLock);
440     ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
441     ok_err(ERROR_SUCCESS);
442     hLock = NULL;
443 
444     /* Get the needed size */
445     SetLastError(0xdeadbeef);
446     bError = QueryServiceLockStatusW(hScm,
447                                      NULL,
448                                      0,
449                                      &dwRequiredSize);
450     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
451     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
452     if (dwRequiredSize == 0)
453     {
454         skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
455         goto cleanup;
456     }
457 
458     /* Allocate memory */
459     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
460     if (lpLockStatus == NULL)
461     {
462         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
463         goto cleanup;
464     }
465 
466     /* Get the actual value */
467     SetLastError(0xdeadbeef);
468     bError = QueryServiceLockStatusW(hScm,
469                                      lpLockStatus,
470                                      dwRequiredSize,
471                                      &dwRequiredSize);
472     ok(bError, "bError = %u, expected TRUE\n", bError);
473 
474     /* These conditions must be verified iff the services database is unlocked */
475     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
476     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
477     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
478     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
479 
480     HeapFree(GetProcessHeap(), 0, lpLockStatus);
481 
482 
483 cleanup:
484     if (hLock)
485         UnlockServiceDatabase(hLock);
486 
487     if (hScm)
488         CloseServiceHandle(hScm);
489 
490     return;
491 }
492 
493 static void Test_QueryLockStatusA(void)
494 {
495     BOOL bError = FALSE;
496 
497     SC_HANDLE hScm  = NULL;
498     SC_LOCK   hLock = NULL;
499     LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus = NULL;
500     DWORD dwRequiredSize = 0;
501 
502     /* Firstly try to get lock status with invalid handles */
503     SetLastError(0xdeadbeef);
504     bError = QueryServiceLockStatusA(hScm,
505                                      NULL,
506                                      0,
507                                      &dwRequiredSize);
508     ok(bError == FALSE && GetLastError() == ERROR_INVALID_HANDLE, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INVALID_HANDLE);
509     ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
510 
511     /* Open the services database without having rights */
512     SetLastError(0xdeadbeef);
513     hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
514     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
515     if (!hScm)
516     {
517         skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
518         goto cleanup;
519     }
520     ok_err(ERROR_SUCCESS);
521 
522     /* Try to get lock status */
523     SetLastError(0xdeadbeef);
524     bError = QueryServiceLockStatusA(hScm,
525                                      NULL,
526                                      0,
527                                      &dwRequiredSize);
528     ok(bError == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_ACCESS_DENIED);
529     ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
530 
531     CloseServiceHandle(hScm);
532 
533 
534     /*
535      * Query only the lock status.
536      */
537 
538     SetLastError(0xdeadbeef);
539     hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_QUERY_LOCK_STATUS);
540     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
541     if (!hScm)
542     {
543         skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
544         goto cleanup;
545     }
546     ok_err(ERROR_SUCCESS);
547 
548     /* Get the needed size */
549     SetLastError(0xdeadbeef);
550     bError = QueryServiceLockStatusA(hScm,
551                                      NULL,
552                                      0,
553                                      &dwRequiredSize);
554     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
555     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
556     if (dwRequiredSize == 0)
557     {
558         skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
559         goto cleanup;
560     }
561 
562     /* Allocate memory */
563     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
564     if (lpLockStatus == NULL)
565     {
566         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
567         goto cleanup;
568     }
569 
570     /* Get the actual value */
571     SetLastError(0xdeadbeef);
572     bError = QueryServiceLockStatusA(hScm,
573                                      lpLockStatus,
574                                      dwRequiredSize,
575                                      &dwRequiredSize);
576     ok(bError, "bError = %u, expected TRUE\n", bError);
577 
578     /* These conditions must be verified iff the services database wasn't previously locked */
579     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
580     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
581     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
582     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
583 
584     HeapFree(GetProcessHeap(), 0, lpLockStatus);
585 
586     CloseServiceHandle(hScm);
587 
588 
589     /*
590      * Now, try to lock the database and check its lock status.
591      */
592 
593     SetLastError(0xdeadbeef);
594     hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS);
595     ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
596     if (!hScm)
597     {
598         skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
599         goto cleanup;
600     }
601     ok_err(ERROR_SUCCESS);
602 
603     /* Get the needed size */
604     SetLastError(0xdeadbeef);
605     bError = QueryServiceLockStatusA(hScm,
606                                      NULL,
607                                      0,
608                                      &dwRequiredSize);
609     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
610     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
611     if (dwRequiredSize == 0)
612     {
613         skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
614         goto cleanup;
615     }
616 
617     /* Allocate memory */
618     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
619     if (lpLockStatus == NULL)
620     {
621         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
622         goto cleanup;
623     }
624 
625     /* Get the actual value */
626     SetLastError(0xdeadbeef);
627     bError = QueryServiceLockStatusA(hScm,
628                                      lpLockStatus,
629                                      dwRequiredSize,
630                                      &dwRequiredSize);
631     ok(bError, "bError = %u, expected TRUE\n", bError);
632 
633     /* These conditions must be verified iff the services database wasn't previously locked */
634     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
635     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
636     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
637     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
638 
639     HeapFree(GetProcessHeap(), 0, lpLockStatus);
640 
641 
642     /*
643      * Try again, this time with the database locked.
644      */
645 
646     SetLastError(0xdeadbeef);
647     hLock = LockServiceDatabase(hScm);
648     ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
649     ok_err(ERROR_SUCCESS);
650 
651     Sleep(1000); /* Wait 1 second to let lpLockStatus->dwLockDuration increment */
652 
653     /* Get the needed size */
654     SetLastError(0xdeadbeef);
655     bError = QueryServiceLockStatusA(hScm,
656                                      NULL,
657                                      0,
658                                      &dwRequiredSize);
659     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
660     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
661     if (dwRequiredSize == 0)
662     {
663         skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
664         goto cleanup;
665     }
666 
667     /* Allocate memory */
668     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
669     if (lpLockStatus == NULL)
670     {
671         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
672         goto cleanup;
673     }
674 
675     /* Get the actual value */
676     SetLastError(0xdeadbeef);
677     bError = QueryServiceLockStatusA(hScm,
678                                      lpLockStatus,
679                                      dwRequiredSize,
680                                      &dwRequiredSize);
681     ok(bError, "bError = %u, expected TRUE\n", bError);
682 
683     /* These conditions must be verified iff the services database is locked */
684     ok(lpLockStatus->fIsLocked != 0, "lpLockStatus->fIsLocked = %lu, expected non-zero\n", lpLockStatus->fIsLocked);
685     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
686     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner != 0, "*lpLockStatus->lpLockOwner = \"\\0\", expected non-zero\n");
687     ok(lpLockStatus->dwLockDuration != 0, "lpLockStatus->dwLockDuration = %lu, expected non-zero\n", lpLockStatus->dwLockDuration);
688 
689     HeapFree(GetProcessHeap(), 0, lpLockStatus);
690 
691 
692     /*
693      * Last try, with the database again unlocked.
694      */
695 
696     SetLastError(0xdeadbeef);
697     bError = UnlockServiceDatabase(hLock);
698     ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
699     ok_err(ERROR_SUCCESS);
700     hLock = NULL;
701 
702     /* Get the needed size */
703     SetLastError(0xdeadbeef);
704     bError = QueryServiceLockStatusA(hScm,
705                                      NULL,
706                                      0,
707                                      &dwRequiredSize);
708     ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
709     ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
710     if (dwRequiredSize == 0)
711     {
712         skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
713         goto cleanup;
714     }
715 
716     /* Allocate memory */
717     lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
718     if (lpLockStatus == NULL)
719     {
720         skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
721         goto cleanup;
722     }
723 
724     /* Get the actual value */
725     SetLastError(0xdeadbeef);
726     bError = QueryServiceLockStatusA(hScm,
727                                      lpLockStatus,
728                                      dwRequiredSize,
729                                      &dwRequiredSize);
730     ok(bError, "bError = %u, expected TRUE\n", bError);
731 
732     /* These conditions must be verified iff the services database is unlocked */
733     ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
734     ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
735     ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
736     ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
737 
738     HeapFree(GetProcessHeap(), 0, lpLockStatus);
739 
740 
741 cleanup:
742     if (hLock)
743         UnlockServiceDatabase(hLock);
744 
745     if (hScm)
746         CloseServiceHandle(hScm);
747 
748     return;
749 }
750 
751 
752 START_TEST(LockServiceDatabase)
753 {
754     Test_LockUnlockServiceDatabase();
755     Test_LockUnlockServiceDatabaseWithServiceStart();
756     Test_QueryLockStatusW();
757     Test_QueryLockStatusA();
758 }
759