Source code of Windows XP (NT5)
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.

1187 lines
26 KiB

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997 Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6. crashdmp.c
  7. Abstract:
  8. Implements the "Recovery" group on the Startup/Recovery
  9. dialog of the System Control Panel Applet
  10. Notes:
  11. The virtual memory settings and the crash dump (core dump) settings
  12. are tightly-coupled. Therefore, crashdmp.c and startup.h have some
  13. heavy dependencies on virtual.c and virtual.h (and vice versa).
  14. Author:
  15. Byron Dazey 06-Jun-1992
  16. Revision History:
  17. 15-Oct-1997 scotthal
  18. Complete overhaul
  19. --*/
  20. #include "sysdm.h"
  21. #include <windowsx.h>
  22. #define KBYTE (1024UI64)
  23. #define MBYTE (1024UI64 * KBYTE)
  24. #define GBYTE (1024UI64 * MBYTE)
  25. //
  26. // CrashDumpEnabled is not a boolean value anymore. It can take on one of the
  27. // following types.
  28. //
  29. #define DUMP_TYPE_NONE (0)
  30. #define DUMP_TYPE_MINI (1)
  31. #define DUMP_TYPE_SUMMARY (2)
  32. #define DUMP_TYPE_FULL (3)
  33. #define DUMP_TYPE_MAX (4)
  34. #define REG_LOG_EVENT_VALUE_NAME TEXT ("LogEvent")
  35. #define REG_SEND_ALERT_VALUE_NAME TEXT ("SendAlert")
  36. #define REG_OVERWRITE_VALUE_NAME TEXT ("Overwrite")
  37. #define REG_AUTOREBOOT_VALUE_NAME TEXT ("AutoReboot")
  38. #define REG_DUMPFILE_VALUE_NAME TEXT ("DumpFile")
  39. #define REG_MINIDUMP_DIR_VALUE_NAME TEXT ("MinidumpDir")
  40. #define REG_DUMP_TYPE_VALUE_NAME TEXT ("CrashDumpEnabled")
  41. #define BIG_MEMORY_MAX_BOOT_PF_MB (2048)
  42. #define CRASH_CONTROL_KEY TEXT("System\\CurrentControlSet\\Control\\CrashControl")
  43. //
  44. // The crashdump code is hard-coded to generate only summary dumps for
  45. // machines with more than 2 GB of physical memory. Do not change this
  46. // constant unless unless you change the same code in ntos\io\dumpctl.c
  47. //
  48. #define LARGE_MEMORY_THRESHOLD (2 * GBYTE)
  49. typedef struct _SYSTEM_MEMORY_CONFIGURATION {
  50. BOOL BigMemory;
  51. ULONG PageSize;
  52. ULONG64 PhysicalMemorySize;
  53. ULONG64 BootPartitionPageFileSize;
  54. TCHAR BootDrive;
  55. } SYSTEM_MEMORY_CONFIGURATION;
  56. VCREG_RET gvcCrashCtrl = VCREG_ERROR;
  57. HKEY ghkeyCrashCtrl = NULL;
  58. int gcrefCrashCtrl = 0;
  59. BOOL gfCoreDumpChanged = FALSE;
  60. TCHAR CrashDumpFile [MAX_PATH] = TEXT("%SystemRoot%\\MEMORY.DMP");
  61. TCHAR MiniDumpDirectory [MAX_PATH] = TEXT("%SystemRoot%\\Minidump");
  62. TCHAR DumpFileText [100];
  63. TCHAR MiniDumpDirText [100];
  64. SYSTEM_MEMORY_CONFIGURATION SystemMemoryConfiguration;
  65. //
  66. // Private function prototypes
  67. //
  68. DWORD
  69. GetDumpSelection(
  70. HWND hDlg
  71. );
  72. NTSTATUS
  73. GetMemoryConfiguration(
  74. OUT SYSTEM_MEMORY_CONFIGURATION * MemoryConfig
  75. );
  76. VOID
  77. DisableCoreDumpControls(
  78. HWND hDlg
  79. );
  80. static
  81. BOOL
  82. CoreDumpInit(
  83. IN HWND hDlg
  84. );
  85. static
  86. BOOL
  87. CoreDumpUpdateRegistry(
  88. IN HWND hDlg,
  89. IN HKEY hKey
  90. );
  91. int
  92. CoreDumpHandleOk(
  93. IN BOOL fInitialized,
  94. IN HWND hDlg,
  95. IN WPARAM wParam,
  96. IN LPARAM lParam
  97. );
  98. VOID
  99. SwapDumpSelection(
  100. HWND hDlg
  101. );
  102. //
  103. // Implementation
  104. //
  105. VCREG_RET
  106. CoreDumpOpenKey(
  107. )
  108. {
  109. if (gvcCrashCtrl == VCREG_ERROR) {
  110. gvcCrashCtrl = OpenRegKey( CRASH_CONTROL_KEY, &ghkeyCrashCtrl );
  111. }
  112. if (gvcCrashCtrl != VCREG_ERROR) {
  113. gcrefCrashCtrl++;
  114. }
  115. return gvcCrashCtrl;
  116. }
  117. void
  118. CoreDumpCloseKey(
  119. )
  120. {
  121. if (gcrefCrashCtrl > 0) {
  122. gcrefCrashCtrl--;
  123. if (gcrefCrashCtrl == 0) {
  124. CloseRegKey( ghkeyCrashCtrl );
  125. gvcCrashCtrl = VCREG_ERROR;
  126. }
  127. }
  128. }
  129. BOOL
  130. StartAlerterService(
  131. IN SC_HANDLE hAlerter
  132. )
  133. {
  134. BOOL fResult = FALSE;
  135. fResult = ChangeServiceConfig(
  136. hAlerter,
  137. SERVICE_NO_CHANGE,
  138. SERVICE_AUTO_START,
  139. SERVICE_NO_CHANGE,
  140. NULL,
  141. NULL,
  142. NULL,
  143. NULL,
  144. NULL,
  145. NULL,
  146. NULL
  147. );
  148. fResult = StartService(hAlerter, 0, NULL);
  149. return(fResult);
  150. }
  151. BOOL
  152. IsAlerterSvcStarted(
  153. HWND hDlg
  154. )
  155. {
  156. SC_HANDLE schSCManager, schService = NULL;
  157. LPQUERY_SERVICE_CONFIG lpqscBuf;
  158. DWORD dwBytesNeeded;
  159. BOOL fRunning = FALSE;
  160. SERVICE_STATUS ssSrvcStat;
  161. /*
  162. * Open the Service Controller
  163. */
  164. schSCManager = OpenSCManager(
  165. NULL, /* local machine */
  166. NULL, /* ServicesActive database */
  167. SC_MANAGER_ALL_ACCESS); /* full access rights */
  168. if (schSCManager == NULL) {
  169. goto iassExit;
  170. }
  171. /*
  172. * Try to open the Alerter Service
  173. */
  174. /* Open a handle to the service. */
  175. schService = OpenService(
  176. schSCManager, /* SCManager database */
  177. TEXT("Alerter"), /* name of service */
  178. SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START
  179. );
  180. if (schService == NULL) {
  181. goto iassExit;
  182. }
  183. /*
  184. * Query the Alerter service to see if it has been started
  185. */
  186. if (!QueryServiceStatus(schService, &ssSrvcStat )) {
  187. goto iassExit;
  188. }
  189. if (ssSrvcStat.dwCurrentState != SERVICE_RUNNING) {
  190. fRunning = StartAlerterService(schService);
  191. } else {
  192. fRunning = TRUE;
  193. }
  194. iassExit:
  195. if (!fRunning) {
  196. MsgBoxParam(hDlg, IDS_SYSDM_NOALERTER, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION );
  197. }
  198. if (schService != NULL) {
  199. CloseServiceHandle(schService);
  200. }
  201. if (schSCManager != NULL) {
  202. CloseServiceHandle(schSCManager);
  203. }
  204. return fRunning;
  205. }
  206. BOOL
  207. VerifyDumpPath(
  208. IN HWND hDlg
  209. )
  210. {
  211. TCHAR szPath[MAX_PATH];
  212. TCHAR szExpPath[MAX_PATH];
  213. LPTSTR psz;
  214. TCHAR ch;
  215. UINT uType;
  216. if( GetDlgItemText(hDlg, IDC_STARTUP_CDMP_FILENAME, szPath,
  217. ARRAYSIZE(szPath)) == 0) {
  218. MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_FILENAME, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK);
  219. return FALSE;
  220. }
  221. /*
  222. * Expand any environment vars, and then check to make sure it
  223. * is a fully quallified path
  224. */
  225. // if it has a '%' in it, then try to expand it
  226. if (ExpandEnvironmentStrings(szPath, szExpPath, ARRAYSIZE(szExpPath)) >= ARRAYSIZE(szExpPath)) {
  227. MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_PATHLONG, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK,
  228. (DWORD)MAX_PATH);
  229. return FALSE;
  230. }
  231. // now cannonicalize it
  232. GetFullPathName( szExpPath, ARRAYSIZE(szPath), szPath, &psz );
  233. // check to see that it already was cannonicalized
  234. if (lstrcmp( szPath, szExpPath ) != 0) {
  235. MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_UNQUALIFIED, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK );
  236. return FALSE;
  237. }
  238. /*
  239. * check the drive (don't allow remote)
  240. */
  241. ch = szPath[3];
  242. szPath[3] = TEXT('\0');
  243. if (IsPathSep(szPath[0]) || ((uType = GetDriveType(szPath)) !=
  244. DRIVE_FIXED && uType != DRIVE_REMOVABLE)) {
  245. MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_DRIVE, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK );
  246. return FALSE;
  247. }
  248. szPath[3] = ch;
  249. /*
  250. * if path is non-exstant, tell user and let him decide what to do
  251. */
  252. if (GetFileAttributes(szPath) == 0xFFFFFFFFL && GetLastError() !=
  253. ERROR_FILE_NOT_FOUND && MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_PATH, IDS_SYSDM_TITLE,
  254. MB_ICONQUESTION | MB_YESNO ) == IDYES) {
  255. return FALSE;
  256. }
  257. return TRUE;
  258. }
  259. BOOL
  260. CoreDumpValidFile(
  261. HWND hDlg
  262. )
  263. {
  264. switch (GetDumpSelection (hDlg)) {
  265. case DUMP_TYPE_NONE:
  266. return TRUE;
  267. case DUMP_TYPE_MINI:
  268. return VerifyDumpPath (hDlg);
  269. case DUMP_TYPE_SUMMARY:
  270. case DUMP_TYPE_FULL:
  271. return VerifyDumpPath (hDlg);
  272. default:
  273. ASSERT (FALSE);
  274. return TRUE;
  275. }
  276. return FALSE;
  277. }
  278. int
  279. APIENTRY
  280. CoreDumpDlgProc(
  281. HWND hDlg,
  282. UINT message,
  283. WPARAM wParam,
  284. LPARAM lParam
  285. )
  286. {
  287. static BOOL fInitialized = FALSE;
  288. switch (message)
  289. {
  290. case WM_INITDIALOG:
  291. g_fStartupInitializing = TRUE;
  292. fInitialized = CoreDumpInit(hDlg);
  293. g_fStartupInitializing = FALSE;
  294. return RET_CONTINUE;
  295. break;
  296. case WM_COMMAND:
  297. switch (LOWORD(wParam)) {
  298. case IDOK:
  299. return(CoreDumpHandleOk(fInitialized, hDlg, wParam, lParam));
  300. break;
  301. case IDCANCEL:
  302. if (fInitialized) {
  303. VirtualCloseKey();
  304. CoreDumpCloseKey();
  305. }
  306. // Let the Startup/Recovery dlg proc also handle IDOK
  307. return(RET_NO_CHANGE);
  308. break;
  309. case IDC_STARTUP_CDMP_TYPE: {
  310. SwapDumpSelection (hDlg);
  311. }
  312. // Fall through
  313. case IDC_STARTUP_CDMP_FILENAME:
  314. case IDC_STARTUP_CDMP_LOG:
  315. case IDC_STARTUP_CDMP_SEND:
  316. case IDC_STARTUP_CDMP_OVERWRITE:
  317. case IDC_STARTUP_CDMP_AUTOREBOOT:
  318. if (!g_fStartupInitializing) {
  319. gfCoreDumpChanged = TRUE;
  320. }
  321. break;
  322. default: {
  323. // indicat not handled
  324. return RET_CONTINUE;
  325. }
  326. }
  327. break; // WM_COMMAND
  328. case WM_DESTROY:
  329. return RET_CONTINUE;
  330. break;
  331. default:
  332. return RET_CONTINUE;
  333. }
  334. return RET_BREAK;
  335. }
  336. int
  337. CoreDumpHandleOk(
  338. IN BOOL fInitialized,
  339. IN HWND hDlg,
  340. IN WPARAM wParam,
  341. IN LPARAM lParam
  342. )
  343. {
  344. BOOL fRegChg;
  345. NTSTATUS Status;
  346. DWORD Ret;
  347. int iRet = RET_NO_CHANGE;
  348. SYSTEM_MEMORY_CONFIGURATION MemoryConfig = {0};
  349. if (fInitialized && gfCoreDumpChanged)
  350. {
  351. // Validate crashdump file name.
  352. if (!CoreDumpValidFile(hDlg))
  353. {
  354. SetFocus(GetDlgItem(hDlg, IDC_STARTUP_CDMP_FILENAME));
  355. SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  356. iRet = RET_ERROR;
  357. return iRet;
  358. }
  359. Status = GetMemoryConfiguration(&MemoryConfig);
  360. if (NT_SUCCESS (Status) &&
  361. MemoryConfig.BootPartitionPageFileSize <
  362. CoreDumpGetRequiredFileSize (hDlg))
  363. {
  364. // Warn that the dump file may be truncated.
  365. Ret = MsgBoxParam (hDlg,
  366. IDS_SYSDM_DEBUGGING_MINIMUM,
  367. IDS_SYSDM_TITLE,
  368. MB_ICONEXCLAMATION | MB_YESNO,
  369. (MemoryConfig.BootDrive ? MemoryConfig.BootDrive : TEXT('?')),
  370. (DWORD) (CoreDumpGetRequiredFileSize (hDlg) / MBYTE)
  371. );
  372. if (Ret == IDNO)
  373. {
  374. return RET_ERROR;
  375. }
  376. }
  377. // If the Alert button is checked, make sure the alerter service
  378. // is started.
  379. if (IsDlgButtonChecked(hDlg, IDC_STARTUP_CDMP_SEND))
  380. {
  381. IsAlerterSvcStarted(hDlg);
  382. }
  383. fRegChg = CoreDumpUpdateRegistry (hDlg, ghkeyCrashCtrl);
  384. // Clean up registry stuff
  385. CoreDumpCloseKey();
  386. VirtualCloseKey();
  387. if (fRegChg)
  388. {
  389. // Notify the kernel to reread the crashdump parameters from the registry.
  390. Status = NtSetSystemInformation(SystemCrashDumpStateInformation, NULL, 0);
  391. if (NT_SUCCESS(Status))
  392. {
  393. iRet = RET_CHANGE_NO_REBOOT;
  394. }
  395. else
  396. {
  397. iRet = RET_RECOVER_CHANGE;
  398. }
  399. }
  400. } else {
  401. iRet = RET_NO_CHANGE;
  402. }
  403. return(iRet);
  404. }
  405. void
  406. CoreDumpInitErrorExit(
  407. HWND hDlg,
  408. HKEY hk
  409. )
  410. {
  411. MsgBoxParam(hDlg, IDS_SYSDM_NOOPEN_RECOVER_GROUP, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION);
  412. if( hk == ghkeyMemMgt )
  413. VirtualCloseKey();
  414. DisableCoreDumpControls(hDlg);
  415. HourGlass(FALSE);
  416. return;
  417. }
  418. DWORD
  419. GetDumpSelection(
  420. HWND hDlg
  421. )
  422. {
  423. HWND hControl;
  424. hControl = GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE);
  425. return ComboBox_GetCurSel ( hControl );
  426. }
  427. VOID
  428. DisableCoreDumpControls(
  429. HWND hDlg
  430. )
  431. {
  432. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_GRP), FALSE);
  433. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_TXT1), FALSE);
  434. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_LOG ), FALSE);
  435. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_SEND), FALSE);
  436. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE), FALSE);
  437. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), FALSE);
  438. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE);
  439. EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_AUTOREBOOT), FALSE);
  440. }
  441. VOID
  442. SwapDumpSelection(
  443. HWND hDlg
  444. )
  445. {
  446. //
  447. // If there is no dump type, disable some controls. If this is a minidump
  448. // disable overwrite and change "File Name:" to "Mini Dump Directory:"
  449. //
  450. switch (GetDumpSelection (hDlg)) {
  451. case DUMP_TYPE_NONE:
  452. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE);
  453. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), FALSE);
  454. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), FALSE);
  455. SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME),
  456. CrashDumpFile
  457. );
  458. Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL),
  459. DumpFileText
  460. );
  461. break;
  462. case DUMP_TYPE_MINI:
  463. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE);
  464. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), TRUE);
  465. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), TRUE);
  466. SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME),
  467. MiniDumpDirectory
  468. );
  469. Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL),
  470. MiniDumpDirText
  471. );
  472. break;
  473. default:
  474. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), TRUE);
  475. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), TRUE);
  476. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), TRUE);
  477. SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME),
  478. CrashDumpFile
  479. );
  480. Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL),
  481. DumpFileText
  482. );
  483. }
  484. }
  485. BOOL
  486. GetSystemDrive(
  487. OUT TCHAR * Drive
  488. )
  489. {
  490. TCHAR WindowsDir [ MAX_PATH ];
  491. if (!GetWindowsDirectory (WindowsDir, ARRAYSIZE (WindowsDir))) {
  492. return FALSE;
  493. }
  494. if (!isalpha (*WindowsDir)) {
  495. return FALSE;
  496. }
  497. *Drive = *WindowsDir;
  498. return TRUE;
  499. }
  500. NTSTATUS
  501. GetMemoryConfiguration(
  502. OUT SYSTEM_MEMORY_CONFIGURATION * MemoryConfig
  503. )
  504. {
  505. BOOL Succ;
  506. TCHAR SystemDrive;
  507. NTSTATUS Status;
  508. SYSTEM_BASIC_INFORMATION BasicInfo;
  509. ULONGLONG iMaxPageFileSize;
  510. Status = NtQuerySystemInformation(
  511. SystemBasicInformation,
  512. &BasicInfo,
  513. sizeof (BasicInfo),
  514. NULL
  515. );
  516. if (NT_SUCCESS (Status)) {
  517. Status;
  518. }
  519. MemoryConfig->PhysicalMemorySize =
  520. (ULONG64) BasicInfo.NumberOfPhysicalPages *
  521. (ULONG64) BasicInfo.PageSize;
  522. MemoryConfig->PageSize = BasicInfo.PageSize;
  523. //
  524. // Get the Boot-partition pagefile size.
  525. //
  526. Succ = GetSystemDrive (&SystemDrive);
  527. if (!Succ) {
  528. return FALSE;
  529. }
  530. MemoryConfig->BootDrive = (WCHAR) toupper (SystemDrive);
  531. SystemDrive = tolower (SystemDrive) - 'a';
  532. //
  533. // A big memory machine is one that has more memory than we can write to
  534. // at crashdump time.
  535. //
  536. iMaxPageFileSize = GetMaxPagefileSizeInMB(SystemDrive);
  537. iMaxPageFileSize *= (1024 * 1024); // MaxPageFileSize stored in megabytes
  538. if ((ULONGLONG)MemoryConfig->PhysicalMemorySize >= iMaxPageFileSize) {
  539. MemoryConfig->BigMemory = TRUE;
  540. } else {
  541. MemoryConfig->BigMemory = FALSE;
  542. }
  543. //
  544. // NOTE: apf is a global exposed by virtual.c
  545. //
  546. Succ = VirtualGetPageFiles ( apf );
  547. if (!Succ) {
  548. return FALSE;
  549. }
  550. //
  551. // This is the file size in terms of megabytes.
  552. //
  553. MemoryConfig->BootPartitionPageFileSize = apf [ SystemDrive ].nMinFileSize;
  554. //
  555. // Convert to bytes.
  556. //
  557. MemoryConfig->BootPartitionPageFileSize *= MBYTE;
  558. VirtualFreePageFiles ( apf );
  559. return STATUS_SUCCESS;
  560. }
  561. BOOL
  562. CheckInitFromRegistry(
  563. IN HWND hDlg,
  564. IN DWORD ControlId,
  565. IN HKEY RegKey,
  566. IN LPTSTR ValueName,
  567. IN BOOL Default
  568. )
  569. {
  570. BOOL Succ;
  571. DWORD Type;
  572. DWORD Data;
  573. BOOL DataSize;
  574. BOOL Value;
  575. DataSize = sizeof (Data);
  576. Succ = RegQueryValueEx (
  577. RegKey,
  578. ValueName,
  579. NULL,
  580. &Type,
  581. (LPBYTE) &Data,
  582. &DataSize
  583. );
  584. if (Succ != ERROR_SUCCESS || Type != REG_DWORD) {
  585. Value = Default;
  586. } else {
  587. Value = Data ? TRUE : FALSE;
  588. }
  589. return CheckDlgButton (hDlg, ControlId, Value);
  590. }
  591. BOOL
  592. ComboAddStringFromResource(
  593. IN HWND hDlg,
  594. IN DWORD ControlId,
  595. IN HINSTANCE ModuleHandle,
  596. IN DWORD ResourceId,
  597. IN DWORD ItemData
  598. )
  599. {
  600. DWORD Res;
  601. DWORD Item;
  602. HWND hControl;
  603. DWORD Result;
  604. WCHAR Buffer[512];
  605. Res = LoadString(ModuleHandle, ResourceId, Buffer, ARRAYSIZE(Buffer));
  606. if (Res == 0)
  607. {
  608. return FALSE;
  609. }
  610. hControl = GetDlgItem(hDlg, ControlId);
  611. Item = ComboBox_InsertString(hControl, -1, Buffer);
  612. ComboBox_SetItemData(hControl, Item, ItemData);
  613. return TRUE;
  614. }
  615. BOOL
  616. StoreCheckboxToReg(
  617. IN HWND hDlg,
  618. IN DWORD ControlId,
  619. IN HKEY hKey,
  620. IN LPCTSTR RegValueName
  621. )
  622. {
  623. DWORD Checked;
  624. Checked = IsDlgButtonChecked (hDlg, ControlId);
  625. RegSetValueEx(
  626. hKey,
  627. RegValueName,
  628. 0,
  629. REG_DWORD,
  630. (LPBYTE) &Checked,
  631. sizeof (Checked)
  632. );
  633. return TRUE;
  634. }
  635. BOOL
  636. StoreStringToReg(
  637. IN HWND hDlg,
  638. IN DWORD ControlId,
  639. IN HKEY hKey,
  640. IN LPCTSTR RegValueName
  641. )
  642. {
  643. TCHAR Buffer [ MAX_PATH ];
  644. GetDlgItemText (hDlg, ControlId, Buffer, ARRAYSIZE(Buffer));
  645. //
  646. // Check the buffer for valid file-name??
  647. //
  648. RegSetValueEx (
  649. hKey,
  650. RegValueName,
  651. 0,
  652. REG_EXPAND_SZ,
  653. (LPBYTE) Buffer,
  654. (wcslen (Buffer) + 1) * sizeof (TCHAR)
  655. );
  656. return TRUE;
  657. }
  658. static DWORD SelectionToType [] = { 0, 3, 2, 1 };
  659. DWORD
  660. GetDumpTypeFromRegistry(
  661. HKEY Key
  662. )
  663. {
  664. DWORD DataSize;
  665. DWORD Type;
  666. DWORD DumpType;
  667. DataSize = sizeof (DWORD);
  668. RegQueryValueEx (
  669. Key,
  670. REG_DUMP_TYPE_VALUE_NAME,
  671. NULL,
  672. &Type,
  673. (LPBYTE) &DumpType,
  674. &DataSize
  675. );
  676. if (DumpType > 3) {
  677. DumpType = DUMP_TYPE_MINI;
  678. } else {
  679. DumpType = SelectionToType [ DumpType ];
  680. }
  681. return DumpType;
  682. }
  683. BOOL CoreDumpInit(HWND hDlg)
  684. {
  685. BOOL Succ;
  686. NTSTATUS Status;
  687. DWORD DataSize;
  688. DWORD DumpType;
  689. DWORD Type;
  690. VCREG_RET vcVirt;
  691. VCREG_RET vcCore;
  692. SYSTEM_MEMORY_CONFIGURATION MemoryConfig;
  693. HourGlass (TRUE);
  694. // Do no put anything before the initialization of the globals, here.
  695. vcVirt = VirtualOpenKey();
  696. if( vcVirt == VCREG_ERROR )
  697. {
  698. CoreDumpInitErrorExit(hDlg, NULL);
  699. return FALSE;
  700. }
  701. vcCore = CoreDumpOpenKey();
  702. if (vcCore == VCREG_ERROR)
  703. {
  704. CoreDumpInitErrorExit(hDlg, ghkeyMemMgt);
  705. return FALSE;
  706. }
  707. else if (vcCore == VCREG_READONLY || vcVirt == VCREG_READONLY)
  708. {
  709. DisableCoreDumpControls (hDlg);
  710. }
  711. else
  712. {
  713. Status = GetMemoryConfiguration (&SystemMemoryConfiguration);
  714. if (!NT_SUCCESS (Status))
  715. {
  716. return FALSE;
  717. }
  718. }
  719. Status = GetMemoryConfiguration (&MemoryConfig);
  720. if (!NT_SUCCESS (Status))
  721. {
  722. return FALSE;
  723. }
  724. Succ = LoadString (hInstance, IDS_CRASHDUMP_DUMP_FILE, DumpFileText, ARRAYSIZE(DumpFileText));
  725. Succ = LoadString (hInstance, IDS_CRASHDUMP_MINI_DIR, MiniDumpDirText, ARRAYSIZE(MiniDumpDirText));
  726. // Special Case: Server Product does not want ability to disable logging
  727. // of crashdumps.
  728. if (IsWorkstationProduct ())
  729. {
  730. CheckInitFromRegistry(
  731. hDlg,
  732. IDC_STARTUP_CDMP_LOG,
  733. ghkeyCrashCtrl,
  734. REG_LOG_EVENT_VALUE_NAME,
  735. TRUE
  736. );
  737. }
  738. else
  739. {
  740. CheckDlgButton (hDlg, IDC_STARTUP_CDMP_LOG, TRUE);
  741. EnableWindow ( GetDlgItem (hDlg, IDC_STARTUP_CDMP_LOG), FALSE);
  742. }
  743. CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_SEND, ghkeyCrashCtrl,REG_SEND_ALERT_VALUE_NAME, TRUE);
  744. CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_OVERWRITE, ghkeyCrashCtrl, REG_OVERWRITE_VALUE_NAME, TRUE);
  745. CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_AUTOREBOOT, ghkeyCrashCtrl, REG_AUTOREBOOT_VALUE_NAME, TRUE);
  746. ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, // Global hInstance
  747. IDS_CRASHDUMP_NONE, 0);
  748. #ifdef _WIN64
  749. ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_MINI_WIN64, 0);
  750. #else
  751. ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_MINI, 0);
  752. #endif
  753. ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_SUMMARY, 0 );
  754. // Special case: Server Products do not allow full memory dumps.
  755. DumpType = GetDumpTypeFromRegistry(ghkeyCrashCtrl);
  756. if (MemoryConfig.PhysicalMemorySize < LARGE_MEMORY_THRESHOLD)
  757. {
  758. ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_FULL, 0);
  759. }
  760. else
  761. {
  762. if (DumpType == DUMP_TYPE_FULL)
  763. {
  764. DumpType = DUMP_TYPE_SUMMARY;
  765. }
  766. }
  767. ComboBox_SetCurSel(GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE), DumpType);
  768. DataSize = sizeof (CrashDumpFile);
  769. RegQueryValueEx (
  770. ghkeyCrashCtrl,
  771. REG_DUMPFILE_VALUE_NAME,
  772. NULL,
  773. &Type,
  774. (LPBYTE) CrashDumpFile,
  775. &DataSize
  776. );
  777. DataSize = sizeof (MiniDumpDirectory);
  778. RegQueryValueEx (
  779. ghkeyCrashCtrl,
  780. REG_MINIDUMP_DIR_VALUE_NAME,
  781. NULL,
  782. &Type,
  783. (LPBYTE) MiniDumpDirectory,
  784. &DataSize
  785. );
  786. // Update the selection fields of the dialog.
  787. SwapDumpSelection (hDlg);
  788. HourGlass(FALSE);
  789. return TRUE;
  790. }
  791. BOOL
  792. CoreDumpUpdateRegistry(
  793. HWND hDlg,
  794. HKEY hKey
  795. )
  796. {
  797. DWORD Selection;
  798. StoreCheckboxToReg(
  799. hDlg,
  800. IDC_STARTUP_CDMP_LOG,
  801. hKey,
  802. REG_LOG_EVENT_VALUE_NAME
  803. );
  804. StoreCheckboxToReg(
  805. hDlg,
  806. IDC_STARTUP_CDMP_SEND,
  807. hKey,
  808. REG_SEND_ALERT_VALUE_NAME
  809. );
  810. StoreCheckboxToReg(
  811. hDlg,
  812. IDC_STARTUP_CDMP_OVERWRITE,
  813. hKey,
  814. REG_OVERWRITE_VALUE_NAME
  815. );
  816. StoreCheckboxToReg(
  817. hDlg,
  818. IDC_STARTUP_CDMP_AUTOREBOOT,
  819. hKey,
  820. REG_AUTOREBOOT_VALUE_NAME
  821. );
  822. Selection = GetDumpSelection (hDlg);
  823. if (Selection == DUMP_TYPE_MINI) {
  824. StoreStringToReg (
  825. hDlg,
  826. IDC_STARTUP_CDMP_FILENAME,
  827. hKey,
  828. REG_MINIDUMP_DIR_VALUE_NAME
  829. );
  830. } else {
  831. StoreStringToReg(
  832. hDlg,
  833. IDC_STARTUP_CDMP_FILENAME,
  834. hKey,
  835. REG_DUMPFILE_VALUE_NAME
  836. );
  837. }
  838. if (Selection > 3) {
  839. Selection = 3;
  840. }
  841. Selection = SelectionToType [ Selection ];
  842. RegSetValueEx (
  843. hKey,
  844. REG_DUMP_TYPE_VALUE_NAME,
  845. 0,
  846. REG_DWORD,
  847. (LPBYTE) &Selection,
  848. sizeof (Selection)
  849. );
  850. return TRUE;
  851. }
  852. ULONG64
  853. EstimateSummaryDumpSize(
  854. ULONG64 PhysicalMemorySize
  855. )
  856. {
  857. ULONG64 Size;
  858. //
  859. // Very rough guesses at the size of the summary dump.
  860. //
  861. if (PhysicalMemorySize < 128 * MBYTE) {
  862. Size = 50 * MBYTE;
  863. } else if (PhysicalMemorySize < 4 * GBYTE) {
  864. Size = 200 * MBYTE;
  865. } else if (PhysicalMemorySize < 8 * GBYTE) {
  866. Size = 400 * MBYTE;
  867. } else {
  868. Size = 800 * MBYTE;
  869. }
  870. return Size;
  871. }
  872. ULONG64
  873. CoreDumpGetRequiredFileSize(
  874. IN HWND hDlg OPTIONAL
  875. )
  876. {
  877. ULONG64 Size;
  878. DWORD DumpType;
  879. NTSTATUS Status;
  880. SYSTEM_MEMORY_CONFIGURATION MemoryConfig;
  881. //
  882. // If we were passed a hDlg, get the selection from the dlg. Otherwise,
  883. // get the selection from the registry.
  884. //
  885. if (hDlg != NULL) {
  886. //
  887. // Get selection from dlg.
  888. //
  889. DumpType = GetDumpSelection ( hDlg );
  890. } else {
  891. HKEY hKey;
  892. DWORD Err;
  893. //
  894. // Get selection from registry.
  895. //
  896. Err = OpenRegKey (CRASH_CONTROL_KEY,
  897. &hKey
  898. );
  899. if (Err == VCREG_ERROR) {
  900. return DUMP_TYPE_MINI;
  901. }
  902. ASSERT ( hKey );
  903. DumpType = GetDumpTypeFromRegistry ( hKey );
  904. CloseRegKey ( hKey );
  905. }
  906. switch (DumpType) {
  907. case DUMP_TYPE_NONE:
  908. Size = 0;
  909. break;
  910. case DUMP_TYPE_MINI:
  911. Size = 64 * KBYTE;
  912. break;
  913. case DUMP_TYPE_SUMMARY:
  914. Status = GetMemoryConfiguration (&MemoryConfig);
  915. if (NT_SUCCESS (Status)) {
  916. Size = EstimateSummaryDumpSize (MemoryConfig.PhysicalMemorySize);
  917. } else {
  918. //
  919. // A (large) shot in the dark.
  920. //
  921. Size = 800 * MBYTE;
  922. }
  923. break;
  924. case DUMP_TYPE_FULL:
  925. Status = GetMemoryConfiguration (&MemoryConfig);
  926. if (NT_SUCCESS (Status)) {
  927. Size = MemoryConfig.PhysicalMemorySize;
  928. } else {
  929. Size = 0;
  930. }
  931. break;
  932. default:
  933. ASSERT (FALSE);
  934. }
  935. return Size;
  936. }