00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
#include "ntlpcapi.h"
00015
00016
#include <winsta.h>
00017 extern BOOLEAN
gbExitInProgress;
00018 BOOL gfTimedOut =
FALSE;
00019
00020
VOID UserHardErrorEx(
00021 PCSR_THREAD pt,
00022 PHARDERROR_MSG pmsg,
00023
PCTXHARDERRORINFO pCtxHEInfo);
00024
00025
VOID UserExitWorkerThread(VOID);
00026
00027
VOID ProcessHardErrorRequest(
00028 BOOL fNewThread);
00029
00030
00031 CONST
UINT wIcons[] = {
00032 0,
00033 MB_ICONINFORMATION,
00034 MB_ICONEXCLAMATION,
00035 MB_ICONSTOP
00036 };
00037 CONST
UINT wOptions[] = {
00038 MB_ABORTRETRYIGNORE,
00039 MB_OK,
00040 MB_OKCANCEL,
00041 MB_RETRYCANCEL,
00042 MB_YESNO,
00043 MB_YESNOCANCEL,
00044 MB_OK,
00045 MB_OK,
00046 MB_CANCELTRYCONTINUE
00047 };
00048 CONST
DWORD dwResponses[] = {
00049 ResponseNotHandled,
00050 ResponseOk,
00051 ResponseCancel,
00052 ResponseAbort,
00053 ResponseRetry,
00054 ResponseIgnore,
00055 ResponseYes,
00056 ResponseNo,
00057 ResponseNotHandled,
00058 ResponseNotHandled,
00059 ResponseTryAgain,
00060 ResponseContinue
00061 };
00062 CONST
DWORD dwResponseDefault[] = {
00063 ResponseAbort,
00064 ResponseOk,
00065 ResponseOk,
00066 ResponseCancel,
00067 ResponseYes,
00068 ResponseYes,
00069 ResponseOk,
00070 ResponseOk,
00071 ResponseCancel
00072 };
00073
00074
00075
00076
00077 static UINT_PTR
gTimerId = 0;
00078
00079
00080
00081
00082
VOID HardErrorInsert(PCSR_THREAD, PHARDERROR_MSG,
PCTXHARDERRORINFO);
00083
VOID HardErrorRemove(
PCTXHARDERRORINFO);
00084
00085 FARPROC
gfnRegisterEventSource;
00086 FARPROC
gfnDeregisterEventSource;
00087 FARPROC
gfnReportEvent;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 HANDLE
00099 UserRegisterEventSource(
00100 PCWSTR pwszSourceName)
00101 {
00102
00103
00104
00105
if (
gfnRegisterEventSource ==
NULL) {
00106 HINSTANCE hAdvApiDll;
00107 FARPROC fnRegisterEventSource;
00108 FARPROC fnDeregisterEventSource;
00109 FARPROC fnReportEvent;
00110
00111
00112
00113
00114
if ((hAdvApiDll = LoadLibrary(
L"advapi32.dll")) ==
NULL) {
00115
return NULL;
00116 }
00117 fnRegisterEventSource = GetProcAddress(hAdvApiDll,
"RegisterEventSourceW");
00118 fnDeregisterEventSource = GetProcAddress(hAdvApiDll,
"DeregisterEventSource");
00119 fnReportEvent = GetProcAddress(hAdvApiDll,
"ReportEventW");
00120
if (!fnRegisterEventSource || !fnDeregisterEventSource || !fnReportEvent) {
00121 FreeLibrary(hAdvApiDll);
00122
return NULL;
00123 }
00124
00125
00126
00127
00128
EnterCrit();
00129
if (
gfnRegisterEventSource ==
NULL) {
00130
gfnReportEvent = fnReportEvent;
00131
gfnDeregisterEventSource = fnDeregisterEventSource;
00132
00133
gfnRegisterEventSource = fnRegisterEventSource;
00134 hAdvApiDll =
NULL;
00135 }
00136
LeaveCrit();
00137
00138
00139
00140
00141
if (hAdvApiDll) {
00142 FreeLibrary(hAdvApiDll);
00143 }
00144 }
00145
00146
00147
00148
00149 UserAssert(
gfnRegisterEventSource !=
NULL);
00150 UserAssert(
gfnDeregisterEventSource !=
NULL);
00151 UserAssert(
gfnReportEvent !=
NULL);
00152
00153
00154
00155
00156
return (HANDLE)
gfnRegisterEventSource(
NULL, pwszSourceName);
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
VOID
00166 LogErrorPopup(
00167 IN LPWSTR Caption,
00168 IN LPWSTR Message
00169 )
00170 {
00171
00172 LPWSTR lps[2];
00173
00174 lps[0] = Caption;
00175 lps[1] = Message;
00176
00177 UserAssert(
gEventSource !=
NULL);
00178
gfnReportEvent(
gEventSource, EVENTLOG_INFORMATION_TYPE, 0,
00179 STATUS_LOG_HARD_ERROR,
NULL,
sizeof(lps) /
sizeof(*lps),
00180 0, lps,
NULL);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 static WCHAR
wszDosDevices[] =
L"\\??\\A:";
00190
VOID
00191 SubstituteDeviceName(
00192 PUNICODE_STRING InputDeviceName,
00193 LPSTR OutputDriveLetter
00194 )
00195 {
00196 UNICODE_STRING LinkName;
00197 UNICODE_STRING DeviceName;
00198 OBJECT_ATTRIBUTES Obja;
00199 HANDLE LinkHandle;
00200
NTSTATUS Status;
00201 ULONG i;
00202 PWCHAR p;
00203 WCHAR DeviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
00204
00205
RtlInitUnicodeString(&LinkName,
wszDosDevices);
00206 p =
wszDosDevices +
ARRAY_SIZE(
wszDosDevices) -
ARRAY_SIZE(
L"A:");
00207
for(i=0;i<26;i++){
00208 *p = (WCHAR)(
'A' + i);
00209
00210 InitializeObjectAttributes(
00211 &Obja,
00212 &LinkName,
00213 OBJ_CASE_INSENSITIVE,
00214
NULL,
00215
NULL
00216 );
00217
Status =
NtOpenSymbolicLinkObject(
00218 &LinkHandle,
00219 SYMBOLIC_LINK_QUERY,
00220 &Obja
00221 );
00222
if (
NT_SUCCESS(
Status )) {
00223
00224
00225
00226
00227
00228 DeviceName.Length = 0;
00229 DeviceName.MaximumLength =
sizeof(DeviceNameBuffer);
00230 DeviceName.Buffer = DeviceNameBuffer;
00231
00232
Status =
NtQuerySymbolicLinkObject(
00233 LinkHandle,
00234 &DeviceName,
00235
NULL
00236 );
00237
NtClose(LinkHandle);
00238
if (
NT_SUCCESS(
Status) ) {
00239
if (
RtlEqualUnicodeString(InputDeviceName,&DeviceName,
TRUE) ) {
00240 OutputDriveLetter[0]=(
CHAR)(
'A'+i);
00241 OutputDriveLetter[1]=
':';
00242 OutputDriveLetter[2]=
'\0';
00243
return;
00244 }
00245 }
00246 }
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255 DWORD GetErrorMode(VOID)
00256 {
00257 HANDLE hKey;
00258 UNICODE_STRING UnicodeString;
00259 OBJECT_ATTRIBUTES OA;
00260 LONG
Status;
00261
BYTE Buf[
sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
sizeof(
DWORD)];
00262
DWORD cbSize;
00263
DWORD dwRet = 0;
00264
00265
RtlInitUnicodeString(&UnicodeString,
00266
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows");
00267 InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE,
NULL,
NULL);
00268
00269
Status =
NtOpenKey(&hKey, KEY_READ, &OA);
00270
if (
NT_SUCCESS(
Status)) {
00271
RtlInitUnicodeString(&UnicodeString,
L"ErrorMode");
00272
Status =
NtQueryValueKey(hKey,
00273 &UnicodeString,
00274 KeyValuePartialInformation,
00275 (PKEY_VALUE_PARTIAL_INFORMATION)Buf,
00276
sizeof(Buf),
00277 &cbSize);
00278
if (
NT_SUCCESS(
Status)) {
00279 dwRet = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)Buf)->Data);
00280 }
00281
NtClose(hKey);
00282 }
00283
return dwRet;
00284 }
00285
00286
00287
00288
00289
00290
00291 void FreePhi (
PHARDERRORINFO phi)
00292 {
00293
if (phi->
dwHEIFFlags &
HEIF_ALLOCATEDMSG) {
00294 LocalFree(phi->
pmsg);
00295 }
00296
00297
RtlFreeUnicodeString(&phi->
usText);
00298
RtlFreeUnicodeString(&phi->
usCaption);
00299
00300 LocalFree(phi);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310 void ReplyHardError (
PHARDERRORINFO phi, DWORD dwResponse)
00311 {
00312 phi->
pmsg->Response = dwResponse;
00313
00314
00315
00316
00317
if (phi->
hEventHardError !=
NULL) {
00318
NtSetEvent(phi->
hEventHardError,
NULL);
00319 }
else if (!(phi->
dwHEIFFlags &
HEIF_REPLIED)) {
00320
NtReplyPort(((PCSR_THREAD)phi->
pthread)->Process->ClientPort,
00321 (PPORT_MESSAGE)phi->
pmsg);
00322 }
00323
00324
00325
00326
00327
if (phi->
dwHEIFFlags &
HEIF_DEREFTHREAD) {
00328 CsrDereferenceThread(phi->
pthread);
00329 }
00330
00331
00332
00333
FreePhi(phi);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 void CheckDefaultDesktop(
void)
00348 {
00349
PHARDERRORINFO phi;
00350
00351
if (HEC_WRONGDESKTOP ==
NtUserHardErrorControl(HardErrorInDefDesktop,
NULL,
NULL)) {
00352
return;
00353 }
00354
00355
EnterCrit();
00356 phi =
gphiList;
00357
while (phi !=
NULL) {
00358 phi->
dwHEIFFlags &= ~
HEIF_WRONGDESKTOP;
00359 phi = phi->
phiNext;
00360 }
00361
LeaveCrit();
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
VOID
00383 MsgBoxTimerFunc(
00384 HWND hWnd,
00385 UINT MessageType,
00386 UINT_PTR idEvent,
00387 DWORD TimeWhenCalled
00388 )
00389 {
00390
BOOL RetVal;
00391
00392 RIPMSG0(RIP_WARNING,
"MsgBoxTimerFunc: timer poped");
00393
00394
00395
00396
00397
if (
gdwHardErrorThreadId != 0 ) {
00398
gfTimedOut =
TRUE;
00399 RetVal =
PostThreadMessage(
gdwHardErrorThreadId, WM_QUIT, 0, 0);
00400 }
00401
00402
if(- !RetVal ) {
00403 RIPMSG0(RIP_WARNING,
"MsgBoxTimerFunc: PostMessageFailed");
00404 }
00405
00406 UNREFERENCED_PARAMETER(
hWnd);
00407 UNREFERENCED_PARAMETER(MessageType);
00408 UNREFERENCED_PARAMETER(idEvent);
00409 UNREFERENCED_PARAMETER(TimeWhenCalled);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 void GetHardErrorText (
PHARDERRORINFO phi)
00424 {
00425
static WCHAR wszUnkownSoftwareException [] =
L"unknown software exception";
00426
static WCHAR wszException [] =
L"{EXCEPTION}";
00427
static WCHAR wszUnknownHardError [] =
L"Unknown Hard Error";
00428 ANSI_STRING asLocal, asMessage;
00429
BOOL fFreeAppNameBuffer, fFreeCaption;
00430
BOOL fResAllocated, fResAllocated1, fErrorIsFromSystem;
00431 WCHAR wszErrorMessage[WSPRINTF_LIMIT + 1];
00432
DWORD dwCounter, dwStringsToFreeMask, dwMBFlags;
00433 ULONG_PTR adwParameterVector[MAXIMUM_HARDERROR_PARAMETERS];
00434 HANDLE hClientProcess;
00435 HWND hwndOwner;
00436
NTSTATUS Status;
00437 PHARDERROR_MSG phemsg;
00438 PMESSAGE_RESOURCE_ENTRY MessageEntry;
00439 PWSTR pwszCaption, pwszFormatString;
00440 PWSTR pwszAppName, pwszResBuffer, pwszResBuffer1;
00441 PWSTR pwszMsg, pwszTitle, pwszFullCaption;
00442
UINT uMsgLen, uCaptionLen, uTitleLen;
00443 UNICODE_STRING usScratch, usLocal, usMessage, usCaption;
00444
00445
00446
00447
00448 fFreeAppNameBuffer = fFreeCaption =
FALSE;
00449 hClientProcess =
NULL;
00450
RtlInitUnicodeString(&usCaption,
NULL);
00451
RtlInitUnicodeString(&usMessage,
NULL);
00452
00453
00454
00455 phemsg = phi->
pmsg;
00456 phemsg->Response = ResponseNotHandled;
00457
00458
00459
00460
00461 UserAssert(phemsg->NumberOfParameters <= MAXIMUM_HARDERROR_PARAMETERS);
00462 RtlCopyMemory(adwParameterVector, phemsg->Parameters, phemsg->NumberOfParameters *
sizeof(*phemsg->Parameters));
00463 dwCounter = phemsg->NumberOfParameters;
00464
while (dwCounter < MAXIMUM_HARDERROR_PARAMETERS) {
00465 adwParameterVector[dwCounter++] = (ULONG_PTR)
L"";
00466 }
00467
00468
00469
00470
00471 hClientProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
00472
FALSE, HandleToUlong(phemsg->h.ClientId.UniqueProcess));
00473 fErrorIsFromSystem = (hClientProcess ==
NULL);
00474
00475
00476
00477
00478
00479 dwStringsToFreeMask = 0;
00480
if (phemsg->UnicodeStringParameterMask) {
00481
00482
for (dwCounter = 0; dwCounter < phemsg->NumberOfParameters; dwCounter++) {
00483
00484
00485
00486
if (!(phemsg->UnicodeStringParameterMask & (1 << dwCounter))) {
00487
continue;
00488 }
00489
00490
00491
00492
00493 adwParameterVector[dwCounter] = (ULONG_PTR)
L"";
00494
if (hClientProcess ==
NULL) {
00495
continue;
00496 }
00497
00498
Status =
NtReadVirtualMemory(hClientProcess,
00499 (PVOID)phemsg->Parameters[dwCounter],
00500 (PVOID)&usScratch,
00501
sizeof(usScratch),
NULL);
00502
00503
if (!
NT_SUCCESS(
Status)) {
00504 RIPMSG0(RIP_WARNING,
"Failed to read error string struct!");
00505
continue;
00506 }
00507
00508 usLocal = usScratch;
00509 usLocal.Buffer = (PWSTR)LocalAlloc(
LMEM_ZEROINIT, usLocal.Length +
sizeof(UNICODE_NULL));
00510
if (usLocal.Buffer ==
NULL) {
00511 RIPMSG0(RIP_WARNING,
"Failed to alloc string buffer!");
00512
continue;
00513 }
00514
00515
Status =
NtReadVirtualMemory(hClientProcess,
00516 (PVOID)usScratch.Buffer,
00517 (PVOID)usLocal.Buffer,
00518 usLocal.Length,
00519
NULL);
00520
00521
if (!
NT_SUCCESS(
Status)) {
00522 LocalFree(usLocal.Buffer);
00523 RIPMSG0(RIP_WARNING,
"Failed to read error string!");
00524
continue;
00525 }
00526
00527 usLocal.MaximumLength = usLocal.Length;
00528
Status =
RtlUnicodeStringToAnsiString(&asLocal, &usLocal,
TRUE);
00529
if (!
NT_SUCCESS(
Status)) {
00530 LocalFree(usLocal.Buffer);
00531 RIPMSG0(RIP_WARNING,
"Failed to translate error string!");
00532
continue;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
if (strstr(asLocal.Buffer,
"\\Device") == asLocal.Buffer) {
00542
SubstituteDeviceName(&usLocal,asLocal.Buffer);
00543 }
else if ((asLocal.Length > 4) && !_strnicmp(asLocal.Buffer,
"\\??\\", 4)) {
00544 strcpy( asLocal.Buffer, asLocal.Buffer+4 );
00545 asLocal.Length -= 4;
00546 }
else {
00547
00548
00549
00550
00551
00552
switch (phemsg->Status) {
00553
case STATUS_SERVICE_NOTIFICATION:
00554
case STATUS_VDM_HARD_ERROR:
00555 adwParameterVector[dwCounter] = (ULONG_PTR)usLocal.Buffer;
00556
RtlFreeAnsiString(&asLocal);
00557
continue;
00558 }
00559
00560 }
00561
00562 LocalFree(usLocal.Buffer);
00563
00564 dwStringsToFreeMask |= (1 << dwCounter);
00565 adwParameterVector[dwCounter] = (ULONG_PTR)asLocal.Buffer;
00566
00567 }
00568
00569 }
00570
00571
00572
00573
00574
#if (HARDERROR_PARAMETERS_FLAGSPOS >= MAXIMUM_HARDERROR_PARAMETERS)
00575
#error Invalid HARDERROR_PARAMETERS_FLAGSPOS value.
00576
#endif
00577
#if (HARDERROR_FLAGS_DEFDESKTOPONLY != MB_DEFAULT_DESKTOP_ONLY)
00578
#error Invalid HARDERROR_FLAGS_DEFDESKTOPONLY
00579
#endif
00580
dwMBFlags = 0;
00581
if (phemsg->NumberOfParameters > HARDERROR_PARAMETERS_FLAGSPOS) {
00582
00583
00584
00585 UserAssert(!(adwParameterVector[HARDERROR_PARAMETERS_FLAGSPOS] & ~MB_DEFAULT_DESKTOP_ONLY));
00586
if (adwParameterVector[HARDERROR_PARAMETERS_FLAGSPOS] & MB_DEFAULT_DESKTOP_ONLY) {
00587 dwMBFlags |= MB_DEFAULT_DESKTOP_ONLY;
00588 }
00589 }
00590
00591
00592
00593
switch (phemsg->Status) {
00594
case STATUS_SERVICE_NOTIFICATION:
00595
if (phemsg->UnicodeStringParameterMask & 0x1) {
00596
RtlInitUnicodeString(&usMessage, (PWSTR)adwParameterVector[0]);
00597 }
else {
00598
RtlInitAnsiString(&asMessage, (PSTR)adwParameterVector[0]);
00599
RtlAnsiStringToUnicodeString(&usMessage, &asMessage,
TRUE);
00600 }
00601
00602
if (phemsg->UnicodeStringParameterMask & 0x2) {
00603
RtlInitUnicodeString(&usCaption, (PWSTR)adwParameterVector[1]);
00604 }
else {
00605
RtlInitAnsiString(&asMessage, (PSTR)adwParameterVector[1]);
00606
RtlAnsiStringToUnicodeString(&usCaption, &asMessage,
TRUE);
00607 }
00608
00609 dwMBFlags = (
DWORD)adwParameterVector[2] & ~MB_SERVICE_NOTIFICATION;
00610
goto CleanUpAndSaveParams;
00611
00612
case STATUS_VDM_HARD_ERROR:
00613
00614
00615
00616
00617
00618
00619 phi->
dwHEIFFlags |=
HEIF_VDMERROR;
00620
00621
00622
00623 phi->
dwVDMParam0 = (
DWORD)adwParameterVector[0];
00624 phi->
dwVDMParam1 = (
DWORD)adwParameterVector[1];
00625
00626
00627
00628
try {
00629
if (phemsg->UnicodeStringParameterMask & 0x4) {
00630
RtlInitUnicodeString(&usCaption, (PWSTR)adwParameterVector[2]);
00631 }
else {
00632 MBToWCS((LPSTR)adwParameterVector[2], -1, &pwszTitle, -1,
TRUE);
00633
RtlCreateUnicodeString(&usCaption, pwszTitle);
00634
RtlFreeHeap(RtlProcessHeap(), 0, pwszTitle);
00635 }
00636
00637
if (phemsg->UnicodeStringParameterMask & 0x8) {
00638
RtlInitUnicodeString(&usMessage, (PWSTR)adwParameterVector[3]);
00639 }
else {
00640 MBToWCS((LPSTR)adwParameterVector[3], -1, &pwszMsg, -1,
TRUE);
00641
RtlCreateUnicodeString(&usMessage, pwszMsg);
00642
RtlFreeHeap(RtlProcessHeap(), 0, pwszMsg);
00643 }
00644
00645
00646 } except (
EXCEPTION_EXECUTE_HANDLER) {
00647
00648 RIPMSG0(RIP_WARNING,
"Exception reading STATUS_VDM_HARD_ERROR paramerters");
00649
00650
RtlFreeUnicodeString(&usCaption);
00651
RtlCreateUnicodeString(&usCaption,
L"VDM Internal Error");
00652
RtlFreeUnicodeString(&usMessage);
00653
RtlCreateUnicodeString(&usMessage,
L"Exception retrieving error text.");
00654 }
00655
goto CleanUpAndSaveParams;
00656 }
00657
00658
00659
00660
00661
00662 dwMBFlags |=
wIcons[(ULONG)(phemsg->Status) >> 30] |
wOptions[phemsg->ValidResponseOptions];
00663
00664
00665
00666
00667
00668 pwszAppName =
NULL;
00669
if (!fErrorIsFromSystem) {
00670 PPEB Peb;
00671 PROCESS_BASIC_INFORMATION BasicInfo;
00672 PLDR_DATA_TABLE_ENTRY LdrEntry;
00673 LDR_DATA_TABLE_ENTRY LdrEntryData;
00674 PLIST_ENTRY LdrHead, LdrNext;
00675 PPEB_LDR_DATA Ldr;
00676 PVOID ImageBaseAddress;
00677 PWSTR ClientApplicationName;
00678
00679
00680
00681
00682
00683
00684
00685
Status =
NtQueryInformationProcess(hClientProcess, ProcessBasicInformation,
00686 &BasicInfo,
sizeof(BasicInfo),
NULL);
00687
00688
if (!
NT_SUCCESS(
Status)) {
00689 fErrorIsFromSystem =
TRUE;
00690
goto noname;
00691 }
00692
00693 Peb = BasicInfo.PebBaseAddress;
00694
if (Peb ==
NULL) {
00695 fErrorIsFromSystem =
TRUE;
00696
goto noname;
00697 }
00698
00699
00700
00701
00702
Status =
NtReadVirtualMemory(hClientProcess, &Peb->Ldr, &Ldr,
00703
sizeof(Ldr),
NULL);
00704
00705
if (!
NT_SUCCESS(
Status)) {
00706
goto noname;
00707 }
00708
00709 LdrHead = &Ldr->InLoadOrderModuleList;
00710
00711
00712
00713
00714
Status =
NtReadVirtualMemory(hClientProcess, &LdrHead->Flink,
00715 &LdrNext,
sizeof(LdrNext),
NULL );
00716
00717
if (!
NT_SUCCESS(
Status)) {
00718
goto noname;
00719 }
00720
00721
if (LdrNext == LdrHead) {
00722
goto noname;
00723 }
00724
00725
00726
00727 LdrEntry = CONTAINING_RECORD(LdrNext, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
00728
Status =
NtReadVirtualMemory(hClientProcess, LdrEntry,
00729 &LdrEntryData,
sizeof(LdrEntryData),
NULL);
00730
00731
if (!
NT_SUCCESS(
Status)) {
00732
goto noname;
00733 }
00734
00735
Status =
NtReadVirtualMemory(hClientProcess, &Peb->ImageBaseAddress,
00736 &ImageBaseAddress,
sizeof(ImageBaseAddress),
NULL);
00737
00738
if (!
NT_SUCCESS(
Status)) {
00739
goto noname;
00740 }
00741
00742
if (ImageBaseAddress != LdrEntryData.DllBase) {
00743
goto noname;
00744 }
00745
00746 LdrNext = LdrEntryData.InLoadOrderLinks.Flink;
00747
00748 ClientApplicationName = (PWSTR)LocalAlloc(
LMEM_ZEROINIT, LdrEntryData.BaseDllName.MaximumLength);
00749
if (ClientApplicationName ==
NULL) {
00750
goto noname;
00751 }
00752
00753
Status =
NtReadVirtualMemory(hClientProcess, LdrEntryData.BaseDllName.Buffer,
00754 ClientApplicationName, LdrEntryData.BaseDllName.MaximumLength,
00755
NULL);
00756
00757
if (!
NT_SUCCESS(
Status)) {
00758 LocalFree(ClientApplicationName);
00759
goto noname;
00760 }
00761
00762 pwszAppName = ClientApplicationName;
00763 fFreeAppNameBuffer =
TRUE;
00764
00765 noname:;
00766 }
00767
00768
if (pwszAppName ==
NULL) {
00769
00770
00771
00772 pwszAppName =
ServerLoadString(
ghModuleWin, STR_UNKNOWN_APPLICATION,
00773
L"System Process", &fFreeAppNameBuffer);
00774 }
00775
00776
00777
00778
00779
00780
00781
EnterCrit();
00782
if (
gNtDllHandle ==
NULL) {
00783
gNtDllHandle = GetModuleHandle(TEXT(
"ntdll"));
00784 UserAssert(
gNtDllHandle !=
NULL);
00785 }
00786
LeaveCrit();
00787
00788
Status =
RtlFindMessage((PVOID)
gNtDllHandle, (ULONG_PTR)RT_MESSAGETABLE,
00789 LANG_NEUTRAL, phemsg->Status, &MessageEntry);
00790
00791
00792
00793
00794 pwszCaption =
NULL;
00795
if (!
NT_SUCCESS(
Status)) {
00796 pwszFormatString = wszUnknownHardError;
00797 }
else {
00798 pwszFormatString = (PWSTR)MessageEntry->Text;
00799
00800
00801
00802
if (*pwszFormatString ==
L'{') {
00803 uCaptionLen = 0;
00804 pwszFormatString++;
00805
00806
00807
00808
while ((*pwszFormatString != (WCHAR)0) && (*pwszFormatString++ !=
L'}')) {
00809 uCaptionLen++;
00810 }
00811
00812
00813
00814
while ((*pwszFormatString != (WCHAR)0) && (*pwszFormatString <=
L' ')) {
00815 pwszFormatString++;
00816 }
00817
00818
00819
00820
if ((uCaptionLen++ > 0)
00821 && ((pwszCaption = (PWSTR)LocalAlloc(LPTR, uCaptionLen *
sizeof(WCHAR))) !=
NULL)) {
00822
00823 RtlCopyMemory(pwszCaption, (PWSTR)MessageEntry->Text + 1, (uCaptionLen - 1) *
sizeof(WCHAR));
00824 fFreeCaption =
TRUE;
00825 }
00826 }
00827
00828
if (*pwszFormatString == (WCHAR)0) {
00829 pwszFormatString = wszUnknownHardError;
00830 }
00831 }
00832
00833
00834
00835
00836
00837
00838
if (pwszCaption ==
NULL) {
00839
switch (phemsg->Status & ERROR_SEVERITY_ERROR) {
00840
case ERROR_SEVERITY_SUCCESS:
00841 pwszCaption =
gpwszaSUCCESS;
00842
break;
00843
case ERROR_SEVERITY_INFORMATIONAL:
00844 pwszCaption =
gpwszaSYSTEM_INFORMATION;
00845
break;
00846
case ERROR_SEVERITY_WARNING:
00847 pwszCaption =
gpwszaSYSTEM_WARNING;
00848
break;
00849
case ERROR_SEVERITY_ERROR:
00850 pwszCaption =
gpwszaSYSTEM_ERROR;
00851
break;
00852 }
00853 }
00854 UserAssert(pwszCaption !=
NULL);
00855
00856
00857
00858
00859 hwndOwner =
NULL;
00860
EnumThreadWindows(HandleToUlong(phemsg->h.ClientId.UniqueThread),
00861
FindWindowFromThread, (LPARAM)&hwndOwner);
00862
if (hwndOwner ==
NULL) {
00863 uTitleLen = 0;
00864 }
else {
00865 uTitleLen =
GetWindowTextLength(hwndOwner);
00866
if (uTitleLen != 0) {
00867 pwszTitle = (PWSTR)LocalAlloc(LPTR, (uTitleLen + 3) *
sizeof(WCHAR));
00868
if (pwszTitle !=
NULL) {
00869
GetWindowText(hwndOwner, pwszTitle, uTitleLen + 1);
00870
00871
00872
00873 *(pwszTitle + uTitleLen++) = (WCHAR)
':';
00874 *(pwszTitle + uTitleLen++) = (WCHAR)
' ';
00875 }
else {
00876
00877
00878
00879 uTitleLen = 0;
00880 }
00881 }
00882 }
00883
00884
00885
00886
00887
if (uTitleLen == 0) {
00888 pwszTitle =
L"";
00889 }
00890
00891
00892
00893
00894 uCaptionLen = uTitleLen + wcslen(pwszAppName) + 3 + wcslen(pwszCaption) + 1;
00895 pwszFullCaption = (PWSTR)LocalAlloc(LPTR, uCaptionLen *
sizeof(WCHAR));
00896
if (pwszFullCaption !=
NULL) {
00897
#if DBG
00898
int iLen =
00899
#endif
00900
wsprintfW(pwszFullCaption,
L"%s%s - %s", pwszTitle, pwszAppName, pwszCaption);
00901 UserAssert((
UINT)iLen < uCaptionLen);
00902
RtlCreateUnicodeString(&usCaption, pwszFullCaption);
00903 LocalFree(pwszFullCaption);
00904 }
00905
00906
00907
00908
if (fFreeCaption) {
00909 LocalFree(pwszCaption);
00910 }
00911
if (fFreeAppNameBuffer) {
00912 LocalFree(pwszAppName);
00913 }
00914
if (uTitleLen != 0) {
00915 LocalFree(pwszTitle);
00916 }
00917
00918
00919
00920
00921
if (phemsg->Status == STATUS_UNHANDLED_EXCEPTION ) {
00922
00923
00924
00925
00926
00927
Status =
RtlFindMessage( (PVOID)
gNtDllHandle, (ULONG_PTR)RT_MESSAGETABLE,
00928 LANG_NEUTRAL, (ULONG)adwParameterVector[0], &MessageEntry);
00929
00930
if (!
NT_SUCCESS(
Status)) {
00931
00932
00933
00934 pwszResBuffer =
ServerLoadString(
ghModuleWin, STR_UNKNOWN_EXCEPTION,
00935 wszUnkownSoftwareException, &fResAllocated);
00936
00937
wsprintfW(wszErrorMessage, pwszFormatString, pwszResBuffer,
00938 adwParameterVector[0], adwParameterVector[1]);
00939
00940
if (fResAllocated) {
00941 LocalFree(pwszResBuffer);
00942 }
00943
00944
RtlCreateUnicodeString(&usMessage, wszErrorMessage);
00945 UserAssert(usMessage.MaximumLength <=
sizeof(wszErrorMessage));
00946
00947 }
else {
00948
00949
00950
00951
00952
if (adwParameterVector[0] == STATUS_ACCESS_VIOLATION ) {
00953
00954
wsprintfW(wszErrorMessage, (PWSTR)MessageEntry->Text, adwParameterVector[1],
00955 adwParameterVector[3], adwParameterVector[2] ?
L"written" :
L"read");
00956
00957 }
else if (adwParameterVector[0] == STATUS_IN_PAGE_ERROR) {
00958
wsprintfW(wszErrorMessage, (PWSTR)MessageEntry->Text, adwParameterVector[1],
00959 adwParameterVector[3], adwParameterVector[2]);
00960
00961 }
else {
00962
00963
00964
00965
00966 pwszCaption = (PWSTR)MessageEntry->Text;
00967
if (!wcsncmp(pwszCaption, wszException,
ARRAY_SIZE(wszException) - 1)) {
00968 pwszCaption +=
ARRAY_SIZE(wszException) - 1;
00969
00970
00971
00972
while ((*pwszCaption != (WCHAR)0) && (*pwszCaption <=
L' ')) {
00973 pwszCaption++;
00974 }
00975
00976 }
else {
00977 pwszCaption = wszUnkownSoftwareException;
00978 }
00979
00980
wsprintfW(wszErrorMessage, pwszFormatString, pwszCaption,
00981 adwParameterVector[0], adwParameterVector[1]);
00982 }
00983
00984 UserAssert(wcslen(wszErrorMessage) <
ARRAY_SIZE(wszErrorMessage));
00985
00986
00987
00988
00989 pwszResBuffer =
ServerLoadString(
ghModuleWin, STR_OK_TO_TERMINATE,
00990
L"Click on OK to terminate the application",
00991 &fResAllocated);
00992
00993
00994
if (phemsg->ValidResponseOptions == OptionOkCancel ) {
00995 pwszResBuffer1 =
ServerLoadString(
ghModuleWin,
00996 STR_CANCEL_TO_DEBUG,
L"Click on CANCEL xx to debug the application",
00997 &fResAllocated1);
00998 }
else {
00999 pwszResBuffer1 =
NULL;
01000 fResAllocated1 =
FALSE;
01001 }
01002
01003
01004
01005
01006 uMsgLen = wcslen(wszErrorMessage)
01007 + wcslen(pwszResBuffer) + 1
01008 + (pwszResBuffer1 ==
NULL ? 0 : wcslen(pwszResBuffer1) + 1)
01009 + 1;
01010
01011 pwszMsg = (PWSTR) LocalAlloc(LPTR, uMsgLen *
sizeof(WCHAR));
01012
if (pwszMsg !=
NULL) {
01013
#if DBG
01014
int iLen =
01015
#endif
01016
wsprintfW(pwszMsg,
L"%s\n%s%s%s", wszErrorMessage, pwszResBuffer,
01017 (pwszResBuffer1 ==
NULL ?
L"" :
L"\n"),
01018 (pwszResBuffer1 ==
NULL ?
L"" : pwszResBuffer1));
01019
01020 UserAssert((
UINT)iLen < uMsgLen);
01021
01022
RtlCreateUnicodeString(&usMessage, pwszMsg);
01023 LocalFree(pwszMsg);
01024 }
01025
01026
01027
01028
01029
if (fResAllocated) {
01030 LocalFree(pwszResBuffer);
01031 }
01032
01033
if (fResAllocated1) {
01034 LocalFree(pwszResBuffer1);
01035 }
01036
01037
01038 }
01039
01040 }
else {
01041
01042
01043
01044
try {
01045
#if DBG
01046
int iLen =
01047
#endif
01048
wsprintfW(wszErrorMessage, pwszFormatString, adwParameterVector[0],
01049 adwParameterVector[1],
01050 adwParameterVector[2],
01051 adwParameterVector[3]);
01052 UserAssert((
UINT)iLen <
ARRAY_SIZE(wszErrorMessage));
01053
01054
01055
01056
01057 pwszFormatString = wszErrorMessage;
01058
while (*pwszFormatString != (WCHAR)0) {
01059
if (*pwszFormatString == (WCHAR)0xd) {
01060 *pwszFormatString =
L' ';
01061
01062
01063
01064
if (*(pwszFormatString+1) == (WCHAR)0xa) {
01065
UINT uSize = (wcslen(pwszFormatString+1) + 1) *
sizeof(WCHAR);
01066 RtlMoveMemory(pwszFormatString, pwszFormatString+1, uSize);
01067 }
01068 }
01069
01070
if (*pwszFormatString == (WCHAR)0xa) {
01071 *pwszFormatString =
L' ';
01072 }
01073
01074 pwszFormatString++;
01075 }
01076
01077
RtlCreateUnicodeString(&usMessage, wszErrorMessage);
01078 UserAssert(usMessage.MaximumLength <=
sizeof(wszErrorMessage));
01079 } except(
EXCEPTION_EXECUTE_HANDLER) {
01080
01081
wsprintfW(wszErrorMessage,
L"Exception Processing Message %lx Parameters %lx %lx %lx %lx",
01082 phemsg->Status, adwParameterVector[0], adwParameterVector[1],
01083 adwParameterVector[2], adwParameterVector[3]);
01084
01085
RtlFreeUnicodeString(&usMessage);
01086
RtlCreateUnicodeString(&usMessage, wszErrorMessage);
01087 UserAssert(usMessage.MaximumLength <=
sizeof(wszErrorMessage));
01088
01089 }
01090
01091 }
01092
01093
01094 CleanUpAndSaveParams:
01095
if (hClientProcess !=
NULL) {
01096
NtClose(hClientProcess);
01097 }
01098
01099
01100
01101
01102
01103
if (dwStringsToFreeMask != 0) {
01104
for (dwCounter = 0; dwCounter < phemsg->NumberOfParameters; dwCounter++) {
01105
if (dwStringsToFreeMask & (1 << dwCounter)) {
01106
RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)adwParameterVector[dwCounter]);
01107 }
01108 }
01109 }
01110
01111
01112
01113
if (fErrorIsFromSystem) {
01114 phi->
dwHEIFFlags |=
HEIF_SYSTEMERROR;
01115 }
01116 phi->
usText = usMessage;
01117 phi->
usCaption = usCaption;
01118 phi->
dwMBFlags = dwMBFlags;
01119
return;
01120 }
01121
01122
01123
01124
01125
01126
01127
01128
01129 VOID HardErrorHandler(
void)
01130 {
01131
int idResponse;
01132
PHARDERRORINFO phi, *pphi;
01133
DWORD dwResponse;
01134 DESKRESTOREDATA drdRestore;
01135
BOOL fNuked;
01136
UINT uHECRet;
01137
DWORD dwCmd;
01138 HANDLE hThread;
01139
int aidButton[3], cButtons;
01140 LPWSTR apstrButton[3];
01141
MSGBOXDATA mbd;
01142
BOOL bDoBlock;
01143
PCTXHARDERRORINFO pCtxHEInfo =
NULL;
01144 MSG
msg;
01145
01146
#if DBG
01147
01148
01149
01150
static long glReentered = -1;
01151 UserAssert(InterlockedIncrement(&glReentered) == 0);
01152
#endif
01153
01154
if (
ISTS()) {
01155 bDoBlock = (
gbExitInProgress || (HEC_ERROR ==
NtUserHardErrorControl(HardErrorSetup,
NULL,
NULL)));
01156 }
else {
01157 bDoBlock = (HEC_ERROR ==
NtUserHardErrorControl(HardErrorSetup,
NULL,
NULL));
01158 }
01159
01160 drdRestore.pdeskRestore =
NULL;
01161
01162
if (bDoBlock) {
01163
01164
01165
01166
01167
EnterCrit();
01168
while (
gphiList !=
NULL) {
01169 phi =
gphiList;
01170
gphiList = phi->
phiNext;
01171
LeaveCrit();
01172
ReplyHardError(phi, ResponseNotHandled);
01173
EnterCrit();
01174 }
01175 UserAssert(InterlockedDecrement(&glReentered) < 0);
01176 UserAssert(
gdwHardErrorThreadId == HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread));
01177
gdwHardErrorThreadId = 0;
01178
LeaveCrit();
01179
return;
01180 }
01181
01182
01183
01184
01185
01186
for (;;) {
01187
01188
01189
01190
01191
01192
EnterCrit();
01193 phi =
gphiList;
01194
if (phi ==
NULL) {
01195 UserAssert(InterlockedDecrement(&glReentered) < 0);
01196 UserAssert(
gdwHardErrorThreadId == HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread));
01197
gdwHardErrorThreadId = 0;
01198 }
else {
01199
while ((phi !=
NULL) && (phi->
dwHEIFFlags &
HEIF_WRONGDESKTOP)) {
01200 phi = phi->
phiNext;
01201 }
01202
if (phi !=
NULL) {
01203
01204
01205
01206 phi->
dwHEIFFlags |=
HEIF_ACTIVE;
01207 }
else {
01208
01209
01210
01211
01212
01213
LeaveCrit();
01214
MsgWaitForMultipleObjects(0,
NULL,
FALSE, INFINITE, QS_POSTMESSAGE);
01215
PeekMessage(&
msg,
NULL, 0, 0, PM_REMOVE);
01216
CheckDefaultDesktop();
01217
continue;
01218 }
01219 }
01220
LeaveCrit();
01221
01222
01223
01224
if (phi ==
NULL) {
01225
NtUserHardErrorControl(HardErrorCleanup,
NULL,
NULL);
01226
return;
01227 }
01228
01229
01230
01231
01232
if (
ISTS()) {
01233 pCtxHEInfo = phi->
pCtxHEInfo;
01234
if (
gbExitInProgress) {
01235 dwResponse = ResponseOk;
01236
goto Reply;
01237 }
01238 }
01239
01240
01241
01242
01243 dwCmd = (phi->
dwMBFlags & MB_DEFAULT_DESKTOP_ONLY) ? HardErrorAttachUser : HardErrorAttach;
01244 hThread = (phi->
pthread !=
NULL) ? phi->
pthread->ThreadHandle :
NULL;
01245
01246
01247
01248
01249
01250 phi->
dwMBFlags &= ~(MB_SERVICE_NOTIFICATION | MB_SETFOREGROUND | MB_SYSTEMMODAL);
01251
01252
01253
01254
if (phi->
dwHEIFFlags &
HEIF_VDMERROR) {
01255
int i;
01256 WORD rgwBtn[3], wBtn;
01257
01258
01259
01260
01261 RtlZeroMemory(&mbd,
sizeof(
MSGBOXDATA));
01262 mbd.cbSize =
sizeof(MSGBOXPARAMS);
01263 mbd.lpszText = phi->
usText.Buffer;
01264 mbd.lpszCaption = phi->
usCaption.Buffer;
01265
01266
01267
01268
01269
01270
01271 rgwBtn[0] = LOWORD(phi->
dwVDMParam0);
01272 rgwBtn[1] = HIWORD(phi->
dwVDMParam1);
01273 rgwBtn[2] = LOWORD(phi->
dwVDMParam1);
01274 cButtons = 0;
01275
for (i = 0; i < 3; i++) {
01276 wBtn = rgwBtn[i] & ~
SEB_DEFBUTTON;
01277
if (wBtn && wBtn <=
MAX_SEB_STYLES) {
01278 apstrButton[cButtons] =
MB_GetString(wBtn-1);
01279 aidButton[cButtons] = i + 1;
01280
if (rgwBtn[i] &
SEB_DEFBUTTON) {
01281 mbd.
DefButton = cButtons;
01282 }
01283
if (wBtn ==
SEB_CANCEL) {
01284 mbd.
CancelId = cButtons;
01285 }
01286 cButtons++;
01287 }
01288 }
01289 mbd.dwStyle = MB_TOPMOST;
01290
if ((cButtons != 1) || (aidButton[0] != 1)) {
01291 mbd.dwStyle |= MB_OKCANCEL;
01292 }
01293 mbd.
ppszButtonText = apstrButton;
01294 mbd.
pidButton = aidButton;
01295 mbd.
cButtons = cButtons;
01296 }
01297
01298
01299
01300
01301
do {
01302 phi->
pmsg->Response = ResponseNotHandled;
01303
01304 uHECRet =
NtUserHardErrorControl(dwCmd, hThread, &drdRestore);
01305
01306
if (uHECRet == HEC_SUCCESS) {
01307
if (phi->
dwHEIFFlags &
HEIF_VDMERROR) {
01308 idResponse =
SoftModalMessageBox(&mbd);
01309 }
else {
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
if (pCtxHEInfo !=
NULL) {
01322
01323
01324
01325
01326
01327
01328
if ((pCtxHEInfo->
Timeout != (-1)) && (pCtxHEInfo->
Timeout != 0)) {
01329
01330
DWORD Timeout;
01331
01332
if (((
DWORD)pCtxHEInfo->
Timeout) < (MAXLONG/1000)) {
01333 Timeout = (
DWORD)pCtxHEInfo->
Timeout * 1000
L;
01334 }
else {
01335 Timeout = MAXLONG;
01336 }
01337
01338
gfTimedOut =
FALSE;
01339
gTimerId =
SetTimer((HWND)0,
01340 (
UINT)0,
01341 Timeout,
01342
MsgBoxTimerFunc);
01343
if (
gTimerId == 0) {
01344 RIPMSG0(RIP_WARNING,
"HardErrorHandler: Could not set system timer");
01345 }
01346 }
01347
01348 RIPMSG2(RIP_WARNING,
"HardErrorHandler: MessageBoxEx( %S, %S )",
01349 phi->
usText.Buffer, phi->
usCaption.Buffer);
01350 }
else {
01351 RIPMSG2(RIP_WARNING,
"HardErrorHandler: MessageBoxEx( %S, %S )",
01352 phi->
usText.Buffer, phi->
usCaption.Buffer);
01353 }
01354
01355 idResponse = MessageBoxEx(
NULL, phi->
usText.Buffer, phi->
usCaption.Buffer,
01356 (phi->
dwMBFlags | MB_TOPMOST) & ~MB_DEFAULT_DESKTOP_ONLY, 0);
01357 }
01358
01359
01360
01361
01362
01363
01364 uHECRet =
NtUserHardErrorControl(HardErrorDetach,
NULL, &drdRestore);
01365
01366
if (
ISTS()) {
01367
01368
01369
01370
if (
gTimerId) {
01371 KillTimer((HWND)0,
gTimerId);
01372
gTimerId = 0;
01373 }
01374
01375
01376
01377
if (uHECRet != HEC_DESKTOPSWITCH && pCtxHEInfo !=
NULL) {
01378
01379
01380
01381
01382
if (
gfTimedOut) {
01383 uHECRet = HEC_SUCCESS;
01384
gfTimedOut =
FALSE;
01385 pCtxHEInfo->
Response = IDTIMEOUT;
01386 }
else {
01387 pCtxHEInfo->
Response = idResponse;
01388 }
01389
01390 }
01391
if (
dwResponses[idResponse] == ResponseNotHandled &&
01392 uHECRet == HEC_DESKTOPSWITCH &&
gSessionId == 0) {
01393
01394 RIPMSG2(RIP_WARNING,
"HardErrorHandler: abort harderror, idResponse %u, uHECRet %u",
01395 idResponse, uHECRet);
01396
01397
break;
01398 }
01399 }
01400 }
else {
01401 idResponse = 0;
01402 }
01403 UserAssert((
UINT)idResponse <
ARRAY_SIZE(
dwResponses));
01404 dwResponse =
dwResponses[idResponse];
01405
01406
01407
01408
if (uHECRet != HEC_DESKTOPSWITCH) {
01409
break;
01410 }
else {
01411
01412
01413
01414
01415
01416
CheckDefaultDesktop();
01417 }
01418
01419
01420
01421
EnterCrit();
01422 fNuked = (phi->
dwHEIFFlags &
HEIF_NUKED);
01423
LeaveCrit();
01424 }
while (!fNuked);
01425
01426
01427
01428
01429
01430
if (uHECRet == HEC_WRONGDESKTOP) {
01431 UserAssert(phi->
dwMBFlags & MB_DEFAULT_DESKTOP_ONLY);
01432
EnterCrit();
01433
COPY_FLAG(phi->
dwHEIFFlags,
HEIF_WRONGDESKTOP,
HEIF_ACTIVE |
HEIF_WRONGDESKTOP);
01434
LeaveCrit();
01435
continue;
01436 }
01437
01438 Reply:
01439
01440
01441
01442
01443
01444
EnterCrit();
01445 UserAssert(phi->
dwHEIFFlags &
HEIF_ACTIVE);
01446 fNuked = (phi->
dwHEIFFlags &
HEIF_NUKED);
01447
if (!fNuked) {
01448 pphi = &
gphiList;
01449
while ((*pphi != phi) && (*pphi !=
NULL)) {
01450 pphi = &(*pphi)->
phiNext;
01451 }
01452 UserAssert(*pphi !=
NULL);
01453 *pphi = phi->
phiNext;
01454 }
01455
01456
#if DBG
01457
else {
01458
01459
01460
01461 pphi = &
gphiList;
01462
while ((*pphi != phi) && (*pphi !=
NULL)) {
01463 UserAssert(!((*pphi)->dwHEIFFlags & (
HEIF_ACTIVE |
HEIF_NUKED)));
01464 pphi = &(*pphi)->
phiNext;
01465 }
01466 UserAssert(*pphi ==
NULL);
01467 }
01468
#endif
01469
01470
if (phi->
pCtxHEInfo) {
01471
01472
01473
01474
01475
HardErrorRemove(phi->
pCtxHEInfo);
01476
01477
01478
01479
01480 phi->
pCtxHEInfo =
NULL;
01481 }
01482
01483
LeaveCrit();
01484
01485
01486
01487
01488
ReplyHardError(phi, (fNuked ? ResponseNotHandled : dwResponse));
01489
01490 }
01491
01492
01493
01494
01495 UserAssert(
FALSE);
01496 }
01497
01498
01499 LPWSTR
RtlLoadStringOrError(
01500 HANDLE hModule,
01501 UINT wID,
01502 LPWSTR lpDefault,
01503 PBOOL pAllocated,
01504 BOOL bAnsi
01505 )
01506 {
01507 LPTSTR lpsz;
01508
int cch;
01509 LPWSTR lpw;
01510 PMESSAGE_RESOURCE_ENTRY MessageEntry;
01511
NTSTATUS Status;
01512
01513 cch = 0;
01514 lpw =
NULL;
01515
01516
Status =
RtlFindMessage((PVOID)hModule, (ULONG_PTR)RT_MESSAGETABLE,
01517 0, wID, &MessageEntry);
01518
if (
NT_SUCCESS(
Status)) {
01519
01520
01521
01522
01523
01524 cch = wcslen((PWCHAR)MessageEntry->Text) - 2;
01525 lpsz = (LPWSTR)MessageEntry->Text;
01526
01527
if (bAnsi) {
01528
int ich;
01529
01530
01531
01532
01533 ich = WCSToMB(lpsz, cch+1, (
CHAR **)&lpw, -1,
TRUE);
01534 ((LPSTR)lpw)[ich-1] = 0;
01535
01536 }
01537
else {
01538 lpw = (LPWSTR)LocalAlloc(
LMEM_ZEROINIT,(cch+1)*
sizeof(WCHAR));
01539
if ( lpw ) {
01540
01541
01542
01543
01544 RtlCopyMemory(lpw, lpsz, cch*
sizeof(WCHAR));
01545 }
01546 }
01547 }
01548
01549
if ( !lpw ) {
01550 lpw = lpDefault;
01551 *pAllocated =
FALSE;
01552 }
else {
01553 *pAllocated =
TRUE;
01554 }
01555
01556
return lpw;
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
NTSTATUS
01569 HardErrorWorkerThread(
01570 PVOID ThreadParameter
01571 )
01572 {
01573 PCSR_THREAD pt;
01574 UNREFERENCED_PARAMETER(ThreadParameter);
01575
01576 pt = CsrConnectToUser();
01577
ProcessHardErrorRequest(
FALSE);
01578
if (pt) {
01579 CsrDereferenceThread(pt);
01580 }
01581
UserExitWorkerThread();
01582
01583
return STATUS_SUCCESS;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
VOID
01599 ProcessHardErrorRequest(
01600 BOOL fNewThread
01601 )
01602 {
01603
NTSTATUS Status;
01604 CLIENT_ID ClientId;
01605 HANDLE hThread;
01606
01607
EnterCrit();
01608
01609
01610
01611
01612
if (
gdwHardErrorThreadId) {
01613
DWORD dwHardErrorHandler =
gdwHardErrorThreadId;
01614
LeaveCrit();
01615
PostThreadMessage(dwHardErrorHandler, WM_NULL, 0, 0);
01616
return;
01617 }
01618
01619
01620
01621
01622
if (fNewThread) {
01623
LeaveCrit();
01624
Status =
RtlCreateUserThread(NtCurrentProcess(),
01625
NULL,
01626
TRUE,
01627 0,
01628 0,
01629 0,
01630
HardErrorWorkerThread,
01631
NULL,
01632 &hThread,
01633 &ClientId);
01634
if (
NT_SUCCESS(
Status)) {
01635 CsrAddStaticServerThread(hThread, &ClientId, 0);
01636
NtResumeThread(hThread,
NULL);
01637
return;
01638 }
01639
EnterCrit();
01640 }
01641
01642
01643
01644
01645
gdwHardErrorThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread);
01646
LeaveCrit();
01647
HardErrorHandler();
01648
01649
return;
01650 }
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 VOID UserHardError(
01663 PCSR_THREAD pt,
01664 PHARDERROR_MSG pmsg)
01665 {
01666
UserHardErrorEx(pt, pmsg,
NULL);
01667 }
01668
01669 VOID HardErrorInsert(
01670 PCSR_THREAD pt,
01671 PHARDERROR_MSG pmsg,
01672
PCTXHARDERRORINFO pCtxHEInfo)
01673 {
01674
UserHardErrorEx(pt, pmsg, pCtxHEInfo);
01675 }
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 VOID UserHardErrorEx(
01687 PCSR_THREAD pt,
01688 PHARDERROR_MSG pmsg,
01689
PCTXHARDERRORINFO pCtxHEInfo)
01690 {
01691
BOOL fClientPort, fNoWait, fMsgBox, fLogEvent;
01692
PHARDERRORINFO phi =
NULL, *pphiLast;
01693 HANDLE hEvent;
01694
DWORD dwReportMode, dwResponse;
01695
01696 UserAssert((ULONG)pmsg->NumberOfParameters <= MAXIMUM_HARDERROR_PARAMETERS);
01697
01698
01699
01700 phi = (
PHARDERRORINFO)LocalAlloc(LPTR,
sizeof(
HARDERRORINFO));
01701
if (phi ==
NULL) {
01702
goto ErrorExit;
01703 }
01704 phi->
pthread = pt;
01705
01706
01707
01708
01709
if (
ISTS()) {
01710 phi->
pCtxHEInfo = pCtxHEInfo;
01711 }
01712
01713
01714
01715
01716 fClientPort = ((pt !=
NULL) && (pt->Process->ClientPort !=
NULL));
01717 fNoWait = (pmsg->ValidResponseOptions == OptionOkNoWait);
01718
01719
01720
01721
01722
if (fClientPort || fNoWait) {
01723 phi->
pmsg = (PHARDERROR_MSG)LocalAlloc(LPTR, pmsg->h.u1.s1.TotalLength);
01724
if (phi->
pmsg ==
NULL) {
01725
goto ErrorExit;
01726 }
01727 phi->
dwHEIFFlags |=
HEIF_ALLOCATEDMSG;
01728 RtlCopyMemory(phi->
pmsg, pmsg, pmsg->h.u1.s1.TotalLength);
01729 hEvent =
NULL;
01730
01731
01732
01733
01734
if (pt !=
NULL) {
01735 phi->
dwHEIFFlags |=
HEIF_DEREFTHREAD;
01736 }
01737 pmsg->Response = (ULONG)-1;
01738
if (fNoWait) {
01739 phi->
pmsg->ValidResponseOptions = OptionOk;
01740 }
01741 }
else {
01742 phi->
pmsg = pmsg;
01743
01744
01745
01746 hEvent = CreateEvent(
NULL,
FALSE,
FALSE,
NULL);
01747
if (hEvent ==
NULL) {
01748
goto ErrorExit;
01749 }
01750 phi->
hEventHardError = hEvent;
01751 }
01752
01753
01754
01755
01756
GetHardErrorText(phi);
01757
01758
01759
01760
01761
if (fNoWait) {
01762 phi->
dwHEIFFlags |=
HEIF_REPLIED;
01763 phi->
pmsg->Response = ResponseOk;
01764
if (fClientPort) {
01765
NtReplyPort(pt->Process->ClientPort, (PPORT_MESSAGE)phi->
pmsg);
01766 }
else {
01767
01768
01769
01770 pmsg->Response = ResponseOk;
01771
01772
01773
01774
01775
if (pt !=
NULL) {
01776
01777
01778
01779 UserAssert(pt ==
NULL);
01780 CsrReferenceThread(pt);
01781 }
01782 }
01783 }
01784
01785
01786
01787
01788
01789
01790
01791 fLogEvent = (
gEventSource !=
NULL);
01792
if (!fLogEvent) {
01793 HANDLE hEventSource;
01794 hEventSource =
UserRegisterEventSource(
L"Application Popup");
01795
01796
01797
01798
if (InterlockedCompareExchangePointer(&
gEventSource, hEventSource,
NULL) ==
NULL) {
01799
01800
01801
01802 fLogEvent = (hEventSource !=
NULL);
01803 }
else {
01804
01805
01806
01807
if (hEventSource !=
NULL) {
01808 UserVerify(
gfnDeregisterEventSource(hEventSource));
01809 }
01810 fLogEvent =
TRUE;
01811 }
01812 }
01813
01814 dwReportMode = (fLogEvent ?
GetErrorMode() : 0);
01815
if (fLogEvent) {
01816
LogErrorPopup(phi->
usCaption.Buffer, phi->
usText.Buffer);
01817 }
01818
01819
01820
01821
01822
if ((phi->
pmsg->Status == STATUS_SERVICE_NOTIFICATION) || (dwReportMode == 0)) {
01823 fMsgBox =
TRUE;
01824 }
else if (phi->
pmsg->Status == STATUS_VDM_HARD_ERROR) {
01825 fMsgBox = (dwReportMode == 1);
01826
if (!fMsgBox) {
01827 dwResponse = ResponseOk;
01828 }
01829 }
else {
01830 fMsgBox = ((dwReportMode == 1) && !(phi->
dwHEIFFlags &
HEIF_SYSTEMERROR));
01831
if (!fMsgBox) {
01832 UserAssert((
UINT)phi->
pmsg->ValidResponseOptions <
ARRAY_SIZE(
dwResponseDefault));
01833 dwResponse =
dwResponseDefault[phi->
pmsg->ValidResponseOptions];
01834 }
01835 }
01836
01837
01838
01839
if (!fMsgBox) {
01840
goto DontNeedErrorHandler;
01841 }
01842
01843
01844
01845
01846
EnterCrit();
01847
01848
01849
01850
01851
01852
if ((pt !=
NULL) && (pt->Process->Flags & CSR_PROCESS_TERMINATED)) {
01853
LeaveCrit();
01854 DontNeedErrorHandler:
01855
ReplyHardError(phi, dwResponse);
01856
if (hEvent !=
NULL) {
01857
NtClose(hEvent);
01858 }
01859
return;
01860 }
01861
01862
01863
01864 pphiLast = &
gphiList;
01865
while (*pphiLast !=
NULL) {
01866 pphiLast = &(*pphiLast)->
phiNext;
01867 }
01868 *pphiLast = phi;
01869
LeaveCrit();
01870
01871
01872
01873
01874
01875
01876
ProcessHardErrorRequest(fNoWait && !fClientPort);
01877
01878
01879
01880
01881
if (hEvent !=
NULL) {
01882
NtWaitForSingleObject(hEvent,
FALSE,
NULL);
01883
NtClose(hEvent);
01884 }
01885
return;
01886
01887
ErrorExit:
01888
if (phi !=
NULL) {
01889
FreePhi(phi);
01890 }
01891 pmsg->Response = ResponseNotHandled;
01892 }
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906 BOOL BoostHardError(
01907 ULONG_PTR dwProcessId,
01908 DWORD dwCode)
01909 {
01910 DESKRESTOREDATA drdRestore;
01911
PHARDERRORINFO phi, *pphi;
01912
BOOL fHasError =
FALSE;
01913
01914
EnterCrit();
01915
01916
01917
01918
if (
gphiList ==
NULL) {
01919
LeaveCrit();
01920
return FALSE;
01921 }
01922 drdRestore.pdeskRestore =
NULL;
01923
01924
01925
01926 pphi = &
gphiList;
01927
while (*pphi !=
NULL) {
01928
01929
01930
01931
if (dwProcessId != (ULONG_PTR)-1) {
01932
if (((*pphi)->pthread ==
NULL)
01933 || ((ULONG_PTR)((*pphi)->pthread->ClientId.UniqueProcess) != dwProcessId)) {
01934
01935 pphi = &(*pphi)->
phiNext;
01936
continue;
01937 }
01938 }
else {
01939 UserAssert(dwCode ==
BHE_FORCE);
01940 }
01941
01942
01943
01944 fHasError =
TRUE;
01945
01946
01947
01948
if (dwCode ==
BHE_FORCE) {
01949
01950
01951
01952 phi = *pphi;
01953 *pphi = phi->
phiNext;
01954
01955
01956
01957
01958
01959
if (phi->
dwHEIFFlags &
HEIF_ACTIVE) {
01960
DWORD dwHardErrorHandler =
gdwHardErrorThreadId;
01961 phi->
dwHEIFFlags |=
HEIF_NUKED;
01962
LeaveCrit();
01963
PostThreadMessage(dwHardErrorHandler, WM_QUIT, 0, 0);
01964 }
else {
01965
01966
01967
01968
LeaveCrit();
01969
ReplyHardError(phi, ResponseNotHandled);
01970 }
01971
01972
01973
01974
01975
EnterCrit();
01976 pphi = &
gphiList;
01977
01978
01979
01980 }
else if (dwCode ==
BHE_ACTIVATE) {
01981
01982
01983
01984 phi = *pphi;
01985
if (phi->
dwHEIFFlags &
HEIF_ACTIVE) {
01986 HWND hwndError =
NULL;
01987
DWORD dwHardErrorHandler =
gdwHardErrorThreadId;
01988
01989
LeaveCrit();
01990
EnumThreadWindows(dwHardErrorHandler,
FindWindowFromThread, (LPARAM)&hwndError);
01991
01992
if ((hwndError !=
NULL)
01993 && (HEC_SUCCESS ==
NtUserHardErrorControl(HardErrorAttachNoQueue,
NULL, &drdRestore))) {
01994
01995
SetForegroundWindow(hwndError);
01996
01997
NtUserHardErrorControl(HardErrorDetachNoQueue,
NULL, &drdRestore);
01998 }
01999
return TRUE;
02000 }
02001
02002
02003
02004
02005
02006 *pphi = phi->
phiNext;
02007 phi->
phiNext =
gphiList;
02008
gphiList = phi;
02009
break;
02010
02011 }
else {
02012
02013
02014
02015
break;
02016 }
02017 }
02018
02019
LeaveCrit();
02020
02021
02022
02023
02024
if (dwCode ==
BHE_FORCE &&
gdwHardErrorThreadId != 0) {
02025
PostThreadMessage(
gdwHardErrorThreadId, WM_NULL, 0, 0);
02026 }
02027
02028
return fHasError;
02029 }