843 lines
24 KiB
C
843 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
harderr.c
|
|
|
|
Abstract:
|
|
|
|
This module implements NT Hard Error APIs
|
|
|
|
Author:
|
|
|
|
Mark Lucovsky (markl) 04-Jul-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "exp.h"
|
|
|
|
extern ULONG KiBugCheckData[5];
|
|
extern ULONG KeBugCheckCount;
|
|
|
|
NTSTATUS
|
|
ExpRaiseHardError(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN ULONG ValidResponseOptions,
|
|
OUT PULONG Response
|
|
);
|
|
|
|
VOID
|
|
ExpSystemErrorHandler(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN BOOLEAN CallShutdown
|
|
);
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE, NtRaiseHardError)
|
|
#pragma alloc_text(PAGE, NtSetDefaultHardErrorPort)
|
|
#pragma alloc_text(PAGE, ExRaiseHardError)
|
|
#pragma alloc_text(PAGE, ExpRaiseHardError)
|
|
#pragma alloc_text(PAGELK, ExpSystemErrorHandler)
|
|
#endif
|
|
|
|
#define HARDERROR_MSG_OVERHEAD (sizeof(HARDERROR_MSG) - sizeof(PORT_MESSAGE))
|
|
#define HARDERROR_API_MSG_LENGTH \
|
|
sizeof(HARDERROR_MSG)<<16 | (HARDERROR_MSG_OVERHEAD)
|
|
|
|
PEPROCESS ExpDefaultErrorPortProcess;
|
|
BOOLEAN ExReadyForErrors = FALSE;
|
|
BOOLEAN ExpTooLateForErrors = FALSE;
|
|
HANDLE ExpDefaultErrorPort;
|
|
extern PVOID PsSystemDllDllBase;
|
|
|
|
VOID
|
|
ExpSystemErrorHandler(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN BOOLEAN CallShutdown
|
|
)
|
|
{
|
|
|
|
ULONG Counter;
|
|
ANSI_STRING AnsiString;
|
|
NTSTATUS Status;
|
|
ULONG ParameterVector[MAXIMUM_HARDERROR_PARAMETERS];
|
|
CHAR DefaultFormatBuffer[32];
|
|
CHAR ExpSystemErrorBuffer[256];
|
|
PMESSAGE_RESOURCE_ENTRY MessageEntry;
|
|
PSZ ErrorCaption;
|
|
PSZ ErrorFormatString;
|
|
ANSI_STRING Astr;
|
|
UNICODE_STRING Ustr;
|
|
OEM_STRING Ostr;
|
|
PSZ OemCaption;
|
|
PSZ OemMessage;
|
|
PSZ UnknownHardError = "Unknown Hard Error";
|
|
PVOID UnlockHandle;
|
|
CONTEXT ContextSave;
|
|
|
|
//
|
|
// This handler is called whenever a hard error occurs before the
|
|
// default handler has been installed.
|
|
//
|
|
// This is done regardless of whether or not the process has chosen
|
|
// default hard error processing.
|
|
//
|
|
|
|
|
|
//
|
|
// Capture the callers context as closely as possible into the debugger's
|
|
// processor state area of the Prcb
|
|
//
|
|
// N.B. There may be some prologue code that shuffles registers such that
|
|
// they get destroyed.
|
|
//
|
|
// this code is here only for crash dumps
|
|
RtlCaptureContext(&KeGetCurrentPrcb()->ProcessorState.ContextFrame);
|
|
KiSaveProcessorControlState(&KeGetCurrentPrcb()->ProcessorState);
|
|
ContextSave = KeGetCurrentPrcb()->ProcessorState.ContextFrame;
|
|
|
|
|
|
DefaultFormatBuffer[0] = '\0';
|
|
RtlZeroMemory(ParameterVector,sizeof(ParameterVector));
|
|
for(Counter=0;Counter < NumberOfParameters;Counter++){
|
|
ParameterVector[Counter] = Parameters[Counter];
|
|
}
|
|
|
|
for(Counter=0;Counter < NumberOfParameters;Counter++){
|
|
if ( UnicodeStringParameterMask & 1<<Counter ) {
|
|
strcat(DefaultFormatBuffer," %s");
|
|
RtlUnicodeStringToAnsiString(&AnsiString,(PUNICODE_STRING)Parameters[Counter],TRUE);
|
|
ParameterVector[Counter] = (ULONG)AnsiString.Buffer;
|
|
}
|
|
else {
|
|
strcat(DefaultFormatBuffer," %x");
|
|
}
|
|
}
|
|
strcat(DefaultFormatBuffer,"\n");
|
|
|
|
//
|
|
// HELP where do I get the resource from !
|
|
//
|
|
|
|
if ( PsSystemDllDllBase ) {
|
|
|
|
try {
|
|
|
|
//
|
|
// If we are on a DBCS code page, we have to use ENGLISH resource
|
|
// instead of default resource because HalDisplayString() can only
|
|
// display ASCII characters on the blue screen.
|
|
//
|
|
|
|
Status = RtlFindMessage(PsSystemDllDllBase,
|
|
11,
|
|
NlsMbCodePageTag ?
|
|
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US) :
|
|
0,
|
|
ErrorStatus,
|
|
&MessageEntry);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
ErrorFormatString = UnknownHardError;
|
|
ErrorCaption = UnknownHardError;
|
|
}
|
|
else {
|
|
ErrorCaption = ExAllocatePool(NonPagedPool,strlen(MessageEntry->Text)+16);
|
|
strcpy(ErrorCaption,MessageEntry->Text);
|
|
ErrorFormatString = ErrorCaption;
|
|
while ( *ErrorFormatString >= ' ' ) {
|
|
ErrorFormatString++;
|
|
}
|
|
*ErrorFormatString++ = '\0';
|
|
while ( *ErrorFormatString && *ErrorFormatString <= ' ') {
|
|
*ErrorFormatString++;
|
|
}
|
|
}
|
|
}
|
|
except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
ErrorFormatString = UnknownHardError;
|
|
ErrorCaption = UnknownHardError;
|
|
}
|
|
}
|
|
else {
|
|
ErrorFormatString = DefaultFormatBuffer;
|
|
ErrorCaption = UnknownHardError;
|
|
}
|
|
|
|
try {
|
|
_snprintf( ExpSystemErrorBuffer, sizeof( ExpSystemErrorBuffer ),
|
|
"\nSTOP: %lx %s\n", ErrorStatus,ErrorCaption);
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
_snprintf( ExpSystemErrorBuffer, sizeof( ExpSystemErrorBuffer ),
|
|
"\nHardError %lx\n", ErrorStatus);
|
|
}
|
|
|
|
UnlockHandle = MmLockPagableCodeSection((PVOID)ExpSystemErrorHandler);
|
|
ASSERT(UnlockHandle);
|
|
|
|
if (CallShutdown) {
|
|
ZwShutdownSystem( FALSE );
|
|
}
|
|
|
|
//
|
|
// take the caption and convert it to OEM
|
|
//
|
|
|
|
OemCaption = UnknownHardError;
|
|
OemMessage = UnknownHardError;
|
|
|
|
RtlInitAnsiString(&Astr,ExpSystemErrorBuffer);
|
|
Status = RtlAnsiStringToUnicodeString(&Ustr,&Astr,TRUE);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto punt1;
|
|
}
|
|
Status = RtlUnicodeStringToOemString(&Ostr,&Ustr,TRUE);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto punt1;
|
|
}
|
|
OemCaption = Ostr.Buffer;
|
|
|
|
//
|
|
// Can't do much of anything after calling HalDisplayString...
|
|
//
|
|
|
|
punt1:;
|
|
try {
|
|
_snprintf( ExpSystemErrorBuffer, sizeof( ExpSystemErrorBuffer ),
|
|
ErrorFormatString,
|
|
ParameterVector[0],
|
|
ParameterVector[1],
|
|
ParameterVector[2],
|
|
ParameterVector[3]
|
|
);
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
_snprintf( ExpSystemErrorBuffer, sizeof( ExpSystemErrorBuffer ),
|
|
"Exception Processing Message %lx Parameters %lx %lx %lx %lx",
|
|
ErrorStatus,
|
|
ParameterVector[0],
|
|
ParameterVector[1],
|
|
ParameterVector[2],
|
|
ParameterVector[3]
|
|
);
|
|
}
|
|
|
|
|
|
RtlInitAnsiString(&Astr,ExpSystemErrorBuffer);
|
|
Status = RtlAnsiStringToUnicodeString(&Ustr,&Astr,TRUE);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto punt2;
|
|
}
|
|
Status = RtlUnicodeStringToOemString(&Ostr,&Ustr,TRUE);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
goto punt2;
|
|
}
|
|
OemMessage = Ostr.Buffer;
|
|
|
|
punt2:;
|
|
HalDisplayString( OemCaption );
|
|
HalDisplayString( OemMessage );
|
|
|
|
if (CallShutdown) {
|
|
#if DBG
|
|
DbgPrint( "EX: Typing go from this breakpoint will shutdown and restart the system.\n" );
|
|
DbgBreakPoint();
|
|
DbgUnLoadImageSymbols( NULL, (PVOID)-1, 0 );
|
|
HalReturnToFirmware( HalRebootRoutine );
|
|
#endif
|
|
}
|
|
|
|
|
|
ASSERT(sizeof(PVOID) == sizeof(ULONG));
|
|
ASSERT(sizeof(ULONG) == sizeof(NTSTATUS));
|
|
|
|
//
|
|
// We don't come back from here.
|
|
//
|
|
|
|
KeBugCheckEx(
|
|
FATAL_UNHANDLED_HARD_ERROR,
|
|
(ULONG)ErrorStatus,
|
|
(ULONG)&(ParameterVector[0]),
|
|
0,
|
|
0
|
|
);
|
|
}
|
|
|
|
NTSTATUS
|
|
ExpRaiseHardError(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN ULONG ValidResponseOptions,
|
|
OUT PULONG Response
|
|
)
|
|
{
|
|
|
|
PEPROCESS Process;
|
|
HARDERROR_MSG m;
|
|
NTSTATUS Status;
|
|
HANDLE ErrorPort;
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
PAGED_CODE();
|
|
|
|
PreviousMode = KeGetPreviousMode();
|
|
|
|
if (ValidResponseOptions == OptionShutdownSystem) {
|
|
//
|
|
// Check to see if the caller has the privilege to make this
|
|
// call.
|
|
//
|
|
|
|
|
|
if (!SeSinglePrivilegeCheck( SeShutdownPrivilege, PreviousMode )) {
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
}
|
|
|
|
ExReadyForErrors = FALSE;
|
|
}
|
|
|
|
Process = PsGetCurrentProcess();
|
|
|
|
//
|
|
// If the default handler is not installed, then
|
|
// call the fatal hard error handler if the error
|
|
// status is error
|
|
//
|
|
// Let GDI override this since it does not want to crash the machine
|
|
// when a bad driver was loaded via MmLoadSystemImage.
|
|
//
|
|
|
|
if ( !(PsGetCurrentThread()->HardErrorsAreDisabled) ) {
|
|
|
|
if (ExReadyForErrors == FALSE && NT_ERROR(ErrorStatus)){
|
|
ExpSystemErrorHandler(
|
|
ErrorStatus,
|
|
NumberOfParameters,
|
|
UnicodeStringParameterMask,
|
|
Parameters,
|
|
(BOOLEAN)((PreviousMode != KernelMode) ? TRUE : FALSE)
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the process has an error port, then if it wants default
|
|
// handling, use its port. If it disabled default handling, then
|
|
// return the error to the caller. If the process does not
|
|
// have a port, then use the registered default handler.
|
|
//
|
|
|
|
if ( Process->ExceptionPort ) {
|
|
if ( Process->DefaultHardErrorProcessing & 1 ) {
|
|
ErrorPort = Process->ExceptionPort;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// if error processing is disabled, check the error override
|
|
// status
|
|
//
|
|
if ( ErrorStatus & 0x10000000 ) {
|
|
ErrorPort = Process->ExceptionPort;
|
|
}
|
|
else {
|
|
ErrorPort = NULL;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ( Process->DefaultHardErrorProcessing & 1 ) {
|
|
ErrorPort = ExpDefaultErrorPort;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// if error processing is disabled, check the error override
|
|
// status
|
|
//
|
|
|
|
if ( ErrorStatus & 0x10000000 ) {
|
|
ErrorPort = ExpDefaultErrorPort;
|
|
}
|
|
else {
|
|
ErrorPort = NULL;
|
|
}
|
|
ErrorPort = NULL;
|
|
}
|
|
}
|
|
|
|
if ( PsGetCurrentThread()->HardErrorsAreDisabled ) {
|
|
ErrorPort = NULL;
|
|
}
|
|
|
|
if ( !IS_SYSTEM_THREAD(PsGetCurrentThread()) ) {
|
|
try {
|
|
PTEB Teb;
|
|
Teb = (PTEB)PsGetCurrentThread()->Tcb.Teb;
|
|
if ( Teb->HardErrorsAreDisabled ) {
|
|
ErrorPort = NULL;
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
;
|
|
}
|
|
}
|
|
|
|
if ( ErrorPort ) {
|
|
if ( Process == ExpDefaultErrorPortProcess ) {
|
|
if ( NT_ERROR(ErrorStatus) ) {
|
|
ExpSystemErrorHandler(
|
|
ErrorStatus,
|
|
NumberOfParameters,
|
|
UnicodeStringParameterMask,
|
|
Parameters,
|
|
(BOOLEAN)((PreviousMode != KernelMode) ? TRUE : FALSE)
|
|
);
|
|
}
|
|
*Response = (ULONG)ResponseReturnToCaller;
|
|
Status = STATUS_SUCCESS;
|
|
return Status;
|
|
}
|
|
m.h.u1.Length = HARDERROR_API_MSG_LENGTH;
|
|
m.h.u2.ZeroInit = LPC_ERROR_EVENT;
|
|
m.Status = ErrorStatus & 0xefffffff;
|
|
m.ValidResponseOptions = ValidResponseOptions;
|
|
m.UnicodeStringParameterMask = UnicodeStringParameterMask;
|
|
m.NumberOfParameters = NumberOfParameters;
|
|
if ( Parameters ) {
|
|
RtlMoveMemory(&m.Parameters,Parameters, sizeof(ULONG)*NumberOfParameters);
|
|
}
|
|
KeQuerySystemTime(&m.ErrorTime);
|
|
|
|
Status = LpcRequestWaitReplyPort(
|
|
ErrorPort,
|
|
(PPORT_MESSAGE) &m,
|
|
(PPORT_MESSAGE) &m
|
|
);
|
|
if ( NT_SUCCESS(Status) ) {
|
|
switch ( m.Response ) {
|
|
case ResponseReturnToCaller :
|
|
case ResponseNotHandled :
|
|
case ResponseAbort :
|
|
case ResponseCancel :
|
|
case ResponseIgnore :
|
|
case ResponseNo :
|
|
case ResponseOk :
|
|
case ResponseRetry :
|
|
case ResponseYes :
|
|
break;
|
|
default:
|
|
m.Response = (ULONG)ResponseReturnToCaller;
|
|
break;
|
|
}
|
|
*Response = m.Response;
|
|
}
|
|
}
|
|
else {
|
|
*Response = (ULONG)ResponseReturnToCaller;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NtRaiseHardError(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN ULONG ValidResponseOptions,
|
|
OUT PULONG Response
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PULONG CapturedParameters;
|
|
KPROCESSOR_MODE PreviousMode;
|
|
ULONG LocalResponse;
|
|
UNICODE_STRING CapturedString;
|
|
ULONG Counter;
|
|
|
|
PAGED_CODE();
|
|
|
|
if ( NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS ) {
|
|
return STATUS_INVALID_PARAMETER_2;
|
|
}
|
|
|
|
PreviousMode = KeGetPreviousMode();
|
|
if (PreviousMode != KernelMode) {
|
|
switch ( ValidResponseOptions ) {
|
|
case OptionAbortRetryIgnore :
|
|
case OptionOk :
|
|
case OptionOkCancel :
|
|
case OptionRetryCancel :
|
|
case OptionYesNo :
|
|
case OptionYesNoCancel :
|
|
case OptionShutdownSystem :
|
|
break;
|
|
default :
|
|
return STATUS_INVALID_PARAMETER_4;
|
|
}
|
|
|
|
CapturedParameters = NULL;
|
|
try {
|
|
ProbeForWriteUlong(Response);
|
|
|
|
if ( ARGUMENT_PRESENT(Parameters) ) {
|
|
ProbeForRead(
|
|
Parameters,
|
|
sizeof(ULONG)*NumberOfParameters,
|
|
sizeof(ULONG)
|
|
);
|
|
CapturedParameters = ExAllocatePool(PagedPool,sizeof(ULONG)*NumberOfParameters);
|
|
if ( !CapturedParameters ) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
RtlMoveMemory(CapturedParameters,Parameters,sizeof(ULONG)*NumberOfParameters);
|
|
|
|
//
|
|
// probe all strings
|
|
//
|
|
|
|
if ( UnicodeStringParameterMask ) {
|
|
for(Counter=0;Counter < NumberOfParameters;Counter++){
|
|
|
|
//
|
|
// if there is a string in this position,
|
|
// then probe and capture the string
|
|
//
|
|
|
|
if ( UnicodeStringParameterMask & 1<<Counter ) {
|
|
ProbeForRead(
|
|
(PVOID)CapturedParameters[Counter],
|
|
sizeof(UNICODE_STRING),
|
|
sizeof(ULONG)
|
|
);
|
|
RtlMoveMemory(
|
|
&CapturedString,
|
|
(PVOID)CapturedParameters[Counter],
|
|
sizeof(UNICODE_STRING)
|
|
);
|
|
|
|
//
|
|
// Now probe the string
|
|
//
|
|
|
|
ProbeForRead(
|
|
CapturedString.Buffer,
|
|
CapturedString.MaximumLength,
|
|
sizeof(UCHAR)
|
|
);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
CapturedParameters = NULL;
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
if ( CapturedParameters ) {
|
|
ExFreePool(CapturedParameters);
|
|
}
|
|
return GetExceptionCode();
|
|
}
|
|
|
|
//
|
|
// Call ExpRaiseHardError. All parameters are probed and everything
|
|
// should be user-mode.
|
|
// ExRaiseHardError will squirt all strings into user-mode
|
|
// without any probing
|
|
//
|
|
|
|
Status = ExpRaiseHardError(
|
|
ErrorStatus,
|
|
NumberOfParameters,
|
|
UnicodeStringParameterMask,
|
|
CapturedParameters,
|
|
ValidResponseOptions,
|
|
&LocalResponse
|
|
);
|
|
}
|
|
else {
|
|
CapturedParameters = Parameters;
|
|
|
|
Status = ExRaiseHardError(
|
|
ErrorStatus,
|
|
NumberOfParameters,
|
|
UnicodeStringParameterMask,
|
|
CapturedParameters,
|
|
ValidResponseOptions,
|
|
&LocalResponse
|
|
);
|
|
}
|
|
|
|
if (PreviousMode != KernelMode) {
|
|
if ( CapturedParameters ) {
|
|
ExFreePool(CapturedParameters);
|
|
}
|
|
try {
|
|
*Response = LocalResponse;
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
return Status;
|
|
}
|
|
}
|
|
else {
|
|
*Response = LocalResponse;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
ExRaiseHardError(
|
|
IN NTSTATUS ErrorStatus,
|
|
IN ULONG NumberOfParameters,
|
|
IN ULONG UnicodeStringParameterMask,
|
|
IN PULONG Parameters,
|
|
IN ULONG ValidResponseOptions,
|
|
OUT PULONG Response
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
PULONG ParameterBlock;
|
|
PULONG UserModeParameterBase;
|
|
PUNICODE_STRING UserModeStringsBase;
|
|
PUCHAR UserModeStringDataBase;
|
|
UNICODE_STRING CapturedStrings[MAXIMUM_HARDERROR_PARAMETERS];
|
|
ULONG LocalResponse;
|
|
ULONG Counter;
|
|
ULONG UserModeSize;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// If we are in the process of shuting down the system, do not allow
|
|
// hard errors.
|
|
//
|
|
|
|
if ( ExpTooLateForErrors ) {
|
|
|
|
*Response = ResponseNotHandled;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// If the parameters contain strings, we need to capture
|
|
// the strings and the string descriptors and push them into
|
|
// user-mode.
|
|
//
|
|
|
|
if ( ARGUMENT_PRESENT(Parameters) ) {
|
|
if ( UnicodeStringParameterMask ) {
|
|
|
|
//
|
|
// We have strings. The parameter block and all strings
|
|
// must be pushed into usermode.
|
|
//
|
|
|
|
UserModeSize = (sizeof(ULONG)+sizeof(UNICODE_STRING))*MAXIMUM_HARDERROR_PARAMETERS;
|
|
UserModeSize += sizeof(UNICODE_STRING);
|
|
|
|
for(Counter=0;Counter < NumberOfParameters;Counter++){
|
|
|
|
//
|
|
// if there is a string in this position,
|
|
// then probe and capture the string
|
|
//
|
|
|
|
if ( UnicodeStringParameterMask & 1<<Counter ) {
|
|
|
|
RtlMoveMemory(
|
|
&CapturedStrings[Counter],
|
|
(PVOID)Parameters[Counter],
|
|
sizeof(UNICODE_STRING)
|
|
);
|
|
|
|
UserModeSize += CapturedStrings[Counter].MaximumLength;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now we have the user-mode size all figured out.
|
|
// Allocate some memory and point to it with the
|
|
// parameter block. Then go through and copy all
|
|
// of the parameters, string descriptors, and
|
|
// string data into the memory
|
|
//
|
|
|
|
ParameterBlock = NULL;
|
|
Status = ZwAllocateVirtualMemory(
|
|
NtCurrentProcess(),
|
|
(PVOID *)&ParameterBlock,
|
|
0,
|
|
&UserModeSize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
);
|
|
|
|
if (!NT_SUCCESS( Status )) {
|
|
return( Status );
|
|
}
|
|
|
|
UserModeParameterBase = ParameterBlock;
|
|
UserModeStringsBase = (PUNICODE_STRING)((PUCHAR)ParameterBlock + sizeof(ULONG)*MAXIMUM_HARDERROR_PARAMETERS);
|
|
UserModeStringDataBase = (PUCHAR)UserModeStringsBase + sizeof(UNICODE_STRING)*MAXIMUM_HARDERROR_PARAMETERS;
|
|
|
|
for(Counter=0;Counter < NumberOfParameters;Counter++){
|
|
|
|
//
|
|
// move parameters to user-mode portion of the
|
|
// address space.
|
|
//
|
|
|
|
if ( UnicodeStringParameterMask & 1<<Counter ) {
|
|
|
|
//
|
|
// fix the parameter to point at the string descriptor slot
|
|
// in the user-mode buffer.
|
|
//
|
|
|
|
UserModeParameterBase[Counter] = (ULONG)&UserModeStringsBase[Counter];
|
|
|
|
//
|
|
// Copy the string data to user-mode
|
|
//
|
|
|
|
RtlMoveMemory(
|
|
UserModeStringDataBase,
|
|
CapturedStrings[Counter].Buffer,
|
|
CapturedStrings[Counter].MaximumLength
|
|
);
|
|
|
|
CapturedStrings[Counter].Buffer = (PWSTR)UserModeStringDataBase;
|
|
|
|
//
|
|
// copy the string descriptor
|
|
//
|
|
|
|
RtlMoveMemory(
|
|
&UserModeStringsBase[Counter],
|
|
&CapturedStrings[Counter],
|
|
sizeof(UNICODE_STRING)
|
|
);
|
|
|
|
//
|
|
// Adjust the string data base
|
|
//
|
|
|
|
UserModeStringDataBase += CapturedStrings[Counter].MaximumLength;
|
|
|
|
}
|
|
else {
|
|
UserModeParameterBase[Counter] = Parameters[Counter];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
ParameterBlock = Parameters;
|
|
}
|
|
}
|
|
else {
|
|
ParameterBlock = NULL;
|
|
}
|
|
|
|
//
|
|
// Call the hard error sender.
|
|
//
|
|
|
|
Status = ExpRaiseHardError(
|
|
ErrorStatus,
|
|
NumberOfParameters,
|
|
UnicodeStringParameterMask,
|
|
ParameterBlock,
|
|
ValidResponseOptions,
|
|
&LocalResponse
|
|
);
|
|
//
|
|
// If the parameter block was allocated, it needs to be
|
|
// freed
|
|
//
|
|
|
|
if ( ParameterBlock && ParameterBlock != Parameters ) {
|
|
UserModeSize = 0;
|
|
ZwFreeVirtualMemory(
|
|
NtCurrentProcess(),
|
|
(PVOID *)&ParameterBlock,
|
|
&UserModeSize,
|
|
MEM_RELEASE
|
|
);
|
|
}
|
|
*Response = LocalResponse;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
NtSetDefaultHardErrorPort(
|
|
IN HANDLE DefaultHardErrorPort
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (!SeSinglePrivilegeCheck( SeTcbPrivilege, KeGetPreviousMode() )) {
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
}
|
|
|
|
if ( ExReadyForErrors ) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Priv check ?
|
|
//
|
|
|
|
Status = ObReferenceObjectByHandle (
|
|
DefaultHardErrorPort,
|
|
0,
|
|
LpcPortObjectType,
|
|
KeGetPreviousMode(),
|
|
(PVOID *)&ExpDefaultErrorPort,
|
|
NULL
|
|
);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
return Status;
|
|
}
|
|
|
|
ExReadyForErrors = TRUE;
|
|
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
_CRTAPI1
|
|
_purecall()
|
|
{
|
|
ASSERTMSG("_purecall() was called", FALSE);
|
|
ExRaiseStatus(STATUS_NOT_IMPLEMENTED);
|
|
}
|