Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

harderr.c File Reference

#include "precomp.h"
#include "ntlpcapi.h"
#include <winsta.h>

Go to the source code of this file.

Functions

VOID UserHardErrorEx (PCSR_THREAD pt, PHARDERROR_MSG pmsg, PCTXHARDERRORINFO pCtxHEInfo)
VOID UserExitWorkerThread (VOID)
VOID ProcessHardErrorRequest (BOOL fNewThread)
VOID HardErrorInsert (PCSR_THREAD, PHARDERROR_MSG, PCTXHARDERRORINFO)
VOID HardErrorRemove (PCTXHARDERRORINFO)
HANDLE UserRegisterEventSource (PCWSTR pwszSourceName)
VOID LogErrorPopup (IN LPWSTR Caption, IN LPWSTR Message)
VOID SubstituteDeviceName (PUNICODE_STRING InputDeviceName, LPSTR OutputDriveLetter)
DWORD GetErrorMode (VOID)
void FreePhi (PHARDERRORINFO phi)
void ReplyHardError (PHARDERRORINFO phi, DWORD dwResponse)
void CheckDefaultDesktop (void)
VOID MsgBoxTimerFunc (HWND hWnd, UINT MessageType, UINT_PTR idEvent, DWORD TimeWhenCalled)
void GetHardErrorText (PHARDERRORINFO phi)
VOID HardErrorHandler (void)
LPWSTR RtlLoadStringOrError (HANDLE hModule, UINT wID, LPWSTR lpDefault, PBOOL pAllocated, BOOL bAnsi)
NTSTATUS HardErrorWorkerThread (PVOID ThreadParameter)
VOID UserHardError (PCSR_THREAD pt, PHARDERROR_MSG pmsg)
BOOL BoostHardError (ULONG_PTR dwProcessId, DWORD dwCode)

Variables

BOOLEAN gbExitInProgress
BOOL gfTimedOut = FALSE
CONST UINT wIcons []
CONST UINT wOptions []
CONST DWORD dwResponses []
CONST DWORD dwResponseDefault []
UINT_PTR gTimerId = 0
FARPROC gfnRegisterEventSource
FARPROC gfnDeregisterEventSource
FARPROC gfnReportEvent
WCHAR wszDosDevices [] = L"\\??\\A:"


Function Documentation

BOOL BoostHardError ULONG_PTR  dwProcessId,
DWORD  dwCode
 

Definition at line 1906 of file w32/ntuser/server/harderr.c.

References BHE_ACTIVATE, BHE_FORCE, BOOL, tagHARDERRORINFO::dwHEIFFlags, DWORD, EnterCrit, EnumThreadWindows(), FALSE, FindWindowFromThread(), gdwHardErrorThreadId, gphiList, HEIF_ACTIVE, HEIF_NUKED, LeaveCrit, NtUserHardErrorControl(), NULL, tagHARDERRORINFO::phiNext, PostThreadMessage(), ReplyHardError(), SetForegroundWindow(), and TRUE.

Referenced by CreateCtrlThread(), EndTaskDlgProc(), KillProcess(), ThreadShutdownNotify(), UserClientShutdown(), and W32WinStationTerminate().

01909 { 01910 DESKRESTOREDATA drdRestore; 01911 PHARDERRORINFO phi, *pphi; 01912 BOOL fHasError = FALSE; 01913 01914 EnterCrit(); 01915 /* 01916 * If the list is empty, nothing do to here. 01917 */ 01918 if (gphiList == NULL) { 01919 LeaveCrit(); 01920 return FALSE; 01921 } 01922 drdRestore.pdeskRestore = NULL; 01923 /* 01924 * Walk the hard error list 01925 */ 01926 pphi = &gphiList; 01927 while (*pphi != NULL) { 01928 /* 01929 * If not not nuking all and not owned by dwProcessId, continue walking 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 * Got one so we want to return TRUE 01943 */ 01944 fHasError = TRUE; 01945 /* 01946 * If nuking the request 01947 */ 01948 if (dwCode == BHE_FORCE) { 01949 /* 01950 * Unlink it from the list. 01951 */ 01952 phi = *pphi; 01953 *pphi = phi->phiNext; 01954 01955 /* 01956 * If this box is being shown right now, signal it to go away. 01957 * Otherwise, nuke it 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 * Acknowledge the error as not handled, reply and free 01967 */ 01968 LeaveCrit(); 01969 ReplyHardError(phi, ResponseNotHandled); 01970 } 01971 01972 /* 01973 * Restart the search because we left the crit sect. 01974 */ 01975 EnterCrit(); 01976 pphi = &gphiList; 01977 01978 /* continue */ 01979 01980 } else if (dwCode == BHE_ACTIVATE) { 01981 /* 01982 * If it's active, find it and show it. 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 * It's not active so move it to the head of the list 02004 * to make it show up next. 02005 */ 02006 *pphi = phi->phiNext; 02007 phi->phiNext = gphiList; 02008 gphiList = phi; 02009 break; 02010 02011 } else { /* BHE_TEST */ 02012 /* 02013 * The caller just want to know if this process owns a hard error 02014 */ 02015 break; 02016 } 02017 } /* while (*pphi != NULL) */ 02018 02019 LeaveCrit(); 02020 02021 /* 02022 * Bug 284468. Wake up the hard error handler 02023 */ 02024 if (dwCode == BHE_FORCE && gdwHardErrorThreadId != 0) { 02025 PostThreadMessage(gdwHardErrorThreadId, WM_NULL, 0, 0); 02026 } 02027 02028 return fHasError; 02029 }

