[NTOSKRNL] Simplify NtRaiseHardError() by merging the terminating blocks.
[reactos.git] / ntoskrnl / ex / harderr.c
index 82d22f4..e8e233d 100644 (file)
@@ -105,13 +105,14 @@ ExpRaiseHardError(IN NTSTATUS ErrorStatus,
                   IN ULONG ValidResponseOptions,
                   OUT PULONG Response)
 {
+    NTSTATUS Status;
     PEPROCESS Process = PsGetCurrentProcess();
     PETHREAD Thread = PsGetCurrentThread();
     UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH];
     PHARDERROR_MSG Message = (PHARDERROR_MSG)Buffer;
-    NTSTATUS Status;
     HANDLE PortHandle;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+
     PAGED_CODE();
 
     /* Check if this error will shutdown the system */
@@ -182,6 +183,31 @@ ExpRaiseHardError(IN NTSTATUS ErrorStatus,
     /* If hard errors are disabled, do nothing */
     if (Thread->HardErrorsAreDisabled) PortHandle = NULL;
 
+    /*
+     * If this is not the system thread, check whether hard errors are
+     * disabled for this thread on user-mode side, and if so, do nothing.
+     */
+    if (!Thread->SystemThread && (PortHandle != NULL))
+    {
+        /* Check if we have a TEB */
+        PTEB Teb = PsGetCurrentThread()->Tcb.Teb;
+        if (Teb)
+        {
+            _SEH2_TRY
+            {
+                if (Teb->HardErrorMode & RTL_SEM_FAILCRITICALERRORS)
+                {
+                    PortHandle = NULL;
+                }
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                NOTHING;
+            }
+            _SEH2_END;
+        }
+    }
+
     /* Now check if we have a port */
     if (PortHandle == NULL)
     {
@@ -361,14 +387,15 @@ ExRaiseHardError(IN NTSTATUS ErrorStatus,
                  IN ULONG ValidResponseOptions,
                  OUT PULONG Response)
 {
+    NTSTATUS Status;
     SIZE_T Size;
     UNICODE_STRING CapturedParams[MAXIMUM_HARDERROR_PARAMETERS];
     ULONG i;
     PVOID UserData = NULL;
     PHARDERROR_USER_PARAMETERS UserParams;
     PWSTR BufferBase;
-    ULONG SafeResponse;
-    NTSTATUS Status;
+    ULONG SafeResponse = ResponseNotHandled;
+
     PAGED_CODE();
 
     /* Check if we have parameters */
@@ -403,41 +430,57 @@ ExRaiseHardError(IN NTSTATUS ErrorStatus,
                                              &Size,
                                              MEM_COMMIT,
                                              PAGE_READWRITE);
-            if (!NT_SUCCESS(Status)) return Status;
+            if (!NT_SUCCESS(Status))
+            {
+                /* Return failure */
+                *Response = ResponseNotHandled;
+                return Status;
+            }
 
             /* Set the pointers to our data */
             UserParams = UserData;
             BufferBase = UserParams->Buffer;
 
-            /* Loop parameters again */
-            for (i = 0; i < NumberOfParameters; i++)
+            /* Enter SEH block as we are writing to user-mode space */
+            _SEH2_TRY
             {
-                /* Check if we're in the mask */
-                if (UnicodeStringParameterMask & (1 << i))
+                /* Loop parameters again */
+                for (i = 0; i < NumberOfParameters; i++)
                 {
-                    /* Update the base */
-                    UserParams->Parameters[i] = (ULONG_PTR)&UserParams->Strings[i];
+                    /* Check if we are in the mask */
+                    if (UnicodeStringParameterMask & (1 << i))
+                    {
+                        /* Update the base */
+                        UserParams->Parameters[i] = (ULONG_PTR)&UserParams->Strings[i];
 
-                    /* Copy the string buffer */
-                    RtlMoveMemory(BufferBase,
-                                  CapturedParams[i].Buffer,
-                                  CapturedParams[i].MaximumLength);
+                        /* Copy the string buffer */
+                        RtlMoveMemory(BufferBase,
+                                      CapturedParams[i].Buffer,
+                                      CapturedParams[i].MaximumLength);
 
-                    /* Set buffer */
-                    CapturedParams[i].Buffer = BufferBase;
+                        /* Set buffer */
+                        CapturedParams[i].Buffer = BufferBase;
 
-                    /* Copy the string structure */
-                    UserParams->Strings[i] = CapturedParams[i];
+                        /* Copy the string structure */
+                        UserParams->Strings[i] = CapturedParams[i];
 
-                    /* Update the pointer */
-                    BufferBase += CapturedParams[i].MaximumLength;
-                }
-                else
-                {
-                    /* No need to copy any strings */
-                    UserParams->Parameters[i] = Parameters[i];
+                        /* Update the pointer */
+                        BufferBase += CapturedParams[i].MaximumLength;
+                    }
+                    else
+                    {
+                        /* No need to copy any strings */
+                        UserParams->Parameters[i] = Parameters[i];
+                    }
                 }
             }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                /* Return the exception code */
+                Status = _SEH2_GetExceptionCode();
+                DPRINT1("ExRaiseHardError - Exception when writing data to user-mode, Status 0x%08lx\n", Status);
+            }
+            _SEH2_END;
         }
         else
         {
@@ -513,12 +556,14 @@ NtRaiseHardError(IN NTSTATUS ErrorStatus,
 {
     NTSTATUS Status = STATUS_SUCCESS;
     PULONG_PTR SafeParams = NULL;
-    ULONG SafeResponse;
+    ULONG SafeResponse = ResponseNotHandled;
     UNICODE_STRING SafeString;
     ULONG i;
     ULONG ParamSize = 0;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
 
+    PAGED_CODE();
+
     /* Validate parameter count */
     if (NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
     {
@@ -624,37 +669,17 @@ NtRaiseHardError(IN NTSTATUS ErrorStatus,
         _SEH2_END;
 
         /* Call the system function directly, because we probed */
-        ExpRaiseHardError(ErrorStatus,
-                          NumberOfParameters,
-                          UnicodeStringParameterMask,
-                          SafeParams,
-                          ValidResponseOptions,
-                          &SafeResponse);
-    }
-    else
-    {
-        /* Reuse variable */
-        SafeParams = Parameters;
-
-        /*
-         * Call the Executive Function. It will probe and copy pointers to
-         * user-mode
-         */
-        ExRaiseHardError(ErrorStatus,
-                         NumberOfParameters,
-                         UnicodeStringParameterMask,
-                         SafeParams,
-                         ValidResponseOptions,
-                         &SafeResponse);
-    }
-
-    /* Check if we were called in user-mode */
-    if (PreviousMode != KernelMode)
-    {
-        /* That means we have a buffer to free */
+        Status = ExpRaiseHardError(ErrorStatus,
+                                   NumberOfParameters,
+                                   UnicodeStringParameterMask,
+                                   SafeParams,
+                                   ValidResponseOptions,
+                                   &SafeResponse);
+
+        /* Free captured buffer */
         if (SafeParams) ExFreePoolWithTag(SafeParams, TAG_ERR);
 
-        /* Enter SEH Block for return */
+        /* Enter SEH Block to return the response */
         _SEH2_TRY
         {
             /* Return the response */
@@ -669,6 +694,20 @@ NtRaiseHardError(IN NTSTATUS ErrorStatus,
     }
     else
     {
+        /* Reuse variable */
+        SafeParams = Parameters;
+
+        /*
+         * Call the Executive Function. It will probe
+         * and copy pointers to user-mode.
+         */
+        Status = ExRaiseHardError(ErrorStatus,
+                                  NumberOfParameters,
+                                  UnicodeStringParameterMask,
+                                  SafeParams,
+                                  ValidResponseOptions,
+                                  &SafeResponse);
+
         /* Return the response */
         *Response = SafeResponse;
     }
@@ -702,6 +741,8 @@ NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status = STATUS_UNSUCCESSFUL;
 
+    PAGED_CODE();
+
     /* Check if we have the privileges */
     if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
     {