crashdmp.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 28k
Category:

Windows Kernel

Development Platform:

Visual C++

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