Files
reactos/reactos/lib/advapi32/service/sctrl.c
T
Gé van Geldorp e9b3a79c09 Silence debug messages
svn path=/trunk/; revision=5893
2003-08-28 13:38:24 +00:00

447 lines
9.8 KiB
C

/* $Id: sctrl.c,v 1.12 2003/08/28 13:38:23 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/service/sctrl.c
* PURPOSE: Service control manager functions
* PROGRAMMER: Emanuele Aliberti
* UPDATE HISTORY:
* 19990413 EA created
* 19990515 EA
*/
/* INCLUDES ******************************************************************/
#define NTOS_MODE_USER
#include <ntos.h>
#include <windows.h>
#include <string.h>
#include <wchar.h>
#define NDEBUG
#include <debug.h>
/* TYPES *********************************************************************/
typedef struct
{
DWORD ThreadId;
UNICODE_STRING ServiceName;
LPSERVICE_MAIN_FUNCTIONW MainFunction;
LPHANDLER_FUNCTION HandlerFunction;
SERVICE_STATUS ServiceStatus;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
/* GLOBALS *******************************************************************/
static ULONG ActiveServiceCount;
static PACTIVE_SERVICE ActiveServices;
/* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in use */
/* FUNCTIONS *****************************************************************/
static PACTIVE_SERVICE
ScLookupServiceByServiceName(LPWSTR lpServiceName)
{
DWORD i;
for (i = 0; i < ActiveServiceCount; i++)
{
if (_wcsicmp(ActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
{
return(&ActiveServices[i]);
}
}
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return(NULL);
}
static PACTIVE_SERVICE
ScLookupServiceByThreadId(DWORD ThreadId)
{
DWORD i;
for (i = 0; i < ActiveServiceCount; i++)
{
if (ActiveServices[i].ThreadId == ThreadId)
{
return(&ActiveServices[i]);
}
}
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return(NULL);
}
static DWORD
ScConnectControlPipe(HANDLE *hPipe)
{
DWORD dwBytesWritten;
DWORD dwProcessId;
DWORD dwState;
WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe",
15000);
*hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (*hPipe == INVALID_HANDLE_VALUE)
return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT);
dwState = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
{
CloseHandle(hPipe);
*hPipe = INVALID_HANDLE_VALUE;
return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT);
}
dwProcessId = GetCurrentProcessId();
WriteFile(*hPipe,
&dwProcessId,
sizeof(DWORD),
&dwBytesWritten,
NULL);
return(ERROR_SUCCESS);
}
static VOID
ScServiceDispatcher(HANDLE hPipe, PVOID p1, PVOID p2)
{
DPRINT1("ScDispatcherLoop() called\n");
#if 0
while (TRUE)
{
/* Read command from the control pipe */
/* Execute command */
}
#endif
}
DWORD WINAPI
ScServiceMainStub(LPVOID Context)
{
LPSERVICE_MAIN_FUNCTIONW lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)Context;
/* FIXME: Send argc and argv (from command line) as arguments */
(lpServiceProc)(0, NULL);
return ERROR_SUCCESS;
}
/**********************************************************************
* RegisterServiceCtrlHandlerA
*
* @implemented
*/
SERVICE_STATUS_HANDLE STDCALL
RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
LPHANDLER_FUNCTION lpHandlerProc)
{
ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameU;
SERVICE_STATUS_HANDLE SHandle;
RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
{
SetLastError(ERROR_OUTOFMEMORY);
return((SERVICE_STATUS_HANDLE)0);
}
SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
lpHandlerProc);
RtlFreeUnicodeString(&ServiceNameU);
return(SHandle);
}
/**********************************************************************
* RegisterServiceCtrlHandlerW
*
* @implemented
*/
SERVICE_STATUS_HANDLE STDCALL
RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
LPHANDLER_FUNCTION lpHandlerProc)
{
PACTIVE_SERVICE Service;
Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
if (Service == NULL)
{
return((SERVICE_STATUS_HANDLE)NULL);
}
Service->HandlerFunction = lpHandlerProc;
return((SERVICE_STATUS_HANDLE)Service->ThreadId);
}
/**********************************************************************
* SetServiceBits
*
* @unimplemented
*/
BOOL STDCALL
SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
DWORD dwServiceBits,
BOOL bSetBitsOn,
BOOL bUpdateImmediately)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return(FALSE);
}
/**********************************************************************
* SetServiceObjectSecurity
*
* @unimplemented
*/
WINBOOL STDCALL
SetServiceObjectSecurity(SC_HANDLE hService,
SECURITY_INFORMATION dwSecurityInformation,
PSECURITY_DESCRIPTOR lpSecurityDescriptor)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/**********************************************************************
* SetServiceStatus
*
* @implemented
*/
BOOL STDCALL
SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
LPSERVICE_STATUS lpServiceStatus)
{
PACTIVE_SERVICE Service;
Service = ScLookupServiceByThreadId((DWORD)hServiceStatus);
if (!Service)
{
SetLastError(ERROR_INVALID_HANDLE);
return(FALSE);
}
RtlCopyMemory(&Service->ServiceStatus,
lpServiceStatus,
sizeof(SERVICE_STATUS));
return(TRUE);
}
/**********************************************************************
* StartServiceCtrlDispatcherA
*
* @unimplemented
*/
BOOL STDCALL
StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
{
// FIXME how to deal with diffs between ANSI/UNICODE
#if 0
LPSERVICE_TABLE_ENTRYW ServiceStartTableW;
ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameW;
ULONG i, j;
ULONG Count;
BOOL b;
i = 0;
while (lpServiceStartTable[i].lpServiceProc != NULL)
{
i++;
}
Count = i;
ServiceStartTableW = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SERVICE_TABLE_ENTRYW) * Count);
for (i = 0; i < Count; i++)
{
RtlInitAnsiString(
&ServiceNameA,
lpServiceStartTable[i].lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
&ServiceNameW,
&ServiceNameA,
TRUE)))
{
for (j = 0; j < i; j++)
{
RtlInitUnicodeString(
&ServiceNameW,
ServiceStartTableW[j].lpServiceName);
RtlFreeUnicodeString(&ServiceNameW);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
ServiceStartTableW[i].lpServiceName = ServiceNameW.Buffer;
ServiceStartTableW[i].lpServiceProc =
lpServiceStartTable[i].lpServiceProc;
}
b = StartServiceCtrlDispatcherW(ServiceStartTableW);
for (i = 0; i < Count; i++)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW[i].lpServiceName);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
return b;
#else
UNIMPLEMENTED;
return 0;
#endif
}
/**********************************************************************
* StartServiceCtrlDispatcherW
*
* @unimplemented
*/
BOOL STDCALL
StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
{
ULONG i;
HANDLE hPipe;
DWORD dwError;
DPRINT("StartServiceCtrlDispatcherW() called\n");
i = 0;
while (lpServiceStartTable[i].lpServiceProc != NULL)
{
i++;
}
ActiveServiceCount = i;
ActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
ActiveServiceCount * sizeof(ACTIVE_SERVICE));
if (ActiveServices == NULL)
{
return(FALSE);
}
/* Copy service names and start procedure */
for (i = 0; i < ActiveServiceCount; i++)
{
RtlCreateUnicodeString(&ActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
ActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc;
}
dwError = ScConnectControlPipe(&hPipe);
if (dwError == ERROR_SUCCESS)
{
/* FIXME: free the service table */
return(FALSE);
}
ScServiceDispatcher(hPipe, NULL, NULL);
CloseHandle(hPipe);
/* FIXME: free the service table */
return(TRUE);
#if 0
ActiveServicesThreadHandles = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
(ActiveServiceCount + 1) * sizeof(HANDLE));
if (!ActiveServicesThreadHandles)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
ActiveServices = NULL;
return(FALSE);
}
for (i = 0; i<ActiveServiceCount; i++)
{
h = CreateThread(
NULL,
0,
ScServiceMainStub,
lpServiceStartTable[i].lpServiceProc,
0,
&Tid);
if (h == INVALID_HANDLE_VALUE)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServicesThreadHandles);
ActiveServicesThreadHandles = NULL;
RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
ActiveServices = NULL;
return(FALSE);
}
ActiveServicesThreadHandles[i + 1] = h;
ActiveServices[i].ThreadId = Tid;
}
while (ActiveServiceCount > 0)
{
r = WaitForMultipleObjects(
ActiveServiceCount + 1,
ActiveServicesThreadHandles,
FALSE,
INFINITE);
if (r == WAIT_OBJECT_0)
{
/* Received message from the scm */
}
else if (r > WAIT_OBJECT_0 && r < (WAIT_OBJECT_0 + ActiveServiceCount))
{
/* A service died */
ActiveServiceCount--;
ActiveServicesThreadHandles[r - WAIT_OBJECT_0 - 1] =
ActiveServicesThreadHandles[ActiveServiceCount + 1];
RtlCopyMemory(
&ActiveServices[r - WAIT_OBJECT_0 - 2],
&ActiveServices[ActiveServiceCount],
sizeof(ACTIVE_SERVICE));
}
else
{
/* Bail */
}
}
return TRUE;
#endif
}
/* EOF */