* COPYRIGHT: Copyright 1999 Emanuele Aliberti
* Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
* Gregor Brunmar <gregor.brunmar@home.se>
- *
*/
/* INCLUDES ******************************************************************/
#include <advapi32.h>
+#include <pseh/pseh2.h>
+
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
DWORD dwArgCount;
LPSTR *lpArgVector;
+ DWORD dwServiceTag;
} SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
DWORD dwArgCount;
LPWSTR *lpArgVector;
+ DWORD dwServiceTag;
} SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
UNICODE_STRING ServiceName;
union
{
- SERVICE_THREAD_PARAMSA A;
- SERVICE_THREAD_PARAMSW W;
- } ThreadParams;
+ LPSERVICE_MAIN_FUNCTIONA A;
+ LPSERVICE_MAIN_FUNCTIONW W;
+ } ServiceMain;
LPHANDLER_FUNCTION HandlerFunction;
LPHANDLER_FUNCTION_EX HandlerFunctionEx;
LPVOID HandlerContext;
BOOL bUnicode;
BOOL bOwnProcess;
+ DWORD dwServiceTag;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;
static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;
static handle_t hStatusBinding = NULL;
+static BOOL bSecurityServiceProcess = FALSE;
/* FUNCTIONS *****************************************************************/
LPWSTR pszStringBinding;
RPC_STATUS status;
- TRACE("ScCreateStatusBinding() called\n");
+ TRACE("ScCreateStatusBinding()\n");
status = RpcStringBindingComposeW(NULL,
L"ncacn_np",
{
RPC_STATUS status;
- TRACE("ScDestroyStatusBinding() called\n");
+ TRACE("ScDestroyStatusBinding()\n");
if (hStatusBinding == NULL)
return RPC_S_OK;
{
DWORD i;
- TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
+ TRACE("ScLookupServiceByServiceName(%S)\n",
+ lpServiceName);
if (lpActiveServices[0].bOwnProcess)
return &lpActiveServices[0];
}
TRACE("No service found!\n");
-
- SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
-
return NULL;
}
static DWORD WINAPI
-ScServiceMainStub(LPVOID Context)
+ScServiceMainStubA(LPVOID Context)
{
- PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
+ PTEB Teb;
+ PSERVICE_THREAD_PARAMSA ThreadParams = Context;
+
+ TRACE("ScServiceMainStubA(%p)\n", Context);
- TRACE("ScServiceMainStub() called\n");
+ /* Set service tag */
+ Teb = NtCurrentTeb();
+ Teb->SubProcessTag = UlongToPtr(ThreadParams->dwServiceTag);
/* Call the main service routine and free the arguments vector */
- if (lpService->bUnicode)
- {
- (lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
- lpService->ThreadParams.W.lpArgVector);
+ (ThreadParams->lpServiceMain)(ThreadParams->dwArgCount,
+ ThreadParams->lpArgVector);
- if (lpService->ThreadParams.W.lpArgVector != NULL)
- {
- HeapFree(GetProcessHeap(),
- 0,
- lpService->ThreadParams.W.lpArgVector);
+ /* Reset service tag */
+ Teb->SubProcessTag = 0;
- lpService->ThreadParams.W.lpArgVector = NULL;
- lpService->ThreadParams.W.dwArgCount = 0;
- }
- }
- else
+ if (ThreadParams->lpArgVector != NULL)
{
- (lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
- lpService->ThreadParams.A.lpArgVector);
+ HeapFree(GetProcessHeap(), 0, ThreadParams->lpArgVector);
+ }
+ HeapFree(GetProcessHeap(), 0, ThreadParams);
- if (lpService->ThreadParams.A.lpArgVector != NULL)
- {
- HeapFree(GetProcessHeap(),
- 0,
- lpService->ThreadParams.A.lpArgVector);
+ return ERROR_SUCCESS;
+}
- lpService->ThreadParams.A.lpArgVector = NULL;
- lpService->ThreadParams.A.dwArgCount = 0;
- }
+
+static DWORD WINAPI
+ScServiceMainStubW(LPVOID Context)
+{
+ PTEB Teb;
+ PSERVICE_THREAD_PARAMSW ThreadParams = Context;
+
+ TRACE("ScServiceMainStubW(%p)\n", Context);
+
+ /* Set service tag */
+ Teb = NtCurrentTeb();
+ Teb->SubProcessTag = UlongToPtr(ThreadParams->dwServiceTag);
+
+ /* Call the main service routine and free the arguments vector */
+ (ThreadParams->lpServiceMain)(ThreadParams->dwArgCount,
+ ThreadParams->lpArgVector);
+
+ /* Reset service tag */
+ Teb->SubProcessTag = 0;
+
+ if (ThreadParams->lpArgVector != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, ThreadParams->lpArgVector);
}
+ HeapFree(GetProcessHeap(), 0, ThreadParams);
return ERROR_SUCCESS;
}
{
DWORD dwBytesWritten;
DWORD dwState;
- DWORD dwServiceCurrent = 0;
+ DWORD dwServiceCurrent = 1;
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,
- sizeof(QueryTable));
-
- QueryTable[0].Name = L"";
- QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
- QueryTable[0].EntryContext = &dwServiceCurrent;
-
- Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
- L"ServiceCurrent",
- QueryTable,
- NULL,
- NULL);
+ TRACE("ScConnectControlPipe(%p)\n",
+ hPipe);
- if (!NT_SUCCESS(Status))
+ /* Get the service number and create the named pipe */
+ if (bSecurityServiceProcess == FALSE)
+ {
+ RtlZeroMemory(&QueryTable, sizeof(QueryTable));
+
+ QueryTable[0].Name = L"";
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].EntryContext = &dwServiceCurrent;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+ L"ServiceCurrent",
+ QueryTable,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+ return RtlNtStatusToDosError(Status);
+ }
+ }
+ else
{
- ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
- return RtlNtStatusToDosError(Status);
+ dwServiceCurrent = 0;
}
swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
+ TRACE("PipeName: %S\n", NtControlPipeName);
- if (!WaitNamedPipeW(NtControlPipeName, 15000))
+ if (!WaitNamedPipeW(NtControlPipeName, 30000))
{
ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
dwProcessId = GetCurrentProcessId();
WriteFile(*hPipe,
&dwProcessId,
- sizeof(DWORD),
+ sizeof(dwProcessId),
&dwBytesWritten,
NULL);
}
+/*
+ * Ansi/Unicode argument layout of the vector passed to a service at startup,
+ * depending on the different versions of Windows considered:
+ *
+ * - XP/2003:
+ * [argv array of pointers][parameter 1][parameter 2]...[service name]
+ *
+ * - Vista:
+ * [argv array of pointers][align to 8 bytes]
+ * [parameter 1][parameter 2]...[service name]
+ *
+ * - Win7/8:
+ * [argv array of pointers][service name]
+ * [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
+ *
+ * Space for parameters and service name is always enough to store
+ * both the Ansi and the Unicode versions including NULL terminator.
+ */
+
static DWORD
ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
LPDWORD lpArgCount,
LPWSTR **lpArgVector)
{
- LPWSTR *lpVector;
- LPWSTR *lpArg;
- LPWSTR pszServiceName;
+ PWSTR *lpVector;
+ PWSTR pszServiceName;
DWORD cbServiceName;
+ DWORD cbArguments;
DWORD cbTotal;
DWORD i;
if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
return ERROR_INVALID_PARAMETER;
- *lpArgCount = 0;
+ *lpArgCount = 0;
*lpArgVector = NULL;
- pszServiceName = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
- cbServiceName = lstrlenW(pszServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+ /* Retrieve and count the start command line (NULL-terminated) */
+ pszServiceName = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
+ cbServiceName = lstrlenW(pszServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
- cbTotal = cbServiceName + sizeof(LPWSTR);
+ /*
+ * The total size of the argument vector is equal to the entry for
+ * the service name, plus the size of the original argument vector.
+ */
+ cbTotal = sizeof(PWSTR) + cbServiceName;
if (ControlPacket->dwArgumentsCount > 0)
- cbTotal += ControlPacket->dwSize - ControlPacket->dwArgumentsOffset;
+ cbArguments = ControlPacket->dwSize - ControlPacket->dwArgumentsOffset;
+ else
+ cbArguments = 0;
+ cbTotal += cbArguments;
- lpVector = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- cbTotal);
+ /* Allocate the new argument vector */
+ lpVector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbTotal);
if (lpVector == NULL)
- return ERROR_OUTOFMEMORY;
-
- lpArg = lpVector;
- *lpArg = (LPWSTR)(lpArg + 1);
- lpArg++;
+ return ERROR_NOT_ENOUGH_MEMORY;
- memcpy(lpArg, pszServiceName, cbServiceName);
- lpArg = (LPWSTR*)((ULONG_PTR)lpArg + cbServiceName);
+ /*
+ * The first argument is reserved for the service name, which
+ * will be appended to the end of the argument string list.
+ */
+ /* Copy the remaining arguments */
if (ControlPacket->dwArgumentsCount > 0)
{
- memcpy(lpArg,
- ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
- ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+ memcpy(&lpVector[1],
+ (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwArgumentsOffset),
+ cbArguments);
for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
{
- *lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
- lpArg++;
+ lpVector[i + 1] = (PWSTR)((ULONG_PTR)&lpVector[1] + (ULONG_PTR)lpVector[i + 1]);
+ TRACE("Unicode lpVector[%lu] = '%ls'\n", i + 1, lpVector[i + 1]);
}
}
- *lpArgCount = ControlPacket->dwArgumentsCount + 1;
+ /* Now copy the service name */
+ lpVector[0] = (PWSTR)((ULONG_PTR)&lpVector[1] + cbArguments);
+ memcpy(lpVector[0], pszServiceName, cbServiceName);
+ TRACE("Unicode lpVector[%lu] = '%ls'\n", 0, lpVector[0]);
+
+ *lpArgCount = ControlPacket->dwArgumentsCount + 1;
*lpArgVector = lpVector;
return ERROR_SUCCESS;
LPDWORD lpArgCount,
LPSTR **lpArgVector)
{
- LPSTR *lpVector;
- LPSTR *lpPtr;
- LPWSTR lpUnicodeString;
- LPWSTR pszServiceName;
- LPSTR lpAnsiString;
- DWORD cbServiceName;
- DWORD dwVectorSize;
- DWORD dwUnicodeSize;
- DWORD dwAnsiSize = 0;
- DWORD dwAnsiNameSize = 0;
- DWORD i;
+ DWORD dwError;
+ NTSTATUS Status;
+ DWORD ArgCount, i;
+ PWSTR *lpVectorW;
+ PSTR *lpVectorA;
+ UNICODE_STRING UnicodeString;
+ ANSI_STRING AnsiString;
if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
return ERROR_INVALID_PARAMETER;
- *lpArgCount = 0;
+ *lpArgCount = 0;
*lpArgVector = NULL;
- pszServiceName = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
- cbServiceName = lstrlenW(pszServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
-
- dwAnsiNameSize = WideCharToMultiByte(CP_ACP,
- 0,
- pszServiceName,
- cbServiceName,
- NULL,
- 0,
- NULL,
- NULL);
-
- dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);
- if (ControlPacket->dwArgumentsCount > 0)
- {
- lpUnicodeString = (LPWSTR)((PBYTE)ControlPacket +
- ControlPacket->dwArgumentsOffset +
- dwVectorSize);
- dwUnicodeSize = (ControlPacket->dwSize -
- ControlPacket->dwArgumentsOffset -
- dwVectorSize) / sizeof(WCHAR);
-
- dwAnsiSize = WideCharToMultiByte(CP_ACP,
- 0,
- lpUnicodeString,
- dwUnicodeSize,
- NULL,
- 0,
- NULL,
- NULL);
- }
-
- dwVectorSize += sizeof(LPWSTR);
-
- lpVector = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- dwVectorSize + dwAnsiNameSize + dwAnsiSize);
- if (lpVector == NULL)
- return ERROR_OUTOFMEMORY;
-
- lpPtr = (LPSTR*)lpVector;
- lpAnsiString = (LPSTR)((ULONG_PTR)lpVector + dwVectorSize);
-
- WideCharToMultiByte(CP_ACP,
- 0,
- pszServiceName,
- cbServiceName,
- lpAnsiString,
- dwAnsiNameSize,
- NULL,
- NULL);
+ /* Build the UNICODE arguments vector */
+ dwError = ScBuildUnicodeArgsVector(ControlPacket, &ArgCount, &lpVectorW);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
- if (ControlPacket->dwArgumentsCount > 0)
+ /* Convert the vector to ANSI in place */
+ lpVectorA = (PSTR*)lpVectorW;
+ for (i = 0; i < ArgCount; i++)
{
- lpAnsiString = (LPSTR)((ULONG_PTR)lpAnsiString + dwAnsiNameSize);
-
- WideCharToMultiByte(CP_ACP,
- 0,
- lpUnicodeString,
- dwUnicodeSize,
- lpAnsiString,
- dwAnsiSize,
- NULL,
- NULL);
- }
+ RtlInitUnicodeString(&UnicodeString, lpVectorW[i]);
+ RtlInitEmptyAnsiString(&AnsiString, lpVectorA[i], UnicodeString.MaximumLength);
+ Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to convert to ANSI; free the allocated vector and return */
+ dwError = RtlNtStatusToDosError(Status);
+ HeapFree(GetProcessHeap(), 0, lpVectorW);
+ return dwError;
+ }
- lpAnsiString = (LPSTR)((ULONG_PTR)lpVector + dwVectorSize);
- for (i = 0; i < ControlPacket->dwArgumentsCount + 1; i++)
- {
- *lpPtr = lpAnsiString;
+ /* NULL-terminate the string */
+ AnsiString.Buffer[AnsiString.Length / sizeof(CHAR)] = ANSI_NULL;
- lpPtr++;
- lpAnsiString += (strlen(lpAnsiString) + 1);
+ TRACE("Ansi lpVector[%lu] = '%s'\n", i, lpVectorA[i]);
}
- *lpArgCount = ControlPacket->dwArgumentsCount + 1;
- *lpArgVector = lpVector;
+ *lpArgCount = ArgCount;
+ *lpArgVector = lpVectorA;
return ERROR_SUCCESS;
}
HANDLE ThreadHandle;
DWORD ThreadId;
DWORD dwError;
+ PSERVICE_THREAD_PARAMSA ThreadParamsA;
+ PSERVICE_THREAD_PARAMSW ThreadParamsW;
+
+ TRACE("ScStartService(%p %p)\n",
+ lpService, ControlPacket);
if (lpService == NULL || ControlPacket == NULL)
return ERROR_INVALID_PARAMETER;
- TRACE("ScStartService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize);
- TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+ TRACE("Service: %S\n", (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset));
/* Set the service status handle */
lpService->hServiceStatus = ControlPacket->hServiceStatus;
+ /* Set the service tag */
+ lpService->dwServiceTag = ControlPacket->dwServiceTag;
/* Build the arguments vector */
- if (lpService->bUnicode == TRUE)
+ if (lpService->bUnicode != FALSE)
{
+ ThreadParamsW = HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW));
+ if (ThreadParamsW == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
dwError = ScBuildUnicodeArgsVector(ControlPacket,
- &lpService->ThreadParams.W.dwArgCount,
- &lpService->ThreadParams.W.lpArgVector);
+ &ThreadParamsW->dwArgCount,
+ &ThreadParamsW->lpArgVector);
+ if (dwError != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, ThreadParamsW);
+ return dwError;
+ }
+ ThreadParamsW->lpServiceMain = lpService->ServiceMain.W;
+ ThreadParamsW->dwServiceTag = ControlPacket->dwServiceTag;
+ ThreadHandle = CreateThread(NULL,
+ 0,
+ ScServiceMainStubW,
+ ThreadParamsW,
+ 0,
+ &ThreadId);
+ if (ThreadHandle == NULL)
+ {
+ if (ThreadParamsW->lpArgVector != NULL)
+ {
+ HeapFree(GetProcessHeap(), 0, ThreadParamsW->lpArgVector);
+ }
+ HeapFree(GetProcessHeap(), 0, ThreadParamsW);
+
+ return ERROR_SERVICE_NO_THREAD;
+ }
+
+ CloseHandle(ThreadHandle);
}
else
{
+ ThreadParamsA = HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA));
+ if (ThreadParamsA == NULL)
+ return ERROR_NOT_ENOUGH_MEMORY;
dwError = ScBuildAnsiArgsVector(ControlPacket,
- &lpService->ThreadParams.A.dwArgCount,
- &lpService->ThreadParams.A.lpArgVector);
- }
-
- if (dwError != ERROR_SUCCESS)
- return dwError;
-
- /* Invoke the services entry point and implement the command loop */
- ThreadHandle = CreateThread(NULL,
- 0,
- ScServiceMainStub,
- lpService,
- CREATE_SUSPENDED,
- &ThreadId);
- if (ThreadHandle == NULL)
- {
- /* Free the arguments vector */
- if (lpService->bUnicode)
+ &ThreadParamsA->dwArgCount,
+ &ThreadParamsA->lpArgVector);
+ if (dwError != ERROR_SUCCESS)
{
- if (lpService->ThreadParams.W.lpArgVector != NULL)
- {
- HeapFree(GetProcessHeap(),
- 0,
- lpService->ThreadParams.W.lpArgVector);
- lpService->ThreadParams.W.lpArgVector = NULL;
- lpService->ThreadParams.W.dwArgCount = 0;
- }
+ HeapFree(GetProcessHeap(), 0, ThreadParamsA);
+ return dwError;
}
- else
+ ThreadParamsA->lpServiceMain = lpService->ServiceMain.A;
+ ThreadParamsA->dwServiceTag = ControlPacket->dwServiceTag;
+ ThreadHandle = CreateThread(NULL,
+ 0,
+ ScServiceMainStubA,
+ ThreadParamsA,
+ 0,
+ &ThreadId);
+ if (ThreadHandle == NULL)
{
- if (lpService->ThreadParams.A.lpArgVector != NULL)
+ if (ThreadParamsA->lpArgVector != NULL)
{
- HeapFree(GetProcessHeap(),
- 0,
- lpService->ThreadParams.A.lpArgVector);
- lpService->ThreadParams.A.lpArgVector = NULL;
- lpService->ThreadParams.A.dwArgCount = 0;
+ HeapFree(GetProcessHeap(), 0, ThreadParamsA->lpArgVector);
}
+ HeapFree(GetProcessHeap(), 0, ThreadParamsA);
+
+ return ERROR_SERVICE_NO_THREAD;
}
- return ERROR_SERVICE_NO_THREAD;
+ CloseHandle(ThreadHandle);
}
- ResumeThread(ThreadHandle);
- CloseHandle(ThreadHandle);
-
return ERROR_SUCCESS;
}
ScControlService(PACTIVE_SERVICE lpService,
PSCM_CONTROL_PACKET ControlPacket)
{
+ DWORD dwError = ERROR_SUCCESS;
+
+ TRACE("ScControlService(%p %p)\n",
+ lpService, ControlPacket);
+
if (lpService == NULL || ControlPacket == NULL)
return ERROR_INVALID_PARAMETER;
- TRACE("ScControlService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize);
- TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+ TRACE("Service: %S\n", (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset));
+
+ /* Set service tag */
+ NtCurrentTeb()->SubProcessTag = UlongToPtr(lpService->dwServiceTag);
if (lpService->HandlerFunction)
{
- (lpService->HandlerFunction)(ControlPacket->dwControl);
+ _SEH2_TRY
+ {
+ (lpService->HandlerFunction)(ControlPacket->dwControl);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ dwError = ERROR_EXCEPTION_IN_SERVICE;
+ }
+ _SEH2_END;
}
else if (lpService->HandlerFunctionEx)
{
- /* FIXME: send correct params */
- (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
+ _SEH2_TRY
+ {
+ /* FIXME: Send correct 2nd and 3rd parameters */
+ (lpService->HandlerFunctionEx)(ControlPacket->dwControl,
+ 0, NULL,
+ lpService->HandlerContext);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ dwError = ERROR_EXCEPTION_IN_SERVICE;
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ dwError = ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
}
- TRACE("ScControlService() done\n");
+ /* Reset service tag */
+ NtCurrentTeb()->SubProcessTag = 0;
- return ERROR_SUCCESS;
+ TRACE("ScControlService() done (Error %lu)\n", dwError);
+
+ return dwError;
}
{
DWORD Count;
BOOL bResult;
- DWORD dwRunningServices = 0;
+ BOOL bRunning = TRUE;
LPWSTR lpServiceName;
PACTIVE_SERVICE lpService;
SCM_REPLY_PACKET ReplyPacket;
DWORD dwError;
- TRACE("ScDispatcherLoop() called\n");
+ TRACE("ScServiceDispatcher(%p %p %lu)\n",
+ hPipe, ControlPacket, dwBufferSize);
if (ControlPacket == NULL || dwBufferSize < sizeof(SCM_CONTROL_PACKET))
return FALSE;
- while (TRUE)
+ while (bRunning)
{
/* Read command from the control pipe */
bResult = ReadFile(hPipe,
lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
TRACE("Service: %S\n", lpServiceName);
- if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
- lpActiveServices[0].bOwnProcess = TRUE;
-
- lpService = ScLookupServiceByServiceName(lpServiceName);
- if (lpService != NULL)
+ if ((ControlPacket->dwControl == SERVICE_CONTROL_STOP) &&
+ (lpServiceName[0] == UNICODE_NULL))
{
- /* Execute command */
- switch (ControlPacket->dwControl)
- {
- case SERVICE_CONTROL_START_SHARE:
- case SERVICE_CONTROL_START_OWN:
- TRACE("Start command - received SERVICE_CONTROL_START\n");
- dwError = ScStartService(lpService, ControlPacket);
- if (dwError == ERROR_SUCCESS)
- dwRunningServices++;
- break;
-
- case SERVICE_CONTROL_STOP:
- TRACE("Stop command - received 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;
- }
+ TRACE("Stop dispatcher thread\n");
+ bRunning = FALSE;
+ dwError = ERROR_SUCCESS;
}
else
{
- dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+ if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
+ lpActiveServices[0].bOwnProcess = TRUE;
+
+ lpService = ScLookupServiceByServiceName(lpServiceName);
+ if (lpService != NULL)
+ {
+ /* Execute command */
+ switch (ControlPacket->dwControl)
+ {
+ case SERVICE_CONTROL_START_SHARE:
+ case SERVICE_CONTROL_START_OWN:
+ TRACE("Start command - received SERVICE_CONTROL_START\n");
+ dwError = ScStartService(lpService, ControlPacket);
+ break;
+
+ case SERVICE_CONTROL_STOP:
+ TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
+ dwError = ScControlService(lpService, ControlPacket);
+ break;
+
+ default:
+ TRACE("Command %lu received\n", ControlPacket->dwControl);
+ dwError = ScControlService(lpService, ControlPacket);
+ break;
+ }
+ }
+ else
+ {
+ dwError = ERROR_SERVICE_NOT_IN_EXE;
+ }
}
ReplyPacket.dwError = dwError;
ERR("Pipe write failed (Error: %lu)\n", GetLastError());
return FALSE;
}
-
- if (dwRunningServices == 0)
- break;
}
return TRUE;
/**********************************************************************
- * RegisterServiceCtrlHandlerA
+ * RegisterServiceCtrlHandlerA
*
* @implemented
*/
{
ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameU;
- SERVICE_STATUS_HANDLE SHandle;
+ SERVICE_STATUS_HANDLE hServiceStatus;
- RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
+ TRACE("RegisterServiceCtrlHandlerA(%s %p)\n",
+ debugstr_a(lpServiceName), lpHandlerProc);
+
+ RtlInitAnsiString(&ServiceNameA, lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
{
- SetLastError(ERROR_OUTOFMEMORY);
- return (SERVICE_STATUS_HANDLE)0;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
}
- SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
- lpHandlerProc);
+ hServiceStatus = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
+ lpHandlerProc);
RtlFreeUnicodeString(&ServiceNameU);
- return SHandle;
+ return hServiceStatus;
}
/**********************************************************************
- * RegisterServiceCtrlHandlerW
+ * RegisterServiceCtrlHandlerW
*
* @implemented
*/
{
PACTIVE_SERVICE Service;
- Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
+ TRACE("RegisterServiceCtrlHandlerW(%s %p)\n",
+ debugstr_w(lpServiceName), lpHandlerProc);
+
+ Service = ScLookupServiceByServiceName(lpServiceName);
if (Service == NULL)
{
- return (SERVICE_STATUS_HANDLE)NULL;
+ SetLastError(ERROR_SERVICE_NOT_IN_EXE);
+ return NULL;
+ }
+
+ if (!lpHandlerProc)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
}
Service->HandlerFunction = lpHandlerProc;
Service->HandlerFunctionEx = NULL;
- TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
+ TRACE("RegisterServiceCtrlHandler returning %p\n", Service->hServiceStatus);
return Service->hServiceStatus;
}
/**********************************************************************
- * RegisterServiceCtrlHandlerExA
+ * RegisterServiceCtrlHandlerExA
*
* @implemented
*/
{
ANSI_STRING ServiceNameA;
UNICODE_STRING ServiceNameU;
- SERVICE_STATUS_HANDLE SHandle;
+ SERVICE_STATUS_HANDLE hServiceStatus;
+
+ TRACE("RegisterServiceCtrlHandlerExA(%s %p %p)\n",
+ debugstr_a(lpServiceName), lpHandlerProc, lpContext);
- RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
+ RtlInitAnsiString(&ServiceNameA, lpServiceName);
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
{
- SetLastError(ERROR_OUTOFMEMORY);
- return (SERVICE_STATUS_HANDLE)0;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
}
- SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
- lpHandlerProc,
- lpContext);
+ hServiceStatus = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
+ lpHandlerProc,
+ lpContext);
RtlFreeUnicodeString(&ServiceNameU);
- return SHandle;
+ return hServiceStatus;
}
/**********************************************************************
- * RegisterServiceCtrlHandlerExW
+ * RegisterServiceCtrlHandlerExW
*
* @implemented
*/
{
PACTIVE_SERVICE Service;
+ TRACE("RegisterServiceCtrlHandlerExW(%s %p %p)\n",
+ debugstr_w(lpServiceName), lpHandlerProc, lpContext);
+
Service = ScLookupServiceByServiceName(lpServiceName);
if (Service == NULL)
{
- return (SERVICE_STATUS_HANDLE)NULL;
+ SetLastError(ERROR_SERVICE_NOT_IN_EXE);
+ return NULL;
+ }
+
+ if (!lpHandlerProc)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
}
Service->HandlerFunction = NULL;
Service->HandlerFunctionEx = lpHandlerProc;
Service->HandlerContext = lpContext;
- TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
+ TRACE("RegisterServiceCtrlHandlerEx returning %p\n", Service->hServiceStatus);
return Service->hServiceStatus;
}
/**********************************************************************
- * I_ScSetServiceBitsA
+ * I_ScIsSecurityProcess
+ *
+ * Undocumented
+ *
+ * @implemented
+ */
+VOID
+WINAPI
+I_ScIsSecurityProcess(VOID)
+{
+ TRACE("I_ScIsSecurityProcess()\n");
+ bSecurityServiceProcess = TRUE;
+}
+
+
+/**********************************************************************
+ * I_ScPnPGetServiceName
+ *
+ * Undocumented
+ *
+ * @implemented
+ */
+DWORD
+WINAPI
+I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus,
+ OUT LPWSTR lpServiceName,
+ IN DWORD cchServiceName)
+{
+ DWORD i;
+
+ TRACE("I_ScPnPGetServiceName(%lu %p %lu)\n",
+ hServiceStatus, lpServiceName, cchServiceName);
+
+ for (i = 0; i < dwActiveServiceCount; i++)
+ {
+ if (lpActiveServices[i].hServiceStatus == hServiceStatus)
+ {
+ wcscpy(lpServiceName, lpActiveServices[i].ServiceName.Buffer);
+ return ERROR_SUCCESS;
+ }
+ }
+
+ return ERROR_SERVICE_NOT_IN_EXE;
+}
+
+
+/**********************************************************************
+ * I_ScSetServiceBitsA
*
* Undocumented
*
{
BOOL bResult;
+ TRACE("I_ScSetServiceBitsA(%lu %lx %u %u %s)\n",
+ hServiceStatus, dwServiceBits, bSetBitsOn, bUpdateImmediately,
+ debugstr_a(lpString));
+
RpcTryExcept
{
- /* Call to services.exe using RPC */
bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
dwServiceBits,
bSetBitsOn,
/**********************************************************************
- * I_ScSetServiceBitsW
+ * I_ScSetServiceBitsW
*
* Undocumented
*
{
BOOL bResult;
+ TRACE("I_ScSetServiceBitsW(%lu %lx %u %u %s)\n",
+ hServiceStatus, dwServiceBits, bSetBitsOn, bUpdateImmediately,
+ debugstr_w(lpString));
+
RpcTryExcept
{
- /* Call to services.exe using RPC */
bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
dwServiceBits,
bSetBitsOn,
/**********************************************************************
- * SetServiceBits
+ * SetServiceBits
*
* @implemented
*/
BOOL bSetBitsOn,
BOOL bUpdateImmediately)
{
+ TRACE("SetServiceBits(%lu %lx %u %u)\n",
+ hServiceStatus, dwServiceBits, bSetBitsOn, bUpdateImmediately);
+
return I_ScSetServiceBitsW(hServiceStatus,
dwServiceBits,
bSetBitsOn,
/**********************************************************************
- * SetServiceStatus
+ * SetServiceStatus
*
* @implemented
*/
{
DWORD dwError;
- TRACE("SetServiceStatus() called\n");
- TRACE("hServiceStatus %lu\n", hServiceStatus);
+ TRACE("SetServiceStatus(%lu %p)\n",
+ hServiceStatus, lpServiceStatus);
RpcTryExcept
{
- /* Call to services.exe using RPC */
dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
lpServiceStatus);
}
if (dwError != ERROR_SUCCESS)
{
- ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
+ ERR("RSetServiceStatus() failed (Error %lu)\n", dwError);
SetLastError(dwError);
return FALSE;
}
- TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
+ TRACE("SetServiceStatus() done\n");
return TRUE;
}
/**********************************************************************
- * StartServiceCtrlDispatcherA
+ * StartServiceCtrlDispatcherA
*
* @implemented
*/
DWORD dwBufSize;
BOOL bRet = TRUE;
- TRACE("StartServiceCtrlDispatcherA() called\n");
+ TRACE("StartServiceCtrlDispatcherA(%p)\n",
+ lpServiceStartTable);
i = 0;
while (lpServiceStartTable[i].lpServiceProc != NULL)
}
dwActiveServiceCount = i;
+
+ /* Allocate the service table */
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
if (lpActiveServices == NULL)
{
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
{
RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
- lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
- lpActiveServices[i].hServiceStatus = 0;
+ lpActiveServices[i].ServiceMain.A = lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].hServiceStatus = NULL;
lpActiveServices[i].bUnicode = FALSE;
lpActiveServices[i].bOwnProcess = FALSE;
}
+ /* Connect to the SCM */
dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS)
{
dwBufSize);
if (ControlPacket == NULL)
{
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
bRet = FALSE;
goto done;
}
ScCreateStatusBinding();
+ /* Call the dispatcher loop */
ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
+
ScDestroyStatusBinding();
+ /* Close the connection */
CloseHandle(hPipe);
/* Free the control packet */
lpActiveServices = NULL;
dwActiveServiceCount = 0;
+ if (!bRet)
+ SetLastError(dwError);
+
return bRet;
}
/**********************************************************************
- * StartServiceCtrlDispatcherW
+ * StartServiceCtrlDispatcherW
*
* @implemented
*/
DWORD dwBufSize;
BOOL bRet = TRUE;
- TRACE("StartServiceCtrlDispatcherW() called\n");
+ TRACE("StartServiceCtrlDispatcherW(%p)\n",
+ lpServiceStartTable);
i = 0;
while (lpServiceStartTable[i].lpServiceProc != NULL)
}
dwActiveServiceCount = i;
+
+ /* Allocate the service table */
lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
if (lpActiveServices == NULL)
{
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
{
RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
lpServiceStartTable[i].lpServiceName);
- lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
- lpActiveServices[i].hServiceStatus = 0;
+ lpActiveServices[i].ServiceMain.W = lpServiceStartTable[i].lpServiceProc;
+ lpActiveServices[i].hServiceStatus = NULL;
lpActiveServices[i].bUnicode = TRUE;
lpActiveServices[i].bOwnProcess = FALSE;
}
+ /* Connect to the SCM */
dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS)
{
dwBufSize);
if (ControlPacket == NULL)
{
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
bRet = FALSE;
goto done;
}
ScCreateStatusBinding();
+ /* Call the dispatcher loop */
ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
ScDestroyStatusBinding();
+ /* Close the connection */
CloseHandle(hPipe);
/* Free the control packet */
lpActiveServices = NULL;
dwActiveServiceCount = 0;
+ if (!bRet)
+ SetLastError(dwError);
+
return bRet;
}