Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenharderror.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * FILE: subsys/csrss/win32csr/dllmain.c 00005 * PURPOSE: Initialization 00006 * PROGRAMMERS: Dmitry Philippov (shedon@mail.ru) 00007 * Timo Kreuzer (timo.kreuzer@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #define NDEBUG 00013 #include "w32csr.h" 00014 #include <debug.h> 00015 #include <strsafe.h> 00016 00017 #define IDTRYAGAIN 10 00018 #define IDCONTINUE 11 00019 00020 /* FUNCTIONS *****************************************************************/ 00021 00022 static 00023 NTSTATUS 00024 CsrpGetClientFileName( 00025 OUT PUNICODE_STRING ClientFileNameU, 00026 HANDLE hProcess) 00027 { 00028 PLIST_ENTRY ModuleListHead; 00029 PLIST_ENTRY Entry; 00030 PLDR_DATA_TABLE_ENTRY Module; 00031 PPEB_LDR_DATA Ldr; 00032 PROCESS_BASIC_INFORMATION ClientBasicInfo; 00033 LDR_DATA_TABLE_ENTRY ModuleData; 00034 PVOID ClientDllBase; 00035 NTSTATUS Status; 00036 PPEB Peb; 00037 00038 /* Initialize string */ 00039 ClientFileNameU->MaximumLength = 0; 00040 ClientFileNameU->Length = 0; 00041 ClientFileNameU->Buffer = NULL; 00042 00043 /* Query process information */ 00044 Status = NtQueryInformationProcess(hProcess, 00045 ProcessBasicInformation, 00046 &ClientBasicInfo, 00047 sizeof(ClientBasicInfo), 00048 NULL); 00049 if (!NT_SUCCESS(Status)) return Status; 00050 00051 Peb = ClientBasicInfo.PebBaseAddress; 00052 if (!Peb) return STATUS_UNSUCCESSFUL; 00053 00054 Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL); 00055 if (!NT_SUCCESS(Status)) return Status; 00056 00057 ModuleListHead = &Ldr->InLoadOrderModuleList; 00058 Status = NtReadVirtualMemory(hProcess, 00059 &ModuleListHead->Flink, 00060 &Entry, 00061 sizeof(Entry), 00062 NULL); 00063 if (!NT_SUCCESS(Status)) return Status; 00064 00065 if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL; 00066 00067 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 00068 00069 Status = NtReadVirtualMemory(hProcess, 00070 Module, 00071 &ModuleData, 00072 sizeof(ModuleData), 00073 NULL); 00074 if (!NT_SUCCESS(Status)) return Status; 00075 00076 Status = NtReadVirtualMemory(hProcess, 00077 &Peb->ImageBaseAddress, 00078 &ClientDllBase, 00079 sizeof(ClientDllBase), 00080 NULL); 00081 if (!NT_SUCCESS(Status)) return Status; 00082 00083 if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL; 00084 00085 ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength; 00086 ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00087 HEAP_ZERO_MEMORY, 00088 ClientFileNameU->MaximumLength); 00089 00090 Status = NtReadVirtualMemory(hProcess, 00091 ModuleData.BaseDllName.Buffer, 00092 ClientFileNameU->Buffer, 00093 ClientFileNameU->MaximumLength, 00094 NULL); 00095 if (!NT_SUCCESS(Status)) 00096 { 00097 RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer); 00098 ClientFileNameU->Buffer = NULL; 00099 ClientFileNameU->MaximumLength = 0; 00100 return Status; 00101 } 00102 00103 ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer)*sizeof(wchar_t); 00104 DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU); 00105 00106 return STATUS_SUCCESS; 00107 } 00108 00109 static 00110 VOID 00111 CsrpFreeStringParameters( 00112 IN OUT PULONG_PTR Parameters, 00113 IN PHARDERROR_MSG HardErrorMessage) 00114 { 00115 ULONG nParam; 00116 00117 /* Loop all parameters */ 00118 for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) 00119 { 00120 /* Check if the current parameter is a string */ 00121 if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam) && Parameters[nParam]) 00122 { 00123 /* Free the string buffer */ 00124 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); 00125 } 00126 } 00127 } 00128 00129 static 00130 NTSTATUS 00131 CsrpCaptureStringParameters( 00132 OUT PULONG_PTR Parameters, 00133 OUT PULONG SizeOfAllUnicodeStrings, 00134 IN PHARDERROR_MSG HardErrorMessage, 00135 HANDLE hProcess) 00136 { 00137 ULONG nParam, Size = 0; 00138 NTSTATUS Status = STATUS_SUCCESS; 00139 UNICODE_STRING TempStringU, ParamStringU; 00140 ANSI_STRING TempStringA; 00141 00142 /* Read all strings from client space */ 00143 for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) 00144 { 00145 Parameters[nParam] = 0; 00146 00147 /* Check if the current parameter is a unicode string */ 00148 if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) 00149 { 00150 /* Read the UNICODE_STRING from the process memory */ 00151 Status = NtReadVirtualMemory(hProcess, 00152 (PVOID)HardErrorMessage->Parameters[nParam], 00153 &ParamStringU, 00154 sizeof(ParamStringU), 00155 NULL); 00156 00157 if (!NT_SUCCESS(Status)) 00158 break; 00159 00160 /* Allocate a buffer for the string */ 00161 TempStringU.MaximumLength = ParamStringU.Length; 00162 TempStringU.Length = ParamStringU.Length; 00163 TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00164 HEAP_ZERO_MEMORY, 00165 TempStringU.MaximumLength); 00166 00167 if (!TempStringU.Buffer) 00168 { 00169 DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength); 00170 Status = STATUS_NO_MEMORY; 00171 } 00172 00173 /* Read the string buffer from the process memory */ 00174 Status = NtReadVirtualMemory(hProcess, 00175 ParamStringU.Buffer, 00176 TempStringU.Buffer, 00177 ParamStringU.Length, 00178 NULL); 00179 if (!NT_SUCCESS(Status)) 00180 { 00181 DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status); 00182 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); 00183 break; 00184 } 00185 00186 DPRINT("ParamString=\'%wZ\'\n", &TempStringU); 00187 00188 /* Allocate a buffer for converted to ANSI string */ 00189 TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU); 00190 TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00191 HEAP_ZERO_MEMORY, 00192 TempStringA.MaximumLength); 00193 00194 if (!TempStringA.Buffer) 00195 { 00196 DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength); 00197 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); 00198 Status = STATUS_NO_MEMORY; 00199 break; 00200 } 00201 00202 /* Convert string to ANSI and free temporary buffer */ 00203 Status = RtlUnicodeStringToAnsiString(&TempStringA, &TempStringU, FALSE); 00204 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); 00205 if (!NT_SUCCESS(Status)) 00206 { 00207 RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer); 00208 break; 00209 } 00210 00211 /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */ 00212 Parameters[nParam] = (ULONG_PTR)TempStringA.Buffer; 00213 Size += TempStringU.Length; 00214 } 00215 else 00216 { 00217 /* It's not a unicode string */ 00218 Parameters[nParam] = HardErrorMessage->Parameters[nParam]; 00219 } 00220 } 00221 00222 if (!NT_SUCCESS(Status)) 00223 { 00224 CsrpFreeStringParameters(Parameters, HardErrorMessage); 00225 return Status; 00226 } 00227 00228 *SizeOfAllUnicodeStrings = Size; 00229 return Status; 00230 } 00231 00232 static 00233 NTSTATUS 00234 CsrpFormatMessages( 00235 OUT PUNICODE_STRING TextStringU, 00236 OUT PUNICODE_STRING CaptionStringU, 00237 IN PULONG_PTR Parameters, 00238 IN ULONG SizeOfStrings, 00239 IN PHARDERROR_MSG Message, 00240 IN HANDLE hProcess) 00241 { 00242 NTSTATUS Status; 00243 UNICODE_STRING FileNameU, TempStringU, FormatU; 00244 ANSI_STRING FormatA; 00245 PMESSAGE_RESOURCE_ENTRY MessageResource; 00246 PWSTR FormatString; 00247 ULONG Size, ExceptionCode; 00248 00249 /* Get the file name of the client process */ 00250 CsrpGetClientFileName(&FileNameU, hProcess); 00251 00252 /* Check if we have a file name */ 00253 if (!FileNameU.Buffer) 00254 { 00255 /* No, use system */ 00256 RtlInitUnicodeString(&FileNameU, L"System"); 00257 } 00258 00259 /* Get text string of the error code */ 00260 Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), 00261 (ULONG_PTR)RT_MESSAGETABLE, 00262 LANG_NEUTRAL, 00263 Message->Status, 00264 &MessageResource); 00265 00266 if (NT_SUCCESS(Status)) 00267 { 00268 if (MessageResource->Flags) 00269 { 00270 RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text); 00271 FormatA.Buffer = NULL; 00272 } 00273 else 00274 { 00275 RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text); 00276 RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE); 00277 } 00278 } 00279 else 00280 { 00281 /* Fall back to hardcoded value */ 00282 RtlInitUnicodeString(&FormatU, L"Unknown Hard Error"); 00283 FormatA.Buffer = NULL; 00284 } 00285 00286 FormatString = FormatU.Buffer; 00287 00288 /* Check whether a caption exists */ 00289 if (FormatString[0] == L'{') 00290 { 00291 /* Set caption start */ 00292 TempStringU.Buffer = ++FormatString; 00293 00294 /* Get size of the caption */ 00295 for (Size = 0; *FormatString != 0 && *FormatString != L'}'; Size++) 00296 FormatString++; 00297 00298 /* Skip '}', '\r', '\n' */ 00299 FormatString += 3; 00300 00301 TempStringU.Length = Size * sizeof(WCHAR); 00302 TempStringU.MaximumLength = TempStringU.Length; 00303 } 00304 else 00305 { 00306 /* FIXME: Set string based on severity */ 00307 RtlInitUnicodeString(&TempStringU, L"Application Error"); 00308 } 00309 00310 /* Calculate buffer length for the caption */ 00311 CaptionStringU->MaximumLength = FileNameU.Length + TempStringU.Length + 00312 4 * sizeof(WCHAR); 00313 00314 /* Allocate a buffer for the caption */ 00315 CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00316 HEAP_ZERO_MEMORY, 00317 CaptionStringU->MaximumLength); 00318 00319 /* Append the file name, seperator and the caption text */ 00320 CaptionStringU->Length = 0; 00321 RtlAppendUnicodeStringToString(CaptionStringU, &FileNameU); 00322 RtlAppendUnicodeToString(CaptionStringU, L" - "); 00323 RtlAppendUnicodeStringToString(CaptionStringU, &TempStringU); 00324 00325 /* Zero terminate the buffer */ 00326 CaptionStringU->Buffer[CaptionStringU->Length / sizeof(WCHAR)] = 0; 00327 00328 /* Free the file name buffer */ 00329 RtlFreeUnicodeString(&FileNameU); 00330 00331 /* Check if this is an exception message */ 00332 if (Message->Status == STATUS_UNHANDLED_EXCEPTION) 00333 { 00334 ExceptionCode = Parameters[0]; 00335 00336 /* Handle special cases */ 00337 if (ExceptionCode == STATUS_ACCESS_VIOLATION) 00338 { 00339 Parameters[0] = Parameters[1]; 00340 Parameters[1] = Parameters[3]; 00341 if (Parameters[2]) Parameters[2] = (ULONG_PTR)L"written"; 00342 else Parameters[2] = (ULONG_PTR)L"read"; 00343 MessageResource = NULL; 00344 } 00345 else if (ExceptionCode == STATUS_IN_PAGE_ERROR) 00346 { 00347 Parameters[0] = Parameters[1]; 00348 Parameters[1] = Parameters[3]; 00349 MessageResource = NULL; 00350 } 00351 else 00352 { 00353 /* Fall back to hardcoded value */ 00354 Parameters[2] = Parameters[1]; 00355 Parameters[1] = Parameters[0]; 00356 Parameters[0] = (ULONG_PTR)L"unknown software exception"; 00357 } 00358 00359 if (!MessageResource) 00360 { 00361 /* Get text string of the exception code */ 00362 Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), 00363 (ULONG_PTR)RT_MESSAGETABLE, 00364 LANG_NEUTRAL, 00365 ExceptionCode, 00366 &MessageResource); 00367 00368 if (NT_SUCCESS(Status)) 00369 { 00370 if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); 00371 00372 if (MessageResource->Flags) 00373 { 00374 RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text); 00375 FormatA.Buffer = NULL; 00376 } 00377 else 00378 { 00379 RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text); 00380 RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE); 00381 } 00382 FormatString = FormatU.Buffer; 00383 } 00384 else 00385 { 00386 /* Fall back to hardcoded value */ 00387 Parameters[2] = Parameters[1]; 00388 Parameters[1] = Parameters[0]; 00389 Parameters[0] = (ULONG_PTR)L"unknown software exception"; 00390 } 00391 } 00392 } 00393 00394 /* Calculate length of text buffer */ 00395 TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + 42 * sizeof(WCHAR); 00396 00397 /* Allocate a buffer for the text */ 00398 TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00399 HEAP_ZERO_MEMORY, 00400 TextStringU->MaximumLength); 00401 00402 /* Wrap in SEH to protect from invalid string parameters */ 00403 _SEH2_TRY 00404 { 00405 /* Print the string into the buffer */ 00406 StringCbPrintfW(TextStringU->Buffer, 00407 TextStringU->MaximumLength, 00408 FormatString, 00409 Parameters[0], 00410 Parameters[1], 00411 Parameters[2], 00412 Parameters[3]); 00413 Status = STATUS_SUCCESS; 00414 } 00415 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00416 { 00417 /* Set error and free buffers */ 00418 Status = _SEH2_GetExceptionCode(); 00419 RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); 00420 RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); 00421 } 00422 _SEH2_END 00423 00424 if (NT_SUCCESS(Status)) 00425 { 00426 TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR); 00427 } 00428 00429 if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); 00430 00431 return Status; 00432 } 00433 00434 static 00435 ULONG 00436 CsrpMessageBox( 00437 PWSTR Text, 00438 PWSTR Caption, 00439 ULONG ValidResponseOptions, 00440 ULONG Severity) 00441 { 00442 ULONG Type, MessageBoxResponse; 00443 00444 /* Set the message box type */ 00445 switch (ValidResponseOptions) 00446 { 00447 case OptionAbortRetryIgnore: 00448 Type = MB_ABORTRETRYIGNORE; 00449 break; 00450 case OptionOk: 00451 Type = MB_OK; 00452 break; 00453 case OptionOkCancel: 00454 Type = MB_OKCANCEL; 00455 break; 00456 case OptionRetryCancel: 00457 Type = MB_RETRYCANCEL; 00458 break; 00459 case OptionYesNo: 00460 Type = MB_YESNO; 00461 break; 00462 case OptionYesNoCancel: 00463 Type = MB_YESNOCANCEL; 00464 break; 00465 case OptionShutdownSystem: 00466 Type = MB_RETRYCANCEL; // FIXME??? 00467 break; 00468 /* Anything else is invalid */ 00469 default: 00470 return ResponseNotHandled; 00471 } 00472 00473 /* Set severity */ 00474 if (Severity == STATUS_SEVERITY_INFORMATIONAL) Type |= MB_ICONINFORMATION; 00475 else if (Severity == STATUS_SEVERITY_WARNING) Type |= MB_ICONWARNING; 00476 else if (Severity == STATUS_SEVERITY_ERROR) Type |= MB_ICONERROR; 00477 00478 Type |= MB_SYSTEMMODAL | MB_SETFOREGROUND; 00479 00480 DPRINT("Text = '%S', Caption = '%S', Severity = %d, Type = 0x%lx\n", 00481 Text, Caption, Severity, Type); 00482 00483 /* Display a message box */ 00484 MessageBoxResponse = MessageBoxW(0, Text, Caption, Type); 00485 00486 /* Return response value */ 00487 switch (MessageBoxResponse) 00488 { 00489 case IDOK: return ResponseOk; 00490 case IDCANCEL: return ResponseCancel; 00491 case IDYES: return ResponseYes; 00492 case IDNO: return ResponseNo; 00493 case IDABORT: return ResponseAbort; 00494 case IDIGNORE: return ResponseIgnore; 00495 case IDRETRY: return ResponseRetry; 00496 case IDTRYAGAIN: return ResponseTryAgain; 00497 case IDCONTINUE: return ResponseContinue; 00498 } 00499 00500 return ResponseNotHandled; 00501 } 00502 00503 VOID 00504 WINAPI 00505 Win32CsrHardError( 00506 IN PCSR_THREAD ThreadData, 00507 IN PHARDERROR_MSG Message) 00508 { 00509 #if DBG 00510 PCSR_PROCESS ProcessData = ThreadData->Process; 00511 #endif 00512 ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS]; 00513 OBJECT_ATTRIBUTES ObjectAttributes; 00514 UNICODE_STRING TextU, CaptionU; 00515 NTSTATUS Status; 00516 HANDLE hProcess; 00517 ULONG Size; 00518 00519 /* Default to not handled */ 00520 ASSERT(ProcessData != NULL); 00521 Message->Response = ResponseNotHandled; 00522 00523 /* Make sure we don't have too many parameters */ 00524 if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS) 00525 Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS; 00526 00527 /* Initialize object attributes */ 00528 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00529 00530 /* Open client process */ 00531 Status = NtOpenProcess(&hProcess, 00532 PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 00533 &ObjectAttributes, 00534 &Message->h.ClientId); 00535 00536 if (!NT_SUCCESS(Status)) 00537 { 00538 DPRINT1("NtOpenProcess failed with code: %lx\n", Status); 00539 return; 00540 } 00541 00542 /* Capture all string parameters from the process memory */ 00543 Status = CsrpCaptureStringParameters(Parameters, &Size, Message, hProcess); 00544 if (!NT_SUCCESS(Status)) 00545 { 00546 NtClose(hProcess); 00547 return; 00548 } 00549 00550 /* Format the caption and message box text */ 00551 Status = CsrpFormatMessages(&TextU, 00552 &CaptionU, 00553 Parameters, 00554 Size, 00555 Message, 00556 hProcess); 00557 00558 /* Cleanup */ 00559 CsrpFreeStringParameters(Parameters, Message); 00560 NtClose(hProcess); 00561 00562 if (!NT_SUCCESS(Status)) 00563 { 00564 return; 00565 } 00566 00567 /* Display the message box */ 00568 Message->Response = CsrpMessageBox(TextU.Buffer, 00569 CaptionU.Buffer, 00570 Message->ValidResponseOptions, 00571 (ULONG)Message->Status >> 30); 00572 00573 RtlFreeUnicodeString(&TextU); 00574 RtlFreeUnicodeString(&CaptionU); 00575 00576 return; 00577 } 00578 Generated on Sun May 27 2012 04:38:45 for ReactOS by
1.7.6.1
|