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
);
165 TlsCallback
= (PIMAGE_TLS_CALLBACK
)((ULONG_PTR
)TlsCallback
+ sizeof(PVOID
));
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
);
228 DPRINT("LdrpInitializeTlsForThread() done\n");
229 return STATUS_SUCCESS
;
233 LdrpInitializeTlsForProccess(VOID
)
235 PLIST_ENTRY ModuleListHead
;
237 PLDR_DATA_TABLE_ENTRY Module
;
238 PIMAGE_TLS_DIRECTORY TlsDirectory
;
242 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
244 if (LdrpTlsCount
> 0)
246 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
248 LdrpTlsCount
* sizeof(TLS_DATA
));
249 if (LdrpTlsArray
== NULL
)
251 DPRINT1("Failed to allocate global tls data\n");
252 return STATUS_NO_MEMORY
;
255 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
256 Entry
= ModuleListHead
->Flink
;
257 while (Entry
!= ModuleListHead
)
259 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
260 if (Module
->LoadCount
== 0xFFFF &&
261 Module
->TlsIndex
!= 0xFFFF)
263 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
264 RtlImageDirectoryEntryToData(Module
->DllBase
,
266 IMAGE_DIRECTORY_ENTRY_TLS
,
268 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
269 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
270 TlsData
->StartAddressOfRawData
= (PVOID
)(ULONG_PTR
)TlsDirectory
->StartAddressOfRawData
;
271 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
272 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
273 if (TlsDirectory
->AddressOfCallBacks
)
274 TlsData
->TlsAddressOfCallBacks
= *(PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
276 TlsData
->TlsAddressOfCallBacks
= NULL
;
277 TlsData
->Module
= Module
;
279 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
280 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
281 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
282 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
283 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
284 DbgPrint("AddressOfCallBacks: %x (%x)\n", TlsDirectory
->AddressOfCallBacks
, *TlsDirectory
->AddressOfCallBacks
);
285 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
286 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
290 * Is this region allways writable ?
292 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
294 Entry
= Entry
->Flink
;
297 DPRINT("LdrpInitializeTlsForProccess() done\n");
298 return STATUS_SUCCESS
;
304 OBJECT_ATTRIBUTES ObjectAttributes
;
305 UNICODE_STRING LinkTarget
;
311 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
313 /* Get handle to the 'KnownDlls' directory */
314 RtlInitUnicodeString(&Name
,
316 InitializeObjectAttributes(&ObjectAttributes
,
318 OBJ_CASE_INSENSITIVE
,
321 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
322 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
324 if (!NT_SUCCESS(Status
))
326 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
327 LdrpKnownDllsDirHandle
= NULL
;
331 /* Allocate target name string */
332 LinkTarget
.Length
= 0;
333 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
334 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
336 MAX_PATH
* sizeof(WCHAR
));
337 if (LinkTarget
.Buffer
== NULL
)
339 NtClose(LdrpKnownDllsDirHandle
);
340 LdrpKnownDllsDirHandle
= NULL
;
344 RtlInitUnicodeString(&Name
,
346 InitializeObjectAttributes(&ObjectAttributes
,
348 OBJ_CASE_INSENSITIVE
,
349 LdrpKnownDllsDirHandle
,
351 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
352 SYMBOLIC_LINK_ALL_ACCESS
,
354 if (!NT_SUCCESS(Status
))
356 RtlFreeUnicodeString(&LinkTarget
);
357 NtClose(LdrpKnownDllsDirHandle
);
358 LdrpKnownDllsDirHandle
= NULL
;
362 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
366 if (!NT_SUCCESS(Status
))
368 RtlFreeUnicodeString(&LinkTarget
);
369 NtClose(LdrpKnownDllsDirHandle
);
370 LdrpKnownDllsDirHandle
= NULL
;
373 RtlCreateUnicodeString(&LdrpKnownDllPath
,
376 RtlFreeUnicodeString(&LinkTarget
);
378 DPRINT("LdrpInitLoader() done\n");
382 /***************************************************************************
387 * Adjusts the name of a dll to a fully qualified name.
390 * FullDllName: Pointer to caller supplied storage for the fully
391 * qualified dll name.
392 * DllName: Pointer to the dll name.
393 * BaseName: TRUE: Only the file name is passed to FullDllName
394 * FALSE: The full path is preserved in FullDllName
402 * A given path is not affected by the adjustment, but the file
404 * ntdll --> ntdll.dll
406 * ntdll.xyz --> ntdll.xyz
409 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
410 PUNICODE_STRING DllName
,
413 WCHAR Buffer
[MAX_PATH
];
418 Length
= DllName
->Length
/ sizeof(WCHAR
);
422 /* get the base dll name */
423 Pointer
= DllName
->Buffer
+ Length
;
430 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
433 Length
= Extension
- Pointer
;
434 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
435 Buffer
[Length
] = L
'\0';
439 /* get the full dll name */
440 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
441 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
444 /* Build the DLL's absolute name */
445 Extension
= wcsrchr (Buffer
, L
'.');
446 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
448 /* with extension - remove dot if it's the last character */
449 if (Buffer
[Length
- 1] == L
'.')
455 /* name without extension - assume that it is .dll */
456 memmove (Buffer
+ Length
, L
".dll", 10);
459 RtlCreateUnicodeString(FullDllName
, Buffer
);
462 PLDR_DATA_TABLE_ENTRY
463 LdrAddModuleEntry(PVOID ImageBase
,
464 PIMAGE_NT_HEADERS NTHeaders
,
467 PLDR_DATA_TABLE_ENTRY Module
;
469 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
471 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
472 Module
->DllBase
= (PVOID
)ImageBase
;
473 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
474 if (Module
->EntryPoint
!= 0)
475 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
476 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
477 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
479 /* loading while app is running */
480 Module
->LoadCount
= 1;
483 * loading while app is initializing
484 * dll must not be unloaded
486 Module
->LoadCount
= 0xFFFF;
490 Module
->TlsIndex
= -1;
491 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
492 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
494 RtlCreateUnicodeString (&Module
->FullDllName
,
496 RtlCreateUnicodeString (&Module
->BaseDllName
,
497 wcsrchr(FullDosName
, L
'\\') + 1);
498 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
500 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
501 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
502 &Module
->InLoadOrderLinks
);
503 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
510 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
511 OUT PUNICODE_STRING FullDosName
,
512 OUT PHANDLE SectionHandle
)
514 OBJECT_ATTRIBUTES ObjectAttributes
;
517 DPRINT("LdrpMapKnownDll() called\n");
519 if (LdrpKnownDllsDirHandle
== NULL
)
521 DPRINT("Invalid 'KnownDlls' directory\n");
522 return STATUS_UNSUCCESSFUL
;
525 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
527 InitializeObjectAttributes(&ObjectAttributes
,
529 OBJ_CASE_INSENSITIVE
,
530 LdrpKnownDllsDirHandle
,
532 Status
= NtOpenSection(SectionHandle
,
533 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
535 if (!NT_SUCCESS(Status
))
537 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
541 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
542 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
543 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
545 FullDosName
->MaximumLength
);
546 if (FullDosName
->Buffer
== NULL
)
548 FullDosName
->Length
= 0;
549 FullDosName
->MaximumLength
= 0;
550 return STATUS_SUCCESS
;
553 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
554 wcscat(FullDosName
->Buffer
, L
"\\");
555 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
557 DPRINT("FullDosName '%wZ'\n", FullDosName
);
559 DPRINT("LdrpMapKnownDll() done\n");
561 return STATUS_SUCCESS
;
566 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
567 IN PUNICODE_STRING DllName
,
568 OUT PUNICODE_STRING FullDosName
,
569 IN BOOLEAN MapAsDataFile
,
570 OUT PHANDLE SectionHandle
)
572 WCHAR SearchPathBuffer
[MAX_PATH
];
573 WCHAR DosName
[MAX_PATH
];
574 UNICODE_STRING FullNtFileName
;
575 OBJECT_ATTRIBUTES FileObjectAttributes
;
577 char BlockBuffer
[1024];
578 PIMAGE_DOS_HEADER DosHeader
;
579 PIMAGE_NT_HEADERS NTHeaders
;
580 IO_STATUS_BLOCK IoStatusBlock
;
584 DPRINT("LdrpMapDllImageFile() called\n");
586 if (SearchPath
== NULL
)
588 /* get application running path */
590 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
592 len
= wcslen (SearchPathBuffer
);
594 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
597 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
599 wcscat (SearchPathBuffer
, L
";");
601 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
602 wcscat (SearchPathBuffer
, L
"\\system32;");
603 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
604 wcscat (SearchPathBuffer
, L
";.");
606 SearchPath
= SearchPathBuffer
;
609 if (RtlDosSearchPath_U (SearchPath
,
615 return STATUS_DLL_NOT_FOUND
;
618 if (!RtlDosPathNameToNtPathName_U (DosName
,
622 return STATUS_DLL_NOT_FOUND
;
624 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
626 InitializeObjectAttributes(&FileObjectAttributes
,
632 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
634 Status
= NtOpenFile(&FileHandle
,
635 GENERIC_READ
|SYNCHRONIZE
,
636 &FileObjectAttributes
,
639 FILE_SYNCHRONOUS_IO_NONALERT
);
640 if (!NT_SUCCESS(Status
))
642 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
643 &FullNtFileName
, Status
);
644 RtlFreeHeap (RtlGetProcessHeap (),
646 FullNtFileName
.Buffer
);
649 RtlFreeHeap (RtlGetProcessHeap (),
651 FullNtFileName
.Buffer
);
656 Status
= NtReadFile(FileHandle
,
665 if (!NT_SUCCESS(Status
))
667 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
673 * Overlay DOS and NT headers structures to the
674 * buffer with DLL's header raw data.
676 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
677 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
679 * Check it is a PE image file.
681 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
682 || (DosHeader
->e_lfanew
== 0L)
683 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
685 DPRINT("NTDLL format invalid\n");
688 return STATUS_UNSUCCESSFUL
;
693 * Create a section for dll.
695 Status
= NtCreateSection(SectionHandle
,
700 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
704 if (!NT_SUCCESS(Status
))
706 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
710 RtlCreateUnicodeString(FullDosName
,
718 /***************************************************************************
735 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
736 IN PULONG LoadFlags OPTIONAL
,
737 IN PUNICODE_STRING Name
,
738 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
741 PLDR_DATA_TABLE_ENTRY Module
;
743 PPEB Peb
= NtCurrentPeb();
745 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
747 SearchPath
? L
" from " : L
"",
748 SearchPath
? SearchPath
: L
"");
750 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
752 if (NT_SUCCESS(Status
) &&
753 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
755 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
757 RtlEnterCriticalSection(Peb
->LoaderLock
);
758 Status
= LdrpAttachProcess();
759 RtlLeaveCriticalSection(Peb
->LoaderLock
);
763 if ((!Module
) && (NT_SUCCESS(Status
)))
766 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
772 /***************************************************************************
774 * LdrFindEntryForAddress
789 LdrFindEntryForAddress(PVOID Address
,
790 PLDR_DATA_TABLE_ENTRY
*Module
)
792 PLIST_ENTRY ModuleListHead
;
794 PLDR_DATA_TABLE_ENTRY ModulePtr
;
796 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
798 if (NtCurrentPeb()->Ldr
== NULL
)
799 return(STATUS_NO_MORE_ENTRIES
);
801 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
802 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
803 Entry
= ModuleListHead
->Flink
;
804 if (Entry
== ModuleListHead
)
806 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
807 return(STATUS_NO_MORE_ENTRIES
);
810 while (Entry
!= ModuleListHead
)
812 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
814 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
816 if ((Address
>= ModulePtr
->DllBase
) &&
817 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
820 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
821 return(STATUS_SUCCESS
);
824 Entry
= Entry
->Flink
;
827 DPRINT("Failed to find module entry.\n");
829 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
830 return(STATUS_NO_MORE_ENTRIES
);
834 /***************************************************************************
836 * LdrFindEntryForName
850 LdrFindEntryForName(PUNICODE_STRING Name
,
851 PLDR_DATA_TABLE_ENTRY
*Module
,
854 PLIST_ENTRY ModuleListHead
;
856 PLDR_DATA_TABLE_ENTRY ModulePtr
;
857 BOOLEAN ContainsPath
;
858 UNICODE_STRING AdjustedName
;
861 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
863 if (NtCurrentPeb()->Ldr
== NULL
)
864 return(STATUS_NO_MORE_ENTRIES
);
866 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
867 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
868 Entry
= ModuleListHead
->Flink
;
869 if (Entry
== ModuleListHead
)
871 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
872 return(STATUS_NO_MORE_ENTRIES
);
875 // NULL is the current process
879 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
880 return(STATUS_SUCCESS
);
883 LdrAdjustDllName (&AdjustedName
, Name
, FALSE
);
885 ContainsPath
= (AdjustedName
.Length
>= 2 * sizeof(WCHAR
) && L
':' == AdjustedName
.Buffer
[1]);
886 for (i
= 0; ! ContainsPath
&& i
< AdjustedName
.Length
/ sizeof(WCHAR
); i
++)
888 ContainsPath
= L
'\\' == AdjustedName
.Buffer
[i
] ||
889 L
'/' == AdjustedName
.Buffer
[i
];
894 if ((! ContainsPath
&&
895 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
897 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
899 *Module
= LdrpLastModule
;
900 if (Ref
&& (*Module
)->LoadCount
!= 0xFFFF)
902 (*Module
)->LoadCount
++;
904 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
905 RtlFreeUnicodeString(&AdjustedName
);
906 return(STATUS_SUCCESS
);
909 while (Entry
!= ModuleListHead
)
911 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
913 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
915 if ((! ContainsPath
&&
916 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
918 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
920 *Module
= LdrpLastModule
= ModulePtr
;
921 if (Ref
&& ModulePtr
->LoadCount
!= 0xFFFF)
923 ModulePtr
->LoadCount
++;
925 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
926 RtlFreeUnicodeString(&AdjustedName
);
927 return(STATUS_SUCCESS
);
930 Entry
= Entry
->Flink
;
933 DPRINT("Failed to find dll %wZ\n", Name
);
934 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
935 RtlFreeUnicodeString(&AdjustedName
);
936 return(STATUS_NO_MORE_ENTRIES
);
939 /**********************************************************************
955 LdrFixupForward(PCHAR ForwardName
)
957 CHAR NameBuffer
[128];
958 UNICODE_STRING DllName
;
961 PLDR_DATA_TABLE_ENTRY Module
;
964 strcpy(NameBuffer
, ForwardName
);
965 p
= strchr(NameBuffer
, '.');
970 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
971 RtlCreateUnicodeStringFromAsciiz (&DllName
,
974 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
976 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
978 if (!NT_SUCCESS(Status
))
980 ULONG Flags
= LDRP_PROCESS_CREATION_TIME
;
981 Status
= LdrLoadDll(NULL
,
985 if (NT_SUCCESS(Status
))
987 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
990 RtlFreeUnicodeString (&DllName
);
991 if (!NT_SUCCESS(Status
))
993 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
997 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
999 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1006 /**********************************************************************
1008 * LdrGetExportByOrdinal
1022 LdrGetExportByOrdinal (
1027 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1028 ULONG ExportDirSize
;
1029 PDWORD
* ExFunctions
;
1032 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1033 RtlImageDirectoryEntryToData (BaseAddress
,
1035 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1039 ExFunctions
= (PDWORD
*)
1042 ExportDir
->AddressOfFunctions
1045 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1047 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1050 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1051 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1054 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1055 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1057 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1058 Function
= LdrFixupForward((PCHAR
)Function
);
1065 /**********************************************************************
1067 * LdrGetExportByName
1078 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1079 * both with NumberOfNames entries.
1083 LdrGetExportByName(PVOID BaseAddress
,
1087 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1088 PDWORD
* ExFunctions
;
1090 USHORT
* ExOrdinals
;
1095 ULONG ExportDirSize
;
1097 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1099 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1100 RtlImageDirectoryEntryToData(BaseAddress
,
1102 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1104 if (ExportDir
== NULL
)
1106 DPRINT1("LdrGetExportByName(): no export directory, "
1107 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1112 //The symbol names may be missing entirely
1113 if (ExportDir
->AddressOfNames
== 0)
1115 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1120 * Get header pointers
1122 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1123 ExportDir
->AddressOfNames
);
1124 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1125 ExportDir
->AddressOfNameOrdinals
);
1126 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1127 ExportDir
->AddressOfFunctions
);
1130 * Check the hint first
1132 if (Hint
< ExportDir
->NumberOfNames
)
1134 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1135 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1137 Ordinal
= ExOrdinals
[Hint
];
1138 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1139 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1140 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1142 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1143 Function
= LdrFixupForward((PCHAR
)Function
);
1144 if (Function
== NULL
)
1146 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1150 if (Function
!= NULL
)
1159 maxn
= ExportDir
->NumberOfNames
- 1;
1160 while (minn
<= maxn
)
1165 mid
= (minn
+ maxn
) / 2;
1167 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1168 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1171 Ordinal
= ExOrdinals
[mid
];
1172 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1173 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1174 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1176 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1177 Function
= LdrFixupForward((PCHAR
)Function
);
1178 if (Function
== NULL
)
1180 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1184 if (Function
!= NULL
)
1187 else if (minn
== maxn
)
1189 DPRINT("LdrGetExportByName(): binary search failed\n");
1202 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1207 /**********************************************************************
1209 * LdrPerformRelocations
1212 * Relocate a DLL's memory image.
1224 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1227 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1228 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1229 ULONG Count
, OldProtect
, OldProtect2
;
1231 PVOID Page
, ProtectPage
, ProtectPage2
;
1236 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1238 return STATUS_SUCCESS
;
1242 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1244 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1246 return STATUS_SUCCESS
;
1249 ProtectSize
= PAGE_SIZE
;
1250 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1251 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1252 RelocationDDir
->VirtualAddress
);
1253 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1254 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1256 while (RelocationDir
< RelocationEnd
&&
1257 RelocationDir
->SizeOfBlock
> 0)
1259 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1261 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1262 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1264 /* Unprotect the page(s) we're about to relocate. */
1266 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1271 if (!NT_SUCCESS(Status
))
1273 DPRINT1("Failed to unprotect relocation target.\n");
1277 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1278 NTHeaders
->OptionalHeader
.SizeOfImage
)
1280 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1281 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1286 if (!NT_SUCCESS(Status
))
1288 DPRINT1("Failed to unprotect relocation target (2).\n");
1289 NtProtectVirtualMemory(NtCurrentProcess(),
1299 ProtectPage2
= NULL
;
1302 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1306 if (RelocationDir
== NULL
)
1307 return STATUS_UNSUCCESSFUL
;
1309 /* Restore old page protection. */
1310 NtProtectVirtualMemory(NtCurrentProcess(),
1316 if (ProtectPage2
!= NULL
)
1318 NtProtectVirtualMemory(NtCurrentProcess(),
1326 return STATUS_SUCCESS
;
1330 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1332 PLDR_DATA_TABLE_ENTRY
* Module
,
1335 ANSI_STRING AnsiDllName
;
1336 UNICODE_STRING DllName
;
1339 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1341 RtlInitAnsiString(&AnsiDllName
, Name
);
1342 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1343 if (!NT_SUCCESS(Status
))
1348 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1349 if (Load
&& !NT_SUCCESS(Status
))
1351 Status
= LdrpLoadModule(SearchPath
,
1352 NtCurrentPeb()->Ldr
->Initialized
? 0 : LDRP_PROCESS_CREATION_TIME
,
1356 if (NT_SUCCESS(Status
))
1358 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1360 if (!NT_SUCCESS(Status
))
1362 ULONG ErrorResponse
;
1363 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1365 DPRINT1("failed to load %wZ\n", &DllName
);
1366 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1374 RtlFreeUnicodeString (&DllName
);
1379 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1381 ULONG ErrorResponse
;
1382 ULONG_PTR ErrorParameters
[2];
1383 ANSI_STRING ProcNameAnsi
;
1384 UNICODE_STRING ProcName
;
1389 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1393 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1394 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1395 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1396 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1397 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1403 RtlFreeUnicodeString(&ProcName
);
1407 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1408 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1409 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1412 PVOID
* ImportAddressList
;
1413 PULONG FunctionNameList
;
1419 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1421 return STATUS_UNSUCCESSFUL
;
1424 /* Get the import address list. */
1425 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1427 /* Get the list of functions to import. */
1428 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1430 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1434 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1437 /* Get the size of IAT. */
1439 while (FunctionNameList
[IATSize
] != 0L)
1444 /* Unprotect the region we are about to write into. */
1445 IATBase
= (PVOID
)ImportAddressList
;
1446 IATSize
*= sizeof(PVOID
*);
1447 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1452 if (!NT_SUCCESS(Status
))
1454 DPRINT1("Failed to unprotect IAT.\n");
1458 /* Walk through function list and fixup addresses. */
1459 while (*FunctionNameList
!= 0L)
1461 if ((*FunctionNameList
) & 0x80000000)
1463 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1464 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1465 if ((*ImportAddressList
) == NULL
)
1467 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1468 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1469 return STATUS_ENTRYPOINT_NOT_FOUND
;
1474 IMAGE_IMPORT_BY_NAME
*pe_name
;
1475 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1476 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1477 if ((*ImportAddressList
) == NULL
)
1479 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1480 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1481 return STATUS_ENTRYPOINT_NOT_FOUND
;
1484 ImportAddressList
++;
1488 /* Protect the region we are about to write into. */
1489 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1494 if (!NT_SUCCESS(Status
))
1496 DPRINT1("Failed to protect IAT.\n");
1500 return STATUS_SUCCESS
;
1504 LdrpProcessImportDirectory(
1505 PLDR_DATA_TABLE_ENTRY Module
,
1506 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1510 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1514 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1515 Module
, &Module
->BaseDllName
, ImportedName
);
1518 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1519 RtlImageDirectoryEntryToData(Module
->DllBase
,
1521 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1523 if (ImportModuleDirectory
== NULL
)
1525 return STATUS_UNSUCCESSFUL
;
1528 while (ImportModuleDirectory
->Name
)
1530 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1531 if (0 == _stricmp(Name
, ImportedName
))
1533 Status
= LdrpProcessImportDirectoryEntry(Module
,
1535 ImportModuleDirectory
);
1536 if (!NT_SUCCESS(Status
))
1541 ImportModuleDirectory
++;
1545 return STATUS_SUCCESS
;
1550 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1551 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1554 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1556 PVOID
* ImportAddressList
;
1559 PULONG FunctionNameList
;
1564 PIMAGE_NT_HEADERS NTHeaders
;
1568 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1569 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1571 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1572 RtlImageDirectoryEntryToData(Module
->DllBase
,
1574 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1576 if (ImportModuleDirectory
== NULL
)
1578 return STATUS_UNSUCCESSFUL
;
1581 while (ImportModuleDirectory
->Name
)
1583 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1584 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1587 /* Get the import address list. */
1588 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1590 /* Get the list of functions to import. */
1591 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1593 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1597 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1600 /* Get the size of IAT. */
1602 while (FunctionNameList
[IATSize
] != 0L)
1607 /* Unprotect the region we are about to write into. */
1608 IATBase
= (PVOID
)ImportAddressList
;
1609 IATSize
*= sizeof(PVOID
*);
1610 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1615 if (!NT_SUCCESS(Status
))
1617 DPRINT1("Failed to unprotect IAT.\n");
1621 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1622 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1623 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1624 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1626 /* Walk through function list and fixup addresses. */
1627 while (*FunctionNameList
!= 0L)
1629 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1631 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1633 ImportAddressList
++;
1637 /* Protect the region we are about to write into. */
1638 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1643 if (!NT_SUCCESS(Status
))
1645 DPRINT1("Failed to protect IAT.\n");
1649 ImportModuleDirectory
++;
1651 return STATUS_SUCCESS
;
1655 /**********************************************************************
1660 * Compute the entry point for every symbol the DLL imports
1661 * from other modules.
1673 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1674 IN PLDR_DATA_TABLE_ENTRY Module
)
1676 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1677 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1678 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1679 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1680 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1683 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1687 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1689 /* Check for tls data */
1690 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1691 RtlImageDirectoryEntryToData(Module
->DllBase
,
1693 IMAGE_DIRECTORY_ENTRY_TLS
,
1697 TlsSize
= TlsDirectory
->EndAddressOfRawData
1698 - TlsDirectory
->StartAddressOfRawData
1699 + TlsDirectory
->SizeOfZeroFill
;
1701 NtCurrentPeb()->Ldr
->Initialized
)
1703 TRACE_LDR("Trying to load dynamicly %wZ which contains a tls directory\n",
1704 &Module
->BaseDllName
);
1705 return STATUS_UNSUCCESSFUL
;
1709 * Process each import module.
1711 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1712 RtlImageDirectoryEntryToData(Module
->DllBase
,
1714 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1717 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1718 RtlImageDirectoryEntryToData(Module
->DllBase
,
1720 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1723 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1725 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1726 return STATUS_UNSUCCESSFUL
;
1728 if (BoundImportDescriptor
)
1730 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1732 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1733 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1735 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1736 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1737 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1738 if (!NT_SUCCESS(Status
))
1740 DPRINT1("failed to load %s\n", ImportedName
);
1743 if (Module
== ImportedModule
)
1745 LdrpDecrementLoadCount(Module
, FALSE
);
1747 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1749 TRACE_LDR("%wZ has stale binding to %wZ\n",
1750 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1751 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1752 if (!NT_SUCCESS(Status
))
1754 DPRINT1("failed to import %s\n", ImportedName
);
1760 BOOLEAN WrongForwarder
;
1761 WrongForwarder
= FALSE
;
1762 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1764 TRACE_LDR("%wZ has stale binding to %s\n",
1765 &Module
->BaseDllName
, ImportedName
);
1769 TRACE_LDR("%wZ has correct binding to %wZ\n",
1770 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1772 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1774 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1776 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1777 PCHAR ForwarderName
;
1779 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1780 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1782 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1783 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1784 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1785 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1786 if (!NT_SUCCESS(Status
))
1788 DPRINT1("failed to load %s\n", ForwarderName
);
1791 if (Module
== ImportedModule
)
1793 LdrpDecrementLoadCount(Module
, FALSE
);
1795 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1796 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1798 TRACE_LDR("%wZ has stale binding to %s\n",
1799 &Module
->BaseDllName
, ForwarderName
);
1800 WrongForwarder
= TRUE
;
1804 TRACE_LDR("%wZ has correct binding to %s\n",
1805 &Module
->BaseDllName
, ForwarderName
);
1809 if (WrongForwarder
||
1810 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1812 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1813 if (!NT_SUCCESS(Status
))
1815 DPRINT1("failed to import %s\n", ImportedName
);
1819 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1821 TRACE_LDR("Adjust imports for %s from %wZ\n",
1822 ImportedName
, &Module
->BaseDllName
);
1823 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1824 if (!NT_SUCCESS(Status
))
1826 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1830 else if (WrongForwarder
)
1834 * Update only forwarders
1836 TRACE_LDR("Stale BIND %s from %wZ\n",
1837 ImportedName
, &Module
->BaseDllName
);
1838 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1839 if (!NT_SUCCESS(Status
))
1841 DPRINT1("faild to import %s\n", ImportedName
);
1850 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1853 else if (ImportModuleDirectory
)
1855 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1857 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1858 while (ImportModuleDirectoryCurrent
->Name
)
1860 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1861 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1863 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1864 if (!NT_SUCCESS(Status
))
1866 DPRINT1("failed to load %s\n", ImportedName
);
1869 if (Module
== ImportedModule
)
1871 LdrpDecrementLoadCount(Module
, FALSE
);
1874 TRACE_LDR("Initializing imports for %wZ from %s\n",
1875 &Module
->BaseDllName
, ImportedName
);
1876 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1877 if (!NT_SUCCESS(Status
))
1879 DPRINT1("failed to import %s\n", ImportedName
);
1882 ImportModuleDirectoryCurrent
++;
1886 if (TlsDirectory
&& TlsSize
> 0)
1888 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1891 return STATUS_SUCCESS
;
1895 /**********************************************************************
1900 * 1. Relocate, if needed the EXE.
1901 * 2. Fixup any imported symbol.
1902 * 3. Compute the EXE's entry point.
1906 * Address at which the EXE's image
1910 * Handle of the section that contains
1914 * NULL on error; otherwise the entry point
1915 * to call for initializing the DLL.
1920 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
1921 * Currently the function is only used for the exe.
1923 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1924 HANDLE SectionHandle
,
1925 PLDR_DATA_TABLE_ENTRY
* Module
,
1929 PEPFUNC EntryPoint
= NULL
;
1930 PIMAGE_DOS_HEADER DosHeader
;
1931 PIMAGE_NT_HEADERS NTHeaders
;
1932 PLDR_DATA_TABLE_ENTRY tmpModule
;
1934 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
1935 ImageBase
, SectionHandle
);
1938 * Overlay DOS and WNT headers structures
1939 * to the DLL's image.
1941 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1942 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
1945 * If the base address is different from the
1946 * one the DLL is actually loaded, perform any
1949 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1951 DPRINT("LDR: Performing relocations\n");
1952 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1953 if (!NT_SUCCESS(Status
))
1955 DPRINT1("LdrPerformRelocations() failed\n");
1962 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1963 (*Module
)->SectionPointer
= SectionHandle
;
1967 Module
= &tmpModule
;
1968 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
1969 if (!NT_SUCCESS(Status
))
1975 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1977 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
1981 * If the DLL's imports symbols from other
1982 * modules, fixup the imported calls entry points.
1984 DPRINT("About to fixup imports\n");
1985 Status
= LdrFixupImports(NULL
, *Module
);
1986 if (!NT_SUCCESS(Status
))
1988 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
1991 DPRINT("Fixup done\n");
1992 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1993 Status
= LdrpInitializeTlsForProccess();
1994 if (NT_SUCCESS(Status
))
1996 Status
= LdrpAttachProcess();
1998 if (NT_SUCCESS(Status
))
2000 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2004 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2005 if (!NT_SUCCESS(Status
))
2011 * Compute the DLL's entry point's address.
2013 DPRINT("ImageBase = %p\n", ImageBase
);
2014 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2015 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2017 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2018 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2020 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2025 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2027 IN PUNICODE_STRING Name
,
2028 PLDR_DATA_TABLE_ENTRY
*Module
,
2029 PVOID
*BaseAddress OPTIONAL
)
2031 UNICODE_STRING AdjustedName
;
2032 UNICODE_STRING FullDosName
;
2034 PLDR_DATA_TABLE_ENTRY tmpModule
;
2035 HANDLE SectionHandle
;
2038 PIMAGE_NT_HEADERS NtHeaders
;
2039 BOOLEAN MappedAsDataFile
;
2040 PVOID ArbitraryUserPointer
;
2044 Module
= &tmpModule
;
2046 /* adjust the full dll name */
2047 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2049 DPRINT("%wZ\n", &AdjustedName
);
2051 MappedAsDataFile
= FALSE
;
2052 /* Test if dll is already loaded */
2053 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2054 if (NT_SUCCESS(Status
))
2056 RtlFreeUnicodeString(&AdjustedName
);
2057 if (NULL
!= BaseAddress
)
2059 *BaseAddress
= (*Module
)->DllBase
;
2064 /* Open or create dll image section */
2065 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2066 if (!NT_SUCCESS(Status
))
2068 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2069 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2070 MappedAsDataFile
, &SectionHandle
);
2072 if (!NT_SUCCESS(Status
))
2074 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2075 RtlFreeUnicodeString(&AdjustedName
);
2078 RtlFreeUnicodeString(&AdjustedName
);
2079 /* Map the dll into the process */
2082 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2083 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2084 Status
= NtMapViewOfSection(SectionHandle
,
2094 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2095 if (!NT_SUCCESS(Status
))
2097 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2098 RtlFreeUnicodeString(&FullDosName
);
2099 NtClose(SectionHandle
);
2102 if (NULL
!= BaseAddress
)
2104 *BaseAddress
= ImageBase
;
2106 if (!MappedAsDataFile
)
2108 /* Get and check the NT headers */
2109 NtHeaders
= RtlImageNtHeader(ImageBase
);
2110 if (NtHeaders
== NULL
)
2112 DPRINT1("RtlImageNtHeaders() failed\n");
2113 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2114 NtClose (SectionHandle
);
2115 RtlFreeUnicodeString(&FullDosName
);
2116 return STATUS_UNSUCCESSFUL
;
2119 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2120 if (MappedAsDataFile
)
2122 ASSERT(NULL
!= BaseAddress
);
2123 if (NULL
!= BaseAddress
)
2125 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2128 RtlFreeUnicodeString(&FullDosName
);
2129 NtClose(SectionHandle
);
2130 return STATUS_SUCCESS
;
2132 /* If the base address is different from the
2133 * one the DLL is actually loaded, perform any
2135 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2137 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2138 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2139 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2140 if (!NT_SUCCESS(Status
))
2142 DPRINT1("LdrPerformRelocations() failed\n");
2143 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2144 NtClose (SectionHandle
);
2145 RtlFreeUnicodeString(&FullDosName
);
2146 return STATUS_UNSUCCESSFUL
;
2149 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2150 (*Module
)->SectionPointer
= SectionHandle
;
2151 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2153 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2155 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2157 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2159 /* fixup the imported calls entry points */
2160 Status
= LdrFixupImports(SearchPath
, *Module
);
2161 if (!NT_SUCCESS(Status
))
2163 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2166 #if defined(DBG) || defined(KDBG)
2167 LdrpLoadUserModuleSymbols(*Module
);
2168 #endif /* DBG || KDBG */
2169 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2170 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2171 &(*Module
)->InInitializationOrderModuleList
);
2172 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2174 return STATUS_SUCCESS
;
2178 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2181 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2182 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2183 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2185 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2192 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2195 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2197 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2201 /* ?????????????????? */
2203 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2205 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2206 RtlImageDirectoryEntryToData(Module
->DllBase
,
2208 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2210 if (BoundImportDescriptor
)
2212 /* dereferencing all imported modules, use the bound import descriptor */
2213 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2214 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2216 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2217 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2218 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2219 if (!NT_SUCCESS(Status
))
2221 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2225 if (Module
!= ImportedModule
)
2227 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2228 if (!NT_SUCCESS(Status
))
2230 DPRINT1("unable to unload %s\n", ImportedName
);
2234 BoundImportDescriptorCurrent
++;
2239 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2240 RtlImageDirectoryEntryToData(Module
->DllBase
,
2242 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2244 if (ImportModuleDirectory
)
2246 /* dereferencing all imported modules, use the import descriptor */
2247 while (ImportModuleDirectory
->Name
)
2249 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2250 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2251 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2252 if (!NT_SUCCESS(Status
))
2254 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2258 if (Module
!= ImportedModule
)
2260 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2261 if (!NT_SUCCESS(Status
))
2263 DPRINT1("unable to unload %s\n", ImportedName
);
2267 ImportModuleDirectory
++;
2275 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2277 LdrpDetachProcess(FALSE
);
2280 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2282 return STATUS_SUCCESS
;
2290 LdrUnloadDll (IN PVOID BaseAddress
)
2292 PLDR_DATA_TABLE_ENTRY Module
;
2295 if (BaseAddress
== NULL
)
2296 return STATUS_SUCCESS
;
2298 if (LdrMappedAsDataFile(&BaseAddress
))
2300 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2304 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2305 if (NT_SUCCESS(Status
))
2307 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2308 Status
= LdrpUnloadModule(Module
, TRUE
);
2319 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2321 PLIST_ENTRY ModuleListHead
;
2323 PLDR_DATA_TABLE_ENTRY Module
;
2326 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2328 Status
= STATUS_DLL_NOT_FOUND
;
2329 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2330 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2331 Entry
= ModuleListHead
->Flink
;
2332 while (Entry
!= ModuleListHead
)
2334 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2336 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2338 if (Module
->DllBase
== BaseAddress
)
2340 if (Module
->TlsIndex
== 0xFFFF)
2342 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2343 Status
= STATUS_SUCCESS
;
2347 Entry
= Entry
->Flink
;
2349 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2357 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2358 IN PULONG DllCharacteristics
,
2359 IN PUNICODE_STRING DllName
,
2360 OUT PVOID
*DllHandle
)
2362 PLDR_DATA_TABLE_ENTRY Module
;
2365 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2366 DllName
, DllPath
? DllPath
: L
"");
2368 /* NULL is the current executable */
2369 if (DllName
== NULL
)
2371 *DllHandle
= ExeModule
->DllBase
;
2372 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2373 return STATUS_SUCCESS
;
2376 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2377 if (NT_SUCCESS(Status
))
2379 *DllHandle
= Module
->DllBase
;
2380 return STATUS_SUCCESS
;
2383 DPRINT("Failed to find dll %wZ\n", DllName
);
2385 return STATUS_DLL_NOT_FOUND
;
2392 LdrAddRefDll(IN ULONG Flags
,
2393 IN PVOID BaseAddress
)
2395 PLIST_ENTRY ModuleListHead
;
2397 PLDR_DATA_TABLE_ENTRY Module
;
2400 if (Flags
& ~(LDR_PIN_MODULE
))
2402 return STATUS_INVALID_PARAMETER
;
2405 Status
= STATUS_DLL_NOT_FOUND
;
2406 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2407 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2408 Entry
= ModuleListHead
->Flink
;
2409 while (Entry
!= ModuleListHead
)
2411 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2413 if (Module
->DllBase
== BaseAddress
)
2415 if (Flags
& LDR_PIN_MODULE
)
2417 Module
->Flags
|= LDRP_STATIC_LINK
;
2421 LdrpIncrementLoadCount(Module
,
2424 Status
= STATUS_SUCCESS
;
2427 Entry
= Entry
->Flink
;
2429 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2437 RtlPcToFileHeader(IN PVOID PcValue
,
2440 PLIST_ENTRY ModuleListHead
;
2442 PLDR_DATA_TABLE_ENTRY Module
;
2443 PVOID ImageBase
= NULL
;
2445 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2446 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2447 Entry
= ModuleListHead
->Flink
;
2448 while (Entry
!= ModuleListHead
)
2450 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2452 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2453 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2455 ImageBase
= Module
->DllBase
;
2458 Entry
= Entry
->Flink
;
2460 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2462 *BaseOfImage
= ImageBase
;
2470 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2471 IN PANSI_STRING Name
,
2473 OUT PVOID
*ProcedureAddress
)
2475 if (Name
&& Name
->Length
)
2477 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2481 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2484 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2485 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2487 if (Name
&& Name
->Length
)
2490 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2491 if (*ProcedureAddress
!= NULL
)
2493 return STATUS_SUCCESS
;
2495 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2500 Ordinal
&= 0x0000FFFF;
2501 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2502 if (*ProcedureAddress
)
2504 return STATUS_SUCCESS
;
2506 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2508 return STATUS_PROCEDURE_NOT_FOUND
;
2511 /**********************************************************************
2516 * Unload dll's which are no longer referenced from others dll's
2527 * The loader lock must be held on enty.
2530 LdrpDetachProcess(BOOLEAN UnloadAll
)
2532 PLIST_ENTRY ModuleListHead
;
2534 PLDR_DATA_TABLE_ENTRY Module
;
2535 static ULONG CallingCount
= 0;
2537 DPRINT("LdrpDetachProcess() called for %wZ\n",
2538 &ExeModule
->BaseDllName
);
2541 LdrpDllShutdownInProgress
= TRUE
;
2545 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2546 Entry
= ModuleListHead
->Blink
;
2547 while (Entry
!= ModuleListHead
)
2549 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2550 if (((UnloadAll
&& Module
->LoadCount
== 0xFFFF) || Module
->LoadCount
== 0) &&
2551 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2552 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2554 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2555 if (Module
== LdrpLastModule
)
2557 LdrpLastModule
= NULL
;
2559 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2561 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2562 &Module
->BaseDllName
, Module
->EntryPoint
);
2563 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2567 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2569 Entry
= ModuleListHead
->Blink
;
2573 Entry
= Entry
->Blink
;
2577 if (CallingCount
== 1)
2579 Entry
= ModuleListHead
->Blink
;
2580 while (Entry
!= ModuleListHead
)
2582 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2583 Entry
= Entry
->Blink
;
2584 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2585 ((UnloadAll
&& Module
->LoadCount
!= 0xFFFF) || Module
->LoadCount
== 0))
2587 /* remove the module entry from the list */
2588 RemoveEntryList (&Module
->InLoadOrderLinks
);
2589 RemoveEntryList (&Module
->InInitializationOrderModuleList
);
2591 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2592 NtClose (Module
->SectionPointer
);
2594 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2596 RtlFreeUnicodeString (&Module
->FullDllName
);
2597 RtlFreeUnicodeString (&Module
->BaseDllName
);
2599 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2604 DPRINT("LdrpDetachProcess() done\n");
2607 /**********************************************************************
2612 * Initialize all dll's which are prepered for loading
2623 * The loader lock must be held on entry.
2627 LdrpAttachProcess(VOID
)
2629 PLIST_ENTRY ModuleListHead
;
2631 PLDR_DATA_TABLE_ENTRY Module
;
2633 NTSTATUS Status
= STATUS_SUCCESS
;
2635 DPRINT("LdrpAttachProcess() called for %wZ\n",
2636 &ExeModule
->BaseDllName
);
2638 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2639 Entry
= ModuleListHead
->Flink
;
2640 while (Entry
!= ModuleListHead
)
2642 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2643 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2645 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2646 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2647 &Module
->BaseDllName
, Module
->EntryPoint
);
2648 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2651 Status
= STATUS_DLL_INIT_FAILED
;
2654 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2656 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2660 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2662 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2664 Entry
= Entry
->Flink
;
2667 DPRINT("LdrpAttachProcess() done\n");
2676 RtlDllShutdownInProgress (VOID
)
2678 return LdrpDllShutdownInProgress
;
2685 LdrShutdownProcess (VOID
)
2687 LdrpDetachProcess(TRUE
);
2688 return STATUS_SUCCESS
;
2696 LdrpAttachThread (VOID
)
2698 PLIST_ENTRY ModuleListHead
;
2700 PLDR_DATA_TABLE_ENTRY Module
;
2703 DPRINT("LdrpAttachThread() called for %wZ\n",
2704 &ExeModule
->BaseDllName
);
2706 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2708 Status
= LdrpInitializeTlsForThread();
2710 if (NT_SUCCESS(Status
))
2712 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2713 Entry
= ModuleListHead
->Flink
;
2715 while (Entry
!= ModuleListHead
)
2717 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2718 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2719 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2720 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2722 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2723 &Module
->BaseDllName
, Module
->EntryPoint
);
2724 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2726 Entry
= Entry
->Flink
;
2729 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2730 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2731 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2734 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2736 DPRINT("LdrpAttachThread() done\n");
2746 LdrShutdownThread (VOID
)
2748 PLIST_ENTRY ModuleListHead
;
2750 PLDR_DATA_TABLE_ENTRY Module
;
2752 DPRINT("LdrShutdownThread() called for %wZ\n",
2753 &ExeModule
->BaseDllName
);
2755 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2757 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2758 Entry
= ModuleListHead
->Blink
;
2759 while (Entry
!= ModuleListHead
)
2761 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2763 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2764 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2765 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2767 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2768 &Module
->BaseDllName
, Module
->EntryPoint
);
2769 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2771 Entry
= Entry
->Blink
;
2774 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2778 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2781 DPRINT("LdrShutdownThread() done\n");
2783 return STATUS_SUCCESS
;
2787 /***************************************************************************
2789 * LdrQueryProcessModuleInformation
2804 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2805 IN ULONG Size OPTIONAL
,
2806 OUT PULONG ReturnedSize
)
2808 PLIST_ENTRY ModuleListHead
;
2810 PLDR_DATA_TABLE_ENTRY Module
;
2811 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2812 NTSTATUS Status
= STATUS_SUCCESS
;
2813 ULONG UsedSize
= sizeof(ULONG
);
2814 ANSI_STRING AnsiString
;
2817 DPRINT("LdrQueryProcessModuleInformation() called\n");
2818 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2819 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2821 if (ModuleInformation
== NULL
|| Size
== 0)
2823 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2827 ModuleInformation
->NumberOfModules
= 0;
2828 ModulePtr
= &ModuleInformation
->Modules
[0];
2829 Status
= STATUS_SUCCESS
;
2832 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2833 Entry
= ModuleListHead
->Flink
;
2835 while (Entry
!= ModuleListHead
)
2837 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2839 DPRINT(" Module %wZ\n",
2840 &Module
->FullDllName
);
2842 if (UsedSize
> Size
)
2844 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2846 else if (ModuleInformation
!= NULL
)
2848 ModulePtr
->Section
= 0;
2849 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2850 ModulePtr
->ImageBase
= Module
->DllBase
;
2851 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2852 ModulePtr
->Flags
= Module
->Flags
;
2853 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2854 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2855 ModulePtr
->LoadCount
= Module
->LoadCount
;
2857 AnsiString
.Length
= 0;
2858 AnsiString
.MaximumLength
= 256;
2859 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2860 RtlUnicodeStringToAnsiString(&AnsiString
,
2861 &Module
->FullDllName
,
2864 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2866 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2868 ModulePtr
->OffsetToFileName
= 0;
2871 ModuleInformation
->NumberOfModules
++;
2873 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2875 Entry
= Entry
->Flink
;
2878 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2880 if (ReturnedSize
!= 0)
2881 *ReturnedSize
= UsedSize
;
2883 DPRINT("LdrQueryProcessModuleInformation() done\n");
2890 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2893 PIMAGE_NT_HEADERS Header
;
2900 Header
= RtlImageNtHeader (BaseAddress
);
2904 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
2909 Ptr
= (PUSHORT
) BaseAddress
;
2910 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
2913 if (HIWORD(Sum
) != 0)
2915 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2922 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
2923 if (HIWORD(Sum
) != 0)
2925 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2929 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
2931 /* Subtract image checksum from calculated checksum. */
2932 /* fix low word of checksum */
2933 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
2935 CalcSum
-= LOWORD(HeaderSum
);
2939 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
2942 /* fix high word of checksum */
2943 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
2945 CalcSum
-= HIWORD(HeaderSum
);
2949 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
2952 /* add file length */
2953 CalcSum
+= ImageSize
;
2955 return (BOOLEAN
)(CalcSum
== HeaderSum
);
2959 * Compute size of an image as it is actually present in virt memory
2960 * (i.e. excluding NEVER_LOAD sections)
2963 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
2965 PIMAGE_SECTION_HEADER SectionHeader
;
2966 unsigned SectionIndex
;
2969 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
2970 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
2972 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
2974 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
2975 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
2977 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
2982 return ResidentSize
;
2986 /***************************************************************************
2988 * LdrVerifyImageMatchesChecksum
3003 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3008 FILE_STANDARD_INFORMATION FileInfo
;
3009 IO_STATUS_BLOCK IoStatusBlock
;
3010 HANDLE SectionHandle
;
3016 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3018 Status
= NtCreateSection (&SectionHandle
,
3025 if (!NT_SUCCESS(Status
))
3027 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3033 Status
= NtMapViewOfSection (SectionHandle
,
3034 NtCurrentProcess (),
3043 if (!NT_SUCCESS(Status
))
3045 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3046 NtClose (SectionHandle
);
3050 Status
= NtQueryInformationFile (FileHandle
,
3053 sizeof (FILE_STANDARD_INFORMATION
),
3054 FileStandardInformation
);
3055 if (!NT_SUCCESS(Status
))
3057 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3058 NtUnmapViewOfSection (NtCurrentProcess (),
3060 NtClose (SectionHandle
);
3064 Result
= LdrpCheckImageChecksum (BaseAddress
,
3065 FileInfo
.EndOfFile
.u
.LowPart
);
3066 if (Result
== FALSE
)
3068 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3071 NtUnmapViewOfSection (NtCurrentProcess (),
3074 NtClose (SectionHandle
);
3080 /***************************************************************************
3082 * LdrQueryImageFileExecutionOptions
3097 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3098 IN PCWSTR ValueName
,
3101 IN ULONG BufferSize
,
3102 OUT PULONG ReturnedLength OPTIONAL
)
3104 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3105 OBJECT_ATTRIBUTES ObjectAttributes
;
3106 UNICODE_STRING ValueNameString
;
3107 UNICODE_STRING KeyName
;
3108 WCHAR NameBuffer
[256];
3116 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3117 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3120 Ptr
= SubKey
->Buffer
;
3126 wcscat (NameBuffer
, Ptr
);
3127 RtlInitUnicodeString (&KeyName
,
3130 InitializeObjectAttributes (&ObjectAttributes
,
3132 OBJ_CASE_INSENSITIVE
,
3136 Status
= NtOpenKey (&KeyHandle
,
3139 if (!NT_SUCCESS(Status
))
3141 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3145 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3146 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3149 if (KeyInfo
== NULL
)
3151 NtClose (KeyHandle
);
3152 return STATUS_INSUFFICIENT_RESOURCES
;
3155 RtlInitUnicodeString (&ValueNameString
,
3157 Status
= NtQueryValueKey (KeyHandle
,
3159 KeyValuePartialInformation
,
3163 if (Status
== STATUS_BUFFER_OVERFLOW
)
3165 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3166 RtlFreeHeap (RtlGetProcessHeap(),
3169 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3172 if (KeyInfo
== NULL
)
3174 NtClose (KeyHandle
);
3175 return STATUS_INSUFFICIENT_RESOURCES
;
3178 Status
= NtQueryValueKey (KeyHandle
,
3180 KeyValuePartialInformation
,
3185 NtClose (KeyHandle
);
3187 if (!NT_SUCCESS(Status
))
3189 if (KeyInfo
!= NULL
)
3191 RtlFreeHeap (RtlGetProcessHeap(),
3198 if (KeyInfo
->Type
!= Type
)
3200 RtlFreeHeap (RtlGetProcessHeap(),
3203 return STATUS_OBJECT_TYPE_MISMATCH
;
3206 ResultSize
= BufferSize
;
3207 if (ResultSize
< KeyInfo
->DataLength
)
3209 Status
= STATUS_BUFFER_OVERFLOW
;
3213 ResultSize
= KeyInfo
->DataLength
;
3215 RtlCopyMemory (Buffer
,
3219 RtlFreeHeap (RtlGetProcessHeap(),
3223 if (ReturnedLength
!= NULL
)
3225 *ReturnedLength
= ResultSize
;
3232 PIMAGE_BASE_RELOCATION NTAPI
3233 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3235 IN PUSHORT TypeOffset
,
3244 for (i
= 0; i
< Count
; i
++)
3246 Offset
= *TypeOffset
& 0xFFF;
3247 Type
= *TypeOffset
>> 12;
3251 case IMAGE_REL_BASED_ABSOLUTE
:
3254 case IMAGE_REL_BASED_HIGH
:
3255 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3256 *ShortPtr
+= HIWORD(Delta
);
3259 case IMAGE_REL_BASED_LOW
:
3260 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3261 *ShortPtr
+= LOWORD(Delta
);
3264 case IMAGE_REL_BASED_HIGHLOW
:
3265 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3269 case IMAGE_REL_BASED_HIGHADJ
:
3270 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3272 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3279 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3284 LdrLockLoaderLock(IN ULONG Flags
,
3285 OUT PULONG Disposition OPTIONAL
,
3286 OUT PULONG Cookie OPTIONAL
)
3289 return STATUS_NOT_IMPLEMENTED
;
3294 LdrUnlockLoaderLock(IN ULONG Flags
,
3295 IN ULONG Cookie OPTIONAL
)
3298 return STATUS_NOT_IMPLEMENTED
;
3303 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)