diff --git a/rostests/apitests/advapi32/CMakeLists.txt b/rostests/apitests/advapi32/CMakeLists.txt index 03e65b2b25b..ca8e6faa7b0 100644 --- a/rostests/apitests/advapi32/CMakeLists.txt +++ b/rostests/apitests/advapi32/CMakeLists.txt @@ -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 index 00000000000..ca194c57b50 --- /dev/null +++ b/rostests/apitests/advapi32/LockDatabase.c @@ -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 +#include +#include + +#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(); +} diff --git a/rostests/apitests/advapi32/QueryServiceConfig2.c b/rostests/apitests/advapi32/QueryServiceConfig2.c index 56f28db3b5c..aeffce56286 100644 --- a/rostests/apitests/advapi32/QueryServiceConfig2.c +++ b/rostests/apitests/advapi32/QueryServiceConfig2.c @@ -2,13 +2,16 @@ * PROJECT: ReactOS api tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Test for QueryServiceConfig2A/W - * PROGRAMMER: Herms BLUSCA - MATO + * PROGRAMMER: Hermès BÉLUSCA - MAÏTO */ #include #include #include +#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: diff --git a/rostests/apitests/advapi32/testlist.c b/rostests/apitests/advapi32/testlist.c index ede80062c93..d7b25577196 100644 --- a/rostests/apitests/advapi32/testlist.c +++ b/rostests/apitests/advapi32/testlist.c @@ -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 }