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
25 #define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
27 /* GLOBALS *******************************************************************/
31 #define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
32 #elif defined(_MSC_VER)
33 #define TRACE_LDR(args, ...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
36 #define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
39 typedef struct _TLS_DATA
41 PVOID StartAddressOfRawData
;
44 PIMAGE_TLS_CALLBACK
*TlsAddressOfCallBacks
;
45 PLDR_DATA_TABLE_ENTRY Module
;
46 } TLS_DATA
, *PTLS_DATA
;
48 static BOOLEAN LdrpDllShutdownInProgress
= FALSE
;
49 static PTLS_DATA LdrpTlsArray
= NULL
;
50 static ULONG LdrpTlsCount
= 0;
51 static ULONG LdrpTlsSize
= 0;
52 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
53 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
54 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
55 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
57 /* PROTOTYPES ****************************************************************/
59 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
60 static PVOID
LdrFixupForward(PCHAR ForwardName
);
61 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
62 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
64 IN PUNICODE_STRING Name
,
65 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
66 OUT PVOID
*BaseAddress OPTIONAL
);
67 static NTSTATUS
LdrpAttachProcess(VOID
);
68 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
70 /* FUNCTIONS *****************************************************************/
72 #if defined(DBG) || defined(KDBG)
75 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule
)
86 #endif /* DBG || KDBG */
89 LdrMappedAsDataFile(PVOID
*BaseAddress
)
91 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
93 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
100 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
105 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
107 LoadCount
= Module
->LoadCount
;
108 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= 0xFFFF)
114 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
119 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
124 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
126 LoadCount
= Module
->LoadCount
;
127 if (Module
->LoadCount
!= 0xFFFF)
133 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
138 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
142 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
144 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
149 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
153 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
155 PIMAGE_TLS_CALLBACK
*TlsCallback
;
156 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== 0xFFFF)
158 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
163 TRACE_LDR("%wZ - Calling tls callback at %x\n",
164 &Module
->BaseDllName
, *TlsCallback
);
165 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
172 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
174 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
175 Module
->EntryPoint
== 0)
179 LdrpTlsCallback(Module
, dwReason
);
180 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
184 LdrpInitializeTlsForThread(VOID
)
190 PTEB Teb
= NtCurrentTeb();
192 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
194 Teb
->StaticUnicodeString
.Length
= 0;
195 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
196 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
198 if (LdrpTlsCount
> 0)
200 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
202 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
203 if (TlsPointers
== NULL
)
205 DPRINT1("failed to allocate thread tls data\n");
206 return STATUS_NO_MEMORY
;
209 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
210 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
212 TlsInfo
= LdrpTlsArray
;
213 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
215 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
216 TlsPointers
[i
] = TlsData
;
217 if (TlsInfo
->TlsDataSize
)
219 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
220 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
222 if (TlsInfo
->TlsZeroSize
)
224 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
225 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
230 DPRINT("LdrpInitializeTlsForThread() done\n");
231 return STATUS_SUCCESS
;
235 LdrpInitializeTlsForProccess(VOID
)
237 PLIST_ENTRY ModuleListHead
;
239 PLDR_DATA_TABLE_ENTRY Module
;
240 PIMAGE_TLS_DIRECTORY TlsDirectory
;
244 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
246 if (LdrpTlsCount
> 0)
248 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
250 LdrpTlsCount
* sizeof(TLS_DATA
));
251 if (LdrpTlsArray
== NULL
)
253 DPRINT1("Failed to allocate global tls data\n");
254 return STATUS_NO_MEMORY
;
257 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
258 Entry
= ModuleListHead
->Flink
;
259 while (Entry
!= ModuleListHead
)
261 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
262 if (Module
->LoadCount
== 0xFFFF &&
263 Module
->TlsIndex
!= 0xFFFF)
265 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
266 RtlImageDirectoryEntryToData(Module
->DllBase
,
268 IMAGE_DIRECTORY_ENTRY_TLS
,
270 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
271 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
272 TlsData
->StartAddressOfRawData
= (PVOID
)(ULONG_PTR
)TlsDirectory
->StartAddressOfRawData
;
273 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
274 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
275 if (TlsDirectory
->AddressOfCallBacks
)
276 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
278 TlsData
->TlsAddressOfCallBacks
= NULL
;
279 TlsData
->Module
= Module
;
281 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
282 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
283 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
284 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
285 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
286 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
287 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
288 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
292 * Is this region allways writable ?
294 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
296 Entry
= Entry
->Flink
;
300 DPRINT("LdrpInitializeTlsForProccess() done\n");
301 return STATUS_SUCCESS
;
307 OBJECT_ATTRIBUTES ObjectAttributes
;
308 UNICODE_STRING LinkTarget
;
314 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
316 /* Get handle to the 'KnownDlls' directory */
317 RtlInitUnicodeString(&Name
,
319 InitializeObjectAttributes(&ObjectAttributes
,
321 OBJ_CASE_INSENSITIVE
,
324 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
325 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
327 if (!NT_SUCCESS(Status
))
329 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
330 LdrpKnownDllsDirHandle
= NULL
;
334 /* Allocate target name string */
335 LinkTarget
.Length
= 0;
336 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
337 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
339 MAX_PATH
* sizeof(WCHAR
));
340 if (LinkTarget
.Buffer
== NULL
)
342 NtClose(LdrpKnownDllsDirHandle
);
343 LdrpKnownDllsDirHandle
= NULL
;
347 RtlInitUnicodeString(&Name
,
349 InitializeObjectAttributes(&ObjectAttributes
,
351 OBJ_CASE_INSENSITIVE
,
352 LdrpKnownDllsDirHandle
,
354 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
355 SYMBOLIC_LINK_ALL_ACCESS
,
357 if (!NT_SUCCESS(Status
))
359 RtlFreeUnicodeString(&LinkTarget
);
360 NtClose(LdrpKnownDllsDirHandle
);
361 LdrpKnownDllsDirHandle
= NULL
;
365 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
369 if (!NT_SUCCESS(Status
))
371 RtlFreeUnicodeString(&LinkTarget
);
372 NtClose(LdrpKnownDllsDirHandle
);
373 LdrpKnownDllsDirHandle
= NULL
;
376 RtlCreateUnicodeString(&LdrpKnownDllPath
,
379 RtlFreeUnicodeString(&LinkTarget
);
381 DPRINT("LdrpInitLoader() done\n");
385 /***************************************************************************
390 * Adjusts the name of a dll to a fully qualified name.
393 * FullDllName: Pointer to caller supplied storage for the fully
394 * qualified dll name.
395 * DllName: Pointer to the dll name.
396 * BaseName: TRUE: Only the file name is passed to FullDllName
397 * FALSE: The full path is preserved in FullDllName
405 * A given path is not affected by the adjustment, but the file
407 * ntdll --> ntdll.dll
409 * ntdll.xyz --> ntdll.xyz
412 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
413 PUNICODE_STRING DllName
,
416 WCHAR Buffer
[MAX_PATH
];
421 Length
= DllName
->Length
/ sizeof(WCHAR
);
425 /* get the base dll name */
426 Pointer
= DllName
->Buffer
+ Length
;
433 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
436 Length
= Extension
- Pointer
;
437 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
438 Buffer
[Length
] = L
'\0';
442 /* get the full dll name */
443 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
444 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
447 /* Build the DLL's absolute name */
448 Extension
= wcsrchr (Buffer
, L
'.');
449 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
451 /* with extension - remove dot if it's the last character */
452 if (Buffer
[Length
- 1] == L
'.')
458 /* name without extension - assume that it is .dll */
459 memmove (Buffer
+ Length
, L
".dll", 10);
462 RtlCreateUnicodeString(FullDllName
, Buffer
);
465 PLDR_DATA_TABLE_ENTRY
466 LdrAddModuleEntry(PVOID ImageBase
,
467 PIMAGE_NT_HEADERS NTHeaders
,
470 PLDR_DATA_TABLE_ENTRY Module
;
472 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
474 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
475 Module
->DllBase
= (PVOID
)ImageBase
;
476 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
477 if (Module
->EntryPoint
!= 0)
478 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
479 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
480 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
482 /* loading while app is running */
483 Module
->LoadCount
= 1;
486 * loading while app is initializing
487 * dll must not be unloaded
489 Module
->LoadCount
= 0xFFFF;
493 Module
->TlsIndex
= -1;
494 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
495 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
497 RtlCreateUnicodeString (&Module
->FullDllName
,
499 RtlCreateUnicodeString (&Module
->BaseDllName
,
500 wcsrchr(FullDosName
, L
'\\') + 1);
501 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
503 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
504 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
505 &Module
->InLoadOrderLinks
);
506 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
513 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
514 OUT PUNICODE_STRING FullDosName
,
515 OUT PHANDLE SectionHandle
)
517 OBJECT_ATTRIBUTES ObjectAttributes
;
520 DPRINT("LdrpMapKnownDll() called\n");
522 if (LdrpKnownDllsDirHandle
== NULL
)
524 DPRINT("Invalid 'KnownDlls' directory\n");
525 return STATUS_UNSUCCESSFUL
;
528 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
530 InitializeObjectAttributes(&ObjectAttributes
,
532 OBJ_CASE_INSENSITIVE
,
533 LdrpKnownDllsDirHandle
,
535 Status
= NtOpenSection(SectionHandle
,
536 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
538 if (!NT_SUCCESS(Status
))
540 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
544 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
545 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
546 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
548 FullDosName
->MaximumLength
);
549 if (FullDosName
->Buffer
== NULL
)
551 FullDosName
->Length
= 0;
552 FullDosName
->MaximumLength
= 0;
553 return STATUS_SUCCESS
;
556 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
557 wcscat(FullDosName
->Buffer
, L
"\\");
558 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
560 DPRINT("FullDosName '%wZ'\n", FullDosName
);
562 DPRINT("LdrpMapKnownDll() done\n");
564 return STATUS_SUCCESS
;
569 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
570 IN PUNICODE_STRING DllName
,
571 OUT PUNICODE_STRING FullDosName
,
572 IN BOOLEAN MapAsDataFile
,
573 OUT PHANDLE SectionHandle
)
575 WCHAR SearchPathBuffer
[MAX_PATH
];
576 WCHAR DosName
[MAX_PATH
];
577 UNICODE_STRING FullNtFileName
;
578 OBJECT_ATTRIBUTES FileObjectAttributes
;
580 char BlockBuffer
[1024];
581 PIMAGE_DOS_HEADER DosHeader
;
582 PIMAGE_NT_HEADERS NTHeaders
;
583 IO_STATUS_BLOCK IoStatusBlock
;
587 DPRINT("LdrpMapDllImageFile() called\n");
589 if (SearchPath
== NULL
)
591 /* get application running path */
593 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
595 len
= wcslen (SearchPathBuffer
);
597 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
600 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
602 wcscat (SearchPathBuffer
, L
";");
604 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
605 wcscat (SearchPathBuffer
, L
"\\system32;");
606 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
607 wcscat (SearchPathBuffer
, L
";.");
609 SearchPath
= SearchPathBuffer
;
612 if (RtlDosSearchPath_U (SearchPath
,
618 return STATUS_DLL_NOT_FOUND
;
620 if (!RtlDosPathNameToNtPathName_U (DosName
,
624 return STATUS_DLL_NOT_FOUND
;
626 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
628 InitializeObjectAttributes(&FileObjectAttributes
,
634 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
636 Status
= NtOpenFile(&FileHandle
,
637 GENERIC_READ
|SYNCHRONIZE
,
638 &FileObjectAttributes
,
641 FILE_SYNCHRONOUS_IO_NONALERT
);
642 if (!NT_SUCCESS(Status
))
644 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
645 &FullNtFileName
, Status
);
646 RtlFreeHeap (RtlGetProcessHeap (),
648 FullNtFileName
.Buffer
);
651 RtlFreeHeap (RtlGetProcessHeap (),
653 FullNtFileName
.Buffer
);
658 Status
= NtReadFile(FileHandle
,
667 if (!NT_SUCCESS(Status
))
669 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
675 * Overlay DOS and NT headers structures to the
676 * buffer with DLL's header raw data.
678 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
679 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
681 * Check it is a PE image file.
683 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
684 || (DosHeader
->e_lfanew
== 0L)
685 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
687 DPRINT("NTDLL format invalid\n");
690 return STATUS_UNSUCCESSFUL
;
695 * Create a section for dll.
697 Status
= NtCreateSection(SectionHandle
,
702 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
706 if (!NT_SUCCESS(Status
))
708 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
712 RtlCreateUnicodeString(FullDosName
,
720 /***************************************************************************
737 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
738 IN PULONG LoadFlags OPTIONAL
,
739 IN PUNICODE_STRING Name
,
740 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
743 PLDR_DATA_TABLE_ENTRY Module
;
745 PPEB Peb
= NtCurrentPeb();
747 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
749 SearchPath
? L
" from " : L
"",
750 SearchPath
? SearchPath
: L
"");
752 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
754 if (NT_SUCCESS(Status
) &&
755 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
757 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
759 RtlEnterCriticalSection(Peb
->LoaderLock
);
760 Status
= LdrpAttachProcess();
761 RtlLeaveCriticalSection(Peb
->LoaderLock
);
765 if ((!Module
) && (NT_SUCCESS(Status
)))
768 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
774 /***************************************************************************
776 * LdrFindEntryForAddress
791 LdrFindEntryForAddress(PVOID Address
,
792 PLDR_DATA_TABLE_ENTRY
*Module
)
794 PLIST_ENTRY ModuleListHead
;
796 PLDR_DATA_TABLE_ENTRY ModulePtr
;
798 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
800 if (NtCurrentPeb()->Ldr
== NULL
)
801 return(STATUS_NO_MORE_ENTRIES
);
803 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
804 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
805 Entry
= ModuleListHead
->Flink
;
806 if (Entry
== ModuleListHead
)
808 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
809 return(STATUS_NO_MORE_ENTRIES
);
812 while (Entry
!= ModuleListHead
)
814 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
816 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
818 if ((Address
>= ModulePtr
->DllBase
) &&
819 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
822 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
823 return(STATUS_SUCCESS
);
826 Entry
= Entry
->Flink
;
829 DPRINT("Failed to find module entry.\n");
831 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
832 return(STATUS_NO_MORE_ENTRIES
);
836 /***************************************************************************
838 * LdrFindEntryForName
852 LdrFindEntryForName(PUNICODE_STRING Name
,
853 PLDR_DATA_TABLE_ENTRY
*Module
,
856 PLIST_ENTRY ModuleListHead
;
858 PLDR_DATA_TABLE_ENTRY ModulePtr
;
859 BOOLEAN ContainsPath
;
860 UNICODE_STRING AdjustedName
;
863 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
865 if (NtCurrentPeb()->Ldr
== NULL
)
866 return(STATUS_NO_MORE_ENTRIES
);
868 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
869 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
870 Entry
= ModuleListHead
->Flink
;
871 if (Entry
== ModuleListHead
)
873 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
874 return(STATUS_NO_MORE_ENTRIES
);
877 // NULL is the current process
881 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
882 return(STATUS_SUCCESS
);
885 LdrAdjustDllName (&AdjustedName
, Name
, FALSE
);
887 ContainsPath
= (AdjustedName
.Length
>= 2 * sizeof(WCHAR
) && L
':' == AdjustedName
.Buffer
[1]);
888 for (i
= 0; ! ContainsPath
&& i
< AdjustedName
.Length
/ sizeof(WCHAR
); i
++)
890 ContainsPath
= L
'\\' == AdjustedName
.Buffer
[i
] ||
891 L
'/' == AdjustedName
.Buffer
[i
];
896 if ((! ContainsPath
&&
897 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
899 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
901 *Module
= LdrpLastModule
;
902 if (Ref
&& (*Module
)->LoadCount
!= 0xFFFF)
904 (*Module
)->LoadCount
++;
906 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
907 RtlFreeUnicodeString(&AdjustedName
);
908 return(STATUS_SUCCESS
);
911 while (Entry
!= ModuleListHead
)
913 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
915 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
917 if ((! ContainsPath
&&
918 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
920 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
922 *Module
= LdrpLastModule
= ModulePtr
;
923 if (Ref
&& ModulePtr
->LoadCount
!= 0xFFFF)
925 ModulePtr
->LoadCount
++;
927 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
928 RtlFreeUnicodeString(&AdjustedName
);
929 return(STATUS_SUCCESS
);
932 Entry
= Entry
->Flink
;
935 DPRINT("Failed to find dll %wZ\n", Name
);
936 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
937 RtlFreeUnicodeString(&AdjustedName
);
938 return(STATUS_NO_MORE_ENTRIES
);
941 /**********************************************************************
957 LdrFixupForward(PCHAR ForwardName
)
959 CHAR NameBuffer
[128];
960 UNICODE_STRING DllName
;
963 PLDR_DATA_TABLE_ENTRY Module
;
966 strcpy(NameBuffer
, ForwardName
);
967 p
= strchr(NameBuffer
, '.');
972 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
973 RtlCreateUnicodeStringFromAsciiz (&DllName
,
976 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
978 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
980 if (!NT_SUCCESS(Status
))
982 ULONG Flags
= LDRP_PROCESS_CREATION_TIME
;
983 Status
= LdrLoadDll(NULL
,
987 if (NT_SUCCESS(Status
))
989 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
992 RtlFreeUnicodeString (&DllName
);
993 if (!NT_SUCCESS(Status
))
995 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
999 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1001 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1008 /**********************************************************************
1010 * LdrGetExportByOrdinal
1024 LdrGetExportByOrdinal (
1029 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1030 ULONG ExportDirSize
;
1031 PDWORD
* ExFunctions
;
1034 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1035 RtlImageDirectoryEntryToData (BaseAddress
,
1037 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1041 ExFunctions
= (PDWORD
*)
1044 ExportDir
->AddressOfFunctions
1047 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1049 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1052 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1053 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1056 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1057 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1059 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1060 Function
= LdrFixupForward((PCHAR
)Function
);
1067 /**********************************************************************
1069 * LdrGetExportByName
1080 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1081 * both with NumberOfNames entries.
1085 LdrGetExportByName(PVOID BaseAddress
,
1089 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1090 PDWORD
* ExFunctions
;
1092 USHORT
* ExOrdinals
;
1097 ULONG ExportDirSize
;
1099 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1101 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1102 RtlImageDirectoryEntryToData(BaseAddress
,
1104 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1106 if (ExportDir
== NULL
)
1108 DPRINT1("LdrGetExportByName(): no export directory, "
1109 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1114 //The symbol names may be missing entirely
1115 if (ExportDir
->AddressOfNames
== 0)
1117 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1122 * Get header pointers
1124 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1125 ExportDir
->AddressOfNames
);
1126 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1127 ExportDir
->AddressOfNameOrdinals
);
1128 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1129 ExportDir
->AddressOfFunctions
);
1132 * Check the hint first
1134 if (Hint
< ExportDir
->NumberOfNames
)
1136 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1137 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1139 Ordinal
= ExOrdinals
[Hint
];
1140 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1141 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1142 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1144 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1145 Function
= LdrFixupForward((PCHAR
)Function
);
1146 if (Function
== NULL
)
1148 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1152 if (Function
!= NULL
)
1161 maxn
= ExportDir
->NumberOfNames
- 1;
1162 while (minn
<= maxn
)
1167 mid
= (minn
+ maxn
) / 2;
1169 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1170 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1173 Ordinal
= ExOrdinals
[mid
];
1174 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1175 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1176 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1178 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1179 Function
= LdrFixupForward((PCHAR
)Function
);
1180 if (Function
== NULL
)
1182 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1186 if (Function
!= NULL
)
1189 else if (minn
== maxn
)
1191 DPRINT("LdrGetExportByName(): binary search failed\n");
1204 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1209 /**********************************************************************
1211 * LdrPerformRelocations
1214 * Relocate a DLL's memory image.
1226 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1229 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1230 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1231 ULONG Count
, OldProtect
, OldProtect2
;
1233 PVOID Page
, ProtectPage
, ProtectPage2
;
1238 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1240 return STATUS_SUCCESS
;
1244 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1246 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1248 return STATUS_SUCCESS
;
1251 ProtectSize
= PAGE_SIZE
;
1252 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1253 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1254 RelocationDDir
->VirtualAddress
);
1255 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1256 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1258 while (RelocationDir
< RelocationEnd
&&
1259 RelocationDir
->SizeOfBlock
> 0)
1261 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1263 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1264 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1266 /* Unprotect the page(s) we're about to relocate. */
1268 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1273 if (!NT_SUCCESS(Status
))
1275 DPRINT1("Failed to unprotect relocation target.\n");
1279 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1280 NTHeaders
->OptionalHeader
.SizeOfImage
)
1282 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1283 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1288 if (!NT_SUCCESS(Status
))
1290 DPRINT1("Failed to unprotect relocation target (2).\n");
1291 NtProtectVirtualMemory(NtCurrentProcess(),
1301 ProtectPage2
= NULL
;
1304 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1308 if (RelocationDir
== NULL
)
1309 return STATUS_UNSUCCESSFUL
;
1311 /* Restore old page protection. */
1312 NtProtectVirtualMemory(NtCurrentProcess(),
1318 if (ProtectPage2
!= NULL
)
1320 NtProtectVirtualMemory(NtCurrentProcess(),
1328 return STATUS_SUCCESS
;
1332 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1334 PLDR_DATA_TABLE_ENTRY
* Module
,
1337 ANSI_STRING AnsiDllName
;
1338 UNICODE_STRING DllName
;
1341 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1343 RtlInitAnsiString(&AnsiDllName
, Name
);
1344 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1345 if (!NT_SUCCESS(Status
))
1350 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1351 if (Load
&& !NT_SUCCESS(Status
))
1353 Status
= LdrpLoadModule(SearchPath
,
1354 NtCurrentPeb()->Ldr
->Initialized
? 0 : LDRP_PROCESS_CREATION_TIME
,
1358 if (NT_SUCCESS(Status
))
1360 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1362 if (!NT_SUCCESS(Status
))
1364 ULONG ErrorResponse
;
1365 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1367 DPRINT1("failed to load %wZ\n", &DllName
);
1368 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1376 RtlFreeUnicodeString (&DllName
);
1381 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1383 ULONG ErrorResponse
;
1384 ULONG_PTR ErrorParameters
[2];
1385 ANSI_STRING ProcNameAnsi
;
1386 UNICODE_STRING ProcName
;
1391 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1395 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1396 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1397 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1398 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1399 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1405 RtlFreeUnicodeString(&ProcName
);
1409 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1410 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1411 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1414 PVOID
* ImportAddressList
;
1415 PULONG FunctionNameList
;
1421 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1423 return STATUS_UNSUCCESSFUL
;
1426 /* Get the import address list. */
1427 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1429 /* Get the list of functions to import. */
1430 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1432 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1436 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1439 /* Get the size of IAT. */
1441 while (FunctionNameList
[IATSize
] != 0L)
1446 /* Unprotect the region we are about to write into. */
1447 IATBase
= (PVOID
)ImportAddressList
;
1448 IATSize
*= sizeof(PVOID
*);
1449 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1454 if (!NT_SUCCESS(Status
))
1456 DPRINT1("Failed to unprotect IAT.\n");
1460 /* Walk through function list and fixup addresses. */
1461 while (*FunctionNameList
!= 0L)
1463 if ((*FunctionNameList
) & 0x80000000)
1465 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1466 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1467 if ((*ImportAddressList
) == NULL
)
1469 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1470 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1471 return STATUS_ENTRYPOINT_NOT_FOUND
;
1476 IMAGE_IMPORT_BY_NAME
*pe_name
;
1477 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1478 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1479 if ((*ImportAddressList
) == NULL
)
1481 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1482 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1483 return STATUS_ENTRYPOINT_NOT_FOUND
;
1486 ImportAddressList
++;
1490 /* Protect the region we are about to write into. */
1491 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1496 if (!NT_SUCCESS(Status
))
1498 DPRINT1("Failed to protect IAT.\n");
1502 return STATUS_SUCCESS
;
1506 LdrpProcessImportDirectory(
1507 PLDR_DATA_TABLE_ENTRY Module
,
1508 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1512 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1516 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1517 Module
, &Module
->BaseDllName
, ImportedName
);
1520 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1521 RtlImageDirectoryEntryToData(Module
->DllBase
,
1523 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1525 if (ImportModuleDirectory
== NULL
)
1527 return STATUS_UNSUCCESSFUL
;
1530 while (ImportModuleDirectory
->Name
)
1532 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1533 if (0 == _stricmp(Name
, ImportedName
))
1535 Status
= LdrpProcessImportDirectoryEntry(Module
,
1537 ImportModuleDirectory
);
1538 if (!NT_SUCCESS(Status
))
1543 ImportModuleDirectory
++;
1547 return STATUS_SUCCESS
;
1552 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1553 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1556 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1558 PVOID
* ImportAddressList
;
1561 PULONG FunctionNameList
;
1566 PIMAGE_NT_HEADERS NTHeaders
;
1570 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1571 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1573 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1574 RtlImageDirectoryEntryToData(Module
->DllBase
,
1576 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1578 if (ImportModuleDirectory
== NULL
)
1580 return STATUS_UNSUCCESSFUL
;
1583 while (ImportModuleDirectory
->Name
)
1585 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1586 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1589 /* Get the import address list. */
1590 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1592 /* Get the list of functions to import. */
1593 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1595 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1599 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1602 /* Get the size of IAT. */
1604 while (FunctionNameList
[IATSize
] != 0L)
1609 /* Unprotect the region we are about to write into. */
1610 IATBase
= (PVOID
)ImportAddressList
;
1611 IATSize
*= sizeof(PVOID
*);
1612 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1617 if (!NT_SUCCESS(Status
))
1619 DPRINT1("Failed to unprotect IAT.\n");
1623 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1624 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1625 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1626 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1628 /* Walk through function list and fixup addresses. */
1629 while (*FunctionNameList
!= 0L)
1631 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1633 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1635 ImportAddressList
++;
1639 /* Protect the region we are about to write into. */
1640 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1645 if (!NT_SUCCESS(Status
))
1647 DPRINT1("Failed to protect IAT.\n");
1651 ImportModuleDirectory
++;
1653 return STATUS_SUCCESS
;
1657 /**********************************************************************
1662 * Compute the entry point for every symbol the DLL imports
1663 * from other modules.
1675 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1676 IN PLDR_DATA_TABLE_ENTRY Module
)
1678 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1679 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1680 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1681 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1682 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1685 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1689 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1691 /* Check for tls data */
1692 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1693 RtlImageDirectoryEntryToData(Module
->DllBase
,
1695 IMAGE_DIRECTORY_ENTRY_TLS
,
1699 TlsSize
= TlsDirectory
->EndAddressOfRawData
1700 - TlsDirectory
->StartAddressOfRawData
1701 + TlsDirectory
->SizeOfZeroFill
;
1703 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1705 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1706 &Module
->BaseDllName
);
1707 TlsDirectory
= NULL
;
1712 * Process each import module.
1714 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1715 RtlImageDirectoryEntryToData(Module
->DllBase
,
1717 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1720 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1721 RtlImageDirectoryEntryToData(Module
->DllBase
,
1723 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1726 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1728 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1729 return STATUS_UNSUCCESSFUL
;
1731 if (BoundImportDescriptor
)
1733 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1735 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1736 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1738 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1739 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1740 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1741 if (!NT_SUCCESS(Status
))
1743 DPRINT1("failed to load %s\n", ImportedName
);
1746 if (Module
== ImportedModule
)
1748 LdrpDecrementLoadCount(Module
, FALSE
);
1750 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1752 TRACE_LDR("%wZ has stale binding to %wZ\n",
1753 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1754 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1755 if (!NT_SUCCESS(Status
))
1757 DPRINT1("failed to import %s\n", ImportedName
);
1763 BOOLEAN WrongForwarder
;
1764 WrongForwarder
= FALSE
;
1765 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1767 TRACE_LDR("%wZ has stale binding to %s\n",
1768 &Module
->BaseDllName
, ImportedName
);
1772 TRACE_LDR("%wZ has correct binding to %wZ\n",
1773 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1775 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1777 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1779 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1780 PCHAR ForwarderName
;
1782 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1783 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1785 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1786 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1787 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1788 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1789 if (!NT_SUCCESS(Status
))
1791 DPRINT1("failed to load %s\n", ForwarderName
);
1794 if (Module
== ImportedModule
)
1796 LdrpDecrementLoadCount(Module
, FALSE
);
1798 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1799 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1801 TRACE_LDR("%wZ has stale binding to %s\n",
1802 &Module
->BaseDllName
, ForwarderName
);
1803 WrongForwarder
= TRUE
;
1807 TRACE_LDR("%wZ has correct binding to %s\n",
1808 &Module
->BaseDllName
, ForwarderName
);
1812 if (WrongForwarder
||
1813 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1815 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1816 if (!NT_SUCCESS(Status
))
1818 DPRINT1("failed to import %s\n", ImportedName
);
1822 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1824 TRACE_LDR("Adjust imports for %s from %wZ\n",
1825 ImportedName
, &Module
->BaseDllName
);
1826 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1827 if (!NT_SUCCESS(Status
))
1829 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1833 else if (WrongForwarder
)
1837 * Update only forwarders
1839 TRACE_LDR("Stale BIND %s from %wZ\n",
1840 ImportedName
, &Module
->BaseDllName
);
1841 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1842 if (!NT_SUCCESS(Status
))
1844 DPRINT1("faild to import %s\n", ImportedName
);
1853 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1856 else if (ImportModuleDirectory
)
1858 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1860 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1861 while (ImportModuleDirectoryCurrent
->Name
)
1863 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1864 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1866 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1867 if (!NT_SUCCESS(Status
))
1869 DPRINT1("failed to load %s\n", ImportedName
);
1872 if (Module
== ImportedModule
)
1874 LdrpDecrementLoadCount(Module
, FALSE
);
1877 TRACE_LDR("Initializing imports for %wZ from %s\n",
1878 &Module
->BaseDllName
, ImportedName
);
1879 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1880 if (!NT_SUCCESS(Status
))
1882 DPRINT1("failed to import %s\n", ImportedName
);
1885 ImportModuleDirectoryCurrent
++;
1889 if (TlsDirectory
&& TlsSize
> 0)
1891 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1894 return STATUS_SUCCESS
;
1898 /**********************************************************************
1903 * 1. Relocate, if needed the EXE.
1904 * 2. Fixup any imported symbol.
1905 * 3. Compute the EXE's entry point.
1909 * Address at which the EXE's image
1913 * Handle of the section that contains
1917 * NULL on error; otherwise the entry point
1918 * to call for initializing the DLL.
1923 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
1924 * Currently the function is only used for the exe.
1926 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1927 HANDLE SectionHandle
,
1928 PLDR_DATA_TABLE_ENTRY
* Module
,
1932 PEPFUNC EntryPoint
= NULL
;
1933 PIMAGE_DOS_HEADER DosHeader
;
1934 PIMAGE_NT_HEADERS NTHeaders
;
1935 PLDR_DATA_TABLE_ENTRY tmpModule
;
1937 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
1938 ImageBase
, SectionHandle
);
1941 * Overlay DOS and WNT headers structures
1942 * to the DLL's image.
1944 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1945 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
1948 * If the base address is different from the
1949 * one the DLL is actually loaded, perform any
1952 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1954 DPRINT("LDR: Performing relocations\n");
1955 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1956 if (!NT_SUCCESS(Status
))
1958 DPRINT1("LdrPerformRelocations() failed\n");
1965 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1966 (*Module
)->SectionPointer
= SectionHandle
;
1970 Module
= &tmpModule
;
1971 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
1972 if (!NT_SUCCESS(Status
))
1978 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1980 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
1984 * If the DLL's imports symbols from other
1985 * modules, fixup the imported calls entry points.
1987 DPRINT("About to fixup imports\n");
1988 Status
= LdrFixupImports(NULL
, *Module
);
1989 if (!NT_SUCCESS(Status
))
1991 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
1994 DPRINT("Fixup done\n");
1995 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1996 Status
= LdrpInitializeTlsForProccess();
1997 if (NT_SUCCESS(Status
))
1999 Status
= LdrpAttachProcess();
2001 if (NT_SUCCESS(Status
))
2003 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2007 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2008 if (!NT_SUCCESS(Status
))
2014 * Compute the DLL's entry point's address.
2016 DPRINT("ImageBase = %p\n", ImageBase
);
2017 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2018 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2020 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2021 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2023 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2028 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2030 IN PUNICODE_STRING Name
,
2031 PLDR_DATA_TABLE_ENTRY
*Module
,
2032 PVOID
*BaseAddress OPTIONAL
)
2034 UNICODE_STRING AdjustedName
;
2035 UNICODE_STRING FullDosName
;
2037 PLDR_DATA_TABLE_ENTRY tmpModule
;
2038 HANDLE SectionHandle
;
2041 PIMAGE_NT_HEADERS NtHeaders
;
2042 BOOLEAN MappedAsDataFile
;
2043 PVOID ArbitraryUserPointer
;
2047 Module
= &tmpModule
;
2049 /* adjust the full dll name */
2050 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2052 DPRINT("%wZ\n", &AdjustedName
);
2054 MappedAsDataFile
= FALSE
;
2055 /* Test if dll is already loaded */
2056 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2057 if (NT_SUCCESS(Status
))
2059 RtlFreeUnicodeString(&AdjustedName
);
2060 if (NULL
!= BaseAddress
)
2062 *BaseAddress
= (*Module
)->DllBase
;
2067 /* Open or create dll image section */
2068 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2069 if (!NT_SUCCESS(Status
))
2071 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2072 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2073 MappedAsDataFile
, &SectionHandle
);
2075 if (!NT_SUCCESS(Status
))
2077 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2078 RtlFreeUnicodeString(&AdjustedName
);
2081 RtlFreeUnicodeString(&AdjustedName
);
2082 /* Map the dll into the process */
2085 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2086 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2087 Status
= NtMapViewOfSection(SectionHandle
,
2097 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2098 if (!NT_SUCCESS(Status
))
2100 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2101 RtlFreeUnicodeString(&FullDosName
);
2102 NtClose(SectionHandle
);
2105 if (NULL
!= BaseAddress
)
2107 *BaseAddress
= ImageBase
;
2109 if (!MappedAsDataFile
)
2111 /* Get and check the NT headers */
2112 NtHeaders
= RtlImageNtHeader(ImageBase
);
2113 if (NtHeaders
== NULL
)
2115 DPRINT1("RtlImageNtHeaders() failed\n");
2116 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2117 NtClose (SectionHandle
);
2118 RtlFreeUnicodeString(&FullDosName
);
2119 return STATUS_UNSUCCESSFUL
;
2122 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2123 if (MappedAsDataFile
)
2125 ASSERT(NULL
!= BaseAddress
);
2126 if (NULL
!= BaseAddress
)
2128 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2131 RtlFreeUnicodeString(&FullDosName
);
2132 NtClose(SectionHandle
);
2133 return STATUS_SUCCESS
;
2135 /* If the base address is different from the
2136 * one the DLL is actually loaded, perform any
2138 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2140 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2141 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2142 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2143 if (!NT_SUCCESS(Status
))
2145 DPRINT1("LdrPerformRelocations() failed\n");
2146 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2147 NtClose (SectionHandle
);
2148 RtlFreeUnicodeString(&FullDosName
);
2149 return STATUS_UNSUCCESSFUL
;
2152 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2153 (*Module
)->SectionPointer
= SectionHandle
;
2154 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2156 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2158 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2160 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2162 /* fixup the imported calls entry points */
2163 Status
= LdrFixupImports(SearchPath
, *Module
);
2164 if (!NT_SUCCESS(Status
))
2166 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2169 #if defined(DBG) || defined(KDBG)
2170 LdrpLoadUserModuleSymbols(*Module
);
2171 #endif /* DBG || KDBG */
2172 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2173 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2174 &(*Module
)->InInitializationOrderLinks
);
2175 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2177 return STATUS_SUCCESS
;
2181 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2184 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2185 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2186 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2188 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2195 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2198 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2200 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2204 /* ?????????????????? */
2206 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2208 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2209 RtlImageDirectoryEntryToData(Module
->DllBase
,
2211 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2213 if (BoundImportDescriptor
)
2215 /* dereferencing all imported modules, use the bound import descriptor */
2216 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2217 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2219 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2220 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2221 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2222 if (!NT_SUCCESS(Status
))
2224 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2228 if (Module
!= ImportedModule
)
2230 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2231 if (!NT_SUCCESS(Status
))
2233 DPRINT1("unable to unload %s\n", ImportedName
);
2237 BoundImportDescriptorCurrent
++;
2242 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2243 RtlImageDirectoryEntryToData(Module
->DllBase
,
2245 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2247 if (ImportModuleDirectory
)
2249 /* dereferencing all imported modules, use the import descriptor */
2250 while (ImportModuleDirectory
->Name
)
2252 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2253 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2254 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2255 if (!NT_SUCCESS(Status
))
2257 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2261 if (Module
!= ImportedModule
)
2263 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2264 if (!NT_SUCCESS(Status
))
2266 DPRINT1("unable to unload %s\n", ImportedName
);
2270 ImportModuleDirectory
++;
2278 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2280 LdrpDetachProcess(FALSE
);
2283 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2285 return STATUS_SUCCESS
;
2293 LdrUnloadDll (IN PVOID BaseAddress
)
2295 PLDR_DATA_TABLE_ENTRY Module
;
2298 if (BaseAddress
== NULL
)
2299 return STATUS_SUCCESS
;
2301 if (LdrMappedAsDataFile(&BaseAddress
))
2303 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2307 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2308 if (NT_SUCCESS(Status
))
2310 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2311 Status
= LdrpUnloadModule(Module
, TRUE
);
2322 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2324 PLIST_ENTRY ModuleListHead
;
2326 PLDR_DATA_TABLE_ENTRY Module
;
2329 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2331 Status
= STATUS_DLL_NOT_FOUND
;
2332 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2333 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2334 Entry
= ModuleListHead
->Flink
;
2335 while (Entry
!= ModuleListHead
)
2337 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2339 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2341 if (Module
->DllBase
== BaseAddress
)
2343 if (Module
->TlsIndex
== 0xFFFF)
2345 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2346 Status
= STATUS_SUCCESS
;
2350 Entry
= Entry
->Flink
;
2352 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2360 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2361 IN PULONG DllCharacteristics
,
2362 IN PUNICODE_STRING DllName
,
2363 OUT PVOID
*DllHandle
)
2365 PLDR_DATA_TABLE_ENTRY Module
;
2368 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2369 DllName
, DllPath
? DllPath
: L
"");
2371 /* NULL is the current executable */
2372 if (DllName
== NULL
)
2374 *DllHandle
= ExeModule
->DllBase
;
2375 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2376 return STATUS_SUCCESS
;
2379 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2380 if (NT_SUCCESS(Status
))
2382 *DllHandle
= Module
->DllBase
;
2383 return STATUS_SUCCESS
;
2386 DPRINT("Failed to find dll %wZ\n", DllName
);
2388 return STATUS_DLL_NOT_FOUND
;
2395 LdrAddRefDll(IN ULONG Flags
,
2396 IN PVOID BaseAddress
)
2398 PLIST_ENTRY ModuleListHead
;
2400 PLDR_DATA_TABLE_ENTRY Module
;
2403 if (Flags
& ~(LDR_PIN_MODULE
))
2405 return STATUS_INVALID_PARAMETER
;
2408 Status
= STATUS_DLL_NOT_FOUND
;
2409 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2410 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2411 Entry
= ModuleListHead
->Flink
;
2412 while (Entry
!= ModuleListHead
)
2414 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2416 if (Module
->DllBase
== BaseAddress
)
2418 if (Flags
& LDR_PIN_MODULE
)
2420 Module
->Flags
|= LDRP_STATIC_LINK
;
2424 LdrpIncrementLoadCount(Module
,
2427 Status
= STATUS_SUCCESS
;
2430 Entry
= Entry
->Flink
;
2432 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2440 RtlPcToFileHeader(IN PVOID PcValue
,
2443 PLIST_ENTRY ModuleListHead
;
2445 PLDR_DATA_TABLE_ENTRY Module
;
2446 PVOID ImageBase
= NULL
;
2448 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2449 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2450 Entry
= ModuleListHead
->Flink
;
2451 while (Entry
!= ModuleListHead
)
2453 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2455 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2456 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2458 ImageBase
= Module
->DllBase
;
2461 Entry
= Entry
->Flink
;
2463 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2465 *BaseOfImage
= ImageBase
;
2473 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2474 IN PANSI_STRING Name
,
2476 OUT PVOID
*ProcedureAddress
)
2478 if (Name
&& Name
->Length
)
2480 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2484 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2487 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2488 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2490 if (Name
&& Name
->Length
)
2493 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2494 if (*ProcedureAddress
!= NULL
)
2496 return STATUS_SUCCESS
;
2498 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2503 Ordinal
&= 0x0000FFFF;
2504 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2505 if (*ProcedureAddress
)
2507 return STATUS_SUCCESS
;
2509 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2511 return STATUS_PROCEDURE_NOT_FOUND
;
2514 /**********************************************************************
2519 * Unload dll's which are no longer referenced from others dll's
2530 * The loader lock must be held on enty.
2533 LdrpDetachProcess(BOOLEAN UnloadAll
)
2535 PLIST_ENTRY ModuleListHead
;
2537 PLDR_DATA_TABLE_ENTRY Module
;
2538 static ULONG CallingCount
= 0;
2540 DPRINT("LdrpDetachProcess() called for %wZ\n",
2541 &ExeModule
->BaseDllName
);
2544 LdrpDllShutdownInProgress
= TRUE
;
2548 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2549 Entry
= ModuleListHead
->Blink
;
2550 while (Entry
!= ModuleListHead
)
2552 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2553 if (((UnloadAll
&& Module
->LoadCount
== 0xFFFF) || Module
->LoadCount
== 0) &&
2554 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2555 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2557 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2558 if (Module
== LdrpLastModule
)
2560 LdrpLastModule
= NULL
;
2562 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2564 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2565 &Module
->BaseDllName
, Module
->EntryPoint
);
2566 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2570 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2572 Entry
= ModuleListHead
->Blink
;
2576 Entry
= Entry
->Blink
;
2580 if (CallingCount
== 1)
2582 Entry
= ModuleListHead
->Blink
;
2583 while (Entry
!= ModuleListHead
)
2585 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2586 Entry
= Entry
->Blink
;
2587 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2588 ((UnloadAll
&& Module
->LoadCount
!= 0xFFFF) || Module
->LoadCount
== 0))
2590 /* remove the module entry from the list */
2591 RemoveEntryList (&Module
->InLoadOrderLinks
);
2592 RemoveEntryList (&Module
->InInitializationOrderLinks
);
2594 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2595 NtClose (Module
->SectionPointer
);
2597 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2599 RtlFreeUnicodeString (&Module
->FullDllName
);
2600 RtlFreeUnicodeString (&Module
->BaseDllName
);
2602 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2607 DPRINT("LdrpDetachProcess() done\n");
2610 /**********************************************************************
2615 * Initialize all dll's which are prepered for loading
2626 * The loader lock must be held on entry.
2630 LdrpAttachProcess(VOID
)
2632 PLIST_ENTRY ModuleListHead
;
2634 PLDR_DATA_TABLE_ENTRY Module
;
2636 NTSTATUS Status
= STATUS_SUCCESS
;
2638 DPRINT("LdrpAttachProcess() called for %wZ\n",
2639 &ExeModule
->BaseDllName
);
2641 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2642 Entry
= ModuleListHead
->Flink
;
2643 while (Entry
!= ModuleListHead
)
2645 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2646 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2648 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2649 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2650 &Module
->BaseDllName
, Module
->EntryPoint
);
2651 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2654 Status
= STATUS_DLL_INIT_FAILED
;
2657 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2659 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2663 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2665 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2667 Entry
= Entry
->Flink
;
2670 DPRINT("LdrpAttachProcess() done\n");
2679 RtlDllShutdownInProgress (VOID
)
2681 return LdrpDllShutdownInProgress
;
2688 LdrShutdownProcess (VOID
)
2690 LdrpDetachProcess(TRUE
);
2691 return STATUS_SUCCESS
;
2699 LdrpAttachThread (VOID
)
2701 PLIST_ENTRY ModuleListHead
;
2703 PLDR_DATA_TABLE_ENTRY Module
;
2706 DPRINT("LdrpAttachThread() called for %wZ\n",
2707 &ExeModule
->BaseDllName
);
2709 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2711 Status
= LdrpInitializeTlsForThread();
2713 if (NT_SUCCESS(Status
))
2715 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2716 Entry
= ModuleListHead
->Flink
;
2718 while (Entry
!= ModuleListHead
)
2720 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2721 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2722 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2723 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2725 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2726 &Module
->BaseDllName
, Module
->EntryPoint
);
2727 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2729 Entry
= Entry
->Flink
;
2732 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2733 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2734 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2737 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2739 DPRINT("LdrpAttachThread() done\n");
2749 LdrShutdownThread (VOID
)
2751 PLIST_ENTRY ModuleListHead
;
2753 PLDR_DATA_TABLE_ENTRY Module
;
2755 DPRINT("LdrShutdownThread() called for %wZ\n",
2756 &ExeModule
->BaseDllName
);
2758 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2760 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2761 Entry
= ModuleListHead
->Blink
;
2762 while (Entry
!= ModuleListHead
)
2764 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2766 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2767 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2768 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2770 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2771 &Module
->BaseDllName
, Module
->EntryPoint
);
2772 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2774 Entry
= Entry
->Blink
;
2777 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2781 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2784 DPRINT("LdrShutdownThread() done\n");
2786 return STATUS_SUCCESS
;
2790 /***************************************************************************
2792 * LdrQueryProcessModuleInformation
2807 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2808 IN ULONG Size OPTIONAL
,
2809 OUT PULONG ReturnedSize
)
2811 PLIST_ENTRY ModuleListHead
;
2813 PLDR_DATA_TABLE_ENTRY Module
;
2814 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2815 NTSTATUS Status
= STATUS_SUCCESS
;
2816 ULONG UsedSize
= sizeof(ULONG
);
2817 ANSI_STRING AnsiString
;
2820 DPRINT("LdrQueryProcessModuleInformation() called\n");
2821 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2822 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2824 if (ModuleInformation
== NULL
|| Size
== 0)
2826 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2830 ModuleInformation
->NumberOfModules
= 0;
2831 ModulePtr
= &ModuleInformation
->Modules
[0];
2832 Status
= STATUS_SUCCESS
;
2835 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2836 Entry
= ModuleListHead
->Flink
;
2838 while (Entry
!= ModuleListHead
)
2840 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2842 DPRINT(" Module %wZ\n",
2843 &Module
->FullDllName
);
2845 if (UsedSize
> Size
)
2847 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2849 else if (ModuleInformation
!= NULL
)
2851 ModulePtr
->Section
= 0;
2852 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2853 ModulePtr
->ImageBase
= Module
->DllBase
;
2854 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2855 ModulePtr
->Flags
= Module
->Flags
;
2856 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2857 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2858 ModulePtr
->LoadCount
= Module
->LoadCount
;
2860 AnsiString
.Length
= 0;
2861 AnsiString
.MaximumLength
= 256;
2862 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2863 RtlUnicodeStringToAnsiString(&AnsiString
,
2864 &Module
->FullDllName
,
2867 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2869 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2871 ModulePtr
->OffsetToFileName
= 0;
2874 ModuleInformation
->NumberOfModules
++;
2876 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2878 Entry
= Entry
->Flink
;
2881 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2883 if (ReturnedSize
!= 0)
2884 *ReturnedSize
= UsedSize
;
2886 DPRINT("LdrQueryProcessModuleInformation() done\n");
2893 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2896 PIMAGE_NT_HEADERS Header
;
2903 Header
= RtlImageNtHeader (BaseAddress
);
2907 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
2912 Ptr
= (PUSHORT
) BaseAddress
;
2913 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
2916 if (HIWORD(Sum
) != 0)
2918 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2925 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
2926 if (HIWORD(Sum
) != 0)
2928 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2932 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
2934 /* Subtract image checksum from calculated checksum. */
2935 /* fix low word of checksum */
2936 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
2938 CalcSum
-= LOWORD(HeaderSum
);
2942 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
2945 /* fix high word of checksum */
2946 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
2948 CalcSum
-= HIWORD(HeaderSum
);
2952 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
2955 /* add file length */
2956 CalcSum
+= ImageSize
;
2958 return (BOOLEAN
)(CalcSum
== HeaderSum
);
2962 * Compute size of an image as it is actually present in virt memory
2963 * (i.e. excluding NEVER_LOAD sections)
2966 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
2968 PIMAGE_SECTION_HEADER SectionHeader
;
2969 unsigned SectionIndex
;
2972 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
2973 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
2975 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
2977 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
2978 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
2980 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
2985 return ResidentSize
;
2989 /***************************************************************************
2991 * LdrVerifyImageMatchesChecksum
3006 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3011 FILE_STANDARD_INFORMATION FileInfo
;
3012 IO_STATUS_BLOCK IoStatusBlock
;
3013 HANDLE SectionHandle
;
3019 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3021 Status
= NtCreateSection (&SectionHandle
,
3028 if (!NT_SUCCESS(Status
))
3030 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3036 Status
= NtMapViewOfSection (SectionHandle
,
3037 NtCurrentProcess (),
3046 if (!NT_SUCCESS(Status
))
3048 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3049 NtClose (SectionHandle
);
3053 Status
= NtQueryInformationFile (FileHandle
,
3056 sizeof (FILE_STANDARD_INFORMATION
),
3057 FileStandardInformation
);
3058 if (!NT_SUCCESS(Status
))
3060 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3061 NtUnmapViewOfSection (NtCurrentProcess (),
3063 NtClose (SectionHandle
);
3067 Result
= LdrpCheckImageChecksum (BaseAddress
,
3068 FileInfo
.EndOfFile
.u
.LowPart
);
3069 if (Result
== FALSE
)
3071 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3074 NtUnmapViewOfSection (NtCurrentProcess (),
3077 NtClose (SectionHandle
);
3083 /***************************************************************************
3085 * LdrQueryImageFileExecutionOptions
3100 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3101 IN PCWSTR ValueName
,
3104 IN ULONG BufferSize
,
3105 OUT PULONG ReturnedLength OPTIONAL
)
3107 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3108 OBJECT_ATTRIBUTES ObjectAttributes
;
3109 UNICODE_STRING ValueNameString
;
3110 UNICODE_STRING KeyName
;
3111 WCHAR NameBuffer
[256];
3119 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3120 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3123 Ptr
= SubKey
->Buffer
;
3129 wcscat (NameBuffer
, Ptr
);
3130 RtlInitUnicodeString (&KeyName
,
3133 InitializeObjectAttributes (&ObjectAttributes
,
3135 OBJ_CASE_INSENSITIVE
,
3139 Status
= NtOpenKey (&KeyHandle
,
3142 if (!NT_SUCCESS(Status
))
3144 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3148 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3149 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3152 if (KeyInfo
== NULL
)
3154 NtClose (KeyHandle
);
3155 return STATUS_INSUFFICIENT_RESOURCES
;
3158 RtlInitUnicodeString (&ValueNameString
,
3160 Status
= NtQueryValueKey (KeyHandle
,
3162 KeyValuePartialInformation
,
3166 if (Status
== STATUS_BUFFER_OVERFLOW
)
3168 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3169 RtlFreeHeap (RtlGetProcessHeap(),
3172 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3175 if (KeyInfo
== NULL
)
3177 NtClose (KeyHandle
);
3178 return STATUS_INSUFFICIENT_RESOURCES
;
3181 Status
= NtQueryValueKey (KeyHandle
,
3183 KeyValuePartialInformation
,
3188 NtClose (KeyHandle
);
3190 if (!NT_SUCCESS(Status
))
3192 if (KeyInfo
!= NULL
)
3194 RtlFreeHeap (RtlGetProcessHeap(),
3201 if (KeyInfo
->Type
!= Type
)
3203 RtlFreeHeap (RtlGetProcessHeap(),
3206 return STATUS_OBJECT_TYPE_MISMATCH
;
3209 ResultSize
= BufferSize
;
3210 if (ResultSize
< KeyInfo
->DataLength
)
3212 Status
= STATUS_BUFFER_OVERFLOW
;
3216 ResultSize
= KeyInfo
->DataLength
;
3218 RtlCopyMemory (Buffer
,
3222 RtlFreeHeap (RtlGetProcessHeap(),
3226 if (ReturnedLength
!= NULL
)
3228 *ReturnedLength
= ResultSize
;
3235 PIMAGE_BASE_RELOCATION NTAPI
3236 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3238 IN PUSHORT TypeOffset
,
3247 for (i
= 0; i
< Count
; i
++)
3249 Offset
= *TypeOffset
& 0xFFF;
3250 Type
= *TypeOffset
>> 12;
3254 case IMAGE_REL_BASED_ABSOLUTE
:
3257 case IMAGE_REL_BASED_HIGH
:
3258 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3259 *ShortPtr
+= HIWORD(Delta
);
3262 case IMAGE_REL_BASED_LOW
:
3263 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3264 *ShortPtr
+= LOWORD(Delta
);
3267 case IMAGE_REL_BASED_HIGHLOW
:
3268 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3272 case IMAGE_REL_BASED_DIR64
:
3273 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3278 case IMAGE_REL_BASED_HIGHADJ
:
3279 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3281 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3288 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3293 LdrLockLoaderLock(IN ULONG Flags
,
3294 OUT PULONG Disposition OPTIONAL
,
3295 OUT PULONG Cookie OPTIONAL
)
3298 return STATUS_NOT_IMPLEMENTED
;
3303 LdrUnlockLoaderLock(IN ULONG Flags
,
3304 IN ULONG Cookie OPTIONAL
)
3307 return STATUS_NOT_IMPLEMENTED
;
3312 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)