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.

997 lines
38 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. imagecfg.c
  5. Abstract:
  6. This function change the image loader configuration information in an image file.
  7. Author:
  8. Steve Wood (stevewo) 8-Nov-1994
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <private.h>
  15. //
  16. // Applications should include the following declaration in their
  17. // global data to create an IMAGE_LOAD_CONFIG_DIRECTORY entry for
  18. // their image. Non-zero entries override defaults.
  19. //
  20. #if 0
  21. IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
  22. 0, // Characteristics;
  23. 0, // TimeDateStamp;
  24. 4, // MajorVersion;
  25. 0, // MinorVersion;
  26. 0, // GlobalFlagsClear;
  27. 0, // GlobalFlagsSet;
  28. 0, // CriticalSectionDefaultTimeout;
  29. 0, // DeCommitFreeBlockThreshold;
  30. 0, // DeCommitTotalFreeThreshold;
  31. 0, // LockPrefixTable;
  32. 0, // MaximumAllocationSize;
  33. 0, // VirtualMemoryThreshold;
  34. 0, // ProcessHeapFlags;
  35. 0, // ProcessAffinityMask;
  36. 0, 0, 0 // Reserved[ 3 ];
  37. };
  38. #endif
  39. struct {
  40. DWORD Flag;
  41. LPSTR ClearPrefix;
  42. LPSTR SetPrefix;
  43. LPSTR Description;
  44. } NtGlobalFlagNames[] = {
  45. {FLG_STOP_ON_EXCEPTION, "Don't ", "", "Stop on exception"},
  46. {FLG_SHOW_LDR_SNAPS, "Don't ", "", "Show Loader Debugging Information"},
  47. {FLG_DEBUG_INITIAL_COMMAND, "Don't ", "", "Debug Initial Command (WINLOGON)"},
  48. {FLG_STOP_ON_HUNG_GUI, "Don't ", "", "Stop on Hung GUI"},
  49. {FLG_HEAP_ENABLE_TAIL_CHECK, "Disable", "Enable", " Heap Tail Checking"},
  50. {FLG_HEAP_ENABLE_FREE_CHECK, "Disable", "Enable", " Heap Free Checking"},
  51. {FLG_HEAP_VALIDATE_PARAMETERS, "Disable", "Enable", " Heap Parameter Validation"},
  52. {FLG_HEAP_VALIDATE_ALL, "Disable", "Enable", " Heap Validate on Call"},
  53. {FLG_POOL_ENABLE_TAGGING, "Disable", "Enable", " Pool Tagging"},
  54. {FLG_HEAP_ENABLE_TAGGING, "Disable", "Enable", " Heap Tagging"},
  55. {FLG_USER_STACK_TRACE_DB, "Disable", "Enable", " User Mode Stack Backtrace DB (x86 checked only)"},
  56. {FLG_KERNEL_STACK_TRACE_DB, "Disable", "Enable", " Kernel Mode Stack Backtrace DB (x86 checked only)"},
  57. {FLG_MAINTAIN_OBJECT_TYPELIST, "Don't ", "", "Maintain list of kernel mode objects by type"},
  58. {FLG_HEAP_ENABLE_TAG_BY_DLL, "Disable", "Enable", " Heap DLL Tagging"},
  59. {FLG_ENABLE_CSRDEBUG, "Disable", "Enable", " Debugging of CSRSS"},
  60. {FLG_ENABLE_KDEBUG_SYMBOL_LOAD, "Disable", "Enable", " Kernel Debugger Symbol load"},
  61. {FLG_DISABLE_PAGE_KERNEL_STACKS, "Enable", "Disable", " Paging of Kernel Stacks"},
  62. {FLG_HEAP_DISABLE_COALESCING, "Enable", "Disable", " Heap Coalescing on Free"},
  63. {FLG_ENABLE_CLOSE_EXCEPTIONS, "Disable", "Enable", " Close Exceptions"},
  64. {FLG_ENABLE_EXCEPTION_LOGGING, "Disable", "Enable", " Exception Logging"},
  65. {FLG_ENABLE_HANDLE_TYPE_TAGGING, "Disable", "Enable", " Handle type tagging"},
  66. {FLG_HEAP_PAGE_ALLOCS, "Disable", "Enable", " Heap page allocs"},
  67. {FLG_DEBUG_INITIAL_COMMAND_EX, "Disable", "Enable", " Extended debug initial command"},
  68. {FLG_DISABLE_DBGPRINT, "Enable", "Disable"," DbgPrint to debugger"},
  69. {0, NULL}
  70. };
  71. void
  72. DisplayGlobalFlags(
  73. LPSTR IndentString,
  74. DWORD NtGlobalFlags,
  75. BOOLEAN Set
  76. )
  77. {
  78. ULONG i;
  79. for (i=0; NtGlobalFlagNames[i].Description; i++) {
  80. if (NtGlobalFlagNames[i].Flag & NtGlobalFlags) {
  81. printf( "%s%s%s\n",
  82. IndentString,
  83. Set ? NtGlobalFlagNames[i].SetPrefix :
  84. NtGlobalFlagNames[i].ClearPrefix,
  85. NtGlobalFlagNames[i].Description
  86. );
  87. }
  88. }
  89. return;
  90. }
  91. BOOL fVerbose;
  92. BOOL fUsage;
  93. BOOL fConfigInfoChanged;
  94. BOOL fImageHasConfigInfo;
  95. BOOL fImageHeaderChanged;
  96. LPSTR CurrentImageName;
  97. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32;
  98. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64;
  99. PIMAGE_FILE_HEADER FileHeader;
  100. LOADED_IMAGE CurrentImage;
  101. IMAGE_LOAD_CONFIG_DIRECTORY ConfigInfo;
  102. CHAR DebugFilePath[_MAX_PATH];
  103. LPSTR SymbolPath;
  104. ULONG GlobalFlagsClear;
  105. ULONG GlobalFlagsSet;
  106. ULONG CriticalSectionDefaultTimeout;
  107. ULONG DeCommitFreeBlockThreshold;
  108. ULONG DeCommitTotalFreeThreshold;
  109. ULONG MaximumAllocationSize;
  110. ULONG VirtualMemoryThreshold;
  111. ULONG ProcessHeapFlags;
  112. ULONG MajorSubsystemVersion;
  113. ULONG MinorSubsystemVersion;
  114. ULONG BuildNumber;
  115. ULONG SizeOfStackReserve;
  116. ULONG SizeOfStackCommit;
  117. PULONG pBuildNumber;
  118. ULONG Win32VersionValue;
  119. ULONG Win32CSDVerValue;
  120. BOOLEAN fUniprocessorOnly;
  121. BOOLEAN fRestrictedWorkingSet;
  122. BOOLEAN fEnableLargeAddresses;
  123. BOOLEAN fNoBind;
  124. BOOLEAN fEnableTerminalServerAware;
  125. BOOLEAN fDisableTerminalServerAware;
  126. BOOLEAN fSwapRunNet;
  127. BOOLEAN fSwapRunCD;
  128. BOOLEAN fQuiet;
  129. DWORD ImageProcessAffinityMask;
  130. VOID
  131. DisplayImageInfo(
  132. BOOL HasConfigInfo
  133. );
  134. PVOID
  135. GetAddressOfExportedData(
  136. PLOADED_IMAGE Dll,
  137. LPSTR ExportedName
  138. );
  139. ULONG
  140. ConvertNum(
  141. char *s
  142. )
  143. {
  144. ULONG n, Result;
  145. if (!_strnicmp( s, "0x", 2 )) {
  146. n = sscanf( s+2, "%x", &Result );
  147. } else {
  148. n = sscanf( s, "%u", &Result );
  149. }
  150. if (n != 1) {
  151. return 0;
  152. } else {
  153. return Result;
  154. }
  155. }
  156. int __cdecl
  157. main(
  158. int argc,
  159. char *argv[],
  160. char *envp[]
  161. )
  162. {
  163. UCHAR c;
  164. LPSTR p, sMajor, sMinor, sReserve, sCommit;
  165. ULONG HeaderSum;
  166. SYSTEMTIME SystemTime;
  167. FILETIME LastWriteTime;
  168. DWORD OldChecksum;
  169. fUsage = FALSE;
  170. fVerbose = FALSE;
  171. _tzset();
  172. if (argc <= 1) {
  173. goto showUsage;
  174. }
  175. while (--argc) {
  176. p = *++argv;
  177. if (*p == '/' || *p == '-') {
  178. while (c = *++p)
  179. switch (toupper( c )) {
  180. case '?':
  181. fUsage = TRUE;
  182. break;
  183. case 'A':
  184. if (--argc) {
  185. ImageProcessAffinityMask = ConvertNum( *++argv );
  186. if (ImageProcessAffinityMask == 0) {
  187. fprintf( stderr, "IMAGECFG: invalid affinity mask specified to /a switch.\n" );
  188. fUsage = TRUE;
  189. }
  190. } else {
  191. fprintf( stderr, "IMAGECFG: /a switch missing argument.\n" );
  192. fUsage = TRUE;
  193. }
  194. break;
  195. case 'B':
  196. if (--argc) {
  197. BuildNumber = ConvertNum( *++argv );
  198. if (BuildNumber == 0) {
  199. fprintf( stderr, "IMAGECFG: invalid build number specified to /b switch.\n" );
  200. fUsage = TRUE;
  201. }
  202. } else {
  203. fprintf( stderr, "IMAGECFG: /b switch missing argument.\n" );
  204. fUsage = TRUE;
  205. }
  206. break;
  207. case 'C':
  208. if (--argc) {
  209. if (sscanf( *++argv, "%x", &Win32CSDVerValue ) != 1) {
  210. fprintf( stderr, "IMAGECFG: invalid version string specified to /c switch.\n" );
  211. fUsage = TRUE;
  212. }
  213. } else {
  214. fprintf( stderr, "IMAGECFG: /c switch missing argument.\n" );
  215. fUsage = TRUE;
  216. }
  217. break;
  218. case 'D':
  219. if (argc >= 2) {
  220. argc -= 2;
  221. DeCommitFreeBlockThreshold = ConvertNum( *++argv );
  222. DeCommitTotalFreeThreshold = ConvertNum( *++argv );
  223. } else {
  224. fprintf( stderr, "IMAGECFG: /d switch missing arguments.\n" );
  225. fUsage = TRUE;
  226. }
  227. break;
  228. case 'G':
  229. if (argc >= 2) {
  230. argc -= 2;
  231. GlobalFlagsClear = ConvertNum( *++argv );
  232. GlobalFlagsSet = ConvertNum( *++argv );
  233. } else {
  234. fprintf( stderr, "IMAGECFG: /g switch missing arguments.\n" );
  235. fUsage = TRUE;
  236. }
  237. break;
  238. case 'H':
  239. if (argc > 2) {
  240. INT flag = -1;
  241. if (sscanf( *++argv, "%d", &flag ) != 1) {
  242. fprintf( stderr, "IMAGECFG: invalid option string specified to /h switch.\n" );
  243. fUsage = TRUE;
  244. } else {
  245. --argc;
  246. if (flag == 0) {
  247. fDisableTerminalServerAware = TRUE;
  248. } else if (flag == 1) {
  249. fEnableTerminalServerAware = TRUE;
  250. } else {
  251. fprintf( stderr, "IMAGECFG: /h switch invalid argument.\n" );
  252. fUsage = TRUE;
  253. }
  254. }
  255. } else {
  256. fprintf( stderr, "IMAGECFG: /h switch missing argument.\n" );
  257. fUsage = TRUE;
  258. }
  259. break;
  260. case 'K':
  261. if (--argc) {
  262. sReserve = *++argv;
  263. sCommit = strchr( sReserve, '.' );
  264. if (sCommit != NULL) {
  265. *sCommit++ = '\0';
  266. SizeOfStackCommit = ConvertNum( sCommit );
  267. SizeOfStackCommit = ((SizeOfStackCommit + 0xFFF) & ~0xFFF);
  268. if (SizeOfStackCommit == 0) {
  269. fprintf( stderr, "IMAGECFG: invalid stack commit size specified to /k switch.\n" );
  270. fUsage = TRUE;
  271. }
  272. }
  273. SizeOfStackReserve = ConvertNum( sReserve );
  274. SizeOfStackReserve = ((SizeOfStackReserve + 0xFFFF) & ~0xFFFF);
  275. if (SizeOfStackReserve == 0) {
  276. fprintf( stderr, "IMAGECFG: invalid stack reserve size specified to /k switch.\n" );
  277. fUsage = TRUE;
  278. }
  279. } else {
  280. fprintf( stderr, "IMAGECFG: /w switch missing argument.\n" );
  281. fUsage = TRUE;
  282. }
  283. break;
  284. case 'L':
  285. fEnableLargeAddresses = TRUE;
  286. break;
  287. case 'M':
  288. if (--argc) {
  289. MaximumAllocationSize = ConvertNum( *++argv );
  290. } else {
  291. fprintf( stderr, "IMAGECFG: /m switch missing argument.\n" );
  292. fUsage = TRUE;
  293. }
  294. break;
  295. case 'N':
  296. fNoBind = TRUE;
  297. break;
  298. case 'O':
  299. if (--argc) {
  300. CriticalSectionDefaultTimeout = ConvertNum( *++argv );
  301. } else {
  302. fprintf( stderr, "IMAGECFG: /o switch missing argument.\n" );
  303. fUsage = TRUE;
  304. }
  305. break;
  306. case 'P':
  307. if (--argc) {
  308. ProcessHeapFlags = ConvertNum( *++argv );
  309. } else {
  310. fprintf( stderr, "IMAGECFG: /p switch missing argument.\n" );
  311. fUsage = TRUE;
  312. }
  313. break;
  314. case 'Q':
  315. fQuiet = TRUE;
  316. break;
  317. case 'R':
  318. fRestrictedWorkingSet = TRUE;
  319. break;
  320. case 'S':
  321. if (--argc) {
  322. SymbolPath = *++argv;
  323. } else {
  324. fprintf( stderr, "IMAGECFG: /s switch missing path argument.\n" );
  325. fUsage = TRUE;
  326. }
  327. break;
  328. case 'T':
  329. if (--argc) {
  330. VirtualMemoryThreshold = ConvertNum( *++argv );
  331. } else {
  332. fprintf( stderr, "IMAGECFG: /t switch missing argument.\n" );
  333. fUsage = TRUE;
  334. }
  335. break;
  336. case 'U':
  337. fUniprocessorOnly = TRUE;
  338. break;
  339. case 'V':
  340. if (--argc) {
  341. sMajor = *++argv;
  342. sMinor = strchr( sMajor, '.' );
  343. if (sMinor != NULL) {
  344. *sMinor++ = '\0';
  345. MinorSubsystemVersion = ConvertNum( sMinor );
  346. }
  347. MajorSubsystemVersion = ConvertNum( sMajor );
  348. if (MajorSubsystemVersion == 0) {
  349. fprintf( stderr, "IMAGECFG: invalid version string specified to /v switch.\n" );
  350. fUsage = TRUE;
  351. }
  352. } else {
  353. fprintf( stderr, "IMAGECFG: /v switch missing argument.\n" );
  354. fUsage = TRUE;
  355. }
  356. break;
  357. case 'W':
  358. if (--argc) {
  359. if (sscanf( *++argv, "%x", &Win32VersionValue ) != 1) {
  360. fprintf( stderr, "IMAGECFG: invalid version string specified to /w switch.\n" );
  361. fUsage = TRUE;
  362. }
  363. } else {
  364. fprintf( stderr, "IMAGECFG: /w switch missing argument.\n" );
  365. fUsage = TRUE;
  366. }
  367. break;
  368. case 'X':
  369. fSwapRunNet = TRUE;
  370. break;
  371. case 'Y':
  372. fSwapRunCD = TRUE;
  373. break;
  374. default:
  375. fprintf( stderr, "IMAGECFG: Invalid switch - /%c\n", c );
  376. fUsage = TRUE;
  377. break;
  378. }
  379. if ( fUsage ) {
  380. showUsage:
  381. fprintf( stderr,
  382. "usage: IMAGECFG [switches] image-names... \n"
  383. " [-?] display this message\n"
  384. " [-a Process Affinity mask value in hex]\n"
  385. " [-b BuildNumber]\n"
  386. " [-c Win32 GetVersionEx Service Pack return value in hex]\n"
  387. " [-d decommit thresholds]\n"
  388. " [-g bitsToClear bitsToSet]\n"
  389. " [-h 1|0 (Enable/Disable Terminal Server Compatible bit)\n"
  390. " [-k StackReserve[.StackCommit]\n"
  391. " [-l enable large (>2GB) addresses\n"
  392. " [-m maximum allocation size]\n"
  393. " [-n bind no longer allowed on this image\n"
  394. " [-o default critical section timeout\n"
  395. " [-p process heap flags]\n"
  396. " [-q only print config info if changed\n"
  397. " [-r run with restricted working set]\n"
  398. " [-s path to symbol files]\n"
  399. " [-t VirtualAlloc threshold]\n"
  400. " [-u Marks image as uniprocessor only]\n"
  401. " [-v MajorVersion.MinorVersion]\n"
  402. " [-w Win32 GetVersion return value in hex]\n"
  403. " [-x Mark image as Net - Run From Swapfile\n"
  404. " [-y Mark image as Removable - Run From Swapfile\n"
  405. );
  406. exit( 1 );
  407. }
  408. } else {
  409. //
  410. // Map and load the current image
  411. //
  412. OptionalHeader32 = NULL;
  413. OptionalHeader64 = NULL;
  414. FileHeader = NULL;
  415. CurrentImageName = p;
  416. if (MapAndLoad( CurrentImageName,
  417. NULL,
  418. &CurrentImage,
  419. FALSE,
  420. TRUE
  421. )
  422. ) {
  423. if (BuildNumber != 0) {
  424. pBuildNumber = (PULONG) GetAddressOfExportedData( &CurrentImage, "NtBuildNumber" );
  425. if (pBuildNumber == NULL) {
  426. fprintf( stderr,
  427. "IMAGECFG: Unable to find exported NtBuildNumber image %s\n",
  428. CurrentImageName
  429. );
  430. }
  431. }
  432. FileHeader = &((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->FileHeader;
  433. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
  434. &OptionalHeader32,
  435. &OptionalHeader64);
  436. //
  437. // make sure the image has correct configuration information,
  438. // and that the LockPrefixTable is set up properly
  439. //
  440. fConfigInfoChanged = FALSE;
  441. fImageHeaderChanged = FALSE;
  442. ZeroMemory(&ConfigInfo, sizeof(ConfigInfo));
  443. fImageHasConfigInfo = GetImageConfigInformation( &CurrentImage, &ConfigInfo );
  444. if (!fQuiet) {
  445. DisplayImageInfo( fImageHasConfigInfo );
  446. }
  447. UnMapAndLoad( &CurrentImage );
  448. OptionalHeader32 = NULL;
  449. OptionalHeader64 = NULL;
  450. FileHeader = NULL;
  451. if (fConfigInfoChanged || fImageHeaderChanged) {
  452. if (!MapAndLoad( CurrentImageName,
  453. NULL,
  454. &CurrentImage,
  455. FALSE,
  456. FALSE
  457. )
  458. ) {
  459. if (!CurrentImage.fDOSImage) {
  460. fprintf( stderr, "IMAGECFG: unable to map and load %s\n", CurrentImageName );
  461. } else {
  462. fprintf( stderr,
  463. "IMAGECFG: unable to modify DOS or Windows image file - %s\n",
  464. CurrentImageName
  465. );
  466. }
  467. } else {
  468. FileHeader = &((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->FileHeader;
  469. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
  470. &OptionalHeader32,
  471. &OptionalHeader64);
  472. if (GlobalFlagsClear) {
  473. ConfigInfo.GlobalFlagsClear = GlobalFlagsClear;
  474. }
  475. if (GlobalFlagsSet) {
  476. ConfigInfo.GlobalFlagsSet = GlobalFlagsSet;
  477. }
  478. if (CriticalSectionDefaultTimeout) {
  479. ConfigInfo.CriticalSectionDefaultTimeout = CriticalSectionDefaultTimeout;
  480. }
  481. if (ProcessHeapFlags) {
  482. ConfigInfo.ProcessHeapFlags = ProcessHeapFlags;
  483. }
  484. if (DeCommitFreeBlockThreshold) {
  485. ConfigInfo.DeCommitFreeBlockThreshold = DeCommitFreeBlockThreshold;
  486. }
  487. if (DeCommitTotalFreeThreshold) {
  488. ConfigInfo.DeCommitTotalFreeThreshold = DeCommitTotalFreeThreshold;
  489. }
  490. if (MaximumAllocationSize) {
  491. ConfigInfo.MaximumAllocationSize = MaximumAllocationSize;
  492. }
  493. if (VirtualMemoryThreshold) {
  494. ConfigInfo.VirtualMemoryThreshold = VirtualMemoryThreshold;
  495. }
  496. if (ImageProcessAffinityMask) {
  497. ConfigInfo.ProcessAffinityMask = ImageProcessAffinityMask;
  498. }
  499. if (fEnableLargeAddresses) {
  500. FileHeader->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
  501. }
  502. if (fNoBind) {
  503. OPTIONALHEADER_SET_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_NO_BIND);
  504. }
  505. if (fEnableTerminalServerAware) {
  506. OPTIONALHEADER_SET_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
  507. }
  508. if (fDisableTerminalServerAware) {
  509. OPTIONALHEADER_CLEAR_FLAG(DllCharacteristics,IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE);
  510. }
  511. if (fSwapRunNet) {
  512. FileHeader->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
  513. }
  514. if (fSwapRunCD) {
  515. FileHeader->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
  516. }
  517. if (fUniprocessorOnly) {
  518. FileHeader->Characteristics |= IMAGE_FILE_UP_SYSTEM_ONLY;
  519. }
  520. if (fRestrictedWorkingSet) {
  521. FileHeader->Characteristics |= IMAGE_FILE_AGGRESIVE_WS_TRIM;
  522. }
  523. if (MajorSubsystemVersion != 0) {
  524. OPTIONALHEADER_ASSIGN(MajorSubsystemVersion, (USHORT)MajorSubsystemVersion);
  525. OPTIONALHEADER_ASSIGN(MinorSubsystemVersion, (USHORT)MinorSubsystemVersion);
  526. }
  527. if (Win32VersionValue != 0) {
  528. OPTIONALHEADER_ASSIGN(Win32VersionValue, Win32VersionValue);
  529. }
  530. if (Win32CSDVerValue != 0) {
  531. ConfigInfo.CSDVersion = (USHORT)Win32CSDVerValue;
  532. }
  533. if (SizeOfStackReserve) {
  534. OPTIONALHEADER_ASSIGN(SizeOfStackReserve, SizeOfStackReserve);
  535. }
  536. if (SizeOfStackCommit) {
  537. OPTIONALHEADER_ASSIGN(SizeOfStackCommit, SizeOfStackCommit);
  538. }
  539. if (BuildNumber != 0) {
  540. pBuildNumber = (PULONG) GetAddressOfExportedData( &CurrentImage, "NtBuildNumber" );
  541. if (pBuildNumber == NULL) {
  542. fprintf( stderr,
  543. "IMAGECFG: Unable to find exported NtBuildNumber image %s\n",
  544. CurrentImageName
  545. );
  546. } else {
  547. if (BuildNumber & 0xFFFF0000) {
  548. *pBuildNumber = BuildNumber;
  549. } else {
  550. *(PUSHORT)pBuildNumber = (USHORT)BuildNumber;
  551. }
  552. }
  553. }
  554. if (fConfigInfoChanged) {
  555. if (SetImageConfigInformation( &CurrentImage, &ConfigInfo )) {
  556. if (!fQuiet) {
  557. printf( "%s updated with the following configuration information:\n", CurrentImageName );
  558. DisplayImageInfo( fImageHasConfigInfo );
  559. }
  560. } else {
  561. fprintf( stderr, "IMAGECFG: Unable to update configuration information in image.\n" );
  562. }
  563. }
  564. //
  565. // recompute the checksum.
  566. //
  567. OldChecksum = OPTIONALHEADER(CheckSum);
  568. OPTIONALHEADER_LV(CheckSum) = 0;
  569. CheckSumMappedFile(
  570. (PVOID)CurrentImage.MappedAddress,
  571. CurrentImage.SizeOfImage,
  572. &HeaderSum,
  573. &OPTIONALHEADER_LV(CheckSum)
  574. );
  575. // And update the .dbg file (if requested)
  576. if (SymbolPath &&
  577. FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
  578. if (UpdateDebugInfoFileEx( CurrentImageName,
  579. SymbolPath,
  580. DebugFilePath,
  581. (PIMAGE_NT_HEADERS32)CurrentImage.FileHeader,
  582. OldChecksum
  583. )
  584. ) {
  585. if (GetLastError() == ERROR_INVALID_DATA) {
  586. printf( "Warning: Old checksum did not match for %s\n", DebugFilePath);
  587. }
  588. printf( "Updated symbols for %s\n", DebugFilePath );
  589. } else {
  590. printf( "Unable to update symbols: %s\n", DebugFilePath );
  591. }
  592. }
  593. GetSystemTime( &SystemTime );
  594. if (SystemTimeToFileTime( &SystemTime, &LastWriteTime )) {
  595. SetFileTime( CurrentImage.hFile, NULL, NULL, &LastWriteTime );
  596. }
  597. UnMapAndLoad( &CurrentImage );
  598. }
  599. }
  600. } else
  601. if (!CurrentImage.fDOSImage) {
  602. fprintf( stderr, "IMAGECFG: unable to map and load %s GetLastError= %d\n", CurrentImageName, GetLastError() );
  603. } else {
  604. fprintf( stderr,
  605. "IMAGECFG: unable to modify DOS or Windows image file - %s\n",
  606. CurrentImageName
  607. );
  608. }
  609. }
  610. }
  611. exit( 1 );
  612. return 1;
  613. }
  614. __inline PVOID
  615. GetVaForRva(
  616. PLOADED_IMAGE Image,
  617. ULONG Rva
  618. )
  619. {
  620. PVOID Va;
  621. Va = ImageRvaToVa( Image->FileHeader,
  622. Image->MappedAddress,
  623. Rva,
  624. &Image->LastRvaSection
  625. );
  626. return Va;
  627. }
  628. PVOID
  629. GetAddressOfExportedData(
  630. PLOADED_IMAGE Dll,
  631. LPSTR ExportedName
  632. )
  633. {
  634. PIMAGE_EXPORT_DIRECTORY Exports;
  635. ULONG ExportSize;
  636. USHORT HintIndex;
  637. USHORT OrdinalNumber;
  638. PULONG NameTableBase;
  639. PUSHORT NameOrdinalTableBase;
  640. PULONG FunctionTableBase;
  641. LPSTR NameTableName;
  642. Exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData( (PVOID)Dll->MappedAddress,
  643. FALSE,
  644. IMAGE_DIRECTORY_ENTRY_EXPORT,
  645. &ExportSize
  646. );
  647. if (Exports) {
  648. NameTableBase = (PULONG)GetVaForRva( Dll, Exports->AddressOfNames );
  649. NameOrdinalTableBase = (PUSHORT)GetVaForRva( Dll, Exports->AddressOfNameOrdinals );
  650. FunctionTableBase = (PULONG)GetVaForRva( Dll, Exports->AddressOfFunctions );
  651. if (NameTableBase != NULL &&
  652. NameOrdinalTableBase != NULL &&
  653. FunctionTableBase != NULL
  654. ) {
  655. for (HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++) {
  656. NameTableName = (LPSTR)GetVaForRva( Dll, NameTableBase[ HintIndex ] );
  657. if (NameTableName) {
  658. if (!strcmp( ExportedName, NameTableName )) {
  659. OrdinalNumber = NameOrdinalTableBase[ HintIndex ];
  660. return FunctionTableBase[ OrdinalNumber ] + Dll->MappedAddress;
  661. }
  662. }
  663. }
  664. }
  665. }
  666. return NULL;
  667. }
  668. VOID
  669. DisplayImageInfo(
  670. BOOL HasConfigInfo
  671. )
  672. {
  673. printf( "%s contains the following configuration information:\n", CurrentImageName );
  674. // if (HasConfigInfo) {
  675. if (ConfigInfo.GlobalFlagsClear != 0) {
  676. printf( " NtGlobalFlags to clear: %08x\n",
  677. ConfigInfo.GlobalFlagsClear
  678. );
  679. DisplayGlobalFlags( " ", ConfigInfo.GlobalFlagsClear, FALSE );
  680. }
  681. if (GlobalFlagsClear && ConfigInfo.GlobalFlagsClear != GlobalFlagsClear) {
  682. fConfigInfoChanged = TRUE;
  683. }
  684. if (ConfigInfo.GlobalFlagsSet != 0) {
  685. printf( " NtGlobalFlags to set: %08x\n",
  686. ConfigInfo.GlobalFlagsSet
  687. );
  688. DisplayGlobalFlags( " ", ConfigInfo.GlobalFlagsSet, TRUE );
  689. }
  690. if (GlobalFlagsSet && ConfigInfo.GlobalFlagsSet != GlobalFlagsSet) {
  691. fConfigInfoChanged = TRUE;
  692. }
  693. if (ConfigInfo.CriticalSectionDefaultTimeout != 0) {
  694. printf( " Default Critical Section Timeout: %u milliseconds\n",
  695. ConfigInfo.CriticalSectionDefaultTimeout
  696. );
  697. }
  698. if (CriticalSectionDefaultTimeout &&
  699. ConfigInfo.CriticalSectionDefaultTimeout != CriticalSectionDefaultTimeout
  700. ) {
  701. fConfigInfoChanged = TRUE;
  702. }
  703. if (ConfigInfo.ProcessHeapFlags != 0) {
  704. printf( " Process Heap Flags: %08x\n",
  705. ConfigInfo.ProcessHeapFlags
  706. );
  707. }
  708. if (ProcessHeapFlags && ConfigInfo.ProcessHeapFlags != ProcessHeapFlags) {
  709. fConfigInfoChanged = TRUE;
  710. }
  711. if (ConfigInfo.DeCommitFreeBlockThreshold != 0) {
  712. printf( " Process Heap DeCommit Free Block threshold: %08x\n",
  713. ConfigInfo.DeCommitFreeBlockThreshold
  714. );
  715. }
  716. if (DeCommitFreeBlockThreshold &&
  717. ConfigInfo.DeCommitFreeBlockThreshold != DeCommitFreeBlockThreshold
  718. ) {
  719. fConfigInfoChanged = TRUE;
  720. }
  721. if (ConfigInfo.DeCommitTotalFreeThreshold != 0) {
  722. printf( " Process Heap DeCommit Total Free threshold: %08x\n",
  723. ConfigInfo.DeCommitTotalFreeThreshold
  724. );
  725. }
  726. if (DeCommitTotalFreeThreshold &&
  727. ConfigInfo.DeCommitTotalFreeThreshold != DeCommitTotalFreeThreshold
  728. ) {
  729. fConfigInfoChanged = TRUE;
  730. }
  731. if (ConfigInfo.MaximumAllocationSize != 0) {
  732. printf( " Process Heap Maximum Allocation Size: %08x\n",
  733. ConfigInfo.MaximumAllocationSize
  734. );
  735. }
  736. if (MaximumAllocationSize && ConfigInfo.MaximumAllocationSize != MaximumAllocationSize) {
  737. fConfigInfoChanged = TRUE;
  738. }
  739. if (ConfigInfo.VirtualMemoryThreshold != 0) {
  740. printf( " Process Heap VirtualAlloc Threshold: %08x\n",
  741. ConfigInfo.VirtualMemoryThreshold
  742. );
  743. }
  744. if (VirtualMemoryThreshold &&
  745. ConfigInfo.VirtualMemoryThreshold != VirtualMemoryThreshold
  746. ) {
  747. fConfigInfoChanged = TRUE;
  748. }
  749. if (ConfigInfo.ProcessAffinityMask != 0) {
  750. printf( " Process Affinity Mask: %08x\n",
  751. ConfigInfo.ProcessAffinityMask
  752. );
  753. }
  754. if (ImageProcessAffinityMask &&
  755. ConfigInfo.ProcessAffinityMask != ImageProcessAffinityMask
  756. ) {
  757. fConfigInfoChanged = TRUE;
  758. }
  759. // } else {
  760. // memset( &ConfigInfo, 0, sizeof( ConfigInfo ) );
  761. // }
  762. printf( " Subsystem Version of %u.%u\n",
  763. OPTIONALHEADER(MajorSubsystemVersion),
  764. OPTIONALHEADER(MinorSubsystemVersion)
  765. );
  766. if (MajorSubsystemVersion != 0) {
  767. if (OPTIONALHEADER(MajorSubsystemVersion) != (USHORT)MajorSubsystemVersion ||
  768. OPTIONALHEADER(MinorSubsystemVersion) != (USHORT)MinorSubsystemVersion
  769. ) {
  770. fImageHeaderChanged = TRUE;
  771. }
  772. }
  773. if (pBuildNumber != NULL) {
  774. printf( " Build Number of %08x\n", *pBuildNumber );
  775. if (BuildNumber != 0) {
  776. if (BuildNumber & 0xFFFF0000) {
  777. if (*pBuildNumber != BuildNumber) {
  778. fImageHeaderChanged = TRUE;
  779. }
  780. } else {
  781. if (*(PUSHORT)pBuildNumber != (USHORT)BuildNumber) {
  782. fImageHeaderChanged = TRUE;
  783. }
  784. }
  785. }
  786. }
  787. if (OPTIONALHEADER(Win32VersionValue) != 0) {
  788. printf( " Win32 GetVersion return value: %08x\n",
  789. OPTIONALHEADER(Win32VersionValue)
  790. );
  791. }
  792. if (Win32VersionValue != 0 &&
  793. OPTIONALHEADER(Win32VersionValue) != Win32VersionValue
  794. ) {
  795. fImageHeaderChanged = TRUE;
  796. }
  797. if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) {
  798. printf( " Image can handle large (>2GB) addresses\n" );
  799. }
  800. if (OPTIONALHEADER(DllCharacteristics) & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE) {
  801. printf( " Image is Terminal Server aware\n" );
  802. }
  803. if (fEnableLargeAddresses &&
  804. !(FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
  805. ) {
  806. fImageHeaderChanged = TRUE;
  807. printf( " Image is Large Address aware\n" );
  808. }
  809. if (fNoBind) {
  810. fImageHeaderChanged = TRUE;
  811. printf( " Image will no longer support binding\n" );
  812. }
  813. if (fEnableTerminalServerAware || fDisableTerminalServerAware) {
  814. printf( " Image %s Terminal Server Aware\n", fEnableTerminalServerAware ? "is" : "is not");
  815. fImageHeaderChanged = TRUE;
  816. }
  817. if (FileHeader->Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP) {
  818. printf( " Image will run from swapfile if located on net\n" );
  819. }
  820. if (fSwapRunNet &&
  821. !(FileHeader->Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP)
  822. ) {
  823. fImageHeaderChanged = TRUE;
  824. }
  825. if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) {
  826. printf( " Image will run from swapfile if located on removable media\n" );
  827. }
  828. if (fSwapRunCD &&
  829. !(FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
  830. ) {
  831. fImageHeaderChanged = TRUE;
  832. }
  833. if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) {
  834. printf( " Image can only run in uni-processor mode on multi-processor systems\n" );
  835. }
  836. if (fUniprocessorOnly &&
  837. !(FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
  838. ) {
  839. fImageHeaderChanged = TRUE;
  840. }
  841. if (FileHeader->Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM) {
  842. printf( " Image working set trimmed aggressively on small memory systems\n" );
  843. }
  844. if (fRestrictedWorkingSet &&
  845. !(FileHeader->Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM)
  846. ) {
  847. fImageHeaderChanged = TRUE;
  848. }
  849. if (OPTIONALHEADER(SizeOfStackReserve)) {
  850. printf( " Stack Reserve Size: 0x%x\n", OPTIONALHEADER(SizeOfStackReserve) );
  851. }
  852. if (SizeOfStackReserve &&
  853. OPTIONALHEADER(SizeOfStackReserve) != SizeOfStackReserve
  854. ) {
  855. fImageHeaderChanged = TRUE;
  856. }
  857. if (OPTIONALHEADER(SizeOfStackCommit)) {
  858. printf( " Stack Commit Size: 0x%x\n", OPTIONALHEADER(SizeOfStackCommit) );
  859. }
  860. if (SizeOfStackCommit &&
  861. OPTIONALHEADER(SizeOfStackCommit) != SizeOfStackCommit
  862. ) {
  863. fImageHeaderChanged = TRUE;
  864. }
  865. return;
  866. }