2007-09-12 08:46:00 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS advapi32
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: dll/win32/advapi32/service/sctrl.c
|
|
|
|
* PURPOSE: Service control manager functions
|
|
|
|
* COPYRIGHT: Copyright 1999 Emanuele Aliberti
|
|
|
|
* Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
|
2005-05-09 01:43:41 +00:00
|
|
|
*
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2005-08-05 10:31:28 +00:00
|
|
|
#include <advapi32.h>
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2002-07-20 13:31:34 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/* TYPES *********************************************************************/
|
|
|
|
|
2007-09-11 12:59:38 +00:00
|
|
|
VOID HandleBind(VOID);
|
|
|
|
|
2005-01-08 18:11:46 +00:00
|
|
|
typedef struct _ACTIVE_SERVICE
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2007-09-12 08:46:00 +00:00
|
|
|
CLIENT_HANDLE hService;
|
2006-09-01 15:49:50 +00:00
|
|
|
UNICODE_STRING ServiceName;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
LPSERVICE_MAIN_FUNCTIONA lpFuncA;
|
|
|
|
LPSERVICE_MAIN_FUNCTIONW lpFuncW;
|
|
|
|
} Main;
|
|
|
|
LPHANDLER_FUNCTION HandlerFunction;
|
|
|
|
LPHANDLER_FUNCTION_EX HandlerFunctionEx;
|
|
|
|
LPVOID HandlerContext;
|
|
|
|
SERVICE_STATUS ServiceStatus;
|
|
|
|
BOOL bUnicode;
|
|
|
|
LPWSTR Arguments;
|
2000-03-26 22:00:10 +00:00
|
|
|
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
|
|
|
|
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
2007-09-11 12:59:38 +00:00
|
|
|
extern handle_t BindingHandle;
|
2005-01-08 18:11:46 +00:00
|
|
|
static DWORD dwActiveServiceCount = 0;
|
|
|
|
static PACTIVE_SERVICE lpActiveServices = NULL;
|
2000-03-26 22:00:10 +00:00
|
|
|
|
|
|
|
|
2005-01-08 18:11:46 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
2002-07-20 13:31:34 +00:00
|
|
|
|
|
|
|
static PACTIVE_SERVICE
|
2007-01-21 22:42:44 +00:00
|
|
|
ScLookupServiceByServiceName(LPCWSTR lpServiceName)
|
2001-10-21 19:06:42 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
DWORD i;
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
for (i = 0; i < dwActiveServiceCount; i++)
|
2001-10-21 19:06:42 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
|
|
|
|
{
|
|
|
|
return &lpActiveServices[i];
|
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return NULL;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
2005-01-08 18:11:46 +00:00
|
|
|
|
|
|
|
static DWORD WINAPI
|
|
|
|
ScServiceMainStub(LPVOID Context)
|
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
PACTIVE_SERVICE lpService;
|
|
|
|
DWORD dwArgCount = 0;
|
|
|
|
DWORD dwLength = 0;
|
|
|
|
DWORD dwLen;
|
|
|
|
LPWSTR lpPtr;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
lpService = (PACTIVE_SERVICE)Context;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT("ScServiceMainStub() called\n");
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Count arguments */
|
|
|
|
lpPtr = lpService->Arguments;
|
|
|
|
while (*lpPtr)
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2007-05-10 10:13:01 +00:00
|
|
|
DPRINT("arg: %S\n", lpPtr);
|
2006-09-01 15:49:50 +00:00
|
|
|
dwLen = wcslen(lpPtr) + 1;
|
|
|
|
dwArgCount++;
|
|
|
|
dwLength += dwLen;
|
|
|
|
lpPtr += dwLen;
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Build the argument vector and call the main service routine */
|
|
|
|
if (lpService->bUnicode)
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
LPWSTR *lpArgVector;
|
|
|
|
LPWSTR Ptr;
|
|
|
|
|
|
|
|
lpArgVector = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(dwArgCount + 1) * sizeof(LPWSTR));
|
|
|
|
if (lpArgVector == NULL)
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
|
|
|
dwArgCount = 0;
|
|
|
|
Ptr = lpService->Arguments;
|
|
|
|
while (*Ptr)
|
|
|
|
{
|
|
|
|
lpArgVector[dwArgCount] = Ptr;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwArgCount++;
|
|
|
|
Ptr += (wcslen(Ptr) + 1);
|
|
|
|
}
|
|
|
|
lpArgVector[dwArgCount] = NULL;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
(lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
lpArgVector);
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
2006-09-01 15:49:50 +00:00
|
|
|
else
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
LPSTR *lpArgVector;
|
|
|
|
LPSTR Ptr;
|
|
|
|
LPSTR AnsiString;
|
|
|
|
DWORD AnsiLength;
|
|
|
|
|
|
|
|
AnsiLength = WideCharToMultiByte(CP_ACP,
|
|
|
|
0,
|
|
|
|
lpService->Arguments,
|
|
|
|
dwLength,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2007-05-10 10:13:01 +00:00
|
|
|
if (AnsiLength == 0)
|
|
|
|
return ERROR_INVALID_PARAMETER; /* ? */
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
AnsiString = HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
2007-05-10 10:13:01 +00:00
|
|
|
AnsiLength + 1);
|
|
|
|
if (AnsiString == NULL)
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
WideCharToMultiByte(CP_ACP,
|
|
|
|
0,
|
|
|
|
lpService->Arguments,
|
|
|
|
dwLength,
|
|
|
|
AnsiString,
|
|
|
|
AnsiLength,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
2007-05-10 10:13:01 +00:00
|
|
|
AnsiString[AnsiLength] = ANSI_NULL;
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
lpArgVector = HeapAlloc(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
(dwArgCount + 1) * sizeof(LPSTR));
|
2007-05-10 10:13:01 +00:00
|
|
|
if (lpArgVector == NULL)
|
2007-07-09 02:02:30 +00:00
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
AnsiString);
|
2007-05-10 10:13:01 +00:00
|
|
|
return ERROR_OUTOFMEMORY;
|
2007-07-09 02:02:30 +00:00
|
|
|
}
|
2006-09-01 15:49:50 +00:00
|
|
|
|
|
|
|
dwArgCount = 0;
|
|
|
|
Ptr = AnsiString;
|
|
|
|
while (*Ptr)
|
|
|
|
{
|
|
|
|
lpArgVector[dwArgCount] = Ptr;
|
|
|
|
|
|
|
|
dwArgCount++;
|
|
|
|
Ptr += (strlen(Ptr) + 1);
|
|
|
|
}
|
|
|
|
lpArgVector[dwArgCount] = NULL;
|
|
|
|
|
|
|
|
(lpService->Main.lpFuncA)(dwArgCount, lpArgVector);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
lpArgVector);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
AnsiString);
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return ERROR_SUCCESS;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
ScConnectControlPipe(HANDLE *hPipe)
|
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
DWORD dwBytesWritten;
|
|
|
|
DWORD dwState;
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
if (!WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", 15000))
|
2005-01-08 18:11:46 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT1("WaitNamedPipe() failed (Error %lu)\n", GetLastError());
|
|
|
|
return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
|
2005-01-08 18:11:46 +00:00
|
|
|
}
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
*hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe",
|
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
NULL);
|
|
|
|
if (*hPipe == INVALID_HANDLE_VALUE)
|
2005-01-08 18:11:46 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT1("CreateFileW() failed (Error %lu)\n", GetLastError());
|
|
|
|
return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
|
2005-01-08 18:11:46 +00:00
|
|
|
}
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwState = PIPE_READMODE_MESSAGE;
|
|
|
|
if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
CloseHandle(hPipe);
|
|
|
|
*hPipe = INVALID_HANDLE_VALUE;
|
|
|
|
return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
/* Share the SERVICE_HANDLE handle with the SCM */
|
2006-09-01 15:49:50 +00:00
|
|
|
WriteFile(*hPipe,
|
2007-09-12 08:46:00 +00:00
|
|
|
(DWORD *)&lpActiveServices->hService,
|
|
|
|
sizeof(CLIENT_HANDLE),
|
2006-09-01 15:49:50 +00:00
|
|
|
&dwBytesWritten,
|
|
|
|
NULL);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
DPRINT("Sent SERVICE_HANDLE %lu\n", lpActiveServices->hService);
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return ERROR_SUCCESS;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-28 13:28:56 +00:00
|
|
|
static DWORD
|
2006-12-26 01:29:22 +00:00
|
|
|
ScStartService(PSCM_CONTROL_PACKET ControlPacket)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
PACTIVE_SERVICE lpService;
|
|
|
|
HANDLE ThreadHandle;
|
2007-09-11 12:59:38 +00:00
|
|
|
DWORD ThreadId;
|
2006-09-01 15:49:50 +00:00
|
|
|
|
|
|
|
DPRINT("ScStartService() called\n");
|
2007-09-12 08:46:00 +00:00
|
|
|
DPRINT("client handle: %lu\n", ControlPacket->hClient);
|
2006-12-26 01:29:22 +00:00
|
|
|
DPRINT("Size: %lu\n", ControlPacket->dwSize);
|
|
|
|
DPRINT("Service: %S\n", &ControlPacket->szArguments[0]);
|
2006-09-01 15:49:50 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
lpService = (PACTIVE_SERVICE)ControlPacket->hClient;
|
2006-09-01 15:49:50 +00:00
|
|
|
if (lpService == NULL)
|
2007-09-12 08:46:00 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Service not found\n");
|
2006-09-01 15:49:50 +00:00
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
2007-09-12 08:46:00 +00:00
|
|
|
}
|
2006-09-01 15:49:50 +00:00
|
|
|
|
|
|
|
lpService->Arguments = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
2006-12-26 01:29:22 +00:00
|
|
|
ControlPacket->dwSize * sizeof(WCHAR));
|
2006-09-01 15:49:50 +00:00
|
|
|
if (lpService->Arguments == NULL)
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
|
|
|
memcpy(lpService->Arguments,
|
2006-12-26 01:29:22 +00:00
|
|
|
ControlPacket->szArguments,
|
|
|
|
ControlPacket->dwSize * sizeof(WCHAR));
|
2006-09-01 15:49:50 +00:00
|
|
|
|
2007-09-11 12:59:38 +00:00
|
|
|
/* invoke the services entry point and implement the command loop */
|
2006-09-01 15:49:50 +00:00
|
|
|
ThreadHandle = CreateThread(NULL,
|
|
|
|
0,
|
|
|
|
ScServiceMainStub,
|
|
|
|
lpService,
|
|
|
|
CREATE_SUSPENDED,
|
2007-09-11 12:59:38 +00:00
|
|
|
&ThreadId);
|
2006-09-01 15:49:50 +00:00
|
|
|
if (ThreadHandle == NULL)
|
|
|
|
return ERROR_SERVICE_NO_THREAD;
|
|
|
|
|
|
|
|
ResumeThread(ThreadHandle);
|
|
|
|
CloseHandle(ThreadHandle);
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-11 12:59:38 +00:00
|
|
|
static DWORD
|
|
|
|
ScControlService(PSCM_CONTROL_PACKET ControlPacket)
|
|
|
|
{
|
|
|
|
PACTIVE_SERVICE lpService;
|
|
|
|
|
|
|
|
DPRINT("ScControlService() called\n");
|
|
|
|
DPRINT("Size: %lu\n", ControlPacket->dwSize);
|
|
|
|
DPRINT("Service: %S\n", &ControlPacket->szArguments[0]);
|
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
lpService = (PACTIVE_SERVICE)ControlPacket->hClient;
|
2007-09-11 12:59:38 +00:00
|
|
|
if (lpService == NULL)
|
2007-09-12 08:46:00 +00:00
|
|
|
{
|
|
|
|
DPRINT1("Service not found\n");
|
2007-09-11 12:59:38 +00:00
|
|
|
return ERROR_SERVICE_DOES_NOT_EXIST;
|
2007-09-12 08:46:00 +00:00
|
|
|
}
|
2007-09-11 12:59:38 +00:00
|
|
|
|
|
|
|
if (lpService->HandlerFunction)
|
|
|
|
{
|
|
|
|
(lpService->HandlerFunction)(ControlPacket->dwControl);
|
|
|
|
}
|
|
|
|
else if (lpService->HandlerFunctionEx)
|
|
|
|
{
|
|
|
|
/* FIXME: send correct params */
|
|
|
|
(lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ControlPacket->dwControl == SERVICE_CONTROL_STOP)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
|
|
|
lpService->Arguments);
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("ScControlService() done\n");
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-28 13:28:56 +00:00
|
|
|
static BOOL
|
|
|
|
ScServiceDispatcher(HANDLE hPipe,
|
2006-09-01 15:49:50 +00:00
|
|
|
PUCHAR lpBuffer,
|
|
|
|
DWORD dwBufferSize)
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2006-12-26 01:29:22 +00:00
|
|
|
PSCM_CONTROL_PACKET ControlPacket;
|
2006-09-01 15:49:50 +00:00
|
|
|
DWORD Count;
|
|
|
|
BOOL bResult;
|
2006-12-26 01:29:22 +00:00
|
|
|
DWORD dwRunningServices = 0;
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT("ScDispatcherLoop() called\n");
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-12-26 01:29:22 +00:00
|
|
|
ControlPacket = HeapAlloc(GetProcessHeap(),
|
2007-09-12 08:46:00 +00:00
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
1024);
|
2006-12-26 01:29:22 +00:00
|
|
|
if (ControlPacket == NULL)
|
2006-09-01 15:49:50 +00:00
|
|
|
return FALSE;
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
while (TRUE)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Read command from the control pipe */
|
|
|
|
bResult = ReadFile(hPipe,
|
2006-12-26 01:29:22 +00:00
|
|
|
ControlPacket,
|
2006-09-01 15:49:50 +00:00
|
|
|
1024,
|
|
|
|
&Count,
|
|
|
|
NULL);
|
|
|
|
if (bResult == FALSE)
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT1("Pipe read failed (Error: %lu)\n", GetLastError());
|
|
|
|
return FALSE;
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Execute command */
|
2006-12-26 01:29:22 +00:00
|
|
|
switch (ControlPacket->dwControl)
|
2005-01-28 13:28:56 +00:00
|
|
|
{
|
2006-12-26 01:29:22 +00:00
|
|
|
case SERVICE_CONTROL_START:
|
2007-09-11 12:59:38 +00:00
|
|
|
DPRINT("Start command - recieved SERVICE_CONTROL_START\n");
|
2006-12-26 01:29:22 +00:00
|
|
|
if (ScStartService(ControlPacket) == ERROR_SUCCESS)
|
|
|
|
dwRunningServices++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SERVICE_CONTROL_STOP:
|
2007-09-11 12:59:38 +00:00
|
|
|
DPRINT("Stop command - recieved SERVICE_CONTROL_STOP\n");
|
|
|
|
if (ScControlService(ControlPacket) == ERROR_SUCCESS)
|
|
|
|
dwRunningServices--;
|
2006-09-01 15:49:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-09-11 12:59:38 +00:00
|
|
|
DPRINT("Unknown command %lu", ControlPacket->dwControl);
|
|
|
|
continue;
|
2005-01-28 13:28:56 +00:00
|
|
|
}
|
2006-12-26 01:29:22 +00:00
|
|
|
|
|
|
|
if (dwRunningServices == 0)
|
|
|
|
break;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2005-01-28 13:28:56 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
HeapFree(GetProcessHeap(),
|
|
|
|
0,
|
2006-12-26 01:29:22 +00:00
|
|
|
ControlPacket);
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return TRUE;
|
2001-10-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* RegisterServiceCtrlHandlerA
|
2003-07-10 15:05:55 +00:00
|
|
|
*
|
|
|
|
* @implemented
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
2002-07-20 13:31:34 +00:00
|
|
|
SERVICE_STATUS_HANDLE STDCALL
|
|
|
|
RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
|
2006-09-01 15:49:50 +00:00
|
|
|
LPHANDLER_FUNCTION lpHandlerProc)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
ANSI_STRING ServiceNameA;
|
|
|
|
UNICODE_STRING ServiceNameU;
|
|
|
|
SERVICE_STATUS_HANDLE SHandle;
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
|
|
|
|
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
|
|
return (SERVICE_STATUS_HANDLE)0;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
|
|
|
|
lpHandlerProc);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlFreeUnicodeString(&ServiceNameU);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return SHandle;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* RegisterServiceCtrlHandlerW
|
2003-07-10 15:05:55 +00:00
|
|
|
*
|
|
|
|
* @implemented
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
2002-07-20 13:31:34 +00:00
|
|
|
SERVICE_STATUS_HANDLE STDCALL
|
|
|
|
RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
|
2006-09-01 15:49:50 +00:00
|
|
|
LPHANDLER_FUNCTION lpHandlerProc)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
PACTIVE_SERVICE Service;
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
|
|
|
|
if (Service == NULL)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
return (SERVICE_STATUS_HANDLE)NULL;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
Service->HandlerFunction = lpHandlerProc;
|
|
|
|
Service->HandlerFunctionEx = NULL;
|
2005-02-06 21:57:44 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
DPRINT("RegisterServiceCtrlHandler returning %lu\n", Service->hService);
|
2007-09-11 12:59:38 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
return (SERVICE_STATUS_HANDLE)Service->hService;
|
2005-02-06 21:57:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* RegisterServiceCtrlHandlerExA
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
SERVICE_STATUS_HANDLE STDCALL
|
|
|
|
RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
|
2006-09-01 15:49:50 +00:00
|
|
|
LPHANDLER_FUNCTION_EX lpHandlerProc,
|
|
|
|
LPVOID lpContext)
|
2005-02-06 21:57:44 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
ANSI_STRING ServiceNameA;
|
|
|
|
UNICODE_STRING ServiceNameU;
|
|
|
|
SERVICE_STATUS_HANDLE SHandle;
|
2005-02-06 21:57:44 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
|
|
|
|
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
|
2005-02-06 21:57:44 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
|
|
return (SERVICE_STATUS_HANDLE)0;
|
2005-02-06 21:57:44 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
|
|
|
|
lpHandlerProc,
|
|
|
|
lpContext);
|
2005-02-06 21:57:44 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlFreeUnicodeString(&ServiceNameU);
|
2005-02-06 21:57:44 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return SHandle;
|
2005-02-06 21:57:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* RegisterServiceCtrlHandlerExW
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
SERVICE_STATUS_HANDLE STDCALL
|
|
|
|
RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
|
2006-09-01 15:49:50 +00:00
|
|
|
LPHANDLER_FUNCTION_EX lpHandlerProc,
|
|
|
|
LPVOID lpContext)
|
2005-02-06 21:57:44 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
PACTIVE_SERVICE Service;
|
2005-02-06 21:57:44 +00:00
|
|
|
|
2007-01-21 22:42:44 +00:00
|
|
|
Service = ScLookupServiceByServiceName(lpServiceName);
|
2006-09-01 15:49:50 +00:00
|
|
|
if (Service == NULL)
|
2005-02-06 21:57:44 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
return (SERVICE_STATUS_HANDLE)NULL;
|
2005-02-06 21:57:44 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
Service->HandlerFunction = NULL;
|
|
|
|
Service->HandlerFunctionEx = lpHandlerProc;
|
|
|
|
Service->HandlerContext = lpContext;
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
DPRINT("RegisterServiceCtrlHandlerEx returning %lu", Service->hService);
|
2007-09-11 12:59:38 +00:00
|
|
|
|
2007-09-12 08:46:00 +00:00
|
|
|
return (SERVICE_STATUS_HANDLE)Service->hService;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* SetServiceBits
|
2003-07-10 15:05:55 +00:00
|
|
|
*
|
|
|
|
* @unimplemented
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
2002-07-20 13:31:34 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
|
2006-09-01 15:49:50 +00:00
|
|
|
DWORD dwServiceBits,
|
|
|
|
BOOL bSetBitsOn,
|
|
|
|
BOOL bUpdateImmediately)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return FALSE;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-11 12:59:38 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* SetServiceStatus
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL STDCALL
|
|
|
|
SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
|
|
|
|
LPSERVICE_STATUS lpServiceStatus)
|
|
|
|
{
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
|
|
DPRINT("SetServiceStatus() called\n");
|
|
|
|
DPRINT("hServiceStatus %lu\n", hServiceStatus);
|
|
|
|
|
|
|
|
HandleBind();
|
|
|
|
|
|
|
|
/* Call to services.exe using RPC */
|
|
|
|
dwError = ScmrSetServiceStatus(BindingHandle,
|
|
|
|
(unsigned long)hServiceStatus,
|
|
|
|
lpServiceStatus);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
DPRINT1("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
|
|
|
|
SetLastError(dwError);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT("SetServiceStatus() done (ret %lu)\n", dwError);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-03-26 22:00:10 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* StartServiceCtrlDispatcherA
|
2003-07-10 15:05:55 +00:00
|
|
|
*
|
2007-09-12 08:46:00 +00:00
|
|
|
* @implemented
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
2002-07-20 13:31:34 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
ULONG i;
|
|
|
|
HANDLE hPipe;
|
|
|
|
DWORD dwError;
|
|
|
|
PUCHAR lpMessageBuffer;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT("StartServiceCtrlDispatcherA() called\n");
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
i = 0;
|
|
|
|
while (lpServiceStartTable[i].lpServiceProc != NULL)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
i++;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwActiveServiceCount = i;
|
|
|
|
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
|
|
|
|
if (lpActiveServices == NULL)
|
2001-10-21 19:06:42 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
return FALSE;
|
2001-10-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Copy service names and start procedure */
|
|
|
|
for (i = 0; i < dwActiveServiceCount; i++)
|
2005-01-08 18:11:46 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
|
|
|
|
lpServiceStartTable[i].lpServiceName);
|
|
|
|
lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
|
2007-09-12 08:46:00 +00:00
|
|
|
lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
|
2006-09-01 15:49:50 +00:00
|
|
|
lpActiveServices[i].bUnicode = FALSE;
|
2005-01-08 18:11:46 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwError = ScConnectControlPipe(&hPipe);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
|
|
|
return FALSE;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
256);
|
|
|
|
if (lpMessageBuffer == NULL)
|
2005-01-08 18:11:46 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
|
|
|
CloseHandle(hPipe);
|
|
|
|
return FALSE;
|
2005-01-08 18:11:46 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
|
|
|
|
CloseHandle(hPipe);
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the message buffer */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
2005-01-08 18:11:46 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return TRUE;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* StartServiceCtrlDispatcherW
|
2003-07-10 15:05:55 +00:00
|
|
|
*
|
2007-09-12 08:46:00 +00:00
|
|
|
* @implemented
|
2000-03-26 22:00:10 +00:00
|
|
|
*/
|
2002-07-20 13:31:34 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
|
2000-03-26 22:00:10 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
ULONG i;
|
|
|
|
HANDLE hPipe;
|
|
|
|
DWORD dwError;
|
|
|
|
PUCHAR lpMessageBuffer;
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
DPRINT("StartServiceCtrlDispatcherW() called\n");
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
i = 0;
|
|
|
|
while (lpServiceStartTable[i].lpServiceProc != NULL)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
i++;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwActiveServiceCount = i;
|
|
|
|
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
|
|
|
|
if (lpActiveServices == NULL)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
return FALSE;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Copy service names and start procedure */
|
|
|
|
for (i = 0; i < dwActiveServiceCount; i++)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
|
|
|
|
lpServiceStartTable[i].lpServiceName);
|
|
|
|
lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
|
2007-09-12 08:46:00 +00:00
|
|
|
lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
|
2006-09-01 15:49:50 +00:00
|
|
|
lpActiveServices[i].bUnicode = TRUE;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
dwError = ScConnectControlPipe(&hPipe);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2002-07-20 13:31:34 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
|
|
|
return FALSE;
|
2002-07-20 13:31:34 +00:00
|
|
|
}
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
256);
|
|
|
|
if (lpMessageBuffer == NULL)
|
2005-01-08 18:11:46 +00:00
|
|
|
{
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
|
|
|
CloseHandle(hPipe);
|
|
|
|
return FALSE;
|
2005-01-08 18:11:46 +00:00
|
|
|
}
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
|
|
|
|
CloseHandle(hPipe);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the message buffer */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
|
2002-07-20 13:31:34 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
/* Free the service table */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
|
|
|
|
lpActiveServices = NULL;
|
|
|
|
dwActiveServiceCount = 0;
|
2001-10-21 19:06:42 +00:00
|
|
|
|
2006-09-01 15:49:50 +00:00
|
|
|
return TRUE;
|
2000-03-26 22:00:10 +00:00
|
|
|
}
|
|
|
|
|
2002-07-20 13:31:34 +00:00
|
|
|
/* EOF */
|