From 8d1e84dfd67adda6c359274c75b32582a864d4a1 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 30 Oct 2006 14:20:45 +0000 Subject: [PATCH] - Implement the rest of Hard Error support. - Kernel support is complete (except temporary LPC hack), and CSRSS properly receives the event and sends it off to win32csr's hard error handler (much like on NT). However, the handler doesn't call NtUserHardErrorControl nor do much of the complex sequence of events that NT does, instead, we only display a hello-world style message box. Anyone up for implementing the rest is welcome. svn path=/trunk/; revision=24665 --- reactos/ntoskrnl/ex/error.c | 40 ++++++++++--- reactos/ntoskrnl/lpc/reply.c | 26 +++++---- reactos/ntoskrnl/lpc/send.c | 2 +- reactos/subsystems/win32/csrss/api/wapi.c | 31 ++++++++-- .../win32/csrss/include/csrplugin.h | 3 + reactos/subsystems/win32/csrss/init.c | 56 ++++++++++++++++++- .../subsystems/win32/csrss/win32csr/dllmain.c | 10 ++++ .../win32/csrss/win32csr/win32csr.def | 2 +- 8 files changed, 143 insertions(+), 27 deletions(-) diff --git a/reactos/ntoskrnl/ex/error.c b/reactos/ntoskrnl/ex/error.c index 23cd803ae5f..33c2131ab1b 100644 --- a/reactos/ntoskrnl/ex/error.c +++ b/reactos/ntoskrnl/ex/error.c @@ -112,11 +112,6 @@ ExpRaiseHardError(IN NTSTATUS ErrorStatus, HANDLE PortHandle; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PAGED_CODE(); - DPRINT1("Hard error, baby!: %lx, %lx, %lx %p\n", - ErrorStatus, - NumberOfParameters, - UnicodeStringParameterMask, - Parameters); /* Check if this error will shutdown the system */ if (ValidResponseOptions == OptionShutdownSystem) @@ -235,15 +230,42 @@ ExpRaiseHardError(IN NTSTATUS ErrorStatus, Parameters, sizeof(ULONG_PTR) * NumberOfParameters); - /* Send the message */ + /* Send the LPC Message */ Status = LpcRequestWaitReplyPort(PortHandle, (PVOID)Message, (PVOID)Message); - DPRINT1("Checkpoint 2: %lx\n", Status); + if (NT_SUCCESS(Status)) + { + /* Check what kind of response we got */ + if ((Message->Response != ResponseReturnToCaller) && + (Message->Response != ResponseNotHandled) && + (Message->Response != ResponseAbort) && + (Message->Response != ResponseCancel) && + (Message->Response != ResponseIgnore) && + (Message->Response != ResponseNo) && + (Message->Response != ResponseOk) && + (Message->Response != ResponseRetry) && + (Message->Response != ResponseYes) && + (Message->Response != ResponseTryAgain) && + (Message->Response != ResponseContinue)) + { + /* Reset to a default one */ + Message->Response = ResponseReturnToCaller; + } + + /* Set the response */ + *Response = Message->Response; + } + } + else + { + /* Set defaults */ + *Response = ResponseReturnToCaller; + Status = STATUS_SUCCESS; } - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + /* Return status */ + return Status; } /*++ diff --git a/reactos/ntoskrnl/lpc/reply.c b/reactos/ntoskrnl/lpc/reply.c index 58159f885d0..5fb58c22fb6 100644 --- a/reactos/ntoskrnl/lpc/reply.c +++ b/reactos/ntoskrnl/lpc/reply.c @@ -429,22 +429,26 @@ LpcRequestWaitReplyPort(IN PVOID Port, { HANDLE PortHandle; NTSTATUS Status; + UNICODE_STRING PortName; + ULONG ConnectInfoLength; - /* This is a SICK hack */ - Status = ObOpenObjectByPointer(Port, - 0, - NULL, - PORT_ALL_ACCESS, - LpcPortObjectType, - KernelMode, - &PortHandle); - DPRINT1("LPC Hack active: %lx %lx\n", Status, PortHandle); + // + // OMG HAXX! + // + RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort"); + ConnectInfoLength = 0; + Status = ZwConnectPort(&PortHandle, + &PortName, + NULL, + NULL, + NULL, + NULL, + NULL, + &ConnectInfoLength); - /* Call the Nt function. Do a ring transition to get Kmode. */ Status = ZwRequestWaitReplyPort(PortHandle, LpcMessageRequest, LpcMessageReply); - DPRINT1("LPC Hack active: %lx %lx\n", Status, PortHandle); /* Close the handle */ ObCloseHandle(PortHandle, KernelMode); diff --git a/reactos/ntoskrnl/lpc/send.c b/reactos/ntoskrnl/lpc/send.c index 53bae7280c8..1dc522f7e66 100644 --- a/reactos/ntoskrnl/lpc/send.c +++ b/reactos/ntoskrnl/lpc/send.c @@ -288,7 +288,7 @@ NtRequestWaitReplyPort (IN HANDLE PortHandle, Status = EiReplyOrRequestPort(Port->OtherPort, LpcRequest, - LPC_REQUEST, + LpcRequest->u2.s2.Type == LPC_ERROR_EVENT ? LPC_ERROR_EVENT : LPC_REQUEST, Port); if (!NT_SUCCESS(Status)) { diff --git a/reactos/subsystems/win32/csrss/api/wapi.c b/reactos/subsystems/win32/csrss/api/wapi.c index 92a726e416a..c647a052f5a 100644 --- a/reactos/subsystems/win32/csrss/api/wapi.c +++ b/reactos/subsystems/win32/csrss/api/wapi.c @@ -104,6 +104,20 @@ CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData, } } +BOOL FASTCALL CallHardError(void); + +static +VOID +NTAPI +CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData, + IN OUT PHARDERROR_MSG Message) +{ + DPRINT1("CSR: received hard error %lx\n", Message->Status); + + /* Call the hard error handler in win32csr */ + CallHardError(); +} + static VOID STDCALL @@ -133,7 +147,7 @@ ClientConnectionThread(HANDLE ServerPort) DPRINT1("NtReplyWaitReceivePort failed\n"); break; } - + /* If the connection was closed, handle that */ if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED) { @@ -161,9 +175,18 @@ ClientConnectionThread(HANDLE ServerPort) continue; } - /* Call the Handler */ - CsrApiCallHandler(ProcessData, Request); - + /* Check if we got a hard error */ + if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT) + { + /* Call the Handler */ + CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request); + } + else + { + /* Call the Handler */ + CsrApiCallHandler(ProcessData, Request); + } + /* Send back the reply */ Reply = Request; } diff --git a/reactos/subsystems/win32/csrss/include/csrplugin.h b/reactos/subsystems/win32/csrss/include/csrplugin.h index 9a435cbc086..a5f250b2c1a 100644 --- a/reactos/subsystems/win32/csrss/include/csrplugin.h +++ b/reactos/subsystems/win32/csrss/include/csrplugin.h @@ -43,9 +43,12 @@ typedef struct tagCSRSS_EXPORTED_FUNCS typedef BOOL (STDCALL *CSRPLUGIN_INIT_COMPLETE_PROC)(void); +typedef BOOL (STDCALL *CSRPLUGIN_HARDERROR_PROC)(void); + typedef BOOL (STDCALL *CSRPLUGIN_INITIALIZE_PROC)(PCSRSS_API_DEFINITION *ApiDefinitions, PCSRSS_OBJECT_DEFINITION *ObjectDefinitions, CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProc, + CSRPLUGIN_HARDERROR_PROC *HardErrorProc, PCSRSS_EXPORTED_FUNCS Exports, HANDLE CsrssApiHeap); diff --git a/reactos/subsystems/win32/csrss/init.c b/reactos/subsystems/win32/csrss/init.c index d1b80bc461f..9ff6bf5e999 100644 --- a/reactos/subsystems/win32/csrss/init.c +++ b/reactos/subsystems/win32/csrss/init.c @@ -28,6 +28,9 @@ extern HANDLE CsrssApiHeap; static unsigned InitCompleteProcCount; static CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProcs = NULL; +static unsigned HardErrorProcCount; +static CSRPLUGIN_HARDERROR_PROC *HardErrorProcs = NULL; + HANDLE hSbApiPort = (HANDLE) 0; HANDLE hBootstrapOk = (HANDLE) 0; @@ -66,6 +69,34 @@ CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc) return STATUS_SUCCESS; } +static NTSTATUS FASTCALL +CsrpAddHardErrorProc(CSRPLUGIN_HARDERROR_PROC Proc) +{ + CSRPLUGIN_HARDERROR_PROC *NewProcs; + + DPRINT("CSR: %s called\n", __FUNCTION__); + + NewProcs = RtlAllocateHeap(CsrssApiHeap, 0, + (HardErrorProcCount + 1) + * sizeof(CSRPLUGIN_HARDERROR_PROC)); + if (NULL == NewProcs) + { + return STATUS_NO_MEMORY; + } + if (0 != HardErrorProcCount) + { + RtlCopyMemory(NewProcs, HardErrorProcs, + HardErrorProcCount * sizeof(CSRPLUGIN_HARDERROR_PROC)); + RtlFreeHeap(CsrssApiHeap, 0, HardErrorProcs); + } + + NewProcs[HardErrorProcCount] = Proc; + HardErrorProcs = NewProcs; + HardErrorProcCount++; + + return STATUS_SUCCESS; +} + /********************************************************************** * CallInitComplete/0 */ @@ -90,6 +121,27 @@ CallInitComplete(void) return Ok; } +BOOL +FASTCALL +CallHardError(void) +{ + BOOL Ok; + unsigned i; + + DPRINT("CSR: %s called\n", __FUNCTION__); + + Ok = TRUE; + if (0 != HardErrorProcCount) + { + for (i = 0; i < HardErrorProcCount && Ok; i++) + { + Ok = (*(HardErrorProcs[i]))(); + } + } + + return Ok; +} + ULONG InitializeVideoAddressSpace(VOID); @@ -182,6 +234,7 @@ CsrpInitWin32Csr (int argc, char ** argv, char ** envp) PCSRSS_API_DEFINITION ApiDefinitions; PCSRSS_OBJECT_DEFINITION ObjectDefinitions; CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc; + CSRPLUGIN_HARDERROR_PROC HardErrorProc; DPRINT("CSR: %s called\n", __FUNCTION__); @@ -202,7 +255,7 @@ CsrpInitWin32Csr (int argc, char ** argv, char ** envp) Exports.CsrReleaseObjectProc = CsrReleaseObject; Exports.CsrEnumProcessesProc = CsrEnumProcesses; if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc, - &Exports, CsrssApiHeap)) + &HardErrorProc, &Exports, CsrssApiHeap)) { return STATUS_UNSUCCESSFUL; } @@ -221,6 +274,7 @@ CsrpInitWin32Csr (int argc, char ** argv, char ** envp) { Status = CsrpAddInitCompleteProc(InitCompleteProc); } + if (HardErrorProc) Status = CsrpAddHardErrorProc(HardErrorProc); return Status; } diff --git a/reactos/subsystems/win32/csrss/win32csr/dllmain.c b/reactos/subsystems/win32/csrss/win32csr/dllmain.c index 683ec5172fc..31272065ca6 100644 --- a/reactos/subsystems/win32/csrss/win32csr/dllmain.c +++ b/reactos/subsystems/win32/csrss/win32csr/dllmain.c @@ -163,10 +163,19 @@ Win32CsrInitComplete(void) return TRUE; } +static BOOL STDCALL +Win32CsrHardError(void) +{ + MessageBox(0, "Hard Error", "TODO", 0); + return TRUE; +} + + BOOL STDCALL Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions, PCSRSS_OBJECT_DEFINITION *ObjectDefinitions, CSRPLUGIN_INIT_COMPLETE_PROC *InitComplete, + CSRPLUGIN_HARDERROR_PROC *HardError, PCSRSS_EXPORTED_FUNCS Exports, HANDLE CsrssApiHeap) { @@ -179,6 +188,7 @@ Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions, *ApiDefinitions = Win32CsrApiDefinitions; *ObjectDefinitions = Win32CsrObjectDefinitions; *InitComplete = Win32CsrInitComplete; + *HardError = Win32CsrHardError; return TRUE; } diff --git a/reactos/subsystems/win32/csrss/win32csr/win32csr.def b/reactos/subsystems/win32/csrss/win32csr/win32csr.def index a4ebf9faf26..9fa863db822 100644 --- a/reactos/subsystems/win32/csrss/win32csr/win32csr.def +++ b/reactos/subsystems/win32/csrss/win32csr/win32csr.def @@ -5,4 +5,4 @@ LIBRARY win32csr.dll EXPORTS -Win32CsrInitialization@20 +Win32CsrInitialization@24