|
|
/*++
Microsoft Confidential Copyright (c) 1992-1997 Microsoft Corporation All rights reserved
Module Name:
crashdmp.c
Abstract:
Implements the "Recovery" group on the Startup/Recovery dialog of the System Control Panel Applet
Notes:
The virtual memory settings and the crash dump (core dump) settings are tightly-coupled. Therefore, crashdmp.c and startup.h have some heavy dependencies on virtual.c and virtual.h (and vice versa).
Author:
Byron Dazey 06-Jun-1992
Revision History:
15-Oct-1997 scotthal Complete overhaul
--*/
#include "sysdm.h"
#include <windowsx.h>
#define KBYTE (1024UI64)
#define MBYTE (1024UI64 * KBYTE)
#define GBYTE (1024UI64 * MBYTE)
//
// CrashDumpEnabled is not a boolean value anymore. It can take on one of the
// following types.
//
#define DUMP_TYPE_NONE (0)
#define DUMP_TYPE_MINI (1)
#define DUMP_TYPE_SUMMARY (2)
#define DUMP_TYPE_FULL (3)
#define DUMP_TYPE_MAX (4)
#define REG_LOG_EVENT_VALUE_NAME TEXT ("LogEvent")
#define REG_SEND_ALERT_VALUE_NAME TEXT ("SendAlert")
#define REG_OVERWRITE_VALUE_NAME TEXT ("Overwrite")
#define REG_AUTOREBOOT_VALUE_NAME TEXT ("AutoReboot")
#define REG_DUMPFILE_VALUE_NAME TEXT ("DumpFile")
#define REG_MINIDUMP_DIR_VALUE_NAME TEXT ("MinidumpDir")
#define REG_DUMP_TYPE_VALUE_NAME TEXT ("CrashDumpEnabled")
#define BIG_MEMORY_MAX_BOOT_PF_MB (2048)
#define CRASH_CONTROL_KEY TEXT("System\\CurrentControlSet\\Control\\CrashControl")
//
// The crashdump code is hard-coded to generate only summary dumps for
// machines with more than 2 GB of physical memory. Do not change this
// constant unless unless you change the same code in ntos\io\dumpctl.c
//
#define LARGE_MEMORY_THRESHOLD (2 * GBYTE)
typedef struct _SYSTEM_MEMORY_CONFIGURATION { BOOL BigMemory; ULONG PageSize; ULONG64 PhysicalMemorySize; ULONG64 BootPartitionPageFileSize; TCHAR BootDrive; } SYSTEM_MEMORY_CONFIGURATION;
VCREG_RET gvcCrashCtrl = VCREG_ERROR; HKEY ghkeyCrashCtrl = NULL; int gcrefCrashCtrl = 0; BOOL gfCoreDumpChanged = FALSE;
TCHAR CrashDumpFile [MAX_PATH] = TEXT("%SystemRoot%\\MEMORY.DMP"); TCHAR MiniDumpDirectory [MAX_PATH] = TEXT("%SystemRoot%\\Minidump"); TCHAR DumpFileText [100]; TCHAR MiniDumpDirText [100];
SYSTEM_MEMORY_CONFIGURATION SystemMemoryConfiguration;
//
// Private function prototypes
//
DWORD GetDumpSelection( HWND hDlg );
NTSTATUS GetMemoryConfiguration( OUT SYSTEM_MEMORY_CONFIGURATION * MemoryConfig );
VOID DisableCoreDumpControls( HWND hDlg );
static BOOL CoreDumpInit( IN HWND hDlg );
static BOOL CoreDumpUpdateRegistry( IN HWND hDlg, IN HKEY hKey );
int CoreDumpHandleOk( IN BOOL fInitialized, IN HWND hDlg, IN WPARAM wParam, IN LPARAM lParam );
VOID SwapDumpSelection( HWND hDlg ); //
// Implementation
//
VCREG_RET CoreDumpOpenKey( ) { if (gvcCrashCtrl == VCREG_ERROR) { gvcCrashCtrl = OpenRegKey( CRASH_CONTROL_KEY, &ghkeyCrashCtrl ); }
if (gvcCrashCtrl != VCREG_ERROR) { gcrefCrashCtrl++; }
return gvcCrashCtrl; }
void CoreDumpCloseKey( ) { if (gcrefCrashCtrl > 0) { gcrefCrashCtrl--; if (gcrefCrashCtrl == 0) { CloseRegKey( ghkeyCrashCtrl ); gvcCrashCtrl = VCREG_ERROR; } } }
BOOL StartAlerterService( IN SC_HANDLE hAlerter ) { BOOL fResult = FALSE;
fResult = ChangeServiceConfig( hAlerter, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
fResult = StartService(hAlerter, 0, NULL);
return(fResult);
}
BOOL IsAlerterSvcStarted( HWND hDlg ) { SC_HANDLE schSCManager, schService = NULL; LPQUERY_SERVICE_CONFIG lpqscBuf; DWORD dwBytesNeeded; BOOL fRunning = FALSE; SERVICE_STATUS ssSrvcStat;
/*
* Open the Service Controller */ schSCManager = OpenSCManager( NULL, /* local machine */ NULL, /* ServicesActive database */ SC_MANAGER_ALL_ACCESS); /* full access rights */
if (schSCManager == NULL) { goto iassExit; }
/*
* Try to open the Alerter Service */
/* Open a handle to the service. */
schService = OpenService( schSCManager, /* SCManager database */ TEXT("Alerter"), /* name of service */ SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START );
if (schService == NULL) { goto iassExit; }
/*
* Query the Alerter service to see if it has been started */
if (!QueryServiceStatus(schService, &ssSrvcStat )) { goto iassExit; }
if (ssSrvcStat.dwCurrentState != SERVICE_RUNNING) { fRunning = StartAlerterService(schService); } else {
fRunning = TRUE; }
iassExit: if (!fRunning) { MsgBoxParam(hDlg, IDS_SYSDM_NOALERTER, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION ); }
if (schService != NULL) { CloseServiceHandle(schService); }
if (schSCManager != NULL) { CloseServiceHandle(schSCManager); }
return fRunning; }
BOOL VerifyDumpPath( IN HWND hDlg ) { TCHAR szPath[MAX_PATH]; TCHAR szExpPath[MAX_PATH]; LPTSTR psz; TCHAR ch; UINT uType;
if( GetDlgItemText(hDlg, IDC_STARTUP_CDMP_FILENAME, szPath, ARRAYSIZE(szPath)) == 0) {
MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_FILENAME, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK); return FALSE; }
/*
* Expand any environment vars, and then check to make sure it * is a fully quallified path */ // if it has a '%' in it, then try to expand it
if (ExpandEnvironmentStrings(szPath, szExpPath, ARRAYSIZE(szExpPath)) >= ARRAYSIZE(szExpPath)) { MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_PATHLONG, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK, (DWORD)MAX_PATH); return FALSE; }
// now cannonicalize it
GetFullPathName( szExpPath, ARRAYSIZE(szPath), szPath, &psz );
// check to see that it already was cannonicalized
if (lstrcmp( szPath, szExpPath ) != 0) { MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_UNQUALIFIED, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK ); return FALSE; }
/*
* check the drive (don't allow remote) */
ch = szPath[3]; szPath[3] = TEXT('\0'); if (IsPathSep(szPath[0]) || ((uType = GetDriveType(szPath)) != DRIVE_FIXED && uType != DRIVE_REMOVABLE)) { MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_DRIVE, IDS_SYSDM_TITLE, MB_ICONSTOP | MB_OK ); return FALSE; } szPath[3] = ch;
/*
* if path is non-exstant, tell user and let him decide what to do */
if (GetFileAttributes(szPath) == 0xFFFFFFFFL && GetLastError() != ERROR_FILE_NOT_FOUND && MsgBoxParam(hDlg, IDS_SYSDM_DEBUGGING_PATH, IDS_SYSDM_TITLE, MB_ICONQUESTION | MB_YESNO ) == IDYES) { return FALSE; }
return TRUE; }
BOOL CoreDumpValidFile( HWND hDlg ) { switch (GetDumpSelection (hDlg)) {
case DUMP_TYPE_NONE: return TRUE;
case DUMP_TYPE_MINI: return VerifyDumpPath (hDlg);
case DUMP_TYPE_SUMMARY: case DUMP_TYPE_FULL: return VerifyDumpPath (hDlg); default: ASSERT (FALSE); return TRUE; }
return FALSE; }
int APIENTRY CoreDumpDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { static BOOL fInitialized = FALSE;
switch (message) { case WM_INITDIALOG: g_fStartupInitializing = TRUE; fInitialized = CoreDumpInit(hDlg); g_fStartupInitializing = FALSE; return RET_CONTINUE; break;
case WM_COMMAND:
switch (LOWORD(wParam)) { case IDOK: return(CoreDumpHandleOk(fInitialized, hDlg, wParam, lParam)); break;
case IDCANCEL: if (fInitialized) { VirtualCloseKey(); CoreDumpCloseKey(); } // Let the Startup/Recovery dlg proc also handle IDOK
return(RET_NO_CHANGE); break;
case IDC_STARTUP_CDMP_TYPE: { SwapDumpSelection (hDlg); } // Fall through
case IDC_STARTUP_CDMP_FILENAME: case IDC_STARTUP_CDMP_LOG: case IDC_STARTUP_CDMP_SEND: case IDC_STARTUP_CDMP_OVERWRITE: case IDC_STARTUP_CDMP_AUTOREBOOT: if (!g_fStartupInitializing) { gfCoreDumpChanged = TRUE; } break; default: { // indicat not handled
return RET_CONTINUE; } } break; // WM_COMMAND
case WM_DESTROY: return RET_CONTINUE; break;
default: return RET_CONTINUE; }
return RET_BREAK; }
int CoreDumpHandleOk( IN BOOL fInitialized, IN HWND hDlg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL fRegChg; NTSTATUS Status; DWORD Ret; int iRet = RET_NO_CHANGE; SYSTEM_MEMORY_CONFIGURATION MemoryConfig = {0};
if (fInitialized && gfCoreDumpChanged) { // Validate crashdump file name.
if (!CoreDumpValidFile(hDlg)) { SetFocus(GetDlgItem(hDlg, IDC_STARTUP_CDMP_FILENAME)); SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE); iRet = RET_ERROR; return iRet; }
Status = GetMemoryConfiguration(&MemoryConfig);
if (NT_SUCCESS (Status) && MemoryConfig.BootPartitionPageFileSize < CoreDumpGetRequiredFileSize (hDlg)) { // Warn that the dump file may be truncated.
Ret = MsgBoxParam (hDlg, IDS_SYSDM_DEBUGGING_MINIMUM, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION | MB_YESNO, (MemoryConfig.BootDrive ? MemoryConfig.BootDrive : TEXT('?')), (DWORD) (CoreDumpGetRequiredFileSize (hDlg) / MBYTE) );
if (Ret == IDNO) { return RET_ERROR; } }
// If the Alert button is checked, make sure the alerter service
// is started.
if (IsDlgButtonChecked(hDlg, IDC_STARTUP_CDMP_SEND)) { IsAlerterSvcStarted(hDlg); }
fRegChg = CoreDumpUpdateRegistry (hDlg, ghkeyCrashCtrl);
// Clean up registry stuff
CoreDumpCloseKey(); VirtualCloseKey();
if (fRegChg) { // Notify the kernel to reread the crashdump parameters from the registry.
Status = NtSetSystemInformation(SystemCrashDumpStateInformation, NULL, 0); if (NT_SUCCESS(Status)) { iRet = RET_CHANGE_NO_REBOOT; } else { iRet = RET_RECOVER_CHANGE; } } } else { iRet = RET_NO_CHANGE; }
return(iRet); }
void CoreDumpInitErrorExit( HWND hDlg, HKEY hk ) { MsgBoxParam(hDlg, IDS_SYSDM_NOOPEN_RECOVER_GROUP, IDS_SYSDM_TITLE, MB_ICONEXCLAMATION); if( hk == ghkeyMemMgt ) VirtualCloseKey();
DisableCoreDumpControls(hDlg);
HourGlass(FALSE); return; }
DWORD GetDumpSelection( HWND hDlg ) { HWND hControl;
hControl = GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE); return ComboBox_GetCurSel ( hControl ); }
VOID DisableCoreDumpControls( HWND hDlg ) { EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_GRP), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_TXT1), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_LOG ), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_SEND), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE); EnableWindow( GetDlgItem (hDlg, IDC_STARTUP_CDMP_AUTOREBOOT), FALSE); }
VOID SwapDumpSelection( HWND hDlg ) { //
// If there is no dump type, disable some controls. If this is a minidump
// disable overwrite and change "File Name:" to "Mini Dump Directory:"
//
switch (GetDumpSelection (hDlg)) {
case DUMP_TYPE_NONE: EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), FALSE); SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), CrashDumpFile ); Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), DumpFileText ); break;
case DUMP_TYPE_MINI: EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), TRUE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), TRUE); SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), MiniDumpDirectory ); Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), MiniDumpDirText ); break;
default: EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_OVERWRITE), TRUE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), TRUE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), TRUE); SetWindowText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILENAME), CrashDumpFile ); Static_SetText (GetDlgItem (hDlg, IDC_STARTUP_CDMP_FILE_LABEL), DumpFileText ); } }
BOOL GetSystemDrive( OUT TCHAR * Drive ) { TCHAR WindowsDir [ MAX_PATH ];
if (!GetWindowsDirectory (WindowsDir, ARRAYSIZE (WindowsDir))) { return FALSE; }
if (!isalpha (*WindowsDir)) { return FALSE; }
*Drive = *WindowsDir;
return TRUE; }
NTSTATUS GetMemoryConfiguration( OUT SYSTEM_MEMORY_CONFIGURATION * MemoryConfig ) { BOOL Succ; TCHAR SystemDrive; NTSTATUS Status; SYSTEM_BASIC_INFORMATION BasicInfo; ULONGLONG iMaxPageFileSize;
Status = NtQuerySystemInformation( SystemBasicInformation, &BasicInfo, sizeof (BasicInfo), NULL );
if (NT_SUCCESS (Status)) { Status; }
MemoryConfig->PhysicalMemorySize = (ULONG64) BasicInfo.NumberOfPhysicalPages * (ULONG64) BasicInfo.PageSize;
MemoryConfig->PageSize = BasicInfo.PageSize;
//
// Get the Boot-partition pagefile size.
//
Succ = GetSystemDrive (&SystemDrive);
if (!Succ) { return FALSE; }
MemoryConfig->BootDrive = (WCHAR) toupper (SystemDrive);
SystemDrive = tolower (SystemDrive) - 'a';
//
// A big memory machine is one that has more memory than we can write to
// at crashdump time.
//
iMaxPageFileSize = GetMaxPagefileSizeInMB(SystemDrive); iMaxPageFileSize *= (1024 * 1024); // MaxPageFileSize stored in megabytes
if ((ULONGLONG)MemoryConfig->PhysicalMemorySize >= iMaxPageFileSize) { MemoryConfig->BigMemory = TRUE; } else { MemoryConfig->BigMemory = FALSE; }
//
// NOTE: apf is a global exposed by virtual.c
//
Succ = VirtualGetPageFiles ( apf );
if (!Succ) { return FALSE; }
//
// This is the file size in terms of megabytes.
//
MemoryConfig->BootPartitionPageFileSize = apf [ SystemDrive ].nMinFileSize;
//
// Convert to bytes.
//
MemoryConfig->BootPartitionPageFileSize *= MBYTE;
VirtualFreePageFiles ( apf );
return STATUS_SUCCESS;
}
BOOL CheckInitFromRegistry( IN HWND hDlg, IN DWORD ControlId, IN HKEY RegKey, IN LPTSTR ValueName, IN BOOL Default ) { BOOL Succ; DWORD Type; DWORD Data; BOOL DataSize; BOOL Value;
DataSize = sizeof (Data);
Succ = RegQueryValueEx ( RegKey, ValueName, NULL, &Type, (LPBYTE) &Data, &DataSize );
if (Succ != ERROR_SUCCESS || Type != REG_DWORD) { Value = Default; } else { Value = Data ? TRUE : FALSE; }
return CheckDlgButton (hDlg, ControlId, Value); }
BOOL ComboAddStringFromResource( IN HWND hDlg, IN DWORD ControlId, IN HINSTANCE ModuleHandle, IN DWORD ResourceId, IN DWORD ItemData ) { DWORD Res; DWORD Item; HWND hControl; DWORD Result; WCHAR Buffer[512];
Res = LoadString(ModuleHandle, ResourceId, Buffer, ARRAYSIZE(Buffer)); if (Res == 0) { return FALSE; }
hControl = GetDlgItem(hDlg, ControlId); Item = ComboBox_InsertString(hControl, -1, Buffer); ComboBox_SetItemData(hControl, Item, ItemData);
return TRUE; }
BOOL StoreCheckboxToReg( IN HWND hDlg, IN DWORD ControlId, IN HKEY hKey, IN LPCTSTR RegValueName ) { DWORD Checked;
Checked = IsDlgButtonChecked (hDlg, ControlId);
RegSetValueEx( hKey, RegValueName, 0, REG_DWORD, (LPBYTE) &Checked, sizeof (Checked) );
return TRUE; }
BOOL StoreStringToReg( IN HWND hDlg, IN DWORD ControlId, IN HKEY hKey, IN LPCTSTR RegValueName ) { TCHAR Buffer [ MAX_PATH ];
GetDlgItemText (hDlg, ControlId, Buffer, ARRAYSIZE(Buffer));
//
// Check the buffer for valid file-name??
//
RegSetValueEx ( hKey, RegValueName, 0, REG_EXPAND_SZ, (LPBYTE) Buffer, (wcslen (Buffer) + 1) * sizeof (TCHAR) );
return TRUE; }
static DWORD SelectionToType [] = { 0, 3, 2, 1 };
DWORD GetDumpTypeFromRegistry( HKEY Key ) { DWORD DataSize; DWORD Type; DWORD DumpType;
DataSize = sizeof (DWORD); RegQueryValueEx ( Key, REG_DUMP_TYPE_VALUE_NAME, NULL, &Type, (LPBYTE) &DumpType, &DataSize );
if (DumpType > 3) { DumpType = DUMP_TYPE_MINI; } else { DumpType = SelectionToType [ DumpType ]; }
return DumpType; }
BOOL CoreDumpInit(HWND hDlg) { BOOL Succ; NTSTATUS Status; DWORD DataSize; DWORD DumpType; DWORD Type; VCREG_RET vcVirt; VCREG_RET vcCore; SYSTEM_MEMORY_CONFIGURATION MemoryConfig;
HourGlass (TRUE);
// Do no put anything before the initialization of the globals, here.
vcVirt = VirtualOpenKey();
if( vcVirt == VCREG_ERROR ) { CoreDumpInitErrorExit(hDlg, NULL); return FALSE; }
vcCore = CoreDumpOpenKey(); if (vcCore == VCREG_ERROR) { CoreDumpInitErrorExit(hDlg, ghkeyMemMgt); return FALSE; } else if (vcCore == VCREG_READONLY || vcVirt == VCREG_READONLY) { DisableCoreDumpControls (hDlg); } else { Status = GetMemoryConfiguration (&SystemMemoryConfiguration); if (!NT_SUCCESS (Status)) { return FALSE; } }
Status = GetMemoryConfiguration (&MemoryConfig); if (!NT_SUCCESS (Status)) { return FALSE; }
Succ = LoadString (hInstance, IDS_CRASHDUMP_DUMP_FILE, DumpFileText, ARRAYSIZE(DumpFileText)); Succ = LoadString (hInstance, IDS_CRASHDUMP_MINI_DIR, MiniDumpDirText, ARRAYSIZE(MiniDumpDirText));
// Special Case: Server Product does not want ability to disable logging
// of crashdumps.
if (IsWorkstationProduct ()) { CheckInitFromRegistry( hDlg, IDC_STARTUP_CDMP_LOG, ghkeyCrashCtrl, REG_LOG_EVENT_VALUE_NAME, TRUE ); } else { CheckDlgButton (hDlg, IDC_STARTUP_CDMP_LOG, TRUE); EnableWindow ( GetDlgItem (hDlg, IDC_STARTUP_CDMP_LOG), FALSE); }
CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_SEND, ghkeyCrashCtrl,REG_SEND_ALERT_VALUE_NAME, TRUE); CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_OVERWRITE, ghkeyCrashCtrl, REG_OVERWRITE_VALUE_NAME, TRUE); CheckInitFromRegistry(hDlg, IDC_STARTUP_CDMP_AUTOREBOOT, ghkeyCrashCtrl, REG_AUTOREBOOT_VALUE_NAME, TRUE); ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, // Global hInstance
IDS_CRASHDUMP_NONE, 0);
#ifdef _WIN64
ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_MINI_WIN64, 0); #else
ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_MINI, 0); #endif
ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_SUMMARY, 0 );
// Special case: Server Products do not allow full memory dumps.
DumpType = GetDumpTypeFromRegistry(ghkeyCrashCtrl); if (MemoryConfig.PhysicalMemorySize < LARGE_MEMORY_THRESHOLD) { ComboAddStringFromResource(hDlg, IDC_STARTUP_CDMP_TYPE, hInstance, IDS_CRASHDUMP_FULL, 0); } else { if (DumpType == DUMP_TYPE_FULL) { DumpType = DUMP_TYPE_SUMMARY; } }
ComboBox_SetCurSel(GetDlgItem (hDlg, IDC_STARTUP_CDMP_TYPE), DumpType);
DataSize = sizeof (CrashDumpFile); RegQueryValueEx ( ghkeyCrashCtrl, REG_DUMPFILE_VALUE_NAME, NULL, &Type, (LPBYTE) CrashDumpFile, &DataSize );
DataSize = sizeof (MiniDumpDirectory); RegQueryValueEx ( ghkeyCrashCtrl, REG_MINIDUMP_DIR_VALUE_NAME, NULL, &Type, (LPBYTE) MiniDumpDirectory, &DataSize );
// Update the selection fields of the dialog.
SwapDumpSelection (hDlg); HourGlass(FALSE);
return TRUE; }
BOOL CoreDumpUpdateRegistry( HWND hDlg, HKEY hKey ) { DWORD Selection;
StoreCheckboxToReg( hDlg, IDC_STARTUP_CDMP_LOG, hKey, REG_LOG_EVENT_VALUE_NAME );
StoreCheckboxToReg( hDlg, IDC_STARTUP_CDMP_SEND, hKey, REG_SEND_ALERT_VALUE_NAME );
StoreCheckboxToReg( hDlg, IDC_STARTUP_CDMP_OVERWRITE, hKey, REG_OVERWRITE_VALUE_NAME );
StoreCheckboxToReg( hDlg, IDC_STARTUP_CDMP_AUTOREBOOT, hKey, REG_AUTOREBOOT_VALUE_NAME );
Selection = GetDumpSelection (hDlg);
if (Selection == DUMP_TYPE_MINI) {
StoreStringToReg ( hDlg, IDC_STARTUP_CDMP_FILENAME, hKey, REG_MINIDUMP_DIR_VALUE_NAME );
} else {
StoreStringToReg( hDlg, IDC_STARTUP_CDMP_FILENAME, hKey, REG_DUMPFILE_VALUE_NAME ); }
if (Selection > 3) { Selection = 3; }
Selection = SelectionToType [ Selection ]; RegSetValueEx ( hKey, REG_DUMP_TYPE_VALUE_NAME, 0, REG_DWORD, (LPBYTE) &Selection, sizeof (Selection) );
return TRUE; }
ULONG64 EstimateSummaryDumpSize( ULONG64 PhysicalMemorySize ) { ULONG64 Size;
//
// Very rough guesses at the size of the summary dump.
//
if (PhysicalMemorySize < 128 * MBYTE) {
Size = 50 * MBYTE;
} else if (PhysicalMemorySize < 4 * GBYTE) {
Size = 200 * MBYTE;
} else if (PhysicalMemorySize < 8 * GBYTE) {
Size = 400 * MBYTE;
} else {
Size = 800 * MBYTE; }
return Size; }
ULONG64 CoreDumpGetRequiredFileSize( IN HWND hDlg OPTIONAL ) { ULONG64 Size; DWORD DumpType; NTSTATUS Status; SYSTEM_MEMORY_CONFIGURATION MemoryConfig;
//
// If we were passed a hDlg, get the selection from the dlg. Otherwise,
// get the selection from the registry.
//
if (hDlg != NULL) {
//
// Get selection from dlg.
//
DumpType = GetDumpSelection ( hDlg );
} else {
HKEY hKey; DWORD Err;
//
// Get selection from registry.
//
Err = OpenRegKey (CRASH_CONTROL_KEY, &hKey );
if (Err == VCREG_ERROR) { return DUMP_TYPE_MINI; }
ASSERT ( hKey ); DumpType = GetDumpTypeFromRegistry ( hKey ); CloseRegKey ( hKey ); }
switch (DumpType) {
case DUMP_TYPE_NONE: Size = 0; break;
case DUMP_TYPE_MINI: Size = 64 * KBYTE; break;
case DUMP_TYPE_SUMMARY:
Status = GetMemoryConfiguration (&MemoryConfig);
if (NT_SUCCESS (Status)) { Size = EstimateSummaryDumpSize (MemoryConfig.PhysicalMemorySize); } else { //
// A (large) shot in the dark.
//
Size = 800 * MBYTE; } break;
case DUMP_TYPE_FULL:
Status = GetMemoryConfiguration (&MemoryConfig);
if (NT_SUCCESS (Status)) { Size = MemoryConfig.PhysicalMemorySize; } else { Size = 0; }
break;
default: ASSERT (FALSE); }
return Size; }
|