void CheckDefaultDesktop void   ) 
 

Definition at line 347 of file w32/ntuser/server/harderr.c.

References tagHARDERRORINFO::dwHEIFFlags, EnterCrit, gphiList, HEIF_WRONGDESKTOP, LeaveCrit, NtUserHardErrorControl(), NULL, and tagHARDERRORINFO::phiNext.

Referenced by HardErrorHandler().

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 }

void FreePhi PHARDERRORINFO  phi  ) 
 

Definition at line 291 of file w32/ntuser/server/harderr.c.

References tagHARDERRORINFO::dwHEIFFlags, HEIF_ALLOCATEDMSG, tagHARDERRORINFO::pmsg, RtlFreeUnicodeString(), tagHARDERRORINFO::usCaption, and tagHARDERRORINFO::usText.

Referenced by ReplyHardError(), and UserHardErrorEx().

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 }

DWORD GetErrorMode VOID   ) 
 

Definition at line 255 of file w32/ntuser/server/harderr.c.

References BYTE, DWORD, L, NT_SUCCESS, NtClose(), NtOpenKey(), NtQueryValueKey(), NULL, RtlInitUnicodeString(), and Status.

Referenced by UserHardErrorEx().

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 }

void GetHardErrorText PHARDERRORINFO  phi  ) 
 

Definition at line 423 of file w32/ntuser/server/harderr.c.

References ARRAY_SIZE, BOOL, tagHARDERRORINFO::dwHEIFFlags, tagHARDERRORINFO::dwMBFlags, DWORD, tagHARDERRORINFO::dwVDMParam0, tagHARDERRORINFO::dwVDMParam1, EnterCrit, EnumThreadWindows(), EXCEPTION_EXECUTE_HANDLER, FALSE, FindWindowFromThread(), GetWindowText(), GetWindowTextLength(), ghModuleWin, gNtDllHandle, gpwszaSUCCESS, gpwszaSYSTEM_ERROR, gpwszaSYSTEM_INFORMATION, gpwszaSYSTEM_WARNING, HEIF_SYSTEMERROR, HEIF_VDMERROR, L, LeaveCrit, LMEM_ZEROINIT, NT_SUCCESS, NtClose(), NtQueryInformationProcess(), NtReadVirtualMemory(), NTSTATUS(), NULL, tagHARDERRORINFO::pmsg, RtlAnsiStringToUnicodeString(), RtlCreateUnicodeString(), RtlFindMessage(), RtlFreeAnsiString(), RtlFreeHeap, RtlFreeUnicodeString(), RtlInitAnsiString(), RtlInitUnicodeString(), RtlUnicodeStringToAnsiString(), ServerLoadString, Status, SubstituteDeviceName(), TRUE, UINT, tagHARDERRORINFO::usCaption, tagHARDERRORINFO::usText, wIcons, wOptions, and wsprintfW().

