Author: ion Date: Thu Oct 26 08:55:34 2006 New Revision: 24658
URL: http://svn.reactos.org/svn/reactos?rev=24658&view=rev Log: - Make CSRSS register the default hard error port on startup. - Stubplement the System Hard Error handler (it simply bugchecks) - Fully implement ExRaiseHardError when called from user-mode so that the strings and parameters are properly captured into user-mode memory. - Almost completely implement ExpRaiseHardError which is responsible for actually doing the error. However, ROS LPC is screwed up so sending the LPC Message crashes since the port isn't in a listening state or something. - Would appreciate some advice on how to get the LPC message to CSRSS. - Fix Get/SetErrorMode. The Native API uses an inverted value of SEM_FAILCRITICALERRORS, so this must be handled in win32. - Cleanup formatting of RaiseException, and only normalize the paramter count if we're actualy going to use it. - Implement LpcRequestWaitReplyPort as a big hack, but it should work.
Modified: trunk/reactos/dll/win32/kernel32/except/except.c trunk/reactos/include/ndk/lpcfuncs.h trunk/reactos/ntoskrnl/ex/error.c trunk/reactos/ntoskrnl/lpc/reply.c trunk/reactos/ntoskrnl/lpc/send.c trunk/reactos/subsystems/win32/csrss/init.c
Modified: trunk/reactos/dll/win32/kernel32/except/except.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/except/e... ============================================================================== --- trunk/reactos/dll/win32/kernel32/except/except.c (original) +++ trunk/reactos/dll/win32/kernel32/except/except.c Thu Oct 26 08:55:34 2006 @@ -18,65 +18,89 @@ LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter = UnhandledExceptionFilter;
UINT -STDCALL +WINAPI GetErrorMode(VOID) { - NTSTATUS Status; - UINT ErrMode; - - Status = NtQueryInformationProcess(NtCurrentProcess(), + NTSTATUS Status; + UINT ErrMode; + + /* Query the current setting */ + Status = NtQueryInformationProcess(NtCurrentProcess(), + ProcessDefaultHardErrorMode, + (PVOID)&ErrMode, + sizeof(ErrMode), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail if we couldn't query */ + SetLastErrorByStatus(Status); + return 0; + } + + /* Check if NOT failing critical errors was requested */ + if (ErrMode & SEM_FAILCRITICALERRORS) + { + /* Mask it out, since the native API works differently */ + ErrMode &= ~SEM_FAILCRITICALERRORS; + } + else + { + /* OR it if the caller didn't, due to different native semantics */ + ErrMode |= SEM_FAILCRITICALERRORS; + } + + /* Return the mode */ + return ErrMode; +} + +/* + * @implemented + */ +UINT +WINAPI +SetErrorMode(IN UINT uMode) +{ + UINT PrevErrMode, NewMode; + NTSTATUS Status; + + /* Get the previous mode */ + PrevErrMode = GetErrorMode(); + NewMode = uMode; + + /* Check if failing critical errors was requested */ + if (NewMode & SEM_FAILCRITICALERRORS) + { + /* Mask it out, since the native API works differently */ + NewMode &= ~SEM_FAILCRITICALERRORS; + } + else + { + /* OR it if the caller didn't, due to different native semantics */ + NewMode |= SEM_FAILCRITICALERRORS; + } + + /* Set the new mode */ + Status = NtSetInformationProcess(NtCurrentProcess(), ProcessDefaultHardErrorMode, - (PVOID)&ErrMode, - sizeof(ErrMode), - NULL); - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return 0; - } - - return ErrMode; + (PVOID)&NewMode, + sizeof(NewMode)); + if(!NT_SUCCESS(Status)) SetLastErrorByStatus(Status); + + /* Return the previous mode */ + return PrevErrMode; }
/* * @implemented */ -UINT -STDCALL -SetErrorMode(UINT uMode) -{ - UINT PrevErrMode; - NTSTATUS Status; - - PrevErrMode = GetErrorMode(); - - Status = NtSetInformationProcess(NtCurrentProcess(), - ProcessDefaultHardErrorMode, - (PVOID)&uMode, - sizeof(uMode)); - if(!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return 0; - } - - return PrevErrMode; -} - - -/* - * @implemented - */ LPTOP_LEVEL_EXCEPTION_FILTER -STDCALL +WINAPI SetUnhandledExceptionFilter( - LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter - ) + IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) { return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter, lpTopLevelExceptionFilter); } -
/* * Private helper function to lookup the module name from a given address. @@ -268,59 +292,54 @@ return EXCEPTION_EXECUTE_HANDLER; }
- /* * @implemented */ VOID -STDCALL -RaiseException ( - DWORD dwExceptionCode, - DWORD dwExceptionFlags, - DWORD nNumberOfArguments, - CONST ULONG_PTR * lpArguments OPTIONAL - ) -{ - EXCEPTION_RECORD ExceptionRecord; - - /* Do NOT normalize dwExceptionCode: it will be done in - * NTDLL.RtlRaiseException(). - */ - ExceptionRecord.ExceptionCode = dwExceptionCode; - ExceptionRecord.ExceptionRecord = NULL; - ExceptionRecord.ExceptionAddress = (PVOID) RaiseException; - /* - * Normalize dwExceptionFlags. - */ - ExceptionRecord.ExceptionFlags = (dwExceptionFlags & EXCEPTION_NONCONTINUABLE); - /* - * Normalize nNumberOfArguments. - */ - if (EXCEPTION_MAXIMUM_PARAMETERS < nNumberOfArguments) - { - nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; - } - /* - * If the exception has no argument, - * ignore nNumberOfArguments and lpArguments. - */ - if (NULL == lpArguments) - { - ExceptionRecord.NumberParameters = 0; - } - else - { - ExceptionRecord.NumberParameters = nNumberOfArguments; - for ( nNumberOfArguments = 0; - (nNumberOfArguments < ExceptionRecord.NumberParameters); - nNumberOfArguments ++ - ) - { - ExceptionRecord.ExceptionInformation [nNumberOfArguments] - = *lpArguments ++; - } - } - RtlRaiseException (& ExceptionRecord); +WINAPI +RaiseException(IN DWORD dwExceptionCode, + IN DWORD dwExceptionFlags, + IN DWORD nNumberOfArguments, + IN CONST ULONG_PTR *lpArguments OPTIONAL) +{ + EXCEPTION_RECORD ExceptionRecord; + + /* Setup the exception record */ + ExceptionRecord.ExceptionCode = dwExceptionCode; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.ExceptionAddress = (PVOID)RaiseException; + ExceptionRecord.ExceptionFlags = dwExceptionFlags & EXCEPTION_NONCONTINUABLE; + + /* Check if we have arguments */ + if (!lpArguments) + { + /* We don't */ + ExceptionRecord.NumberParameters = 0; + } + else + { + /* We do, normalize the count */ + if (nNumberOfArguments > EXCEPTION_MAXIMUM_PARAMETERS) + { + nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; + } + + /* Set the count of parameters */ + ExceptionRecord.NumberParameters = nNumberOfArguments; + + /* Loop each parameter */ + for (nNumberOfArguments = 0; + (nNumberOfArguments < ExceptionRecord.NumberParameters); + nNumberOfArguments ++) + { + /* Copy the exception information */ + ExceptionRecord.ExceptionInformation[nNumberOfArguments] = + *lpArguments++; + } + } + + /* Raise the exception */ + RtlRaiseException(&ExceptionRecord); }
/* EOF */
Modified: trunk/reactos/include/ndk/lpcfuncs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/lpcfuncs.h?rev=... ============================================================================== --- trunk/reactos/include/ndk/lpcfuncs.h (original) +++ trunk/reactos/include/ndk/lpcfuncs.h Thu Oct 26 08:55:34 2006 @@ -23,6 +23,20 @@ // Dependencies // #include <umtypes.h> + +// +// LPC Exports +// +#ifndef NTOS_MODE_USER +NTKERNELAPI +NTSTATUS +NTAPI +LpcRequestWaitReplyPort( + IN PVOID Port, + IN PPORT_MESSAGE LpcMessageRequest, + OUT PPORT_MESSAGE LpcMessageReply) +; +#endif
// // Native calls
Modified: trunk/reactos/ntoskrnl/ex/error.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/error.c?rev=246... ============================================================================== --- trunk/reactos/ntoskrnl/ex/error.c (original) +++ trunk/reactos/ntoskrnl/ex/error.c Thu Oct 26 08:55:34 2006 @@ -23,6 +23,51 @@ /* FUNCTIONS ****************************************************************/
/*++ +* @name ExpRaiseHardError +* +* For now it's a stub +* +* @param ErrorStatus +* FILLME +* +* @param NumberOfParameters +* FILLME +* +* @param UnicodeStringParameterMask +* FILLME +* +* @param Parameters +* FILLME +* +* @param ValidResponseOptions +* FILLME +* +* @param Response +* FILLME +* +* @return None +* +* @remarks None +* +*--*/ +NTSTATUS +NTAPI +ExpSystemErrorHandler(IN NTSTATUS ErrorStatus, + IN ULONG NumberOfParameters, + IN ULONG UnicodeStringParameterMask, + IN PULONG_PTR Parameters, + IN BOOLEAN Shutdown) +{ + /* FIXME: STUB */ + KeBugCheckEx(FATAL_UNHANDLED_HARD_ERROR, + ErrorStatus, + 0, + 0, + 0); + return STATUS_SUCCESS; +} + +/*++ * @name ExpRaiseHardError * * For now it's a stub @@ -50,7 +95,7 @@ * @remarks None * *--*/ -VOID +NTSTATUS NTAPI ExpRaiseHardError(IN NTSTATUS ErrorStatus, IN ULONG NumberOfParameters, @@ -59,7 +104,146 @@ IN ULONG ValidResponseOptions, OUT PULONG Response) { + 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(); + DPRINT1("Hard error, baby!: %lx, %lx, %lx %p\n", + ErrorStatus, + NumberOfParameters, + UnicodeStringParameterMask, + Parameters); + + /* Check if this error will shutdown the system */ + if (ValidResponseOptions == OptionShutdownSystem) + { + /* Check for privilege */ + if (!SeSinglePrivilegeCheck(SeShutdownPrivilege, PreviousMode)) + { + /* No rights */ + return STATUS_PRIVILEGE_NOT_HELD; + } + + /* Don't handle any new hard errors */ + ExReadyForErrors = FALSE; + } + + /* Check if hard errors are not disabled */ + if (!Thread->HardErrorsAreDisabled) + { + /* Check if we can't do errors anymore, and this is serious */ + if ((!ExReadyForErrors) && (NT_ERROR(ErrorStatus))) + { + /* Use the system handler */ + ExpSystemErrorHandler(ErrorStatus, + NumberOfParameters, + UnicodeStringParameterMask, + Parameters, + (PreviousMode != KernelMode) ? TRUE: FALSE); + } + } + + /* Check if we have an exception port */ + if (Process->ExceptionPort) + { + /* Check if hard errors should be processed */ + if (Process->DefaultHardErrorProcessing & 1) + { + /* Use the port */ + PortHandle = Process->ExceptionPort; + } + else + { + /* It's disabled, check if the error overrides it */ + if (ErrorStatus & 0x10000000) + { + /* Use the port anyway */ + PortHandle = Process->ExceptionPort; + } + else + { + /* No such luck */ + PortHandle = NULL; + } + } + } + else + { + /* Check if hard errors are enabled */ + if (Process->DefaultHardErrorProcessing & 1) + { + /* Use our default system port */ + PortHandle = ExpDefaultErrorPort; + } + else + { + /* It's disabled, check if the error overrides it */ + if (ErrorStatus & 0x10000000) + { + /* Use the port anyway */ + PortHandle = ExpDefaultErrorPort; + } + else + { + /* No such luck */ + PortHandle = NULL; + } + } + } + + /* If hard errors are disabled, do nothing */ + if (Thread->HardErrorsAreDisabled) PortHandle = NULL; + + /* Now check if we have a port */ + if (PortHandle) + { + /* Check if this is the default process */ + if (Process == ExpDefaultErrorPortProcess) + { + /* We can't handle the error, check if this is critical */ + if (NT_ERROR(ErrorStatus)) + { + /* It is, invoke the system handler */ + ExpSystemErrorHandler(ErrorStatus, + NumberOfParameters, + UnicodeStringParameterMask, + Parameters, + (PreviousMode != KernelMode) ? TRUE: FALSE); + + /* If we survived, return to caller */ + *Response = ResponseReturnToCaller; + return STATUS_SUCCESS; + } + } + + /* Setup the LPC Message */ + Message->h.u1.Length = (sizeof(HARDERROR_MSG) << 16) | + (sizeof(HARDERROR_MSG) - sizeof(PORT_MESSAGE)); + Message->h.u2.ZeroInit = LPC_ERROR_EVENT; + Message->Status = ErrorStatus &~ 0x10000000; + Message->ValidResponseOptions = ValidResponseOptions; + Message->UnicodeStringParameterMask = UnicodeStringParameterMask; + Message->NumberOfParameters = NumberOfParameters; + KeQuerySystemTime(&Message->ErrorTime); + + /* Copy the parameters */ + if (Parameters) RtlMoveMemory(&Message->Parameters, + Parameters, + sizeof(ULONG_PTR) * NumberOfParameters); + + /* Send the message */ + Status = LpcRequestWaitReplyPort(PortHandle, + (PVOID)Message, + (PVOID)Message); + DPRINT1("Checkpoint 2: %lx\n", Status); + } + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; }
/*++ @@ -155,7 +339,7 @@ * @remarks None * *--*/ -VOID +NTSTATUS NTAPI ExRaiseHardError(IN NTSTATUS ErrorStatus, IN ULONG NumberOfParameters, @@ -164,15 +348,121 @@ IN ULONG ValidResponseOptions, OUT PULONG Response) { - /* FIXME: Capture to user-mode! */ + ULONG Size; + UNICODE_STRING CapturedParams[MAXIMUM_HARDERROR_PARAMETERS]; + ULONG i; + PULONG_PTR UserData = NULL, ParameterBase; + PUNICODE_STRING StringBase; + PWSTR BufferBase; + ULONG SafeResponse; + NTSTATUS Status; + PAGED_CODE(); + + /* Check if we have parameters */ + if (Parameters) + { + /* Check if we have strings */ + if (UnicodeStringParameterMask) + { + /* Add the maximum possible size */ + Size = (sizeof(ULONG_PTR) + sizeof(UNICODE_STRING)) * + MAXIMUM_HARDERROR_PARAMETERS + sizeof(UNICODE_STRING); + + /* Loop each parameter */ + for (i = 0; i < NumberOfParameters; i++) + { + /* Check if it's part of the mask */ + if (UnicodeStringParameterMask & (1 << i)) + { + /* Copy it */ + RtlMoveMemory(&CapturedParams[i], + &Parameters[i], + sizeof(UNICODE_STRING)); + + /* Increase the size */ + Size += CapturedParams[i].MaximumLength; + } + } + + /* Allocate the user data region */ + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + (PVOID*)&UserData, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) return Status; + + /* Set the pointers to our various data */ + ParameterBase = UserData; + StringBase = (PVOID)((ULONG_PTR)UserData + + sizeof(ULONG_PTR) * + MAXIMUM_HARDERROR_PARAMETERS); + BufferBase = (PVOID)((ULONG_PTR)StringBase + + sizeof(UNICODE_STRING) * + MAXIMUM_HARDERROR_PARAMETERS); + + /* Loop parameters again */ + for (i = 0; i < NumberOfParameters; i++) + { + /* Check if we're in the mask */ + if (UnicodeStringParameterMask & (1 << i)) + { + /* Update the base */ + ParameterBase[i] = (ULONG_PTR)&StringBase[i]; + + /* Copy the string buffer */ + RtlMoveMemory(BufferBase, + CapturedParams[i].Buffer, + CapturedParams[i].MaximumLength); + + /* Set buffer */ + CapturedParams[i].Buffer = BufferBase; + + /* Copy the string structure */ + RtlMoveMemory(&StringBase[i], + &CapturedParams[i], + sizeof(UNICODE_STRING)); + + /* Update the pointer */ + BufferBase += CapturedParams[i].MaximumLength; + } + else + { + /* No need to copy any strings */ + ParameterBase[i] = Parameters[i]; + } + } + } + else + { + /* Just keep the data as is */ + UserData = Parameters; + } + }
/* Now call the worker function */ - ExpRaiseHardError(ErrorStatus, - NumberOfParameters, - UnicodeStringParameterMask, - Parameters, - ValidResponseOptions, - Response); + Status = ExpRaiseHardError(ErrorStatus, + NumberOfParameters, + UnicodeStringParameterMask, + UserData, + ValidResponseOptions, + &SafeResponse); + + /* Check if we had done user-mode allocation */ + if ((UserData) && (UserData != Parameters)) + { + /* We did! Delete it */ + Size = 0; + ZwFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&UserData, + &Size, + MEM_RELEASE); + } + + /* Return status and the response */ + *Response = SafeResponse; + return Status; }
/*++ @@ -223,13 +513,11 @@ ULONG i; ULONG ParamSize; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - DPRINT1("Hard error %x\n", ErrorStatus);
/* Validate parameter count */ if (NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS) { /* Fail */ - DPRINT1("Invalid parameters\n"); return STATUS_INVALID_PARAMETER_2; }
@@ -237,7 +525,6 @@ if ((Parameters) && !(NumberOfParameters)) { /* Fail */ - DPRINT1("Invalid parameters\n"); return STATUS_INVALID_PARAMETER_2; }
@@ -401,7 +688,7 @@ NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Check if we have the Privilege */ - if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) + if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) { DPRINT1("NtSetDefaultHardErrorPort: Caller requires " "the SeTcbPrivilege privilege!\n"); @@ -409,7 +696,7 @@ }
/* Only called once during bootup, make sure we weren't called yet */ - if(!ExReadyForErrors) + if (!ExReadyForErrors) { /* Reference the port */ Status = ObReferenceObjectByHandle(PortHandle, @@ -418,9 +705,7 @@ PreviousMode, (PVOID*)&ExpDefaultErrorPort, NULL); - - /* Check for Success */ - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { /* Save the data */ ExpDefaultErrorPortProcess = PsGetCurrentProcess();
Modified: trunk/reactos/ntoskrnl/lpc/reply.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/reply.c?rev=24... ============================================================================== --- trunk/reactos/ntoskrnl/lpc/reply.c (original) +++ trunk/reactos/ntoskrnl/lpc/reply.c Thu Oct 26 08:55:34 2006 @@ -419,18 +419,36 @@ }
/* - * @unimplemented + * @implemented */ NTSTATUS -STDCALL -LpcRequestWaitReplyPort ( - IN PEPORT Port, - IN PPORT_MESSAGE LpcMessageRequest, - OUT PPORT_MESSAGE LpcMessageReply - ) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; +NTAPI +LpcRequestWaitReplyPort(IN PVOID Port, + IN PPORT_MESSAGE LpcMessageRequest, + OUT PPORT_MESSAGE LpcMessageReply) +{ + HANDLE PortHandle; + NTSTATUS Status; + + /* 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); + + /* 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); + return Status; }
/* EOF */
Modified: trunk/reactos/ntoskrnl/lpc/send.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/send.c?rev=246... ============================================================================== --- trunk/reactos/ntoskrnl/lpc/send.c (original) +++ trunk/reactos/ntoskrnl/lpc/send.c Thu Oct 26 08:55:34 2006 @@ -14,60 +14,6 @@
#define NDEBUG #include <internal/debug.h> - -/********************************************************************** - * NAME - * LpcSendDebugMessagePort/3 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * - * REVISIONS - */ -NTSTATUS STDCALL -LpcSendDebugMessagePort (IN PEPORT Port, - IN PDBGKM_MSG Message, - OUT PDBGKM_MSG Reply) -{ - NTSTATUS Status; - KIRQL oldIrql; - PQUEUEDMESSAGE ReplyMessage; - - Status = EiReplyOrRequestPort(Port, - &Message->h, - LPC_REQUEST, - Port); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject(Port); - return(Status); - } - KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); - - /* - * Wait for a reply - */ - KeWaitForSingleObject(&Port->Semaphore, - UserRequest, - UserMode, - FALSE, - NULL); - - /* - * Dequeue the reply - */ - KeAcquireSpinLock(&Port->Lock, &oldIrql); - ReplyMessage = EiDequeueMessagePort(Port); - KeReleaseSpinLock(&Port->Lock, oldIrql); - memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.u1.s1.TotalLength); - ExFreePool(ReplyMessage); - - return(STATUS_SUCCESS); -} -
/********************************************************************** * NAME
Modified: trunk/reactos/subsystems/win32/csrss/init.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/init... ============================================================================== --- trunk/reactos/subsystems/win32/csrss/init.c (original) +++ trunk/reactos/subsystems/win32/csrss/init.c Thu Oct 26 08:55:34 2006 @@ -555,7 +555,11 @@ return Status; }
- +static NTSTATUS +CsrpCreateHardErrorPort (int argc, char ** argv, char ** envp) +{ + return NtSetDefaultHardErrorPort(hApiPort); +}
typedef NTSTATUS (* CSR_INIT_ROUTINE)(int,char**,char**);
@@ -568,6 +572,7 @@ {TRUE, CsrpRegisterSubsystem, "register with SM"}, {TRUE, CsrpCreateHeap, "create the CSR heap"}, {TRUE, CsrpCreateApiPort, "create the api port \Windows\ApiPort"}, + {TRUE, CsrpCreateHardErrorPort, "create the hard error port"}, {TRUE, CsrpCreateObjectDirectory,"create the object directory \Windows"}, {TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"}, {TRUE, CsrpInitVideo, "initialize video"},