ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

harderror.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.