Referenced by UserHardErrorEx().

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 * Initialize working variables 00447 */ 00448 fFreeAppNameBuffer = fFreeCaption = FALSE; 00449 hClientProcess = NULL; 00450 RtlInitUnicodeString(&usCaption, NULL); 00451 RtlInitUnicodeString(&usMessage, NULL); 00452 /* 00453 * Initialize response in case something goes wrong 00454 */ 00455 phemsg = phi->pmsg; 00456 phemsg->Response = ResponseNotHandled; 00457 /* 00458 * Make a copy of the parameters. Initialize unused ones to point to empty 00459 * strings (in case we expect a string there). 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 * Open the client process so we can read the strings parameters, process 00469 * name, etc., from its address space 00470 */ 00471 hClientProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 00472 FALSE, HandleToUlong(phemsg->h.ClientId.UniqueProcess)); 00473 fErrorIsFromSystem = (hClientProcess == NULL); 00474 /* 00475 * If there are unicode strings, then we need to 00476 * convert them to ansi and store them in the 00477 * parameter vector 00478 */ 00479 dwStringsToFreeMask = 0; 00480 if (phemsg->UnicodeStringParameterMask) { 00481 00482 for (dwCounter = 0; dwCounter < phemsg->NumberOfParameters; dwCounter++) { 00483 /* 00484 * if there is no string in this position, continue 00485 */ 00486 if (!(phemsg->UnicodeStringParameterMask & (1 << dwCounter))) { 00487 continue; 00488 } 00489 /* 00490 * Point to an empty string in case we don't have 00491 * a client to read from or something fails later on. 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 * check to see if string contains an NT 00537 * device name. If so, then attempt a 00538 * drive letter substitution 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 * Processing some status code doesn't require ansi strings. 00549 * Since no substitution took place, let's ignore the translation 00550 * to avoid losing chars -- incorrect code page translation 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 } /* for (dwCounter... */ 00568 00569 } /* if (phemsg->UnicodeStringParameterMask) */ 00570 00571 /* 00572 * Read additional MB flags, if provided. 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 * Currently we only use MB_DEFAULT_DESKTOP_ONLY 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 * For some status codes, all MessageBox parameters are provided in the HardError parameters 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 * Parameters[0] = (fForWOW << 16) | wBtn1; 00615 * Parameters[1] = (wBtn2 << 16) | wBtn3; 00616 * Parameters[2] = (DWORD) szTitle; 00617 * Parameters[3] = (DWORD) szMessage; 00618 */ 00619 phi->dwHEIFFlags |= HEIF_VDMERROR; 00620 /* 00621 * Save VDM's Button(s) info to be used later. 00622 */ 00623 phi->dwVDMParam0 = (DWORD)adwParameterVector[0]; 00624 phi->dwVDMParam1 = (DWORD)adwParameterVector[1]; 00625 /* 00626 * Get caption and text. 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 * For all other status codes, we generate the information from the status code. 00660 * First, Map status code and valid response to MessageBox flags. 00661 */ 00662 dwMBFlags |= wIcons[(ULONG)(phemsg->Status) >> 30] | wOptions[phemsg->ValidResponseOptions]; 00663 00664 00665 /* 00666 * If we have a client process, try to get the actual application name 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 * This is cumbersome, but basically, we locate the processes 00681 * loader data table and get it's name directly out of the 00682 * loader table 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 * ldr = Peb->Ldr 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 * LdrNext = Head->Flink; 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 * This is the entry data for the image. 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 } /* if (!fErrorIsFromSystem) */ 00767 00768 if (pwszAppName == NULL) { 00769 /* 00770 * Load default application name (to be used in the caption). 00771 */ 00772 pwszAppName = ServerLoadString(ghModuleWin, STR_UNKNOWN_APPLICATION, 00773 L"System Process", &fFreeAppNameBuffer); 00774 } 00775 00776 /* 00777 * Map status code to (optional) caption and format string. 00778 * If a caption is provided, it's enclosed in {} and it's 00779 * the first thing in the format string 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 * Parse the caption (if any) and the format string. 00793 */ 00794 pwszCaption = NULL; 00795 if (!NT_SUCCESS(Status)) { 00796 pwszFormatString = wszUnknownHardError; 00797 } else { 00798 pwszFormatString = (PWSTR)MessageEntry->Text; 00799 /* 00800 * If the message starts with a '{', it has a caption. 00801 */ 00802 if (*pwszFormatString == L'{') { 00803 uCaptionLen = 0; 00804 pwszFormatString++; 00805 /* 00806 * Find the closing bracket 00807 */ 00808 while ((*pwszFormatString != (WCHAR)0) && (*pwszFormatString++ != L'}')) { 00809 uCaptionLen++; 00810 } 00811 /* 00812 * Eat any non-printable stuff (\r\n), up to the NULL 00813 */ 00814 while ((*pwszFormatString != (WCHAR)0) && (*pwszFormatString <= L' ')) { 00815 pwszFormatString++; 00816 } 00817 /* 00818 * Allocate a buffer an copy the caption string 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 } /* if (*pszParsedCaption == '{') */ 00827 00828 if (*pwszFormatString == (WCHAR)0) { 00829 pwszFormatString = wszUnknownHardError; 00830 } 00831 } /* if (!NT_SUCCESS(Status)) (Failed to read caption/format string) */ 00832 00833 00834 /* 00835 * If the message didn't include a caption (or we didn't find the message), 00836 * default to something 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 * If the client has a window, get its title so it can be added to 00857 * the caption. 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 * Add format chars. 00872 */ 00873 *(pwszTitle + uTitleLen++) = (WCHAR)':'; 00874 *(pwszTitle + uTitleLen++) = (WCHAR)' '; 00875 } else { 00876 /* 00877 * We couldn't allocate a buffer to get the title 00878 */ 00879 uTitleLen = 0; 00880 } 00881 } /* if (uTitleLen != 0) */ 00882 } /* else if (hwndOwner == NULL) */ 00883 /* 00884 * If we don't have a window title, make it an empty string so we won't 00885 * have to special case it later. 00886 */ 00887 if (uTitleLen == 0) { 00888 pwszTitle = L""; 00889 } 00890 /* 00891 * Finally we can build the caption string now. 00892 * It looks like this: [WindowTile: ]ApplicationName - ErrorCaption 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 * Free caption working buffers, as appropriate. 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 * Build the error message using pszFormatString and adwParameterVector. 00919 * Special case UAE 00920 */ 00921 if (phemsg->Status == STATUS_UNHANDLED_EXCEPTION ) { 00922 /* 00923 * The first parameter has the exception status code. Map it to a 00924 * format string and build the error message with it and the 00925 * parameters. 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 * We couldn't read the exception name so let's use unknown. 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 * Access Violations are handled a bit differently 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 * If this is a marked exception, skip the mark; 00964 * the exception name follows it. 00965 */ 00966 pwszCaption = (PWSTR)MessageEntry->Text; 00967 if (!wcsncmp(pwszCaption, wszException, ARRAY_SIZE(wszException) - 1)) { 00968 pwszCaption += ARRAY_SIZE(wszException) - 1; 00969 /* 00970 * Skip not printable stuff (\r\n) 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 * Add button(s) explanation text. 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 * Conncatenate all strings, one per line. 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 * Free ServerLoadString allocations. 01028 */ 01029 if (fResAllocated) { 01030 LocalFree(pwszResBuffer); 01031 } 01032 01033 if (fResAllocated1) { 01034 LocalFree(pwszResBuffer1); 01035 } 01036 01037 01038 } 01039 01040 } else { 01041 /* 01042 * Default message text generation for all other status codes 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 * Remove \r\n 01056 */ 01057 pwszFormatString = wszErrorMessage; 01058 while (*pwszFormatString != (WCHAR)0) { 01059 if (*pwszFormatString == (WCHAR)0xd) { 01060 *pwszFormatString = L' '; 01061 /* 01062 * Move everything up if a CR LF sequence is found 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 } /* try */ 01090 01091 } /* else if (phemsg->Status == STATUS_UNHANDLED_EXCEPTION) */ 01092 01093 01094 CleanUpAndSaveParams: 01095 if (hClientProcess != NULL) { 01096 NtClose(hClientProcess); 01097 } 01098 /* 01099 * Free string parameters. 01100 * Note that we're supposed to call RtlFreeAnsiString since these were 01101 * allocated by RtlUnicodeStringToAnsiString.... but we only saved the buffers... 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 * Save MessageBox Parameters in phi to be used and freed later. 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 }

VOID HardErrorHandler void   ) 
 

Definition at line 1129 of file w32/ntuser/server/harderr.c.

References ARRAY_SIZE, BOOL, _MSGBOXDATA::CancelId, _MSGBOXDATA::cButtons, CheckDefaultDesktop(), COPY_FLAG, _MSGBOXDATA::DefButton, tagHARDERRORINFO::dwHEIFFlags, tagHARDERRORINFO::dwMBFlags, DWORD, dwResponses, tagHARDERRORINFO::dwVDMParam0, tagHARDERRORINFO::dwVDMParam1, EnterCrit, FALSE, gbExitInProgress, gdwHardErrorThreadId, gfTimedOut, gphiList, gSessionId, gTimerId, HardErrorRemove(), HEIF_ACTIVE, HEIF_NUKED, HEIF_VDMERROR, HEIF_WRONGDESKTOP, ISTS, L, LeaveCrit, MAX_SEB_STYLES, MB_GetString(), msg, MSGBOXDATA, MsgBoxTimerFunc(), MsgWaitForMultipleObjects(), NtUserHardErrorControl(), NULL, tagHARDERRORINFO::pCtxHEInfo, PeekMessage(), tagHARDERRORINFO::phiNext, _MSGBOXDATA::pidButton, tagHARDERRORINFO::pmsg, _MSGBOXDATA::ppszButtonText, tagHARDERRORINFO::pthread, ReplyHardError(), tagCTXHARDERRORINFO::Response, SEB_CANCEL, SEB_DEFBUTTON, SetTimer, SoftModalMessageBox(), tagCTXHARDERRORINFO::Timeout, UINT, tagHARDERRORINFO::usCaption, tagHARDERRORINFO::usText, and VOID().

Referenced by ProcessHardErrorRequest().

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 * We should have only one error handler at the time. 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 * We failed to set up to process hard errors. Acknowledge all 01165 * pending errors as NotHandled. 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 * Process all hard error requests. 01184 */ 01185 01186 for (;;) { 01187 /* 01188 * Grab the next request (for the current desktop) 01189 * If we're done, reset gdwHardErrorThreadId so any request 01190 * after this point will be handled by someone else 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 * We're going to show this one. 01205 */ 01206 phi->dwHEIFFlags |= HEIF_ACTIVE; 01207 } else { 01208 /* 01209 * We have some requests pending but they are not 01210 * for the current desktop. Let's wait for another 01211 * request (WM_NULL posted) or a desktop switch (PostQuitMessage) 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 * If no messages are pending, we're done. 01223 */ 01224 if (phi == NULL) { 01225 NtUserHardErrorControl(HardErrorCleanup, NULL, NULL); 01226 return; 01227 } 01228 01229 /* 01230 * The Boost routine can mess with the list, so must get citrix info now. 01231 */ 01232 if (ISTS()) { 01233 pCtxHEInfo = phi->pCtxHEInfo; 01234 if (gbExitInProgress) { 01235 dwResponse = ResponseOk; 01236 goto Reply; 01237 } 01238 } 01239 01240 /* 01241 * Get win32k attach parameters. 01242 */ 01243 dwCmd = (phi->dwMBFlags & MB_DEFAULT_DESKTOP_ONLY) ? HardErrorAttachUser : HardErrorAttach; 01244 hThread = (phi->pthread != NULL) ? phi->pthread->ThreadHandle : NULL; 01245 /* 01246 * We have already handled the MB_SERVICE_NOTIFICATION flags. 01247 * Clear it to prevent recursion. 01248 * Also, don't let hard error boxes steal the foreground 01249 */ 01250 phi->dwMBFlags &= ~(MB_SERVICE_NOTIFICATION | MB_SETFOREGROUND | MB_SYSTEMMODAL); 01251 /* 01252 * If this is a VDM error, figure out buttons, default id, style, etc 01253 */ 01254 if (phi->dwHEIFFlags & HEIF_VDMERROR) { 01255 int i; 01256 WORD rgwBtn[3], wBtn; 01257 /* 01258 * Initialize MSGBOXDATA with the information we 01259 * have already figured out. 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 * phi->dwVDMParam0 = (fForWOW << 16) | wBtn1; 01267 * phi->dwVDMParam1 = (wBtn2 << 16) | wBtn3; 01268 * Right now, only WOW does this. If NTVDM does it, 01269 * fForWOW will be false. 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 * Attach to win32k and show the dialog. 01299 * If we switch desktops, (loop and) show it on the new desktop (if applicable) 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 * Bring up the message box. Or in MB_TOPMOST so 01312 * it comes up on top. 01313 * We want to preserve the MB_DEFAULT_DESKTOP_ONLY flag 01314 * but don't want to pass it to MessageBox or we'll 01315 * recurse due to a compatibility hack 01316 */ 01317 01318 /* 01319 * Really a Terminal Server message 01320 */ 01321 if (pCtxHEInfo != NULL) { 01322 01323 /* 01324 * If timeout is not (-1), or 0, then we must queue 01325 * a system timer to call our timer callback function 01326 * to cancel the message box. 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 * 1000L; 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 * Restore hard error handler desktop; this will also 01360 * tell us if the input desktop has changed; if so, 01361 * we want to bring the error box again on the new 01362 * desktop. 01363 */ 01364 uHECRet = NtUserHardErrorControl(HardErrorDetach, NULL, &drdRestore); 01365 01366 if (ISTS()) { 01367 /* 01368 * Kill the timer if set 01369 */ 01370 if (gTimerId) { 01371 KillTimer((HWND)0, gTimerId); 01372 gTimerId = 0; 01373 } 01374 /* 01375 * Really a citrix message 01376 */ 01377 if (uHECRet != HEC_DESKTOPSWITCH && pCtxHEInfo != NULL) { 01378 01379 /* 01380 * Check for message box timeout 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 * If we don't want to reshow this box, done 01407 */ 01408 if (uHECRet != HEC_DESKTOPSWITCH) { 01409 break; 01410 } else { 01411 /* 01412 * We've switched desktops; if we're in the default one 01413 * now, then we can show all MB_DEFAULT_DESKTOP_ONLY 01414 * requests. 01415 */ 01416 CheckDefaultDesktop(); 01417 } 01418 /* 01419 * If BoostHardError nuked it, don't re-show it 01420 */ 01421 EnterCrit(); 01422 fNuked = (phi->dwHEIFFlags & HEIF_NUKED); 01423 LeaveCrit(); 01424 } while (!fNuked); 01425 01426 /* 01427 * If we didn't show this box because we're not in the 01428 * default desktop, mark this phi and continue 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 * We're done with this phi. 01441 * Unlink it if BoostHardError haven't done so already; 01442 * If unlinked, it is marked as nuked. 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 * Let's make sure it was unlinked. 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 * Clean up 01474 */ 01475 HardErrorRemove(phi->pCtxHEInfo); 01476 01477 /* 01478 * Done 01479 */ 01480 phi->pCtxHEInfo = NULL; 01481 } 01482 01483 LeaveCrit(); 01484 01485 /* 01486 * Save the response, reply and free phi 01487 */ 01488 ReplyHardError(phi, (fNuked ? ResponseNotHandled : dwResponse)); 01489 01490 } /* for (;;) */ 01491 01492 /* 01493 * Nobody should break out of the loop. 01494 */ 01495 UserAssert(FALSE); 01496 }

VOID HardErrorInsert PCSR_THREAD  ,
PHARDERROR_MSG  ,
PCTXHARDERRORINFO 
 

Definition at line 1669 of file w32/ntuser/server/harderr.c.

References UserHardErrorEx(), and VOID().

01673 { 01674 UserHardErrorEx(pt, pmsg, pCtxHEInfo); 01675 }

VOID HardErrorRemove PCTXHARDERRORINFO   ) 
 

Definition at line 282 of file icamsg.c.

References tagCTXHARDERRORINFO::DoNotWait, tagCTXHARDERRORINFO::pMessage, tagCTXHARDERRORINFO::pTitle, ReplyMessageToTerminalServer(), and VOID().

00284 { 00285 00286 /* 00287 * Notify ICASRV's RPC thread if waiting 00288 */ 00289 if (!pchi->DoNotWait) { 00290 ReplyMessageToTerminalServer(pchi); 00291 } 00292 00293 /* 00294 * Free memory 00295 */ 00296 LocalFree(pchi->pMessage); 00297 LocalFree(pchi->pTitle); 00298 LocalFree(pchi); 00299 }

NTSTATUS HardErrorWorkerThread PVOID  ThreadParameter  ) 
 

Definition at line 1569 of file w32/ntuser/server/harderr.c.

References FALSE, ProcessHardErrorRequest(), and UserExitWorkerThread().

Referenced by ProcessHardErrorRequest().

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 }

