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.

1456 lines
51 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. bindi.c
  5. Abstract:
  6. Implementation for the BindImage API
  7. Author:
  8. Revision History:
  9. --*/
  10. #include <private.h>
  11. typedef struct _BOUND_FORWARDER_REFS {
  12. struct _BOUND_FORWARDER_REFS *Next;
  13. ULONG TimeDateStamp;
  14. LPSTR ModuleName;
  15. } BOUND_FORWARDER_REFS, *PBOUND_FORWARDER_REFS;
  16. typedef struct _IMPORT_DESCRIPTOR {
  17. struct _IMPORT_DESCRIPTOR *Next;
  18. LPSTR ModuleName;
  19. ULONG TimeDateStamp;
  20. USHORT NumberOfModuleForwarderRefs;
  21. PBOUND_FORWARDER_REFS Forwarders;
  22. } IMPORT_DESCRIPTOR, *PIMPORT_DESCRIPTOR;
  23. typedef struct _BINDP_PARAMETERS {
  24. DWORD Flags;
  25. BOOLEAN fNoUpdate;
  26. BOOLEAN fNewImports;
  27. LPSTR ImageName;
  28. LPSTR DllPath;
  29. LPSTR SymbolPath;
  30. PIMAGEHLP_STATUS_ROUTINE StatusRoutine;
  31. } BINDP_PARAMETERS, *PBINDP_PARAMETERS;
  32. BOOL
  33. BindpLookupThunk(
  34. PBINDP_PARAMETERS Parms,
  35. PIMAGE_THUNK_DATA ThunkName,
  36. PLOADED_IMAGE Image,
  37. PIMAGE_THUNK_DATA SnappedThunks,
  38. PIMAGE_THUNK_DATA FunctionAddress,
  39. PLOADED_IMAGE Dll,
  40. PIMAGE_EXPORT_DIRECTORY Exports,
  41. PIMPORT_DESCRIPTOR NewImport,
  42. LPSTR DllPath,
  43. PULONG *ForwarderChain
  44. );
  45. PVOID
  46. BindpRvaToVa(
  47. PBINDP_PARAMETERS Parms,
  48. ULONG Rva,
  49. PLOADED_IMAGE Image
  50. );
  51. VOID
  52. BindpWalkAndProcessImports(
  53. PBINDP_PARAMETERS Parms,
  54. PLOADED_IMAGE Image,
  55. LPSTR DllPath,
  56. PBOOL ImageModified
  57. );
  58. BOOL
  59. BindImage(
  60. IN LPSTR ImageName,
  61. IN LPSTR DllPath,
  62. IN LPSTR SymbolPath
  63. )
  64. {
  65. return BindImageEx( 0,
  66. ImageName,
  67. DllPath,
  68. SymbolPath,
  69. NULL
  70. );
  71. }
  72. UCHAR BindpCapturedModuleNames[4096];
  73. LPSTR BindpEndCapturedModuleNames;
  74. LPSTR
  75. BindpCaptureImportModuleName(
  76. LPSTR DllName
  77. )
  78. {
  79. LPSTR s;
  80. s = (LPSTR) BindpCapturedModuleNames;
  81. if (BindpEndCapturedModuleNames == NULL) {
  82. *s = '\0';
  83. BindpEndCapturedModuleNames = s;
  84. }
  85. while (*s) {
  86. if (!_stricmp(s, DllName)) {
  87. return s;
  88. }
  89. s += strlen(s)+1;
  90. }
  91. strcpy(s, DllName);
  92. BindpEndCapturedModuleNames = s + strlen(s) + 1;
  93. *BindpEndCapturedModuleNames = '\0';
  94. return s;
  95. }
  96. PIMPORT_DESCRIPTOR
  97. BindpAddImportDescriptor(
  98. PBINDP_PARAMETERS Parms,
  99. PIMPORT_DESCRIPTOR *NewImportDescriptor,
  100. PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor,
  101. LPSTR ModuleName,
  102. PLOADED_IMAGE Dll
  103. )
  104. {
  105. PIMPORT_DESCRIPTOR p, *pp;
  106. if (!Parms->fNewImports) {
  107. return NULL;
  108. }
  109. pp = NewImportDescriptor;
  110. while (p = *pp) {
  111. if (!_stricmp( p->ModuleName, ModuleName )) {
  112. return p;
  113. }
  114. pp = &p->Next;
  115. }
  116. p = (PIMPORT_DESCRIPTOR) MemAlloc( sizeof( *p ) );
  117. if (p != NULL) {
  118. if (Dll != NULL) {
  119. p->TimeDateStamp = ((PIMAGE_NT_HEADERS32)Dll->FileHeader)->FileHeader.TimeDateStamp;
  120. }
  121. p->ModuleName = BindpCaptureImportModuleName( ModuleName );
  122. *pp = p;
  123. }
  124. else
  125. if (Parms->StatusRoutine != NULL) {
  126. (Parms->StatusRoutine)( BindOutOfMemory, NULL, NULL, 0, sizeof( *p ) );
  127. }
  128. return p;
  129. }
  130. PUCHAR
  131. BindpAddForwarderReference(
  132. PBINDP_PARAMETERS Parms,
  133. LPSTR ImageName,
  134. LPSTR ImportName,
  135. PIMPORT_DESCRIPTOR NewImportDescriptor,
  136. LPSTR DllPath,
  137. PUCHAR ForwarderString,
  138. PBOOL BoundForwarder
  139. )
  140. {
  141. CHAR DllName[ MAX_PATH ];
  142. PUCHAR s;
  143. PLOADED_IMAGE Dll;
  144. ULONG cb;
  145. USHORT OrdinalNumber;
  146. USHORT HintIndex;
  147. ULONG ExportSize;
  148. PIMAGE_EXPORT_DIRECTORY Exports;
  149. PULONG NameTableBase;
  150. PUSHORT NameOrdinalTableBase;
  151. PULONG FunctionTableBase;
  152. LPSTR NameTableName;
  153. ULONG64 ForwardedAddress;
  154. PBOUND_FORWARDER_REFS p, *pp;
  155. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  156. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  157. PIMAGE_FILE_HEADER FileHeader;
  158. *BoundForwarder = FALSE;
  159. BindAnotherForwarder:
  160. s = ForwarderString;
  161. while (*s && *s != '.') {
  162. s++;
  163. }
  164. if (*s != '.') {
  165. return ForwarderString;
  166. }
  167. cb = (ULONG) (s - ForwarderString);
  168. if (cb >= MAX_PATH) {
  169. return ForwarderString;
  170. }
  171. strncpy( DllName, (LPSTR) ForwarderString, cb );
  172. DllName[ cb ] = '\0';
  173. strcat( DllName, ".DLL" );
  174. Dll = ImageLoad( DllName, DllPath );
  175. if (!Dll) {
  176. return ForwarderString;
  177. }
  178. s += 1;
  179. Exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
  180. (PVOID)Dll->MappedAddress,
  181. FALSE,
  182. IMAGE_DIRECTORY_ENTRY_EXPORT,
  183. &ExportSize
  184. );
  185. if (!Exports) {
  186. return ForwarderString;
  187. }
  188. FileHeader = &((PIMAGE_NT_HEADERS32)Dll->FileHeader)->FileHeader;
  189. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Dll->FileHeader,
  190. &OptionalHeader32,
  191. &OptionalHeader64);
  192. if ( *s == '#' ) {
  193. // Binding for ordinal forwarders
  194. OrdinalNumber = (atoi((PCHAR)s + 1)) - (USHORT)Exports->Base;
  195. if (OrdinalNumber >= Exports->NumberOfFunctions) {
  196. return ForwarderString;
  197. }
  198. } else {
  199. // Regular binding for named forwarders
  200. OrdinalNumber = 0xFFFF;
  201. }
  202. NameTableBase = (PULONG) BindpRvaToVa( Parms, Exports->AddressOfNames, Dll );
  203. NameOrdinalTableBase = (PUSHORT) BindpRvaToVa( Parms, Exports->AddressOfNameOrdinals, Dll );
  204. FunctionTableBase = (PULONG) BindpRvaToVa( Parms, Exports->AddressOfFunctions, Dll );
  205. if (OrdinalNumber == 0xFFFF) {
  206. for ( HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++){
  207. NameTableName = (LPSTR) BindpRvaToVa( Parms, NameTableBase[HintIndex], Dll );
  208. if ( NameTableName ) {
  209. OrdinalNumber = NameOrdinalTableBase[HintIndex];
  210. if (!strcmp((PCHAR)s, NameTableName)) {
  211. break;
  212. }
  213. }
  214. }
  215. if (HintIndex >= Exports->NumberOfNames) {
  216. return ForwarderString;
  217. }
  218. }
  219. do {
  220. ForwardedAddress = FunctionTableBase[OrdinalNumber] +
  221. OPTIONALHEADER(ImageBase);
  222. pp = &NewImportDescriptor->Forwarders;
  223. while (p = *pp) {
  224. if (!_stricmp(DllName, p->ModuleName)) {
  225. break;
  226. }
  227. pp = &p->Next;
  228. }
  229. if (p == NULL) {
  230. p = (PBOUND_FORWARDER_REFS) MemAlloc( sizeof( *p ) );
  231. if (p == NULL) {
  232. if (Parms->StatusRoutine != NULL) {
  233. (Parms->StatusRoutine)( BindOutOfMemory, NULL, NULL, 0, sizeof( *p ) );
  234. }
  235. break;
  236. }
  237. p->ModuleName = BindpCaptureImportModuleName( DllName );
  238. *pp = p;
  239. NewImportDescriptor->NumberOfModuleForwarderRefs += 1;
  240. }
  241. p->TimeDateStamp = FileHeader->TimeDateStamp;
  242. if (Parms->StatusRoutine != NULL)
  243. {
  244. (Parms->StatusRoutine)( BindForwarder,
  245. ImageName,
  246. ImportName,
  247. (ULONG_PTR)ForwardedAddress,
  248. (ULONG_PTR)ForwarderString
  249. );
  250. }
  251. Exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
  252. (PVOID)Dll->MappedAddress,
  253. TRUE,
  254. IMAGE_DIRECTORY_ENTRY_EXPORT,
  255. &ExportSize
  256. );
  257. Exports = (PIMAGE_EXPORT_DIRECTORY) ((ULONG_PTR)Exports -
  258. (ULONG_PTR) Dll->MappedAddress +
  259. OPTIONALHEADER(ImageBase));
  260. if ((ForwardedAddress >= (ULONG_PTR)Exports) &&
  261. (ForwardedAddress < ((ULONG_PTR)Exports + ExportSize)))
  262. {
  263. ForwarderString = (PUCHAR)BindpRvaToVa(Parms,
  264. FunctionTableBase[OrdinalNumber],
  265. Dll);
  266. goto BindAnotherForwarder;
  267. } else {
  268. ForwarderString = (PUCHAR)ForwardedAddress;
  269. *BoundForwarder = TRUE;
  270. break;
  271. }
  272. }
  273. while (0);
  274. return ForwarderString;
  275. }
  276. PIMAGE_BOUND_IMPORT_DESCRIPTOR
  277. BindpCreateNewImportSection(
  278. PBINDP_PARAMETERS Parms,
  279. PIMPORT_DESCRIPTOR *NewImportDescriptor,
  280. PULONG NewImportsSize
  281. )
  282. {
  283. ULONG cbString, cbStruct;
  284. PIMPORT_DESCRIPTOR p, *pp;
  285. PBOUND_FORWARDER_REFS p1, *pp1;
  286. LPSTR CapturedStrings;
  287. PIMAGE_BOUND_IMPORT_DESCRIPTOR NewImports, NewImport;
  288. PIMAGE_BOUND_FORWARDER_REF NewForwarder;
  289. *NewImportsSize = 0;
  290. cbString = 0;
  291. cbStruct = 0;
  292. pp = NewImportDescriptor;
  293. while (p = *pp) {
  294. cbStruct += sizeof( IMAGE_BOUND_IMPORT_DESCRIPTOR );
  295. pp1 = &p->Forwarders;
  296. while (p1 = *pp1) {
  297. cbStruct += sizeof( IMAGE_BOUND_FORWARDER_REF );
  298. pp1 = &p1->Next;
  299. }
  300. pp = &p->Next;
  301. }
  302. if (cbStruct == 0) {
  303. BindpEndCapturedModuleNames = NULL;
  304. return NULL;
  305. }
  306. cbStruct += sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR); // Room for terminating zero entry
  307. cbString = (ULONG) (BindpEndCapturedModuleNames - (LPSTR) BindpCapturedModuleNames);
  308. BindpEndCapturedModuleNames = NULL;
  309. *NewImportsSize = cbStruct+((cbString + sizeof(ULONG) - 1) & ~(sizeof(ULONG)-1));
  310. NewImports = (PIMAGE_BOUND_IMPORT_DESCRIPTOR) MemAlloc( *NewImportsSize );
  311. if (NewImports != NULL) {
  312. CapturedStrings = (LPSTR)NewImports + cbStruct;
  313. memcpy(CapturedStrings, BindpCapturedModuleNames, cbString);
  314. NewImport = NewImports;
  315. pp = NewImportDescriptor;
  316. while (p = *pp) {
  317. NewImport->TimeDateStamp = p->TimeDateStamp;
  318. NewImport->OffsetModuleName = (USHORT)(cbStruct + (p->ModuleName - (LPSTR) BindpCapturedModuleNames));
  319. NewImport->NumberOfModuleForwarderRefs = p->NumberOfModuleForwarderRefs;
  320. NewForwarder = (PIMAGE_BOUND_FORWARDER_REF)(NewImport+1);
  321. pp1 = &p->Forwarders;
  322. while (p1 = *pp1) {
  323. NewForwarder->TimeDateStamp = p1->TimeDateStamp;
  324. NewForwarder->OffsetModuleName = (USHORT)(cbStruct + (p1->ModuleName - (LPSTR) BindpCapturedModuleNames));
  325. NewForwarder += 1;
  326. pp1 = &p1->Next;
  327. }
  328. NewImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewForwarder;
  329. pp = &p->Next;
  330. }
  331. }
  332. else
  333. if (Parms->StatusRoutine != NULL) {
  334. (Parms->StatusRoutine)( BindOutOfMemory, NULL, NULL, 0, *NewImportsSize );
  335. }
  336. pp = NewImportDescriptor;
  337. while ((p = *pp) != NULL) {
  338. *pp = p->Next;
  339. pp1 = &p->Forwarders;
  340. while ((p1 = *pp1) != NULL) {
  341. *pp1 = p1->Next;
  342. MemFree(p1);
  343. }
  344. MemFree(p);
  345. }
  346. return NewImports;
  347. }
  348. BOOL
  349. BindpExpandImageFileHeaders(
  350. PBINDP_PARAMETERS Parms,
  351. PLOADED_IMAGE Dll,
  352. ULONG NewSizeOfHeaders
  353. )
  354. {
  355. HANDLE hMappedFile;
  356. LPVOID lpMappedAddress;
  357. DWORD dwFileSizeLow, dwOldFileSize;
  358. DWORD dwFileSizeHigh;
  359. DWORD dwSizeDelta;
  360. PIMAGE_SECTION_HEADER Section;
  361. ULONG SectionNumber;
  362. PIMAGE_DEBUG_DIRECTORY DebugDirectories;
  363. ULONG DebugDirectoriesSize;
  364. ULONG OldSizeOfHeaders;
  365. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  366. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  367. PIMAGE_FILE_HEADER FileHeader;
  368. dwFileSizeLow = GetFileSize( Dll->hFile, &dwFileSizeHigh );
  369. if (dwFileSizeLow == 0xFFFFFFFF || dwFileSizeHigh != 0) {
  370. return FALSE;
  371. }
  372. FileHeader = &((PIMAGE_NT_HEADERS32)Dll->FileHeader)->FileHeader;
  373. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Dll->FileHeader,
  374. &OptionalHeader32,
  375. &OptionalHeader64);
  376. if (!OptionalHeader32 && !OptionalHeader64) {
  377. return FALSE;
  378. }
  379. OldSizeOfHeaders = OPTIONALHEADER(SizeOfHeaders);
  380. dwOldFileSize = dwFileSizeLow;
  381. dwSizeDelta = NewSizeOfHeaders - OldSizeOfHeaders;
  382. dwFileSizeLow += dwSizeDelta;
  383. hMappedFile = CreateFileMapping(Dll->hFile,
  384. NULL,
  385. PAGE_READWRITE,
  386. dwFileSizeHigh,
  387. dwFileSizeLow,
  388. NULL
  389. );
  390. if (!hMappedFile) {
  391. return FALSE;
  392. }
  393. FlushViewOfFile(Dll->MappedAddress, Dll->SizeOfImage);
  394. UnmapViewOfFile(Dll->MappedAddress);
  395. lpMappedAddress = MapViewOfFileEx(hMappedFile,
  396. FILE_MAP_WRITE,
  397. 0,
  398. 0,
  399. 0,
  400. Dll->MappedAddress
  401. );
  402. if (!lpMappedAddress) {
  403. lpMappedAddress = MapViewOfFileEx(hMappedFile,
  404. FILE_MAP_WRITE,
  405. 0,
  406. 0,
  407. 0,
  408. 0
  409. );
  410. }
  411. CloseHandle(hMappedFile);
  412. if (lpMappedAddress != Dll->MappedAddress) {
  413. Dll->MappedAddress = (PUCHAR) lpMappedAddress;
  414. CalculateImagePtrs(Dll);
  415. FileHeader = &((PIMAGE_NT_HEADERS32)Dll->FileHeader)->FileHeader;
  416. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Dll->FileHeader,
  417. &OptionalHeader32,
  418. &OptionalHeader64);
  419. }
  420. if (Dll->SizeOfImage != dwFileSizeLow) {
  421. Dll->SizeOfImage = dwFileSizeLow;
  422. }
  423. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryEntryToData(
  424. (PVOID)Dll->MappedAddress,
  425. FALSE,
  426. IMAGE_DIRECTORY_ENTRY_DEBUG,
  427. &DebugDirectoriesSize
  428. );
  429. if (DebugDirectoryIsUseful(DebugDirectories, DebugDirectoriesSize)) {
  430. while (DebugDirectoriesSize != 0) {
  431. DebugDirectories->PointerToRawData += dwSizeDelta;
  432. DebugDirectories += 1;
  433. DebugDirectoriesSize -= sizeof( *DebugDirectories );
  434. }
  435. }
  436. OPTIONALHEADER_LV(SizeOfHeaders) = NewSizeOfHeaders;
  437. if (FileHeader->PointerToSymbolTable != 0) {
  438. // Only adjust if it's already set
  439. FileHeader->PointerToSymbolTable += dwSizeDelta;
  440. }
  441. Section = Dll->Sections;
  442. for (SectionNumber=0; SectionNumber<FileHeader->NumberOfSections; SectionNumber++) {
  443. if (Section->PointerToRawData != 0) {
  444. Section->PointerToRawData += dwSizeDelta;
  445. }
  446. if (Section->PointerToRelocations != 0) {
  447. Section->PointerToRelocations += dwSizeDelta;
  448. }
  449. if (Section->PointerToLinenumbers != 0) {
  450. Section->PointerToLinenumbers += dwSizeDelta;
  451. }
  452. Section += 1;
  453. }
  454. memmove((LPSTR)lpMappedAddress + NewSizeOfHeaders,
  455. (LPSTR)lpMappedAddress + OldSizeOfHeaders,
  456. dwOldFileSize - OldSizeOfHeaders
  457. );
  458. if (Parms->StatusRoutine != NULL) {
  459. (Parms->StatusRoutine)( BindExpandFileHeaders, Dll->ModuleName, NULL, 0, NewSizeOfHeaders );
  460. }
  461. return TRUE;
  462. }
  463. BOOL
  464. BindImageEx(
  465. IN DWORD Flags,
  466. IN LPSTR ImageName,
  467. IN LPSTR DllPath,
  468. IN LPSTR SymbolPath,
  469. IN PIMAGEHLP_STATUS_ROUTINE StatusRoutine
  470. )
  471. {
  472. BINDP_PARAMETERS Parms;
  473. LOADED_IMAGE LoadedImageBuffer;
  474. PLOADED_IMAGE LoadedImage;
  475. ULONG CheckSum;
  476. ULONG HeaderSum;
  477. BOOL fSymbolsAlreadySplit, fRC;
  478. SYSTEMTIME SystemTime;
  479. FILETIME LastWriteTime;
  480. BOOL ImageModified;
  481. DWORD OldChecksum;
  482. CHAR DebugFileName[ MAX_PATH ];
  483. CHAR DebugFilePath[ MAX_PATH ];
  484. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  485. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  486. PIMAGE_FILE_HEADER FileHeader;
  487. Parms.Flags = Flags;
  488. if (Flags & BIND_NO_BOUND_IMPORTS) {
  489. Parms.fNewImports = FALSE;
  490. } else {
  491. Parms.fNewImports = TRUE;
  492. }
  493. if (Flags & BIND_NO_UPDATE) {
  494. Parms.fNoUpdate = TRUE;
  495. } else {
  496. Parms.fNoUpdate = FALSE;
  497. }
  498. Parms.ImageName = ImageName;
  499. Parms.DllPath = DllPath;
  500. Parms.SymbolPath = SymbolPath;
  501. Parms.StatusRoutine = StatusRoutine;
  502. fRC = FALSE; // Assume we'll fail to bind
  503. __try {
  504. // Map and load the image
  505. LoadedImage = &LoadedImageBuffer;
  506. memset( LoadedImage, 0, sizeof( *LoadedImage ) );
  507. if (MapAndLoad( ImageName, DllPath, LoadedImage, TRUE, Parms.fNoUpdate )) {
  508. LoadedImage->ModuleName = ImageName;
  509. //
  510. // Now locate and walk through and process the images imports
  511. //
  512. if (LoadedImage->FileHeader != NULL &&
  513. ((Flags & BIND_ALL_IMAGES) || (!LoadedImage->fSystemImage)) ) {
  514. FileHeader = &((PIMAGE_NT_HEADERS32)LoadedImage->FileHeader)->FileHeader;
  515. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)LoadedImage->FileHeader,
  516. &OptionalHeader32,
  517. &OptionalHeader64);
  518. if (OPTIONALHEADER(DllCharacteristics) & IMAGE_DLLCHARACTERISTICS_NO_BIND) {
  519. goto NoBind;
  520. }
  521. {
  522. DWORD dwDataSize;
  523. PVOID pData = ImageDirectoryEntryToData(
  524. LoadedImage->MappedAddress,
  525. FALSE,
  526. IMAGE_DIRECTORY_ENTRY_SECURITY,
  527. &dwDataSize
  528. );
  529. if (pData || dwDataSize) {
  530. // Signed - can't bind it.
  531. goto NoBind;
  532. }
  533. pData = ImageDirectoryEntryToData(
  534. LoadedImage->MappedAddress,
  535. FALSE,
  536. IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
  537. &dwDataSize
  538. );
  539. if (pData || dwDataSize) {
  540. // COR header found - see if it's strong signed
  541. if (((IMAGE_COR20_HEADER *)pData)->StrongNameSignature.VirtualAddress &&
  542. ((IMAGE_COR20_HEADER *)pData)->StrongNameSignature.Size)
  543. {
  544. goto NoBind;
  545. }
  546. }
  547. }
  548. BindpWalkAndProcessImports(
  549. &Parms,
  550. LoadedImage,
  551. DllPath,
  552. &ImageModified
  553. );
  554. //
  555. // If the file is being updated, then recompute the checksum.
  556. // and update image and possibly stripped symbol file.
  557. //
  558. if (!Parms.fNoUpdate && ImageModified &&
  559. (LoadedImage->hFile != INVALID_HANDLE_VALUE)) {
  560. // The image may have been moved as part of remapping it to add space for the
  561. // bound imports. Recalculate the file and optional headers.
  562. FileHeader = &((PIMAGE_NT_HEADERS32)LoadedImage->FileHeader)->FileHeader;
  563. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)LoadedImage->FileHeader,
  564. &OptionalHeader32,
  565. &OptionalHeader64);
  566. if ( (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) &&
  567. (SymbolPath != NULL) ) {
  568. PIMAGE_DEBUG_DIRECTORY DebugDirectories;
  569. ULONG DebugDirectoriesSize;
  570. PIMAGE_DEBUG_MISC MiscDebug;
  571. fSymbolsAlreadySplit = TRUE;
  572. strcpy( DebugFileName, ImageName );
  573. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryEntryToData(
  574. LoadedImage->MappedAddress,
  575. FALSE,
  576. IMAGE_DIRECTORY_ENTRY_DEBUG,
  577. &DebugDirectoriesSize
  578. );
  579. if (DebugDirectoryIsUseful(DebugDirectories, DebugDirectoriesSize)) {
  580. while (DebugDirectoriesSize != 0) {
  581. if (DebugDirectories->Type == IMAGE_DEBUG_TYPE_MISC) {
  582. MiscDebug = (PIMAGE_DEBUG_MISC)
  583. ((PCHAR)LoadedImage->MappedAddress +
  584. DebugDirectories->PointerToRawData
  585. );
  586. strcpy( DebugFileName, (PCHAR) MiscDebug->Data );
  587. break;
  588. } else {
  589. DebugDirectories += 1;
  590. DebugDirectoriesSize -= sizeof( *DebugDirectories );
  591. }
  592. }
  593. }
  594. } else {
  595. fSymbolsAlreadySplit = FALSE;
  596. }
  597. OldChecksum = OPTIONALHEADER(CheckSum);
  598. CheckSumMappedFile(
  599. (PVOID)LoadedImage->MappedAddress,
  600. GetFileSize(LoadedImage->hFile, NULL),
  601. &HeaderSum,
  602. &CheckSum
  603. );
  604. OPTIONALHEADER_LV(CheckSum) = CheckSum;
  605. FlushViewOfFile(LoadedImage->MappedAddress, LoadedImage->SizeOfImage);
  606. if (fSymbolsAlreadySplit) {
  607. if ( UpdateDebugInfoFileEx(ImageName,
  608. SymbolPath,
  609. DebugFilePath,
  610. (PIMAGE_NT_HEADERS32)(LoadedImage->FileHeader),
  611. OldChecksum)) {
  612. if (GetLastError() == ERROR_INVALID_DATA) {
  613. if (Parms.StatusRoutine != NULL) {
  614. (Parms.StatusRoutine)( BindMismatchedSymbols,
  615. LoadedImage->ModuleName,
  616. NULL,
  617. 0,
  618. (ULONG_PTR)DebugFileName
  619. );
  620. }
  621. }
  622. } else {
  623. if (Parms.StatusRoutine != NULL) {
  624. (Parms.StatusRoutine)( BindSymbolsNotUpdated,
  625. LoadedImage->ModuleName,
  626. NULL,
  627. 0,
  628. (ULONG_PTR)DebugFileName
  629. );
  630. }
  631. }
  632. }
  633. GetSystemTime(&SystemTime);
  634. if (SystemTimeToFileTime( &SystemTime, &LastWriteTime )) {
  635. SetFileTime( LoadedImage->hFile, NULL, NULL, &LastWriteTime );
  636. }
  637. }
  638. }
  639. NoBind:
  640. fRC = TRUE;
  641. }
  642. } __except (EXCEPTION_EXECUTE_HANDLER) {
  643. // Nothing to do...
  644. }
  645. if (LoadedImage->MappedAddress) {
  646. UnmapViewOfFile( LoadedImage->MappedAddress );
  647. }
  648. if (LoadedImage->hFile != INVALID_HANDLE_VALUE) {
  649. CloseHandle( LoadedImage->hFile );
  650. }
  651. if (!(Flags & BIND_CACHE_IMPORT_DLLS)) {
  652. UnloadAllImages();
  653. }
  654. return (fRC);
  655. }
  656. BOOL
  657. BindpLookupThunk(
  658. PBINDP_PARAMETERS Parms,
  659. PIMAGE_THUNK_DATA ThunkName,
  660. PLOADED_IMAGE Image,
  661. PIMAGE_THUNK_DATA SnappedThunks,
  662. PIMAGE_THUNK_DATA FunctionAddress,
  663. PLOADED_IMAGE Dll,
  664. PIMAGE_EXPORT_DIRECTORY Exports,
  665. PIMPORT_DESCRIPTOR NewImport,
  666. LPSTR DllPath,
  667. PULONG *ForwarderChain
  668. )
  669. {
  670. BOOL Ordinal;
  671. USHORT OrdinalNumber;
  672. PULONG NameTableBase;
  673. PUSHORT NameOrdinalTableBase;
  674. PULONG FunctionTableBase;
  675. PIMAGE_IMPORT_BY_NAME ImportName;
  676. USHORT HintIndex;
  677. LPSTR NameTableName;
  678. ULONG64 ExportsBase;
  679. ULONG ExportSize;
  680. UCHAR NameBuffer[ 32 ];
  681. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  682. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  683. PIMAGE_OPTIONAL_HEADER32 DllOptionalHeader32 = NULL;
  684. PIMAGE_OPTIONAL_HEADER64 DllOptionalHeader64 = NULL;
  685. NameTableBase = (PULONG) BindpRvaToVa( Parms, Exports->AddressOfNames, Dll );
  686. if (!NameTableBase)
  687. return FALSE;
  688. NameOrdinalTableBase = (PUSHORT) BindpRvaToVa( Parms, Exports->AddressOfNameOrdinals, Dll );
  689. FunctionTableBase = (PULONG) BindpRvaToVa( Parms, Exports->AddressOfFunctions, Dll );
  690. if (!FunctionTableBase) {
  691. return FALSE;
  692. }
  693. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Image->FileHeader,
  694. &OptionalHeader32,
  695. &OptionalHeader64);
  696. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Dll->FileHeader,
  697. &DllOptionalHeader32,
  698. &DllOptionalHeader64);
  699. //
  700. // Determine if snap is by name, or by ordinal
  701. //
  702. Ordinal = (BOOL)IMAGE_SNAP_BY_ORDINAL(ThunkName->u1.Ordinal);
  703. if (Ordinal) {
  704. UCHAR szOrdinal[8];
  705. OrdinalNumber = (USHORT)(IMAGE_ORDINAL(ThunkName->u1.Ordinal) - Exports->Base);
  706. if ( (ULONG)OrdinalNumber >= Exports->NumberOfFunctions ) {
  707. return FALSE;
  708. }
  709. ImportName = (PIMAGE_IMPORT_BY_NAME)NameBuffer;
  710. // Can't use sprintf w/o dragging in more CRT support than we want... Must run on Win95.
  711. strcpy((PCHAR) ImportName->Name, "Ordinal");
  712. strcat((PCHAR) ImportName->Name, _ultoa((ULONG) OrdinalNumber, (LPSTR) szOrdinal, 16));
  713. }
  714. else {
  715. ImportName = (PIMAGE_IMPORT_BY_NAME)BindpRvaToVa(
  716. Parms,
  717. (ULONG)(ULONG_PTR)(ThunkName->u1.AddressOfData),
  718. Image
  719. );
  720. if (!ImportName) {
  721. return FALSE;
  722. }
  723. //
  724. // now check to see if the hint index is in range. If it
  725. // is, then check to see if it matches the function at
  726. // the hint. If all of this is true, then we can snap
  727. // by hint. Otherwise need to scan the name ordinal table
  728. //
  729. OrdinalNumber = (USHORT)(Exports->NumberOfFunctions+1);
  730. HintIndex = ImportName->Hint;
  731. if ((ULONG)HintIndex < Exports->NumberOfNames ) {
  732. NameTableName = (LPSTR) BindpRvaToVa( Parms, NameTableBase[HintIndex], Dll );
  733. if ( NameTableName ) {
  734. if ( !strcmp((PCHAR)ImportName->Name, NameTableName) ) {
  735. OrdinalNumber = NameOrdinalTableBase[HintIndex];
  736. }
  737. }
  738. }
  739. if ((ULONG)OrdinalNumber >= Exports->NumberOfFunctions) {
  740. for (HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++) {
  741. NameTableName = (LPSTR) BindpRvaToVa( Parms, NameTableBase[HintIndex], Dll );
  742. if (NameTableName) {
  743. if (!strcmp( (PCHAR)ImportName->Name, NameTableName )) {
  744. OrdinalNumber = NameOrdinalTableBase[HintIndex];
  745. break;
  746. }
  747. }
  748. }
  749. if ((ULONG)OrdinalNumber >= Exports->NumberOfFunctions) {
  750. return FALSE;
  751. }
  752. }
  753. }
  754. (FunctionAddress->u1.Function) = (ULONG)(FunctionTableBase[OrdinalNumber] +
  755. (DllOptionalHeader32 ?
  756. DllOptionalHeader32->ImageBase :
  757. DllOptionalHeader64->ImageBase)
  758. );
  759. ExportsBase = (ULONG64)ImageDirectoryEntryToData(
  760. (PVOID)Dll->MappedAddress,
  761. TRUE,
  762. IMAGE_DIRECTORY_ENTRY_EXPORT,
  763. &ExportSize
  764. ) - (ULONG_PTR)Dll->MappedAddress;
  765. ExportsBase += (DllOptionalHeader32 ?
  766. DllOptionalHeader32->ImageBase :
  767. DllOptionalHeader64->ImageBase);
  768. if ((ULONG64)FunctionAddress->u1.Function > (ULONG64)ExportsBase &&
  769. (ULONG64)FunctionAddress->u1.Function < ((ULONG64)ExportsBase + ExportSize)
  770. ) {
  771. BOOL BoundForwarder;
  772. BoundForwarder = FALSE;
  773. if (NewImport != NULL) {
  774. (FunctionAddress->u1.ForwarderString) = (ULONG_PTR)BindpAddForwarderReference(Parms,
  775. Image->ModuleName,
  776. (LPSTR) ImportName->Name,
  777. NewImport,
  778. DllPath,
  779. (PUCHAR) BindpRvaToVa( Parms, FunctionTableBase[OrdinalNumber], Dll ),
  780. &BoundForwarder
  781. );
  782. }
  783. if (!BoundForwarder) {
  784. **ForwarderChain = (ULONG) (FunctionAddress - SnappedThunks);
  785. *ForwarderChain = (ULONG *)&FunctionAddress->u1.Ordinal;
  786. if (Parms->StatusRoutine != NULL) {
  787. (Parms->StatusRoutine)( BindForwarderNOT,
  788. Image->ModuleName,
  789. Dll->ModuleName,
  790. (ULONG_PTR)FunctionAddress->u1.Function,
  791. (ULONG_PTR)(ImportName->Name)
  792. );
  793. }
  794. }
  795. }
  796. else {
  797. if (Parms->StatusRoutine != NULL) {
  798. (Parms->StatusRoutine)( BindImportProcedure,
  799. Image->ModuleName,
  800. Dll->ModuleName,
  801. (ULONG_PTR)FunctionAddress->u1.Function,
  802. (ULONG_PTR)(ImportName->Name)
  803. );
  804. }
  805. }
  806. return TRUE;
  807. }
  808. PVOID
  809. BindpRvaToVa(
  810. PBINDP_PARAMETERS Parms,
  811. ULONG Rva,
  812. PLOADED_IMAGE Image
  813. )
  814. {
  815. PVOID Va;
  816. Va = ImageRvaToVa( Image->FileHeader,
  817. Image->MappedAddress,
  818. Rva,
  819. &Image->LastRvaSection
  820. );
  821. if (!Va && Parms->StatusRoutine != NULL) {
  822. (Parms->StatusRoutine)( BindRvaToVaFailed,
  823. Image->ModuleName,
  824. NULL,
  825. (ULONG)Rva,
  826. 0
  827. );
  828. }
  829. return Va;
  830. }
  831. VOID
  832. SetIdataToRo(
  833. PLOADED_IMAGE Image
  834. )
  835. {
  836. PIMAGE_SECTION_HEADER Section;
  837. ULONG i;
  838. for(Section = Image->Sections,i=0; i<Image->NumberOfSections; i++,Section++) {
  839. if (!_stricmp((PCHAR) Section->Name, ".idata")) {
  840. if (Section->Characteristics & IMAGE_SCN_MEM_WRITE) {
  841. Section->Characteristics &= ~IMAGE_SCN_MEM_WRITE;
  842. Section->Characteristics |= IMAGE_SCN_MEM_READ;
  843. }
  844. break;
  845. }
  846. }
  847. }
  848. VOID
  849. BindpWalkAndProcessImports(
  850. PBINDP_PARAMETERS Parms,
  851. PLOADED_IMAGE Image,
  852. LPSTR DllPath,
  853. PBOOL ImageModified
  854. )
  855. {
  856. ULONG ForwarderChainHead;
  857. PULONG ForwarderChain;
  858. ULONG ImportSize;
  859. ULONG ExportSize;
  860. PIMPORT_DESCRIPTOR NewImportDescriptorHead, NewImportDescriptor;
  861. PIMAGE_BOUND_IMPORT_DESCRIPTOR PrevNewImports, NewImports;
  862. ULONG PrevNewImportsSize, NewImportsSize;
  863. PIMAGE_IMPORT_DESCRIPTOR Imports;
  864. PIMAGE_EXPORT_DIRECTORY Exports;
  865. LPSTR ImportModule;
  866. PLOADED_IMAGE Dll;
  867. PIMAGE_THUNK_DATA tname,tsnap;
  868. PIMAGE_THUNK_DATA ThunkNames;
  869. PIMAGE_THUNK_DATA SnappedThunks;
  870. PIMAGE_IMPORT_BY_NAME ImportName;
  871. ULONG NumberOfThunks;
  872. ULONG i, cb;
  873. BOOL Ordinal, BindThunkFailed, NoErrors;
  874. USHORT OrdinalNumber;
  875. UCHAR NameBuffer[ 32 ];
  876. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  877. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  878. PIMAGE_FILE_HEADER FileHeader;
  879. NoErrors = FALSE;
  880. *ImageModified = FALSE;
  881. //
  882. // Locate the import array for this image/dll
  883. //
  884. NewImportDescriptorHead = NULL;
  885. Imports = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
  886. (PVOID)Image->MappedAddress,
  887. FALSE,
  888. IMAGE_DIRECTORY_ENTRY_IMPORT,
  889. &ImportSize
  890. );
  891. if (Imports == NULL) {
  892. //
  893. // Nothing to bind if no imports
  894. //
  895. return;
  896. }
  897. FileHeader = &((PIMAGE_NT_HEADERS32)Image->FileHeader)->FileHeader;
  898. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Image->FileHeader,
  899. &OptionalHeader32,
  900. &OptionalHeader64);
  901. PrevNewImports = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(
  902. (PVOID)Image->MappedAddress,
  903. FALSE,
  904. IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,
  905. &PrevNewImportsSize
  906. );
  907. // If the user asked for an old style bind and there are new style bind records
  908. // already in the image, zero them out first. This is the fix the problem where
  909. // you bind on NT (creating new import descriptors), boot Win95 and bind there
  910. // (creating old bind format), and then reboot to NT (the loader will only check
  911. // the BOUND_IMPORT array.
  912. if (PrevNewImports &&
  913. (Parms->fNewImports == FALSE) &&
  914. (Parms->fNoUpdate == FALSE ))
  915. {
  916. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].VirtualAddress) = 0;
  917. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].Size) = 0;
  918. PrevNewImports = 0;
  919. PrevNewImportsSize = 0;
  920. *ImageModified = TRUE;
  921. }
  922. //
  923. // For each import record
  924. //
  925. for(;Imports;Imports++) {
  926. if ( !Imports->Name ) {
  927. break;
  928. }
  929. //
  930. // Locate the module being imported and load the dll
  931. //
  932. ImportModule = (LPSTR)BindpRvaToVa( Parms, Imports->Name, Image );
  933. if (ImportModule) {
  934. Dll = ImageLoad( ImportModule, DllPath );
  935. if (!Dll) {
  936. if (Parms->StatusRoutine != NULL) {
  937. (Parms->StatusRoutine)( BindImportModuleFailed,
  938. Image->ModuleName,
  939. ImportModule,
  940. 0,
  941. 0
  942. );
  943. }
  944. //
  945. // Unless specifically told not to, generate the new style
  946. // import descriptor.
  947. //
  948. BindpAddImportDescriptor(Parms,
  949. &NewImportDescriptorHead,
  950. Imports,
  951. ImportModule,
  952. Dll
  953. );
  954. continue;
  955. }
  956. if (Parms->StatusRoutine != NULL) {
  957. (Parms->StatusRoutine)( BindImportModule,
  958. Image->ModuleName,
  959. ImportModule,
  960. 0,
  961. 0
  962. );
  963. }
  964. //
  965. // If we can load the DLL, locate the export section and
  966. // start snapping the thunks
  967. //
  968. Exports = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryEntryToData(
  969. (PVOID)Dll->MappedAddress,
  970. FALSE,
  971. IMAGE_DIRECTORY_ENTRY_EXPORT,
  972. &ExportSize
  973. );
  974. if ( !Exports ) {
  975. continue;
  976. }
  977. //
  978. // assert that the export directory addresses can be translated
  979. //
  980. if ( !BindpRvaToVa( Parms, Exports->AddressOfNames, Dll ) ) {
  981. continue;
  982. }
  983. if ( !BindpRvaToVa( Parms, Exports->AddressOfNameOrdinals, Dll ) ) {
  984. continue;
  985. }
  986. if ( !BindpRvaToVa( Parms, Exports->AddressOfFunctions, Dll ) ) {
  987. continue;
  988. }
  989. //
  990. // For old style bind, bypass the bind if it's already bound.
  991. // New style binds s/b looked up in PrevNewImport.
  992. //
  993. if ( Parms->fNewImports == FALSE &&
  994. Imports->TimeDateStamp &&
  995. Imports->TimeDateStamp == FileHeader->TimeDateStamp ) {
  996. continue;
  997. }
  998. //
  999. // Now we need to size our thunk table and
  1000. // allocate a buffer to hold snapped thunks. This is
  1001. // done instead of writting to the mapped view so that
  1002. // thunks are only updated if we find all the entry points
  1003. //
  1004. ThunkNames = (PIMAGE_THUNK_DATA) BindpRvaToVa( Parms, Imports->OriginalFirstThunk, Image );
  1005. if (!ThunkNames || ThunkNames->u1.Function == 0) {
  1006. //
  1007. // Skip this one if no thunks or first thunk is the terminating null thunk
  1008. //
  1009. continue;
  1010. }
  1011. //
  1012. // Unless specifically told not to, generate the new style
  1013. // import descriptor.
  1014. //
  1015. NewImportDescriptor = BindpAddImportDescriptor(Parms,
  1016. &NewImportDescriptorHead,
  1017. Imports,
  1018. ImportModule,
  1019. Dll
  1020. );
  1021. NumberOfThunks = 0;
  1022. tname = ThunkNames;
  1023. while (tname->u1.AddressOfData) {
  1024. NumberOfThunks++;
  1025. tname++;
  1026. }
  1027. SnappedThunks = (PIMAGE_THUNK_DATA) MemAlloc( NumberOfThunks*sizeof(*SnappedThunks) );
  1028. if ( !SnappedThunks ) {
  1029. continue;
  1030. }
  1031. tname = ThunkNames;
  1032. tsnap = SnappedThunks;
  1033. NoErrors = TRUE;
  1034. ForwarderChainHead = (ULONG)-1;
  1035. ForwarderChain = &ForwarderChainHead;
  1036. for(i=0;i<NumberOfThunks;i++) {
  1037. BindThunkFailed = FALSE;
  1038. __try {
  1039. if (!BindpLookupThunk( Parms,
  1040. tname,
  1041. Image,
  1042. SnappedThunks,
  1043. tsnap,
  1044. Dll,
  1045. Exports,
  1046. NewImportDescriptor,
  1047. DllPath,
  1048. &ForwarderChain
  1049. )
  1050. ) {
  1051. BindThunkFailed = TRUE;
  1052. }
  1053. } __except ( EXCEPTION_EXECUTE_HANDLER ) {
  1054. BindThunkFailed = TRUE;
  1055. }
  1056. if (BindThunkFailed) {
  1057. if (NewImportDescriptor != NULL) {
  1058. NewImportDescriptor->TimeDateStamp = 0;
  1059. }
  1060. if (Parms->StatusRoutine != NULL) {
  1061. Ordinal = (BOOL)IMAGE_SNAP_BY_ORDINAL(tname->u1.Ordinal);
  1062. if (Ordinal) {
  1063. UCHAR szOrdinal[8];
  1064. OrdinalNumber = (USHORT)(IMAGE_ORDINAL(tname->u1.Ordinal) - Exports->Base);
  1065. ImportName = (PIMAGE_IMPORT_BY_NAME)NameBuffer;
  1066. // Can't use sprintf w/o dragging in more CRT support than we want... Must run on Win95.
  1067. strcpy((PCHAR) ImportName->Name, "Ordinal");
  1068. strcat((PCHAR) ImportName->Name, _ultoa((ULONG) OrdinalNumber, (LPSTR)szOrdinal, 16));
  1069. }
  1070. else {
  1071. ImportName = (PIMAGE_IMPORT_BY_NAME)BindpRvaToVa(
  1072. Parms,
  1073. (ULONG)(ULONG_PTR)(tname->u1.AddressOfData),
  1074. Image
  1075. );
  1076. }
  1077. (Parms->StatusRoutine)( BindImportProcedureFailed,
  1078. Image->ModuleName,
  1079. Dll->ModuleName,
  1080. (ULONG_PTR)tsnap->u1.Function,
  1081. (ULONG_PTR)(ImportName->Name)
  1082. );
  1083. }
  1084. break;
  1085. }
  1086. tname++;
  1087. tsnap++;
  1088. }
  1089. tname = (PIMAGE_THUNK_DATA) BindpRvaToVa( Parms, Imports->FirstThunk, Image );
  1090. if ( !tname ) {
  1091. NoErrors = FALSE;
  1092. }
  1093. //
  1094. // If we were able to locate all of the entrypoints in the
  1095. // target dll, then copy the snapped thunks into the image,
  1096. // update the time and date stamp, and flush the image to
  1097. // disk
  1098. //
  1099. if ( NoErrors && Parms->fNoUpdate == FALSE ) {
  1100. if (ForwarderChainHead != -1) {
  1101. *ImageModified = TRUE;
  1102. *ForwarderChain = -1;
  1103. }
  1104. if (Imports->ForwarderChain != ForwarderChainHead) {
  1105. Imports->ForwarderChain = ForwarderChainHead;
  1106. *ImageModified = TRUE;
  1107. }
  1108. cb = NumberOfThunks*sizeof(*SnappedThunks);
  1109. if (memcmp(tname,SnappedThunks,cb)) {
  1110. MoveMemory(tname,SnappedThunks,cb);
  1111. *ImageModified = TRUE;
  1112. }
  1113. if (NewImportDescriptorHead == NULL) {
  1114. if (Imports->TimeDateStamp != FileHeader->TimeDateStamp) {
  1115. Imports->TimeDateStamp = FileHeader->TimeDateStamp;
  1116. *ImageModified = TRUE;
  1117. }
  1118. }
  1119. else
  1120. if (Imports->TimeDateStamp != 0xFFFFFFFF) {
  1121. Imports->TimeDateStamp = 0xFFFFFFFF;
  1122. *ImageModified = TRUE;
  1123. }
  1124. }
  1125. MemFree(SnappedThunks);
  1126. }
  1127. }
  1128. NewImports = BindpCreateNewImportSection(Parms, &NewImportDescriptorHead, &NewImportsSize);
  1129. if (PrevNewImportsSize != NewImportsSize ||
  1130. memcmp( PrevNewImports, NewImports, NewImportsSize )
  1131. ) {
  1132. *ImageModified = TRUE;
  1133. }
  1134. if (!*ImageModified) {
  1135. return;
  1136. }
  1137. if (Parms->StatusRoutine != NULL) {
  1138. (Parms->StatusRoutine)( BindImageModified,
  1139. Image->ModuleName,
  1140. NULL,
  1141. 0,
  1142. 0
  1143. );
  1144. }
  1145. if (NewImports != NULL) {
  1146. ULONG cbFreeFile, cbFreeHeaders, OffsetHeaderFreeSpace, cbFreeSpaceOnDisk;
  1147. if (NoErrors && Parms->fNoUpdate == FALSE) {
  1148. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].VirtualAddress) = 0;
  1149. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].Size) = 0;
  1150. }
  1151. OffsetHeaderFreeSpace = GetImageUnusedHeaderBytes( Image, &cbFreeFile );
  1152. cbFreeHeaders = Image->Sections->VirtualAddress -
  1153. OPTIONALHEADER(SizeOfHeaders) +
  1154. cbFreeFile;
  1155. // FreeSpace on Disk may be larger that FreeHeaders in the headers (the linker
  1156. // can start the first section on a page boundary already)
  1157. cbFreeSpaceOnDisk = Image->Sections->PointerToRawData -
  1158. OPTIONALHEADER(SizeOfHeaders) +
  1159. cbFreeFile;
  1160. if (NewImportsSize > cbFreeFile) {
  1161. if (NewImportsSize > cbFreeHeaders) {
  1162. if (Parms->StatusRoutine != NULL) {
  1163. (Parms->StatusRoutine)( BindNoRoomInImage,
  1164. Image->ModuleName,
  1165. NULL,
  1166. 0,
  1167. 0
  1168. );
  1169. }
  1170. NoErrors = FALSE;
  1171. }
  1172. else
  1173. if (NoErrors && (Parms->fNoUpdate == FALSE)) {
  1174. if (NewImportsSize <= cbFreeSpaceOnDisk) {
  1175. // There's already space on disk. Just adjust the header size.
  1176. OPTIONALHEADER_LV(SizeOfHeaders) =
  1177. (OPTIONALHEADER(SizeOfHeaders) -
  1178. cbFreeFile + NewImportsSize + (OPTIONALHEADER(FileAlignment)-1)
  1179. ) & ~(OPTIONALHEADER(FileAlignment)-1);
  1180. } else {
  1181. NoErrors = BindpExpandImageFileHeaders( Parms,
  1182. Image,
  1183. (OPTIONALHEADER(SizeOfHeaders) -
  1184. cbFreeFile +
  1185. NewImportsSize +
  1186. (OPTIONALHEADER(FileAlignment)-1)
  1187. ) &
  1188. ~(OPTIONALHEADER(FileAlignment)-1)
  1189. );
  1190. // Expand may have remapped the image. Recalc the header ptrs.
  1191. FileHeader = &((PIMAGE_NT_HEADERS32)Image->FileHeader)->FileHeader;
  1192. OptionalHeadersFromNtHeaders((PIMAGE_NT_HEADERS32)Image->FileHeader,
  1193. &OptionalHeader32,
  1194. &OptionalHeader64);
  1195. }
  1196. }
  1197. }
  1198. if (Parms->StatusRoutine != NULL) {
  1199. (Parms->StatusRoutine)( BindImageComplete,
  1200. Image->ModuleName,
  1201. NULL,
  1202. (ULONG_PTR)NewImports,
  1203. NoErrors
  1204. );
  1205. }
  1206. if (NoErrors && Parms->fNoUpdate == FALSE) {
  1207. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].VirtualAddress) = OffsetHeaderFreeSpace;
  1208. OPTIONALHEADER_LV(DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ].Size) = NewImportsSize;
  1209. memcpy( (LPSTR)(Image->MappedAddress) + OffsetHeaderFreeSpace,
  1210. NewImports,
  1211. NewImportsSize
  1212. );
  1213. }
  1214. MemFree(NewImports);
  1215. }
  1216. if (NoErrors && Parms->fNoUpdate == FALSE) {
  1217. SetIdataToRo( Image );
  1218. }
  1219. }
  1220. DWORD
  1221. GetImageUnusedHeaderBytes(
  1222. PLOADED_IMAGE LoadedImage,
  1223. LPDWORD SizeUnusedHeaderBytes
  1224. )
  1225. {
  1226. DWORD OffsetFirstUnusedHeaderByte;
  1227. DWORD i;
  1228. DWORD OffsetHeader;
  1229. PIMAGE_OPTIONAL_HEADER32 OptionalHeader32 = NULL;
  1230. PIMAGE_OPTIONAL_HEADER64 OptionalHeader64 = NULL;
  1231. PIMAGE_NT_HEADERS32 NtHeaders;
  1232. NtHeaders = (PIMAGE_NT_HEADERS32)LoadedImage->FileHeader;
  1233. //
  1234. // this calculates an offset, not an address, so DWORD is correct
  1235. //
  1236. OffsetFirstUnusedHeaderByte = (DWORD)
  1237. (((LPSTR)NtHeaders - (LPSTR)LoadedImage->MappedAddress) +
  1238. (FIELD_OFFSET( IMAGE_NT_HEADERS32, OptionalHeader ) +
  1239. NtHeaders->FileHeader.SizeOfOptionalHeader +
  1240. (NtHeaders->FileHeader.NumberOfSections *
  1241. sizeof(IMAGE_SECTION_HEADER)
  1242. )
  1243. )
  1244. );
  1245. OptionalHeadersFromNtHeaders(NtHeaders,
  1246. &OptionalHeader32,
  1247. &OptionalHeader64);
  1248. for ( i=0; i<OPTIONALHEADER(NumberOfRvaAndSizes); i++ ) {
  1249. OffsetHeader = OPTIONALHEADER(DataDirectory[i].VirtualAddress);
  1250. if (OffsetHeader < OPTIONALHEADER(SizeOfHeaders)) {
  1251. if (OffsetHeader >= OffsetFirstUnusedHeaderByte) {
  1252. OffsetFirstUnusedHeaderByte = OffsetHeader +
  1253. OPTIONALHEADER(DataDirectory[i].Size);
  1254. }
  1255. }
  1256. }
  1257. *SizeUnusedHeaderBytes = OPTIONALHEADER(SizeOfHeaders) -
  1258. OffsetFirstUnusedHeaderByte;
  1259. return OffsetFirstUnusedHeaderByte;
  1260. }