/*++ Copyright (c) 1991-2002 Microsoft Corporation Module Name: erwatch.cpp Abstract: This module contains the code to report pending watchdog timeout events at logon after dirty reboot. Author: Michael Maciesowicz (mmacie) 29-May-2001 Environment: User mode at logon. Revision History: --*/ #include "savedump.h" #include BOOL WriteWatchdogEventFile( IN HANDLE FileHandle, IN PWSTR String ); BOOL WriteWatchdogEventFileHeader( IN HANDLE FileHandle ) { WCHAR Buffer[256]; BOOL Status; SYSTEMTIME Time; TIME_ZONE_INFORMATION TimeZone; Status = WriteWatchdogEventFile(FileHandle, L"//\r\n// Watchdog Event Log File\r\n//\r\n\r\n"); if (TRUE == Status) { Status = WriteWatchdogEventFile(FileHandle, L"LogType: Watchdog\r\n"); } if (TRUE == Status) { GetLocalTime(&Time); if (StringCchPrintf(Buffer, RTL_NUMBER_OF(Buffer), L"Created: %d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d\r\n", Time.wYear, Time.wMonth, Time.wDay, Time.wHour, Time.wMinute, Time.wSecond) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, Buffer); } } if (TRUE == Status) { GetTimeZoneInformation(&TimeZone); if (StringCchPrintf(Buffer, RTL_NUMBER_OF(Buffer), L"TimeZone: %d - %s\r\n", TimeZone.Bias, TimeZone.StandardName) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, Buffer); } } if (TRUE == Status) { if (StringCchPrintf(Buffer, RTL_NUMBER_OF(Buffer), L"WindowsVersion: " LVER_PRODUCTVERSION_STR L"\r\n") != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, Buffer); } } if (TRUE == Status) { Status = WriteWatchdogEventFile(FileHandle, L"EventType: 0xEA - Thread Stuck in Device Driver\r\n"); } return Status; } HANDLE CreateWatchdogEventFile( OUT PWSTR FileName ) { INT Retry; WCHAR DirName[MAX_PATH]; SYSTEMTIME Time; HANDLE FileHandle; ULONG ReturnedSize; ASSERT(NULL != FileName); // // Create %SystemRoot%\LogFiles\Watchdog directory for event files. // ReturnedSize = GetWindowsDirectory(DirName, RTL_NUMBER_OF(DirName)); if (ReturnedSize < 1 || ReturnedSize >= RTL_NUMBER_OF(DirName)) { return INVALID_HANDLE_VALUE; } if (StringCchCat(DirName, RTL_NUMBER_OF(DirName), L"\\LogFiles") != S_OK) { return INVALID_HANDLE_VALUE; } CreateDirectory(DirName, NULL); if (StringCchCat(DirName, RTL_NUMBER_OF(DirName), L"\\WatchDog") != S_OK) { return INVALID_HANDLE_VALUE; } CreateDirectory(DirName, NULL); // // Create watchdog event file as YYMMDD_HHMM_NN.wdl. // GetLocalTime(&Time); for (Retry = 1; Retry < ER_WD_MAX_RETRY; Retry++) { if (StringCchPrintf(FileName, MAX_PATH, L"%s\\%2.2d%2.2d%2.2d_%2.2d%2.2d_%2.2d.wdl", DirName, Time.wYear % 100, Time.wMonth, Time.wDay, Time.wHour, Time.wMinute, Retry) != S_OK) { return INVALID_HANDLE_VALUE; } FileHandle = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != FileHandle) { break; } } // // If we failed to create a suitable file name just fail. // if (Retry == ER_WD_MAX_RETRY) { return INVALID_HANDLE_VALUE; } if (!WriteWatchdogEventFileHeader(FileHandle)) { CloseHandle(FileHandle); DeleteFile(FileName); FileHandle = INVALID_HANDLE_VALUE; } return FileHandle; } VOID GetDriverInfo( IN HKEY Key, IN OPTIONAL PWCHAR Extension, OUT PER_WD_DRIVER_INFO DriverInfo ) /*++ Routine Description: This routine collects driver's version info. Arguments: Key - Watchdog open key (device specific). Extension - Driver file name extension if one should be appended. DriverInfo - Storage for driver version info. --*/ { PVOID VersionBuffer; PVOID VersionValue; LONG WinStatus; DWORD Handle; ULONG Index; USHORT CodePage; UINT Length; if (NULL == DriverInfo) { return; } ZeroMemory(DriverInfo, sizeof (ER_WD_DRIVER_INFO)); // // Get driver file name from registry. // if (GetRegStr(Key, L"DriverName", DriverInfo->DriverName, RTL_NUMBER_OF(DriverInfo->DriverName), NULL) != S_OK) { StringCchCopy(DriverInfo->DriverName, RTL_NUMBER_OF(DriverInfo->DriverName), L"Unknown"); return; } if (Extension) { if ((wcslen(DriverInfo->DriverName) <= wcslen(Extension)) || wcscmp(DriverInfo->DriverName + wcslen(DriverInfo->DriverName) - wcslen(Extension), Extension)) { if (StringCchCat(DriverInfo->DriverName, RTL_NUMBER_OF(DriverInfo->DriverName), Extension) != S_OK) { StringCchCopy(DriverInfo->DriverName, RTL_NUMBER_OF(DriverInfo->DriverName), L"Unknown"); return; } } } Length = GetFileVersionInfoSize(DriverInfo->DriverName, &Handle); if (Length) { VersionBuffer = malloc(Length); if (NULL != VersionBuffer) { if (GetFileVersionInfo(DriverInfo->DriverName, Handle, Length, VersionBuffer)) { // // Get fixed file info. // if (VerQueryValue(VersionBuffer, L"\\", &VersionValue, &Length) && Length == sizeof(DriverInfo->FixedFileInfo)) { CopyMemory(&(DriverInfo->FixedFileInfo), VersionValue, Length); } // // Try to locate English code page. // CodePage = 0; if (VerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation", &VersionValue, &Length)) { for (Index = 0; Index < Length / sizeof (ER_WD_LANG_AND_CODE_PAGE); Index++) { if (((PER_WD_LANG_AND_CODE_PAGE)VersionValue + Index)-> Language == ER_WD_LANG_ENGLISH) { CodePage = ((PER_WD_LANG_AND_CODE_PAGE) VersionValue + Index)->CodePage; break; } } } if (CodePage) { WCHAR ValueName[ER_WD_MAX_NAME_LENGTH + 1]; PWCHAR Destination[] = { DriverInfo->Comments, DriverInfo->CompanyName, DriverInfo->FileDescription, DriverInfo->FileVersion, DriverInfo->InternalName, DriverInfo->LegalCopyright, DriverInfo->LegalTrademarks, DriverInfo->OriginalFilename, DriverInfo->PrivateBuild, DriverInfo->ProductName, DriverInfo->ProductVersion, DriverInfo->SpecialBuild, NULL }; PWCHAR Source[] = { L"Comments", L"CompanyName", L"FileDescription", L"FileVersion", L"InternalName", L"LegalCopyright", L"LegalTrademarks", L"OriginalFilename", L"PrivateBuild", L"ProductName", L"ProductVersion", L"SpecialBuild", NULL }; // // Read version properties. // for (Index = 0; Source[Index] && Destination[Index]; Index++) { if (StringCchPrintf(ValueName, RTL_NUMBER_OF(ValueName), L"\\StringFileInfo\\%04X%04X\\%s", ER_WD_LANG_ENGLISH, CodePage, Source[Index]) == S_OK && VerQueryValue(VersionBuffer, ValueName, &VersionValue, &Length)) { CopyMemory(Destination[Index], VersionValue, min(Length * sizeof (WCHAR), ER_WD_MAX_FILE_INFO_LENGTH * sizeof (WCHAR))); } } } } free(VersionBuffer); } } } #define MAX_DATA_CHARS (ER_WD_MAX_DATA_SIZE / sizeof(WCHAR)) BOOL SaveWatchdogEventData( IN HANDLE FileHandle, IN HKEY Key, IN PER_WD_DRIVER_INFO DriverInfo ) /*++ Routine Description: This routine transfers watchdog event data from registry to the watchdog event report file. Arguments: FileHandle - Handle of open watchdog event report file. Key - Watchdog open key (device specific). Return Value: TRUE if successful, FALSE otherwise. --*/ { LONG WinStatus; DWORD Index; DWORD NameLength; DWORD DataSize; DWORD ReturnedSize; DWORD Type; WCHAR Name[ER_WD_MAX_NAME_LENGTH + 1]; WCHAR DwordBuffer[20]; PBYTE Data; BOOL Status = TRUE; ASSERT(INVALID_HANDLE_VALUE != FileHandle); Data = (PBYTE)malloc(ER_WD_MAX_DATA_SIZE); if (NULL == Data) { return FALSE; } // // Pull watchdog data from registry and write it to report. // for (Index = 0;; Index++) { // // Read watchdog registry value. // NameLength = ER_WD_MAX_NAME_LENGTH; DataSize = ER_WD_MAX_DATA_SIZE; WinStatus = RegEnumValue(Key, Index, Name, &NameLength, NULL, &Type, Data, &DataSize); if (ERROR_NO_MORE_ITEMS == WinStatus) { break; } if (ERROR_SUCCESS != WinStatus) { continue; } // // Pick up strings and dwords only. // if ((REG_EXPAND_SZ == Type) || (REG_SZ == Type) || (REG_MULTI_SZ == Type) || (REG_DWORD == Type)) { // // Write registry entry to watchdog event file. // Status = WriteWatchdogEventFile(FileHandle, Name); if (TRUE != Status) { break; } Status = WriteWatchdogEventFile(FileHandle, L": "); if (TRUE != Status) { break; } if (REG_DWORD == Type) { if (StringCchPrintf(DwordBuffer, RTL_NUMBER_OF(DwordBuffer), L"%u", *(PULONG)Data) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, DwordBuffer); } } else { Status = WriteWatchdogEventFile(FileHandle, (PWSTR)Data); } if (TRUE != Status) { break; } Status = WriteWatchdogEventFile(FileHandle, L"\r\n"); if (TRUE != Status) { break; } } } // // Write driver info to report. // if (NULL != DriverInfo) { if (TRUE == Status) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverFixedFileInfo: %08X %08X %08X %08X " L"%08X %08X %08X %08X %08X %08X %08X %08X %08X\r\n", DriverInfo->FixedFileInfo.dwSignature, DriverInfo->FixedFileInfo.dwStrucVersion, DriverInfo->FixedFileInfo.dwFileVersionMS, DriverInfo->FixedFileInfo.dwFileVersionLS, DriverInfo->FixedFileInfo.dwProductVersionMS, DriverInfo->FixedFileInfo.dwProductVersionLS, DriverInfo->FixedFileInfo.dwFileFlagsMask, DriverInfo->FixedFileInfo.dwFileFlags, DriverInfo->FixedFileInfo.dwFileOS, DriverInfo->FixedFileInfo.dwFileType, DriverInfo->FixedFileInfo.dwFileSubtype, DriverInfo->FixedFileInfo.dwFileDateMS, DriverInfo->FixedFileInfo.dwFileDateLS) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->Comments[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverComments: %s\r\n", DriverInfo->Comments) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->CompanyName[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverCompanyName: %s\r\n", DriverInfo->CompanyName) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->FileDescription[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverFileDescription: %s\r\n", DriverInfo->FileDescription) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->FileVersion[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverFileVersion: %s\r\n", DriverInfo->FileVersion) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->InternalName[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverInternalName: %s\r\n", DriverInfo->InternalName) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->LegalCopyright[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverLegalCopyright: %s\r\n", DriverInfo->LegalCopyright) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->LegalTrademarks[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverLegalTrademarks: %s\r\n", DriverInfo->LegalTrademarks) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->OriginalFilename[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverOriginalFilename: %s\r\n", DriverInfo->OriginalFilename) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->PrivateBuild[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverPrivateBuild: %s\r\n", DriverInfo->PrivateBuild) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->ProductName[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverProductName: %s\r\n", DriverInfo->ProductName) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->ProductVersion[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverProductVersion: %s\r\n", DriverInfo->ProductVersion) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } if ((TRUE == Status) && DriverInfo->SpecialBuild[0]) { if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS, L"DriverSpecialBuild: %s\r\n", DriverInfo->SpecialBuild) != S_OK) { Status = FALSE; } else { Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data); } } } if (NULL != Data) { free(Data); Data = NULL; } return Status; } HRESULT WatchdogEventHandler( IN BOOL NotifyPcHealth ) /*++ Routine Description: This is the boot time routine to handle pending watchdog events. Arguments: NotifyPcHealth - TRUE if we should report event to PC Health, FALSE otherwise. --*/ { HKEY Key; ULONG WinStatus; ULONG Type; ULONG Length; ULONG EventFlag; ULONG Index; SEventInfoW EventInfo; HANDLE FileHandle; WCHAR FileList[2 * MAX_PATH]; PWSTR DeleteLog; PWSTR FinalFileList; WCHAR Stage2Url[ER_WD_MAX_URL_LENGTH + 1]; PWCHAR MessageBuffer; PWCHAR DescriptionBuffer; PWCHAR DeviceDescription; PWCHAR String000; PWCHAR String001; PWCHAR String002; PWCHAR String003; PWCHAR String004; PWCHAR String005; BOOL LogStatus; HRESULT ReturnStatus; HINSTANCE Instance; PER_WD_DRIVER_INFO DriverInfo; OSVERSIONINFOEX OsVersion; Key = NULL; MessageBuffer = NULL; DescriptionBuffer = NULL; DeviceDescription = NULL; String000 = NULL; String001 = NULL; String002 = NULL; String003 = NULL; String004 = NULL; String005 = NULL; ReturnStatus = E_FAIL; Instance = (HINSTANCE)GetModuleHandle(NULL); DriverInfo = NULL; LogStatus = FALSE; DeleteLog = NULL; // // Check if Watchdog\Display key present. // WinStatus = RegOpenKey(HKEY_LOCAL_MACHINE, SUBKEY_WATCHDOG_DISPLAY, &Key); if (ERROR_SUCCESS != WinStatus) { return S_FALSE; } // // Check if watchdog display event captured. // GetRegWord32(Key, L"EventFlag", &EventFlag, 0, TRUE); if (!EventFlag) { ReturnStatus = S_FALSE; goto Exit; } // // Report watchdog event to PC Health if requested. // if (!NotifyPcHealth) { ReturnStatus = S_FALSE; goto Exit; } // // Allocate storage for localized strings. // Load localized strings from resources. // String000 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); String001 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); String002 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); String003 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); String004 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); String005 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR)); if (!String000 || !LoadString(Instance, IDS_000, String000, ER_WD_MAX_STRING) || !String001 || !LoadString(Instance, IDS_001, String001, ER_WD_MAX_STRING) || !String002 || !LoadString(Instance, IDS_002, String002, ER_WD_MAX_STRING) || !String003 || !LoadString(Instance, IDS_003, String003, ER_WD_MAX_STRING) || !String004 || !LoadString(Instance, IDS_004, String004, ER_WD_MAX_STRING) || !String005 || !LoadString(Instance, IDS_005, String005, ER_WD_MAX_STRING)) { ReturnStatus = E_OUTOFMEMORY; goto Exit; } // // Allocate and get DriverInfo data. // DriverInfo is not critical information so don't // quit on failure. // DriverInfo = (PER_WD_DRIVER_INFO)malloc(sizeof (ER_WD_DRIVER_INFO)); if (NULL != DriverInfo) { GetDriverInfo(Key, L".dll", DriverInfo); } // // Create watchdog report file. // FileHandle = CreateWatchdogEventFile(FileList); if (INVALID_HANDLE_VALUE != FileHandle) { LogStatus = TRUE; DeleteLog = FileList + wcslen(FileList); } if (TRUE == LogStatus) { LogStatus = WriteWatchdogEventFile( FileHandle, L"\r\n//\r\n" L"// The driver for the display device got stuck in an infinite loop. This\r\n" L"// usually indicates a problem with the device itself or with the device\r\n" L"// driver programming the hardware incorrectly. Please check with your\r\n" L"// display device vendor for any driver updates.\r\n" L"//\r\n\r\n"); } if (TRUE == LogStatus) { LogStatus = SaveWatchdogEventData(FileHandle, Key, DriverInfo); } if (INVALID_HANDLE_VALUE != FileHandle) { CloseHandle(FileHandle); } // // Append minidump file name if minidump available (server won't have it). // if (LogStatus) { if (g_MiniDumpFile[0]) { if (StringCchCat(FileList, RTL_NUMBER_OF(FileList), L"|") != S_OK || StringCchCat(FileList, RTL_NUMBER_OF(FileList), g_MiniDumpFile) != S_OK) { ReturnStatus = E_OUTOFMEMORY; goto Exit; } } FinalFileList = FileList; } else if (g_MiniDumpFile[0]) { FinalFileList = g_MiniDumpFile; } else { // Nothing to report. ReturnStatus = S_FALSE; goto Exit; } // // Get device description. // DescriptionBuffer = NULL; DeviceDescription = NULL; Length = 0; WinStatus = RegQueryValueEx(Key, L"DeviceDescription", NULL, &Type, NULL, &Length); if (ERROR_SUCCESS == WinStatus && Type == REG_SZ) { DescriptionBuffer = (PWCHAR)malloc(Length + sizeof(WCHAR)); if (NULL != DescriptionBuffer) { WinStatus = RegQueryValueEx(Key, L"DeviceDescription", NULL, &Type, (LPBYTE)DescriptionBuffer, &Length); DescriptionBuffer[Length / sizeof(WCHAR)] = 0; } else { Length = 0; } } else { WinStatus = ERROR_INVALID_PARAMETER; } if ((ERROR_SUCCESS == WinStatus) && (0 != Length)) { DeviceDescription = DescriptionBuffer; } else { DeviceDescription = String004; Length = (ER_WD_MAX_STRING + 1) * sizeof (WCHAR); } Length += 2 * ER_WD_MAX_STRING * sizeof (WCHAR); MessageBuffer = (PWCHAR)malloc(Length); if (NULL != MessageBuffer) { // This should never overflow as we allocated the right amount. StringCbPrintf(MessageBuffer, Length, L"%s%s%s", String003, DeviceDescription, String005); } // // Create stage 2 URL and fill in EventInfo. // OsVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); if (!GetVersionEx((LPOSVERSIONINFOW)&OsVersion)) { ReturnStatus = LAST_HR(); goto Exit; } ZeroMemory(&EventInfo, sizeof (EventInfo)); if (g_DumpHeader.Signature == DUMP_SIGNATURE && (g_DumpHeader.BugCheckCode & 0xff) == 0xea) { // // We bluescreened with bugcheck EA - we have minidump and wdl. // if ((ReturnStatus = StringCchPrintf(Stage2Url, RTL_NUMBER_OF(Stage2Url), L"\r\nStage2URL=/dw/BlueTwo.asp?" L"BCCode=%x&BCP1=%p&BCP2=%p&BCP3=%p&BCP4=%p&" L"OSVer=%d_%d_%d&SP=%d_%d&Product=%d_%d", g_DumpHeader.BugCheckCode, (PVOID)(g_DumpHeader.BugCheckParameter1), (PVOID)(g_DumpHeader.BugCheckParameter2), (PVOID)(g_DumpHeader.BugCheckParameter3), (PVOID)(g_DumpHeader.BugCheckParameter4), OsVersion.dwMajorVersion, OsVersion.dwMinorVersion, OsVersion.dwBuildNumber, OsVersion.wServicePackMajor, OsVersion.wServicePackMinor, OsVersion.wSuiteMask, OsVersion.wProductType)) != S_OK) { goto Exit; } EventInfo.wszCorpPath = L"blue"; } else if (g_DumpHeader.Signature == DUMP_SIGNATURE && 0 == g_DumpHeader.BugCheckCode) { // // User dirty rebooted with watchdog event trapped - we have only wdl. // if ((ReturnStatus = StringCchPrintf(Stage2Url, RTL_NUMBER_OF(Stage2Url), L"\r\nStage2URL=/dw/ShutdownTwo.asp?" L"OSVer=%d_%d_%d&SP=%d_%d&Product=%d_%d", OsVersion.dwMajorVersion, OsVersion.dwMinorVersion, OsVersion.dwBuildNumber, OsVersion.wServicePackMajor, OsVersion.wServicePackMinor, OsVersion.wSuiteMask, OsVersion.wProductType)) != S_OK) { goto Exit; } EventInfo.wszCorpPath = L"shutdown"; } else { ReturnStatus = E_UNEXPECTED; goto Exit; } EventInfo.cbSEI = sizeof (EventInfo); EventInfo.wszEventName = L"Thread Stuck in Device Driver"; EventInfo.wszErrMsg = String002; EventInfo.wszHdr = String001; EventInfo.wszTitle = String000; EventInfo.wszStage1 = NULL; EventInfo.wszStage2 = Stage2Url; EventInfo.wszFileList = FinalFileList; EventInfo.wszEventSrc = NULL; EventInfo.wszPlea = MessageBuffer; EventInfo.wszSendBtn = NULL; EventInfo.wszNoSendBtn = NULL; EventInfo.fUseLitePlea = FALSE; EventInfo.fUseIEForURLs = FALSE; EventInfo.fNoBucketLogs = TRUE; EventInfo.fNoDefCabLimit = TRUE; // // Notify PC Health. // ReturnStatus = FrrvToStatus(ReportEREvent(eetUseEventInfo, NULL, &EventInfo)); // XXX drewb - Leave the log around for later use? When does // this get deleted? This is what previous code did. DeleteLog = NULL; Exit: // // Knock down watchdog's EventFlag. We do this after registering our // event with PC Health. // if (Key) { RegDeleteValue(Key, L"EventFlag"); RegCloseKey(Key); } // // TODO: Handle additional device classes here when supported. // if (DeleteLog) { *DeleteLog = 0; DeleteFile(FileList); } free(DescriptionBuffer); free(MessageBuffer); free(String000); free(String001); free(String002); free(String003); free(String004); free(String005); free(DriverInfo); return ReturnStatus; } BOOL WriteWatchdogEventFile( IN HANDLE FileHandle, IN PWSTR String ) /*++ Routine Description: This routine writes a string to watchdog event report file. Arguments: FileHandle - Handle of open watchdog event report file. String - Points to the string to write. Return Value: TRUE if successful, FALSE otherwise. --*/ { DWORD Size; DWORD ReturnedSize; PCHAR MultiByte; BOOL Status; ASSERT(INVALID_HANDLE_VALUE != FileHandle); ASSERT(NULL != String); // // Get buffer size for translated string. // Size = WideCharToMultiByte(CP_ACP, 0, String, -1, NULL, 0, NULL, NULL); if (Size <= 1) { return Size > 0; } MultiByte = (PCHAR)malloc(Size); if (NULL == MultiByte) { return FALSE; } Size = WideCharToMultiByte(CP_ACP, 0, String, -1, MultiByte, Size, NULL, NULL); if (Size > 0) { Status = WriteFile(FileHandle, MultiByte, Size - 1, &ReturnedSize, NULL); } else { ASSERT(FALSE); Status = FALSE; } free(MultiByte); return Status; }