VOID LogErrorPopup IN LPWSTR  Caption,
IN LPWSTR  Message
 

Definition at line 166 of file w32/ntuser/server/harderr.c.

References gEventSource, gfnReportEvent, and NULL.

Referenced by UserHardErrorEx().

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 }

VOID MsgBoxTimerFunc HWND  hWnd,
UINT  MessageType,
UINT_PTR  idEvent,
DWORD  TimeWhenCalled
 

Definition at line 383 of file w32/ntuser/server/harderr.c.

References BOOL, gdwHardErrorThreadId, gfTimedOut, hWnd, PostThreadMessage(), and TRUE.

Referenced by HardErrorHandler().

00389 { 00390 BOOL RetVal; 00391 00392 RIPMSG0(RIP_WARNING, "MsgBoxTimerFunc: timer poped"); 00393 00394 // 00395 // Post a WM_QUIT message into the messagebox threads queue 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 }

VOID ProcessHardErrorRequest BOOL  fNewThread  ) 
 

Definition at line 1599 of file w32/ntuser/server/harderr.c.

References DWORD, EnterCrit, gdwHardErrorThreadId, HardErrorHandler(), HardErrorWorkerThread(), LeaveCrit, NT_SUCCESS, NtResumeThread(), NTSTATUS(), NULL, PostThreadMessage(), RtlCreateUserThread(), Status, and TRUE.

