mirror of
https://github.com/reactos/reactos.git
synced 2024-08-29 22:58:34 +00:00
![Hermès Bélusca-Maïto](/assets/img/avatar_default.png)
Introduce a "apitest.h" header gathering special things for apitests (SEH macros, wine/test.h inclusion, and so on...). svn path=/trunk/; revision=60313
762 lines
29 KiB
C
762 lines
29 KiB
C
/*
|
|
* 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 <apitest.h>
|
|
|
|
#include <winsvc.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();
|
|
}
|