windows-nt/Source/XPSP1/NT/shell/cpls/system/crashdmp.c
2020-09-26 16:20:57 +08:00

1188 lines
26 KiB
C

/*++
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;
}