Referenced by HardErrorWorkerThread(), and UserHardErrorEx().

01602 { 01603 NTSTATUS Status; 01604 CLIENT_ID ClientId; 01605 HANDLE hThread; 01606 01607 EnterCrit(); 01608 01609 /* 01610 * If there's already a hard error handler, make sure he's awake. 01611 */ 01612 if (gdwHardErrorThreadId) { 01613 DWORD dwHardErrorHandler = gdwHardErrorThreadId; 01614 LeaveCrit(); 01615 PostThreadMessage(dwHardErrorHandler, WM_NULL, 0, 0); 01616 return; 01617 } 01618 01619 /* 01620 * Create a worker thread to handle the hard error. 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 * Let this thread handle the hard error. 01644 */ 01645 gdwHardErrorThreadId = HandleToUlong(NtCurrentTeb()->ClientId.UniqueThread); 01646 LeaveCrit(); 01647 HardErrorHandler(); 01648 01649 return; 01650 }

void ReplyHardError PHARDERRORINFO  phi,
DWORD  dwResponse
 

Definition at line 310 of file w32/ntuser/server/harderr.c.

References tagHARDERRORINFO::dwHEIFFlags, FreePhi(), HEIF_DEREFTHREAD, HEIF_REPLIED, tagHARDERRORINFO::hEventHardError, NtReplyPort(), NtSetEvent(), NULL, tagHARDERRORINFO::pmsg, and tagHARDERRORINFO::pthread.

