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