mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:35:41 +00:00
Dmitry Philippov
- Implement hard error message handler. Now whenever a hard error occurs (like an exception in the win32 application, or missing DLL import), a user will be presented with a nice message box saying about the problem. svn path=/trunk/; revision=31400
This commit is contained in:
parent
aa2093d7d9
commit
0a73568c82
4 changed files with 380 additions and 10 deletions
|
@ -106,7 +106,9 @@ CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL FASTCALL CallHardError(void);
|
BOOL
|
||||||
|
CallHardError(IN PCSRSS_PROCESS_DATA ProcessData,
|
||||||
|
IN PHARDERROR_MSG HardErrorMessage);
|
||||||
|
|
||||||
static
|
static
|
||||||
VOID
|
VOID
|
||||||
|
@ -117,7 +119,7 @@ CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData,
|
||||||
DPRINT1("CSR: received hard error %lx\n", Message->Status);
|
DPRINT1("CSR: received hard error %lx\n", Message->Status);
|
||||||
|
|
||||||
/* Call the hard error handler in win32csr */
|
/* Call the hard error handler in win32csr */
|
||||||
CallHardError();
|
(VOID)CallHardError(ProcessData, Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
|
|
|
@ -43,7 +43,8 @@ typedef struct tagCSRSS_EXPORTED_FUNCS
|
||||||
|
|
||||||
typedef BOOL (STDCALL *CSRPLUGIN_INIT_COMPLETE_PROC)(void);
|
typedef BOOL (STDCALL *CSRPLUGIN_INIT_COMPLETE_PROC)(void);
|
||||||
|
|
||||||
typedef BOOL (STDCALL *CSRPLUGIN_HARDERROR_PROC)(void);
|
typedef BOOL (STDCALL *CSRPLUGIN_HARDERROR_PROC)(IN PCSRSS_PROCESS_DATA ProcessData,
|
||||||
|
IN PHARDERROR_MSG HardErrorMessage);
|
||||||
|
|
||||||
typedef BOOL (STDCALL *CSRPLUGIN_INITIALIZE_PROC)(PCSRSS_API_DEFINITION *ApiDefinitions,
|
typedef BOOL (STDCALL *CSRPLUGIN_INITIALIZE_PROC)(PCSRSS_API_DEFINITION *ApiDefinitions,
|
||||||
PCSRSS_OBJECT_DEFINITION *ObjectDefinitions,
|
PCSRSS_OBJECT_DEFINITION *ObjectDefinitions,
|
||||||
|
|
|
@ -122,8 +122,8 @@ CallInitComplete(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
FASTCALL
|
CallHardError(IN PCSRSS_PROCESS_DATA ProcessData,
|
||||||
CallHardError(void)
|
IN PHARDERROR_MSG HardErrorMessage)
|
||||||
{
|
{
|
||||||
BOOL Ok;
|
BOOL Ok;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -135,7 +135,7 @@ CallHardError(void)
|
||||||
{
|
{
|
||||||
for (i = 0; i < HardErrorProcCount && Ok; i++)
|
for (i = 0; i < HardErrorProcCount && Ok; i++)
|
||||||
{
|
{
|
||||||
Ok = (*(HardErrorProcs[i]))();
|
Ok = (*(HardErrorProcs[i]))(ProcessData, HardErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
* FILE: subsys/csrss/win32csr/dllmain.c
|
* FILE: subsys/csrss/win32csr/dllmain.c
|
||||||
* PURPOSE: Initialization
|
* PURPOSE: Initialization
|
||||||
|
* PROGRAMMERS: Dmitry Philippov (shedon@mail.ru)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -172,9 +172,376 @@ Win32CsrInitComplete(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL STDCALL
|
static BOOL STDCALL
|
||||||
Win32CsrHardError(void)
|
Win32CsrHardError(IN PCSRSS_PROCESS_DATA ProcessData,
|
||||||
|
IN PHARDERROR_MSG HardErrorMessage)
|
||||||
{
|
{
|
||||||
MessageBox(0, "Hard Error", "TODO", 0);
|
UINT responce = MB_OK;
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE hProcess;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
ULONG nParam = 0;
|
||||||
|
PRTL_MESSAGE_RESOURCE_ENTRY MessageResource;
|
||||||
|
ULONG ParameterList[MAXIMUM_HARDERROR_PARAMETERS];
|
||||||
|
LPSTR CaptionText, MessageBody;
|
||||||
|
LPWSTR szxCaptionText, szxMessageBody;
|
||||||
|
DWORD SizeOfAllUnicodeStrings = 0;
|
||||||
|
PROCESS_BASIC_INFORMATION ClientBasicInfo;
|
||||||
|
UNICODE_STRING ClientFileNameU;
|
||||||
|
UNICODE_STRING TempStringU;
|
||||||
|
UNICODE_STRING ParameterStringU;
|
||||||
|
ANSI_STRING ParamStringA;
|
||||||
|
ULONG UnicodeStringParameterMask = HardErrorMessage->UnicodeStringParameterMask;
|
||||||
|
int MessageBoxResponse;
|
||||||
|
|
||||||
|
HardErrorMessage->Response = ResponseNotHandled;
|
||||||
|
|
||||||
|
DPRINT1("NumberOfParameters = %d\n", HardErrorMessage->NumberOfParameters);
|
||||||
|
DPRINT1("Status = %lx\n", HardErrorMessage->Status);
|
||||||
|
|
||||||
|
// open client process
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||||
|
Status = NtOpenProcess(&hProcess, PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, &ObjectAttributes, &HardErrorMessage->h.ClientId);
|
||||||
|
if( !NT_SUCCESS(Status) ) {
|
||||||
|
DPRINT1("NtOpenProcess failed with code: %lx\n", Status);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's get a name of the client process to display it in the caption of a message box
|
||||||
|
|
||||||
|
ClientFileNameU.MaximumLength = 0;
|
||||||
|
ClientFileNameU.Length = 0;
|
||||||
|
ClientFileNameU.Buffer = NULL;
|
||||||
|
Status = NtQueryInformationProcess(hProcess,
|
||||||
|
ProcessBasicInformation,
|
||||||
|
&ClientBasicInfo,
|
||||||
|
sizeof(ClientBasicInfo),
|
||||||
|
NULL);
|
||||||
|
if( NT_SUCCESS(Status) ) {
|
||||||
|
PLIST_ENTRY ModuleListHead;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PLDR_DATA_TABLE_ENTRY Module;
|
||||||
|
PPEB_LDR_DATA Ldr;
|
||||||
|
PPEB Peb = ClientBasicInfo.PebBaseAddress;
|
||||||
|
|
||||||
|
if( Peb )
|
||||||
|
{
|
||||||
|
Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL);
|
||||||
|
if( NT_SUCCESS(Status) ) {
|
||||||
|
ModuleListHead = &Ldr->InLoadOrderModuleList;
|
||||||
|
Status = NtReadVirtualMemory(
|
||||||
|
hProcess,
|
||||||
|
&ModuleListHead->Flink,
|
||||||
|
&Entry,
|
||||||
|
sizeof(Entry),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if( NT_SUCCESS(Status) )
|
||||||
|
{
|
||||||
|
if (Entry != ModuleListHead)
|
||||||
|
{
|
||||||
|
LDR_DATA_TABLE_ENTRY ModuleData;
|
||||||
|
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
||||||
|
|
||||||
|
Status = NtReadVirtualMemory(hProcess, Module, &ModuleData, sizeof(ModuleData), NULL);
|
||||||
|
if( NT_SUCCESS(Status) ) {
|
||||||
|
PVOID ClientDllBase;
|
||||||
|
|
||||||
|
Status = NtReadVirtualMemory(
|
||||||
|
hProcess,
|
||||||
|
&Peb->ImageBaseAddress,
|
||||||
|
&ClientDllBase,
|
||||||
|
sizeof(ClientDllBase),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if( NT_SUCCESS(Status) && (ClientDllBase == ModuleData.DllBase) ) {
|
||||||
|
|
||||||
|
ClientFileNameU.MaximumLength = ModuleData.BaseDllName.MaximumLength;
|
||||||
|
ClientFileNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength);
|
||||||
|
Status = NtReadVirtualMemory(
|
||||||
|
hProcess,
|
||||||
|
ModuleData.BaseDllName.Buffer,
|
||||||
|
ClientFileNameU.Buffer,
|
||||||
|
ClientFileNameU.MaximumLength,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if( NT_SUCCESS(Status) ) {
|
||||||
|
ClientFileNameU.Length = wcslen(ClientFileNameU.Buffer)*sizeof(wchar_t);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
|
||||||
|
ClientFileNameU.Buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read all unicode strings from client space
|
||||||
|
for(nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++, UnicodeStringParameterMask >>= 1)
|
||||||
|
{
|
||||||
|
if( UnicodeStringParameterMask & 0x01 ) {
|
||||||
|
Status = NtReadVirtualMemory(hProcess,
|
||||||
|
(PVOID)HardErrorMessage->Parameters[nParam],
|
||||||
|
(PVOID)&TempStringU,
|
||||||
|
sizeof(TempStringU),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if( NT_SUCCESS(Status) ) {
|
||||||
|
ParameterStringU.Buffer = (PWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TempStringU.MaximumLength);
|
||||||
|
if( !ParameterStringU.Buffer ) {
|
||||||
|
DPRINT1("Cannot allocate memory %d\n", TempStringU.MaximumLength);
|
||||||
|
NtClose(hProcess);
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtReadVirtualMemory(hProcess,
|
||||||
|
(PVOID)TempStringU.Buffer,
|
||||||
|
(PVOID)ParameterStringU.Buffer,
|
||||||
|
TempStringU.MaximumLength,
|
||||||
|
NULL);
|
||||||
|
if( !NT_SUCCESS(Status) ) {
|
||||||
|
DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status);
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, ParameterStringU.Buffer);
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
|
||||||
|
}
|
||||||
|
NtClose(hProcess);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ParameterStringU.Length = TempStringU.Length;
|
||||||
|
ParameterStringU.MaximumLength = TempStringU.MaximumLength;
|
||||||
|
DPRINT("ParameterStringU=\'%wZ\'\n", &ParameterStringU);
|
||||||
|
RtlUnicodeStringToAnsiString(&ParamStringA, &ParameterStringU, TRUE);
|
||||||
|
ParameterList[nParam] = (ULONG)ParamStringA.Buffer;
|
||||||
|
SizeOfAllUnicodeStrings += ParamStringA.MaximumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// it's not a unicode string
|
||||||
|
ParameterList[nParam] = HardErrorMessage->Parameters[nParam];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NtClose(hProcess);
|
||||||
|
|
||||||
|
// get text string of the error code
|
||||||
|
Status = RtlFindMessage(
|
||||||
|
(PVOID)GetModuleHandle(TEXT("ntdll")),
|
||||||
|
(ULONG)RT_MESSAGETABLE,
|
||||||
|
LANG_NEUTRAL,
|
||||||
|
HardErrorMessage->Status,
|
||||||
|
&MessageResource );
|
||||||
|
if( !NT_SUCCESS(Status) ) {
|
||||||
|
// WE HAVE TO DISPLAY HERE: "Unknown hard error"
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength+64);
|
||||||
|
wsprintfW(szxCaptionText, L"%s - %hs", ClientFileNameU.Buffer, "Application Error");
|
||||||
|
} else {
|
||||||
|
szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 64);
|
||||||
|
wsprintfW(szxCaptionText, L"System - Application Error");
|
||||||
|
}
|
||||||
|
MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 38);
|
||||||
|
wsprintfA(MessageBody, "Unknown hard error");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LPSTR NtStatusString;
|
||||||
|
UNICODE_STRING MessageU;
|
||||||
|
ANSI_STRING MessageA;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&MessageU, (PWSTR)MessageResource->Text);
|
||||||
|
RtlUnicodeStringToAnsiString(&MessageA, &MessageU, TRUE);
|
||||||
|
|
||||||
|
USHORT CaptionSize = 0;
|
||||||
|
// check whether a caption exists
|
||||||
|
if( *MessageA.Buffer == '{' ) {
|
||||||
|
// get size of the caption
|
||||||
|
for( CaptionSize = 0; (CaptionSize < MessageA.Length) && ('}' != MessageA.Buffer[CaptionSize]); CaptionSize++);
|
||||||
|
|
||||||
|
CaptionText = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CaptionSize);
|
||||||
|
RtlCopyMemory(CaptionText, MessageA.Buffer+1, CaptionSize-1);
|
||||||
|
CaptionSize += 3; // "}\r\n" - 3
|
||||||
|
|
||||||
|
szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(wchar_t)*CaptionSize+ClientFileNameU.MaximumLength+128);
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
wsprintfW(szxCaptionText, L"%s - %hs", ClientFileNameU.Buffer, CaptionText);
|
||||||
|
} else {
|
||||||
|
wsprintfW(szxCaptionText, L"System - %hs", CaptionText);
|
||||||
|
}
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, CaptionText);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ClientFileNameU.MaximumLength);
|
||||||
|
wsprintfW(szxCaptionText, L"%s", ClientFileNameU.Buffer);
|
||||||
|
} else {
|
||||||
|
szxCaptionText = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 14); // 14 - "System\0\0"
|
||||||
|
wsprintfW(szxCaptionText, L"System");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( STATUS_UNHANDLED_EXCEPTION == HardErrorMessage->Status )
|
||||||
|
{
|
||||||
|
PRTL_MESSAGE_RESOURCE_ENTRY MsgResException;
|
||||||
|
MessageBody = NULL;
|
||||||
|
Status = RtlFindMessage(
|
||||||
|
(PVOID)GetModuleHandle(TEXT("ntdll")),
|
||||||
|
(ULONG)RT_MESSAGETABLE,
|
||||||
|
LANG_NEUTRAL,
|
||||||
|
ParameterList[0],
|
||||||
|
&MsgResException);
|
||||||
|
|
||||||
|
if( NT_SUCCESS(Status) )
|
||||||
|
{
|
||||||
|
UNICODE_STRING ExcMessageU;
|
||||||
|
ANSI_STRING ExcMessageA;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ExcMessageU, (PWSTR)MsgResException->Text);
|
||||||
|
|
||||||
|
RtlUnicodeStringToAnsiString(&ExcMessageA, &ExcMessageU, TRUE);
|
||||||
|
|
||||||
|
MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MsgResException->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a magic number I think it should be enough
|
||||||
|
if( STATUS_ACCESS_VIOLATION == ParameterList[0] ) {
|
||||||
|
LPSTR pOperationType;
|
||||||
|
if( ParameterList[2] ) pOperationType = "written";
|
||||||
|
else pOperationType = "read";
|
||||||
|
wsprintfA(MessageBody, ExcMessageA.Buffer, ParameterList[1], ParameterList[3], pOperationType);
|
||||||
|
}
|
||||||
|
else if( STATUS_IN_PAGE_ERROR == ParameterList[0] ) {
|
||||||
|
wsprintfA(MessageBody, ExcMessageA.Buffer, ParameterList[1], ParameterList[3], ParameterList[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !MessageBody ) {
|
||||||
|
NtStatusString = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MessageResource->Length-CaptionSize);
|
||||||
|
RtlCopyMemory(NtStatusString, MessageA.Buffer+CaptionSize, (MessageResource->Length-CaptionSize)-1);
|
||||||
|
|
||||||
|
MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MessageResource->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a magic number I think it should be enough
|
||||||
|
|
||||||
|
wsprintfA(MessageBody, NtStatusString,
|
||||||
|
L"Unknown software exception",
|
||||||
|
ParameterList[0],
|
||||||
|
ParameterList[1]);
|
||||||
|
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, NtStatusString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NtStatusString = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MessageResource->Length-CaptionSize);
|
||||||
|
RtlCopyMemory(NtStatusString, MessageA.Buffer+CaptionSize, (MessageResource->Length-CaptionSize)-1);
|
||||||
|
|
||||||
|
MessageBody = (LPSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MessageResource->Length+SizeOfAllUnicodeStrings+1024); // 1024 is a magic number I think it should be enough
|
||||||
|
|
||||||
|
wsprintfA(MessageBody, NtStatusString,
|
||||||
|
ParameterList[0],
|
||||||
|
ParameterList[1],
|
||||||
|
ParameterList[2],
|
||||||
|
ParameterList[3]);
|
||||||
|
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, NtStatusString);
|
||||||
|
}
|
||||||
|
RtlFreeAnsiString(&MessageA);
|
||||||
|
}
|
||||||
|
if( ClientFileNameU.Buffer ) {
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, ClientFileNameU.Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
szxMessageBody = (LPWSTR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(wchar_t)*(strlen(MessageBody)+1));
|
||||||
|
wsprintfW(szxMessageBody, L"%hs", MessageBody);
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, MessageBody);
|
||||||
|
|
||||||
|
switch ( HardErrorMessage->ValidResponseOptions )
|
||||||
|
{
|
||||||
|
case OptionAbortRetryIgnore:
|
||||||
|
responce = MB_ABORTRETRYIGNORE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionOk:
|
||||||
|
responce = MB_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionOkCancel:
|
||||||
|
responce = MB_OKCANCEL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionRetryCancel:
|
||||||
|
responce = MB_RETRYCANCEL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionYesNo:
|
||||||
|
responce = MB_YESNO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionYesNoCancel:
|
||||||
|
responce = MB_YESNOCANCEL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OptionShutdownSystem:
|
||||||
|
// XZ??
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("Wrong option: ValidResponseOptions = %d\n", HardErrorMessage->ValidResponseOptions);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: We should not use MessageBox !!!!
|
||||||
|
MessageBoxResponse = MessageBoxW(0, szxMessageBody, szxCaptionText, responce|MB_ICONERROR|MB_SYSTEMMODAL|MB_SETFOREGROUND);
|
||||||
|
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, szxMessageBody);
|
||||||
|
RtlFreeHeap (RtlGetProcessHeap(), 0, szxCaptionText);
|
||||||
|
|
||||||
|
switch( MessageBoxResponse )
|
||||||
|
{
|
||||||
|
case IDOK:
|
||||||
|
HardErrorMessage->Response = ResponseOk;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDCANCEL:
|
||||||
|
HardErrorMessage->Response = ResponseCancel;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDYES:
|
||||||
|
HardErrorMessage->Response = ResponseYes;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDNO:
|
||||||
|
HardErrorMessage->Response = ResponseNo;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDABORT:
|
||||||
|
HardErrorMessage->Response = ResponseAbort;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDIGNORE:
|
||||||
|
HardErrorMessage->Response = ResponseIgnore;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDRETRY:
|
||||||
|
HardErrorMessage->Response = ResponseRetry;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10://IDTRYAGAIN:
|
||||||
|
HardErrorMessage->Response = ResponseTryAgain;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11://IDCONTINUE:
|
||||||
|
HardErrorMessage->Response = ResponseContinue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue