/* INCLUDES ******************************************************************/
#include <advapi32.h>
-#include "wine/debug.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
/* TYPES *********************************************************************/
+typedef struct _SERVICE_THREAD_PARAMSA
+{
+ LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
+ DWORD dwArgCount;
+ LPSTR *lpArgVector;
+} SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
+
+
+typedef struct _SERVICE_THREAD_PARAMSW
+{
+ LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
+ DWORD dwArgCount;
+ LPWSTR *lpArgVector;
+} SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
+
+
typedef struct _ACTIVE_SERVICE
{
- CLIENT_HANDLE hService;
+ SERVICE_STATUS_HANDLE hServiceStatus;
UNICODE_STRING ServiceName;
union
{
- LPSERVICE_MAIN_FUNCTIONA lpFuncA;
- LPSERVICE_MAIN_FUNCTIONW lpFuncW;
- } Main;
+ SERVICE_THREAD_PARAMSA A;
+ SERVICE_THREAD_PARAMSW W;
+ } ThreadParams;
LPHANDLER_FUNCTION HandlerFunction;
LPHANDLER_FUNCTION_EX HandlerFunctionEx;
LPVOID HandlerContext;
- SERVICE_STATUS ServiceStatus;
BOOL bUnicode;
- LPWSTR Arguments;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;
+static handle_t hStatusBinding = NULL;
/* FUNCTIONS *****************************************************************/
+handle_t __RPC_USER
+RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
+{
+ return hStatusBinding;
+}
+
+
+void __RPC_USER
+RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
+ handle_t hBinding)
+{
+}
+
+
+static RPC_STATUS
+ScCreateStatusBinding(VOID)
+{
+ LPWSTR pszStringBinding;
+ RPC_STATUS status;
+
+ TRACE("ScCreateStatusBinding() called\n");
+
+ status = RpcStringBindingComposeW(NULL,
+ L"ncacn_np",
+ NULL,
+ L"\\pipe\\ntsvcs",
+ NULL,
+ &pszStringBinding);
+ if (status != RPC_S_OK)
+ {
+ ERR("RpcStringBindingCompose returned 0x%x\n", status);
+ return status;
+ }
+
+ /* Set the binding handle that will be used to bind to the server. */
+ status = RpcBindingFromStringBindingW(pszStringBinding,
+ &hStatusBinding);
+ if (status != RPC_S_OK)
+ {
+ ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
+ }
+
+ status = RpcStringFreeW(&pszStringBinding);
+ if (status != RPC_S_OK)
+ {
+ ERR("RpcStringFree returned 0x%x\n", status);
+ }
+
+ return status;
+}
+
+
+static RPC_STATUS
+ScDestroyStatusBinding(VOID)
+{
+ RPC_STATUS status;
+
+ TRACE("ScDestroyStatusBinding() called\n");
+
+ if (hStatusBinding == NULL)
+ return RPC_S_OK;
+
+ status = RpcBindingFree(&hStatusBinding);
+ if (status != RPC_S_OK)
+ {
+ ERR("RpcBindingFree returned 0x%x\n", status);
+ }
+ else
+ {
+ hStatusBinding = NULL;
+ }
+
+ return status;
+}
+
+
static PACTIVE_SERVICE
ScLookupServiceByServiceName(LPCWSTR lpServiceName)
{
DWORD i;
+ TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
+
for (i = 0; i < dwActiveServiceCount; i++)
{
+ TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
{
+ TRACE("Found!\n");
return &lpActiveServices[i];
}
}
+ TRACE("No service found!\n");
+
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return NULL;
static DWORD WINAPI
ScServiceMainStub(LPVOID Context)
{
- PACTIVE_SERVICE lpService;
- DWORD dwArgCount = 0;
- DWORD dwLength = 0;
- DWORD dwLen;
- LPWSTR lpPtr;
-
- lpService = (PACTIVE_SERVICE)Context;
+ PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
TRACE("ScServiceMainStub() called\n");
- /* Count arguments */
- lpPtr = lpService->Arguments;
- while (*lpPtr)
- {
- TRACE("arg: %S\n", lpPtr);
- dwLen = wcslen(lpPtr) + 1;
- dwArgCount++;
- dwLength += dwLen;
- lpPtr += dwLen;
- }
- TRACE("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
-
- /* Build the argument vector and call the main service routine */
+ /* Call the main service routine and free the arguments vector */
if (lpService->bUnicode)
{
- LPWSTR *lpArgVector;
- LPWSTR Ptr;
+ (lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
+ lpService->ThreadParams.W.lpArgVector);
- lpArgVector = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (dwArgCount + 1) * sizeof(LPWSTR));
- if (lpArgVector == NULL)
- return ERROR_OUTOFMEMORY;
-
- dwArgCount = 0;
- Ptr = lpService->Arguments;
- while (*Ptr)
+ if (lpService->ThreadParams.A.lpArgVector != NULL)
{
- lpArgVector[dwArgCount] = Ptr;
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpService->ThreadParams.W.lpArgVector);
- dwArgCount++;
- Ptr += (wcslen(Ptr) + 1);
+ lpService->ThreadParams.W.lpArgVector = NULL;
+ lpService->ThreadParams.W.dwArgCount = 0;
}
- lpArgVector[dwArgCount] = NULL;
-
- (lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
-
- HeapFree(GetProcessHeap(),
- 0,
- lpArgVector);
}
else
{
- LPSTR *lpArgVector;
- LPSTR Ptr;
- LPSTR AnsiString;
- DWORD AnsiLength;
-
- AnsiLength = WideCharToMultiByte(CP_ACP,
- 0,
- lpService->Arguments,
- dwLength,
- NULL,
- 0,
- NULL,
- NULL);
- if (AnsiLength == 0)
- return ERROR_INVALID_PARAMETER; /* ? */
+ (lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
+ lpService->ThreadParams.A.lpArgVector);
- AnsiString = HeapAlloc(GetProcessHeap(),
- 0,
- AnsiLength + 1);
- if (AnsiString == NULL)
- return ERROR_OUTOFMEMORY;
-
- WideCharToMultiByte(CP_ACP,
- 0,
- lpService->Arguments,
- dwLength,
- AnsiString,
- AnsiLength,
- NULL,
- NULL);
-
- AnsiString[AnsiLength] = ANSI_NULL;
-
- lpArgVector = HeapAlloc(GetProcessHeap(),
- 0,
- (dwArgCount + 1) * sizeof(LPSTR));
- if (lpArgVector == NULL)
+ if (lpService->ThreadParams.A.lpArgVector != NULL)
{
HeapFree(GetProcessHeap(),
- 0,
- AnsiString);
- return ERROR_OUTOFMEMORY;
- }
+ 0,
+ lpService->ThreadParams.A.lpArgVector);
- dwArgCount = 0;
- Ptr = AnsiString;
- while (*Ptr)
- {
- lpArgVector[dwArgCount] = Ptr;
-
- dwArgCount++;
- Ptr += (strlen(Ptr) + 1);
+ lpService->ThreadParams.A.lpArgVector = NULL;
+ lpService->ThreadParams.A.dwArgCount = 0;
}
- lpArgVector[dwArgCount] = NULL;
-
- (lpService->Main.lpFuncA)(dwArgCount, lpArgVector);
-
- HeapFree(GetProcessHeap(),
- 0,
- lpArgVector);
- HeapFree(GetProcessHeap(),
- 0,
- AnsiString);
}
return ERROR_SUCCESS;
NTSTATUS Status;
WCHAR NtControlPipeName[MAX_PATH + 1];
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ DWORD dwProcessId;
/* Get the service number and create the named pipe */
RtlZeroMemory(&QueryTable,
return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
}
- /* Share the SERVICE_HANDLE handle with the SCM */
+ /* Pass the ProcessId to the SCM */
+ dwProcessId = GetCurrentProcessId();
WriteFile(*hPipe,
- (DWORD *)&lpActiveServices->hService,
- sizeof(CLIENT_HANDLE),
+ &dwProcessId,
+ sizeof(DWORD),
&dwBytesWritten,
NULL);
- TRACE("Sent SERVICE_HANDLE %lu\n", lpActiveServices->hService);
+ TRACE("Sent Process ID %lu\n", dwProcessId);
return ERROR_SUCCESS;
}
static DWORD
-ScStartService(PSCM_CONTROL_PACKET ControlPacket)
+ScStartService(PACTIVE_SERVICE lpService,
+ PSCM_CONTROL_PACKET ControlPacket)
{
- PACTIVE_SERVICE lpService;
HANDLE ThreadHandle;
DWORD ThreadId;
+ LPWSTR *lpArgW;
+ DWORD i;
TRACE("ScStartService() called\n");
- TRACE("client handle: %lu\n", ControlPacket->hClient);
TRACE("Size: %lu\n", ControlPacket->dwSize);
- TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
+ TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+
+ /* Set the service status handle */
+ lpService->hServiceStatus = ControlPacket->hServiceStatus;
- lpService = (PACTIVE_SERVICE)(ULONG_PTR)ControlPacket->hClient;
- if (lpService == NULL)
+ if (lpService->bUnicode == TRUE)
{
- TRACE("Service not found\n");
- return ERROR_SERVICE_DOES_NOT_EXIST;
+ lpService->ThreadParams.W.dwArgCount = ControlPacket->dwArgumentsCount;
+ lpService->ThreadParams.W.lpArgVector = NULL;
+
+ if (ControlPacket->dwArgumentsOffset > 0)
+ {
+ lpService->ThreadParams.W.lpArgVector =
+ HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+ if (lpService->ThreadParams.W.lpArgVector == NULL)
+ return ERROR_OUTOFMEMORY;
+
+ memcpy(lpService->ThreadParams.W.lpArgVector,
+ ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
+ ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+
+ lpArgW = lpService->ThreadParams.W.lpArgVector;
+ for (i = 0; i < lpService->ThreadParams.W.dwArgCount; i++)
+ {
+ *lpArgW = (LPWSTR)((ULONG_PTR)lpArgW + (ULONG_PTR)*lpArgW);
+ lpArgW++;
+ }
+ }
}
+ else
+ {
+ /* FIXME */
+ lpService->ThreadParams.A.dwArgCount = 0;
+ lpService->ThreadParams.A.lpArgVector = NULL;
+
+#if 0
+ LPSTR *lpArgVector;
+ LPSTR Ptr;
+ LPSTR AnsiString;
+ DWORD AnsiLength;
+
+ AnsiLength = WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->Arguments,
+ dwLength,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (AnsiLength == 0)
+ return ERROR_INVALID_PARAMETER; /* ? */
+
+ AnsiString = HeapAlloc(GetProcessHeap(),
+ 0,
+ AnsiLength + 1);
+ if (AnsiString == NULL)
+ return ERROR_OUTOFMEMORY;
- lpService->Arguments = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- (ControlPacket->dwSize + 1) * sizeof(WCHAR));
- if (lpService->Arguments == NULL)
- return ERROR_OUTOFMEMORY;
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ lpService->Arguments,
+ dwLength,
+ AnsiString,
+ AnsiLength,
+ NULL,
+ NULL);
+
+ AnsiString[AnsiLength] = ANSI_NULL;
+
+ lpArgVector = HeapAlloc(GetProcessHeap(),
+ 0,
+ (dwArgCount + 1) * sizeof(LPSTR));
+ if (lpArgVector == NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ AnsiString);
+ return ERROR_OUTOFMEMORY;
+ }
- memcpy(lpService->Arguments,
- ControlPacket->szArguments,
- ControlPacket->dwSize * sizeof(WCHAR));
+ dwArgCount = 0;
+ Ptr = AnsiString;
+ while (*Ptr)
+ {
+ lpArgVector[dwArgCount] = Ptr;
- /* invoke the services entry point and implement the command loop */
+ dwArgCount++;
+ Ptr += (strlen(Ptr) + 1);
+ }
+ lpArgVector[dwArgCount] = NULL;
+
+ (lpService->ThreadParams.A.lpServiceMain)(dwArgCount, lpArgVector);
+
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpArgVector);
+ HeapFree(GetProcessHeap(),
+ 0,
+ AnsiString);
+#endif
+ }
+
+ /* Invoke the services entry point and implement the command loop */
ThreadHandle = CreateThread(NULL,
0,
ScServiceMainStub,
CREATE_SUSPENDED,
&ThreadId);
if (ThreadHandle == NULL)
+ {
+ /* Free the arguments vector */
+ if (lpService->bUnicode)
+ {
+ if (lpService->ThreadParams.W.lpArgVector != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpService->ThreadParams.W.lpArgVector);
+ lpService->ThreadParams.W.lpArgVector = NULL;
+ lpService->ThreadParams.W.dwArgCount = 0;
+ }
+ }
+ else
+ {
+ if (lpService->ThreadParams.A.lpArgVector != NULL)
+ {
+ HeapFree(GetProcessHeap(),
+ 0,
+ lpService->ThreadParams.A.lpArgVector);
+ lpService->ThreadParams.A.lpArgVector = NULL;
+ lpService->ThreadParams.A.dwArgCount = 0;
+ }
+ }
+
return ERROR_SERVICE_NO_THREAD;
+ }
ResumeThread(ThreadHandle);
CloseHandle(ThreadHandle);
static DWORD
-ScControlService(PSCM_CONTROL_PACKET ControlPacket)
+ScControlService(PACTIVE_SERVICE lpService,
+ PSCM_CONTROL_PACKET ControlPacket)
{
- PACTIVE_SERVICE lpService;
-
TRACE("ScControlService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize);
- TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
-
- lpService = (PACTIVE_SERVICE)(ULONG_PTR)ControlPacket->hClient;
- if (lpService == NULL)
- {
- TRACE("Service not found\n");
- return ERROR_SERVICE_DOES_NOT_EXIST;
- }
+ TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
if (lpService->HandlerFunction)
{
(lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
}
- if (ControlPacket->dwControl == SERVICE_CONTROL_STOP)
- {
- HeapFree(GetProcessHeap(),
- 0,
- lpService->Arguments);
- }
-
TRACE("ScControlService() done\n");
return ERROR_SUCCESS;
DWORD Count;
BOOL bResult;
DWORD dwRunningServices = 0;
+ LPWSTR lpServiceName;
+ PACTIVE_SERVICE lpService;
+ SCM_REPLY_PACKET ReplyPacket;
+ DWORD dwError;
TRACE("ScDispatcherLoop() called\n");
return FALSE;
}
- /* Execute command */
- switch (ControlPacket->dwControl)
+ lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
+ TRACE("Service: %S\n", lpServiceName);
+
+ lpService = ScLookupServiceByServiceName(lpServiceName);
+ if (lpService != NULL)
+ {
+ /* Execute command */
+ switch (ControlPacket->dwControl)
+ {
+ case SERVICE_CONTROL_START:
+ TRACE("Start command - recieved SERVICE_CONTROL_START\n");
+ dwError = ScStartService(lpService, ControlPacket);
+ if (dwError == ERROR_SUCCESS)
+ dwRunningServices++;
+ break;
+
+ case SERVICE_CONTROL_STOP:
+ TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
+ dwError = ScControlService(lpService, ControlPacket);
+ if (dwError == ERROR_SUCCESS)
+ dwRunningServices--;
+ break;
+
+ default:
+ TRACE("Command %lu received", ControlPacket->dwControl);
+ dwError = ScControlService(lpService, ControlPacket);
+ break;
+ }
+ }
+ else
{
- case SERVICE_CONTROL_START:
- TRACE("Start command - recieved SERVICE_CONTROL_START\n");
- if (ScStartService(ControlPacket) == ERROR_SUCCESS)
- dwRunningServices++;
- break;
-
- case SERVICE_CONTROL_STOP:
- TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
- if (ScControlService(ControlPacket) == ERROR_SUCCESS)
- dwRunningServices--;
- break;
-
- default:
- TRACE("Command %lu received", ControlPacket->dwControl);
- ScControlService(ControlPacket);
- continue;
+ dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ }
+
+ ReplyPacket.dwError = dwError;
+
+ /* Send the reply packet */
+ bResult = WriteFile(hPipe,
+ &ReplyPacket,
+ sizeof(ReplyPacket),
+ &Count,
+ NULL);
+ if (bResult == FALSE)
+ {
+ ERR("Pipe write failed (Error: %lu)\n", GetLastError());
+ return FALSE;
}
if (dwRunningServices == 0)
Service->HandlerFunction = lpHandlerProc;
Service->HandlerFunctionEx = NULL;
- TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hService);
+ TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
- return (SERVICE_STATUS_HANDLE)Service->hService;
+ return Service->hServiceStatus;
}
Service->HandlerFunctionEx = lpHandlerProc;
Service->HandlerContext = lpContext;
- TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hService);
+ TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
- return (SERVICE_STATUS_HANDLE)Service->hService;
+ return Service->hServiceStatus;
}
TRACE("SetServiceStatus() called\n");
TRACE("hServiceStatus %lu\n", hServiceStatus);
- /* Call to services.exe using RPC */
- dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
- lpServiceStatus);
+ RpcTryExcept
+ {
+ /* Call to services.exe using RPC */
+ dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
+ lpServiceStatus);
+ }
+ RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+ {
+ dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+ }
+ RpcEndExcept;
+
if (dwError != ERROR_SUCCESS)
{
ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
{
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
- lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
- lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
+ lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = FALSE;
}
return FALSE;
}
+ ScCreateStatusBinding();
+
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+ ScDestroyStatusBinding();
+
CloseHandle(hPipe);
/* Free the message buffer */
{
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
- lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
- lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
+ lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = TRUE;
}
return FALSE;
}
+ ScCreateStatusBinding();
+
ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+ ScDestroyStatusBinding();
+
CloseHandle(hPipe);
/* Free the message buffer */