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

227 lines
7.7 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
verfix.c
Abstract:
This module fixes updates the major and minor subsystem version
numbers in an executable and recomputes the checksum.
Author:
Robert Reichel (robertre) 2-May-1993
Revision History:
--*/
#include <private.h>
#define NEW_MAJOR_VERSION 3
#define NEW_MINOR_VERSION 10
void Usage()
{
fputs( "usage: VERFIX [-?] [-v] [-q] image-names...\n"
" [-?] display this message\n"
" [-n #.#] Subsystem Major.Minor versions (default to 3.10)\n"
" [-q] quiet on failure\n"
" [-v] verbose output\n",
stderr);
exit( 1 );
}
int
__cdecl
main(
int argc,
char *argv[]
)
{
HANDLE FileHandle;
HANDLE MappingHandle;
PIMAGE_NT_HEADERS NtHeaders;
PVOID BaseAddress;
ULONG CheckSum;
ULONG FileLength;
ULONG HeaderSum;
ULONG OldCheckSum;
USHORT MajorSubsystemVersion;
USHORT MinorSubsystemVersion;
ULONG NewMajorSubsystemVersion = NEW_MAJOR_VERSION;
ULONG NewMinorSubsystemVersion = NEW_MINOR_VERSION;
LPSTR ImageName;
BOOLEAN fVerbose = FALSE;
BOOLEAN fQuiet = FALSE;
LPSTR s;
UCHAR c;
if (argc <= 1) {
Usage();
}
--argc;
while (argc) {
s = *++argv;
if ( *s == '-' ) {
while (c=*++s) {
switch (c) {
case 'q':
case 'Q':
fQuiet = TRUE;
break;
case 'v':
case 'V':
fVerbose=TRUE;
break;
case 'n':
case 'N':
s = *++argv;
--argc;
sscanf(s, "%d.%d", &NewMajorSubsystemVersion, &NewMinorSubsystemVersion);
goto NextArgument;
break;
case 'h':
case 'H':
case '?':
Usage();
default:
fprintf( stderr, "VERFIX: illegal option /%c\n", c );
Usage();
}
}
} else {
ImageName = s;
FileHandle = CreateFile( ImageName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (FileHandle == INVALID_HANDLE_VALUE) {
if (!fQuiet) {
fprintf( stderr, "VERFIX: Unable to open %s (%u) - skipping\n", ImageName, GetLastError() );
goto NextArgument;
}
}
MappingHandle = CreateFileMapping( FileHandle,
NULL,
PAGE_READWRITE,
0,
0,
NULL
);
if (MappingHandle == NULL) {
CloseHandle( FileHandle );
if (!fQuiet) {
fprintf( stderr, "VERFIX: Unable to create mapping object for file %s (%u) - skipping\n", ImageName, GetLastError() );
}
} else {
BaseAddress = MapViewOfFile( MappingHandle,
FILE_MAP_READ | FILE_MAP_WRITE,
0,
0,
0
);
CloseHandle( MappingHandle );
if (BaseAddress == NULL) {
CloseHandle( FileHandle );
if (!fQuiet ) {
fprintf( stderr, "VERFIX: Unable to map view of file %s (%u) - skipping\n", ImageName, GetLastError() );
}
} else {
//
// Get the length of the file in bytes and compute the checksum.
//
FileLength = GetFileSize( FileHandle, NULL );
//
// Obtain a pointer to the header information.
//
NtHeaders = ImageNtHeader( BaseAddress );
if (NtHeaders == NULL) {
CloseHandle( FileHandle );
UnmapViewOfFile( BaseAddress );
if (!fQuiet) {
fprintf( stderr, "VERFIX: %s is not a valid image file - skipping\n", ImageName, GetLastError() );
}
} else {
//
// Write the information to the file. Update the
// SubsystemVersion major and minor codes.
//
MajorSubsystemVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
MinorSubsystemVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
OldCheckSum = NtHeaders->OptionalHeader.CheckSum;
NtHeaders->OptionalHeader.MajorSubsystemVersion = (USHORT)NewMajorSubsystemVersion;
NtHeaders->OptionalHeader.MinorSubsystemVersion = (USHORT)NewMinorSubsystemVersion;
//
// Recompute and reset the checksum of the modified file.
//
(VOID) CheckSumMappedFile( BaseAddress,
FileLength,
&HeaderSum,
&CheckSum
);
NtHeaders->OptionalHeader.CheckSum = CheckSum;
if (fVerbose) {
printf( "%s - Old version: %u.%u Old Checksum: %x",
ImageName, MajorSubsystemVersion, MinorSubsystemVersion, OldCheckSum
);
printf( " New version: %u.%u New Checksum: %x\n",
NtHeaders->OptionalHeader.MajorSubsystemVersion,
NtHeaders->OptionalHeader.MinorSubsystemVersion,
NtHeaders->OptionalHeader.CheckSum
);
}
if (!FlushViewOfFile( BaseAddress, FileLength )) {
if (!fQuiet) {
fprintf( stderr,
"VERFIX: Flush of %s failed (%u)\n",
ImageName,
GetLastError()
);
}
}
UnmapViewOfFile( BaseAddress );
if (!TouchFileTimes( FileHandle, NULL )) {
if (!fQuiet) {
fprintf( stderr, "VERFIX: Unable to touch file %s (%u)\n", ImageName, GetLastError() );
}
}
CloseHandle( FileHandle );
}
}
}
}
NextArgument:
--argc;
}
return 0;
}