У меня есть служба Windows, которая пытается запустить драйвер.
Я получаю дескриптор драйвера и вызываю StartService, и он возвращает SUCCESS.Но сразу после этого я делаю QueryServiceStatusEx и dwCurrentState равен 1 (SERVICE_STOPPED).
Затем я пытаюсь запустить его снова (хотя StartService вернул true в первый раз), и происходит то же самое: StartService возвращает true, но dwCurrentStateвсе еще 1. Что интересно, если я помещаю одну секунду в спящий режим между двумя запусками, она работает как положено.
Код слишком велик, чтобы я мог опубликовать его полностью, но он выглядит примерно так:
SERVICE_STATUS_PROCESS get_service_info(const wchar_t* szSvcName)
{
SERVICE_STATUS_PROCESS ssStatus{};
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
DWORD dwBytesNeeded;
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // servicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL != schSCManager)
{
// Get a handle to the service.
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_ALL_ACCESS); // full access
if (schService != NULL)
{
// Check the status in case the service is not stopped.
QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // information level
(LPBYTE)&ssStatus, // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded); // size needed if buffer is too small
}
}
if (schService != NULL)
CloseServiceHandle(schService);
if (schSCManager != NULL)
CloseServiceHandle(schSCManager);
return ssStatus;
}
void ServiceEntryPoint()
{
if (StartStopService(name, true, 5000))
{
auto IsServiceStopped = [name]
{
SERVICE_STATUS_PROCESS status = get_service_info(name);
return status.dwCurrentState == SERVICE_STOPPED;
};
// check if the service was really started
if (IsServiceStopped())
{
//Sleep(1000);
StartStopService(name, true, 1000);
}
bool stillStopped = IsServiceStopped();
}
}
Если я закомментирую строку Sleep (1000), get_service_info вернет SERVICE_STATUS_PROCESS со следующими значениями (для обоих вызовов):
DWORD dwServiceType = 1;
DWORD dwCurrentState = 1;
DWORD dwControlsAccepted = 0;
DWORD dwWin32ExitCode = 31;
DWORD dwServiceSpecificExitCode = 0;
DWORD dwCheckPoint = 0;
DWORD dwWaitHint = 0;
DWORD dwProcessId = 0;
DWORD dwServiceFlags = 0;
Если я сохраню Sleep (1000), get_service_info вернет SERVICE_STATUS_PROCESS с теми же значениями, что и выше, для первого вызова, но для второго вызова (после сна) он будет иметь следующие значения:
DWORD dwServiceType = 1;
DWORD dwCurrentState = 4;
DWORD dwControlsAccepted = 1;
DWORD dwWin32ExitCode = 0;
DWORD dwServiceSpecificExitCode = 0;
DWORD dwCheckPoint = 0;
DWORD dwWaitHint = 0;
DWORD dwProcessId = 0;
DWORD dwServiceFlags = 0;
У меня два вопроса:
Почему StartService возвращает true, если служба не была запущена?(даже не в ожидании запуска) Я добавил __debugbreak в DriverEntry моего драйвера, и он не срабатывает в первый раз.Как будто я вообще не вызываю StartService.То же поведение для второго вызова, если я не добавлю режим сна.При наличии сна происходит отладка.
Какое возможное объяснение необходимости этого сна для работы этого сценария?Я проверил раздел «Примечания» для StartService, но не нашел ничего, что давало бы четкое объяснение этому поведению.
Примечание!ServiceEntryPoint - это вызываемая функция, вызываемая в начале службы, которая пытается запустить драйвер (который не запускается).