Leaked source code of windows server 2003
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.

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