Referenced by BoostHardError(), HardErrorHandler(), and UserHardErrorEx().

00311 { 00312 phi->pmsg->Response = dwResponse; 00313 /* 00314 * Signal the event if any. If not, reply if we haven't done so 00315 * already. 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 * If we had locked the thread or were holding the client port, 00325 * then let it go now. 00326 */ 00327 if (phi->dwHEIFFlags & HEIF_DEREFTHREAD) { 00328 CsrDereferenceThread(phi->pthread); 00329 } 00330 /* 00331 * We're done with this dude 00332 */ 00333 FreePhi(phi); 00334 }

LPWSTR RtlLoadStringOrError HANDLE  hModule,
UINT  wID,
LPWSTR  lpDefault,
PBOOL  pAllocated,
BOOL  bAnsi
 

Definition at line 1499 of file w32/ntuser/server/harderr.c.

References CHAR, FALSE, LMEM_ZEROINIT, NT_SUCCESS, NTSTATUS(), NULL, RtlFindMessage(), Status, and TRUE.

Referenced by GetRegIntFromID(), and UserServerDllInitialization().

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 * Return two fewer chars so the crlf in the message will be 01522 * stripped out. 01523 */ 01524 cch = wcslen((PWCHAR)MessageEntry->Text) - 2; 01525 lpsz = (LPWSTR)MessageEntry->Text; 01526 01527 if (bAnsi) { 01528 int ich; 01529 01530 /* 01531 * Add one to zero terminate then force the termination 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 * Copy the string into the buffer. 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 }

VOID SubstituteDeviceName PUNICODE_STRING  InputDeviceName,
LPSTR  OutputDriveLetter
 

Definition at line 191 of file w32/ntuser/server/harderr.c.

References ARRAY_SIZE, CHAR, L, NT_SUCCESS, NtClose(), NtOpenSymbolicLinkObject(), NtQuerySymbolicLinkObject(), NTSTATUS(), NULL, RtlEqualUnicodeString(), RtlInitUnicodeString(), Status, TRUE, and wszDosDevices.

Referenced by GetHardErrorText().

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 // Open succeeded, Now get the link value 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 }

VOID UserExitWorkerThread VOID   ) 
 

Referenced by ConsoleInputThread(), HardErrorWorkerThread(), and UnlockConsole().

VOID UserHardError PCSR_THREAD  pt,
PHARDERROR_MSG  pmsg
 

Definition at line 1662 of file w32/ntuser/server/harderr.c.

References NULL, UserHardErrorEx(), and VOID().

Referenced by UserServerDllInitialization().

01665 { 01666 UserHardErrorEx(pt, pmsg, NULL); 01667 }

VOID UserHardErrorEx PCSR_THREAD  pt,
PHARDERROR_MSG  pmsg,
PCTXHARDERRORINFO  pCtxHEInfo
 

Definition at line 1686 of file w32/ntuser/server/harderr.c.

References ARRAY_SIZE, BOOL, tagHARDERRORINFO::dwHEIFFlags, DWORD, dwResponseDefault, EnterCrit, ErrorExit(), FALSE, FreePhi(), GetErrorMode(), GetHardErrorText(), gEventSource, gfnDeregisterEventSource, gphiList, HARDERRORINFO, HEIF_ALLOCATEDMSG, HEIF_DEREFTHREAD, HEIF_REPLIED, HEIF_SYSTEMERROR, tagHARDERRORINFO::hEventHardError, ISTS, L, LeaveCrit, LogErrorPopup(), NtClose(), NtReplyPort(), NtWaitForSingleObject(), NULL, tagHARDERRORINFO::pCtxHEInfo, tagHARDERRORINFO::phiNext, tagHARDERRORINFO::pmsg, ProcessHardErrorRequest(), tagHARDERRORINFO::pthread, ReplyHardError(), TRUE, UINT, tagHARDERRORINFO::usCaption, UserRegisterEventSource(), tagHARDERRORINFO::usText, and VOID().

Referenced by HardErrorInsert(), and UserHardError().

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 * Allocate memory to queue request. 01699 */ 01700 phi = (PHARDERRORINFO)LocalAlloc(LPTR, sizeof(HARDERRORINFO)); 01701 if (phi == NULL) { 01702 goto ErrorExit; 01703 } 01704 phi->pthread = pt; 01705 01706 /* 01707 * Set up citrix specific stuff 01708 */ 01709 if (ISTS()) { 01710 phi->pCtxHEInfo = pCtxHEInfo; 01711 } 01712 01713 /* 01714 * Determine reply type 01715 */ 01716 fClientPort = ((pt != NULL) && (pt->Process->ClientPort != NULL)); 01717 fNoWait = (pmsg->ValidResponseOptions == OptionOkNoWait); 01718 01719 /* 01720 * Capture HARDERROR_MSG data or create wait event as needed 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 * Set the magic response value (-1) to let CsrApiRequestThread know 01732 * that we'll take care of dereferencing and replying. 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 * There is no reply port but we need to wait; create an event. 01745 */ 01746 hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 01747 if (hEvent == NULL) { 01748 goto ErrorExit; 01749 } 01750 phi->hEventHardError = hEvent; 01751 } 01752 01753 /* 01754 * Build hard error title, message and flags. Then log the event. 01755 */ 01756 GetHardErrorText(phi); 01757 01758 /* 01759 * Reply now if we're not going to wait. 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 * Must let CsrApiRequestThread reply since we don't have a port 01769 */ 01770 pmsg->Response = ResponseOk; 01771 /* 01772 * If we have a thread, reference it because we're telling 01773 * CsrApiRequestThread that we're done with it. 01774 */ 01775 if (pt != NULL) { 01776 /* 01777 * Later5.0 GerardoB. Let's stop to see how this happens. 01778 */ 01779 UserAssert(pt == NULL); 01780 CsrReferenceThread(pt); 01781 } 01782 } 01783 } 01784 01785 /* 01786 * Register the event if we haven't done so already. 01787 * Since RegisterEventSource is supported by a service, we must not hold 01788 * any locks while making this call. Hence we might have several threads 01789 * registering the event simultaneously. 01790 */ 01791 fLogEvent = (gEventSource != NULL); 01792 if (!fLogEvent) { 01793 HANDLE hEventSource; 01794 hEventSource = UserRegisterEventSource(L"Application Popup"); 01795 /* 01796 * Save the first handle, deregister all others. 01797 */ 01798 if (InterlockedCompareExchangePointer(&gEventSource, hEventSource, NULL) == NULL) { 01799 /* 01800 * This is the first handle. If valid, we can log events. 01801 */ 01802 fLogEvent = (hEventSource != NULL); 01803 } else { 01804 /* 01805 * We had already saved another handle (so we can log events). Deregister this one. 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 * Determine if we need to display a message box. 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 * If we don't have to display a message box, we're done. 01838 */ 01839 if (!fMsgBox) { 01840 goto DontNeedErrorHandler; 01841 } 01842 01843 /* 01844 * We want to display a message box. Queue the request and go for it. 01845 */ 01846 EnterCrit(); 01847 /* 01848 * Never mind if the process has terminated. Got to check this holding the 01849 * critical section to make sure that no other thread makes it to BoostHardError 01850 * before we add this phi to the list. 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 * Add it to the end of the list. 01863 */ 01864 pphiLast = &gphiList; 01865 while (*pphiLast != NULL) { 01866 pphiLast = &(*pphiLast)->phiNext; 01867 } 01868 *pphiLast = phi; 01869 LeaveCrit(); 01870 01871 /* 01872 * Process the hard error request. If this is a NoWait request and there 01873 * is no reply port, then we'll try to launch a new worker thread so this 01874 * one can return. 01875 */ 01876 ProcessHardErrorRequest(fNoWait && !fClientPort); 01877 01878 /* 01879 * If there is an event handle, wait for it. 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 }

HANDLE UserRegisterEventSource PCWSTR  pwszSourceName  ) 
 

Definition at line 99 of file w32/ntuser/server/harderr.c.

References EnterCrit, gfnDeregisterEventSource, gfnRegisterEventSource, gfnReportEvent, L, LeaveCrit, and NULL.

Referenced by UserHardErrorEx().

00101 { 00102 /* 00103 * If we haven't already dynamically linked to advadpi32.dll, do it now. 00104 */ 00105 if (gfnRegisterEventSource == NULL) { 00106 HINSTANCE hAdvApiDll; 00107 FARPROC fnRegisterEventSource; 00108 FARPROC fnDeregisterEventSource; 00109 FARPROC fnReportEvent; 00110 00111 /* 00112 * Try to load the DLL and function pointers. 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 * Update the global function pointers if they're not set already. 00127 */ 00128 EnterCrit(); 00129 if (gfnRegisterEventSource == NULL) { 00130 gfnReportEvent = fnReportEvent; 00131 gfnDeregisterEventSource = fnDeregisterEventSource; 00132 // This must be last since we test it above 00133 gfnRegisterEventSource = fnRegisterEventSource; 00134 hAdvApiDll = NULL; 00135 } 00136 LeaveCrit(); 00137 00138 /* 00139 * If another thread beat us to it, free the library. 00140 */ 00141 if (hAdvApiDll) { 00142 FreeLibrary(hAdvApiDll); 00143 } 00144 } 00145 00146 /* 00147 * Let's be paranoid and verify we loaded everything correctly. 00148 */ 00149 UserAssert(gfnRegisterEventSource != NULL); 00150 UserAssert(gfnDeregisterEventSource != NULL); 00151 UserAssert(gfnReportEvent != NULL); 00152 00153 /* 00154 * Call the real function. 00155 */ 00156 return (HANDLE)gfnRegisterEventSource(NULL, pwszSourceName); 00157 }


Variable Documentation

CONST DWORD dwResponseDefault[]
 

Initial value:

{ ResponseAbort, ResponseOk, ResponseOk, ResponseCancel, ResponseYes, ResponseYes, ResponseOk, ResponseOk, ResponseCancel }

Definition at line 62 of file w32/ntuser/server/harderr.c.

Referenced by UserHardErrorEx().

CONST DWORD dwResponses[]
 

Initial value:

{ ResponseNotHandled, ResponseOk, ResponseCancel, ResponseAbort, ResponseRetry, ResponseIgnore, ResponseYes, ResponseNo, ResponseNotHandled, ResponseNotHandled, ResponseTryAgain, ResponseContinue }

Definition at line 48 of file w32/ntuser/server/harderr.c.

Referenced by HardErrorHandler().

BOOLEAN gbExitInProgress
 

Definition at line 17 of file w32/ntuser/server/harderr.c.

FARPROC gfnDeregisterEventSource
 

Definition at line 86 of file w32/ntuser/server/harderr.c.

Referenced by UserHardErrorEx(), and UserRegisterEventSource().

FARPROC gfnRegisterEventSource
 

Definition at line 85 of file w32/ntuser/server/harderr.c.

Referenced by UserRegisterEventSource().

FARPROC gfnReportEvent
 

Definition at line 87 of file w32/ntuser/server/harderr.c.

Referenced by LogErrorPopup(), and UserRegisterEventSource().

BOOL gfTimedOut = FALSE
 

Definition at line 18 of file w32/ntuser/server/harderr.c.

Referenced by HardErrorHandler(), and MsgBoxTimerFunc().

UINT_PTR gTimerId = 0 [static]
 

Definition at line 77 of file w32/ntuser/server/harderr.c.

Referenced by HardErrorHandler().

CONST UINT wIcons[]
 

Initial value:

{ 0, MB_ICONINFORMATION, MB_ICONEXCLAMATION, MB_ICONSTOP }

Definition at line 31 of file w32/ntuser/server/harderr.c.

Referenced by GetHardErrorText().

CONST UINT wOptions[]
 

Initial value:

{ MB_ABORTRETRYIGNORE, MB_OK, MB_OKCANCEL, MB_RETRYCANCEL, MB_YESNO, MB_YESNOCANCEL, MB_OK, MB_OK, MB_CANCELTRYCONTINUE }

Definition at line 37 of file w32/ntuser/server/harderr.c.

Referenced by GetHardErrorText().

WCHAR wszDosDevices[] = L"\\??\\A:" [static]
 

Definition at line 189 of file w32/ntuser/server/harderr.c.

Referenced by SubstituteDeviceName().


Generated on Sat May 15 19:44:02 2004 for test by doxygen 1.3.7