3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/utils.c
6 * PURPOSE: Process startup for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
13 * - Handle loading flags correctly
14 * - Handle errors correctly (unload dll's)
15 * - Implement a faster way to find modules (hash table)
19 /* INCLUDES *****************************************************************/
25 #define LDRP_PROCESS_CREATION_TIME 0x8000000
27 /* GLOBALS *******************************************************************/
31 #define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
35 #define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
38 typedef struct _TLS_DATA
40 PVOID StartAddressOfRawData
;
43 PIMAGE_TLS_CALLBACK TlsAddressOfCallBacks
;
44 PLDR_DATA_TABLE_ENTRY Module
;
45 } TLS_DATA
, *PTLS_DATA
;
47 static PTLS_DATA LdrpTlsArray
= NULL
;
48 static ULONG LdrpTlsCount
= 0;
49 static ULONG LdrpTlsSize
= 0;
50 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
51 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
52 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
53 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
55 /* PROTOTYPES ****************************************************************/
57 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
58 static PVOID
LdrFixupForward(PCHAR ForwardName
);
59 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
60 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
62 IN PUNICODE_STRING Name
,
63 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
64 OUT PVOID
*BaseAddress OPTIONAL
);
65 static NTSTATUS
LdrpAttachProcess(VOID
);
66 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
68 /* FUNCTIONS *****************************************************************/
70 #if defined(DBG) || defined(KDBG)
73 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule
)
84 #endif /* DBG || KDBG */
87 LdrMappedAsDataFile(PVOID
*BaseAddress
)
89 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
91 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
98 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
103 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
105 LoadCount
= Module
->LoadCount
;
106 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= 0xFFFF)
112 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
117 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
122 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
124 LoadCount
= Module
->LoadCount
;
125 if (Module
->LoadCount
!= 0xFFFF)
131 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
136 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
140 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
142 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
147 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
151 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
153 PIMAGE_TLS_CALLBACK TlsCallback
;
154 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== 0xFFFF)
156 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
161 TRACE_LDR("%wZ - Calling tls callback at %x\n",
162 &Module
->BaseDllName
, TlsCallback
);
163 TlsCallback(Module
->DllBase
, dwReason
, NULL
);
164 TlsCallback
= (PIMAGE_TLS_CALLBACK
)((ULONG_PTR
)TlsCallback
+ sizeof(PVOID
));
170 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
172 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
173 Module
->EntryPoint
== 0)
177 LdrpTlsCallback(Module
, dwReason
);
178 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
182 LdrpInitializeTlsForThread(VOID
)
188 PTEB Teb
= NtCurrentTeb();
190 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
192 Teb
->StaticUnicodeString
.Length
= 0;
193 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
194 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
196 if (LdrpTlsCount
> 0)
198 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
200 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
201 if (TlsPointers
== NULL
)
203 DPRINT1("failed to allocate thread tls data\n");
204 return STATUS_NO_MEMORY
;
207 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
208 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
210 TlsInfo
= LdrpTlsArray
;
211 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
213 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
214 TlsPointers
[i
] = TlsData
;
215 if (TlsInfo
->TlsDataSize
)
217 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
218 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
220 if (TlsInfo
->TlsZeroSize
)
222 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
223 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
227 DPRINT("LdrpInitializeTlsForThread() done\n");
228 return STATUS_SUCCESS
;
232 LdrpInitializeTlsForProccess(VOID
)
234 PLIST_ENTRY ModuleListHead
;
236 PLDR_DATA_TABLE_ENTRY Module
;
237 PIMAGE_TLS_DIRECTORY TlsDirectory
;
241 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
243 if (LdrpTlsCount
> 0)
245 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
247 LdrpTlsCount
* sizeof(TLS_DATA
));
248 if (LdrpTlsArray
== NULL
)
250 DPRINT1("Failed to allocate global tls data\n");
251 return STATUS_NO_MEMORY
;
254 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
255 Entry
= ModuleListHead
->Flink
;
256 while (Entry
!= ModuleListHead
)
258 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
259 if (Module
->LoadCount
== 0xFFFF &&
260 Module
->TlsIndex
!= 0xFFFF)
262 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
263 RtlImageDirectoryEntryToData(Module
->DllBase
,
265 IMAGE_DIRECTORY_ENTRY_TLS
,
267 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
268 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
269 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
270 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
271 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
272 if (TlsDirectory
->AddressOfCallBacks
)
273 TlsData
->TlsAddressOfCallBacks
= *(PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
275 TlsData
->TlsAddressOfCallBacks
= NULL
;
276 TlsData
->Module
= Module
;
278 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
279 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
280 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
281 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
282 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
283 DbgPrint("AddressOfCallBacks: %x (%x)\n", TlsDirectory
->AddressOfCallBacks
, *TlsDirectory
->AddressOfCallBacks
);
284 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
285 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
289 * Is this region allways writable ?
291 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
293 Entry
= Entry
->Flink
;
296 DPRINT("LdrpInitializeTlsForProccess() done\n");
297 return STATUS_SUCCESS
;
303 OBJECT_ATTRIBUTES ObjectAttributes
;
304 UNICODE_STRING LinkTarget
;
310 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
312 /* Get handle to the 'KnownDlls' directory */
313 RtlInitUnicodeString(&Name
,
315 InitializeObjectAttributes(&ObjectAttributes
,
317 OBJ_CASE_INSENSITIVE
,
320 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
321 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
323 if (!NT_SUCCESS(Status
))
325 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
326 LdrpKnownDllsDirHandle
= NULL
;
330 /* Allocate target name string */
331 LinkTarget
.Length
= 0;
332 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
333 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
335 MAX_PATH
* sizeof(WCHAR
));
336 if (LinkTarget
.Buffer
== NULL
)
338 NtClose(LdrpKnownDllsDirHandle
);
339 LdrpKnownDllsDirHandle
= NULL
;
343 RtlInitUnicodeString(&Name
,
345 InitializeObjectAttributes(&ObjectAttributes
,
347 OBJ_CASE_INSENSITIVE
| OBJ_OPENLINK
,
348 LdrpKnownDllsDirHandle
,
350 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
351 SYMBOLIC_LINK_ALL_ACCESS
,
353 if (!NT_SUCCESS(Status
))
355 RtlFreeUnicodeString(&LinkTarget
);
356 NtClose(LdrpKnownDllsDirHandle
);
357 LdrpKnownDllsDirHandle
= NULL
;
361 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
365 if (!NT_SUCCESS(Status
))
367 RtlFreeUnicodeString(&LinkTarget
);
368 NtClose(LdrpKnownDllsDirHandle
);
369 LdrpKnownDllsDirHandle
= NULL
;
372 RtlCreateUnicodeString(&LdrpKnownDllPath
,
375 RtlFreeUnicodeString(&LinkTarget
);
377 DPRINT("LdrpInitLoader() done\n");
381 /***************************************************************************
386 * Adjusts the name of a dll to a fully qualified name.
389 * FullDllName: Pointer to caller supplied storage for the fully
390 * qualified dll name.
391 * DllName: Pointer to the dll name.
392 * BaseName: TRUE: Only the file name is passed to FullDllName
393 * FALSE: The full path is preserved in FullDllName
401 * A given path is not affected by the adjustment, but the file
403 * ntdll --> ntdll.dll
405 * ntdll.xyz --> ntdll.xyz
408 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
409 PUNICODE_STRING DllName
,
412 WCHAR Buffer
[MAX_PATH
];
417 Length
= DllName
->Length
/ sizeof(WCHAR
);
421 /* get the base dll name */
422 Pointer
= DllName
->Buffer
+ Length
;
429 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
432 Length
= Extension
- Pointer
;
433 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
434 Buffer
[Length
] = L
'\0';
438 /* get the full dll name */
439 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
440 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
443 /* Build the DLL's absolute name */
444 Extension
= wcsrchr (Buffer
, L
'.');
445 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
447 /* with extension - remove dot if it's the last character */
448 if (Buffer
[Length
- 1] == L
'.')
454 /* name without extension - assume that it is .dll */
455 memmove (Buffer
+ Length
, L
".dll", 10);
458 RtlCreateUnicodeString(FullDllName
, Buffer
);
461 PLDR_DATA_TABLE_ENTRY
462 LdrAddModuleEntry(PVOID ImageBase
,
463 PIMAGE_NT_HEADERS NTHeaders
,
466 PLDR_DATA_TABLE_ENTRY Module
;
468 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
470 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
471 Module
->DllBase
= (PVOID
)ImageBase
;
472 Module
->EntryPoint
= (PVOID
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
473 if (Module
->EntryPoint
!= 0)
474 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
475 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
476 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
478 /* loading while app is running */
479 Module
->LoadCount
= 1;
482 * loading while app is initializing
483 * dll must not be unloaded
485 Module
->LoadCount
= 0xFFFF;
489 Module
->TlsIndex
= -1;
490 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
491 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
493 RtlCreateUnicodeString (&Module
->FullDllName
,
495 RtlCreateUnicodeString (&Module
->BaseDllName
,
496 wcsrchr(FullDosName
, L
'\\') + 1);
497 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
499 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
500 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
501 &Module
->InLoadOrderModuleList
);
502 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
509 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
510 OUT PUNICODE_STRING FullDosName
,
511 OUT PHANDLE SectionHandle
)
513 OBJECT_ATTRIBUTES ObjectAttributes
;
516 DPRINT("LdrpMapKnownDll() called\n");
518 if (LdrpKnownDllsDirHandle
== NULL
)
520 DPRINT("Invalid 'KnownDlls' directory\n");
521 return STATUS_UNSUCCESSFUL
;
524 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
526 InitializeObjectAttributes(&ObjectAttributes
,
528 OBJ_CASE_INSENSITIVE
,
529 LdrpKnownDllsDirHandle
,
531 Status
= NtOpenSection(SectionHandle
,
532 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
534 if (!NT_SUCCESS(Status
))
536 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
540 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
541 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
542 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
544 FullDosName
->MaximumLength
);
545 if (FullDosName
->Buffer
== NULL
)
547 FullDosName
->Length
= 0;
548 FullDosName
->MaximumLength
= 0;
549 return STATUS_SUCCESS
;
552 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
553 wcscat(FullDosName
->Buffer
, L
"\\");
554 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
556 DPRINT("FullDosName '%wZ'\n", FullDosName
);
558 DPRINT("LdrpMapKnownDll() done\n");
560 return STATUS_SUCCESS
;
565 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
566 IN PUNICODE_STRING DllName
,
567 OUT PUNICODE_STRING FullDosName
,
568 IN BOOLEAN MapAsDataFile
,
569 OUT PHANDLE SectionHandle
)
571 WCHAR SearchPathBuffer
[MAX_PATH
];
572 WCHAR DosName
[MAX_PATH
];
573 UNICODE_STRING FullNtFileName
;
574 OBJECT_ATTRIBUTES FileObjectAttributes
;
576 char BlockBuffer
[1024];
577 PIMAGE_DOS_HEADER DosHeader
;
578 PIMAGE_NT_HEADERS NTHeaders
;
579 IO_STATUS_BLOCK IoStatusBlock
;
583 DPRINT("LdrpMapDllImageFile() called\n");
585 if (SearchPath
== NULL
)
587 /* get application running path */
589 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
591 len
= wcslen (SearchPathBuffer
);
593 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
596 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
598 wcscat (SearchPathBuffer
, L
";");
600 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
601 wcscat (SearchPathBuffer
, L
"\\system32;");
602 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
603 wcscat (SearchPathBuffer
, L
";.");
605 SearchPath
= SearchPathBuffer
;
608 if (RtlDosSearchPath_U (SearchPath
,
614 return STATUS_DLL_NOT_FOUND
;
617 if (!RtlDosPathNameToNtPathName_U (DosName
,
621 return STATUS_DLL_NOT_FOUND
;
623 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
625 InitializeObjectAttributes(&FileObjectAttributes
,
631 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
633 Status
= NtOpenFile(&FileHandle
,
634 GENERIC_READ
|SYNCHRONIZE
,
635 &FileObjectAttributes
,
638 FILE_SYNCHRONOUS_IO_NONALERT
);
639 if (!NT_SUCCESS(Status
))
641 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
642 &FullNtFileName
, Status
);
643 RtlFreeHeap (RtlGetProcessHeap (),
645 FullNtFileName
.Buffer
);
648 RtlFreeHeap (RtlGetProcessHeap (),
650 FullNtFileName
.Buffer
);
652 Status
= NtReadFile(FileHandle
,
661 if (!NT_SUCCESS(Status
))
663 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
668 * Overlay DOS and NT headers structures to the
669 * buffer with DLL's header raw data.
671 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
672 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
674 * Check it is a PE image file.
676 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
677 || (DosHeader
->e_lfanew
== 0L)
678 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
680 DPRINT("NTDLL format invalid\n");
683 return STATUS_UNSUCCESSFUL
;
687 * Create a section for dll.
689 Status
= NtCreateSection(SectionHandle
,
694 SEC_COMMIT
| (MapAsDataFile
? 0 : SEC_IMAGE
),
698 if (!NT_SUCCESS(Status
))
700 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
704 RtlCreateUnicodeString(FullDosName
,
712 /***************************************************************************
729 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
731 IN PUNICODE_STRING Name
,
732 OUT PVOID
*BaseAddress OPTIONAL
)
735 PLDR_DATA_TABLE_ENTRY Module
;
737 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
739 SearchPath
? " from " : "",
740 SearchPath
? SearchPath
: L
"");
744 *BaseAddress
= NtCurrentPeb()->ImageBaseAddress
;
745 return STATUS_SUCCESS
;
750 Status
= LdrpLoadModule(SearchPath
, LoadFlags
, Name
, &Module
, BaseAddress
);
751 if (NT_SUCCESS(Status
) && 0 == (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
))
753 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
754 Status
= LdrpAttachProcess();
755 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
756 if (NT_SUCCESS(Status
))
758 *BaseAddress
= Module
->DllBase
;
765 /***************************************************************************
767 * LdrFindEntryForAddress
782 LdrFindEntryForAddress(PVOID Address
,
783 PLDR_DATA_TABLE_ENTRY
*Module
)
785 PLIST_ENTRY ModuleListHead
;
787 PLDR_DATA_TABLE_ENTRY ModulePtr
;
789 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
791 if (NtCurrentPeb()->Ldr
== NULL
)
792 return(STATUS_NO_MORE_ENTRIES
);
794 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
795 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
796 Entry
= ModuleListHead
->Flink
;
797 if (Entry
== ModuleListHead
)
799 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
800 return(STATUS_NO_MORE_ENTRIES
);
803 while (Entry
!= ModuleListHead
)
805 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
807 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
809 if ((Address
>= ModulePtr
->DllBase
) &&
810 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
813 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
814 return(STATUS_SUCCESS
);
817 Entry
= Entry
->Flink
;
820 DPRINT("Failed to find module entry.\n");
822 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
823 return(STATUS_NO_MORE_ENTRIES
);
827 /***************************************************************************
829 * LdrFindEntryForName
843 LdrFindEntryForName(PUNICODE_STRING Name
,
844 PLDR_DATA_TABLE_ENTRY
*Module
,
847 PLIST_ENTRY ModuleListHead
;
849 PLDR_DATA_TABLE_ENTRY ModulePtr
;
850 BOOLEAN ContainsPath
;
851 UNICODE_STRING AdjustedName
;
854 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
856 if (NtCurrentPeb()->Ldr
== NULL
)
857 return(STATUS_NO_MORE_ENTRIES
);
859 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
860 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
861 Entry
= ModuleListHead
->Flink
;
862 if (Entry
== ModuleListHead
)
864 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
865 return(STATUS_NO_MORE_ENTRIES
);
868 // NULL is the current process
872 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
873 return(STATUS_SUCCESS
);
876 LdrAdjustDllName (&AdjustedName
, Name
, FALSE
);
878 ContainsPath
= (AdjustedName
.Length
>= 2 * sizeof(WCHAR
) && L
':' == AdjustedName
.Buffer
[1]);
879 for (i
= 0; ! ContainsPath
&& i
< AdjustedName
.Length
/ sizeof(WCHAR
); i
++)
881 ContainsPath
= L
'\\' == AdjustedName
.Buffer
[i
] ||
882 L
'/' == AdjustedName
.Buffer
[i
];
887 if ((! ContainsPath
&&
888 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
890 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
892 *Module
= LdrpLastModule
;
893 if (Ref
&& (*Module
)->LoadCount
!= 0xFFFF)
895 (*Module
)->LoadCount
++;
897 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
898 RtlFreeUnicodeString(&AdjustedName
);
899 return(STATUS_SUCCESS
);
902 while (Entry
!= ModuleListHead
)
904 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
906 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
908 if ((! ContainsPath
&&
909 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
911 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
913 *Module
= LdrpLastModule
= ModulePtr
;
914 if (Ref
&& ModulePtr
->LoadCount
!= 0xFFFF)
916 ModulePtr
->LoadCount
++;
918 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
919 RtlFreeUnicodeString(&AdjustedName
);
920 return(STATUS_SUCCESS
);
923 Entry
= Entry
->Flink
;
926 DPRINT("Failed to find dll %wZ\n", Name
);
927 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
928 RtlFreeUnicodeString(&AdjustedName
);
929 return(STATUS_NO_MORE_ENTRIES
);
932 /**********************************************************************
948 LdrFixupForward(PCHAR ForwardName
)
950 CHAR NameBuffer
[128];
951 UNICODE_STRING DllName
;
954 PLDR_DATA_TABLE_ENTRY Module
;
957 strcpy(NameBuffer
, ForwardName
);
958 p
= strchr(NameBuffer
, '.');
963 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
964 RtlCreateUnicodeStringFromAsciiz (&DllName
,
967 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
969 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
971 if (!NT_SUCCESS(Status
))
973 Status
= LdrLoadDll(NULL
,
974 LDRP_PROCESS_CREATION_TIME
,
977 if (NT_SUCCESS(Status
))
979 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
982 RtlFreeUnicodeString (&DllName
);
983 if (!NT_SUCCESS(Status
))
985 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
989 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
991 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
998 /**********************************************************************
1000 * LdrGetExportByOrdinal
1014 LdrGetExportByOrdinal (
1019 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1020 ULONG ExportDirSize
;
1021 PDWORD
* ExFunctions
;
1024 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1025 RtlImageDirectoryEntryToData (BaseAddress
,
1027 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1031 ExFunctions
= (PDWORD
*)
1034 ExportDir
->AddressOfFunctions
1037 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1039 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1042 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1043 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1046 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1047 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1049 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1050 Function
= LdrFixupForward((PCHAR
)Function
);
1057 /**********************************************************************
1059 * LdrGetExportByName
1070 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1071 * both with NumberOfNames entries.
1075 LdrGetExportByName(PVOID BaseAddress
,
1079 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1080 PDWORD
* ExFunctions
;
1082 USHORT
* ExOrdinals
;
1087 ULONG ExportDirSize
;
1089 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1091 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1092 RtlImageDirectoryEntryToData(BaseAddress
,
1094 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1096 if (ExportDir
== NULL
)
1098 DPRINT1("LdrGetExportByName(): no export directory!\n");
1103 //The symbol names may be missing entirely
1104 if (ExportDir
->AddressOfNames
== 0)
1106 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1111 * Get header pointers
1113 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1114 ExportDir
->AddressOfNames
);
1115 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1116 ExportDir
->AddressOfNameOrdinals
);
1117 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1118 ExportDir
->AddressOfFunctions
);
1121 * Check the hint first
1123 if (Hint
< ExportDir
->NumberOfNames
)
1125 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1126 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1128 Ordinal
= ExOrdinals
[Hint
];
1129 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1130 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1131 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1133 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1134 Function
= LdrFixupForward((PCHAR
)Function
);
1135 if (Function
== NULL
)
1137 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1141 if (Function
!= NULL
)
1150 maxn
= ExportDir
->NumberOfNames
- 1;
1151 while (minn
<= maxn
)
1156 mid
= (minn
+ maxn
) / 2;
1158 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1159 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1162 Ordinal
= ExOrdinals
[mid
];
1163 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1164 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1165 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1167 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1168 Function
= LdrFixupForward((PCHAR
)Function
);
1169 if (Function
== NULL
)
1171 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1175 if (Function
!= NULL
)
1178 else if (minn
== maxn
)
1180 DPRINT("LdrGetExportByName(): binary search failed\n");
1193 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1198 /**********************************************************************
1200 * LdrPerformRelocations
1203 * Relocate a DLL's memory image.
1215 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1218 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1219 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1220 ULONG Count
, ProtectSize
, OldProtect
, OldProtect2
;
1221 PVOID Page
, ProtectPage
, ProtectPage2
;
1226 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1228 return STATUS_UNSUCCESSFUL
;
1232 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1234 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1236 return STATUS_SUCCESS
;
1239 ProtectSize
= PAGE_SIZE
;
1240 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1241 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1242 RelocationDDir
->VirtualAddress
);
1243 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1244 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1246 while (RelocationDir
< RelocationEnd
&&
1247 RelocationDir
->SizeOfBlock
> 0)
1249 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1251 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1252 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1254 /* Unprotect the page(s) we're about to relocate. */
1256 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1261 if (!NT_SUCCESS(Status
))
1263 DPRINT1("Failed to unprotect relocation target.\n");
1267 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1268 NTHeaders
->OptionalHeader
.SizeOfImage
)
1270 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1271 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1276 if (!NT_SUCCESS(Status
))
1278 DPRINT1("Failed to unprotect relocation target (2).\n");
1279 NtProtectVirtualMemory(NtCurrentProcess(),
1289 ProtectPage2
= NULL
;
1292 RelocationDir
= LdrProcessRelocationBlock(Page
,
1296 if (RelocationDir
== NULL
)
1297 return STATUS_UNSUCCESSFUL
;
1299 /* Restore old page protection. */
1300 NtProtectVirtualMemory(NtCurrentProcess(),
1306 if (ProtectPage2
!= NULL
)
1308 NtProtectVirtualMemory(NtCurrentProcess(),
1316 return STATUS_SUCCESS
;
1320 LdrpGetOrLoadModule(PWCHAR SerachPath
,
1322 PLDR_DATA_TABLE_ENTRY
* Module
,
1325 UNICODE_STRING DllName
;
1328 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1330 RtlCreateUnicodeStringFromAsciiz (&DllName
, Name
);
1332 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1333 if (Load
&& !NT_SUCCESS(Status
))
1335 Status
= LdrpLoadModule(SerachPath
,
1336 NtCurrentPeb()->Ldr
->Initialized
? 0 : LDRP_PROCESS_CREATION_TIME
,
1340 if (NT_SUCCESS(Status
))
1342 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1344 if (!NT_SUCCESS(Status
))
1346 DPRINT1("failed to load %wZ\n", &DllName
);
1349 RtlFreeUnicodeString (&DllName
);
1354 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1355 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1356 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1359 PVOID
* ImportAddressList
;
1360 PULONG FunctionNameList
;
1366 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1368 return STATUS_UNSUCCESSFUL
;
1371 /* Get the import address list. */
1372 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1374 /* Get the list of functions to import. */
1375 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1377 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1381 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1384 /* Get the size of IAT. */
1386 while (FunctionNameList
[IATSize
] != 0L)
1391 /* Unprotect the region we are about to write into. */
1392 IATBase
= (PVOID
)ImportAddressList
;
1393 IATSize
*= sizeof(PVOID
*);
1394 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1399 if (!NT_SUCCESS(Status
))
1401 DPRINT1("Failed to unprotect IAT.\n");
1405 /* Walk through function list and fixup addresses. */
1406 while (*FunctionNameList
!= 0L)
1408 if ((*FunctionNameList
) & 0x80000000)
1410 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1411 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1412 if ((*ImportAddressList
) == NULL
)
1414 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1415 return STATUS_UNSUCCESSFUL
;
1420 IMAGE_IMPORT_BY_NAME
*pe_name
;
1421 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1422 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1423 if ((*ImportAddressList
) == NULL
)
1425 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1426 return STATUS_UNSUCCESSFUL
;
1429 ImportAddressList
++;
1433 /* Protect the region we are about to write into. */
1434 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1439 if (!NT_SUCCESS(Status
))
1441 DPRINT1("Failed to protect IAT.\n");
1445 return STATUS_SUCCESS
;
1449 LdrpProcessImportDirectory(
1450 PLDR_DATA_TABLE_ENTRY Module
,
1451 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1455 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1459 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1460 Module
, &Module
->BaseDllName
, ImportedName
);
1463 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1464 RtlImageDirectoryEntryToData(Module
->DllBase
,
1466 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1468 if (ImportModuleDirectory
== NULL
)
1470 return STATUS_UNSUCCESSFUL
;
1473 while (ImportModuleDirectory
->Name
)
1475 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1476 if (0 == _stricmp(Name
, ImportedName
))
1478 Status
= LdrpProcessImportDirectoryEntry(Module
,
1480 ImportModuleDirectory
);
1481 if (!NT_SUCCESS(Status
))
1486 ImportModuleDirectory
++;
1490 return STATUS_SUCCESS
;
1495 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1496 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1499 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1501 PVOID
* ImportAddressList
;
1504 PULONG FunctionNameList
;
1509 PIMAGE_NT_HEADERS NTHeaders
;
1513 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1514 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1516 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1517 RtlImageDirectoryEntryToData(Module
->DllBase
,
1519 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1521 if (ImportModuleDirectory
== NULL
)
1523 return STATUS_UNSUCCESSFUL
;
1526 while (ImportModuleDirectory
->Name
)
1528 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1529 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1532 /* Get the import address list. */
1533 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1535 /* Get the list of functions to import. */
1536 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1538 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1542 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1545 /* Get the size of IAT. */
1547 while (FunctionNameList
[IATSize
] != 0L)
1552 /* Unprotect the region we are about to write into. */
1553 IATBase
= (PVOID
)ImportAddressList
;
1554 IATSize
*= sizeof(PVOID
*);
1555 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1560 if (!NT_SUCCESS(Status
))
1562 DPRINT1("Failed to unprotect IAT.\n");
1566 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1567 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1568 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1569 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1571 /* Walk through function list and fixup addresses. */
1572 while (*FunctionNameList
!= 0L)
1574 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1576 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1578 ImportAddressList
++;
1582 /* Protect the region we are about to write into. */
1583 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1588 if (!NT_SUCCESS(Status
))
1590 DPRINT1("Failed to protect IAT.\n");
1594 ImportModuleDirectory
++;
1596 return STATUS_SUCCESS
;
1600 /**********************************************************************
1605 * Compute the entry point for every symbol the DLL imports
1606 * from other modules.
1618 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1619 IN PLDR_DATA_TABLE_ENTRY Module
)
1621 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1622 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1623 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1624 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1625 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1628 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1632 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1634 /* Check for tls data */
1635 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1636 RtlImageDirectoryEntryToData(Module
->DllBase
,
1638 IMAGE_DIRECTORY_ENTRY_TLS
,
1642 TlsSize
= TlsDirectory
->EndAddressOfRawData
1643 - TlsDirectory
->StartAddressOfRawData
1644 + TlsDirectory
->SizeOfZeroFill
;
1646 NtCurrentPeb()->Ldr
->Initialized
)
1648 TRACE_LDR("Trying to load dynamicly %wZ which contains a tls directory\n",
1649 &Module
->BaseDllName
);
1650 return STATUS_UNSUCCESSFUL
;
1654 * Process each import module.
1656 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1657 RtlImageDirectoryEntryToData(Module
->DllBase
,
1659 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1662 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1663 RtlImageDirectoryEntryToData(Module
->DllBase
,
1665 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1668 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1670 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1671 return STATUS_UNSUCCESSFUL
;
1673 if (BoundImportDescriptor
)
1675 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1677 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1678 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1680 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1681 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1682 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1683 if (!NT_SUCCESS(Status
))
1685 DPRINT1("failed to load %s\n", ImportedName
);
1688 if (Module
== ImportedModule
)
1690 LdrpDecrementLoadCount(Module
, FALSE
);
1692 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1694 TRACE_LDR("%wZ has stale binding to %wZ\n",
1695 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1696 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1697 if (!NT_SUCCESS(Status
))
1699 DPRINT1("failed to import %s\n", ImportedName
);
1705 BOOLEAN WrongForwarder
;
1706 WrongForwarder
= FALSE
;
1707 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1709 TRACE_LDR("%wZ has stale binding to %s\n",
1710 &Module
->BaseDllName
, ImportedName
);
1714 TRACE_LDR("%wZ has correct binding to %wZ\n",
1715 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1717 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1719 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1721 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1722 PCHAR ForwarderName
;
1724 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1725 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1727 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1728 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1729 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1730 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1731 if (!NT_SUCCESS(Status
))
1733 DPRINT1("failed to load %s\n", ForwarderName
);
1736 if (Module
== ImportedModule
)
1738 LdrpDecrementLoadCount(Module
, FALSE
);
1740 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1741 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1743 TRACE_LDR("%wZ has stale binding to %s\n",
1744 &Module
->BaseDllName
, ForwarderName
);
1745 WrongForwarder
= TRUE
;
1749 TRACE_LDR("%wZ has correct binding to %s\n",
1750 &Module
->BaseDllName
, ForwarderName
);
1754 if (WrongForwarder
||
1755 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1757 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1758 if (!NT_SUCCESS(Status
))
1760 DPRINT1("failed to import %s\n", ImportedName
);
1764 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1766 TRACE_LDR("Adjust imports for %s from %wZ\n",
1767 ImportedName
, &Module
->BaseDllName
);
1768 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1769 if (!NT_SUCCESS(Status
))
1771 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1775 else if (WrongForwarder
)
1779 * Update only forwarders
1781 TRACE_LDR("Stale BIND %s from %wZ\n",
1782 ImportedName
, &Module
->BaseDllName
);
1783 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1784 if (!NT_SUCCESS(Status
))
1786 DPRINT1("faild to import %s\n", ImportedName
);
1795 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1798 else if (ImportModuleDirectory
)
1800 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1802 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1803 while (ImportModuleDirectoryCurrent
->Name
)
1805 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1806 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1808 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1809 if (!NT_SUCCESS(Status
))
1811 DPRINT1("failed to load %s\n", ImportedName
);
1814 if (Module
== ImportedModule
)
1816 LdrpDecrementLoadCount(Module
, FALSE
);
1819 TRACE_LDR("Initializing imports for %wZ from %s\n",
1820 &Module
->BaseDllName
, ImportedName
);
1821 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1822 if (!NT_SUCCESS(Status
))
1824 DPRINT1("failed to import %s\n", ImportedName
);
1827 ImportModuleDirectoryCurrent
++;
1831 if (TlsDirectory
&& TlsSize
> 0)
1833 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1836 return STATUS_SUCCESS
;
1840 /**********************************************************************
1845 * 1. Relocate, if needed the EXE.
1846 * 2. Fixup any imported symbol.
1847 * 3. Compute the EXE's entry point.
1851 * Address at which the EXE's image
1855 * Handle of the section that contains
1859 * NULL on error; otherwise the entry point
1860 * to call for initializing the DLL.
1865 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
1866 * Currently the function is only used for the exe.
1868 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1869 HANDLE SectionHandle
,
1870 PLDR_DATA_TABLE_ENTRY
* Module
,
1874 PEPFUNC EntryPoint
= NULL
;
1875 PIMAGE_DOS_HEADER DosHeader
;
1876 PIMAGE_NT_HEADERS NTHeaders
;
1877 PLDR_DATA_TABLE_ENTRY tmpModule
;
1879 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
1880 ImageBase
, SectionHandle
);
1883 * Overlay DOS and WNT headers structures
1884 * to the DLL's image.
1886 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1887 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
1890 * If the base address is different from the
1891 * one the DLL is actually loaded, perform any
1894 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1896 DPRINT("LDR: Performing relocations\n");
1897 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1898 if (!NT_SUCCESS(Status
))
1900 DPRINT1("LdrPerformRelocations() failed\n");
1907 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1908 (*Module
)->SectionPointer
= SectionHandle
;
1912 Module
= &tmpModule
;
1913 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
1914 if (!NT_SUCCESS(Status
))
1920 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1922 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
1926 * If the DLL's imports symbols from other
1927 * modules, fixup the imported calls entry points.
1929 DPRINT("About to fixup imports\n");
1930 Status
= LdrFixupImports(NULL
, *Module
);
1931 if (!NT_SUCCESS(Status
))
1933 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
1936 DPRINT("Fixup done\n");
1937 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1938 Status
= LdrpInitializeTlsForProccess();
1939 if (NT_SUCCESS(Status
))
1941 Status
= LdrpAttachProcess();
1943 if (NT_SUCCESS(Status
))
1945 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
1949 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1950 if (!NT_SUCCESS(Status
))
1956 * Compute the DLL's entry point's address.
1958 DPRINT("ImageBase = %p\n", ImageBase
);
1959 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1960 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
1962 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
1963 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1965 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
1970 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
1972 IN PUNICODE_STRING Name
,
1973 PLDR_DATA_TABLE_ENTRY
*Module
,
1974 PVOID
*BaseAddress OPTIONAL
)
1976 UNICODE_STRING AdjustedName
;
1977 UNICODE_STRING FullDosName
;
1979 PLDR_DATA_TABLE_ENTRY tmpModule
;
1980 HANDLE SectionHandle
;
1983 PIMAGE_NT_HEADERS NtHeaders
;
1984 BOOLEAN MappedAsDataFile
;
1988 Module
= &tmpModule
;
1990 /* adjust the full dll name */
1991 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
1993 DPRINT("%wZ\n", &AdjustedName
);
1995 MappedAsDataFile
= FALSE
;
1996 /* Test if dll is already loaded */
1997 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
1998 if (NT_SUCCESS(Status
))
2000 RtlFreeUnicodeString(&AdjustedName
);
2001 if (NULL
!= BaseAddress
)
2003 *BaseAddress
= (*Module
)->DllBase
;
2008 /* Open or create dll image section */
2009 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2010 if (!NT_SUCCESS(Status
))
2012 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2013 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2014 MappedAsDataFile
, &SectionHandle
);
2016 if (!NT_SUCCESS(Status
))
2018 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2019 RtlFreeUnicodeString(&AdjustedName
);
2022 RtlFreeUnicodeString(&AdjustedName
);
2023 /* Map the dll into the process */
2026 Status
= NtMapViewOfSection(SectionHandle
,
2036 if (!NT_SUCCESS(Status
))
2038 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2039 RtlFreeUnicodeString(&FullDosName
);
2040 NtClose(SectionHandle
);
2043 if (NULL
!= BaseAddress
)
2045 *BaseAddress
= ImageBase
;
2047 /* Get and check the NT headers */
2048 NtHeaders
= RtlImageNtHeader(ImageBase
);
2049 if (NtHeaders
== NULL
)
2051 DPRINT1("RtlImageNtHeaders() failed\n");
2052 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2053 NtClose (SectionHandle
);
2054 RtlFreeUnicodeString(&FullDosName
);
2055 return STATUS_UNSUCCESSFUL
;
2057 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2058 if (MappedAsDataFile
)
2060 ASSERT(NULL
!= BaseAddress
);
2061 if (NULL
!= BaseAddress
)
2063 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2066 RtlFreeUnicodeString(&FullDosName
);
2067 NtClose(SectionHandle
);
2068 return STATUS_SUCCESS
;
2070 /* If the base address is different from the
2071 * one the DLL is actually loaded, perform any
2073 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2075 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2076 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2077 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2078 if (!NT_SUCCESS(Status
))
2080 DPRINT1("LdrPerformRelocations() failed\n");
2081 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2082 NtClose (SectionHandle
);
2083 RtlFreeUnicodeString(&FullDosName
);
2084 return STATUS_UNSUCCESSFUL
;
2087 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2088 (*Module
)->SectionPointer
= SectionHandle
;
2089 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2091 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2093 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2095 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2097 /* fixup the imported calls entry points */
2098 Status
= LdrFixupImports(SearchPath
, *Module
);
2099 if (!NT_SUCCESS(Status
))
2101 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2104 #if defined(DBG) || defined(KDBG)
2105 LdrpLoadUserModuleSymbols(*Module
);
2106 #endif /* DBG || KDBG */
2107 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2108 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2109 &(*Module
)->InInitializationOrderModuleList
);
2110 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2112 return STATUS_SUCCESS
;
2116 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2119 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2120 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2121 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2123 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2130 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2133 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2135 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2139 /* ?????????????????? */
2141 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2143 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2144 RtlImageDirectoryEntryToData(Module
->DllBase
,
2146 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2148 if (BoundImportDescriptor
)
2150 /* dereferencing all imported modules, use the bound import descriptor */
2151 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2152 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2154 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2155 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2156 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2157 if (!NT_SUCCESS(Status
))
2159 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2163 if (Module
!= ImportedModule
)
2165 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2166 if (!NT_SUCCESS(Status
))
2168 DPRINT1("unable to unload %s\n", ImportedName
);
2172 BoundImportDescriptorCurrent
++;
2177 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2178 RtlImageDirectoryEntryToData(Module
->DllBase
,
2180 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2182 if (ImportModuleDirectory
)
2184 /* dereferencing all imported modules, use the import descriptor */
2185 while (ImportModuleDirectory
->Name
)
2187 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2188 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2189 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2190 if (!NT_SUCCESS(Status
))
2192 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2196 if (Module
!= ImportedModule
)
2198 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2199 if (!NT_SUCCESS(Status
))
2201 DPRINT1("unable to unload %s\n", ImportedName
);
2205 ImportModuleDirectory
++;
2213 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2215 LdrpDetachProcess(FALSE
);
2218 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2220 return STATUS_SUCCESS
;
2228 LdrUnloadDll (IN PVOID BaseAddress
)
2230 PLDR_DATA_TABLE_ENTRY Module
;
2233 if (BaseAddress
== NULL
)
2234 return STATUS_SUCCESS
;
2236 if (LdrMappedAsDataFile(&BaseAddress
))
2238 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2242 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2243 if (NT_SUCCESS(Status
))
2245 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2246 Status
= LdrpUnloadModule(Module
, TRUE
);
2257 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2259 PLIST_ENTRY ModuleListHead
;
2261 PLDR_DATA_TABLE_ENTRY Module
;
2264 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2266 Status
= STATUS_DLL_NOT_FOUND
;
2267 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2268 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2269 Entry
= ModuleListHead
->Flink
;
2270 while (Entry
!= ModuleListHead
)
2272 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
2274 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2276 if (Module
->DllBase
== BaseAddress
)
2278 if (Module
->TlsIndex
== 0xFFFF)
2280 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2281 Status
= STATUS_SUCCESS
;
2285 Entry
= Entry
->Flink
;
2287 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2295 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2296 IN PULONG DllCharacteristics
,
2297 IN PUNICODE_STRING DllName
,
2298 OUT PVOID
*DllHandle
)
2300 PLDR_DATA_TABLE_ENTRY Module
;
2303 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2304 DllName
, DllPath
? DllPath
: L
"");
2306 /* NULL is the current executable */
2307 if (DllName
== NULL
)
2309 *DllHandle
= ExeModule
->DllBase
;
2310 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2311 return STATUS_SUCCESS
;
2314 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2315 if (NT_SUCCESS(Status
))
2317 *DllHandle
= Module
->DllBase
;
2318 return STATUS_SUCCESS
;
2321 DPRINT("Failed to find dll %wZ\n", DllName
);
2323 return STATUS_DLL_NOT_FOUND
;
2330 LdrAddRefDll(IN ULONG Flags
,
2331 IN PVOID BaseAddress
)
2333 PLIST_ENTRY ModuleListHead
;
2335 PLDR_DATA_TABLE_ENTRY Module
;
2338 if (Flags
& ~(LDR_PIN_MODULE
))
2340 return STATUS_INVALID_PARAMETER
;
2343 Status
= STATUS_DLL_NOT_FOUND
;
2344 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2345 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2346 Entry
= ModuleListHead
->Flink
;
2347 while (Entry
!= ModuleListHead
)
2349 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
2351 if (Module
->DllBase
== BaseAddress
)
2353 if (Flags
& LDR_PIN_MODULE
)
2355 Module
->Flags
|= LDRP_STATIC_LINK
;
2359 LdrpIncrementLoadCount(Module
,
2362 Status
= STATUS_SUCCESS
;
2365 Entry
= Entry
->Flink
;
2367 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2375 RtlPcToFileHeader(IN PVOID PcValue
,
2378 PLIST_ENTRY ModuleListHead
;
2380 PLDR_DATA_TABLE_ENTRY Module
;
2381 PVOID ImageBase
= NULL
;
2383 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2384 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2385 Entry
= ModuleListHead
->Flink
;
2386 while (Entry
!= ModuleListHead
)
2388 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
2390 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2391 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2393 ImageBase
= Module
->DllBase
;
2396 Entry
= Entry
->Flink
;
2398 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2400 *BaseOfImage
= ImageBase
;
2408 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2409 IN PANSI_STRING Name
,
2411 OUT PVOID
*ProcedureAddress
)
2413 if (Name
&& Name
->Length
)
2415 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2419 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2422 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2423 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2425 if (Name
&& Name
->Length
)
2428 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2429 if (*ProcedureAddress
!= NULL
)
2431 return STATUS_SUCCESS
;
2433 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2438 Ordinal
&= 0x0000FFFF;
2439 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2440 if (*ProcedureAddress
)
2442 return STATUS_SUCCESS
;
2444 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2446 return STATUS_PROCEDURE_NOT_FOUND
;
2449 /**********************************************************************
2454 * Unload dll's which are no longer referenced from others dll's
2465 * The loader lock must be held on enty.
2468 LdrpDetachProcess(BOOLEAN UnloadAll
)
2470 PLIST_ENTRY ModuleListHead
;
2472 PLDR_DATA_TABLE_ENTRY Module
;
2473 static ULONG CallingCount
= 0;
2475 DPRINT("LdrpDetachProcess() called for %wZ\n",
2476 &ExeModule
->BaseDllName
);
2480 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2481 Entry
= ModuleListHead
->Blink
;
2482 while (Entry
!= ModuleListHead
)
2484 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2485 if (((UnloadAll
&& Module
->LoadCount
== 0xFFFF) || Module
->LoadCount
== 0) &&
2486 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2487 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2489 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2490 if (Module
== LdrpLastModule
)
2492 LdrpLastModule
= NULL
;
2494 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2496 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2497 &Module
->BaseDllName
, Module
->EntryPoint
);
2498 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2502 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2504 Entry
= ModuleListHead
->Blink
;
2508 Entry
= Entry
->Blink
;
2512 if (CallingCount
== 1)
2514 Entry
= ModuleListHead
->Blink
;
2515 while (Entry
!= ModuleListHead
)
2517 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2518 Entry
= Entry
->Blink
;
2519 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2520 ((UnloadAll
&& Module
->LoadCount
!= 0xFFFF) || Module
->LoadCount
== 0))
2522 /* remove the module entry from the list */
2523 RemoveEntryList (&Module
->InLoadOrderModuleList
);
2524 RemoveEntryList (&Module
->InInitializationOrderModuleList
);
2526 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2527 NtClose (Module
->SectionPointer
);
2529 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2531 RtlFreeUnicodeString (&Module
->FullDllName
);
2532 RtlFreeUnicodeString (&Module
->BaseDllName
);
2534 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2539 DPRINT("LdrpDetachProcess() done\n");
2542 /**********************************************************************
2547 * Initialize all dll's which are prepered for loading
2558 * The loader lock must be held on entry.
2562 LdrpAttachProcess(VOID
)
2564 PLIST_ENTRY ModuleListHead
;
2566 PLDR_DATA_TABLE_ENTRY Module
;
2568 NTSTATUS Status
= STATUS_SUCCESS
;
2570 DPRINT("LdrpAttachProcess() called for %wZ\n",
2571 &ExeModule
->BaseDllName
);
2573 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2574 Entry
= ModuleListHead
->Flink
;
2575 while (Entry
!= ModuleListHead
)
2577 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2578 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2580 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2581 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2582 &Module
->BaseDllName
, Module
->EntryPoint
);
2583 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2586 Status
= STATUS_DLL_INIT_FAILED
;
2589 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2591 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2595 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2597 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2599 Entry
= Entry
->Flink
;
2602 DPRINT("LdrpAttachProcess() done\n");
2611 LdrShutdownProcess (VOID
)
2613 LdrpDetachProcess(TRUE
);
2614 return STATUS_SUCCESS
;
2622 LdrpAttachThread (VOID
)
2624 PLIST_ENTRY ModuleListHead
;
2626 PLDR_DATA_TABLE_ENTRY Module
;
2629 DPRINT("LdrpAttachThread() called for %wZ\n",
2630 &ExeModule
->BaseDllName
);
2632 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2634 Status
= LdrpInitializeTlsForThread();
2636 if (NT_SUCCESS(Status
))
2638 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2639 Entry
= ModuleListHead
->Flink
;
2641 while (Entry
!= ModuleListHead
)
2643 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2644 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2645 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2646 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2648 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2649 &Module
->BaseDllName
, Module
->EntryPoint
);
2650 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2652 Entry
= Entry
->Flink
;
2655 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2656 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
2657 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2660 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2662 DPRINT("LdrpAttachThread() done\n");
2672 LdrShutdownThread (VOID
)
2674 PLIST_ENTRY ModuleListHead
;
2676 PLDR_DATA_TABLE_ENTRY Module
;
2678 DPRINT("LdrShutdownThread() called for %wZ\n",
2679 &ExeModule
->BaseDllName
);
2681 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2683 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2684 Entry
= ModuleListHead
->Blink
;
2685 while (Entry
!= ModuleListHead
)
2687 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2689 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2690 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2691 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2693 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2694 &Module
->BaseDllName
, Module
->EntryPoint
);
2695 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2697 Entry
= Entry
->Blink
;
2700 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2704 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2707 DPRINT("LdrShutdownThread() done\n");
2709 return STATUS_SUCCESS
;
2713 /***************************************************************************
2715 * LdrQueryProcessModuleInformation
2730 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2731 IN ULONG Size OPTIONAL
,
2732 OUT PULONG ReturnedSize
)
2734 PLIST_ENTRY ModuleListHead
;
2736 PLDR_DATA_TABLE_ENTRY Module
;
2737 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2738 NTSTATUS Status
= STATUS_SUCCESS
;
2739 ULONG UsedSize
= sizeof(ULONG
);
2740 ANSI_STRING AnsiString
;
2743 DPRINT("LdrQueryProcessModuleInformation() called\n");
2745 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2747 if (ModuleInformation
== NULL
|| Size
== 0)
2749 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2753 ModuleInformation
->ModuleCount
= 0;
2754 ModulePtr
= &ModuleInformation
->ModuleEntry
[0];
2755 Status
= STATUS_SUCCESS
;
2758 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2759 Entry
= ModuleListHead
->Flink
;
2761 while (Entry
!= ModuleListHead
)
2763 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
);
2765 DPRINT(" Module %wZ\n",
2766 &Module
->FullDllName
);
2768 if (UsedSize
> Size
)
2770 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2772 else if (ModuleInformation
!= NULL
)
2774 ModulePtr
->Reserved
[0] = ModulePtr
->Reserved
[1] = 0; // FIXME: ??
2775 ModulePtr
->Base
= Module
->DllBase
;
2776 ModulePtr
->Size
= Module
->SizeOfImage
;
2777 ModulePtr
->Flags
= Module
->Flags
;
2778 ModulePtr
->Index
= 0; // FIXME: index ??
2779 ModulePtr
->Unknown
= 0; // FIXME: ??
2780 ModulePtr
->LoadCount
= Module
->LoadCount
;
2782 AnsiString
.Length
= 0;
2783 AnsiString
.MaximumLength
= 256;
2784 AnsiString
.Buffer
= ModulePtr
->ImageName
;
2785 RtlUnicodeStringToAnsiString(&AnsiString
,
2786 &Module
->FullDllName
,
2788 p
= strrchr(ModulePtr
->ImageName
, '\\');
2790 ModulePtr
->ModuleNameOffset
= p
- ModulePtr
->ImageName
+ 1;
2792 ModulePtr
->ModuleNameOffset
= 0;
2795 ModuleInformation
->ModuleCount
++;
2797 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2799 Entry
= Entry
->Flink
;
2802 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2804 if (ReturnedSize
!= 0)
2805 *ReturnedSize
= UsedSize
;
2807 DPRINT("LdrQueryProcessModuleInformation() done\n");
2814 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2817 PIMAGE_NT_HEADERS Header
;
2824 Header
= RtlImageNtHeader (BaseAddress
);
2828 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
2833 Ptr
= (PUSHORT
) BaseAddress
;
2834 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
2837 if (HIWORD(Sum
) != 0)
2839 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2846 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
2847 if (HIWORD(Sum
) != 0)
2849 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2853 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
2855 /* Subtract image checksum from calculated checksum. */
2856 /* fix low word of checksum */
2857 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
2859 CalcSum
-= LOWORD(HeaderSum
);
2863 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
2866 /* fix high word of checksum */
2867 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
2869 CalcSum
-= HIWORD(HeaderSum
);
2873 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
2876 /* add file length */
2877 CalcSum
+= ImageSize
;
2879 return (BOOLEAN
)(CalcSum
== HeaderSum
);
2883 * Compute size of an image as it is actually present in virt memory
2884 * (i.e. excluding NEVER_LOAD sections)
2887 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
2889 PIMAGE_SECTION_HEADER SectionHeader
;
2890 unsigned SectionIndex
;
2893 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
2894 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
2896 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
2898 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
2899 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
2901 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
2906 return ResidentSize
;
2910 /***************************************************************************
2912 * LdrVerifyImageMatchesChecksum
2927 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
2932 FILE_STANDARD_INFORMATION FileInfo
;
2933 IO_STATUS_BLOCK IoStatusBlock
;
2934 HANDLE SectionHandle
;
2940 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
2942 Status
= NtCreateSection (&SectionHandle
,
2949 if (!NT_SUCCESS(Status
))
2951 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
2957 Status
= NtMapViewOfSection (SectionHandle
,
2958 NtCurrentProcess (),
2967 if (!NT_SUCCESS(Status
))
2969 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
2970 NtClose (SectionHandle
);
2974 Status
= NtQueryInformationFile (FileHandle
,
2977 sizeof (FILE_STANDARD_INFORMATION
),
2978 FileStandardInformation
);
2979 if (!NT_SUCCESS(Status
))
2981 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
2982 NtUnmapViewOfSection (NtCurrentProcess (),
2984 NtClose (SectionHandle
);
2988 Result
= LdrpCheckImageChecksum (BaseAddress
,
2989 FileInfo
.EndOfFile
.u
.LowPart
);
2990 if (Result
== FALSE
)
2992 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
2995 NtUnmapViewOfSection (NtCurrentProcess (),
2998 NtClose (SectionHandle
);
3004 /***************************************************************************
3006 * LdrQueryImageFileExecutionOptions
3021 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3022 IN PCWSTR ValueName
,
3025 IN ULONG BufferSize
,
3026 OUT PULONG ReturnedLength OPTIONAL
)
3028 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3029 OBJECT_ATTRIBUTES ObjectAttributes
;
3030 UNICODE_STRING ValueNameString
;
3031 UNICODE_STRING KeyName
;
3032 WCHAR NameBuffer
[256];
3040 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3041 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3044 Ptr
= SubKey
->Buffer
;
3050 wcscat (NameBuffer
, Ptr
);
3051 RtlInitUnicodeString (&KeyName
,
3054 InitializeObjectAttributes (&ObjectAttributes
,
3056 OBJ_CASE_INSENSITIVE
,
3060 Status
= NtOpenKey (&KeyHandle
,
3063 if (!NT_SUCCESS(Status
))
3065 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3069 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3070 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3073 if (KeyInfo
== NULL
)
3075 NtClose (KeyHandle
);
3076 return STATUS_INSUFFICIENT_RESOURCES
;
3079 RtlInitUnicodeString (&ValueNameString
,
3081 Status
= NtQueryValueKey (KeyHandle
,
3083 KeyValuePartialInformation
,
3087 if (Status
== STATUS_BUFFER_OVERFLOW
)
3089 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3090 RtlFreeHeap (RtlGetProcessHeap(),
3093 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3096 if (KeyInfo
== NULL
)
3098 NtClose (KeyHandle
);
3099 return STATUS_INSUFFICIENT_RESOURCES
;
3102 Status
= NtQueryValueKey (KeyHandle
,
3104 KeyValuePartialInformation
,
3109 NtClose (KeyHandle
);
3111 if (!NT_SUCCESS(Status
))
3113 if (KeyInfo
!= NULL
)
3115 RtlFreeHeap (RtlGetProcessHeap(),
3122 if (KeyInfo
->Type
!= Type
)
3124 RtlFreeHeap (RtlGetProcessHeap(),
3127 return STATUS_OBJECT_TYPE_MISMATCH
;
3130 ResultSize
= BufferSize
;
3131 if (ResultSize
< KeyInfo
->DataLength
)
3133 Status
= STATUS_BUFFER_OVERFLOW
;
3137 ResultSize
= KeyInfo
->DataLength
;
3139 RtlCopyMemory (Buffer
,
3143 RtlFreeHeap (RtlGetProcessHeap(),
3147 if (ReturnedLength
!= NULL
)
3149 *ReturnedLength
= ResultSize
;
3156 PIMAGE_BASE_RELOCATION NTAPI
3157 LdrProcessRelocationBlock(IN PVOID Address
,
3159 IN PUSHORT TypeOffset
,
3168 for (i
= 0; i
< Count
; i
++)
3170 Offset
= *TypeOffset
& 0xFFF;
3171 Type
= *TypeOffset
>> 12;
3175 case IMAGE_REL_BASED_ABSOLUTE
:
3178 case IMAGE_REL_BASED_HIGH
:
3179 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3180 *ShortPtr
+= HIWORD(Delta
);
3183 case IMAGE_REL_BASED_LOW
:
3184 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3185 *ShortPtr
+= LOWORD(Delta
);
3188 case IMAGE_REL_BASED_HIGHLOW
:
3189 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3193 case IMAGE_REL_BASED_HIGHADJ
:
3194 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3196 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3203 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;