windows-nt/Source/XPSP1/NT/sdktools/debuggers/imagehlp/imagecfg.c
2020-09-26 16:20:57 +08:00

998 lines
38 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
imagecfg.c
Abstract:
This function change the image loader configuration information in an image file.
Author:
Steve Wood (stevewo) 8-Nov-1994
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <private.h>
//
// Applications should include the following declaration in their
// global data to create an IMAGE_LOAD_CONFIG_DIRECTORY entry for
// their image. Non-zero entries override defaults.
//
#if 0
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
0, // Characteristics;
0, // TimeDateStamp;
4, // MajorVersion;
0, // MinorVersion;
0, // GlobalFlagsClear;
0, // GlobalFlagsSet;
0, // CriticalSectionDefaultTimeout;
0, // DeCommitFreeBlockThreshold;
0, // DeCommitTotalFreeThreshold;
0, // LockPrefixTable;
0, // MaximumAllocationSize;
0, // VirtualMemoryThreshold;
0, // ProcessHeapFlags;
0, // ProcessAffinityMask;
0, 0, 0 // Reserved[ 3 ];
};
#endif
struct {
DWORD Flag;
LPSTR ClearPrefix;
LPSTR SetPrefix;
LPSTR Description;
} NtGlobalFlagNames[] = {
{FLG_STOP_ON_EXCEPTION, "Don't ", "", "Stop on exception"},
{FLG_SHOW_LDR_SNAPS, "Don't ", "", "Show Loader Debugging Information"},
{FLG_DEBUG_INITIAL_COMMAND, "Don't ", "", "Debug Initial Command (WINLOGON)"},
{FLG_STOP_ON_HUNG_GUI, "Don't ", "", "Stop on Hung GUI"},
{FLG_HEAP_ENABLE_TAIL_CHECK, "Disable", "Enable", " Heap Tail Checking"},
{FLG_HEAP_ENABLE_FREE_CHECK, "Disable", "Enable", " Heap Free Checking"},
{FLG_HEAP_VALIDATE_PARAMETERS, "Disable", "Enable", " Heap Parameter Validation"},
{FLG_HEAP_VALIDATE_ALL, "Disable", "Enable", " Heap Validate on Call"},
{FLG_POOL_ENABLE_TAGGING, "Disable", "Enable", " Pool Tagging"},
{FLG_HEAP_ENABLE_TAGGING, "Disable", "Enable", " Heap Tagging"},
{FLG_USER_STACK_TRACE_DB, "Disable", "Enable", " User Mode Stack Backtrace DB (x86 checked only)"},
{FLG_KERNEL_STACK_TRACE_DB, "Disable", "Enable", " Kernel Mode Stack Backtrace DB (x86 checked only)"},
{FLG_MAINTAIN_OBJECT_TYPELIST, "Don't ", "", "Maintain list of kernel mode objects by type"},
{FLG_HEAP_ENABLE_TAG_BY_DLL, "Disable", "Enable", " Heap DLL Tagging"},
{FLG_ENABLE_CSRDEBUG, "Disable", "Enable", " Debugging of CSRSS"},
{FLG_ENABLE_KDEBUG_SYMBOL_LOAD, "Disable", "Enable", " Kernel Debugger Symbol load"},
{FLG_DISABLE_PAGE_KERNEL_STACKS, "Enable", "Disable", " Paging of Kernel Stacks"},
{FLG_HEAP_DISABLE_COALESCING, "Enable", "Disable", " Heap Coalescing on Free"},
{FLG_ENABLE_CLOSE_EXCEPTIONS, "Disable", "Enable", " Close Exceptions"},
{FLG_ENABLE_EXCEPTION_LOGGING, "Disable", "Enable", " Exception Logging"},
{FLG_ENABLE_HANDLE_TYPE_TAGGING, "Disable", "Enable", " Handle type tagging"},
{FLG_HEAP_PAGE_ALLOCS, "Disable", "Enable", " Heap page allocs"},
{FLG_DEBUG_INITIAL_COMMAND_EX, "Disable", "Enable", " Extended debug initial command"},
{FLG_DISABLE_DBGPRINT, "Enable", "Disable"," DbgPrint to debugger"},
{0, NULL}
};
void
DisplayGlobalFlags(
LPSTR IndentString,
DWORD NtGlobalFlags,
BOOLEAN Set
)
{
ULONG i;
for (i=0; NtGlobalFlagNames[i].Description; i++) {
if (NtGlobalFlagNames[i].Flag & NtGlobalFlags) {
printf( "%s%s%s\n",
IndentString,
Set ? NtGlobalFlagNames[i].SetPrefix :
NtGlobalFlagNames[i].ClearPrefix,
NtGlobalFlagNames[i].Description
);
}
}
return;
}
BOOL fVerbose;
BOOL fUsage;
BOOL fConfigInfoChanged;
BOOL fImageHasConfigInfo;
BOOL fImageHeaderChanged;
LPSTR CurrentImageName;
PIMAGE_OPTIONAL_HEADER32 OptionalHeader32;
PIMAGE_OPTIONAL_HEADER64 OptionalHeader64;
PIMAGE_FILE_HEADER FileHeader;
LOADED_IMAGE CurrentImage;
IMAGE_LOAD_CONFIG_DIRECTORY ConfigInfo;
CHAR DebugFilePath[_MAX_PATH];
LPSTR SymbolPath;
ULONG GlobalFlagsClear;
ULONG GlobalFlagsSet;
ULONG CriticalSectionDefaultTimeout;
ULONG DeCommitFreeBlockThreshold;
ULONG DeCommitTotalFreeThreshold;
ULONG MaximumAllocationSize;
ULONG VirtualMemoryThreshold;
ULONG ProcessHeapFlags;
ULONG MajorSubsystemVersion;
ULONG MinorSubsystemVersion;
ULONG BuildNumber;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
PULONG pBuildNumber;
ULONG Win32VersionValue;
ULONG Win32CSDVerValue;
BOOLEAN fUniprocessorOnly;
BOOLEAN fRestrictedWorkingSet;
BOOLEAN fEnableLargeAddresses;
BOOLEAN fNoBind;
BOOLEAN fEnableTerminalServerAware;
BOOLEAN fDisableTerminalServerAware;
BOOLEAN fSwapRunNet;
BOOLEAN fSwapRunCD;
BOOLEAN fQuiet;
DWORD ImageProcessAffinityMask;
VOID
DisplayImageInfo(
BOOL HasConfigInfo
);
PVOID
GetAddressOfExportedData(
PLOADED_IMAGE Dll,
LPSTR ExportedName
);
ULONG
ConvertNum(
char *s
)
{
ULONG n, Result;
if (!_strnicmp( s, "0x", 2 )) {
n = sscanf( s+2, "%x", &Result );
} else {
n = sscanf( s, "%u", &Result );
}
if (n != 1) {
return 0;
} else {
return Result;
}
}
int __cdecl
main(
int argc,
char *argv[],
char *envp[]
)
{
UCHAR c;
LPSTR p, sMajor, sMinor, sReserve, sCommit;
ULONG HeaderSum;
SYSTEMTIME SystemTime;
FILETIME LastWriteTime;
DWORD OldChecksum;
fUsage = FALSE;
fVerbose = FALSE;
_tzset();
if (argc <= 1) {
goto showUsage;
}
while (--argc) {
p = *++argv;
if (*p == '/' || *p == '-') {
while (c = *++p)
switch (toupper( c )) {
case '?':
fUsage = TRUE;
break;
case 'A':
if (--argc) {
ImageProcessAffinityMask = ConvertNum( *++argv );
if (ImageProcessAffinityMask == 0) {
fprintf( stderr, "IMAGECFG: invalid affinity mask specified to /a switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /a switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'B':
if (--argc) {
BuildNumber = ConvertNum( *++argv );
if (BuildNumber == 0) {
fprintf( stderr, "IMAGECFG: invalid build number specified to /b switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /b switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'C':
if (--argc) {
if (sscanf( *++argv, "%x", &Win32CSDVerValue ) != 1) {
fprintf( stderr, "IMAGECFG: invalid version string specified to /c switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /c switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'D':
if (argc >= 2) {
argc -= 2;
DeCommitFreeBlockThreshold = ConvertNum( *++argv );
DeCommitTotalFreeThreshold = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /d switch missing arguments.\n" );
fUsage = TRUE;
}
break;
case 'G':
if (argc >= 2) {
argc -= 2;
GlobalFlagsClear = ConvertNum( *++argv );
GlobalFlagsSet = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /g switch missing arguments.\n" );
fUsage = TRUE;
}
break;
case 'H':
if (argc > 2) {
INT flag = -1;
if (sscanf( *++argv, "%d", &flag ) != 1) {
fprintf( stderr, "IMAGECFG: invalid option string specified to /h switch.\n" );
fUsage = TRUE;
} else {
--argc;
if (flag == 0) {
fDisableTerminalServerAware = TRUE;
} else if (flag == 1) {
fEnableTerminalServerAware = TRUE;
} else {
fprintf( stderr, "IMAGECFG: /h switch invalid argument.\n" );
fUsage = TRUE;
}
}
} else {
fprintf( stderr, "IMAGECFG: /h switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'K':
if (--argc) {
sReserve = *++argv;
sCommit = strchr( sReserve, '.' );
if (sCommit != NULL) {
*sCommit++ = '\0';
SizeOfStackCommit = ConvertNum( sCommit );
SizeOfStackCommit = ((SizeOfStackCommit + 0xFFF) & ~0xFFF);
if (SizeOfStackCommit == 0) {
fprintf( stderr, "IMAGECFG: invalid stack commit size specified to /k switch.\n" );
fUsage = TRUE;
}
}
SizeOfStackReserve = ConvertNum( sReserve );
SizeOfStackReserve = ((SizeOfStackReserve + 0xFFFF) & ~0xFFFF);
if (SizeOfStackReserve == 0) {
fprintf( stderr, "IMAGECFG: invalid stack reserve size specified to /k switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /w switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'L':
fEnableLargeAddresses = TRUE;
break;
case 'M':
if (--argc) {
MaximumAllocationSize = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /m switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'N':
fNoBind = TRUE;
break;
case 'O':
if (--argc) {
CriticalSectionDefaultTimeout = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /o switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'P':
if (--argc) {
ProcessHeapFlags = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /p switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'Q':
fQuiet = TRUE;
break;
case 'R':
fRestrictedWorkingSet = TRUE;
break;
case 'S':
if (--argc) {
SymbolPath = *++argv;
} else {
fprintf( stderr, "IMAGECFG: /s switch missing path argument.\n" );
fUsage = TRUE;
}
break;
case 'T':
if (--argc) {
VirtualMemoryThreshold = ConvertNum( *++argv );
} else {
fprintf( stderr, "IMAGECFG: /t switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'U':
fUniprocessorOnly = TRUE;
break;
case 'V':
if (--argc) {
sMajor = *++argv;
sMinor = strchr( sMajor, '.' );
if (sMinor != NULL) {
*sMinor++ = '\0';
MinorSubsystemVersion = ConvertNum( sMinor );
}
MajorSubsystemVersion = ConvertNum( sMajor );
if (MajorSubsystemVersion == 0) {
fprintf( stderr, "IMAGECFG: invalid version string specified to /v switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /v switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'W':
if (--argc) {
if (sscanf( *++argv, "%x", &Win32VersionValue ) != 1) {
fprintf( stderr, "IMAGECFG: invalid version string specified to /w switch.\n" );
fUsage = TRUE;
}
} else {
fprintf( stderr, "IMAGECFG: /w switch missing argument.\n" );
fUsage = TRUE;
}
break;
case 'X':
fSwapRunNet = TRUE;
break;
case 'Y':
fSwapRunCD = TRUE;
break;
default:
fprintf( stderr, "IMAGECFG: Invalid switch - /%c\n", c );
fUsage = TRUE;
break;
}
if ( fUsage ) {
showUsage:
fprintf( stderr,
"usage: IMAGECFG [switches] image-names... \n"
" [-?] display this message\n"
" [-a Process Affinity mask value in hex]\n"
" [-b BuildNumber]\n"
" [-c Win32 GetVersionEx Service Pack return value in hex]\n"
" [-d decommit thresholds]\n"
" [-g bitsToClear bitsToSet]\n"
" [-h 1|0 (Enable/Disable Terminal Server Compatible bit)\n"
" [-k StackReserve[.StackCommit]\n"
" [-l enable large (>2GB) addresses\n"
" [-m maximum allocation size]\n"
" [-n bind no longer allowed on this image\n"
" [-o default critical section timeout\n"
" [-p process heap flags]\n"
" [-q only print config info if changed\n"
" [-r run with restricted working set]\n"
" [-s path to symbol files]\n"
" [-t VirtualAlloc threshold]\n"
" [-u Marks image as uniprocessor only]\n"
" [-v MajorVersion.MinorVersion]\n"
" [-w Win32 GetVersion return value in hex]\n"
" [-x Mark image as Net - Run From Swapfile\n"
" [-y Mark image as Removable - Run From Swapfile\n"
);
exit( 1 );
}
} else {
//
// Map and load the current image
//
OptionalHeader32 = NULL;
OptionalHeader64 = NULL;
FileHeader = NULL;
CurrentImageName = p;
if (MapAndLoad( CurrentImageName,
NULL,
&CurrentImage,
FALSE,
TRUE
)
) {
if (BuildNumber != 0) {
pBuildNumber = (PULONG) GetAddressOfExportedData( &CurrentImage, "NtBuildNumber" );
if (pBuildNumber == NULL) {
fprintf( stderr,
"IMAGECFG: Unable to find exported NtBuildNumber image %s\n",
CurrentImageName
);
}
}
FileHeader = &((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->FileHeader;
OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
&OptionalHeader32,
&OptionalHeader64);
//
// make sure the image has correct configuration information,
// and that the LockPrefixTable is set up properly
//
fConfigInfoChanged = FALSE;
fImageHeaderChanged = FALSE;
ZeroMemory(&ConfigInfo, sizeof(ConfigInfo));
fImageHasConfigInfo = GetImageConfigInformation( &CurrentImage, &ConfigInfo );
if (!fQuiet) {
DisplayImageInfo( fImageHasConfigInfo );
}
UnMapAndLoad( &CurrentImage );
OptionalHeader32 = NULL;
OptionalHeader64 = NULL;
FileHeader = NULL;
if (fConfigInfoChanged || fImageHeaderChanged) {
if (!MapAndLoad( CurrentImageName,
NULL,
&CurrentImage,
FALSE,
FALSE
)
) {
if (!CurrentImage.fDOSImage) {
fprintf( stderr, "IMAGECFG: unable to map and load %s\n", CurrentImageName );
} else {
fprintf( stderr,
"IMAGECFG: unable to modify DOS or Windows image file - %s\n",
CurrentImageName
);
}
} else {
FileHeader = &((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->FileHeader;
OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
&OptionalHeader32,
&OptionalHeader64);
if (GlobalFlagsClear) {
ConfigInfo.GlobalFlagsClear = GlobalFlagsClear;
}
if (GlobalFlagsSet) {
ConfigInfo.GlobalFlagsSet = GlobalFlagsSet;
}
if (CriticalSectionDefaultTimeout) {
ConfigInfo.CriticalSectionDefaultTimeout = CriticalSectionDefaultTimeout;
}
if (ProcessHeapFlags) {
ConfigInfo.ProcessHeapFlags = ProcessHeapFlags;
}
if (DeCommitFreeBlockThreshold) {
ConfigInfo.DeCommitFreeBlockThreshold = DeCommitFreeBlockThreshold;
}
if (DeCommitTotalFreeThreshold) {
ConfigInfo.DeCommitTotalFreeThreshold = DeCommitTotalFreeThreshold;
}
if (MaximumAllocationSize) {
ConfigInfo.MaximumAllocationSize = MaximumAllocationSize;
}
if (VirtualMemoryThreshold) {
ConfigInfo.VirtualMemoryThreshold = VirtualMemoryThreshold;
}
if (ImageProcessAffinityMask) {
ConfigInfo.ProcessAffinityMask = ImageProcessAffinityMask;
}
if (fEnableLargeAddresses) {
FileHeader->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
}
if (fNoBind) {
OPTIONALHEADER_SET_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_NO_BIND);
}
if (fEnableTerminalServerAware) {
OPTIONALHEADER_SET_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
}
if (fDisableTerminalServerAware) {
OPTIONALHEADER_CLEAR_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
}
if (fSwapRunNet) {
FileHeader->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
}
if (fSwapRunCD) {
FileHeader->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
}
if (fUniprocessorOnly) {
FileHeader->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY;
}
if (fRestrictedWorkingSet) {
FileHeader->Characteristics |= IMAGE_FILE_AGGRESIVE_WS_TRIM;
}
if (MajorSubsystemVersion != 0) {
OPTIONALHEADER_ASSIGN(MajorSubsystemVersion, (USHORT)MajorSubsystemVersion);
OPTIONALHEADER_ASSIGN(MinorSubsystemVersion, (USHORT)MinorSubsystemVersion);
}
if (Win32VersionValue != 0) {
OPTIONALHEADER_ASSIGN(Win32VersionValue, Win32VersionValue);
}
if (Win32CSDVerValue != 0) {
ConfigInfo.CSDVersion = (USHORT)Win32CSDVerValue;
}
if (SizeOfStackReserve) {
OPTIONALHEADER_ASSIGN(SizeOfStackReserve, SizeOfStackReserve);
}
if (SizeOfStackCommit) {
OPTIONALHEADER_ASSIGN(SizeOfStackCommit, SizeOfStackCommit);
}
if (BuildNumber != 0) {
pBuildNumber = (PULONG) GetAddressOfExportedData( &CurrentImage, "NtBuildNumber" );
if (pBuildNumber == NULL) {
fprintf( stderr,
"IMAGECFG: Unable to find exported NtBuildNumber image %s\n",
CurrentImageName
);
} else {
if (BuildNumber & 0xFFFF0000) {
*pBuildNumber = BuildNumber;
} else {
*(PUSHORT)pBuildNumber = (USHORT)BuildNumber;
}
}
}
if (fConfigInfoChanged) {
if (SetImageConfigInformation( &CurrentImage, &ConfigInfo )) {
if (!fQuiet) {
printf( "%s updated with the following configuration information:\n", CurrentImageName );
DisplayImageInfo( fImageHasConfigInfo );
}
} else {
fprintf( stderr, "IMAGECFG: Unable to update configuration information in image.\n" );
}
}
//
// recompute the checksum.
//
OldChecksum = OPTIONALHEADER(CheckSum);
OPTIONALHEADER_LV(CheckSum) = 0;
CheckSumMappedFile(
(PVOID)CurrentImage.MappedAddress,
CurrentImage.SizeOfImage,
&HeaderSum,
&OPTIONALHEADER_LV(CheckSum)
);
// And update the .dbg file (if requested)
if (SymbolPath &&
FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
if (UpdateDebugInfoFileEx( CurrentImageName,
SymbolPath,
DebugFilePath,
(PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
OldChecksum
)
) {
if (GetLastError() == ERROR_INVALID_DATA) {
printf( "Warning: Old checksum did not match for %s\n", DebugFilePath);
}
printf( "Updated symbols for %s\n", DebugFilePath );
} else {
printf( "Unable to update symbols: %s\n", DebugFilePath );
}
}
GetSystemTime( &SystemTime );
if (SystemTimeToFileTime( &SystemTime, &LastWriteTime )) {
SetFileTime( CurrentImage.hFile, NULL, NULL, &LastWriteTime );
}
UnMapAndLoad( &CurrentImage );
}
}
} else
if (!CurrentImage.fDOSImage) {
fprintf( stderr, "IMAGECFG: unable to map and load %s GetLastError= %d\n", CurrentImageName, GetLastError() );
} else {
fprintf( stderr,
"IMAGECFG: unable to modify DOS or Windows image file - %s\n",
CurrentImageName
);
}
}
}
exit( 1 );
return 1;
}
__inline PVOID
GetVaForRva(
PLOADED_IMAGE Image,
ULONG Rva
)
{
PVOID Va;
Va = ImageRvaToVa( Image->FileHeader,
Image->MappedAddress,
Rva,
&Image->LastRvaSection
);
return Va;
}
PVOID
GetAddressOfExportedData(
PLOADED_IMAGE Dll,
LPSTR ExportedName
)
{
PIMAGE_EXPORT_DIRECTORY Exports;
ULONG ExportSize;
USHORT HintIndex;
USHORT OrdinalNumber;
PULONG NameTableBase;
PUSHORT NameOrdinalTableBase;
PULONG FunctionTableBase;
LPSTR NameTableName;
Exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData( (PVOID)Dll->MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&ExportSize
);
if (Exports) {
NameTableBase = (PULONG)GetVaForRva( Dll, Exports->AddressOfNames );
NameOrdinalTableBase = (PUSHORT)GetVaForRva( Dll, Exports->AddressOfNameOrdinals );
FunctionTableBase = (PULONG)GetVaForRva( Dll, Exports->AddressOfFunctions );
if (NameTableBase != NULL &&
NameOrdinalTableBase != NULL &&
FunctionTableBase != NULL
) {
for (HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++) {
NameTableName = (LPSTR)GetVaForRva( Dll, NameTableBase[ HintIndex ] );
if (NameTableName) {
if (!strcmp( ExportedName, NameTableName )) {
OrdinalNumber = NameOrdinalTableBase[ HintIndex ];
return FunctionTableBase[ OrdinalNumber ] + Dll->MappedAddress;
}
}
}
}
}
return NULL;
}
VOID
DisplayImageInfo(
BOOL HasConfigInfo
)
{
printf( "%s contains the following configuration information:\n", CurrentImageName );
// if (HasConfigInfo) {
if (ConfigInfo.GlobalFlagsClear != 0) {
printf( " NtGlobalFlags to clear: %08x\n",
ConfigInfo.GlobalFlagsClear
);
DisplayGlobalFlags( " ", ConfigInfo.GlobalFlagsClear, FALSE );
}
if (GlobalFlagsClear && ConfigInfo.GlobalFlagsClear != GlobalFlagsClear) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.GlobalFlagsSet != 0) {
printf( " NtGlobalFlags to set: %08x\n",
ConfigInfo.GlobalFlagsSet
);
DisplayGlobalFlags( " ", ConfigInfo.GlobalFlagsSet, TRUE );
}
if (GlobalFlagsSet && ConfigInfo.GlobalFlagsSet != GlobalFlagsSet) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.CriticalSectionDefaultTimeout != 0) {
printf( " Default Critical Section Timeout: %u milliseconds\n",
ConfigInfo.CriticalSectionDefaultTimeout
);
}
if (CriticalSectionDefaultTimeout &&
ConfigInfo.CriticalSectionDefaultTimeout != CriticalSectionDefaultTimeout
) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.ProcessHeapFlags != 0) {
printf( " Process Heap Flags: %08x\n",
ConfigInfo.ProcessHeapFlags
);
}
if (ProcessHeapFlags && ConfigInfo.ProcessHeapFlags != ProcessHeapFlags) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.DeCommitFreeBlockThreshold != 0) {
printf( " Process Heap DeCommit Free Block threshold: %08x\n",
ConfigInfo.DeCommitFreeBlockThreshold
);
}
if (DeCommitFreeBlockThreshold &&
ConfigInfo.DeCommitFreeBlockThreshold != DeCommitFreeBlockThreshold
) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.DeCommitTotalFreeThreshold != 0) {
printf( " Process Heap DeCommit Total Free threshold: %08x\n",
ConfigInfo.DeCommitTotalFreeThreshold
);
}
if (DeCommitTotalFreeThreshold &&
ConfigInfo.DeCommitTotalFreeThreshold != DeCommitTotalFreeThreshold
) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.MaximumAllocationSize != 0) {
printf( " Process Heap Maximum Allocation Size: %08x\n",
ConfigInfo.MaximumAllocationSize
);
}
if (MaximumAllocationSize && ConfigInfo.MaximumAllocationSize != MaximumAllocationSize) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.VirtualMemoryThreshold != 0) {
printf( " Process Heap VirtualAlloc Threshold: %08x\n",
ConfigInfo.VirtualMemoryThreshold
);
}
if (VirtualMemoryThreshold &&
ConfigInfo.VirtualMemoryThreshold != VirtualMemoryThreshold
) {
fConfigInfoChanged = TRUE;
}
if (ConfigInfo.ProcessAffinityMask != 0) {
printf( " Process Affinity Mask: %08x\n",
ConfigInfo.ProcessAffinityMask
);
}
if (ImageProcessAffinityMask &&
ConfigInfo.ProcessAffinityMask != ImageProcessAffinityMask
) {
fConfigInfoChanged = TRUE;
}
// } else {
// memset( &ConfigInfo, 0, sizeof( ConfigInfo ) );
// }
printf( " Subsystem Version of %u.%u\n",
OPTIONALHEADER(MajorSubsystemVersion),
OPTIONALHEADER(MinorSubsystemVersion)
);
if (MajorSubsystemVersion != 0) {
if (OPTIONALHEADER(MajorSubsystemVersion) != (USHORT)MajorSubsystemVersion ||
OPTIONALHEADER(MinorSubsystemVersion) != (USHORT)MinorSubsystemVersion
) {
fImageHeaderChanged = TRUE;
}
}
if (pBuildNumber != NULL) {
printf( " Build Number of %08x\n", *pBuildNumber );
if (BuildNumber != 0) {
if (BuildNumber & 0xFFFF0000) {
if (*pBuildNumber != BuildNumber) {
fImageHeaderChanged = TRUE;
}
} else {
if (*(PUSHORT)pBuildNumber != (USHORT)BuildNumber) {
fImageHeaderChanged = TRUE;
}
}
}
}
if (OPTIONALHEADER(Win32VersionValue) != 0) {
printf( " Win32 GetVersion return value: %08x\n",
OPTIONALHEADER(Win32VersionValue)
);
}
if (Win32VersionValue != 0 &&
OPTIONALHEADER(Win32VersionValue) != Win32VersionValue
) {
fImageHeaderChanged = TRUE;
}
if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) {
printf( " Image can handle large (>2GB) addresses\n" );
}
if (OPTIONALHEADER(DllCharacteristics) & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE) {
printf( " Image is Terminal Server aware\n" );
}
if (fEnableLargeAddresses &&
!(FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
) {
fImageHeaderChanged = TRUE;
printf( " Image is Large Address aware\n" );
}
if (fNoBind) {
fImageHeaderChanged = TRUE;
printf( " Image will no longer support binding\n" );
}
if (fEnableTerminalServerAware || fDisableTerminalServerAware) {
printf( " Image %s Terminal Server Aware\n", fEnableTerminalServerAware ? "is" : "is not");
fImageHeaderChanged = TRUE;
}
if (FileHeader->Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP) {
printf( " Image will run from swapfile if located on net\n" );
}
if (fSwapRunNet &&
!(FileHeader->Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP)
) {
fImageHeaderChanged = TRUE;
}
if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) {
printf( " Image will run from swapfile if located on removable media\n" );
}
if (fSwapRunCD &&
!(FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
) {
fImageHeaderChanged = TRUE;
}
if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) {
printf( " Image can only run in uni-processor mode on multi-processor systems\n" );
}
if (fUniprocessorOnly &&
!(FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
) {
fImageHeaderChanged = TRUE;
}
if (FileHeader->Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM) {
printf( " Image working set trimmed aggressively on small memory systems\n" );
}
if (fRestrictedWorkingSet &&
!(FileHeader->Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM)
) {
fImageHeaderChanged = TRUE;
}
if (OPTIONALHEADER(SizeOfStackReserve)) {
printf( " Stack Reserve Size: 0x%x\n", OPTIONALHEADER(SizeOfStackReserve) );
}
if (SizeOfStackReserve &&
OPTIONALHEADER(SizeOfStackReserve) != SizeOfStackReserve
) {
fImageHeaderChanged = TRUE;
}
if (OPTIONALHEADER(SizeOfStackCommit)) {
printf( " Stack Commit Size: 0x%x\n", OPTIONALHEADER(SizeOfStackCommit) );
}
if (SizeOfStackCommit &&
OPTIONALHEADER(SizeOfStackCommit) != SizeOfStackCommit
) {
fImageHeaderChanged = TRUE;
}
return;
}