998 lines
38 KiB
C
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;
|
|
}
|