Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1228 lines
34 KiB

  1. /*++
  2. Copyright (c) 1991-2002 Microsoft Corporation
  3. Module Name:
  4. erwatch.cpp
  5. Abstract:
  6. This module contains the code to report pending watchdog timeout
  7. events at logon after dirty reboot.
  8. Author:
  9. Michael Maciesowicz (mmacie) 29-May-2001
  10. Environment:
  11. User mode at logon.
  12. Revision History:
  13. --*/
  14. #include "savedump.h"
  15. #include <ntverp.h>
  16. BOOL
  17. WriteWatchdogEventFile(
  18. IN HANDLE FileHandle,
  19. IN PWSTR String
  20. );
  21. BOOL
  22. WriteWatchdogEventFileHeader(
  23. IN HANDLE FileHandle
  24. )
  25. {
  26. WCHAR Buffer[256];
  27. BOOL Status;
  28. SYSTEMTIME Time;
  29. TIME_ZONE_INFORMATION TimeZone;
  30. Status = WriteWatchdogEventFile(FileHandle,
  31. L"//\r\n// Watchdog Event Log File\r\n//\r\n\r\n");
  32. if (TRUE == Status)
  33. {
  34. Status = WriteWatchdogEventFile(FileHandle, L"LogType: Watchdog\r\n");
  35. }
  36. if (TRUE == Status)
  37. {
  38. GetLocalTime(&Time);
  39. if (StringCchPrintf(Buffer,
  40. RTL_NUMBER_OF(Buffer),
  41. L"Created: %d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d\r\n",
  42. Time.wYear,
  43. Time.wMonth,
  44. Time.wDay,
  45. Time.wHour,
  46. Time.wMinute,
  47. Time.wSecond) != S_OK)
  48. {
  49. Status = FALSE;
  50. }
  51. else
  52. {
  53. Status = WriteWatchdogEventFile(FileHandle, Buffer);
  54. }
  55. }
  56. if (TRUE == Status)
  57. {
  58. GetTimeZoneInformation(&TimeZone);
  59. if (StringCchPrintf(Buffer,
  60. RTL_NUMBER_OF(Buffer),
  61. L"TimeZone: %d - %s\r\n",
  62. TimeZone.Bias,
  63. TimeZone.StandardName) != S_OK)
  64. {
  65. Status = FALSE;
  66. }
  67. else
  68. {
  69. Status = WriteWatchdogEventFile(FileHandle, Buffer);
  70. }
  71. }
  72. if (TRUE == Status)
  73. {
  74. if (StringCchPrintf(Buffer, RTL_NUMBER_OF(Buffer),
  75. L"WindowsVersion: " LVER_PRODUCTVERSION_STR
  76. L"\r\n") != S_OK)
  77. {
  78. Status = FALSE;
  79. }
  80. else
  81. {
  82. Status = WriteWatchdogEventFile(FileHandle, Buffer);
  83. }
  84. }
  85. if (TRUE == Status)
  86. {
  87. Status = WriteWatchdogEventFile(FileHandle,
  88. L"EventType: 0xEA - Thread Stuck in Device Driver\r\n");
  89. }
  90. return Status;
  91. }
  92. HANDLE
  93. CreateWatchdogEventFile(
  94. OUT PWSTR FileName
  95. )
  96. {
  97. INT Retry;
  98. WCHAR DirName[MAX_PATH];
  99. SYSTEMTIME Time;
  100. HANDLE FileHandle;
  101. ULONG ReturnedSize;
  102. ASSERT(NULL != FileName);
  103. //
  104. // Create %SystemRoot%\LogFiles\Watchdog directory for event files.
  105. //
  106. ReturnedSize = GetWindowsDirectory(DirName, RTL_NUMBER_OF(DirName));
  107. if (ReturnedSize < 1 || ReturnedSize >= RTL_NUMBER_OF(DirName))
  108. {
  109. return INVALID_HANDLE_VALUE;
  110. }
  111. if (StringCchCat(DirName, RTL_NUMBER_OF(DirName), L"\\LogFiles") != S_OK)
  112. {
  113. return INVALID_HANDLE_VALUE;
  114. }
  115. CreateDirectory(DirName, NULL);
  116. if (StringCchCat(DirName, RTL_NUMBER_OF(DirName), L"\\WatchDog") != S_OK)
  117. {
  118. return INVALID_HANDLE_VALUE;
  119. }
  120. CreateDirectory(DirName, NULL);
  121. //
  122. // Create watchdog event file as YYMMDD_HHMM_NN.wdl.
  123. //
  124. GetLocalTime(&Time);
  125. for (Retry = 1; Retry < ER_WD_MAX_RETRY; Retry++)
  126. {
  127. if (StringCchPrintf(FileName,
  128. MAX_PATH,
  129. L"%s\\%2.2d%2.2d%2.2d_%2.2d%2.2d_%2.2d.wdl",
  130. DirName,
  131. Time.wYear % 100,
  132. Time.wMonth,
  133. Time.wDay,
  134. Time.wHour,
  135. Time.wMinute,
  136. Retry) != S_OK)
  137. {
  138. return INVALID_HANDLE_VALUE;
  139. }
  140. FileHandle = CreateFile(FileName,
  141. GENERIC_WRITE,
  142. FILE_SHARE_READ,
  143. NULL,
  144. CREATE_NEW,
  145. FILE_ATTRIBUTE_NORMAL,
  146. NULL);
  147. if (INVALID_HANDLE_VALUE != FileHandle)
  148. {
  149. break;
  150. }
  151. }
  152. //
  153. // If we failed to create a suitable file name just fail.
  154. //
  155. if (Retry == ER_WD_MAX_RETRY)
  156. {
  157. return INVALID_HANDLE_VALUE;
  158. }
  159. if (!WriteWatchdogEventFileHeader(FileHandle))
  160. {
  161. CloseHandle(FileHandle);
  162. DeleteFile(FileName);
  163. FileHandle = INVALID_HANDLE_VALUE;
  164. }
  165. return FileHandle;
  166. }
  167. VOID
  168. GetDriverInfo(
  169. IN HKEY Key,
  170. IN OPTIONAL PWCHAR Extension,
  171. OUT PER_WD_DRIVER_INFO DriverInfo
  172. )
  173. /*++
  174. Routine Description:
  175. This routine collects driver's version info.
  176. Arguments:
  177. Key - Watchdog open key (device specific).
  178. Extension - Driver file name extension if one should be appended.
  179. DriverInfo - Storage for driver version info.
  180. --*/
  181. {
  182. PVOID VersionBuffer;
  183. PVOID VersionValue;
  184. LONG WinStatus;
  185. DWORD Handle;
  186. ULONG Index;
  187. USHORT CodePage;
  188. UINT Length;
  189. if (NULL == DriverInfo)
  190. {
  191. return;
  192. }
  193. ZeroMemory(DriverInfo, sizeof (ER_WD_DRIVER_INFO));
  194. //
  195. // Get driver file name from registry.
  196. //
  197. if (GetRegStr(Key, L"DriverName",
  198. DriverInfo->DriverName,
  199. RTL_NUMBER_OF(DriverInfo->DriverName),
  200. NULL) != S_OK)
  201. {
  202. StringCchCopy(DriverInfo->DriverName,
  203. RTL_NUMBER_OF(DriverInfo->DriverName),
  204. L"Unknown");
  205. return;
  206. }
  207. if (Extension)
  208. {
  209. if ((wcslen(DriverInfo->DriverName) <= wcslen(Extension)) ||
  210. wcscmp(DriverInfo->DriverName + wcslen(DriverInfo->DriverName) -
  211. wcslen(Extension), Extension))
  212. {
  213. if (StringCchCat(DriverInfo->DriverName,
  214. RTL_NUMBER_OF(DriverInfo->DriverName),
  215. Extension) != S_OK)
  216. {
  217. StringCchCopy(DriverInfo->DriverName,
  218. RTL_NUMBER_OF(DriverInfo->DriverName),
  219. L"Unknown");
  220. return;
  221. }
  222. }
  223. }
  224. Length = GetFileVersionInfoSize(DriverInfo->DriverName, &Handle);
  225. if (Length)
  226. {
  227. VersionBuffer = malloc(Length);
  228. if (NULL != VersionBuffer)
  229. {
  230. if (GetFileVersionInfo(DriverInfo->DriverName, Handle,
  231. Length, VersionBuffer))
  232. {
  233. //
  234. // Get fixed file info.
  235. //
  236. if (VerQueryValue(VersionBuffer,
  237. L"\\",
  238. &VersionValue,
  239. &Length) &&
  240. Length == sizeof(DriverInfo->FixedFileInfo))
  241. {
  242. CopyMemory(&(DriverInfo->FixedFileInfo),
  243. VersionValue,
  244. Length);
  245. }
  246. //
  247. // Try to locate English code page.
  248. //
  249. CodePage = 0;
  250. if (VerQueryValue(VersionBuffer,
  251. L"\\VarFileInfo\\Translation",
  252. &VersionValue,
  253. &Length))
  254. {
  255. for (Index = 0;
  256. Index < Length / sizeof (ER_WD_LANG_AND_CODE_PAGE);
  257. Index++)
  258. {
  259. if (((PER_WD_LANG_AND_CODE_PAGE)VersionValue + Index)->
  260. Language == ER_WD_LANG_ENGLISH)
  261. {
  262. CodePage = ((PER_WD_LANG_AND_CODE_PAGE)
  263. VersionValue + Index)->CodePage;
  264. break;
  265. }
  266. }
  267. }
  268. if (CodePage)
  269. {
  270. WCHAR ValueName[ER_WD_MAX_NAME_LENGTH + 1];
  271. PWCHAR Destination[] =
  272. {
  273. DriverInfo->Comments,
  274. DriverInfo->CompanyName,
  275. DriverInfo->FileDescription,
  276. DriverInfo->FileVersion,
  277. DriverInfo->InternalName,
  278. DriverInfo->LegalCopyright,
  279. DriverInfo->LegalTrademarks,
  280. DriverInfo->OriginalFilename,
  281. DriverInfo->PrivateBuild,
  282. DriverInfo->ProductName,
  283. DriverInfo->ProductVersion,
  284. DriverInfo->SpecialBuild,
  285. NULL
  286. };
  287. PWCHAR Source[] =
  288. {
  289. L"Comments",
  290. L"CompanyName",
  291. L"FileDescription",
  292. L"FileVersion",
  293. L"InternalName",
  294. L"LegalCopyright",
  295. L"LegalTrademarks",
  296. L"OriginalFilename",
  297. L"PrivateBuild",
  298. L"ProductName",
  299. L"ProductVersion",
  300. L"SpecialBuild",
  301. NULL
  302. };
  303. //
  304. // Read version properties.
  305. //
  306. for (Index = 0;
  307. Source[Index] && Destination[Index];
  308. Index++)
  309. {
  310. if (StringCchPrintf(ValueName,
  311. RTL_NUMBER_OF(ValueName),
  312. L"\\StringFileInfo\\%04X%04X\\%s",
  313. ER_WD_LANG_ENGLISH,
  314. CodePage,
  315. Source[Index]) == S_OK &&
  316. VerQueryValue(VersionBuffer,
  317. ValueName,
  318. &VersionValue,
  319. &Length))
  320. {
  321. CopyMemory(Destination[Index],
  322. VersionValue,
  323. min(Length * sizeof (WCHAR),
  324. ER_WD_MAX_FILE_INFO_LENGTH *
  325. sizeof (WCHAR)));
  326. }
  327. }
  328. }
  329. }
  330. free(VersionBuffer);
  331. }
  332. }
  333. }
  334. #define MAX_DATA_CHARS (ER_WD_MAX_DATA_SIZE / sizeof(WCHAR))
  335. BOOL
  336. SaveWatchdogEventData(
  337. IN HANDLE FileHandle,
  338. IN HKEY Key,
  339. IN PER_WD_DRIVER_INFO DriverInfo
  340. )
  341. /*++
  342. Routine Description:
  343. This routine transfers watchdog event data from registry to
  344. the watchdog event report file.
  345. Arguments:
  346. FileHandle - Handle of open watchdog event report file.
  347. Key - Watchdog open key (device specific).
  348. Return Value:
  349. TRUE if successful, FALSE otherwise.
  350. --*/
  351. {
  352. LONG WinStatus;
  353. DWORD Index;
  354. DWORD NameLength;
  355. DWORD DataSize;
  356. DWORD ReturnedSize;
  357. DWORD Type;
  358. WCHAR Name[ER_WD_MAX_NAME_LENGTH + 1];
  359. WCHAR DwordBuffer[20];
  360. PBYTE Data;
  361. BOOL Status = TRUE;
  362. ASSERT(INVALID_HANDLE_VALUE != FileHandle);
  363. Data = (PBYTE)malloc(ER_WD_MAX_DATA_SIZE);
  364. if (NULL == Data)
  365. {
  366. return FALSE;
  367. }
  368. //
  369. // Pull watchdog data from registry and write it to report.
  370. //
  371. for (Index = 0;; Index++)
  372. {
  373. //
  374. // Read watchdog registry value.
  375. //
  376. NameLength = ER_WD_MAX_NAME_LENGTH;
  377. DataSize = ER_WD_MAX_DATA_SIZE;
  378. WinStatus = RegEnumValue(Key,
  379. Index,
  380. Name,
  381. &NameLength,
  382. NULL,
  383. &Type,
  384. Data,
  385. &DataSize);
  386. if (ERROR_NO_MORE_ITEMS == WinStatus)
  387. {
  388. break;
  389. }
  390. if (ERROR_SUCCESS != WinStatus)
  391. {
  392. continue;
  393. }
  394. //
  395. // Pick up strings and dwords only.
  396. //
  397. if ((REG_EXPAND_SZ == Type) || (REG_SZ == Type) ||
  398. (REG_MULTI_SZ == Type) || (REG_DWORD == Type))
  399. {
  400. //
  401. // Write registry entry to watchdog event file.
  402. //
  403. Status = WriteWatchdogEventFile(FileHandle, Name);
  404. if (TRUE != Status)
  405. {
  406. break;
  407. }
  408. Status = WriteWatchdogEventFile(FileHandle, L": ");
  409. if (TRUE != Status)
  410. {
  411. break;
  412. }
  413. if (REG_DWORD == Type)
  414. {
  415. if (StringCchPrintf(DwordBuffer, RTL_NUMBER_OF(DwordBuffer),
  416. L"%u", *(PULONG)Data) != S_OK)
  417. {
  418. Status = FALSE;
  419. }
  420. else
  421. {
  422. Status = WriteWatchdogEventFile(FileHandle, DwordBuffer);
  423. }
  424. }
  425. else
  426. {
  427. Status = WriteWatchdogEventFile(FileHandle, (PWSTR)Data);
  428. }
  429. if (TRUE != Status)
  430. {
  431. break;
  432. }
  433. Status = WriteWatchdogEventFile(FileHandle, L"\r\n");
  434. if (TRUE != Status)
  435. {
  436. break;
  437. }
  438. }
  439. }
  440. //
  441. // Write driver info to report.
  442. //
  443. if (NULL != DriverInfo)
  444. {
  445. if (TRUE == Status)
  446. {
  447. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  448. L"DriverFixedFileInfo: %08X %08X %08X %08X "
  449. L"%08X %08X %08X %08X %08X %08X %08X %08X %08X\r\n",
  450. DriverInfo->FixedFileInfo.dwSignature,
  451. DriverInfo->FixedFileInfo.dwStrucVersion,
  452. DriverInfo->FixedFileInfo.dwFileVersionMS,
  453. DriverInfo->FixedFileInfo.dwFileVersionLS,
  454. DriverInfo->FixedFileInfo.dwProductVersionMS,
  455. DriverInfo->FixedFileInfo.dwProductVersionLS,
  456. DriverInfo->FixedFileInfo.dwFileFlagsMask,
  457. DriverInfo->FixedFileInfo.dwFileFlags,
  458. DriverInfo->FixedFileInfo.dwFileOS,
  459. DriverInfo->FixedFileInfo.dwFileType,
  460. DriverInfo->FixedFileInfo.dwFileSubtype,
  461. DriverInfo->FixedFileInfo.dwFileDateMS,
  462. DriverInfo->FixedFileInfo.dwFileDateLS) != S_OK)
  463. {
  464. Status = FALSE;
  465. }
  466. else
  467. {
  468. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  469. }
  470. }
  471. if ((TRUE == Status) && DriverInfo->Comments[0])
  472. {
  473. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  474. L"DriverComments: %s\r\n",
  475. DriverInfo->Comments) != S_OK)
  476. {
  477. Status = FALSE;
  478. }
  479. else
  480. {
  481. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  482. }
  483. }
  484. if ((TRUE == Status) && DriverInfo->CompanyName[0])
  485. {
  486. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  487. L"DriverCompanyName: %s\r\n",
  488. DriverInfo->CompanyName) != S_OK)
  489. {
  490. Status = FALSE;
  491. }
  492. else
  493. {
  494. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  495. }
  496. }
  497. if ((TRUE == Status) && DriverInfo->FileDescription[0])
  498. {
  499. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  500. L"DriverFileDescription: %s\r\n",
  501. DriverInfo->FileDescription) != S_OK)
  502. {
  503. Status = FALSE;
  504. }
  505. else
  506. {
  507. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  508. }
  509. }
  510. if ((TRUE == Status) && DriverInfo->FileVersion[0])
  511. {
  512. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  513. L"DriverFileVersion: %s\r\n",
  514. DriverInfo->FileVersion) != S_OK)
  515. {
  516. Status = FALSE;
  517. }
  518. else
  519. {
  520. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  521. }
  522. }
  523. if ((TRUE == Status) && DriverInfo->InternalName[0])
  524. {
  525. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  526. L"DriverInternalName: %s\r\n",
  527. DriverInfo->InternalName) != S_OK)
  528. {
  529. Status = FALSE;
  530. }
  531. else
  532. {
  533. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  534. }
  535. }
  536. if ((TRUE == Status) && DriverInfo->LegalCopyright[0])
  537. {
  538. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  539. L"DriverLegalCopyright: %s\r\n",
  540. DriverInfo->LegalCopyright) != S_OK)
  541. {
  542. Status = FALSE;
  543. }
  544. else
  545. {
  546. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  547. }
  548. }
  549. if ((TRUE == Status) && DriverInfo->LegalTrademarks[0])
  550. {
  551. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  552. L"DriverLegalTrademarks: %s\r\n",
  553. DriverInfo->LegalTrademarks) != S_OK)
  554. {
  555. Status = FALSE;
  556. }
  557. else
  558. {
  559. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  560. }
  561. }
  562. if ((TRUE == Status) && DriverInfo->OriginalFilename[0])
  563. {
  564. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  565. L"DriverOriginalFilename: %s\r\n",
  566. DriverInfo->OriginalFilename) != S_OK)
  567. {
  568. Status = FALSE;
  569. }
  570. else
  571. {
  572. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  573. }
  574. }
  575. if ((TRUE == Status) && DriverInfo->PrivateBuild[0])
  576. {
  577. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  578. L"DriverPrivateBuild: %s\r\n",
  579. DriverInfo->PrivateBuild) != S_OK)
  580. {
  581. Status = FALSE;
  582. }
  583. else
  584. {
  585. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  586. }
  587. }
  588. if ((TRUE == Status) && DriverInfo->ProductName[0])
  589. {
  590. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  591. L"DriverProductName: %s\r\n",
  592. DriverInfo->ProductName) != S_OK)
  593. {
  594. Status = FALSE;
  595. }
  596. else
  597. {
  598. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  599. }
  600. }
  601. if ((TRUE == Status) && DriverInfo->ProductVersion[0])
  602. {
  603. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  604. L"DriverProductVersion: %s\r\n",
  605. DriverInfo->ProductVersion) != S_OK)
  606. {
  607. Status = FALSE;
  608. }
  609. else
  610. {
  611. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  612. }
  613. }
  614. if ((TRUE == Status) && DriverInfo->SpecialBuild[0])
  615. {
  616. if (StringCchPrintf((PWCHAR)Data, MAX_DATA_CHARS,
  617. L"DriverSpecialBuild: %s\r\n",
  618. DriverInfo->SpecialBuild) != S_OK)
  619. {
  620. Status = FALSE;
  621. }
  622. else
  623. {
  624. Status = WriteWatchdogEventFile(FileHandle, (PWCHAR)Data);
  625. }
  626. }
  627. }
  628. if (NULL != Data)
  629. {
  630. free(Data);
  631. Data = NULL;
  632. }
  633. return Status;
  634. }
  635. HRESULT
  636. WatchdogEventHandler(
  637. IN BOOL NotifyPcHealth
  638. )
  639. /*++
  640. Routine Description:
  641. This is the boot time routine to handle pending watchdog events.
  642. Arguments:
  643. NotifyPcHealth - TRUE if we should report event to PC Health, FALSE otherwise.
  644. --*/
  645. {
  646. HKEY Key;
  647. ULONG WinStatus;
  648. ULONG Type;
  649. ULONG Length;
  650. ULONG EventFlag;
  651. ULONG Index;
  652. SEventInfoW EventInfo;
  653. HANDLE FileHandle;
  654. WCHAR FileList[2 * MAX_PATH];
  655. PWSTR DeleteLog;
  656. PWSTR FinalFileList;
  657. WCHAR Stage2Url[ER_WD_MAX_URL_LENGTH + 1];
  658. PWCHAR MessageBuffer;
  659. PWCHAR DescriptionBuffer;
  660. PWCHAR DeviceDescription;
  661. PWCHAR String000;
  662. PWCHAR String001;
  663. PWCHAR String002;
  664. PWCHAR String003;
  665. PWCHAR String004;
  666. PWCHAR String005;
  667. BOOL LogStatus;
  668. HRESULT ReturnStatus;
  669. HINSTANCE Instance;
  670. PER_WD_DRIVER_INFO DriverInfo;
  671. OSVERSIONINFOEX OsVersion;
  672. Key = NULL;
  673. MessageBuffer = NULL;
  674. DescriptionBuffer = NULL;
  675. DeviceDescription = NULL;
  676. String000 = NULL;
  677. String001 = NULL;
  678. String002 = NULL;
  679. String003 = NULL;
  680. String004 = NULL;
  681. String005 = NULL;
  682. ReturnStatus = E_FAIL;
  683. Instance = (HINSTANCE)GetModuleHandle(NULL);
  684. DriverInfo = NULL;
  685. LogStatus = FALSE;
  686. DeleteLog = NULL;
  687. //
  688. // Check if Watchdog\Display key present.
  689. //
  690. WinStatus = RegOpenKey(HKEY_LOCAL_MACHINE,
  691. SUBKEY_WATCHDOG_DISPLAY,
  692. &Key);
  693. if (ERROR_SUCCESS != WinStatus)
  694. {
  695. return S_FALSE;
  696. }
  697. //
  698. // Check if watchdog display event captured.
  699. //
  700. GetRegWord32(Key, L"EventFlag", &EventFlag, 0, TRUE);
  701. if (!EventFlag)
  702. {
  703. ReturnStatus = S_FALSE;
  704. goto Exit;
  705. }
  706. //
  707. // Report watchdog event to PC Health if requested.
  708. //
  709. if (!NotifyPcHealth)
  710. {
  711. ReturnStatus = S_FALSE;
  712. goto Exit;
  713. }
  714. //
  715. // Allocate storage for localized strings.
  716. // Load localized strings from resources.
  717. //
  718. String000 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  719. String001 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  720. String002 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  721. String003 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  722. String004 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  723. String005 = (PWCHAR)malloc(ER_WD_MAX_STRING * sizeof(WCHAR));
  724. if (!String000 ||
  725. !LoadString(Instance, IDS_000, String000, ER_WD_MAX_STRING) ||
  726. !String001 ||
  727. !LoadString(Instance, IDS_001, String001, ER_WD_MAX_STRING) ||
  728. !String002 ||
  729. !LoadString(Instance, IDS_002, String002, ER_WD_MAX_STRING) ||
  730. !String003 ||
  731. !LoadString(Instance, IDS_003, String003, ER_WD_MAX_STRING) ||
  732. !String004 ||
  733. !LoadString(Instance, IDS_004, String004, ER_WD_MAX_STRING) ||
  734. !String005 ||
  735. !LoadString(Instance, IDS_005, String005, ER_WD_MAX_STRING))
  736. {
  737. ReturnStatus = E_OUTOFMEMORY;
  738. goto Exit;
  739. }
  740. //
  741. // Allocate and get DriverInfo data.
  742. // DriverInfo is not critical information so don't
  743. // quit on failure.
  744. //
  745. DriverInfo = (PER_WD_DRIVER_INFO)malloc(sizeof (ER_WD_DRIVER_INFO));
  746. if (NULL != DriverInfo)
  747. {
  748. GetDriverInfo(Key, L".dll", DriverInfo);
  749. }
  750. //
  751. // Create watchdog report file.
  752. //
  753. FileHandle = CreateWatchdogEventFile(FileList);
  754. if (INVALID_HANDLE_VALUE != FileHandle)
  755. {
  756. LogStatus = TRUE;
  757. DeleteLog = FileList + wcslen(FileList);
  758. }
  759. if (TRUE == LogStatus)
  760. {
  761. LogStatus = WriteWatchdogEventFile(
  762. FileHandle,
  763. L"\r\n//\r\n"
  764. L"// The driver for the display device got stuck in an infinite loop. This\r\n"
  765. L"// usually indicates a problem with the device itself or with the device\r\n"
  766. L"// driver programming the hardware incorrectly. Please check with your\r\n"
  767. L"// display device vendor for any driver updates.\r\n"
  768. L"//\r\n\r\n");
  769. }
  770. if (TRUE == LogStatus)
  771. {
  772. LogStatus = SaveWatchdogEventData(FileHandle, Key, DriverInfo);
  773. }
  774. if (INVALID_HANDLE_VALUE != FileHandle)
  775. {
  776. CloseHandle(FileHandle);
  777. }
  778. //
  779. // Append minidump file name if minidump available (server won't have it).
  780. //
  781. if (LogStatus)
  782. {
  783. if (g_MiniDumpFile[0])
  784. {
  785. if (StringCchCat(FileList, RTL_NUMBER_OF(FileList),
  786. L"|") != S_OK ||
  787. StringCchCat(FileList, RTL_NUMBER_OF(FileList),
  788. g_MiniDumpFile) != S_OK)
  789. {
  790. ReturnStatus = E_OUTOFMEMORY;
  791. goto Exit;
  792. }
  793. }
  794. FinalFileList = FileList;
  795. }
  796. else if (g_MiniDumpFile[0])
  797. {
  798. FinalFileList = g_MiniDumpFile;
  799. }
  800. else
  801. {
  802. // Nothing to report.
  803. ReturnStatus = S_FALSE;
  804. goto Exit;
  805. }
  806. //
  807. // Get device description.
  808. //
  809. DescriptionBuffer = NULL;
  810. DeviceDescription = NULL;
  811. Length = 0;
  812. WinStatus = RegQueryValueEx(Key,
  813. L"DeviceDescription",
  814. NULL,
  815. &Type,
  816. NULL,
  817. &Length);
  818. if (ERROR_SUCCESS == WinStatus && Type == REG_SZ)
  819. {
  820. DescriptionBuffer = (PWCHAR)malloc(Length + sizeof(WCHAR));
  821. if (NULL != DescriptionBuffer)
  822. {
  823. WinStatus = RegQueryValueEx(Key,
  824. L"DeviceDescription",
  825. NULL,
  826. &Type,
  827. (LPBYTE)DescriptionBuffer,
  828. &Length);
  829. DescriptionBuffer[Length / sizeof(WCHAR)] = 0;
  830. }
  831. else
  832. {
  833. Length = 0;
  834. }
  835. }
  836. else
  837. {
  838. WinStatus = ERROR_INVALID_PARAMETER;
  839. }
  840. if ((ERROR_SUCCESS == WinStatus) && (0 != Length))
  841. {
  842. DeviceDescription = DescriptionBuffer;
  843. }
  844. else
  845. {
  846. DeviceDescription = String004;
  847. Length = (ER_WD_MAX_STRING + 1) * sizeof (WCHAR);
  848. }
  849. Length += 2 * ER_WD_MAX_STRING * sizeof (WCHAR);
  850. MessageBuffer = (PWCHAR)malloc(Length);
  851. if (NULL != MessageBuffer)
  852. {
  853. // This should never overflow as we allocated the right amount.
  854. StringCbPrintf(MessageBuffer,
  855. Length,
  856. L"%s%s%s",
  857. String003,
  858. DeviceDescription,
  859. String005);
  860. }
  861. //
  862. // Create stage 2 URL and fill in EventInfo.
  863. //
  864. OsVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
  865. if (!GetVersionEx((LPOSVERSIONINFOW)&OsVersion))
  866. {
  867. ReturnStatus = LAST_HR();
  868. goto Exit;
  869. }
  870. ZeroMemory(&EventInfo, sizeof (EventInfo));
  871. if (g_DumpHeader.Signature == DUMP_SIGNATURE &&
  872. (g_DumpHeader.BugCheckCode & 0xff) == 0xea)
  873. {
  874. //
  875. // We bluescreened with bugcheck EA - we have minidump and wdl.
  876. //
  877. if ((ReturnStatus =
  878. StringCchPrintf(Stage2Url,
  879. RTL_NUMBER_OF(Stage2Url),
  880. L"\r\nStage2URL=/dw/BlueTwo.asp?"
  881. L"BCCode=%x&BCP1=%p&BCP2=%p&BCP3=%p&BCP4=%p&"
  882. L"OSVer=%d_%d_%d&SP=%d_%d&Product=%d_%d",
  883. g_DumpHeader.BugCheckCode,
  884. (PVOID)(g_DumpHeader.BugCheckParameter1),
  885. (PVOID)(g_DumpHeader.BugCheckParameter2),
  886. (PVOID)(g_DumpHeader.BugCheckParameter3),
  887. (PVOID)(g_DumpHeader.BugCheckParameter4),
  888. OsVersion.dwMajorVersion,
  889. OsVersion.dwMinorVersion,
  890. OsVersion.dwBuildNumber,
  891. OsVersion.wServicePackMajor,
  892. OsVersion.wServicePackMinor,
  893. OsVersion.wSuiteMask,
  894. OsVersion.wProductType)) != S_OK)
  895. {
  896. goto Exit;
  897. }
  898. EventInfo.wszCorpPath = L"blue";
  899. }
  900. else if (g_DumpHeader.Signature == DUMP_SIGNATURE &&
  901. 0 == g_DumpHeader.BugCheckCode)
  902. {
  903. //
  904. // User dirty rebooted with watchdog event trapped - we have only wdl.
  905. //
  906. if ((ReturnStatus =
  907. StringCchPrintf(Stage2Url,
  908. RTL_NUMBER_OF(Stage2Url),
  909. L"\r\nStage2URL=/dw/ShutdownTwo.asp?"
  910. L"OSVer=%d_%d_%d&SP=%d_%d&Product=%d_%d",
  911. OsVersion.dwMajorVersion,
  912. OsVersion.dwMinorVersion,
  913. OsVersion.dwBuildNumber,
  914. OsVersion.wServicePackMajor,
  915. OsVersion.wServicePackMinor,
  916. OsVersion.wSuiteMask,
  917. OsVersion.wProductType)) != S_OK)
  918. {
  919. goto Exit;
  920. }
  921. EventInfo.wszCorpPath = L"shutdown";
  922. }
  923. else
  924. {
  925. ReturnStatus = E_UNEXPECTED;
  926. goto Exit;
  927. }
  928. EventInfo.cbSEI = sizeof (EventInfo);
  929. EventInfo.wszEventName = L"Thread Stuck in Device Driver";
  930. EventInfo.wszErrMsg = String002;
  931. EventInfo.wszHdr = String001;
  932. EventInfo.wszTitle = String000;
  933. EventInfo.wszStage1 = NULL;
  934. EventInfo.wszStage2 = Stage2Url;
  935. EventInfo.wszFileList = FinalFileList;
  936. EventInfo.wszEventSrc = NULL;
  937. EventInfo.wszPlea = MessageBuffer;
  938. EventInfo.wszSendBtn = NULL;
  939. EventInfo.wszNoSendBtn = NULL;
  940. EventInfo.fUseLitePlea = FALSE;
  941. EventInfo.fUseIEForURLs = FALSE;
  942. EventInfo.fNoBucketLogs = TRUE;
  943. EventInfo.fNoDefCabLimit = TRUE;
  944. //
  945. // Notify PC Health.
  946. //
  947. ReturnStatus =
  948. FrrvToStatus(ReportEREvent(eetUseEventInfo, NULL, &EventInfo));
  949. // XXX drewb - Leave the log around for later use? When does
  950. // this get deleted? This is what previous code did.
  951. DeleteLog = NULL;
  952. Exit:
  953. //
  954. // Knock down watchdog's EventFlag. We do this after registering our
  955. // event with PC Health.
  956. //
  957. if (Key)
  958. {
  959. RegDeleteValue(Key, L"EventFlag");
  960. RegCloseKey(Key);
  961. }
  962. //
  963. // TODO: Handle additional device classes here when supported.
  964. //
  965. if (DeleteLog)
  966. {
  967. *DeleteLog = 0;
  968. DeleteFile(FileList);
  969. }
  970. free(DescriptionBuffer);
  971. free(MessageBuffer);
  972. free(String000);
  973. free(String001);
  974. free(String002);
  975. free(String003);
  976. free(String004);
  977. free(String005);
  978. free(DriverInfo);
  979. return ReturnStatus;
  980. }
  981. BOOL
  982. WriteWatchdogEventFile(
  983. IN HANDLE FileHandle,
  984. IN PWSTR String
  985. )
  986. /*++
  987. Routine Description:
  988. This routine writes a string to watchdog event report file.
  989. Arguments:
  990. FileHandle - Handle of open watchdog event report file.
  991. String - Points to the string to write.
  992. Return Value:
  993. TRUE if successful, FALSE otherwise.
  994. --*/
  995. {
  996. DWORD Size;
  997. DWORD ReturnedSize;
  998. PCHAR MultiByte;
  999. BOOL Status;
  1000. ASSERT(INVALID_HANDLE_VALUE != FileHandle);
  1001. ASSERT(NULL != String);
  1002. //
  1003. // Get buffer size for translated string.
  1004. //
  1005. Size = WideCharToMultiByte(CP_ACP,
  1006. 0,
  1007. String,
  1008. -1,
  1009. NULL,
  1010. 0,
  1011. NULL,
  1012. NULL);
  1013. if (Size <= 1)
  1014. {
  1015. return Size > 0;
  1016. }
  1017. MultiByte = (PCHAR)malloc(Size);
  1018. if (NULL == MultiByte)
  1019. {
  1020. return FALSE;
  1021. }
  1022. Size = WideCharToMultiByte(CP_ACP,
  1023. 0,
  1024. String,
  1025. -1,
  1026. MultiByte,
  1027. Size,
  1028. NULL,
  1029. NULL);
  1030. if (Size > 0)
  1031. {
  1032. Status = WriteFile(FileHandle,
  1033. MultiByte,
  1034. Size - 1,
  1035. &ReturnedSize,
  1036. NULL);
  1037. }
  1038. else
  1039. {
  1040. ASSERT(FALSE);
  1041. Status = FALSE;
  1042. }
  1043. free(MultiByte);
  1044. return Status;
  1045. }