2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/ntdll/ldr/utils.c
5 * PURPOSE: Process startup for PE executables
6 * PROGRAMMERS: Jean Michault
7 * Rex Jolliff (rex@lvcablemodem.com)
12 * - Handle loading flags correctly
13 * - Handle errors correctly (unload dll's)
14 * - Implement a faster way to find modules (hash table)
18 /* INCLUDES *****************************************************************/
24 #define LDRP_PROCESS_CREATION_TIME 0x8000000
26 /* GLOBALS *******************************************************************/
30 #define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
31 #elif defined(_MSC_VER)
32 #define TRACE_LDR(args, ...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_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 BOOLEAN LdrpDllShutdownInProgress
= FALSE
;
48 static PTLS_DATA LdrpTlsArray
= NULL
;
49 static ULONG LdrpTlsCount
= 0;
50 static ULONG LdrpTlsSize
= 0;
51 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
52 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
53 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
54 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
56 /* PROTOTYPES ****************************************************************/
58 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
59 static PVOID
LdrFixupForward(PCHAR ForwardName
);
60 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
61 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
63 IN PUNICODE_STRING Name
,
64 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
65 OUT PVOID
*BaseAddress OPTIONAL
);
66 static NTSTATUS
LdrpAttachProcess(VOID
);
67 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
69 /* FUNCTIONS *****************************************************************/
71 #if defined(DBG) || defined(KDBG)
74 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule
)
85 #endif /* DBG || KDBG */
88 LdrMappedAsDataFile(PVOID
*BaseAddress
)
90 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
92 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
99 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
104 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
106 LoadCount
= Module
->LoadCount
;
107 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= 0xFFFF)
113 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
118 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
123 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
125 LoadCount
= Module
->LoadCount
;
126 if (Module
->LoadCount
!= 0xFFFF)
132 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
137 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
141 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
143 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
148 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
152 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
154 PIMAGE_TLS_CALLBACK
*TlsCallback
;
155 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== 0xFFFF)
157 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
162 TRACE_LDR("%wZ - Calling tls callback at %x\n",
163 &Module
->BaseDllName
, *TlsCallback
);
164 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
171 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
173 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
174 Module
->EntryPoint
== 0)
178 LdrpTlsCallback(Module
, dwReason
);
179 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
183 LdrpInitializeTlsForThread(VOID
)
189 PTEB Teb
= NtCurrentTeb();
191 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
193 Teb
->StaticUnicodeString
.Length
= 0;
194 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
195 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
197 if (LdrpTlsCount
> 0)
199 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
201 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
202 if (TlsPointers
== NULL
)
204 DPRINT1("failed to allocate thread tls data\n");
205 return STATUS_NO_MEMORY
;
208 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
209 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
211 TlsInfo
= LdrpTlsArray
;
212 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
214 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
215 TlsPointers
[i
] = TlsData
;
216 if (TlsInfo
->TlsDataSize
)
218 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
219 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
221 if (TlsInfo
->TlsZeroSize
)
223 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
224 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
229 DPRINT("LdrpInitializeTlsForThread() done\n");
230 return STATUS_SUCCESS
;
234 LdrpInitializeTlsForProccess(VOID
)
236 PLIST_ENTRY ModuleListHead
;
238 PLDR_DATA_TABLE_ENTRY Module
;
239 PIMAGE_TLS_DIRECTORY TlsDirectory
;
243 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
245 if (LdrpTlsCount
> 0)
247 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
249 LdrpTlsCount
* sizeof(TLS_DATA
));
250 if (LdrpTlsArray
== NULL
)
252 DPRINT1("Failed to allocate global tls data\n");
253 return STATUS_NO_MEMORY
;
256 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
257 Entry
= ModuleListHead
->Flink
;
258 while (Entry
!= ModuleListHead
)
260 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
261 if (Module
->LoadCount
== 0xFFFF &&
262 Module
->TlsIndex
!= 0xFFFF)
264 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
265 RtlImageDirectoryEntryToData(Module
->DllBase
,
267 IMAGE_DIRECTORY_ENTRY_TLS
,
269 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
270 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
271 TlsData
->StartAddressOfRawData
= (PVOID
)(ULONG_PTR
)TlsDirectory
->StartAddressOfRawData
;
272 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
273 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
274 if (TlsDirectory
->AddressOfCallBacks
)
275 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
277 TlsData
->TlsAddressOfCallBacks
= NULL
;
278 TlsData
->Module
= Module
;
280 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
281 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
282 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
283 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
284 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
285 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
286 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
287 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
291 * Is this region allways writable ?
293 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
295 Entry
= Entry
->Flink
;
299 DPRINT("LdrpInitializeTlsForProccess() done\n");
300 return STATUS_SUCCESS
;
306 OBJECT_ATTRIBUTES ObjectAttributes
;
307 UNICODE_STRING LinkTarget
;
313 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
315 /* Get handle to the 'KnownDlls' directory */
316 RtlInitUnicodeString(&Name
,
318 InitializeObjectAttributes(&ObjectAttributes
,
320 OBJ_CASE_INSENSITIVE
,
323 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
324 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
326 if (!NT_SUCCESS(Status
))
328 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
329 LdrpKnownDllsDirHandle
= NULL
;
333 /* Allocate target name string */
334 LinkTarget
.Length
= 0;
335 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
336 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
338 MAX_PATH
* sizeof(WCHAR
));
339 if (LinkTarget
.Buffer
== NULL
)
341 NtClose(LdrpKnownDllsDirHandle
);
342 LdrpKnownDllsDirHandle
= NULL
;
346 RtlInitUnicodeString(&Name
,
348 InitializeObjectAttributes(&ObjectAttributes
,
350 OBJ_CASE_INSENSITIVE
,
351 LdrpKnownDllsDirHandle
,
353 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
354 SYMBOLIC_LINK_ALL_ACCESS
,
356 if (!NT_SUCCESS(Status
))
358 RtlFreeUnicodeString(&LinkTarget
);
359 NtClose(LdrpKnownDllsDirHandle
);
360 LdrpKnownDllsDirHandle
= NULL
;
364 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
368 if (!NT_SUCCESS(Status
))
370 RtlFreeUnicodeString(&LinkTarget
);
371 NtClose(LdrpKnownDllsDirHandle
);
372 LdrpKnownDllsDirHandle
= NULL
;
375 RtlCreateUnicodeString(&LdrpKnownDllPath
,
378 RtlFreeUnicodeString(&LinkTarget
);
380 DPRINT("LdrpInitLoader() done\n");
384 /***************************************************************************
389 * Adjusts the name of a dll to a fully qualified name.
392 * FullDllName: Pointer to caller supplied storage for the fully
393 * qualified dll name.
394 * DllName: Pointer to the dll name.
395 * BaseName: TRUE: Only the file name is passed to FullDllName
396 * FALSE: The full path is preserved in FullDllName
404 * A given path is not affected by the adjustment, but the file
406 * ntdll --> ntdll.dll
408 * ntdll.xyz --> ntdll.xyz
411 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
412 PUNICODE_STRING DllName
,
415 WCHAR Buffer
[MAX_PATH
];
420 Length
= DllName
->Length
/ sizeof(WCHAR
);
424 /* get the base dll name */
425 Pointer
= DllName
->Buffer
+ Length
;
432 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
435 Length
= Extension
- Pointer
;
436 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
437 Buffer
[Length
] = L
'\0';
441 /* get the full dll name */
442 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
443 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
446 /* Build the DLL's absolute name */
447 Extension
= wcsrchr (Buffer
, L
'.');
448 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
450 /* with extension - remove dot if it's the last character */
451 if (Buffer
[Length
- 1] == L
'.')
457 /* name without extension - assume that it is .dll */
458 memmove (Buffer
+ Length
, L
".dll", 10);
461 RtlCreateUnicodeString(FullDllName
, Buffer
);
464 PLDR_DATA_TABLE_ENTRY
465 LdrAddModuleEntry(PVOID ImageBase
,
466 PIMAGE_NT_HEADERS NTHeaders
,
469 PLDR_DATA_TABLE_ENTRY Module
;
471 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
473 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
474 Module
->DllBase
= (PVOID
)ImageBase
;
475 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
476 if (Module
->EntryPoint
!= 0)
477 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
478 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
479 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
481 /* loading while app is running */
482 Module
->LoadCount
= 1;
485 * loading while app is initializing
486 * dll must not be unloaded
488 Module
->LoadCount
= 0xFFFF;
492 Module
->TlsIndex
= -1;
493 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
494 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
496 RtlCreateUnicodeString (&Module
->FullDllName
,
498 RtlCreateUnicodeString (&Module
->BaseDllName
,
499 wcsrchr(FullDosName
, L
'\\') + 1);
500 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
502 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
503 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
504 &Module
->InLoadOrderLinks
);
505 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
512 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
513 OUT PUNICODE_STRING FullDosName
,
514 OUT PHANDLE SectionHandle
)
516 OBJECT_ATTRIBUTES ObjectAttributes
;
519 DPRINT("LdrpMapKnownDll() called\n");
521 if (LdrpKnownDllsDirHandle
== NULL
)
523 DPRINT("Invalid 'KnownDlls' directory\n");
524 return STATUS_UNSUCCESSFUL
;
527 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
529 InitializeObjectAttributes(&ObjectAttributes
,
531 OBJ_CASE_INSENSITIVE
,
532 LdrpKnownDllsDirHandle
,
534 Status
= NtOpenSection(SectionHandle
,
535 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
537 if (!NT_SUCCESS(Status
))
539 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
543 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
544 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
545 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
547 FullDosName
->MaximumLength
);
548 if (FullDosName
->Buffer
== NULL
)
550 FullDosName
->Length
= 0;
551 FullDosName
->MaximumLength
= 0;
552 return STATUS_SUCCESS
;
555 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
556 wcscat(FullDosName
->Buffer
, L
"\\");
557 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
559 DPRINT("FullDosName '%wZ'\n", FullDosName
);
561 DPRINT("LdrpMapKnownDll() done\n");
563 return STATUS_SUCCESS
;
568 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
569 IN PUNICODE_STRING DllName
,
570 OUT PUNICODE_STRING FullDosName
,
571 IN BOOLEAN MapAsDataFile
,
572 OUT PHANDLE SectionHandle
)
574 WCHAR SearchPathBuffer
[MAX_PATH
];
575 WCHAR DosName
[MAX_PATH
];
576 UNICODE_STRING FullNtFileName
;
577 OBJECT_ATTRIBUTES FileObjectAttributes
;
579 char BlockBuffer
[1024];
580 PIMAGE_DOS_HEADER DosHeader
;
581 PIMAGE_NT_HEADERS NTHeaders
;
582 IO_STATUS_BLOCK IoStatusBlock
;
586 DPRINT("LdrpMapDllImageFile() called\n");
588 if (SearchPath
== NULL
)
590 /* get application running path */
592 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
594 len
= wcslen (SearchPathBuffer
);
596 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
599 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
601 wcscat (SearchPathBuffer
, L
";");
603 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
604 wcscat (SearchPathBuffer
, L
"\\system32;");
605 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
606 wcscat (SearchPathBuffer
, L
";.");
608 SearchPath
= SearchPathBuffer
;
611 if (RtlDosSearchPath_U (SearchPath
,
617 return STATUS_DLL_NOT_FOUND
;
619 if (!RtlDosPathNameToNtPathName_U (DosName
,
623 return STATUS_DLL_NOT_FOUND
;
625 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
627 InitializeObjectAttributes(&FileObjectAttributes
,
633 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
635 Status
= NtOpenFile(&FileHandle
,
636 GENERIC_READ
|SYNCHRONIZE
,
637 &FileObjectAttributes
,
640 FILE_SYNCHRONOUS_IO_NONALERT
);
641 if (!NT_SUCCESS(Status
))
643 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
644 &FullNtFileName
, Status
);
645 RtlFreeHeap (RtlGetProcessHeap (),
647 FullNtFileName
.Buffer
);
650 RtlFreeHeap (RtlGetProcessHeap (),
652 FullNtFileName
.Buffer
);
657 Status
= NtReadFile(FileHandle
,
666 if (!NT_SUCCESS(Status
))
668 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
674 * Overlay DOS and NT headers structures to the
675 * buffer with DLL's header raw data.
677 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
678 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
680 * Check it is a PE image file.
682 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
683 || (DosHeader
->e_lfanew
== 0L)
684 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
686 DPRINT("NTDLL format invalid\n");
689 return STATUS_UNSUCCESSFUL
;
694 * Create a section for dll.
696 Status
= NtCreateSection(SectionHandle
,
701 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
705 if (!NT_SUCCESS(Status
))
707 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
711 RtlCreateUnicodeString(FullDosName
,
719 /***************************************************************************
736 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
737 IN PULONG LoadFlags OPTIONAL
,
738 IN PUNICODE_STRING Name
,
739 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
742 PLDR_DATA_TABLE_ENTRY Module
;
744 PPEB Peb
= NtCurrentPeb();
746 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
748 SearchPath
? L
" from " : L
"",
749 SearchPath
? SearchPath
: L
"");
751 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
753 if (NT_SUCCESS(Status
) &&
754 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
756 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
758 RtlEnterCriticalSection(Peb
->LoaderLock
);
759 Status
= LdrpAttachProcess();
760 RtlLeaveCriticalSection(Peb
->LoaderLock
);
764 if ((!Module
) && (NT_SUCCESS(Status
)))
767 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
773 /***************************************************************************
775 * LdrFindEntryForAddress
790 LdrFindEntryForAddress(PVOID Address
,
791 PLDR_DATA_TABLE_ENTRY
*Module
)
793 PLIST_ENTRY ModuleListHead
;
795 PLDR_DATA_TABLE_ENTRY ModulePtr
;
797 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
799 if (NtCurrentPeb()->Ldr
== NULL
)
800 return(STATUS_NO_MORE_ENTRIES
);
802 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
803 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
804 Entry
= ModuleListHead
->Flink
;
805 if (Entry
== ModuleListHead
)
807 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
808 return(STATUS_NO_MORE_ENTRIES
);
811 while (Entry
!= ModuleListHead
)
813 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
815 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
817 if ((Address
>= ModulePtr
->DllBase
) &&
818 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
821 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
822 return(STATUS_SUCCESS
);
825 Entry
= Entry
->Flink
;
828 DPRINT("Failed to find module entry.\n");
830 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
831 return(STATUS_NO_MORE_ENTRIES
);
835 /***************************************************************************
837 * LdrFindEntryForName
851 LdrFindEntryForName(PUNICODE_STRING Name
,
852 PLDR_DATA_TABLE_ENTRY
*Module
,
855 PLIST_ENTRY ModuleListHead
;
857 PLDR_DATA_TABLE_ENTRY ModulePtr
;
858 BOOLEAN ContainsPath
;
859 UNICODE_STRING AdjustedName
;
862 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
864 if (NtCurrentPeb()->Ldr
== NULL
)
865 return(STATUS_NO_MORE_ENTRIES
);
867 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
868 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
869 Entry
= ModuleListHead
->Flink
;
870 if (Entry
== ModuleListHead
)
872 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
873 return(STATUS_NO_MORE_ENTRIES
);
876 // NULL is the current process
880 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
881 return(STATUS_SUCCESS
);
884 LdrAdjustDllName (&AdjustedName
, Name
, FALSE
);
886 ContainsPath
= (AdjustedName
.Length
>= 2 * sizeof(WCHAR
) && L
':' == AdjustedName
.Buffer
[1]);
887 for (i
= 0; ! ContainsPath
&& i
< AdjustedName
.Length
/ sizeof(WCHAR
); i
++)
889 ContainsPath
= L
'\\' == AdjustedName
.Buffer
[i
] ||
890 L
'/' == AdjustedName
.Buffer
[i
];
895 if ((! ContainsPath
&&
896 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
898 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
900 *Module
= LdrpLastModule
;
901 if (Ref
&& (*Module
)->LoadCount
!= 0xFFFF)
903 (*Module
)->LoadCount
++;
905 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
906 RtlFreeUnicodeString(&AdjustedName
);
907 return(STATUS_SUCCESS
);
910 while (Entry
!= ModuleListHead
)
912 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
914 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
916 if ((! ContainsPath
&&
917 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
919 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
921 *Module
= LdrpLastModule
= ModulePtr
;
922 if (Ref
&& ModulePtr
->LoadCount
!= 0xFFFF)
924 ModulePtr
->LoadCount
++;
926 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
927 RtlFreeUnicodeString(&AdjustedName
);
928 return(STATUS_SUCCESS
);
931 Entry
= Entry
->Flink
;
934 DPRINT("Failed to find dll %wZ\n", Name
);
935 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
936 RtlFreeUnicodeString(&AdjustedName
);
937 return(STATUS_NO_MORE_ENTRIES
);
940 /**********************************************************************
956 LdrFixupForward(PCHAR ForwardName
)
958 CHAR NameBuffer
[128];
959 UNICODE_STRING DllName
;
962 PLDR_DATA_TABLE_ENTRY Module
;
965 strcpy(NameBuffer
, ForwardName
);
966 p
= strchr(NameBuffer
, '.');
971 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
972 RtlCreateUnicodeStringFromAsciiz (&DllName
,
975 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
977 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
979 if (!NT_SUCCESS(Status
))
981 ULONG Flags
= LDRP_PROCESS_CREATION_TIME
;
982 Status
= LdrLoadDll(NULL
,
986 if (NT_SUCCESS(Status
))
988 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
991 RtlFreeUnicodeString (&DllName
);
992 if (!NT_SUCCESS(Status
))
994 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
998 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1000 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1007 /**********************************************************************
1009 * LdrGetExportByOrdinal
1023 LdrGetExportByOrdinal (
1028 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1029 ULONG ExportDirSize
;
1030 PDWORD
* ExFunctions
;
1033 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1034 RtlImageDirectoryEntryToData (BaseAddress
,
1036 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1040 ExFunctions
= (PDWORD
*)
1043 ExportDir
->AddressOfFunctions
1046 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1048 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1051 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1052 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1055 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1056 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1058 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1059 Function
= LdrFixupForward((PCHAR
)Function
);
1066 /**********************************************************************
1068 * LdrGetExportByName
1079 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1080 * both with NumberOfNames entries.
1084 LdrGetExportByName(PVOID BaseAddress
,
1088 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1089 PDWORD
* ExFunctions
;
1091 USHORT
* ExOrdinals
;
1096 ULONG ExportDirSize
;
1098 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1100 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1101 RtlImageDirectoryEntryToData(BaseAddress
,
1103 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1105 if (ExportDir
== NULL
)
1107 DPRINT1("LdrGetExportByName(): no export directory, "
1108 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1113 //The symbol names may be missing entirely
1114 if (ExportDir
->AddressOfNames
== 0)
1116 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1121 * Get header pointers
1123 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1124 ExportDir
->AddressOfNames
);
1125 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1126 ExportDir
->AddressOfNameOrdinals
);
1127 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1128 ExportDir
->AddressOfFunctions
);
1131 * Check the hint first
1133 if (Hint
< ExportDir
->NumberOfNames
)
1135 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1136 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1138 Ordinal
= ExOrdinals
[Hint
];
1139 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1140 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1141 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1143 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1144 Function
= LdrFixupForward((PCHAR
)Function
);
1145 if (Function
== NULL
)
1147 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1151 if (Function
!= NULL
)
1160 maxn
= ExportDir
->NumberOfNames
- 1;
1161 while (minn
<= maxn
)
1166 mid
= (minn
+ maxn
) / 2;
1168 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1169 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1172 Ordinal
= ExOrdinals
[mid
];
1173 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1174 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1175 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1177 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1178 Function
= LdrFixupForward((PCHAR
)Function
);
1179 if (Function
== NULL
)
1181 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1185 if (Function
!= NULL
)
1188 else if (minn
== maxn
)
1190 DPRINT("LdrGetExportByName(): binary search failed\n");
1203 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1208 /**********************************************************************
1210 * LdrPerformRelocations
1213 * Relocate a DLL's memory image.
1225 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1228 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1229 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1230 ULONG Count
, OldProtect
, OldProtect2
;
1232 PVOID Page
, ProtectPage
, ProtectPage2
;
1237 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1239 return STATUS_SUCCESS
;
1243 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1245 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1247 return STATUS_SUCCESS
;
1250 ProtectSize
= PAGE_SIZE
;
1251 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1252 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1253 RelocationDDir
->VirtualAddress
);
1254 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1255 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1257 while (RelocationDir
< RelocationEnd
&&
1258 RelocationDir
->SizeOfBlock
> 0)
1260 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1262 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1263 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1265 /* Unprotect the page(s) we're about to relocate. */
1267 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1272 if (!NT_SUCCESS(Status
))
1274 DPRINT1("Failed to unprotect relocation target.\n");
1278 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1279 NTHeaders
->OptionalHeader
.SizeOfImage
)
1281 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1282 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1287 if (!NT_SUCCESS(Status
))
1289 DPRINT1("Failed to unprotect relocation target (2).\n");
1290 NtProtectVirtualMemory(NtCurrentProcess(),
1300 ProtectPage2
= NULL
;
1303 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1307 if (RelocationDir
== NULL
)
1308 return STATUS_UNSUCCESSFUL
;
1310 /* Restore old page protection. */
1311 NtProtectVirtualMemory(NtCurrentProcess(),
1317 if (ProtectPage2
!= NULL
)
1319 NtProtectVirtualMemory(NtCurrentProcess(),
1327 return STATUS_SUCCESS
;
1331 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1333 PLDR_DATA_TABLE_ENTRY
* Module
,
1336 ANSI_STRING AnsiDllName
;
1337 UNICODE_STRING DllName
;
1340 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1342 RtlInitAnsiString(&AnsiDllName
, Name
);
1343 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1344 if (!NT_SUCCESS(Status
))
1349 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1350 if (Load
&& !NT_SUCCESS(Status
))
1352 Status
= LdrpLoadModule(SearchPath
,
1353 NtCurrentPeb()->Ldr
->Initialized
? 0 : LDRP_PROCESS_CREATION_TIME
,
1357 if (NT_SUCCESS(Status
))
1359 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1361 if (!NT_SUCCESS(Status
))
1363 ULONG ErrorResponse
;
1364 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1366 DPRINT1("failed to load %wZ\n", &DllName
);
1367 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1375 RtlFreeUnicodeString (&DllName
);
1380 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1382 ULONG ErrorResponse
;
1383 ULONG_PTR ErrorParameters
[2];
1384 ANSI_STRING ProcNameAnsi
;
1385 UNICODE_STRING ProcName
;
1390 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1394 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1395 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1396 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1397 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1398 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1404 RtlFreeUnicodeString(&ProcName
);
1408 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1409 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1410 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1413 PVOID
* ImportAddressList
;
1414 PULONG FunctionNameList
;
1420 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1422 return STATUS_UNSUCCESSFUL
;
1425 /* Get the import address list. */
1426 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1428 /* Get the list of functions to import. */
1429 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1431 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1435 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1438 /* Get the size of IAT. */
1440 while (FunctionNameList
[IATSize
] != 0L)
1445 /* Unprotect the region we are about to write into. */
1446 IATBase
= (PVOID
)ImportAddressList
;
1447 IATSize
*= sizeof(PVOID
*);
1448 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1453 if (!NT_SUCCESS(Status
))
1455 DPRINT1("Failed to unprotect IAT.\n");
1459 /* Walk through function list and fixup addresses. */
1460 while (*FunctionNameList
!= 0L)
1462 if ((*FunctionNameList
) & 0x80000000)
1464 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1465 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1466 if ((*ImportAddressList
) == NULL
)
1468 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1469 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1470 return STATUS_ENTRYPOINT_NOT_FOUND
;
1475 IMAGE_IMPORT_BY_NAME
*pe_name
;
1476 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1477 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1478 if ((*ImportAddressList
) == NULL
)
1480 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1481 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1482 return STATUS_ENTRYPOINT_NOT_FOUND
;
1485 ImportAddressList
++;
1489 /* Protect the region we are about to write into. */
1490 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1495 if (!NT_SUCCESS(Status
))
1497 DPRINT1("Failed to protect IAT.\n");
1501 return STATUS_SUCCESS
;
1505 LdrpProcessImportDirectory(
1506 PLDR_DATA_TABLE_ENTRY Module
,
1507 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1511 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1515 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1516 Module
, &Module
->BaseDllName
, ImportedName
);
1519 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1520 RtlImageDirectoryEntryToData(Module
->DllBase
,
1522 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1524 if (ImportModuleDirectory
== NULL
)
1526 return STATUS_UNSUCCESSFUL
;
1529 while (ImportModuleDirectory
->Name
)
1531 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1532 if (0 == _stricmp(Name
, ImportedName
))
1534 Status
= LdrpProcessImportDirectoryEntry(Module
,
1536 ImportModuleDirectory
);
1537 if (!NT_SUCCESS(Status
))
1542 ImportModuleDirectory
++;
1546 return STATUS_SUCCESS
;
1551 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1552 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1555 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1557 PVOID
* ImportAddressList
;
1560 PULONG FunctionNameList
;
1565 PIMAGE_NT_HEADERS NTHeaders
;
1569 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1570 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1572 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1573 RtlImageDirectoryEntryToData(Module
->DllBase
,
1575 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1577 if (ImportModuleDirectory
== NULL
)
1579 return STATUS_UNSUCCESSFUL
;
1582 while (ImportModuleDirectory
->Name
)
1584 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1585 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1588 /* Get the import address list. */
1589 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1591 /* Get the list of functions to import. */
1592 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1594 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1598 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1601 /* Get the size of IAT. */
1603 while (FunctionNameList
[IATSize
] != 0L)
1608 /* Unprotect the region we are about to write into. */
1609 IATBase
= (PVOID
)ImportAddressList
;
1610 IATSize
*= sizeof(PVOID
*);
1611 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1616 if (!NT_SUCCESS(Status
))
1618 DPRINT1("Failed to unprotect IAT.\n");
1622 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1623 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1624 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1625 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1627 /* Walk through function list and fixup addresses. */
1628 while (*FunctionNameList
!= 0L)
1630 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1632 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1634 ImportAddressList
++;
1638 /* Protect the region we are about to write into. */
1639 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1644 if (!NT_SUCCESS(Status
))
1646 DPRINT1("Failed to protect IAT.\n");
1650 ImportModuleDirectory
++;
1652 return STATUS_SUCCESS
;
1656 /**********************************************************************
1661 * Compute the entry point for every symbol the DLL imports
1662 * from other modules.
1674 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1675 IN PLDR_DATA_TABLE_ENTRY Module
)
1677 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1678 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1679 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1680 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1681 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1684 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1688 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1690 /* Check for tls data */
1691 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1692 RtlImageDirectoryEntryToData(Module
->DllBase
,
1694 IMAGE_DIRECTORY_ENTRY_TLS
,
1698 TlsSize
= TlsDirectory
->EndAddressOfRawData
1699 - TlsDirectory
->StartAddressOfRawData
1700 + TlsDirectory
->SizeOfZeroFill
;
1702 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1704 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1705 &Module
->BaseDllName
);
1706 TlsDirectory
= NULL
;
1711 * Process each import module.
1713 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1714 RtlImageDirectoryEntryToData(Module
->DllBase
,
1716 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1719 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1720 RtlImageDirectoryEntryToData(Module
->DllBase
,
1722 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1725 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1727 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1728 return STATUS_UNSUCCESSFUL
;
1730 if (BoundImportDescriptor
)
1732 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1734 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1735 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1737 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1738 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1739 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1740 if (!NT_SUCCESS(Status
))
1742 DPRINT1("failed to load %s\n", ImportedName
);
1745 if (Module
== ImportedModule
)
1747 LdrpDecrementLoadCount(Module
, FALSE
);
1749 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1751 TRACE_LDR("%wZ has stale binding to %wZ\n",
1752 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1753 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1754 if (!NT_SUCCESS(Status
))
1756 DPRINT1("failed to import %s\n", ImportedName
);
1762 BOOLEAN WrongForwarder
;
1763 WrongForwarder
= FALSE
;
1764 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1766 TRACE_LDR("%wZ has stale binding to %s\n",
1767 &Module
->BaseDllName
, ImportedName
);
1771 TRACE_LDR("%wZ has correct binding to %wZ\n",
1772 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1774 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1776 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1778 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1779 PCHAR ForwarderName
;
1781 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1782 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1784 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1785 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1786 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1787 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1788 if (!NT_SUCCESS(Status
))
1790 DPRINT1("failed to load %s\n", ForwarderName
);
1793 if (Module
== ImportedModule
)
1795 LdrpDecrementLoadCount(Module
, FALSE
);
1797 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1798 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1800 TRACE_LDR("%wZ has stale binding to %s\n",
1801 &Module
->BaseDllName
, ForwarderName
);
1802 WrongForwarder
= TRUE
;
1806 TRACE_LDR("%wZ has correct binding to %s\n",
1807 &Module
->BaseDllName
, ForwarderName
);
1811 if (WrongForwarder
||
1812 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1814 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1815 if (!NT_SUCCESS(Status
))
1817 DPRINT1("failed to import %s\n", ImportedName
);
1821 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1823 TRACE_LDR("Adjust imports for %s from %wZ\n",
1824 ImportedName
, &Module
->BaseDllName
);
1825 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1826 if (!NT_SUCCESS(Status
))
1828 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1832 else if (WrongForwarder
)
1836 * Update only forwarders
1838 TRACE_LDR("Stale BIND %s from %wZ\n",
1839 ImportedName
, &Module
->BaseDllName
);
1840 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1841 if (!NT_SUCCESS(Status
))
1843 DPRINT1("faild to import %s\n", ImportedName
);
1852 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1855 else if (ImportModuleDirectory
)
1857 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1859 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1860 while (ImportModuleDirectoryCurrent
->Name
)
1862 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1863 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1865 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1866 if (!NT_SUCCESS(Status
))
1868 DPRINT1("failed to load %s\n", ImportedName
);
1871 if (Module
== ImportedModule
)
1873 LdrpDecrementLoadCount(Module
, FALSE
);
1876 TRACE_LDR("Initializing imports for %wZ from %s\n",
1877 &Module
->BaseDllName
, ImportedName
);
1878 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1879 if (!NT_SUCCESS(Status
))
1881 DPRINT1("failed to import %s\n", ImportedName
);
1884 ImportModuleDirectoryCurrent
++;
1888 if (TlsDirectory
&& TlsSize
> 0)
1890 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1893 return STATUS_SUCCESS
;
1897 /**********************************************************************
1902 * 1. Relocate, if needed the EXE.
1903 * 2. Fixup any imported symbol.
1904 * 3. Compute the EXE's entry point.
1908 * Address at which the EXE's image
1912 * Handle of the section that contains
1916 * NULL on error; otherwise the entry point
1917 * to call for initializing the DLL.
1922 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
1923 * Currently the function is only used for the exe.
1925 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1926 HANDLE SectionHandle
,
1927 PLDR_DATA_TABLE_ENTRY
* Module
,
1931 PEPFUNC EntryPoint
= NULL
;
1932 PIMAGE_DOS_HEADER DosHeader
;
1933 PIMAGE_NT_HEADERS NTHeaders
;
1934 PLDR_DATA_TABLE_ENTRY tmpModule
;
1936 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
1937 ImageBase
, SectionHandle
);
1940 * Overlay DOS and WNT headers structures
1941 * to the DLL's image.
1943 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1944 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
1947 * If the base address is different from the
1948 * one the DLL is actually loaded, perform any
1951 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1953 DPRINT("LDR: Performing relocations\n");
1954 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1955 if (!NT_SUCCESS(Status
))
1957 DPRINT1("LdrPerformRelocations() failed\n");
1964 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1965 (*Module
)->SectionPointer
= SectionHandle
;
1969 Module
= &tmpModule
;
1970 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
1971 if (!NT_SUCCESS(Status
))
1977 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1979 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
1983 * If the DLL's imports symbols from other
1984 * modules, fixup the imported calls entry points.
1986 DPRINT("About to fixup imports\n");
1987 Status
= LdrFixupImports(NULL
, *Module
);
1988 if (!NT_SUCCESS(Status
))
1990 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
1993 DPRINT("Fixup done\n");
1994 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1995 Status
= LdrpInitializeTlsForProccess();
1996 if (NT_SUCCESS(Status
))
1998 Status
= LdrpAttachProcess();
2000 if (NT_SUCCESS(Status
))
2002 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2006 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2007 if (!NT_SUCCESS(Status
))
2013 * Compute the DLL's entry point's address.
2015 DPRINT("ImageBase = %p\n", ImageBase
);
2016 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2017 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2019 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2020 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2022 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2027 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2029 IN PUNICODE_STRING Name
,
2030 PLDR_DATA_TABLE_ENTRY
*Module
,
2031 PVOID
*BaseAddress OPTIONAL
)
2033 UNICODE_STRING AdjustedName
;
2034 UNICODE_STRING FullDosName
;
2036 PLDR_DATA_TABLE_ENTRY tmpModule
;
2037 HANDLE SectionHandle
;
2040 PIMAGE_NT_HEADERS NtHeaders
;
2041 BOOLEAN MappedAsDataFile
;
2042 PVOID ArbitraryUserPointer
;
2046 Module
= &tmpModule
;
2048 /* adjust the full dll name */
2049 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2051 DPRINT("%wZ\n", &AdjustedName
);
2053 MappedAsDataFile
= FALSE
;
2054 /* Test if dll is already loaded */
2055 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2056 if (NT_SUCCESS(Status
))
2058 RtlFreeUnicodeString(&AdjustedName
);
2059 if (NULL
!= BaseAddress
)
2061 *BaseAddress
= (*Module
)->DllBase
;
2066 /* Open or create dll image section */
2067 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2068 if (!NT_SUCCESS(Status
))
2070 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2071 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2072 MappedAsDataFile
, &SectionHandle
);
2074 if (!NT_SUCCESS(Status
))
2076 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2077 RtlFreeUnicodeString(&AdjustedName
);
2080 RtlFreeUnicodeString(&AdjustedName
);
2081 /* Map the dll into the process */
2084 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2085 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2086 Status
= NtMapViewOfSection(SectionHandle
,
2096 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2097 if (!NT_SUCCESS(Status
))
2099 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2100 RtlFreeUnicodeString(&FullDosName
);
2101 NtClose(SectionHandle
);
2104 if (NULL
!= BaseAddress
)
2106 *BaseAddress
= ImageBase
;
2108 if (!MappedAsDataFile
)
2110 /* Get and check the NT headers */
2111 NtHeaders
= RtlImageNtHeader(ImageBase
);
2112 if (NtHeaders
== NULL
)
2114 DPRINT1("RtlImageNtHeaders() failed\n");
2115 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2116 NtClose (SectionHandle
);
2117 RtlFreeUnicodeString(&FullDosName
);
2118 return STATUS_UNSUCCESSFUL
;
2121 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2122 if (MappedAsDataFile
)
2124 ASSERT(NULL
!= BaseAddress
);
2125 if (NULL
!= BaseAddress
)
2127 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2130 RtlFreeUnicodeString(&FullDosName
);
2131 NtClose(SectionHandle
);
2132 return STATUS_SUCCESS
;
2134 /* If the base address is different from the
2135 * one the DLL is actually loaded, perform any
2137 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2139 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2140 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2141 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2142 if (!NT_SUCCESS(Status
))
2144 DPRINT1("LdrPerformRelocations() failed\n");
2145 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2146 NtClose (SectionHandle
);
2147 RtlFreeUnicodeString(&FullDosName
);
2148 return STATUS_UNSUCCESSFUL
;
2151 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2152 (*Module
)->SectionPointer
= SectionHandle
;
2153 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2155 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2157 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2159 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2161 /* fixup the imported calls entry points */
2162 Status
= LdrFixupImports(SearchPath
, *Module
);
2163 if (!NT_SUCCESS(Status
))
2165 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2168 #if defined(DBG) || defined(KDBG)
2169 LdrpLoadUserModuleSymbols(*Module
);
2170 #endif /* DBG || KDBG */
2171 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2172 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2173 &(*Module
)->InInitializationOrderModuleList
);
2174 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2176 return STATUS_SUCCESS
;
2180 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2183 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2184 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2185 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2187 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2194 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2197 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2199 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2203 /* ?????????????????? */
2205 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2207 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2208 RtlImageDirectoryEntryToData(Module
->DllBase
,
2210 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2212 if (BoundImportDescriptor
)
2214 /* dereferencing all imported modules, use the bound import descriptor */
2215 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2216 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2218 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2219 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2220 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2221 if (!NT_SUCCESS(Status
))
2223 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2227 if (Module
!= ImportedModule
)
2229 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2230 if (!NT_SUCCESS(Status
))
2232 DPRINT1("unable to unload %s\n", ImportedName
);
2236 BoundImportDescriptorCurrent
++;
2241 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2242 RtlImageDirectoryEntryToData(Module
->DllBase
,
2244 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2246 if (ImportModuleDirectory
)
2248 /* dereferencing all imported modules, use the import descriptor */
2249 while (ImportModuleDirectory
->Name
)
2251 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2252 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2253 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2254 if (!NT_SUCCESS(Status
))
2256 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2260 if (Module
!= ImportedModule
)
2262 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2263 if (!NT_SUCCESS(Status
))
2265 DPRINT1("unable to unload %s\n", ImportedName
);
2269 ImportModuleDirectory
++;
2277 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2279 LdrpDetachProcess(FALSE
);
2282 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2284 return STATUS_SUCCESS
;
2292 LdrUnloadDll (IN PVOID BaseAddress
)
2294 PLDR_DATA_TABLE_ENTRY Module
;
2297 if (BaseAddress
== NULL
)
2298 return STATUS_SUCCESS
;
2300 if (LdrMappedAsDataFile(&BaseAddress
))
2302 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2306 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2307 if (NT_SUCCESS(Status
))
2309 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2310 Status
= LdrpUnloadModule(Module
, TRUE
);
2321 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2323 PLIST_ENTRY ModuleListHead
;
2325 PLDR_DATA_TABLE_ENTRY Module
;
2328 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2330 Status
= STATUS_DLL_NOT_FOUND
;
2331 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2332 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2333 Entry
= ModuleListHead
->Flink
;
2334 while (Entry
!= ModuleListHead
)
2336 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2338 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2340 if (Module
->DllBase
== BaseAddress
)
2342 if (Module
->TlsIndex
== 0xFFFF)
2344 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2345 Status
= STATUS_SUCCESS
;
2349 Entry
= Entry
->Flink
;
2351 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2359 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2360 IN PULONG DllCharacteristics
,
2361 IN PUNICODE_STRING DllName
,
2362 OUT PVOID
*DllHandle
)
2364 PLDR_DATA_TABLE_ENTRY Module
;
2367 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2368 DllName
, DllPath
? DllPath
: L
"");
2370 /* NULL is the current executable */
2371 if (DllName
== NULL
)
2373 *DllHandle
= ExeModule
->DllBase
;
2374 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2375 return STATUS_SUCCESS
;
2378 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2379 if (NT_SUCCESS(Status
))
2381 *DllHandle
= Module
->DllBase
;
2382 return STATUS_SUCCESS
;
2385 DPRINT("Failed to find dll %wZ\n", DllName
);
2387 return STATUS_DLL_NOT_FOUND
;
2394 LdrAddRefDll(IN ULONG Flags
,
2395 IN PVOID BaseAddress
)
2397 PLIST_ENTRY ModuleListHead
;
2399 PLDR_DATA_TABLE_ENTRY Module
;
2402 if (Flags
& ~(LDR_PIN_MODULE
))
2404 return STATUS_INVALID_PARAMETER
;
2407 Status
= STATUS_DLL_NOT_FOUND
;
2408 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2409 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2410 Entry
= ModuleListHead
->Flink
;
2411 while (Entry
!= ModuleListHead
)
2413 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2415 if (Module
->DllBase
== BaseAddress
)
2417 if (Flags
& LDR_PIN_MODULE
)
2419 Module
->Flags
|= LDRP_STATIC_LINK
;
2423 LdrpIncrementLoadCount(Module
,
2426 Status
= STATUS_SUCCESS
;
2429 Entry
= Entry
->Flink
;
2431 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2439 RtlPcToFileHeader(IN PVOID PcValue
,
2442 PLIST_ENTRY ModuleListHead
;
2444 PLDR_DATA_TABLE_ENTRY Module
;
2445 PVOID ImageBase
= NULL
;
2447 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2448 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2449 Entry
= ModuleListHead
->Flink
;
2450 while (Entry
!= ModuleListHead
)
2452 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2454 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2455 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2457 ImageBase
= Module
->DllBase
;
2460 Entry
= Entry
->Flink
;
2462 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2464 *BaseOfImage
= ImageBase
;
2472 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2473 IN PANSI_STRING Name
,
2475 OUT PVOID
*ProcedureAddress
)
2477 if (Name
&& Name
->Length
)
2479 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2483 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2486 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2487 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2489 if (Name
&& Name
->Length
)
2492 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2493 if (*ProcedureAddress
!= NULL
)
2495 return STATUS_SUCCESS
;
2497 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2502 Ordinal
&= 0x0000FFFF;
2503 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2504 if (*ProcedureAddress
)
2506 return STATUS_SUCCESS
;
2508 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2510 return STATUS_PROCEDURE_NOT_FOUND
;
2513 /**********************************************************************
2518 * Unload dll's which are no longer referenced from others dll's
2529 * The loader lock must be held on enty.
2532 LdrpDetachProcess(BOOLEAN UnloadAll
)
2534 PLIST_ENTRY ModuleListHead
;
2536 PLDR_DATA_TABLE_ENTRY Module
;
2537 static ULONG CallingCount
= 0;
2539 DPRINT("LdrpDetachProcess() called for %wZ\n",
2540 &ExeModule
->BaseDllName
);
2543 LdrpDllShutdownInProgress
= TRUE
;
2547 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2548 Entry
= ModuleListHead
->Blink
;
2549 while (Entry
!= ModuleListHead
)
2551 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2552 if (((UnloadAll
&& Module
->LoadCount
== 0xFFFF) || Module
->LoadCount
== 0) &&
2553 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2554 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2556 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2557 if (Module
== LdrpLastModule
)
2559 LdrpLastModule
= NULL
;
2561 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2563 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2564 &Module
->BaseDllName
, Module
->EntryPoint
);
2565 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2569 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2571 Entry
= ModuleListHead
->Blink
;
2575 Entry
= Entry
->Blink
;
2579 if (CallingCount
== 1)
2581 Entry
= ModuleListHead
->Blink
;
2582 while (Entry
!= ModuleListHead
)
2584 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2585 Entry
= Entry
->Blink
;
2586 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2587 ((UnloadAll
&& Module
->LoadCount
!= 0xFFFF) || Module
->LoadCount
== 0))
2589 /* remove the module entry from the list */
2590 RemoveEntryList (&Module
->InLoadOrderLinks
);
2591 RemoveEntryList (&Module
->InInitializationOrderModuleList
);
2593 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2594 NtClose (Module
->SectionPointer
);
2596 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2598 RtlFreeUnicodeString (&Module
->FullDllName
);
2599 RtlFreeUnicodeString (&Module
->BaseDllName
);
2601 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2606 DPRINT("LdrpDetachProcess() done\n");
2609 /**********************************************************************
2614 * Initialize all dll's which are prepered for loading
2625 * The loader lock must be held on entry.
2629 LdrpAttachProcess(VOID
)
2631 PLIST_ENTRY ModuleListHead
;
2633 PLDR_DATA_TABLE_ENTRY Module
;
2635 NTSTATUS Status
= STATUS_SUCCESS
;
2637 DPRINT("LdrpAttachProcess() called for %wZ\n",
2638 &ExeModule
->BaseDllName
);
2640 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2641 Entry
= ModuleListHead
->Flink
;
2642 while (Entry
!= ModuleListHead
)
2644 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2645 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2647 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2648 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2649 &Module
->BaseDllName
, Module
->EntryPoint
);
2650 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2653 Status
= STATUS_DLL_INIT_FAILED
;
2656 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2658 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2662 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2664 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2666 Entry
= Entry
->Flink
;
2669 DPRINT("LdrpAttachProcess() done\n");
2678 RtlDllShutdownInProgress (VOID
)
2680 return LdrpDllShutdownInProgress
;
2687 LdrShutdownProcess (VOID
)
2689 LdrpDetachProcess(TRUE
);
2690 return STATUS_SUCCESS
;
2698 LdrpAttachThread (VOID
)
2700 PLIST_ENTRY ModuleListHead
;
2702 PLDR_DATA_TABLE_ENTRY Module
;
2705 DPRINT("LdrpAttachThread() called for %wZ\n",
2706 &ExeModule
->BaseDllName
);
2708 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2710 Status
= LdrpInitializeTlsForThread();
2712 if (NT_SUCCESS(Status
))
2714 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2715 Entry
= ModuleListHead
->Flink
;
2717 while (Entry
!= ModuleListHead
)
2719 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2720 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2721 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2722 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2724 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2725 &Module
->BaseDllName
, Module
->EntryPoint
);
2726 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2728 Entry
= Entry
->Flink
;
2731 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2732 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2733 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2736 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2738 DPRINT("LdrpAttachThread() done\n");
2748 LdrShutdownThread (VOID
)
2750 PLIST_ENTRY ModuleListHead
;
2752 PLDR_DATA_TABLE_ENTRY Module
;
2754 DPRINT("LdrShutdownThread() called for %wZ\n",
2755 &ExeModule
->BaseDllName
);
2757 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2759 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2760 Entry
= ModuleListHead
->Blink
;
2761 while (Entry
!= ModuleListHead
)
2763 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2765 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2766 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2767 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2769 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2770 &Module
->BaseDllName
, Module
->EntryPoint
);
2771 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2773 Entry
= Entry
->Blink
;
2776 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2780 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2783 DPRINT("LdrShutdownThread() done\n");
2785 return STATUS_SUCCESS
;
2789 /***************************************************************************
2791 * LdrQueryProcessModuleInformation
2806 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2807 IN ULONG Size OPTIONAL
,
2808 OUT PULONG ReturnedSize
)
2810 PLIST_ENTRY ModuleListHead
;
2812 PLDR_DATA_TABLE_ENTRY Module
;
2813 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2814 NTSTATUS Status
= STATUS_SUCCESS
;
2815 ULONG UsedSize
= sizeof(ULONG
);
2816 ANSI_STRING AnsiString
;
2819 DPRINT("LdrQueryProcessModuleInformation() called\n");
2820 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2821 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2823 if (ModuleInformation
== NULL
|| Size
== 0)
2825 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2829 ModuleInformation
->NumberOfModules
= 0;
2830 ModulePtr
= &ModuleInformation
->Modules
[0];
2831 Status
= STATUS_SUCCESS
;
2834 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2835 Entry
= ModuleListHead
->Flink
;
2837 while (Entry
!= ModuleListHead
)
2839 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2841 DPRINT(" Module %wZ\n",
2842 &Module
->FullDllName
);
2844 if (UsedSize
> Size
)
2846 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2848 else if (ModuleInformation
!= NULL
)
2850 ModulePtr
->Section
= 0;
2851 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2852 ModulePtr
->ImageBase
= Module
->DllBase
;
2853 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2854 ModulePtr
->Flags
= Module
->Flags
;
2855 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2856 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2857 ModulePtr
->LoadCount
= Module
->LoadCount
;
2859 AnsiString
.Length
= 0;
2860 AnsiString
.MaximumLength
= 256;
2861 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2862 RtlUnicodeStringToAnsiString(&AnsiString
,
2863 &Module
->FullDllName
,
2866 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2868 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2870 ModulePtr
->OffsetToFileName
= 0;
2873 ModuleInformation
->NumberOfModules
++;
2875 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2877 Entry
= Entry
->Flink
;
2880 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2882 if (ReturnedSize
!= 0)
2883 *ReturnedSize
= UsedSize
;
2885 DPRINT("LdrQueryProcessModuleInformation() done\n");
2892 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2895 PIMAGE_NT_HEADERS Header
;
2902 Header
= RtlImageNtHeader (BaseAddress
);
2906 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
2911 Ptr
= (PUSHORT
) BaseAddress
;
2912 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
2915 if (HIWORD(Sum
) != 0)
2917 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2924 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
2925 if (HIWORD(Sum
) != 0)
2927 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2931 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
2933 /* Subtract image checksum from calculated checksum. */
2934 /* fix low word of checksum */
2935 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
2937 CalcSum
-= LOWORD(HeaderSum
);
2941 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
2944 /* fix high word of checksum */
2945 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
2947 CalcSum
-= HIWORD(HeaderSum
);
2951 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
2954 /* add file length */
2955 CalcSum
+= ImageSize
;
2957 return (BOOLEAN
)(CalcSum
== HeaderSum
);
2961 * Compute size of an image as it is actually present in virt memory
2962 * (i.e. excluding NEVER_LOAD sections)
2965 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
2967 PIMAGE_SECTION_HEADER SectionHeader
;
2968 unsigned SectionIndex
;
2971 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
2972 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
2974 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
2976 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
2977 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
2979 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
2984 return ResidentSize
;
2988 /***************************************************************************
2990 * LdrVerifyImageMatchesChecksum
3005 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3010 FILE_STANDARD_INFORMATION FileInfo
;
3011 IO_STATUS_BLOCK IoStatusBlock
;
3012 HANDLE SectionHandle
;
3018 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3020 Status
= NtCreateSection (&SectionHandle
,
3027 if (!NT_SUCCESS(Status
))
3029 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3035 Status
= NtMapViewOfSection (SectionHandle
,
3036 NtCurrentProcess (),
3045 if (!NT_SUCCESS(Status
))
3047 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3048 NtClose (SectionHandle
);
3052 Status
= NtQueryInformationFile (FileHandle
,
3055 sizeof (FILE_STANDARD_INFORMATION
),
3056 FileStandardInformation
);
3057 if (!NT_SUCCESS(Status
))
3059 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3060 NtUnmapViewOfSection (NtCurrentProcess (),
3062 NtClose (SectionHandle
);
3066 Result
= LdrpCheckImageChecksum (BaseAddress
,
3067 FileInfo
.EndOfFile
.u
.LowPart
);
3068 if (Result
== FALSE
)
3070 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3073 NtUnmapViewOfSection (NtCurrentProcess (),
3076 NtClose (SectionHandle
);
3082 /***************************************************************************
3084 * LdrQueryImageFileExecutionOptions
3099 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3100 IN PCWSTR ValueName
,
3103 IN ULONG BufferSize
,
3104 OUT PULONG ReturnedLength OPTIONAL
)
3106 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3107 OBJECT_ATTRIBUTES ObjectAttributes
;
3108 UNICODE_STRING ValueNameString
;
3109 UNICODE_STRING KeyName
;
3110 WCHAR NameBuffer
[256];
3118 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3119 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3122 Ptr
= SubKey
->Buffer
;
3128 wcscat (NameBuffer
, Ptr
);
3129 RtlInitUnicodeString (&KeyName
,
3132 InitializeObjectAttributes (&ObjectAttributes
,
3134 OBJ_CASE_INSENSITIVE
,
3138 Status
= NtOpenKey (&KeyHandle
,
3141 if (!NT_SUCCESS(Status
))
3143 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3147 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3148 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3151 if (KeyInfo
== NULL
)
3153 NtClose (KeyHandle
);
3154 return STATUS_INSUFFICIENT_RESOURCES
;
3157 RtlInitUnicodeString (&ValueNameString
,
3159 Status
= NtQueryValueKey (KeyHandle
,
3161 KeyValuePartialInformation
,
3165 if (Status
== STATUS_BUFFER_OVERFLOW
)
3167 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3168 RtlFreeHeap (RtlGetProcessHeap(),
3171 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3174 if (KeyInfo
== NULL
)
3176 NtClose (KeyHandle
);
3177 return STATUS_INSUFFICIENT_RESOURCES
;
3180 Status
= NtQueryValueKey (KeyHandle
,
3182 KeyValuePartialInformation
,
3187 NtClose (KeyHandle
);
3189 if (!NT_SUCCESS(Status
))
3191 if (KeyInfo
!= NULL
)
3193 RtlFreeHeap (RtlGetProcessHeap(),
3200 if (KeyInfo
->Type
!= Type
)
3202 RtlFreeHeap (RtlGetProcessHeap(),
3205 return STATUS_OBJECT_TYPE_MISMATCH
;
3208 ResultSize
= BufferSize
;
3209 if (ResultSize
< KeyInfo
->DataLength
)
3211 Status
= STATUS_BUFFER_OVERFLOW
;
3215 ResultSize
= KeyInfo
->DataLength
;
3217 RtlCopyMemory (Buffer
,
3221 RtlFreeHeap (RtlGetProcessHeap(),
3225 if (ReturnedLength
!= NULL
)
3227 *ReturnedLength
= ResultSize
;
3234 PIMAGE_BASE_RELOCATION NTAPI
3235 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3237 IN PUSHORT TypeOffset
,
3246 for (i
= 0; i
< Count
; i
++)
3248 Offset
= *TypeOffset
& 0xFFF;
3249 Type
= *TypeOffset
>> 12;
3253 case IMAGE_REL_BASED_ABSOLUTE
:
3256 case IMAGE_REL_BASED_HIGH
:
3257 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3258 *ShortPtr
+= HIWORD(Delta
);
3261 case IMAGE_REL_BASED_LOW
:
3262 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3263 *ShortPtr
+= LOWORD(Delta
);
3266 case IMAGE_REL_BASED_HIGHLOW
:
3267 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3271 case IMAGE_REL_BASED_DIR64
:
3272 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3277 case IMAGE_REL_BASED_HIGHADJ
:
3278 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3280 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3287 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3292 LdrLockLoaderLock(IN ULONG Flags
,
3293 OUT PULONG Disposition OPTIONAL
,
3294 OUT PULONG Cookie OPTIONAL
)
3297 return STATUS_NOT_IMPLEMENTED
;
3302 LdrUnlockLoaderLock(IN ULONG Flags
,
3303 IN ULONG Cookie OPTIONAL
)
3306 return STATUS_NOT_IMPLEMENTED
;
3311 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)