mirror of
https://github.com/reactos/reactos.git
synced 2024-11-19 13:33:42 +00:00
4b95e17c61
Introduce a "apitest.h" header gathering special things for apitests (SEH macros, wine/test.h inclusion, and so on...). svn path=/trunk/; revision=60313
573 lines
20 KiB
C
573 lines
20 KiB
C
/*
|
|
* 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
|
|
*/
|
|
|
|
#include <apitest.h>
|
|
|
|
#include <winreg.h>
|
|
#include <winsvc.h>
|
|
#include <strsafe.h>
|
|
|
|
#define TESTING_SERVICEW L"Spooler"
|
|
#define TESTING_SERVICEA "Spooler"
|
|
|
|
/*
|
|
* Taken from base/system/services/config.c and adapted.
|
|
*/
|
|
static DWORD
|
|
RegReadStringW(HKEY hKey,
|
|
LPWSTR lpValueName,
|
|
LPWSTR *lpValue)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
*lpValue = NULL;
|
|
|
|
dwSize = 0;
|
|
dwError = RegQueryValueExW(hKey,
|
|
lpValueName,
|
|
0,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (dwError != ERROR_SUCCESS)
|
|
return dwError;
|
|
|
|
*lpValue = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
if (*lpValue == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
dwError = RegQueryValueExW(hKey,
|
|
lpValueName,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)*lpValue,
|
|
&dwSize);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *lpValue);
|
|
*lpValue = NULL;
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
static DWORD
|
|
RegReadStringA(HKEY hKey,
|
|
LPSTR lpValueName,
|
|
LPSTR *lpValue)
|
|
{
|
|
DWORD dwError;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
|
|
*lpValue = NULL;
|
|
|
|
dwSize = 0;
|
|
dwError = RegQueryValueExA(hKey,
|
|
lpValueName,
|
|
0,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if (dwError != ERROR_SUCCESS)
|
|
return dwError;
|
|
|
|
*lpValue = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
if (*lpValue == NULL)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
dwError = RegQueryValueExA(hKey,
|
|
lpValueName,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)*lpValue,
|
|
&dwSize);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *lpValue);
|
|
*lpValue = NULL;
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
static int QueryConfig2W(SC_HANDLE hService, LPCWSTR serviceName, DWORD dwInfoLevel)
|
|
{
|
|
int iRet = 0;
|
|
LONG lRet = 0;
|
|
DWORD dwRet = 0;
|
|
BOOL bError = FALSE;
|
|
DWORD dwRequiredSize = 0;
|
|
LPBYTE lpBuffer = NULL;
|
|
|
|
WCHAR keyName[256];
|
|
HKEY hKey = NULL;
|
|
DWORD dwType = 0;
|
|
|
|
/* Get the needed size */
|
|
SetLastError(0xdeadbeef);
|
|
bError = QueryServiceConfig2W(hService,
|
|
dwInfoLevel,
|
|
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 QueryConfig2W --> %lu test\n", dwInfoLevel);
|
|
return 1;
|
|
}
|
|
|
|
/* Allocate memory */
|
|
lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
|
|
if (lpBuffer == NULL)
|
|
{
|
|
skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
|
|
return 2;
|
|
}
|
|
|
|
/* Get the actual value */
|
|
SetLastError(0xdeadbeef);
|
|
bError = QueryServiceConfig2W(hService,
|
|
dwInfoLevel,
|
|
lpBuffer,
|
|
dwRequiredSize,
|
|
&dwRequiredSize);
|
|
ok(bError, "bError = %u, expected TRUE\n", bError);
|
|
if (bError == FALSE)
|
|
{
|
|
skip("QueryServiceConfig2W returned an error; cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel);
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
return 3;
|
|
}
|
|
|
|
/* Now we can compare the retrieved value with what it's actually stored in the registry */
|
|
StringCbPrintfW(keyName, sizeof(keyName), L"System\\CurrentControlSet\\Services\\%s", serviceName);
|
|
SetLastError(0xdeadbeef);
|
|
lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey);
|
|
ok(lRet == ERROR_SUCCESS, "RegOpenKeyExW failed with 0x%08lx\n", lRet);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
skip("No regkey; cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel);
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
return 4;
|
|
}
|
|
|
|
switch (dwInfoLevel)
|
|
{
|
|
case SERVICE_CONFIG_DESCRIPTION:
|
|
{
|
|
LPSERVICE_DESCRIPTIONW lpDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
|
|
LPWSTR lpszDescription = NULL;
|
|
|
|
/* Retrieve the description via the registry */
|
|
dwRet = RegReadStringW(hKey, L"Description", &lpszDescription);
|
|
ok(dwRet == ERROR_SUCCESS, "RegReadStringW returned 0x%08lx\n", dwRet);
|
|
ok(lpszDescription != NULL, "lpszDescription is null, expected non-null\n");
|
|
|
|
/* Compare it with the description retrieved via QueryServiceConfig2 */
|
|
if (lpszDescription)
|
|
iRet = wcscmp(lpDescription->lpDescription, lpszDescription);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved descriptions are different !\n");
|
|
|
|
|
|
/* Memory cleanup */
|
|
HeapFree(GetProcessHeap(), 0, lpszDescription);
|
|
|
|
break;
|
|
}
|
|
|
|
case SERVICE_CONFIG_FAILURE_ACTIONS:
|
|
{
|
|
LPSERVICE_FAILURE_ACTIONSW lpFailureActions1 = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
|
|
LPSERVICE_FAILURE_ACTIONSW lpFailureActions2 = NULL;
|
|
LPWSTR lpRebootMessage = NULL;
|
|
LPWSTR lpFailureCommand = NULL;
|
|
DWORD i = 0;
|
|
|
|
/* Retrieve the failure actions via the registry */
|
|
lRet = RegQueryValueExW(hKey,
|
|
L"FailureActions",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwRequiredSize);
|
|
ok(lRet == ERROR_SUCCESS, "RegQueryValueExW returned 0x%08lx\n", lRet);
|
|
ok(dwType == REG_BINARY, "dwType = %lu, expected REG_BINARY\n", dwType);
|
|
ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
|
|
|
|
lpFailureActions2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
|
|
if (lpFailureActions2 == NULL)
|
|
{
|
|
skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
|
|
break;
|
|
}
|
|
|
|
lRet = RegQueryValueExW(hKey,
|
|
L"FailureActions",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)lpFailureActions2,
|
|
&dwRequiredSize);
|
|
ok(lRet == ERROR_SUCCESS, "RegQueryValueExW returned 0x%08lx\n", lRet);
|
|
ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
|
|
|
|
/* Get the strings */
|
|
RegReadStringW(hKey, L"FailureCommand", &lpFailureCommand);
|
|
RegReadStringW(hKey, L"RebootMessage" , &lpRebootMessage );
|
|
|
|
/* Check the values */
|
|
ok(lpFailureActions1->dwResetPeriod == lpFailureActions2->dwResetPeriod, "lpFailureActions1->dwResetPeriod != lpFailureActions2->dwResetPeriod\n");
|
|
ok(lpFailureActions1->cActions == lpFailureActions2->cActions, "lpFailureActions1->cActions != lpFailureActions2->cActions\n");
|
|
|
|
/* Compare the actions */
|
|
if (lpFailureActions1->cActions == lpFailureActions2->cActions)
|
|
{
|
|
lpFailureActions2->lpsaActions = (lpFailureActions2->cActions > 0 ? (LPSC_ACTION)(lpFailureActions2 + 1) : NULL);
|
|
|
|
if (lpFailureActions1->cActions > 0 &&
|
|
lpFailureActions1->lpsaActions != NULL)
|
|
{
|
|
for (i = 0; i < lpFailureActions1->cActions; ++i)
|
|
{
|
|
ok(lpFailureActions1->lpsaActions[i].Type == lpFailureActions2->lpsaActions[i].Type , "lpFailureActions1->lpsaActions[%lu].Type != lpFailureActions2->lpsaActions[%lu].Type\n" , i, i);
|
|
ok(lpFailureActions1->lpsaActions[i].Delay == lpFailureActions2->lpsaActions[i].Delay, "lpFailureActions1->lpsaActions[%lu].Delay != lpFailureActions2->lpsaActions[%lu].Delay\n", i, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* TODO: retrieve the strings if they are in MUI format */
|
|
|
|
/* Compare RebootMsg */
|
|
if (lpFailureActions1->lpRebootMsg && lpRebootMessage)
|
|
iRet = wcscmp(lpFailureActions1->lpRebootMsg, lpRebootMessage);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved reboot messages are different !\n");
|
|
|
|
/* Compare Command */
|
|
if (lpFailureActions1->lpCommand && lpFailureCommand)
|
|
iRet = wcscmp(lpFailureActions1->lpCommand, lpFailureCommand);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved commands are different !\n");
|
|
|
|
|
|
/* Memory cleanup */
|
|
if (lpRebootMessage)
|
|
HeapFree(GetProcessHeap(), 0, lpRebootMessage);
|
|
|
|
if (lpFailureCommand)
|
|
HeapFree(GetProcessHeap(), 0, lpFailureCommand);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpFailureActions2);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
skip("Unknown dwInfoLevel %lu, cannot proceed with QueryConfig2W --> %lu test\n", dwInfoLevel, dwInfoLevel);
|
|
break;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int QueryConfig2A(SC_HANDLE hService, LPCSTR serviceName, DWORD dwInfoLevel)
|
|
{
|
|
int iRet = 0;
|
|
LONG lRet = 0;
|
|
DWORD dwRet = 0;
|
|
BOOL bError = FALSE;
|
|
DWORD dwRequiredSize = 0;
|
|
LPBYTE lpBuffer = NULL;
|
|
|
|
CHAR keyName[256];
|
|
HKEY hKey = NULL;
|
|
DWORD dwType = 0;
|
|
|
|
/* Get the needed size */
|
|
SetLastError(0xdeadbeef);
|
|
bError = QueryServiceConfig2A(hService,
|
|
dwInfoLevel,
|
|
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 QueryConfig2A --> %lu test\n", dwInfoLevel);
|
|
return 1;
|
|
}
|
|
|
|
/* Allocate memory */
|
|
lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
|
|
if (lpBuffer == NULL)
|
|
{
|
|
skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
|
|
return 2;
|
|
}
|
|
|
|
/* Get the actual value */
|
|
SetLastError(0xdeadbeef);
|
|
bError = QueryServiceConfig2A(hService,
|
|
dwInfoLevel,
|
|
lpBuffer,
|
|
dwRequiredSize,
|
|
&dwRequiredSize);
|
|
ok(bError, "bError = %u, expected TRUE\n", bError);
|
|
if (bError == FALSE)
|
|
{
|
|
skip("QueryServiceConfig2A returned an error; cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel);
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
return 3;
|
|
}
|
|
|
|
/* Now we can compare the retrieved value with what it's actually stored in the registry */
|
|
StringCbPrintfA(keyName, sizeof(keyName), "System\\CurrentControlSet\\Services\\%s", serviceName);
|
|
SetLastError(0xdeadbeef);
|
|
lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey);
|
|
ok(lRet == ERROR_SUCCESS, "RegOpenKeyExA failed with 0x%08lx\n", lRet);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
skip("No regkey; cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel);
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
return 4;
|
|
}
|
|
|
|
switch (dwInfoLevel)
|
|
{
|
|
case SERVICE_CONFIG_DESCRIPTION:
|
|
{
|
|
LPSERVICE_DESCRIPTIONA lpDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer;
|
|
LPSTR lpszDescription = NULL;
|
|
|
|
/* Retrieve the description via the registry */
|
|
dwRet = RegReadStringA(hKey, "Description", &lpszDescription);
|
|
ok(dwRet == ERROR_SUCCESS, "RegReadStringA returned 0x%08lx\n", dwRet);
|
|
ok(lpszDescription != NULL, "lpszDescription is null, expected non-null\n");
|
|
|
|
/* Compare it with the description retrieved via QueryServiceConfig2 */
|
|
if (lpszDescription)
|
|
iRet = strcmp(lpDescription->lpDescription, lpszDescription);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved descriptions are different !\n");
|
|
|
|
|
|
/* Memory cleanup */
|
|
HeapFree(GetProcessHeap(), 0, lpszDescription);
|
|
|
|
break;
|
|
}
|
|
|
|
case SERVICE_CONFIG_FAILURE_ACTIONS:
|
|
{
|
|
LPSERVICE_FAILURE_ACTIONSA lpFailureActions1 = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
|
|
LPSERVICE_FAILURE_ACTIONSA lpFailureActions2 = NULL;
|
|
LPSTR lpRebootMessage = NULL;
|
|
LPSTR lpFailureCommand = NULL;
|
|
DWORD i = 0;
|
|
|
|
/* Retrieve the failure actions via the registry */
|
|
lRet = RegQueryValueExA(hKey,
|
|
"FailureActions",
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwRequiredSize);
|
|
ok(lRet == ERROR_SUCCESS, "RegQueryValueExA returned 0x%08lx\n", lRet);
|
|
ok(dwType == REG_BINARY, "dwType = %lu, expected REG_BINARY\n", dwType);
|
|
ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
|
|
|
|
lpFailureActions2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize);
|
|
if (lpFailureActions2 == NULL)
|
|
{
|
|
skip("Cannot allocate %lu bytes of memory\n", dwRequiredSize);
|
|
break;
|
|
}
|
|
|
|
lRet = RegQueryValueExA(hKey,
|
|
"FailureActions",
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)lpFailureActions2,
|
|
&dwRequiredSize);
|
|
ok(lRet == ERROR_SUCCESS, "RegQueryValueExA returned 0x%08lx\n", lRet);
|
|
ok(dwRequiredSize != 0, "dwRequiredSize is zero, expected non-zero\n");
|
|
|
|
/* Get the strings */
|
|
RegReadStringA(hKey, "FailureCommand", &lpFailureCommand);
|
|
RegReadStringA(hKey, "RebootMessage" , &lpRebootMessage );
|
|
|
|
/* Check the values */
|
|
ok(lpFailureActions1->dwResetPeriod == lpFailureActions2->dwResetPeriod, "lpFailureActions1->dwResetPeriod != lpFailureActions2->dwResetPeriod\n");
|
|
ok(lpFailureActions1->cActions == lpFailureActions2->cActions, "lpFailureActions1->cActions != lpFailureActions2->cActions\n");
|
|
|
|
/* Compare the actions */
|
|
if (lpFailureActions1->cActions == lpFailureActions2->cActions)
|
|
{
|
|
lpFailureActions2->lpsaActions = (lpFailureActions2->cActions > 0 ? (LPSC_ACTION)(lpFailureActions2 + 1) : NULL);
|
|
|
|
if (lpFailureActions1->cActions > 0 &&
|
|
lpFailureActions1->lpsaActions != NULL)
|
|
{
|
|
for (i = 0; i < lpFailureActions1->cActions; ++i)
|
|
{
|
|
ok(lpFailureActions1->lpsaActions[i].Type == lpFailureActions2->lpsaActions[i].Type , "lpFailureActions1->lpsaActions[%lu].Type != lpFailureActions2->lpsaActions[%lu].Type\n" , i, i);
|
|
ok(lpFailureActions1->lpsaActions[i].Delay == lpFailureActions2->lpsaActions[i].Delay, "lpFailureActions1->lpsaActions[%lu].Delay != lpFailureActions2->lpsaActions[%lu].Delay\n", i, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* TODO: retrieve the strings if they are in MUI format */
|
|
|
|
/* Compare RebootMsg */
|
|
if (lpFailureActions1->lpRebootMsg && lpRebootMessage)
|
|
iRet = strcmp(lpFailureActions1->lpRebootMsg, lpRebootMessage);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved reboot messages are different !\n");
|
|
|
|
/* Compare Command */
|
|
if (lpFailureActions1->lpCommand && lpFailureCommand)
|
|
iRet = strcmp(lpFailureActions1->lpCommand, lpFailureCommand);
|
|
else
|
|
iRet = 0;
|
|
|
|
ok(iRet == 0, "Retrieved commands are different !\n");
|
|
|
|
|
|
/* Memory cleanup */
|
|
if (lpRebootMessage)
|
|
HeapFree(GetProcessHeap(), 0, lpRebootMessage);
|
|
|
|
if (lpFailureCommand)
|
|
HeapFree(GetProcessHeap(), 0, lpFailureCommand);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpFailureActions2);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
skip("Unknown dwInfoLevel %lu, cannot proceed with QueryConfig2A --> %lu test\n", dwInfoLevel, dwInfoLevel);
|
|
break;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpBuffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void Test_QueryServiceConfig2W(void)
|
|
{
|
|
SC_HANDLE hScm = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
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 QueryServiceConfig2W test\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
ok_err(ERROR_SUCCESS);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
hService = OpenServiceW(hScm, TESTING_SERVICEW, SERVICE_QUERY_CONFIG);
|
|
ok(hService != NULL, "Failed to open service handle, error=0x%08lx\n", GetLastError());
|
|
if (!hService)
|
|
{
|
|
skip("Service not found; cannot proceed with QueryServiceConfig2W test\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
ok_err(ERROR_SUCCESS);
|
|
|
|
if (QueryConfig2W(hService, TESTING_SERVICEW, SERVICE_CONFIG_DESCRIPTION) != 0)
|
|
goto cleanup;
|
|
|
|
if (QueryConfig2W(hService, TESTING_SERVICEW, SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
if (hService)
|
|
CloseServiceHandle(hService);
|
|
|
|
if (hScm)
|
|
CloseServiceHandle(hScm);
|
|
}
|
|
|
|
static void Test_QueryServiceConfig2A(void)
|
|
{
|
|
SC_HANDLE hScm = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
|
|
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 QueryServiceConfig2A test\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
ok_err(ERROR_SUCCESS);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
hService = OpenServiceA(hScm, TESTING_SERVICEA, SERVICE_QUERY_CONFIG);
|
|
ok(hService != NULL, "Failed to open service handle, error=0x%08lx\n", GetLastError());
|
|
if (!hService)
|
|
{
|
|
skip("Service not found; cannot proceed with QueryServiceConfig2A test\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
ok_err(ERROR_SUCCESS);
|
|
|
|
if (QueryConfig2A(hService, TESTING_SERVICEA, SERVICE_CONFIG_DESCRIPTION) != 0)
|
|
goto cleanup;
|
|
|
|
if (QueryConfig2A(hService, TESTING_SERVICEA, SERVICE_CONFIG_FAILURE_ACTIONS) != 0)
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
if (hService)
|
|
CloseServiceHandle(hService);
|
|
|
|
if (hScm)
|
|
CloseServiceHandle(hScm);
|
|
}
|
|
|
|
|
|
START_TEST(QueryServiceConfig2)
|
|
{
|
|
Test_QueryServiceConfig2W();
|
|
Test_QueryServiceConfig2A();
|
|
}
|