[SERVICES][ADVAPI32] Support the security process aka lsass.exe
[reactos.git] / dll / win32 / advapi32 / service / sctrl.c
index 40970f0..c0cf0f4 100644 (file)
@@ -22,6 +22,7 @@ typedef struct _SERVICE_THREAD_PARAMSA
     LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
     DWORD dwArgCount;
     LPSTR *lpArgVector;
+    DWORD dwServiceTag;
 } SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
 
 
@@ -30,6 +31,7 @@ typedef struct _SERVICE_THREAD_PARAMSW
     LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
     DWORD dwArgCount;
     LPWSTR *lpArgVector;
+    DWORD dwServiceTag;
 } SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
 
 
@@ -47,6 +49,7 @@ typedef struct _ACTIVE_SERVICE
     LPVOID HandlerContext;
     BOOL bUnicode;
     BOOL bOwnProcess;
+    DWORD dwServiceTag;
 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
 
 
@@ -55,6 +58,7 @@ typedef struct _ACTIVE_SERVICE
 static DWORD dwActiveServiceCount = 0;
 static PACTIVE_SERVICE lpActiveServices = NULL;
 static handle_t hStatusBinding = NULL;
+static BOOL bSecurityServiceProcess = FALSE;
 
 
 /* FUNCTIONS *****************************************************************/
@@ -164,14 +168,22 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
 static DWORD WINAPI
 ScServiceMainStubA(LPVOID Context)
 {
+    PTEB Teb;
     PSERVICE_THREAD_PARAMSA ThreadParams = Context;
 
     TRACE("ScServiceMainStubA(%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);
@@ -185,14 +197,22 @@ ScServiceMainStubA(LPVOID Context)
 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);
@@ -208,7 +228,7 @@ ScConnectControlPipe(HANDLE *hPipe)
 {
     DWORD dwBytesWritten;
     DWORD dwState;
-    DWORD dwServiceCurrent = 0;
+    DWORD dwServiceCurrent = 1;
     NTSTATUS Status;
     WCHAR NtControlPipeName[MAX_PATH + 1];
     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
@@ -218,25 +238,32 @@ ScConnectControlPipe(HANDLE *hPipe)
           hPipe);
 
     /* 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);
-    if (!NT_SUCCESS(Status))
+    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, 30000))
     {
@@ -440,6 +467,8 @@ ScStartService(PACTIVE_SERVICE lpService,
 
     /* Set the service status handle */
     lpService->hServiceStatus = ControlPacket->hServiceStatus;
+    /* Set the service tag */
+    lpService->dwServiceTag = ControlPacket->dwServiceTag;
 
     /* Build the arguments vector */
     if (lpService->bUnicode != FALSE)
@@ -456,6 +485,7 @@ ScStartService(PACTIVE_SERVICE lpService,
             return dwError;
         }
         ThreadParamsW->lpServiceMain = lpService->ServiceMain.W;
+        ThreadParamsW->dwServiceTag = ControlPacket->dwServiceTag;
         ThreadHandle = CreateThread(NULL,
                                     0,
                                     ScServiceMainStubW,
@@ -489,6 +519,7 @@ ScStartService(PACTIVE_SERVICE lpService,
             return dwError;
         }
         ThreadParamsA->lpServiceMain = lpService->ServiceMain.A;
+        ThreadParamsA->dwServiceTag = ControlPacket->dwServiceTag;
         ThreadHandle = CreateThread(NULL,
                                     0,
                                     ScServiceMainStubA,
@@ -517,7 +548,7 @@ static DWORD
 ScControlService(PACTIVE_SERVICE lpService,
                  PSCM_CONTROL_PACKET ControlPacket)
 {
-    DWORD dwError;
+    DWORD dwError = ERROR_SUCCESS;
 
     TRACE("ScControlService(%p %p)\n",
           lpService, ControlPacket);
@@ -528,19 +559,44 @@ ScControlService(PACTIVE_SERVICE lpService,
     TRACE("Size: %lu\n", ControlPacket->dwSize);
     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);
-        dwError = ERROR_SUCCESS;
+        _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 2nd and 3rd parameters */
-        dwError = (lpService->HandlerFunctionEx)(ControlPacket->dwControl,
-                                                 0, NULL,
-                                                 lpService->HandlerContext);
+        _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;
     }
 
+    /* Reset service tag */
+    NtCurrentTeb()->SubProcessTag = 0;
+
     TRACE("ScControlService() done (Error %lu)\n", dwError);
 
     return dwError;
@@ -583,9 +639,10 @@ ScServiceDispatcher(HANDLE hPipe,
         lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
         TRACE("Service: %S\n", lpServiceName);
 
-        if (lpServiceName[0] == UNICODE_NULL)
+        if ((ControlPacket->dwControl == SERVICE_CONTROL_STOP) &&
+            (lpServiceName[0] == UNICODE_NULL))
         {
-            ERR("Stop dispatcher thread\n");
+            TRACE("Stop dispatcher thread\n");
             bRunning = FALSE;
             dwError = ERROR_SUCCESS;
         }
@@ -655,7 +712,7 @@ RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
     UNICODE_STRING ServiceNameU;
     SERVICE_STATUS_HANDLE hServiceStatus;
 
-    TRACE("RegisterServiceCtrlHandlerA(%s %p %p)\n",
+    TRACE("RegisterServiceCtrlHandlerA(%s %p)\n",
           debugstr_a(lpServiceName), lpHandlerProc);
 
     RtlInitAnsiString(&ServiceNameA, lpServiceName);
@@ -685,7 +742,7 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
 {
     PACTIVE_SERVICE Service;
 
-    TRACE("RegisterServiceCtrlHandlerW(%s %p %p)\n",
+    TRACE("RegisterServiceCtrlHandlerW(%s %p)\n",
           debugstr_w(lpServiceName), lpHandlerProc);
 
     Service = ScLookupServiceByServiceName(lpServiceName);
@@ -787,13 +844,14 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
  *
  * Undocumented
  *
- * @unimplemented
+ * @implemented
  */
 VOID
 WINAPI
 I_ScIsSecurityProcess(VOID)
 {
-    FIXME("I_ScIsSecurityProcess()\n");
+    TRACE("I_ScIsSecurityProcess()\n");
+    bSecurityServiceProcess = TRUE;
 }