[ADVAPI32_APITEST]
authorThomas Faber <thomas.faber@reactos.org>
Fri, 29 Jun 2012 11:48:35 +0000 (11:48 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Fri, 29 Jun 2012 11:48:35 +0000 (11:48 +0000)
- Use a define for the service name in QueryServiceConfig2 test. Patch by Hermes Belusca. Bug 7145.
- Add LockDatabase test for Lock/UnlockServiceDatabase, QueryServiceLockStatus. Patch by Hermes Belusca. Bug 7146.

svn path=/trunk/; revision=56810

rostests/apitests/advapi32/CMakeLists.txt
rostests/apitests/advapi32/LockDatabase.c [new file with mode: 0644]
rostests/apitests/advapi32/QueryServiceConfig2.c
rostests/apitests/advapi32/testlist.c

index 03e65b2..ca8e6fa 100644 (file)
@@ -1,6 +1,7 @@
 
 list(APPEND SOURCE
      CreateService.c
+     LockDatabase.c
      QueryServiceConfig2.c
      testlist.c)
 
diff --git a/rostests/apitests/advapi32/LockDatabase.c b/rostests/apitests/advapi32/LockDatabase.c
new file mode 100644 (file)
index 0000000..ca194c5
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+ * PROJECT:         ReactOS api tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Tests for Lock/UnlockServiceDatabase and QueryServiceLockStatusA/W
+ * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO
+ */
+
+#include <wine/test.h>
+#include <windows.h>
+#include <strsafe.h>
+
+#define TESTING_SERVICE     L"Spooler"
+
+static void Test_LockUnlockServiceDatabase(void)
+{
+    BOOL bError = FALSE;
+
+    SC_HANDLE hScm  = NULL;
+    SC_LOCK   hLock = NULL;
+
+    /* First of all, try to lock / unlock the services database with invalid handles */
+    SetLastError(0xdeadbeef);
+    hScm  = NULL;
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
+    ok_err(ERROR_INVALID_HANDLE);
+
+    SetLastError(0xdeadbeef);
+    hScm  = (SC_HANDLE)0xdeadbeef;
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
+    ok_err(ERROR_INVALID_HANDLE);
+
+/** This test seems to make this application crash on Windows 7... I do not know why... **/
+    SetLastError(0xdeadbeef);
+    hLock = NULL;
+    bError = UnlockServiceDatabase(hLock);
+    ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
+    ok_err(ERROR_INVALID_SERVICE_LOCK);
+/*****************************************************************************************/
+
+    SetLastError(0xdeadbeef);
+    hLock = (SC_LOCK)0xdeadbeef;
+    bError = UnlockServiceDatabase(hLock);
+    ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
+    ok_err(ERROR_INVALID_SERVICE_LOCK);
+
+
+    /* Then, try to lock the services database without having rights */
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with LockUnlockServiceDatabase test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    SetLastError(0xdeadbeef);
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock == NULL, "hLock = 0x%p, expected 0\n", hLock);
+    ok_err(ERROR_ACCESS_DENIED);
+
+    if (hLock)
+        UnlockServiceDatabase(hLock);
+    CloseServiceHandle(hScm);
+
+    /* Try to lock the services database with good rights */
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with LockUnlockServiceDatabase test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    SetLastError(0xdeadbeef);
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
+    ok_err(ERROR_SUCCESS);
+
+    /* Now unlock it */
+    if (hLock)
+    {
+        SetLastError(0xdeadbeef);
+        bError = UnlockServiceDatabase(hLock);
+        ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
+        ok_err(ERROR_SUCCESS);
+    }
+
+
+cleanup:
+    if (hScm)
+        CloseServiceHandle(hScm);
+
+    return;
+}
+
+static void Test_LockUnlockServiceDatabaseWithServiceStart(void)
+{
+    BOOL bError = FALSE;
+
+    SC_HANDLE hScm  = NULL;
+    SC_HANDLE hSvc  = NULL;
+    SC_LOCK   hLock = NULL;
+
+    LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
+    DWORD dwRequiredSize = 0;
+    SERVICE_STATUS status;
+    BOOL bWasRunning = FALSE;
+    DWORD dwOldStartType = 0;
+
+    /* Open the services database */
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Grab a handle to the testing service */
+    SetLastError(0xdeadbeef);
+    hSvc = OpenServiceW(hScm, TESTING_SERVICE, SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
+    ok(hSvc != NULL, "hSvc = 0x%p, expected non-null, error=0x%08lx\n", hSvc, GetLastError());
+    if (!hSvc)
+    {
+        skip("Cannot open a handle to service %S; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n", TESTING_SERVICE);
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Lock the services database */
+    SetLastError(0xdeadbeef);
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock != NULL, "hLock = 0x%p, expected non-zero, error=0x%08lx\n", hLock, GetLastError());
+    if (!hLock)
+    {
+        skip("Cannot lock the services database; cannot proceed with LockUnlockServiceDatabaseWithServiceStart test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* To proceed further, firstly attempt to stop the testing service */
+    QueryServiceConfigW(hSvc, NULL, 0, &dwRequiredSize);
+    lpConfig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    QueryServiceConfigW(hSvc, lpConfig, dwRequiredSize, &dwRequiredSize);
+    dwOldStartType = lpConfig->dwStartType;
+    HeapFree(GetProcessHeap(), 0, lpConfig);
+    if (dwOldStartType == SERVICE_DISABLED)
+    {
+        ChangeServiceConfigW(hSvc,
+                             SERVICE_NO_CHANGE,
+                             SERVICE_DEMAND_START,
+                             SERVICE_NO_CHANGE,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL);
+    }
+    QueryServiceStatus(hSvc, &status);
+    bWasRunning = (status.dwCurrentState != SERVICE_STOPPED);
+    if (bWasRunning)
+    {
+        ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
+        Sleep(1000); /* Wait 1 second for the service to stop */
+    }
+
+    /* Now try to start it (this test won't work under Windows Vista / 7 / 8) */
+    SetLastError(0xdeadbeef);
+    bError = StartServiceW(hSvc, 0, NULL);
+    ok(bError == FALSE, "bError = %u, expected FALSE\n", bError);
+    ok_err(ERROR_SERVICE_DATABASE_LOCKED);
+    Sleep(1000); /* Wait 1 second for the service to start */
+
+    /* Stop the testing service */
+    ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
+    Sleep(1000); /* Wait 1 second for the service to stop */
+
+    /* Now unlock the services database */
+    SetLastError(0xdeadbeef);
+    bError = UnlockServiceDatabase(hLock);
+    ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
+    ok_err(ERROR_SUCCESS);
+
+    /* Try to start again the service, this time the database unlocked */
+    SetLastError(0xdeadbeef);
+    bError = StartServiceW(hSvc, 0, NULL);
+    ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
+    ok_err(ERROR_SUCCESS);
+    Sleep(1000); /* Wait 1 second for the service to start */
+
+    /* Stop the testing service */
+    ControlService(hSvc, SERVICE_CONTROL_STOP, &status);
+    Sleep(1000); /* Wait 1 second for the service to stop */
+
+    /* Restore its original state */
+    if (bWasRunning)
+    {
+        StartServiceW(hSvc, 0, NULL);
+    }
+
+    if (dwOldStartType == SERVICE_DISABLED)
+    {
+        ChangeServiceConfigW(hSvc,
+                             SERVICE_NO_CHANGE,
+                             SERVICE_DISABLED,
+                             SERVICE_NO_CHANGE,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL);
+    }
+
+
+cleanup:
+    if (hSvc)
+        CloseServiceHandle(hSvc);
+
+    if (hScm)
+        CloseServiceHandle(hScm);
+
+    return;
+}
+
+static void Test_QueryLockStatusW(void)
+{
+    BOOL bError = FALSE;
+
+    SC_HANDLE hScm  = NULL;
+    SC_LOCK   hLock = NULL;
+    LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus = NULL;
+    DWORD dwRequiredSize = 0;
+
+    /* Firstly try to get lock status with invalid handles */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INVALID_HANDLE, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INVALID_HANDLE);
+    ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
+
+    /* Open the services database without having rights */
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Try to get lock status */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_ACCESS_DENIED);
+    ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
+
+    CloseServiceHandle(hScm);
+
+
+    /*
+     * Query only the lock status.
+     */
+
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_QUERY_LOCK_STATUS);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database wasn't previously locked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+    CloseServiceHandle(hScm);
+
+
+    /*
+     * Now, try to lock the database and check its lock status.
+     */
+
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database wasn't previously locked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+    /*
+     * Try again, this time with the database locked.
+     */
+
+    SetLastError(0xdeadbeef);
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
+    ok_err(ERROR_SUCCESS);
+
+    Sleep(1000); /* Wait 1 second to let lpLockStatus->dwLockDuration increment */
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database is locked */
+    ok(lpLockStatus->fIsLocked != 0, "lpLockStatus->fIsLocked = %lu, expected non-zero\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner != 0, "*lpLockStatus->lpLockOwner = \"\\0\", expected non-zero\n");
+    ok(lpLockStatus->dwLockDuration != 0, "lpLockStatus->dwLockDuration = %lu, expected non-zero\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+    /*
+     * Last try, with the database again unlocked.
+     */
+
+    SetLastError(0xdeadbeef);
+    bError = UnlockServiceDatabase(hLock);
+    ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
+    ok_err(ERROR_SUCCESS);
+    hLock = NULL;
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusW test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusW(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database is unlocked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+cleanup:
+    if (hLock)
+        UnlockServiceDatabase(hLock);
+
+    if (hScm)
+        CloseServiceHandle(hScm);
+
+    return;
+}
+
+static void Test_QueryLockStatusA(void)
+{
+    BOOL bError = FALSE;
+
+    SC_HANDLE hScm  = NULL;
+    SC_LOCK   hLock = NULL;
+    LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus = NULL;
+    DWORD dwRequiredSize = 0;
+
+    /* Firstly try to get lock status with invalid handles */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INVALID_HANDLE, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INVALID_HANDLE);
+    ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
+
+    /* Open the services database without having rights */
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Try to get lock status */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_ACCESS_DENIED);
+    ok(dwRequiredSize == 0, "dwRequiredSize is non-zero, expected zero\n");
+
+    CloseServiceHandle(hScm);
+
+
+    /*
+     * Query only the lock status.
+     */
+
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_QUERY_LOCK_STATUS);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database wasn't previously locked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+    CloseServiceHandle(hScm);
+
+
+    /*
+     * Now, try to lock the database and check its lock status.
+     */
+
+    SetLastError(0xdeadbeef);
+    hScm = OpenSCManagerA(NULL, NULL, SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS);
+    ok(hScm != NULL, "Failed to open service manager, error=0x%08lx\n", GetLastError());
+    if (!hScm)
+    {
+        skip("No service control manager; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+    ok_err(ERROR_SUCCESS);
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database wasn't previously locked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+    /*
+     * Try again, this time with the database locked.
+     */
+
+    SetLastError(0xdeadbeef);
+    hLock = LockServiceDatabase(hScm);
+    ok(hLock != NULL, "hLock = 0x%p, expected non-zero\n", hLock);
+    ok_err(ERROR_SUCCESS);
+
+    Sleep(1000); /* Wait 1 second to let lpLockStatus->dwLockDuration increment */
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database is locked */
+    ok(lpLockStatus->fIsLocked != 0, "lpLockStatus->fIsLocked = %lu, expected non-zero\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner != 0, "*lpLockStatus->lpLockOwner = \"\\0\", expected non-zero\n");
+    ok(lpLockStatus->dwLockDuration != 0, "lpLockStatus->dwLockDuration = %lu, expected non-zero\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+    /*
+     * Last try, with the database again unlocked.
+     */
+
+    SetLastError(0xdeadbeef);
+    bError = UnlockServiceDatabase(hLock);
+    ok(bError == TRUE, "bError = %u, expected TRUE\n", bError);
+    ok_err(ERROR_SUCCESS);
+    hLock = NULL;
+
+    /* Get the needed size */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     NULL,
+                                     0,
+                                     &dwRequiredSize);
+    ok(bError == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "(bError, GetLastError()) = (%u, 0x%08lx), expected (FALSE, 0x%08lx)\n", bError, GetLastError(), (DWORD)ERROR_INSUFFICIENT_BUFFER);
+    ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
+    if (dwRequiredSize == 0)
+    {
+        skip("Required size is null; cannot proceed with QueryLockStatusA test\n");
+        goto cleanup;
+    }
+
+    /* Allocate memory */
+    lpLockStatus = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
+    if (lpLockStatus == NULL)
+    {
+        skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
+        goto cleanup;
+    }
+
+    /* Get the actual value */
+    SetLastError(0xdeadbeef);
+    bError = QueryServiceLockStatusA(hScm,
+                                     lpLockStatus,
+                                     dwRequiredSize,
+                                     &dwRequiredSize);
+    ok(bError, "bError = %u, expected TRUE\n", bError);
+
+    /* These conditions must be verified iff the services database is unlocked */
+    ok(lpLockStatus->fIsLocked == 0, "lpLockStatus->fIsLocked = %lu, expected 0\n", lpLockStatus->fIsLocked);
+    ok(lpLockStatus->lpLockOwner != NULL, "lpLockStatus->lpLockOwner is null, expected non-null\n");
+    ok(lpLockStatus->lpLockOwner && *lpLockStatus->lpLockOwner == 0, "*lpLockStatus->lpLockOwner != \"\\0\", expected \"\\0\"\n");
+    ok(lpLockStatus->dwLockDuration == 0, "lpLockStatus->dwLockDuration = %lu, expected 0\n", lpLockStatus->dwLockDuration);
+
+    HeapFree(GetProcessHeap(), 0, lpLockStatus);
+
+
+cleanup:
+    if (hLock)
+        UnlockServiceDatabase(hLock);
+
+    if (hScm)
+        CloseServiceHandle(hScm);
+
+    return;
+}
+
+
+START_TEST(LockDatabase)
+{
+    Test_LockUnlockServiceDatabase();
+    Test_LockUnlockServiceDatabaseWithServiceStart();
+    Test_QueryLockStatusW();
+    Test_QueryLockStatusA();
+}
index 56f28db..aeffce5 100644 (file)
@@ -2,13 +2,16 @@
  * PROJECT:         ReactOS api tests
  * LICENSE:         GPLv2+ - See COPYING in the top level directory
  * PURPOSE:         Test for QueryServiceConfig2A/W
- * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO
+ * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO
  */
 
 #include <wine/test.h>
 #include <windows.h>
 #include <strsafe.h>
 
+#define TESTING_SERVICEW     L"Spooler"
+#define TESTING_SERVICEA      "Spooler"
+
 /*
  * Taken from base/system/services/config.c and adapted.
  */
@@ -495,7 +498,7 @@ static void Test_QueryServiceConfig2W(void)
     ok_err(ERROR_SUCCESS);
 
     SetLastError(0xdeadbeef);
-    hService = OpenServiceW(hScm, L"Spooler", SERVICE_QUERY_CONFIG);
+    hService = OpenServiceW(hScm, TESTING_SERVICEW, SERVICE_QUERY_CONFIG);
     ok(hService != NULL, "Failed to open service handle, error=0x%08lx\n", GetLastError());
     if (!hService)
     {
@@ -505,10 +508,10 @@ static void Test_QueryServiceConfig2W(void)
 
     ok_err(ERROR_SUCCESS);
 
-    if (QueryConfig2W(hService, L"Spooler", SERVICE_CONFIG_DESCRIPTION) != 0)
+    if (QueryConfig2W(hService, TESTING_SERVICEW, SERVICE_CONFIG_DESCRIPTION) != 0)
         goto cleanup;
 
-    if (QueryConfig2W(hService, L"Spooler", SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
+    if (QueryConfig2W(hService, TESTING_SERVICEW, SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
         goto cleanup;
 
 cleanup:
@@ -536,7 +539,7 @@ static void Test_QueryServiceConfig2A(void)
     ok_err(ERROR_SUCCESS);
 
     SetLastError(0xdeadbeef);
-    hService = OpenServiceA(hScm, "Spooler", SERVICE_QUERY_CONFIG);
+    hService = OpenServiceA(hScm, TESTING_SERVICEA, SERVICE_QUERY_CONFIG);
     ok(hService != NULL, "Failed to open service handle, error=0x%08lx\n", GetLastError());
     if (!hService)
     {
@@ -546,10 +549,10 @@ static void Test_QueryServiceConfig2A(void)
 
     ok_err(ERROR_SUCCESS);
 
-    if (QueryConfig2A(hService, "Spooler", SERVICE_CONFIG_DESCRIPTION) != 0)
+    if (QueryConfig2A(hService, TESTING_SERVICEA, SERVICE_CONFIG_DESCRIPTION) != 0)
         goto cleanup;
 
-    if (QueryConfig2A(hService, "Spooler", SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
+    if (QueryConfig2A(hService, TESTING_SERVICEA, SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
         goto cleanup;
 
 cleanup:
index ede8006..d7b2557 100644 (file)
@@ -6,11 +6,13 @@
 #include "wine/test.h"
 
 extern void func_CreateService(void);
+extern void func_LockDatabase(void);
 extern void func_QueryServiceConfig2(void);
 
 const struct test winetest_testlist[] =
 {
     { "CreateService", func_CreateService },
+    { "LockDatabase" , func_LockDatabase },
     { "QueryServiceConfig2", func_QueryServiceConfig2 },
 
     { 0, 0 }