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

2333 lines
69 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
gflags.cxx
Abstract:
This module contains the routines to make global flags
settings (i.e. the FLG_XXX constants from ntexapi.h).
Author:
- others -
Silviu Calinoiu (silviuc) 09-Nov-2001
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntexapi.dbg>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "gflags.h"
//
// Valid global flag bits for the three scenarios: per image flags,
// system wide flags (require a reboot or will affect future processes
// in user mode) and kernel mode flags on the fly.
//
#define GFLGS_VALID_KERNEL_MODE_FLAGS ((VALID_KERNEL_MODE_FLAGS) \
& ~FLG_KERNEL_STACK_TRACE_DB \
& ~FLG_POOL_ENABLE_TAGGING)
#define GFLGS_VALID_SYSTEM_REGISTRY_FLAGS ((VALID_SYSTEM_REGISTRY_FLAGS))
#define GFLGS_VALID_IMAGE_FILE_NAME_FLAGS ((VALID_IMAGE_FILE_NAME_FLAGS))
CHAR GflagsHelpText[] =
" \n"
"usage: GFLAGS [-r [<Flags>]] | \n"
" [-k [<Flags>]] | \n"
" [-i <ImageFileName> [<Flags>]] | \n"
" [-i <ImageFileName> -tracedb <SizeInMb>] | \n"
" [-p <PageHeapOptions>] (use `-p ?' for help) \n"
" \n"
"where: <Flags> is a 32 bit hex number (0x12345678) that specifies \n"
" one or more global flags to set. \n"
" -r operates on system registry settings. \n"
" -k operates on kernel settings of the running system. \n"
" -i operates on settings for a specific image file. \n"
" \n"
" If only the switch is specified, then current settings \n"
" are displayed, not modified. If flags specified for -i \n"
" option are FFFFFFFF, then registry entry for that image \n"
" is deleted \n"
" \n"
"The `-tracedb' option is used to set the size of the stack trace \n"
"database used to store runtime stack traces. The actual database \n"
"will be created if the `+ust' flag is set in a previous command. \n"
"`-tracedb 0' will revert to the default size for the database. \n"
" \n"
"If no arguments are specified to GFLAGS then it displays \n"
"a dialog box that allows the user to modify the global \n"
"flag settings. \n"
" \n"
"Flags may either be a single hex number that specifies all \n"
"32-bits of the GlobalFlags value, or it can be one or more \n"
"arguments, each beginning with a + or -, where the + means \n"
"to set the corresponding bit(s) in the GlobalFlags and a - \n"
"means to clear the corresponding bit(s). After the + or - \n"
"may be either a hex number or a three letter abbreviation \n"
"for a GlobalFlag. Valid abbreviations are: \n"
" \n";
#define _PART_OF_GFLAGS_ 1
#include "..\pageheap\pageheap.cxx"
#if defined(_X86_)
//
// Use function pointers for ntdll import functions so gflags
// can fail with a user friendly message on win9x.
//
#define RtlIntegerToChar pRtlIntegerToChar
#define NtQueryInformationProcess pNtQueryInformationProcess
#define RtlCharToInteger pRtlCharToInteger
#define NtSetSystemInformation pNtSetSystemInformation
#define NtQuerySystemInformation pNtQuerySystemInformation
typedef NTSTATUS (NTAPI *PRTLINTEGERTOCHAR)(
ULONG,
ULONG,
LONG,
PSZ
);
typedef NTSTATUS (NTAPI *PNTQUERYINFORMATIONPROCESS) (
IN HANDLE,
IN PROCESSINFOCLASS,
OUT PVOID,
IN ULONG,
OUT PULONG
);
typedef NTSTATUS (NTAPI * PRTLCHARTOINTEGER) (
PCSZ,
ULONG,
PULONG
);
typedef NTSTATUS (NTAPI * PNTSETSYSTEMINFORMATION) (
IN SYSTEM_INFORMATION_CLASS,
IN PVOID,
IN ULONG
);
typedef NTSTATUS (NTAPI * PNTQUERYSYSTEMINFORMATION) (
IN SYSTEM_INFORMATION_CLASS,
OUT PVOID,
IN ULONG,
OUT PULONG
);
PRTLINTEGERTOCHAR pRtlIntegerToChar;
PNTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
PRTLCHARTOINTEGER pRtlCharToInteger;
PNTSETSYSTEMINFORMATION pNtSetSystemInformation;
PNTQUERYSYSTEMINFORMATION pNtQuerySystemInformation;
#endif
BOOL
GflagsSetTraceDatabaseSize (
PCHAR ApplicationName,
ULONG SizeInMb,
PULONG RealSize
);
INT_PTR APIENTRY MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL
EnableDebugPrivilege( VOID );
BOOL
OkToEnablePagedHeap( VOID );
HWND hwndMain;
HWND hwndPagedHeapDlg;
HKEY hSmKey, hMmKey;
DWORD InitialSetFlags;
DWORD LastSetFlags;
//
// Special pool management
//
#define SPECIAL_POOL_OVERRUNS_CHECK_FORWARD 1
#define SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD 0
DWORD LastSetSpecialPoolTag;
DWORD LastSetSpecialPoolOverruns = SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
TCHAR SpecialPoolRenderBuffer[8 + 1];
CHAR LastDebuggerValue[ MAX_PATH ];
UINT SpecialPool[] = {
ID_SPECIAL_POOL_GROUP,
ID_SPECIAL_POOL_IS_TEXT,
ID_SPECIAL_POOL_IS_NUMBER,
ID_SPECIAL_POOL_TAG,
ID_SPECIAL_POOL_VERIFY_START,
ID_SPECIAL_POOL_VERIFY_END,
0
};
UINT Debugger[] = {
ID_IMAGE_DEBUGGER_GROUP,
ID_IMAGE_DEBUGGER_VALUE,
ID_IMAGE_DEBUGGER_BUTTON,
0
};
PCHAR SystemProcesses[] = {
"csrss.exe",
"winlogon.exe",
"services.exe",
"lsass.exe",
"svchost.exe",
"ntmssvc.exe",
"rpcss.exe",
"spoolsv.exe"
};
//
// POOL Tagging is always on for .NET server, the "Enable pool tagging" option
// will be greyed out if it is on a .NET server.
// Pool Tagging on XP will still be controlled by GFlags same as w2k.
//
BOOL PoolTaggingAlwaysOn = FALSE;
ULONG PoolTagEnabledFlag = 0;
EnableSetOfControls(
HWND hDlg,
UINT * Controls,
BOOL Enable
)
{
UINT Control ;
HWND hWnd ;
Control = *Controls++ ;
while ( Control )
{
hWnd = GetDlgItem( hDlg, Control );
EnableWindow( hWnd, Enable );
ShowWindow( hWnd, Enable ? SW_NORMAL : SW_HIDE );
Control = *Controls++ ;
}
return 0;
}
DWORD
GetSystemRegistryFlags( VOID )
{
DWORD cbKey;
DWORD GFlags;
DWORD type;
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\Session Manager",
0,
KEY_READ | KEY_WRITE,
&hSmKey
) != ERROR_SUCCESS
) {
MessageBox( hwndMain, "Open Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager", MB_OK );
ExitProcess( 0 );
}
cbKey = sizeof( GFlags );
if (RegQueryValueEx( hSmKey,
"GlobalFlag",
0,
&type,
(LPBYTE)&GFlags,
&cbKey
) != ERROR_SUCCESS ||
type != REG_DWORD
) {
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
RegCloseKey( hSmKey );
ExitProcess( 0 );
}
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
0,
KEY_READ | KEY_WRITE,
&hMmKey
) != ERROR_SUCCESS
) {
MessageBox( hwndMain, "Open Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management", MB_OK );
RegCloseKey( hSmKey );
ExitProcess( 0 );
}
cbKey = sizeof( LastSetSpecialPoolTag );
if (RegQueryValueEx( hMmKey,
"PoolTag",
0,
&type,
(LPBYTE)&LastSetSpecialPoolTag,
&cbKey
) == ERROR_SUCCESS
) {
if (type != REG_DWORD) {
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PoolTag", MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
} else {
LastSetSpecialPoolTag = 0;
}
cbKey = sizeof( LastSetSpecialPoolOverruns );
if (RegQueryValueEx( hMmKey,
"PoolTagOverruns",
0,
&type,
(LPBYTE)&LastSetSpecialPoolOverruns,
&cbKey
) == ERROR_SUCCESS
) {
if (type != REG_DWORD) {
MessageBox( hwndMain,
"Value Type Error",
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
"\\PoolTagOverruns",
MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
//
// The only legal values are 0, 1.
//
if (LastSetSpecialPoolOverruns != SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD &&
LastSetSpecialPoolOverruns != SPECIAL_POOL_OVERRUNS_CHECK_FORWARD) {
MessageBox( hwndMain,
"Value Data Error",
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
"\\PoolTagOverruns",
MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
} else {
LastSetSpecialPoolOverruns = SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
}
return GFlags;
}
BOOLEAN
SetSystemRegistryFlags(
DWORD GFlags,
DWORD SpecialPoolTag,
DWORD SpecialPoolOverruns
)
{
if (RegSetValueEx( hSmKey,
"GlobalFlag",
0,
REG_DWORD,
(LPBYTE)&GFlags,
sizeof( GFlags )
) != ERROR_SUCCESS
) {
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\GlobalFlag", MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
//
// Only modify special pool if we went to GUI mode
//
if (hwndMain) {
if (SpecialPoolTag) {
if (RegSetValueEx( hMmKey,
"PoolTag",
0,
REG_DWORD,
(LPBYTE)&SpecialPoolTag,
sizeof( SpecialPoolTag )
) != ERROR_SUCCESS
) {
MessageBox( hwndMain,
"Value Error",
"SYSTEM\\CurrentControlSet\\Control\\Session Manager"
"\\Memory Management\\PoolTag",
MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
if (RegSetValueEx( hMmKey,
"PoolTagOverruns",
0,
REG_DWORD,
(LPBYTE)&SpecialPoolOverruns,
sizeof( SpecialPoolOverruns )
) != ERROR_SUCCESS
) {
MessageBox( hwndMain,
"Value Error",
"SYSTEM\\CurrentControlSet\\Control\\Session Manager"
"\\Memory Management\\PoolTag",
MB_OK );
RegCloseKey( hSmKey );
RegCloseKey( hMmKey );
ExitProcess( 0 );
}
} else {
RegDeleteValue( hMmKey,
"PoolTag"
);
RegDeleteValue( hMmKey,
"PoolTagOverruns"
);
}
}
LastSetFlags = GFlags;
LastSetSpecialPoolTag = SpecialPoolTag;
LastSetSpecialPoolOverruns = SpecialPoolOverruns;
return TRUE;
}
DWORD
GetKernelModeFlags( VOID )
{
NTSTATUS Status;
SYSTEM_FLAGS_INFORMATION SystemInformation;
Status = NtQuerySystemInformation( SystemFlagsInformation,
&SystemInformation,
sizeof( SystemInformation ),
NULL
);
if (!NT_SUCCESS( Status )) {
MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
ExitProcess( 0 );
}
return SystemInformation.Flags;
}
BOOLEAN
AddImageNameToUSTString(
PCHAR ImageFileName
)
{
CHAR *Enabled = NULL;
HKEY hKey;
DWORD Result;
DWORD Length;
if (strlen( ImageFileName ) == 0)
return FALSE;
// Open the Key
Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if (Result == ERROR_SUCCESS) {
// Get the current length of the registry key
Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, NULL, &Length );
if (Result == ERROR_SUCCESS){
// Get a buffer big enough for current key, a ';', and our new name.
Enabled = (PCHAR)malloc(Length + strlen(ImageFileName)+ 1);
if (Enabled) {
// Get the current key value
Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, (PBYTE)Enabled, &Length );
if (Result == ERROR_SUCCESS) {
// If we are not currently in there, let add ourselves
if (!strstr(Enabled, ImageFileName)) {
//Watch for a trailing ';'
if (Enabled[strlen(Enabled) - 1] != ';')
strcat(Enabled, ";");
strcat(Enabled, ImageFileName);
Result = RegSetValueEx( hKey,
"USTEnabled",
0,
REG_SZ,
(PBYTE)Enabled,
(ULONG)(strlen(Enabled) + 1));
}
}
free(Enabled);
} // if enabled
} // Result == ERROR_SUCCESS on RegQueryValue
else if (Result == ERROR_FILE_NOT_FOUND) {
// Key doesnt currently exist so lets just set it.
Result = RegSetValueEx( hKey,
"USTEnabled",
0,
REG_SZ,
(PBYTE)ImageFileName,
(ULONG)(strlen(ImageFileName) + 1));
} // Result == ERROR_FILE_NOT_FOUND on RegQueryValue
RegCloseKey( hKey );
} // Result == ERROR_SUCCESS on RegCreateKeyEx
// Did we succeed or not
if (Result != ERROR_SUCCESS) {
MessageBox( hwndMain,
"Failure adding or accessing User Stack Trace Registry Key",
ImageFileName,
MB_OK
);
return FALSE;
}
return TRUE;
}
BOOLEAN
DelImageNameFromUSTString(
PCHAR ImageFileName
)
{
CHAR *Enabled = NULL;
CHAR *NameStart = NULL, *NameEnd = NULL;
HKEY hKey;
DWORD Result;
DWORD Length;
if (strlen( ImageFileName ) == 0)
return FALSE;
// Open the Key
Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
if (Result == ERROR_SUCCESS) {
// Get the current length of the registry key
Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, NULL, &Length );
if (Result == ERROR_SUCCESS) {
if (Length != 0) {
// Get a buffer big enough for current key
Enabled = (PCHAR)malloc(Length);
if (Enabled) {
// Get the current key value
Result = RegQueryValueEx( hKey, "USTEnabled", NULL, NULL, (PBYTE)Enabled, &Length );
if (Result == ERROR_SUCCESS) {
// If we are currently in there, delete ourselves
NameStart = strstr(Enabled, ImageFileName);
if (NameStart) {
NameEnd = NameStart + strlen(ImageFileName);
if (*NameEnd == ';'){
NameEnd++;
strcpy(NameStart, NameEnd);
}
else
*NameStart = '\0';
//Knock off any trailing ';'
if (Enabled[strlen(Enabled) - 1] == ';')
Enabled[strlen(Enabled) - 1] = '\0';
if (strlen(Enabled)) {
Result = RegSetValueEx( hKey,
"USTEnabled",
0,
REG_SZ,
(PBYTE)Enabled,
(ULONG)(strlen(Enabled) + 1));
}
else{
Result = RegDeleteValue( hKey, "USTEnabled");
}
}
}
free(Enabled);
}
}
}
else if (Result == ERROR_FILE_NOT_FOUND) {
// This is a case where the registry key does not already exist
Result = ERROR_SUCCESS;
}
RegCloseKey( hKey );
}
// Did we succeed or not
if (Result != ERROR_SUCCESS) {
MessageBox( hwndMain,
"Failure accessing or deleting User Stack Trace Registry Key",
ImageFileName,
MB_OK
);
return FALSE;
}
return TRUE;
}
BOOLEAN
SetKernelModeFlags(
DWORD GFlags
)
{
NTSTATUS Status;
SYSTEM_FLAGS_INFORMATION SystemInformation;
if (!EnableDebugPrivilege()) {
MessageBox( hwndMain, "Access Denied", "Unable to enable debug privilege", MB_OK );
ExitProcess( 0 );
}
SystemInformation.Flags = GFlags;
Status = NtSetSystemInformation( SystemFlagsInformation,
&SystemInformation,
sizeof( SystemInformation )
);
if (!NT_SUCCESS( Status )) {
MessageBox( hwndMain, "Value Error", "Kernel Mode Flags", MB_OK );
ExitProcess( 0 );
}
LastSetFlags = GFlags;
return TRUE;
}
DWORD
GetImageFileNameFlags(
PCHAR ImageFileName
)
{
CHAR Buffer[ MAX_PATH ];
CHAR RegKey[ MAX_PATH ];
DWORD Length = MAX_PATH;
DWORD GFlags;
HKEY hKey;
GFlags = 0;
if (strlen( ImageFileName ) != 0) {
sprintf( RegKey,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
ImageFileName
);
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS ) {
if (RegQueryValueEx( hKey, "GlobalFlag", NULL, NULL, (PBYTE)Buffer, &Length ) == ERROR_SUCCESS ) {
RtlCharToInteger( Buffer, 0, &GFlags );
}
RegCloseKey( hKey );
}
}
return GFlags;
}
BOOL
GetImageFileNameDebugger(
PCHAR ImageFileName,
PCHAR Debugger
)
{
CHAR RegKey[ MAX_PATH ];
DWORD Length = MAX_PATH;
DWORD GFlags;
HKEY hKey;
BOOL Success = FALSE;
GFlags = 0;
if (strlen( ImageFileName ) != 0) {
sprintf( RegKey,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
ImageFileName
);
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, RegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS ) {
if (RegQueryValueEx( hKey, "Debugger", NULL, NULL, (PBYTE)Debugger, &Length ) == ERROR_SUCCESS ) {
Success = TRUE ;
}
RegCloseKey( hKey );
}
}
return Success ;
}
BOOLEAN
SetImageFileNameFlags(
PCHAR ImageFileName,
DWORD GFlags
)
{
CHAR Buffer[ MAX_PATH ];
CHAR RegKey[ MAX_PATH ];
HKEY hKey;
DWORD Result;
DWORD Length;
DWORD Disposition;
if (strlen( ImageFileName ) != 0) {
sprintf( RegKey,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
ImageFileName
);
Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
RegKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&Disposition
);
if (Result == ERROR_SUCCESS) {
if (GFlags == (DWORD)-1) {
Result = RegDeleteValue( hKey,
"GlobalFlag"
);
DelImageNameFromUSTString(ImageFileName);
}
else {
Length = sprintf( Buffer, "0x%08x", GFlags ) + 1;
Result = RegSetValueEx( hKey,
"GlobalFlag",
0,
REG_SZ,
(PBYTE)Buffer,
Length
);
if (GFlags&FLG_USER_STACK_TRACE_DB)
AddImageNameToUSTString(ImageFileName);
else
DelImageNameFromUSTString(ImageFileName);
//
// If we enable page heap for a single application
// then we will avoid default behavior which is
// page heap light (only normal allocations) and
// we will enable the page heap full power.
// Note that we do not do this for system wide
// settings because this will make the machine
// unbootable.
//
if ((GFlags & FLG_HEAP_PAGE_ALLOCS)) {
Length = sprintf( Buffer, "0x%08x", 0x03 ) + 1;
Result = RegSetValueEx(
hKey,
"PageHeapFlags",
0,
REG_SZ,
(PBYTE)Buffer,
Length
);
}
}
RegCloseKey( hKey );
}
if (Result != ERROR_SUCCESS) {
MessageBox( hwndMain,
(GFlags == (DWORD)-1) ?
"Failed to delete registry value" :
"Failed to set registry value",
ImageFileName,
MB_OK
);
return FALSE;
}
LastSetFlags = GFlags;
return TRUE;
}
return FALSE;
}
BOOLEAN
SetImageFileNameDebugger(
PCHAR ImageFileName,
PCHAR Debugger
)
{
CHAR RegKey[ MAX_PATH ];
HKEY hKey;
DWORD Result;
DWORD Disposition;
if (strlen( ImageFileName ) != 0) {
sprintf( RegKey,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
ImageFileName
);
Result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
RegKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&Disposition
);
if (Result == ERROR_SUCCESS) {
if ( *Debugger )
{
Result = RegSetValueEx( hKey,
"Debugger",
0,
REG_SZ,
(PBYTE)Debugger,
(ULONG)(strlen( Debugger ) + 1));
}
else
{
Result = RegDeleteValue( hKey, "Debugger" );
}
RegCloseKey( hKey );
}
if (Result != ERROR_SUCCESS) {
MessageBox( hwndMain,
( *Debugger ) ?
"Failed to delete registry value" :
"Failed to set registry value",
ImageFileName,
MB_OK
);
return FALSE;
}
return TRUE;
}
return FALSE;
}
BOOLEAN fRegistrySettings;
BOOLEAN fKernelSettings;
BOOLEAN fImageFileSettings;
BOOLEAN fDisplaySettings;
BOOLEAN fLaunchCommand;
BOOLEAN fFlushImageSettings;
PUCHAR TargetImageFileName;
DWORD GlobalFlagMask;
DWORD GlobalFlagSetting;
DWORD OldGlobalFlags;
DWORD NewGlobalFlags;
DWORD NewGlobalFlagsValidMask;
DWORD NewGlobalFlagsIgnored;
void
DisplayFlags(
PCHAR Msg,
DWORD Flags,
DWORD FlagsIgnored
)
{
int i;
if (Flags == 0xFFFFFFFF) {
printf( "No %s\n", Msg );
return;
}
printf( "Current %s are: %08x\n", Msg, Flags );
for (i=0; i<32; i++) {
if (GlobalFlagInfo[i].Abbreviation != NULL &&
(Flags & GlobalFlagInfo[i].Flag)
) {
if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, "Enable page heap");
}
else {
printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, GlobalFlagInfo[i].Description );
}
}
}
if (FlagsIgnored) {
printf( "Following settings were ignored: %08x\n", FlagsIgnored );
for (i=0; i<32; i++) {
if (GlobalFlagInfo[i].Abbreviation != NULL &&
(FlagsIgnored & GlobalFlagInfo[i].Flag)
) {
if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, "Enable page heap");
}
else {
printf( " %s - %s\n", GlobalFlagInfo[i].Abbreviation, GlobalFlagInfo[i].Description );
}
}
}
}
}
BOOL
IsCmdlineOption (
PCHAR Option,
PCHAR Name,
PCHAR NameEx
)
{
if (_stricmp (Option, Name) == 0 || _stricmp (Option, NameEx) == 0) {
return TRUE;
}
else {
return FALSE;
}
}
int
__cdecl
main(
int argc,
char **argv
)
{
MSG msg;
CHAR c;
PCHAR s;
BOOLEAN fUsage, fExpectingFlags;
ULONG i;
CHAR Settings[ 2*MAX_PATH ];
OSVERSIONINFO VersionInfo;
VersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &VersionInfo );
//
// if the machine is running XP SP1+ or .NET server, the
// pool tagging will always be on.
//
if ( VersionInfo.dwMajorVersion >= 5 &&
VersionInfo.dwMinorVersion >= 1 ){
OSVERSIONINFOEX VersionInfoEx;
VersionInfoEx.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
GetVersionEx( (LPOSVERSIONINFO) &VersionInfoEx );
if ( VersionInfoEx.wProductType != VER_NT_WORKSTATION ){
PoolTaggingAlwaysOn = TRUE;
}
}
#if defined(_X86_)
if ( VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ) {
MessageBox( NULL,
"Global flags only runs on Windows NT and Windows 2000. The glfags command was ignored.",
"Global Flags Error",
0 );
exit(0);
}
else {
HMODULE hDll;
hDll = GetModuleHandle("ntdll");
if (hDll != NULL) {
pRtlIntegerToChar = ( PRTLINTEGERTOCHAR )
GetProcAddress(
hDll,
"RtlIntegerToChar"
);
pNtQueryInformationProcess = ( PNTQUERYINFORMATIONPROCESS )
GetProcAddress(
hDll,
"NtQueryInformationProcess"
);
pRtlCharToInteger = ( PRTLCHARTOINTEGER )
GetProcAddress(
hDll,
"RtlCharToInteger"
);
pNtSetSystemInformation = ( PNTSETSYSTEMINFORMATION )
GetProcAddress(
hDll,
"NtSetSystemInformation"
);
pNtQuerySystemInformation = ( PNTQUERYSYSTEMINFORMATION )
GetProcAddress(
hDll,
"NtQuerySystemInformation"
);
}
}
#endif
//
// Check if we need to redirect the whole command line to the page heap
// command line parser.
//
if (argc >= 2 && IsCmdlineOption (argv[1], "/p", "-p")) {
PageHeapMain (argc - 1, argv + 1);
exit(0);
}
//
// Check forst for `-i APP -tracedb SIZE' option
//
if (argc == 5 &&
IsCmdlineOption (argv[3], "/tracedb", "-tracedb") &&
IsCmdlineOption (argv[1], "/i", "-i")) {
ULONG RealSize;
if (GflagsSetTraceDatabaseSize (argv[2], atoi (argv[4]), &RealSize) == FALSE) {
printf("Failed to set the trace database size for `%s' \n", argv[2]);
printf("The user mode stack trace database flag (+ust) "
"must be enabled before setting /tracedb .\n");
exit(5);
}
else {
if (RealSize > 0) {
printf("Trace database size for `%s' set to %u Mb.\n", argv[2], RealSize);
}
else {
printf("Will use default size for the trace database. \n");
}
exit(0);
}
}
//
// Continue ...
//
hwndMain = NULL;
fUsage = FALSE;
fExpectingFlags = FALSE;
GlobalFlagMask = 0xFFFFFFFF;
GlobalFlagSetting = 0;
while (--argc) {
s = *++argv;
if (!fExpectingFlags && (*s == '-' || *s == '/')) {
while (*++s) {
c = (char)tolower(*s);
switch (c) {
case 'r':
case 'k':
case 'i':
if (fRegistrySettings || fKernelSettings || fImageFileSettings) {
fprintf( stderr, "GFLAG: may only specify one of -r, -k or -i\n" );
fUsage = TRUE;
}
else {
fExpectingFlags = TRUE;
fDisplaySettings = TRUE;
if (c == 'r') {
fRegistrySettings = TRUE;
OldGlobalFlags = GetSystemRegistryFlags();
NewGlobalFlagsValidMask = GFLGS_VALID_SYSTEM_REGISTRY_FLAGS;
strcpy( Settings, "Boot Registry Settings" );
}
else
if (c == 'k') {
fKernelSettings = TRUE;
NewGlobalFlagsValidMask = GFLGS_VALID_KERNEL_MODE_FLAGS;
OldGlobalFlags = GetKernelModeFlags();
strcpy( Settings, "Running Kernel Settings" );
}
else {
fImageFileSettings = TRUE;
NewGlobalFlagsValidMask = GFLGS_VALID_IMAGE_FILE_NAME_FLAGS;
if (!--argc) {
fprintf( stderr, "GFLAGS: ImageFileName missing after -i switch\n" );
fUsage = TRUE;
exit( 0 ); // 179741 - JHH
}
else {
TargetImageFileName = (PUCHAR)(*++argv);
OldGlobalFlags = GetImageFileNameFlags( (PCHAR)TargetImageFileName );
sprintf( Settings, "Registry Settings for %s executable", TargetImageFileName );
}
}
}
break;
case 'l':
fLaunchCommand = TRUE;
fExpectingFlags = TRUE;
break;
default:
fUsage = TRUE;
break;
}
}
}
else {
if (fExpectingFlags) {
fDisplaySettings = FALSE;
if (*s == '+' || *s == '-') {
if (strlen(s+1) == 3) {
for (i = 0; i < 32; i += 1) {
if ((NewGlobalFlagsValidMask & GlobalFlagInfo[i].Flag) &&
(GlobalFlagInfo[i].Abbreviation != NULL) &&
_stricmp( GlobalFlagInfo[i].Abbreviation, s+1 ) == NULL) {
if (fKernelSettings) {
if (_stricmp(GlobalFlagInfo[i].Abbreviation, "ptg") == NULL) {
fprintf (stderr,
"Ignoring `ptg' flag. It can be used only with registry "
"settings (`-r') because it requires a reboot.\n");
continue;
}
if (_stricmp(GlobalFlagInfo[i].Abbreviation, "kst") == NULL) {
fprintf (stderr,
"Ignoring `kst' flag. It can be used only with registry "
"settings (`-r') because it requires a reboot.\n");
continue;
}
}
if (*s == '-') {
GlobalFlagMask &= ~GlobalFlagInfo[i].Flag;
}
else {
GlobalFlagSetting |= GlobalFlagInfo[i].Flag;
}
s += 4;
break;
}
}
}
if (*s != '\0') {
if (*s++ == '-') {
GlobalFlagMask &= ~strtoul( s, &s, 16 );
}
else {
GlobalFlagSetting |= strtoul( s, &s, 16 );
}
}
}
else {
fExpectingFlags = FALSE;
GlobalFlagSetting = strtoul( s, &s, 16 );
}
if (fLaunchCommand) {
exit( 0 );
}
if (fImageFileSettings && OldGlobalFlags == 0xFFFFFFFF) {
OldGlobalFlags = 0;
}
}
else {
fprintf( stderr, "GFLAGS: Unexpected argument - '%s'\n", s );
fUsage = TRUE;
}
}
}
if (fUsage) {
fputs(GflagsHelpText,
stderr);
for (i=0; i<32; i++) {
if (GlobalFlagInfo[i].Abbreviation != NULL) {
if (_stricmp(GlobalFlagInfo[i].Abbreviation, "hpa") == 0) {
fprintf( stderr, " %s - %s\n",
GlobalFlagInfo[i].Abbreviation,
"Enable page heap");
}
else {
fprintf( stderr, " %s - %s\n",
GlobalFlagInfo[i].Abbreviation,
GlobalFlagInfo[i].Description);
}
}
}
fprintf( stderr, "\nAll images with ust enabled can be accessed in the\n" );
fprintf( stderr, "USTEnabled key under 'Image File Options'.\n" );
exit( 1 );
}
if ( PoolTaggingAlwaysOn && !fImageFileSettings ){
for (i = 0; i < 32; i += 1) {
if ( (GlobalFlagInfo[i].Abbreviation != NULL ) &&
(_stricmp(GlobalFlagInfo[i].Abbreviation, "ptg" ) == NULL ) ){
PoolTagEnabledFlag = GlobalFlagInfo[i].Flag;
break;
}
}
if ( (~GlobalFlagMask & PoolTagEnabledFlag) ||
(GlobalFlagSetting & PoolTagEnabledFlag ) ) {
fprintf( stderr,
"\nIgnoring `ptg' flag. Pool Tagging is always enabled on this operating system.\n");
exit(1);
}
}
NewGlobalFlags = (OldGlobalFlags & GlobalFlagMask) | GlobalFlagSetting;
if (!fImageFileSettings || NewGlobalFlags != 0xFFFFFFFF) {
NewGlobalFlagsIgnored = ~NewGlobalFlagsValidMask & NewGlobalFlags;
NewGlobalFlags &= NewGlobalFlagsValidMask;
}
if (fDisplaySettings) {
DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
exit( 0 );
}
if (fRegistrySettings) {
SetSystemRegistryFlags( NewGlobalFlags,
0,
SPECIAL_POOL_OVERRUNS_CHECK_FORWARD
);
DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
exit( 0 );
}
else
if (fKernelSettings) {
SetKernelModeFlags( NewGlobalFlags );
DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
exit( 0 );
}
else
if (fImageFileSettings) {
SetImageFileNameFlags( (PCHAR)TargetImageFileName, NewGlobalFlags );
DisplayFlags( Settings, NewGlobalFlags, NewGlobalFlagsIgnored );
exit( 0 );
}
CreateDialog( NULL,
(LPSTR)DID_GFLAGS,
NULL,
MainWndProc
);
if (!hwndMain) {
MessageBox( hwndMain, "Main Error", "Cant create dialog", MB_OK );
ExitProcess( 0 );
}
while (GetMessage( &msg, 0, 0, 0 )) {
if (!IsDialogMessage( hwndMain, &msg )) {
DispatchMessage( &msg );
}
}
return 0;
}
VOID
SetCheckBoxesFromFlags(
DWORD GFlags,
DWORD ValidFlags
)
{
int iBit;
GFlags &= ValidFlags;
LastSetFlags = GFlags;
for (iBit=0; iBit < 32; iBit++) {
CheckDlgButton( hwndMain,
ID_FLAG_1 + iBit,
(GFlags & (1 << iBit)) ? 1 : 0
);
ShowWindow( GetDlgItem( hwndMain, ID_FLAG_1 + iBit ),
(ValidFlags & (1 << iBit)) ? SW_SHOWNORMAL : SW_HIDE
);
}
}
DWORD
GetFlagsFromCheckBoxes( VOID )
{
DWORD GFlags;
int iBit;
GFlags = 0;
for (iBit=0; iBit < 32; iBit++) {
if (IsDlgButtonChecked( hwndMain, ID_FLAG_1 + iBit )) {
GFlags |= (1 << iBit);
}
}
return GFlags;
}
VOID
DoLaunch(
PCHAR CommandLine,
DWORD GFlags
)
{
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
NTSTATUS Status;
PROCESS_BASIC_INFORMATION BasicInformation;
BOOLEAN ReadImageFileExecOptions;
memset( &StartupInfo, 0, sizeof( StartupInfo ) );
StartupInfo.cb = sizeof( StartupInfo );
if (CreateProcess( NULL,
CommandLine,
NULL,
NULL,
FALSE,
CREATE_SUSPENDED,
NULL,
NULL,
&StartupInfo,
&ProcessInformation
)
) {
Status = NtQueryInformationProcess( ProcessInformation.hProcess,
ProcessBasicInformation,
&BasicInformation,
sizeof( BasicInformation ),
NULL
);
if (NT_SUCCESS( Status )) {
ReadImageFileExecOptions = TRUE;
if (!WriteProcessMemory( ProcessInformation.hProcess,
&BasicInformation.PebBaseAddress->ReadImageFileExecOptions,
&ReadImageFileExecOptions,
sizeof( ReadImageFileExecOptions ),
NULL
) ||
!WriteProcessMemory( ProcessInformation.hProcess,
&BasicInformation.PebBaseAddress->NtGlobalFlag,
&GFlags,
sizeof( GFlags ),
NULL
)
) {
Status = STATUS_UNSUCCESSFUL;
}
}
if (!NT_SUCCESS( Status )) {
MessageBox( hwndMain,
"Launch Command Line",
"Unable to pass flags to process - terminating",
MB_OK
);
TerminateProcess( ProcessInformation.hProcess, 1 );
}
ResumeThread( ProcessInformation.hThread );
CloseHandle( ProcessInformation.hThread );
MsgWaitForMultipleObjects( 1,
&ProcessInformation.hProcess,
FALSE,
NMPWAIT_WAIT_FOREVER,
QS_ALLINPUT
);
CloseHandle( ProcessInformation.hProcess );
}
else {
MessageBox( hwndMain, "Launch Command Line", "Unable to create process", MB_OK );
}
return;
}
DWORD LastRadioButtonId;
DWORD SpecialPoolModeId;
DWORD SpecialPoolOverrunsId;
BOOLEAN
CheckSpecialPoolTagItem(
HWND hwnd,
BOOLEAN ForApply
)
{
DWORD NumChars;
DWORD i;
BOOLEAN IsIllegal = FALSE;
NumChars = GetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer, sizeof( SpecialPoolRenderBuffer ));
if (NumChars != 0) {
if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
//
// Check for illegal characters.
//
if (NumChars > 8) {
IsIllegal = TRUE;
} else {
for (i = 0; i < NumChars; i++) {
if (!((SpecialPoolRenderBuffer[i] >= '0' &&
SpecialPoolRenderBuffer[i] <= '9') ||
(SpecialPoolRenderBuffer[i] >= 'a' &&
SpecialPoolRenderBuffer[i] <= 'f') ||
(SpecialPoolRenderBuffer[i] >= 'A' &&
SpecialPoolRenderBuffer[i] <= 'F'))) {
IsIllegal = TRUE;
break;
}
}
}
} else {
//
// Check for too many characters.
//
if (NumChars > sizeof(DWORD)) {
IsIllegal = TRUE;
}
//
// We check a few more things when the user is really writing back.
//
if (!IsIllegal && ForApply) {
//
// If this is not four characters and does not end in a '*',
// it is usually the case that the user really wanted a space
// at the end of the tag 'Gh1 ', not 'Gh1'. Make sure they
// get a little feedback.
//
if (NumChars != sizeof(DWORD) && SpecialPoolRenderBuffer[NumChars - 1] != '*') {
MessageBox( hwnd,
"The specified tag is less than 4 characters, but most\n"
"are really padded out with spaces. Please check and\n"
"add spaces if neccesary.",
"Possibly ambiguous special pool tag",
MB_OK );
}
}
}
}
if (IsIllegal) {
MessageBox( hwnd, (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER ? "Must be a hexadecimal DWORD" :
"Must be at most 4 characters"),
"Illegal characters in special pool tag",
MB_OK );
}
return !IsIllegal;
}
DWORD
GetSpecialPoolTagItem(
HWND hwnd
)
{
DWORD NumChars;
DWORD Tag = 0;
UNREFERENCED_PARAMETER(hwnd);
//
// We assume that the field is has been retrieved and checked.
//
NumChars = (ULONG)strlen( SpecialPoolRenderBuffer );
if (NumChars != 0) {
if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
RtlCharToInteger( SpecialPoolRenderBuffer, 16, &Tag );
} else {
//
// Just drop the bytes into the DWORD - endianess is correct as is.
//
RtlCopyMemory( &Tag,
SpecialPoolRenderBuffer,
NumChars );
}
}
return Tag;
}
DWORD
GetSpecialPoolOverrunsItem(
HWND hwnd
)
{
UNREFERENCED_PARAMETER(hwnd);
switch (SpecialPoolOverrunsId) {
case ID_SPECIAL_POOL_VERIFY_END: return SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
case ID_SPECIAL_POOL_VERIFY_START: return SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD;
default: return SPECIAL_POOL_OVERRUNS_CHECK_FORWARD;
}
}
VOID
ReRenderSpecialPoolTagItem(
HWND hwnd
)
{
DWORD NumChars;
DWORD Tag = 0;
//
// We assume that the field is has been retrieved and checked.
//
NumChars = (ULONG)strlen( SpecialPoolRenderBuffer );
//
// Assume that the dialog contents are of the previous mode. Switch it.
//
if (NumChars != 0) {
if (SpecialPoolModeId == ID_SPECIAL_POOL_IS_NUMBER) {
RtlCopyMemory( &Tag,
SpecialPoolRenderBuffer,
NumChars );
RtlIntegerToChar( Tag, 16, sizeof( SpecialPoolRenderBuffer ), SpecialPoolRenderBuffer);
} else {
RtlCharToInteger( SpecialPoolRenderBuffer, 16, &Tag );
RtlCopyMemory( SpecialPoolRenderBuffer,
&Tag,
sizeof( Tag ));
SpecialPoolRenderBuffer[sizeof( Tag )] = '\0';
}
}
SetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer );
}
BOOLEAN
CheckForUnsaved(
HWND hwnd
)
{
//
// Appropriate to the mode we are leaving, see if there were unsaved changes.
// Return TRUE if there are unsaved changes.
//
if (GetFlagsFromCheckBoxes() != LastSetFlags ||
(fFlushImageSettings && (LastRadioButtonId == ID_IMAGE_FILE_OPTIONS)) ||
(LastRadioButtonId == ID_SYSTEM_REGISTRY &&
(!CheckSpecialPoolTagItem( hwnd, FALSE ) ||
(GetSpecialPoolTagItem( hwnd ) != LastSetSpecialPoolTag) ||
(GetSpecialPoolOverrunsItem( hwnd ) != LastSetSpecialPoolOverruns)))) {
if (MessageBox( hwndMain,
"You didn't click 'apply' - did you want to discard current changes??",
"Warning",
MB_YESNO
) == IDNO
) {
return TRUE;
}
}
return FALSE;
}
INT_PTR
APIENTRY
MainWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
DWORD NewFlags;
CHAR ImageFileName[ MAX_PATH ];
CHAR CommandLine[ MAX_PATH ];
BOOL bCancelDiscard;
int i;
UNREFERENCED_PARAMETER(lParam);
bCancelDiscard = FALSE;
switch (message) {
case WM_INITDIALOG:
hwndMain = hwnd;
LastRadioButtonId = ID_SYSTEM_REGISTRY;
CheckRadioButton( hwnd,
ID_SYSTEM_REGISTRY,
ID_IMAGE_FILE_OPTIONS,
LastRadioButtonId
);
EnableSetOfControls( hwnd, SpecialPool, TRUE );
EnableSetOfControls( hwnd, Debugger, FALSE );
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), GFLGS_VALID_SYSTEM_REGISTRY_FLAGS );
//
// Make a not so wild guess about what kind of tag it is.
//
if (LastSetSpecialPoolTag && LastSetSpecialPoolTag < 0x2000) {
SpecialPoolModeId = ID_SPECIAL_POOL_IS_NUMBER;
RtlIntegerToChar( LastSetSpecialPoolTag,
16,
sizeof( SpecialPoolRenderBuffer ),
SpecialPoolRenderBuffer );
}
else {
SpecialPoolModeId = ID_SPECIAL_POOL_IS_TEXT;
RtlCopyMemory( SpecialPoolRenderBuffer,
&LastSetSpecialPoolTag,
sizeof( LastSetSpecialPoolTag ));
SpecialPoolRenderBuffer[sizeof(LastSetSpecialPoolTag)] = '\0';
}
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_IS_TEXT,
ID_SPECIAL_POOL_IS_NUMBER,
SpecialPoolModeId
);
SetDlgItemText( hwnd, ID_SPECIAL_POOL_TAG, SpecialPoolRenderBuffer );
//
// Initial state for the special pool overrun radio buttons.
//
switch (LastSetSpecialPoolOverruns) {
case SPECIAL_POOL_OVERRUNS_CHECK_FORWARD:
SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_END;
break;
case SPECIAL_POOL_OVERRUNS_CHECK_BACKWARD:
SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_START;
break;
default:
SpecialPoolOverrunsId = ID_SPECIAL_POOL_VERIFY_END;
break;
}
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_VERIFY_START,
ID_SPECIAL_POOL_VERIFY_END,
SpecialPoolOverrunsId
);
if ( PoolTaggingAlwaysOn )
{
//
// on windows XP and above, POOL tagging will always be on.
//
CheckDlgButton(hwnd, ID_FLAG_11, BST_CHECKED);
EnableWindow(GetDlgItem(hwnd, ID_FLAG_11), FALSE);
}
return(TRUE);
case WM_COMMAND:
switch ( LOWORD(wParam) ) {
case ID_LAUNCH:
GetDlgItemText( hwnd, ID_COMMAND_LINE, CommandLine, sizeof( CommandLine ) );
if (strlen( ImageFileName ) == 0) {
MessageBox( hwndMain, "Launch Command Line", "Must fill in command line first", MB_OK );
SetFocus( GetDlgItem( hwnd, ID_COMMAND_LINE ) );
break;
}
// fall through
case ID_APPLY:
if (IsDlgButtonChecked( hwnd, ID_SYSTEM_REGISTRY )) {
//
// System wide settings
//
if (CheckSpecialPoolTagItem( hwnd, TRUE )) {
NewFlags = GetFlagsFromCheckBoxes();
SetSystemRegistryFlags(
NewFlags,
GetSpecialPoolTagItem( hwnd ),
GetSpecialPoolOverrunsItem (hwnd));
}
}
else if (IsDlgButtonChecked( hwnd, ID_KERNEL_MODE )) {
//
// Kernel mode settings
//
// N.B. This will set flags on the fly. It does not touch
// the registry and does not require a reboot.
//
NewFlags = GetFlagsFromCheckBoxes();
SetKernelModeFlags( NewFlags );
}
else if (IsDlgButtonChecked( hwnd, ID_IMAGE_FILE_OPTIONS )) {
//
// Application specific settings
//
GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
if (strlen( ImageFileName ) == 0) {
MessageBox( hwnd, "Missing Image File Name", "Must set image file name", MB_OK );
SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
break;
}
SetImageFileNameFlags( ImageFileName, GetFlagsFromCheckBoxes() );
if ( fFlushImageSettings ) {
GetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, LastDebuggerValue, MAX_PATH );
SetImageFileNameDebugger( ImageFileName, LastDebuggerValue );
fFlushImageSettings = FALSE ;
}
}
if (LOWORD(wParam) == ID_LAUNCH) {
DoLaunch( CommandLine,
GetFlagsFromCheckBoxes()
);
}
break;
case IDOK:
if (CheckForUnsaved( hwnd )) {
break;
}
// fall through
case IDCANCEL:
PostQuitMessage(0);
DestroyWindow( hwnd );
break;
case ID_SPECIAL_POOL_IS_TEXT:
case ID_SPECIAL_POOL_IS_NUMBER:
if (CheckSpecialPoolTagItem( hwnd, FALSE )) {
if (LOWORD(wParam) != SpecialPoolModeId) {
SpecialPoolModeId = LOWORD(wParam);
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_IS_TEXT,
ID_SPECIAL_POOL_IS_NUMBER,
SpecialPoolModeId
);
ReRenderSpecialPoolTagItem( hwnd );
}
}
else {
//
// Always treat this as a cancel.
//
bCancelDiscard = TRUE;
}
break;
case ID_SPECIAL_POOL_VERIFY_START:
case ID_SPECIAL_POOL_VERIFY_END:
if (LOWORD(wParam) != SpecialPoolOverrunsId) {
SpecialPoolOverrunsId = LOWORD(wParam);
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_VERIFY_START,
ID_SPECIAL_POOL_VERIFY_END,
SpecialPoolOverrunsId
);
}
break;
case ID_IMAGE_DEBUGGER_BUTTON:
if (IsDlgButtonChecked( hwnd, ID_IMAGE_DEBUGGER_BUTTON ) == BST_CHECKED ) {
EnableWindow( GetDlgItem( hwnd, ID_IMAGE_DEBUGGER_VALUE ), TRUE );
GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, MAX_PATH );
for ( i = 0 ; i < sizeof( SystemProcesses ) / sizeof( PCHAR ) ; i++ ) {
if (_stricmp( ImageFileName, SystemProcesses[i] ) == 0 ) {
SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, "ntsd -d -g -G" );
break;
}
}
}
else {
SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, "" );
EnableWindow( GetDlgItem( hwnd, ID_IMAGE_DEBUGGER_VALUE ), FALSE );
}
fFlushImageSettings = TRUE ;
break;
case ID_SYSTEM_REGISTRY:
if (CheckForUnsaved( hwnd )) {
bCancelDiscard = TRUE;
break;
}
LastRadioButtonId = ID_SYSTEM_REGISTRY;
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), GFLGS_VALID_SYSTEM_REGISTRY_FLAGS );
EnableSetOfControls( hwnd, SpecialPool, TRUE );
EnableSetOfControls( hwnd, Debugger, FALSE );
break;
case ID_KERNEL_MODE:
if (CheckForUnsaved( hwnd )) {
bCancelDiscard = TRUE;
break;
}
LastRadioButtonId = ID_KERNEL_MODE;
SetCheckBoxesFromFlags( GetKernelModeFlags(), GFLGS_VALID_KERNEL_MODE_FLAGS );
EnableSetOfControls( hwnd, SpecialPool, FALSE );
EnableSetOfControls( hwnd, Debugger, FALSE );
break;
case ID_IMAGE_FILE_OPTIONS:
if (CheckForUnsaved( hwnd )) {
bCancelDiscard = TRUE;
break;
}
GetDlgItemText( hwnd, ID_IMAGE_FILE_NAME, ImageFileName, sizeof( ImageFileName ) );
if (strlen( ImageFileName ) == 0) {
MessageBox( hwndMain, "Image File Name Missing", "Must fill in image file name first", MB_OK );
CheckRadioButton( hwnd,
ID_SYSTEM_REGISTRY,
ID_IMAGE_FILE_OPTIONS,
LastRadioButtonId
);
SetCheckBoxesFromFlags( GetSystemRegistryFlags(), GFLGS_VALID_SYSTEM_REGISTRY_FLAGS );
SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
break;
}
else {
LastRadioButtonId = ID_IMAGE_FILE_OPTIONS;
SetCheckBoxesFromFlags( GetImageFileNameFlags( ImageFileName ),
GFLGS_VALID_IMAGE_FILE_NAME_FLAGS
);
if ( GetImageFileNameDebugger( ImageFileName, LastDebuggerValue ) ) {
SetDlgItemText( hwnd, ID_IMAGE_DEBUGGER_VALUE, LastDebuggerValue );
CheckDlgButton( hwnd, ID_IMAGE_DEBUGGER_BUTTON, 1 );
}
EnableSetOfControls( hwnd, SpecialPool, FALSE );
EnableSetOfControls( hwnd, Debugger, TRUE );
}
break;
default:
break;
}
break;
case WM_CLOSE:
PostQuitMessage(0);
DestroyWindow( hwnd );
break;
}
if (bCancelDiscard) {
//
// Recheck the right radio buttons 'cause the user didn't
// *really* mean it.
//
CheckRadioButton( hwnd,
ID_SYSTEM_REGISTRY,
ID_IMAGE_FILE_OPTIONS,
LastRadioButtonId
);
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_IS_TEXT,
ID_SPECIAL_POOL_IS_NUMBER,
SpecialPoolModeId
);
CheckRadioButton( hwnd,
ID_SPECIAL_POOL_VERIFY_START,
ID_SPECIAL_POOL_VERIFY_END,
SpecialPoolOverrunsId
);
}
return 0;
}
BOOL
EnableDebugPrivilege( VOID )
{
HANDLE Token = NULL;
PTOKEN_PRIVILEGES NewPrivileges = NULL;
ULONG cbNeeded = 0;
BOOL fRc = FALSE;
LUID LuidPrivilege = {0};
DWORD dwError = ERROR_SUCCESS;
//
// Make sure we have access to adjust and to get the old token privileges
//
fRc = OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&Token);
if (!fRc) {
dwError = GetLastError();
goto Exit;
}
//
// Initialize the privilege adjustment structure
//
fRc = LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege );
if (!fRc) {
dwError = GetLastError();
goto Exit;
}
//
// Allocate memory for NewPrivileges
//
cbNeeded = sizeof(TOKEN_PRIVILEGES) +
(1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
NewPrivileges = (PTOKEN_PRIVILEGES)HeapAlloc(GetProcessHeap(), 0, cbNeeded);
if (NewPrivileges == NULL) {
dwError = ERROR_OUTOFMEMORY;
fRc = FALSE;
goto Exit;
}
NewPrivileges->PrivilegeCount = 1;
NewPrivileges->Privileges[0].Luid = LuidPrivilege;
NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
//
// Enable the privilege
//
fRc = AdjustTokenPrivileges(Token,
FALSE,
NewPrivileges,
0,
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL);
if (!fRc) {
dwError = GetLastError();
goto Exit;
}
Exit:
//
// Cleanup handles, memory, etc. before exiting the function
//
if (NULL != Token) {
CloseHandle(Token);
Token = NULL;
}
if (NULL != NewPrivileges) {
HeapFree(GetProcessHeap(), 0, NewPrivileges);
NewPrivileges = NULL;
}
SetLastError(dwError);
return fRc;
}
VOID
CenterDialog( HWND hWndDialog )
{
RECT rectWindow;
POINT pointCenter;
POINT pointNewCornerChild;
INT nChildWidth;
INT nChildHeight;
HWND hWndParent;
hWndParent = GetParent( hWndDialog );
//
// parent window's rectangle
//
GetWindowRect( hWndParent, &rectWindow );
//
// the center, in screen coordinates
//
pointCenter.x = rectWindow.left + ( rectWindow.right - rectWindow.left ) / 2;
pointCenter.y = rectWindow.top + ( rectWindow.bottom - rectWindow.top ) / 2;
//
// chils window's rectangle, in screen coordinates
//
GetWindowRect( hWndDialog, &rectWindow );
nChildWidth = rectWindow.right - rectWindow.left ;
nChildHeight = rectWindow.bottom - rectWindow.top;
//
// the new top-left corner of the child
//
pointNewCornerChild.x = pointCenter.x - nChildWidth / 2;
pointNewCornerChild.y = pointCenter.y - nChildHeight / 2;
//
// move the child window
//
MoveWindow(
hWndDialog,
pointNewCornerChild.x,
pointNewCornerChild.y,
nChildWidth,
nChildHeight,
TRUE );
}
INT_PTR
APIENTRY
PagedHeapDlgProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
INT_PTR nResult;
UNREFERENCED_PARAMETER(lParam);
nResult = FALSE;
switch ( message ) {
case WM_INITDIALOG:
hwndPagedHeapDlg = hwnd;
//
// center this dialog
//
CenterDialog( hwndPagedHeapDlg );
break;
case WM_COMMAND:
switch( LOWORD(wParam) ) {
case IDYES:
EndDialog( hwndPagedHeapDlg, IDYES );
break;
case IDNO:
EndDialog( hwndPagedHeapDlg, IDNO );
break;
}
break;
case WM_CLOSE:
case WM_DESTROY:
case WM_ENDSESSION:
case WM_QUIT:
EndDialog(hwndPagedHeapDlg,IDNO);
nResult = TRUE;
break;
default:
break;
}
return nResult;
}
BOOL
OkToEnablePagedHeap( VOID )
{
MEMORYSTATUS MemoryStatus;
GlobalMemoryStatus( &MemoryStatus );
if( MemoryStatus.dwTotalPhys < 512 * 1024 * 1024 ) {
//
// less than 512 Mb of RAM
//
return ( DialogBoxParam(
NULL,
(LPCTSTR)( MAKEINTRESOURCE(DID_PAGED_HEAP_WARNING) ),
hwndMain,
PagedHeapDlgProc,
0 ) == IDYES );
}
return TRUE;
}
BOOL
GflagsSetTraceDatabaseSize (
PCHAR ApplicationName,
ULONG SizeInMb,
PULONG RealSize
)
{
HKEY ImageKey;
CHAR ImageKeyName[ MAX_PATH ];
LONG Result;
DWORD TraceDatabaseSize;
*RealSize = 0;
if (ApplicationName == NULL) {
return FALSE;
}
sprintf (ImageKeyName,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
ApplicationName);
Result = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
ImageKeyName,
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&ImageKey);
if (Result != ERROR_SUCCESS) {
return FALSE;
}
if (SizeInMb == 0) {
Result = RegDeleteValue (ImageKey,
"StackTraceDatabaseSizeInMb");
if (Result != ERROR_SUCCESS) {
RegCloseKey (ImageKey);
return FALSE;
}
}
else {
if (SizeInMb < 8) {
TraceDatabaseSize = 8;
}
else {
TraceDatabaseSize = SizeInMb;
}
Result = RegSetValueEx (ImageKey,
"StackTraceDatabaseSizeInMb",
0,
REG_DWORD,
(PBYTE)(&TraceDatabaseSize),
sizeof TraceDatabaseSize);
if (Result != ERROR_SUCCESS) {
RegCloseKey (ImageKey);
return FALSE;
}
*RealSize = TraceDatabaseSize;
}
RegCloseKey (ImageKey);
return TRUE;
}