Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. verfix.c
  5. Abstract:
  6. This module fixes updates the major and minor subsystem version
  7. numbers in an executable and recomputes the checksum.
  8. Author:
  9. Robert Reichel (robertre) 2-May-1993
  10. Revision History:
  11. --*/
  12. #include <private.h>
  13. #define NEW_MAJOR_VERSION 3
  14. #define NEW_MINOR_VERSION 10
  15. void Usage()
  16. {
  17. fputs( "usage: VERFIX [-?] [-v] [-q] image-names...\n"
  18. " [-?] display this message\n"
  19. " [-n #.#] Subsystem Major.Minor versions (default to 3.10)\n"
  20. " [-q] quiet on failure\n"
  21. " [-v] verbose output\n",
  22. stderr);
  23. exit( 1 );
  24. }
  25. int
  26. __cdecl
  27. main(
  28. int argc,
  29. char *argv[]
  30. )
  31. {
  32. HANDLE FileHandle;
  33. HANDLE MappingHandle;
  34. PIMAGE_NT_HEADERS NtHeaders;
  35. PVOID BaseAddress;
  36. ULONG CheckSum;
  37. ULONG FileLength;
  38. ULONG HeaderSum;
  39. ULONG OldCheckSum;
  40. USHORT MajorSubsystemVersion;
  41. USHORT MinorSubsystemVersion;
  42. ULONG NewMajorSubsystemVersion = NEW_MAJOR_VERSION;
  43. ULONG NewMinorSubsystemVersion = NEW_MINOR_VERSION;
  44. LPSTR ImageName;
  45. BOOLEAN fVerbose = FALSE;
  46. BOOLEAN fQuiet = FALSE;
  47. LPSTR s;
  48. UCHAR c;
  49. if (argc <= 1) {
  50. Usage();
  51. }
  52. --argc;
  53. while (argc) {
  54. s = *++argv;
  55. if ( *s == '-' ) {
  56. while (c=*++s) {
  57. switch (c) {
  58. case 'q':
  59. case 'Q':
  60. fQuiet = TRUE;
  61. break;
  62. case 'v':
  63. case 'V':
  64. fVerbose=TRUE;
  65. break;
  66. case 'n':
  67. case 'N':
  68. s = *++argv;
  69. --argc;
  70. sscanf(s, "%d.%d", &NewMajorSubsystemVersion, &NewMinorSubsystemVersion);
  71. goto NextArgument;
  72. break;
  73. case 'h':
  74. case 'H':
  75. case '?':
  76. Usage();
  77. default:
  78. fprintf( stderr, "VERFIX: illegal option /%c\n", c );
  79. Usage();
  80. }
  81. }
  82. } else {
  83. ImageName = s;
  84. FileHandle = CreateFile( ImageName,
  85. GENERIC_READ | GENERIC_WRITE,
  86. FILE_SHARE_READ,
  87. NULL,
  88. OPEN_EXISTING,
  89. 0,
  90. NULL
  91. );
  92. if (FileHandle == INVALID_HANDLE_VALUE) {
  93. if (!fQuiet) {
  94. fprintf( stderr, "VERFIX: Unable to open %s (%u) - skipping\n", ImageName, GetLastError() );
  95. goto NextArgument;
  96. }
  97. }
  98. MappingHandle = CreateFileMapping( FileHandle,
  99. NULL,
  100. PAGE_READWRITE,
  101. 0,
  102. 0,
  103. NULL
  104. );
  105. if (MappingHandle == NULL) {
  106. CloseHandle( FileHandle );
  107. if (!fQuiet) {
  108. fprintf( stderr, "VERFIX: Unable to create mapping object for file %s (%u) - skipping\n", ImageName, GetLastError() );
  109. }
  110. } else {
  111. BaseAddress = MapViewOfFile( MappingHandle,
  112. FILE_MAP_READ | FILE_MAP_WRITE,
  113. 0,
  114. 0,
  115. 0
  116. );
  117. CloseHandle( MappingHandle );
  118. if (BaseAddress == NULL) {
  119. CloseHandle( FileHandle );
  120. if (!fQuiet ) {
  121. fprintf( stderr, "VERFIX: Unable to map view of file %s (%u) - skipping\n", ImageName, GetLastError() );
  122. }
  123. } else {
  124. //
  125. // Get the length of the file in bytes and compute the checksum.
  126. //
  127. FileLength = GetFileSize( FileHandle, NULL );
  128. //
  129. // Obtain a pointer to the header information.
  130. //
  131. NtHeaders = ImageNtHeader( BaseAddress );
  132. if (NtHeaders == NULL) {
  133. CloseHandle( FileHandle );
  134. UnmapViewOfFile( BaseAddress );
  135. if (!fQuiet) {
  136. fprintf( stderr, "VERFIX: %s is not a valid image file - skipping\n", ImageName, GetLastError() );
  137. }
  138. } else {
  139. //
  140. // Write the information to the file. Update the
  141. // SubsystemVersion major and minor codes.
  142. //
  143. MajorSubsystemVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion;
  144. MinorSubsystemVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion;
  145. OldCheckSum = NtHeaders->OptionalHeader.CheckSum;
  146. NtHeaders->OptionalHeader.MajorSubsystemVersion = (USHORT)NewMajorSubsystemVersion;
  147. NtHeaders->OptionalHeader.MinorSubsystemVersion = (USHORT)NewMinorSubsystemVersion;
  148. //
  149. // Recompute and reset the checksum of the modified file.
  150. //
  151. (VOID) CheckSumMappedFile( BaseAddress,
  152. FileLength,
  153. &HeaderSum,
  154. &CheckSum
  155. );
  156. NtHeaders->OptionalHeader.CheckSum = CheckSum;
  157. if (fVerbose) {
  158. printf( "%s - Old version: %u.%u Old Checksum: %x",
  159. ImageName, MajorSubsystemVersion, MinorSubsystemVersion, OldCheckSum
  160. );
  161. printf( " New version: %u.%u New Checksum: %x\n",
  162. NtHeaders->OptionalHeader.MajorSubsystemVersion,
  163. NtHeaders->OptionalHeader.MinorSubsystemVersion,
  164. NtHeaders->OptionalHeader.CheckSum
  165. );
  166. }
  167. if (!FlushViewOfFile( BaseAddress, FileLength )) {
  168. if (!fQuiet) {
  169. fprintf( stderr,
  170. "VERFIX: Flush of %s failed (%u)\n",
  171. ImageName,
  172. GetLastError()
  173. );
  174. }
  175. }
  176. UnmapViewOfFile( BaseAddress );
  177. if (!TouchFileTimes( FileHandle, NULL )) {
  178. if (!fQuiet) {
  179. fprintf( stderr, "VERFIX: Unable to touch file %s (%u)\n", ImageName, GetLastError() );
  180. }
  181. }
  182. CloseHandle( FileHandle );
  183. }
  184. }
  185. }
  186. }
  187. NextArgument:
  188. --argc;
  189. }
  190. return 0;
  191. }