2282 lines
66 KiB
C++
2282 lines
66 KiB
C++
|
/*++
|
||
|
|
||
|
|
||
|
Copyright (c) 1994-1999 Microsoft Corporation
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <ntexapi.dbg>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "gflags.h"
|
||
|
|
||
|
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];
|
||
|
|
||
|
|
||
|
|
||
|
DWORD InitialMaxStackTraceDepth;
|
||
|
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,
|
||
|
ID_MAX_STACK_DEPTH,
|
||
|
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"
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
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 );
|
||
|
}
|
||
|
|
||
|
cbKey = sizeof( InitialMaxStackTraceDepth );
|
||
|
if (RegQueryValueEx( hSmKey,
|
||
|
"MaxStackTraceDepth",
|
||
|
0,
|
||
|
&type,
|
||
|
(LPBYTE)&InitialMaxStackTraceDepth,
|
||
|
&cbKey
|
||
|
) != ERROR_SUCCESS ||
|
||
|
type != REG_DWORD
|
||
|
) {
|
||
|
InitialMaxStackTraceDepth = 16;
|
||
|
}
|
||
|
|
||
|
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 MaxStackTraceDepth,
|
||
|
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 );
|
||
|
}
|
||
|
|
||
|
if (RegSetValueEx( hSmKey,
|
||
|
"MaxStackTraceDepth",
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(LPBYTE)&MaxStackTraceDepth,
|
||
|
sizeof( MaxStackTraceDepth )
|
||
|
) != ERROR_SUCCESS
|
||
|
) {
|
||
|
MessageBox( hwndMain, "Value Error", "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\MaxStackTraceDepth", 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"
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
InitialMaxStackTraceDepth = MaxStackTraceDepth;
|
||
|
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 RegKey[ MAX_PATH ];
|
||
|
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,
|
||
|
(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,
|
||
|
(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 RegKey[ MAX_PATH ];
|
||
|
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
|
||
|
if (NameStart = strstr(Enabled, ImageFileName)) {
|
||
|
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,
|
||
|
(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 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 ( *Debugger )
|
||
|
{
|
||
|
Result = RegSetValueEx( hKey,
|
||
|
"Debugger",
|
||
|
0,
|
||
|
REG_SZ,
|
||
|
(PBYTE)Debugger,
|
||
|
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 ImageFileName;
|
||
|
DWORD GlobalFlagMask;
|
||
|
DWORD GlobalFlagSetting;
|
||
|
DWORD MaxDepthSetting;
|
||
|
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, fExpectingDepth;
|
||
|
ULONG i;
|
||
|
CHAR Settings[ 2*MAX_PATH ];
|
||
|
|
||
|
#if defined(_X86_)
|
||
|
|
||
|
OSVERSIONINFO VersionInfo;
|
||
|
VersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
|
||
|
GetVersionEx( &VersionInfo );
|
||
|
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]);
|
||
|
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;
|
||
|
fExpectingDepth = 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;
|
||
|
fExpectingDepth = TRUE;
|
||
|
OldGlobalFlags = GetSystemRegistryFlags();
|
||
|
NewGlobalFlagsValidMask = VALID_SYSTEM_REGISTRY_FLAGS;
|
||
|
strcpy( Settings, "Boot Registry Settings" );
|
||
|
}
|
||
|
else
|
||
|
if (c == 'k') {
|
||
|
fKernelSettings = TRUE;
|
||
|
NewGlobalFlagsValidMask = VALID_KERNEL_MODE_FLAGS;
|
||
|
OldGlobalFlags = GetKernelModeFlags();
|
||
|
strcpy( Settings, "Running Kernel Settings" );
|
||
|
}
|
||
|
else {
|
||
|
fImageFileSettings = TRUE;
|
||
|
NewGlobalFlagsValidMask = VALID_IMAGE_FILE_NAME_FLAGS;
|
||
|
if (!--argc) {
|
||
|
fprintf( stderr, "GFLAGS: ImageFileName missing after -i switch\n" );
|
||
|
fUsage = TRUE;
|
||
|
exit( 0 ); // 179741 - JHH
|
||
|
}
|
||
|
else {
|
||
|
ImageFileName = (PUCHAR)(*++argv);
|
||
|
OldGlobalFlags = GetImageFileNameFlags( (PCHAR)ImageFileName );
|
||
|
sprintf( Settings, "Registry Settings for %s executable", ImageFileName );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
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
|
||
|
if (fExpectingDepth) {
|
||
|
MaxDepthSetting = strtoul( s, &s, 10 );
|
||
|
fExpectingDepth = FALSE;
|
||
|
}
|
||
|
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 );
|
||
|
}
|
||
|
|
||
|
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,
|
||
|
fExpectingDepth ? InitialMaxStackTraceDepth : MaxDepthSetting,
|
||
|
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)ImageFileName, 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 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit( 0 );
|
||
|
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;
|
||
|
BOOLEAN IsAmbiguous = 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;
|
||
|
|
||
|
//
|
||
|
// We assume that the field is has been retrieved and checked.
|
||
|
//
|
||
|
|
||
|
NumChars = 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
|
||
|
)
|
||
|
{
|
||
|
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 = 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
|
||
|
)
|
||
|
{
|
||
|
BOOL b;
|
||
|
|
||
|
//
|
||
|
// 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)) ||
|
||
|
GetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, &b, FALSE ) != InitialMaxStackTraceDepth)) {
|
||
|
|
||
|
|
||
|
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 b, bCancelDiscard;
|
||
|
int i;
|
||
|
|
||
|
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(), VALID_SYSTEM_REGISTRY_FLAGS );
|
||
|
SetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, InitialMaxStackTraceDepth, FALSE );
|
||
|
|
||
|
//
|
||
|
// 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
|
||
|
);
|
||
|
|
||
|
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,
|
||
|
GetDlgItemInt( hwnd, ID_MAX_STACK_DEPTH, &b, FALSE ),
|
||
|
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(), 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(), 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(), VALID_SYSTEM_REGISTRY_FLAGS );
|
||
|
SetFocus( GetDlgItem( hwnd, ID_IMAGE_FILE_NAME ) );
|
||
|
break;
|
||
|
}
|
||
|
else {
|
||
|
LastRadioButtonId = ID_IMAGE_FILE_OPTIONS;
|
||
|
SetCheckBoxesFromFlags( GetImageFileNameFlags( ImageFileName ),
|
||
|
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;
|
||
|
PTOKEN_PRIVILEGES NewPrivileges;
|
||
|
BYTE OldPriv[ 1024 ];
|
||
|
PBYTE pbOldPriv;
|
||
|
ULONG cbNeeded;
|
||
|
BOOL fRc;
|
||
|
LUID LuidPrivilege;
|
||
|
|
||
|
//
|
||
|
// Make sure we have access to adjust and to get the old token privileges
|
||
|
//
|
||
|
if (!OpenProcessToken( GetCurrentProcess(),
|
||
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||
|
&Token
|
||
|
)
|
||
|
) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
cbNeeded = 0;
|
||
|
|
||
|
//
|
||
|
// Initialize the privilege adjustment structure
|
||
|
//
|
||
|
|
||
|
LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &LuidPrivilege );
|
||
|
NewPrivileges = (PTOKEN_PRIVILEGES)HeapAlloc( GetProcessHeap(), 0,
|
||
|
sizeof(TOKEN_PRIVILEGES) +
|
||
|
(1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)
|
||
|
);
|
||
|
if (NewPrivileges == NULL) {
|
||
|
CloseHandle( Token );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
NewPrivileges->PrivilegeCount = 1;
|
||
|
NewPrivileges->Privileges[0].Luid = LuidPrivilege;
|
||
|
NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||
|
|
||
|
//
|
||
|
// Enable the privilege
|
||
|
//
|
||
|
|
||
|
pbOldPriv = OldPriv;
|
||
|
fRc = AdjustTokenPrivileges( Token,
|
||
|
FALSE,
|
||
|
NewPrivileges,
|
||
|
sizeof( OldPriv ),
|
||
|
(PTOKEN_PRIVILEGES)pbOldPriv,
|
||
|
&cbNeeded
|
||
|
);
|
||
|
if (!fRc) {
|
||
|
//
|
||
|
// If the stack was too small to hold the privileges
|
||
|
// then allocate off the heap
|
||
|
//
|
||
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||
|
pbOldPriv = (PBYTE)HeapAlloc( GetProcessHeap(), 0, cbNeeded );
|
||
|
if (pbOldPriv == NULL) {
|
||
|
CloseHandle( Token );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
fRc = AdjustTokenPrivileges( Token,
|
||
|
FALSE,
|
||
|
NewPrivileges,
|
||
|
cbNeeded,
|
||
|
(PTOKEN_PRIVILEGES)pbOldPriv,
|
||
|
&cbNeeded
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
|
||
|
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;
|
||
|
|
||
|
CHAR Buffer[ MAX_PATH ];
|
||
|
DWORD Length = MAX_PATH;
|
||
|
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;
|
||
|
}
|
||
|
|