3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/utils.c
6 * PURPOSE: Process startup for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
13 * - Handle loading flags correctly
14 * - Handle errors correctly (unload dll's)
15 * - Implement a faster way to find modules (hash table)
19 /* INCLUDES *****************************************************************/
25 #define LDRP_PROCESS_CREATION_TIME 0x8000000
27 /* GLOBALS *******************************************************************/
31 #define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
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
);
166 TlsCallback
= (PIMAGE_TLS_CALLBACK
)((ULONG_PTR
)TlsCallback
+ sizeof(PVOID
));
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
);
229 DPRINT("LdrpInitializeTlsForThread() done\n");
230 return STATUS_SUCCESS
;
234 LdrpInitializeTlsForProccess(VOID
)
236 PLIST_ENTRY ModuleListHead
;
238 PLDR_DATA_TABLE_ENTRY Module
;
239 PIMAGE_TLS_DIRECTORY TlsDirectory
;
243 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
245 if (LdrpTlsCount
> 0)
247 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
249 LdrpTlsCount
* sizeof(TLS_DATA
));
250 if (LdrpTlsArray
== NULL
)
252 DPRINT1("Failed to allocate global tls data\n");
253 return STATUS_NO_MEMORY
;
256 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
257 Entry
= ModuleListHead
->Flink
;
258 while (Entry
!= ModuleListHead
)
260 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
261 if (Module
->LoadCount
== 0xFFFF &&
262 Module
->TlsIndex
!= 0xFFFF)
264 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
265 RtlImageDirectoryEntryToData(Module
->DllBase
,
267 IMAGE_DIRECTORY_ENTRY_TLS
,
269 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
270 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
271 TlsData
->StartAddressOfRawData
= (PVOID
)(ULONG_PTR
)TlsDirectory
->StartAddressOfRawData
;
272 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
273 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
274 if (TlsDirectory
->AddressOfCallBacks
)
275 TlsData
->TlsAddressOfCallBacks
= *(PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
277 TlsData
->TlsAddressOfCallBacks
= NULL
;
278 TlsData
->Module
= Module
;
280 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
281 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
282 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
283 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
284 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
285 DbgPrint("AddressOfCallBacks: %x (%x)\n", TlsDirectory
->AddressOfCallBacks
, *TlsDirectory
->AddressOfCallBacks
);
286 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
287 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
291 * Is this region allways writable ?
293 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
295 Entry
= Entry
->Flink
;
298 DPRINT("LdrpInitializeTlsForProccess() done\n");
299 return STATUS_SUCCESS
;
305 OBJECT_ATTRIBUTES ObjectAttributes
;
306 UNICODE_STRING LinkTarget
;
312 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
314 /* Get handle to the 'KnownDlls' directory */
315 RtlInitUnicodeString(&Name
,
317 InitializeObjectAttributes(&ObjectAttributes
,
319 OBJ_CASE_INSENSITIVE
,
322 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
323 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
325 if (!NT_SUCCESS(Status
))
327 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
328 LdrpKnownDllsDirHandle
= NULL
;
332 /* Allocate target name string */
333 LinkTarget
.Length
= 0;
334 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
335 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
337 MAX_PATH
* sizeof(WCHAR
));
338 if (LinkTarget
.Buffer
== NULL
)
340 NtClose(LdrpKnownDllsDirHandle
);
341 LdrpKnownDllsDirHandle
= NULL
;
345 RtlInitUnicodeString(&Name
,
347 InitializeObjectAttributes(&ObjectAttributes
,
349 OBJ_CASE_INSENSITIVE
,
350 LdrpKnownDllsDirHandle
,
352 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
353 SYMBOLIC_LINK_ALL_ACCESS
,
355 if (!NT_SUCCESS(Status
))
357 RtlFreeUnicodeString(&LinkTarget
);
358 NtClose(LdrpKnownDllsDirHandle
);
359 LdrpKnownDllsDirHandle
= NULL
;
363 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
367 if (!NT_SUCCESS(Status
))
369 RtlFreeUnicodeString(&LinkTarget
);
370 NtClose(LdrpKnownDllsDirHandle
);
371 LdrpKnownDllsDirHandle
= NULL
;
374 RtlCreateUnicodeString(&LdrpKnownDllPath
,
377 RtlFreeUnicodeString(&LinkTarget
);
379 DPRINT("LdrpInitLoader() done\n");
383 /***************************************************************************
388 * Adjusts the name of a dll to a fully qualified name.
391 * FullDllName: Pointer to caller supplied storage for the fully
392 * qualified dll name.
393 * DllName: Pointer to the dll name.
394 * BaseName: TRUE: Only the file name is passed to FullDllName
395 * FALSE: The full path is preserved in FullDllName
403 * A given path is not affected by the adjustment, but the file
405 * ntdll --> ntdll.dll
407 * ntdll.xyz --> ntdll.xyz
410 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
411 PUNICODE_STRING DllName
,
414 WCHAR Buffer
[MAX_PATH
];
419 Length
= DllName
->Length
/ sizeof(WCHAR
);
423 /* get the base dll name */
424 Pointer
= DllName
->Buffer
+ Length
;
431 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
434 Length
= Extension
- Pointer
;
435 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
436 Buffer
[Length
] = L
'\0';
440 /* get the full dll name */
441 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
442 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
445 /* Build the DLL's absolute name */
446 Extension
= wcsrchr (Buffer
, L
'.');
447 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
449 /* with extension - remove dot if it's the last character */
450 if (Buffer
[Length
- 1] == L
'.')
456 /* name without extension - assume that it is .dll */
457 memmove (Buffer
+ Length
, L
".dll", 10);
460 RtlCreateUnicodeString(FullDllName
, Buffer
);
463 PLDR_DATA_TABLE_ENTRY
464 LdrAddModuleEntry(PVOID ImageBase
,
465 PIMAGE_NT_HEADERS NTHeaders
,
468 PLDR_DATA_TABLE_ENTRY Module
;
470 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
472 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
473 Module
->DllBase
= (PVOID
)ImageBase
;
474 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
475 if (Module
->EntryPoint
!= 0)
476 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
477 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
478 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
480 /* loading while app is running */
481 Module
->LoadCount
= 1;
484 * loading while app is initializing
485 * dll must not be unloaded
487 Module
->LoadCount
= 0xFFFF;
491 Module
->TlsIndex
= -1;
492 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
493 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
495 RtlCreateUnicodeString (&Module
->FullDllName
,
497 RtlCreateUnicodeString (&Module
->BaseDllName
,
498 wcsrchr(FullDosName
, L
'\\') + 1);
499 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
501 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
502 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
503 &Module
->InLoadOrderLinks
);
504 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
511 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
512 OUT PUNICODE_STRING FullDosName
,
513 OUT PHANDLE SectionHandle
)
515 OBJECT_ATTRIBUTES ObjectAttributes
;
518 DPRINT("LdrpMapKnownDll() called\n");
520 if (LdrpKnownDllsDirHandle
== NULL
)
522 DPRINT("Invalid 'KnownDlls' directory\n");
523 return STATUS_UNSUCCESSFUL
;
526 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
528 InitializeObjectAttributes(&ObjectAttributes
,
530 OBJ_CASE_INSENSITIVE
,
531 LdrpKnownDllsDirHandle
,
533 Status
= NtOpenSection(SectionHandle
,
534 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
536 if (!NT_SUCCESS(Status
))
538 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
542 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
543 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
544 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
546 FullDosName
->MaximumLength
);
547 if (FullDosName
->Buffer
== NULL
)
549 FullDosName
->Length
= 0;
550 FullDosName
->MaximumLength
= 0;
551 return STATUS_SUCCESS
;
554 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
555 wcscat(FullDosName
->Buffer
, L
"\\");
556 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
558 DPRINT("FullDosName '%wZ'\n", FullDosName
);
560 DPRINT("LdrpMapKnownDll() done\n");
562 return STATUS_SUCCESS
;
567 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
568 IN PUNICODE_STRING DllName
,
569 OUT PUNICODE_STRING FullDosName
,
570 IN BOOLEAN MapAsDataFile
,
571 OUT PHANDLE SectionHandle
)
573 WCHAR SearchPathBuffer
[MAX_PATH
];
574 WCHAR DosName
[MAX_PATH
];
575 UNICODE_STRING FullNtFileName
;
576 OBJECT_ATTRIBUTES FileObjectAttributes
;
578 char BlockBuffer
[1024];
579 PIMAGE_DOS_HEADER DosHeader
;
580 PIMAGE_NT_HEADERS NTHeaders
;
581 IO_STATUS_BLOCK IoStatusBlock
;
585 DPRINT("LdrpMapDllImageFile() called\n");
587 if (SearchPath
== NULL
)
589 /* get application running path */
591 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
593 len
= wcslen (SearchPathBuffer
);
595 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
598 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
600 wcscat (SearchPathBuffer
, L
";");
602 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
603 wcscat (SearchPathBuffer
, L
"\\system32;");
604 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
605 wcscat (SearchPathBuffer
, L
";.");
607 SearchPath
= SearchPathBuffer
;
610 if (RtlDosSearchPath_U (SearchPath
,
616 return STATUS_DLL_NOT_FOUND
;
619 if (!RtlDosPathNameToNtPathName_U (DosName
,
623 return STATUS_DLL_NOT_FOUND
;
625 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
627 InitializeObjectAttributes(&FileObjectAttributes
,
633 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
635 Status
= NtOpenFile(&FileHandle
,
636 GENERIC_READ
|SYNCHRONIZE
,
637 &FileObjectAttributes
,
640 FILE_SYNCHRONOUS_IO_NONALERT
);
641 if (!NT_SUCCESS(Status
))
643 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
644 &FullNtFileName
, Status
);
645 RtlFreeHeap (RtlGetProcessHeap (),
647 FullNtFileName
.Buffer
);
650 RtlFreeHeap (RtlGetProcessHeap (),
652 FullNtFileName
.Buffer
);
654 Status
= NtReadFile(FileHandle
,
663 if (!NT_SUCCESS(Status
))
665 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
670 * Overlay DOS and NT headers structures to the
671 * buffer with DLL's header raw data.
673 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
674 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
676 * Check it is a PE image file.
678 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
679 || (DosHeader
->e_lfanew
== 0L)
680 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
682 DPRINT("NTDLL format invalid\n");
685 return STATUS_UNSUCCESSFUL
;
689 * Create a section for dll.
691 Status
= NtCreateSection(SectionHandle
,
696 SEC_COMMIT
| (MapAsDataFile
? 0 : SEC_IMAGE
),
700 if (!NT_SUCCESS(Status
))
702 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
706 RtlCreateUnicodeString(FullDosName
,
714 /***************************************************************************
731 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
732 IN PULONG LoadFlags OPTIONAL
,
733 IN PUNICODE_STRING Name
,
734 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
737 PLDR_DATA_TABLE_ENTRY Module
;
739 PPEB Peb
= NtCurrentPeb();
741 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
743 SearchPath
? L
" from " : L
"",
744 SearchPath
? SearchPath
: L
"");
746 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
748 if (NT_SUCCESS(Status
) &&
749 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
751 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
753 RtlEnterCriticalSection(Peb
->LoaderLock
);
754 Status
= LdrpAttachProcess();
755 RtlLeaveCriticalSection(Peb
->LoaderLock
);
759 if ((!Module
) && (NT_SUCCESS(Status
)))
762 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
768 /***************************************************************************
770 * LdrFindEntryForAddress
785 LdrFindEntryForAddress(PVOID Address
,
786 PLDR_DATA_TABLE_ENTRY
*Module
)
788 PLIST_ENTRY ModuleListHead
;
790 PLDR_DATA_TABLE_ENTRY ModulePtr
;
792 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
794 if (NtCurrentPeb()->Ldr
== NULL
)
795 return(STATUS_NO_MORE_ENTRIES
);
797 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
798 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
799 Entry
= ModuleListHead
->Flink
;
800 if (Entry
== ModuleListHead
)
802 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
803 return(STATUS_NO_MORE_ENTRIES
);
806 while (Entry
!= ModuleListHead
)
808 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
810 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
812 if ((Address
>= ModulePtr
->DllBase
) &&
813 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
816 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
817 return(STATUS_SUCCESS
);
820 Entry
= Entry
->Flink
;
823 DPRINT("Failed to find module entry.\n");
825 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
826 return(STATUS_NO_MORE_ENTRIES
);
830 /***************************************************************************
832 * LdrFindEntryForName
846 LdrFindEntryForName(PUNICODE_STRING Name
,
847 PLDR_DATA_TABLE_ENTRY
*Module
,
850 PLIST_ENTRY ModuleListHead
;
852 PLDR_DATA_TABLE_ENTRY ModulePtr
;
853 BOOLEAN ContainsPath
;
854 UNICODE_STRING AdjustedName
;
857 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
859 if (NtCurrentPeb()->Ldr
== NULL
)
860 return(STATUS_NO_MORE_ENTRIES
);
862 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
863 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
864 Entry
= ModuleListHead
->Flink
;
865 if (Entry
== ModuleListHead
)
867 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
868 return(STATUS_NO_MORE_ENTRIES
);
871 // NULL is the current process
875 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
876 return(STATUS_SUCCESS
);
879 LdrAdjustDllName (&AdjustedName
, Name
, FALSE
);
881 ContainsPath
= (AdjustedName
.Length
>= 2 * sizeof(WCHAR
) && L
':' == AdjustedName
.Buffer
[1]);
882 for (i
= 0; ! ContainsPath
&& i
< AdjustedName
.Length
/ sizeof(WCHAR
); i
++)
884 ContainsPath
= L
'\\' == AdjustedName
.Buffer
[i
] ||
885 L
'/' == AdjustedName
.Buffer
[i
];
890 if ((! ContainsPath
&&
891 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
893 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
895 *Module
= LdrpLastModule
;
896 if (Ref
&& (*Module
)->LoadCount
!= 0xFFFF)
898 (*Module
)->LoadCount
++;
900 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
901 RtlFreeUnicodeString(&AdjustedName
);
902 return(STATUS_SUCCESS
);
905 while (Entry
!= ModuleListHead
)
907 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
909 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
911 if ((! ContainsPath
&&
912 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
914 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
916 *Module
= LdrpLastModule
= ModulePtr
;
917 if (Ref
&& ModulePtr
->LoadCount
!= 0xFFFF)
919 ModulePtr
->LoadCount
++;
921 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
922 RtlFreeUnicodeString(&AdjustedName
);
923 return(STATUS_SUCCESS
);
926 Entry
= Entry
->Flink
;
929 DPRINT("Failed to find dll %wZ\n", Name
);
930 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
931 RtlFreeUnicodeString(&AdjustedName
);
932 return(STATUS_NO_MORE_ENTRIES
);
935 /**********************************************************************
951 LdrFixupForward(PCHAR ForwardName
)
953 CHAR NameBuffer
[128];
954 UNICODE_STRING DllName
;
957 PLDR_DATA_TABLE_ENTRY Module
;
960 strcpy(NameBuffer
, ForwardName
);
961 p
= strchr(NameBuffer
, '.');
966 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
967 RtlCreateUnicodeStringFromAsciiz (&DllName
,
970 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
972 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
974 if (!NT_SUCCESS(Status
))
976 ULONG Flags
= LDRP_PROCESS_CREATION_TIME
;
977 Status
= LdrLoadDll(NULL
,
981 if (NT_SUCCESS(Status
))
983 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
986 RtlFreeUnicodeString (&DllName
);
987 if (!NT_SUCCESS(Status
))
989 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
993 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
995 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1002 /**********************************************************************
1004 * LdrGetExportByOrdinal
1018 LdrGetExportByOrdinal (
1023 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1024 ULONG ExportDirSize
;
1025 PDWORD
* ExFunctions
;
1028 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1029 RtlImageDirectoryEntryToData (BaseAddress
,
1031 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1035 ExFunctions
= (PDWORD
*)
1038 ExportDir
->AddressOfFunctions
1041 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1043 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1046 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1047 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1050 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1051 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1053 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1054 Function
= LdrFixupForward((PCHAR
)Function
);
1061 /**********************************************************************
1063 * LdrGetExportByName
1074 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1075 * both with NumberOfNames entries.
1079 LdrGetExportByName(PVOID BaseAddress
,
1083 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1084 PDWORD
* ExFunctions
;
1086 USHORT
* ExOrdinals
;
1091 ULONG ExportDirSize
;
1093 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1095 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1096 RtlImageDirectoryEntryToData(BaseAddress
,
1098 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1100 if (ExportDir
== NULL
)
1102 DPRINT1("LdrGetExportByName(): no export directory, "
1103 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1108 //The symbol names may be missing entirely
1109 if (ExportDir
->AddressOfNames
== 0)
1111 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1116 * Get header pointers
1118 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1119 ExportDir
->AddressOfNames
);
1120 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1121 ExportDir
->AddressOfNameOrdinals
);
1122 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1123 ExportDir
->AddressOfFunctions
);
1126 * Check the hint first
1128 if (Hint
< ExportDir
->NumberOfNames
)
1130 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1131 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1133 Ordinal
= ExOrdinals
[Hint
];
1134 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1135 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1136 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1138 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1139 Function
= LdrFixupForward((PCHAR
)Function
);
1140 if (Function
== NULL
)
1142 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1146 if (Function
!= NULL
)
1155 maxn
= ExportDir
->NumberOfNames
- 1;
1156 while (minn
<= maxn
)
1161 mid
= (minn
+ maxn
) / 2;
1163 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1164 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1167 Ordinal
= ExOrdinals
[mid
];
1168 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1169 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1170 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1172 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1173 Function
= LdrFixupForward((PCHAR
)Function
);
1174 if (Function
== NULL
)
1176 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1180 if (Function
!= NULL
)
1183 else if (minn
== maxn
)
1185 DPRINT("LdrGetExportByName(): binary search failed\n");
1198 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1203 /**********************************************************************
1205 * LdrPerformRelocations
1208 * Relocate a DLL's memory image.
1220 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1223 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1224 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1225 ULONG Count
, ProtectSize
, OldProtect
, OldProtect2
;
1226 PVOID Page
, ProtectPage
, ProtectPage2
;
1231 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1233 return STATUS_SUCCESS
;
1237 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1239 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1241 return STATUS_SUCCESS
;
1244 ProtectSize
= PAGE_SIZE
;
1245 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1246 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1247 RelocationDDir
->VirtualAddress
);
1248 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1249 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1251 while (RelocationDir
< RelocationEnd
&&
1252 RelocationDir
->SizeOfBlock
> 0)
1254 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1256 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1257 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1259 /* Unprotect the page(s) we're about to relocate. */
1261 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1266 if (!NT_SUCCESS(Status
))
1268 DPRINT1("Failed to unprotect relocation target.\n");
1272 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1273 NTHeaders
->OptionalHeader
.SizeOfImage
)
1275 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1276 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1281 if (!NT_SUCCESS(Status
))
1283 DPRINT1("Failed to unprotect relocation target (2).\n");
1284 NtProtectVirtualMemory(NtCurrentProcess(),
1294 ProtectPage2
= NULL
;
1297 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1301 if (RelocationDir
== NULL
)
1302 return STATUS_UNSUCCESSFUL
;
1304 /* Restore old page protection. */
1305 NtProtectVirtualMemory(NtCurrentProcess(),
1311 if (ProtectPage2
!= NULL
)
1313 NtProtectVirtualMemory(NtCurrentProcess(),
1321 return STATUS_SUCCESS
;
1325 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1327 PLDR_DATA_TABLE_ENTRY
* Module
,
1330 ANSI_STRING AnsiDllName
;
1331 UNICODE_STRING DllName
;
1334 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1336 RtlInitAnsiString(&AnsiDllName
, Name
);
1337 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1338 if (!NT_SUCCESS(Status
))
1343 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1344 if (Load
&& !NT_SUCCESS(Status
))
1346 Status
= LdrpLoadModule(SearchPath
,
1347 NtCurrentPeb()->Ldr
->Initialized
? 0 : LDRP_PROCESS_CREATION_TIME
,
1351 if (NT_SUCCESS(Status
))
1353 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1355 if (!NT_SUCCESS(Status
))
1357 DPRINT1("failed to load %wZ\n", &DllName
);
1360 RtlFreeUnicodeString (&DllName
);
1365 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1366 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1367 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1370 PVOID
* ImportAddressList
;
1371 PULONG FunctionNameList
;
1377 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1379 return STATUS_UNSUCCESSFUL
;
1382 /* Get the import address list. */
1383 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1385 /* Get the list of functions to import. */
1386 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1388 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1392 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1395 /* Get the size of IAT. */
1397 while (FunctionNameList
[IATSize
] != 0L)
1402 /* Unprotect the region we are about to write into. */
1403 IATBase
= (PVOID
)ImportAddressList
;
1404 IATSize
*= sizeof(PVOID
*);
1405 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1410 if (!NT_SUCCESS(Status
))
1412 DPRINT1("Failed to unprotect IAT.\n");
1416 /* Walk through function list and fixup addresses. */
1417 while (*FunctionNameList
!= 0L)
1419 if ((*FunctionNameList
) & 0x80000000)
1421 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1422 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1423 if ((*ImportAddressList
) == NULL
)
1425 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1426 return STATUS_UNSUCCESSFUL
;
1431 IMAGE_IMPORT_BY_NAME
*pe_name
;
1432 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1433 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1434 if ((*ImportAddressList
) == NULL
)
1436 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1437 return STATUS_UNSUCCESSFUL
;
1440 ImportAddressList
++;
1444 /* Protect the region we are about to write into. */
1445 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1450 if (!NT_SUCCESS(Status
))
1452 DPRINT1("Failed to protect IAT.\n");
1456 return STATUS_SUCCESS
;
1460 LdrpProcessImportDirectory(
1461 PLDR_DATA_TABLE_ENTRY Module
,
1462 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1466 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1470 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1471 Module
, &Module
->BaseDllName
, ImportedName
);
1474 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1475 RtlImageDirectoryEntryToData(Module
->DllBase
,
1477 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1479 if (ImportModuleDirectory
== NULL
)
1481 return STATUS_UNSUCCESSFUL
;
1484 while (ImportModuleDirectory
->Name
)
1486 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1487 if (0 == _stricmp(Name
, ImportedName
))
1489 Status
= LdrpProcessImportDirectoryEntry(Module
,
1491 ImportModuleDirectory
);
1492 if (!NT_SUCCESS(Status
))
1497 ImportModuleDirectory
++;
1501 return STATUS_SUCCESS
;
1506 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1507 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1510 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1512 PVOID
* ImportAddressList
;
1515 PULONG FunctionNameList
;
1520 PIMAGE_NT_HEADERS NTHeaders
;
1524 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1525 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1527 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1528 RtlImageDirectoryEntryToData(Module
->DllBase
,
1530 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1532 if (ImportModuleDirectory
== NULL
)
1534 return STATUS_UNSUCCESSFUL
;
1537 while (ImportModuleDirectory
->Name
)
1539 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1540 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1543 /* Get the import address list. */
1544 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1546 /* Get the list of functions to import. */
1547 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1549 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1553 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1556 /* Get the size of IAT. */
1558 while (FunctionNameList
[IATSize
] != 0L)
1563 /* Unprotect the region we are about to write into. */
1564 IATBase
= (PVOID
)ImportAddressList
;
1565 IATSize
*= sizeof(PVOID
*);
1566 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1571 if (!NT_SUCCESS(Status
))
1573 DPRINT1("Failed to unprotect IAT.\n");
1577 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1578 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1579 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1580 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1582 /* Walk through function list and fixup addresses. */
1583 while (*FunctionNameList
!= 0L)
1585 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1587 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1589 ImportAddressList
++;
1593 /* Protect the region we are about to write into. */
1594 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1599 if (!NT_SUCCESS(Status
))
1601 DPRINT1("Failed to protect IAT.\n");
1605 ImportModuleDirectory
++;
1607 return STATUS_SUCCESS
;
1611 /**********************************************************************
1616 * Compute the entry point for every symbol the DLL imports
1617 * from other modules.
1629 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1630 IN PLDR_DATA_TABLE_ENTRY Module
)
1632 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1633 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1634 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1635 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1636 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1639 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1643 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1645 /* Check for tls data */
1646 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1647 RtlImageDirectoryEntryToData(Module
->DllBase
,
1649 IMAGE_DIRECTORY_ENTRY_TLS
,
1653 TlsSize
= TlsDirectory
->EndAddressOfRawData
1654 - TlsDirectory
->StartAddressOfRawData
1655 + TlsDirectory
->SizeOfZeroFill
;
1657 NtCurrentPeb()->Ldr
->Initialized
)
1659 TRACE_LDR("Trying to load dynamicly %wZ which contains a tls directory\n",
1660 &Module
->BaseDllName
);
1661 return STATUS_UNSUCCESSFUL
;
1665 * Process each import module.
1667 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1668 RtlImageDirectoryEntryToData(Module
->DllBase
,
1670 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1673 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1674 RtlImageDirectoryEntryToData(Module
->DllBase
,
1676 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1679 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1681 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1682 return STATUS_UNSUCCESSFUL
;
1684 if (BoundImportDescriptor
)
1686 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1688 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1689 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1691 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1692 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1693 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1694 if (!NT_SUCCESS(Status
))
1696 DPRINT1("failed to load %s\n", ImportedName
);
1699 if (Module
== ImportedModule
)
1701 LdrpDecrementLoadCount(Module
, FALSE
);
1703 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1705 TRACE_LDR("%wZ has stale binding to %wZ\n",
1706 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1707 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1708 if (!NT_SUCCESS(Status
))
1710 DPRINT1("failed to import %s\n", ImportedName
);
1716 BOOLEAN WrongForwarder
;
1717 WrongForwarder
= FALSE
;
1718 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1720 TRACE_LDR("%wZ has stale binding to %s\n",
1721 &Module
->BaseDllName
, ImportedName
);
1725 TRACE_LDR("%wZ has correct binding to %wZ\n",
1726 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1728 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1730 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1732 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1733 PCHAR ForwarderName
;
1735 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1736 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1738 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1739 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1740 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1741 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1742 if (!NT_SUCCESS(Status
))
1744 DPRINT1("failed to load %s\n", ForwarderName
);
1747 if (Module
== ImportedModule
)
1749 LdrpDecrementLoadCount(Module
, FALSE
);
1751 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1752 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1754 TRACE_LDR("%wZ has stale binding to %s\n",
1755 &Module
->BaseDllName
, ForwarderName
);
1756 WrongForwarder
= TRUE
;
1760 TRACE_LDR("%wZ has correct binding to %s\n",
1761 &Module
->BaseDllName
, ForwarderName
);
1765 if (WrongForwarder
||
1766 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1768 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1769 if (!NT_SUCCESS(Status
))
1771 DPRINT1("failed to import %s\n", ImportedName
);
1775 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1777 TRACE_LDR("Adjust imports for %s from %wZ\n",
1778 ImportedName
, &Module
->BaseDllName
);
1779 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1780 if (!NT_SUCCESS(Status
))
1782 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1786 else if (WrongForwarder
)
1790 * Update only forwarders
1792 TRACE_LDR("Stale BIND %s from %wZ\n",
1793 ImportedName
, &Module
->BaseDllName
);
1794 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1795 if (!NT_SUCCESS(Status
))
1797 DPRINT1("faild to import %s\n", ImportedName
);
1806 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1809 else if (ImportModuleDirectory
)
1811 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1813 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1814 while (ImportModuleDirectoryCurrent
->Name
)
1816 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1817 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1819 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1820 if (!NT_SUCCESS(Status
))
1822 DPRINT1("failed to load %s\n", ImportedName
);
1825 if (Module
== ImportedModule
)
1827 LdrpDecrementLoadCount(Module
, FALSE
);
1830 TRACE_LDR("Initializing imports for %wZ from %s\n",
1831 &Module
->BaseDllName
, ImportedName
);
1832 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1833 if (!NT_SUCCESS(Status
))
1835 DPRINT1("failed to import %s\n", ImportedName
);
1838 ImportModuleDirectoryCurrent
++;
1842 if (TlsDirectory
&& TlsSize
> 0)
1844 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1847 return STATUS_SUCCESS
;
1851 /**********************************************************************
1856 * 1. Relocate, if needed the EXE.
1857 * 2. Fixup any imported symbol.
1858 * 3. Compute the EXE's entry point.
1862 * Address at which the EXE's image
1866 * Handle of the section that contains
1870 * NULL on error; otherwise the entry point
1871 * to call for initializing the DLL.
1876 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
1877 * Currently the function is only used for the exe.
1879 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
1880 HANDLE SectionHandle
,
1881 PLDR_DATA_TABLE_ENTRY
* Module
,
1885 PEPFUNC EntryPoint
= NULL
;
1886 PIMAGE_DOS_HEADER DosHeader
;
1887 PIMAGE_NT_HEADERS NTHeaders
;
1888 PLDR_DATA_TABLE_ENTRY tmpModule
;
1890 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
1891 ImageBase
, SectionHandle
);
1894 * Overlay DOS and WNT headers structures
1895 * to the DLL's image.
1897 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
1898 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
1901 * If the base address is different from the
1902 * one the DLL is actually loaded, perform any
1905 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1907 DPRINT("LDR: Performing relocations\n");
1908 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
1909 if (!NT_SUCCESS(Status
))
1911 DPRINT1("LdrPerformRelocations() failed\n");
1918 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
1919 (*Module
)->SectionPointer
= SectionHandle
;
1923 Module
= &tmpModule
;
1924 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
1925 if (!NT_SUCCESS(Status
))
1931 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
1933 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
1937 * If the DLL's imports symbols from other
1938 * modules, fixup the imported calls entry points.
1940 DPRINT("About to fixup imports\n");
1941 Status
= LdrFixupImports(NULL
, *Module
);
1942 if (!NT_SUCCESS(Status
))
1944 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
1947 DPRINT("Fixup done\n");
1948 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1949 Status
= LdrpInitializeTlsForProccess();
1950 if (NT_SUCCESS(Status
))
1952 Status
= LdrpAttachProcess();
1954 if (NT_SUCCESS(Status
))
1956 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
1960 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1961 if (!NT_SUCCESS(Status
))
1967 * Compute the DLL's entry point's address.
1969 DPRINT("ImageBase = %p\n", ImageBase
);
1970 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1971 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
1973 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
1974 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
1976 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
1981 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
1983 IN PUNICODE_STRING Name
,
1984 PLDR_DATA_TABLE_ENTRY
*Module
,
1985 PVOID
*BaseAddress OPTIONAL
)
1987 UNICODE_STRING AdjustedName
;
1988 UNICODE_STRING FullDosName
;
1990 PLDR_DATA_TABLE_ENTRY tmpModule
;
1991 HANDLE SectionHandle
;
1994 PIMAGE_NT_HEADERS NtHeaders
;
1995 BOOLEAN MappedAsDataFile
;
1996 PVOID ArbitraryUserPointer
;
2000 Module
= &tmpModule
;
2002 /* adjust the full dll name */
2003 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2005 DPRINT("%wZ\n", &AdjustedName
);
2007 MappedAsDataFile
= FALSE
;
2008 /* Test if dll is already loaded */
2009 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2010 if (NT_SUCCESS(Status
))
2012 RtlFreeUnicodeString(&AdjustedName
);
2013 if (NULL
!= BaseAddress
)
2015 *BaseAddress
= (*Module
)->DllBase
;
2020 /* Open or create dll image section */
2021 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2022 if (!NT_SUCCESS(Status
))
2024 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2025 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2026 MappedAsDataFile
, &SectionHandle
);
2028 if (!NT_SUCCESS(Status
))
2030 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2031 RtlFreeUnicodeString(&AdjustedName
);
2034 RtlFreeUnicodeString(&AdjustedName
);
2035 /* Map the dll into the process */
2038 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2039 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2040 Status
= NtMapViewOfSection(SectionHandle
,
2050 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2051 if (!NT_SUCCESS(Status
))
2053 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2054 RtlFreeUnicodeString(&FullDosName
);
2055 NtClose(SectionHandle
);
2058 if (NULL
!= BaseAddress
)
2060 *BaseAddress
= ImageBase
;
2062 /* Get and check the NT headers */
2063 NtHeaders
= RtlImageNtHeader(ImageBase
);
2064 if (NtHeaders
== NULL
)
2066 DPRINT1("RtlImageNtHeaders() failed\n");
2067 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2068 NtClose (SectionHandle
);
2069 RtlFreeUnicodeString(&FullDosName
);
2070 return STATUS_UNSUCCESSFUL
;
2072 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2073 if (MappedAsDataFile
)
2075 ASSERT(NULL
!= BaseAddress
);
2076 if (NULL
!= BaseAddress
)
2078 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2081 RtlFreeUnicodeString(&FullDosName
);
2082 NtClose(SectionHandle
);
2083 return STATUS_SUCCESS
;
2085 /* If the base address is different from the
2086 * one the DLL is actually loaded, perform any
2088 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2090 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2091 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2092 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2093 if (!NT_SUCCESS(Status
))
2095 DPRINT1("LdrPerformRelocations() failed\n");
2096 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2097 NtClose (SectionHandle
);
2098 RtlFreeUnicodeString(&FullDosName
);
2099 return STATUS_UNSUCCESSFUL
;
2102 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2103 (*Module
)->SectionPointer
= SectionHandle
;
2104 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2106 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2108 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2110 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2112 /* fixup the imported calls entry points */
2113 Status
= LdrFixupImports(SearchPath
, *Module
);
2114 if (!NT_SUCCESS(Status
))
2116 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2119 #if defined(DBG) || defined(KDBG)
2120 LdrpLoadUserModuleSymbols(*Module
);
2121 #endif /* DBG || KDBG */
2122 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2123 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2124 &(*Module
)->InInitializationOrderModuleList
);
2125 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2127 return STATUS_SUCCESS
;
2131 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2134 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2135 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2136 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2138 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2145 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2148 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2150 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2154 /* ?????????????????? */
2156 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2158 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2159 RtlImageDirectoryEntryToData(Module
->DllBase
,
2161 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2163 if (BoundImportDescriptor
)
2165 /* dereferencing all imported modules, use the bound import descriptor */
2166 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2167 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2169 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2170 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2171 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2172 if (!NT_SUCCESS(Status
))
2174 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2178 if (Module
!= ImportedModule
)
2180 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2181 if (!NT_SUCCESS(Status
))
2183 DPRINT1("unable to unload %s\n", ImportedName
);
2187 BoundImportDescriptorCurrent
++;
2192 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2193 RtlImageDirectoryEntryToData(Module
->DllBase
,
2195 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2197 if (ImportModuleDirectory
)
2199 /* dereferencing all imported modules, use the import descriptor */
2200 while (ImportModuleDirectory
->Name
)
2202 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2203 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2204 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2205 if (!NT_SUCCESS(Status
))
2207 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2211 if (Module
!= ImportedModule
)
2213 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2214 if (!NT_SUCCESS(Status
))
2216 DPRINT1("unable to unload %s\n", ImportedName
);
2220 ImportModuleDirectory
++;
2228 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2230 LdrpDetachProcess(FALSE
);
2233 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2235 return STATUS_SUCCESS
;
2243 LdrUnloadDll (IN PVOID BaseAddress
)
2245 PLDR_DATA_TABLE_ENTRY Module
;
2248 if (BaseAddress
== NULL
)
2249 return STATUS_SUCCESS
;
2251 if (LdrMappedAsDataFile(&BaseAddress
))
2253 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2257 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2258 if (NT_SUCCESS(Status
))
2260 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2261 Status
= LdrpUnloadModule(Module
, TRUE
);
2272 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2274 PLIST_ENTRY ModuleListHead
;
2276 PLDR_DATA_TABLE_ENTRY Module
;
2279 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2281 Status
= STATUS_DLL_NOT_FOUND
;
2282 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2283 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2284 Entry
= ModuleListHead
->Flink
;
2285 while (Entry
!= ModuleListHead
)
2287 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2289 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2291 if (Module
->DllBase
== BaseAddress
)
2293 if (Module
->TlsIndex
== 0xFFFF)
2295 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2296 Status
= STATUS_SUCCESS
;
2300 Entry
= Entry
->Flink
;
2302 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2310 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2311 IN PULONG DllCharacteristics
,
2312 IN PUNICODE_STRING DllName
,
2313 OUT PVOID
*DllHandle
)
2315 PLDR_DATA_TABLE_ENTRY Module
;
2318 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2319 DllName
, DllPath
? DllPath
: L
"");
2321 /* NULL is the current executable */
2322 if (DllName
== NULL
)
2324 *DllHandle
= ExeModule
->DllBase
;
2325 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2326 return STATUS_SUCCESS
;
2329 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2330 if (NT_SUCCESS(Status
))
2332 *DllHandle
= Module
->DllBase
;
2333 return STATUS_SUCCESS
;
2336 DPRINT("Failed to find dll %wZ\n", DllName
);
2338 return STATUS_DLL_NOT_FOUND
;
2345 LdrAddRefDll(IN ULONG Flags
,
2346 IN PVOID BaseAddress
)
2348 PLIST_ENTRY ModuleListHead
;
2350 PLDR_DATA_TABLE_ENTRY Module
;
2353 if (Flags
& ~(LDR_PIN_MODULE
))
2355 return STATUS_INVALID_PARAMETER
;
2358 Status
= STATUS_DLL_NOT_FOUND
;
2359 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2360 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2361 Entry
= ModuleListHead
->Flink
;
2362 while (Entry
!= ModuleListHead
)
2364 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2366 if (Module
->DllBase
== BaseAddress
)
2368 if (Flags
& LDR_PIN_MODULE
)
2370 Module
->Flags
|= LDRP_STATIC_LINK
;
2374 LdrpIncrementLoadCount(Module
,
2377 Status
= STATUS_SUCCESS
;
2380 Entry
= Entry
->Flink
;
2382 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2390 RtlPcToFileHeader(IN PVOID PcValue
,
2393 PLIST_ENTRY ModuleListHead
;
2395 PLDR_DATA_TABLE_ENTRY Module
;
2396 PVOID ImageBase
= NULL
;
2398 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2399 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2400 Entry
= ModuleListHead
->Flink
;
2401 while (Entry
!= ModuleListHead
)
2403 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2405 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2406 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2408 ImageBase
= Module
->DllBase
;
2411 Entry
= Entry
->Flink
;
2413 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2415 *BaseOfImage
= ImageBase
;
2423 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2424 IN PANSI_STRING Name
,
2426 OUT PVOID
*ProcedureAddress
)
2428 if (Name
&& Name
->Length
)
2430 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2434 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2437 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2438 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2440 if (Name
&& Name
->Length
)
2443 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2444 if (*ProcedureAddress
!= NULL
)
2446 return STATUS_SUCCESS
;
2448 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2453 Ordinal
&= 0x0000FFFF;
2454 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2455 if (*ProcedureAddress
)
2457 return STATUS_SUCCESS
;
2459 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2461 return STATUS_PROCEDURE_NOT_FOUND
;
2464 /**********************************************************************
2469 * Unload dll's which are no longer referenced from others dll's
2480 * The loader lock must be held on enty.
2483 LdrpDetachProcess(BOOLEAN UnloadAll
)
2485 PLIST_ENTRY ModuleListHead
;
2487 PLDR_DATA_TABLE_ENTRY Module
;
2488 static ULONG CallingCount
= 0;
2490 DPRINT("LdrpDetachProcess() called for %wZ\n",
2491 &ExeModule
->BaseDllName
);
2494 LdrpDllShutdownInProgress
= TRUE
;
2498 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2499 Entry
= ModuleListHead
->Blink
;
2500 while (Entry
!= ModuleListHead
)
2502 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2503 if (((UnloadAll
&& Module
->LoadCount
== 0xFFFF) || Module
->LoadCount
== 0) &&
2504 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2505 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2507 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2508 if (Module
== LdrpLastModule
)
2510 LdrpLastModule
= NULL
;
2512 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2514 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2515 &Module
->BaseDllName
, Module
->EntryPoint
);
2516 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2520 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2522 Entry
= ModuleListHead
->Blink
;
2526 Entry
= Entry
->Blink
;
2530 if (CallingCount
== 1)
2532 Entry
= ModuleListHead
->Blink
;
2533 while (Entry
!= ModuleListHead
)
2535 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2536 Entry
= Entry
->Blink
;
2537 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2538 ((UnloadAll
&& Module
->LoadCount
!= 0xFFFF) || Module
->LoadCount
== 0))
2540 /* remove the module entry from the list */
2541 RemoveEntryList (&Module
->InLoadOrderLinks
);
2542 RemoveEntryList (&Module
->InInitializationOrderModuleList
);
2544 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2545 NtClose (Module
->SectionPointer
);
2547 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2549 RtlFreeUnicodeString (&Module
->FullDllName
);
2550 RtlFreeUnicodeString (&Module
->BaseDllName
);
2552 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2557 DPRINT("LdrpDetachProcess() done\n");
2560 /**********************************************************************
2565 * Initialize all dll's which are prepered for loading
2576 * The loader lock must be held on entry.
2580 LdrpAttachProcess(VOID
)
2582 PLIST_ENTRY ModuleListHead
;
2584 PLDR_DATA_TABLE_ENTRY Module
;
2586 NTSTATUS Status
= STATUS_SUCCESS
;
2588 DPRINT("LdrpAttachProcess() called for %wZ\n",
2589 &ExeModule
->BaseDllName
);
2591 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2592 Entry
= ModuleListHead
->Flink
;
2593 while (Entry
!= ModuleListHead
)
2595 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2596 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2598 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2599 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2600 &Module
->BaseDllName
, Module
->EntryPoint
);
2601 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(Module
->LoadCount
== 0xFFFF ? 1 : 0));
2604 Status
= STATUS_DLL_INIT_FAILED
;
2607 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2609 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2613 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2615 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2617 Entry
= Entry
->Flink
;
2620 DPRINT("LdrpAttachProcess() done\n");
2629 RtlDllShutdownInProgress (VOID
)
2631 return LdrpDllShutdownInProgress
;
2638 LdrShutdownProcess (VOID
)
2640 LdrpDetachProcess(TRUE
);
2641 return STATUS_SUCCESS
;
2649 LdrpAttachThread (VOID
)
2651 PLIST_ENTRY ModuleListHead
;
2653 PLDR_DATA_TABLE_ENTRY Module
;
2656 DPRINT("LdrpAttachThread() called for %wZ\n",
2657 &ExeModule
->BaseDllName
);
2659 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2661 Status
= LdrpInitializeTlsForThread();
2663 if (NT_SUCCESS(Status
))
2665 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2666 Entry
= ModuleListHead
->Flink
;
2668 while (Entry
!= ModuleListHead
)
2670 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2671 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2672 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2673 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2675 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2676 &Module
->BaseDllName
, Module
->EntryPoint
);
2677 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2679 Entry
= Entry
->Flink
;
2682 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2683 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2684 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2687 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2689 DPRINT("LdrpAttachThread() done\n");
2699 LdrShutdownThread (VOID
)
2701 PLIST_ENTRY ModuleListHead
;
2703 PLDR_DATA_TABLE_ENTRY Module
;
2705 DPRINT("LdrShutdownThread() called for %wZ\n",
2706 &ExeModule
->BaseDllName
);
2708 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2710 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2711 Entry
= ModuleListHead
->Blink
;
2712 while (Entry
!= ModuleListHead
)
2714 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2716 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2717 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2718 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2720 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2721 &Module
->BaseDllName
, Module
->EntryPoint
);
2722 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2724 Entry
= Entry
->Blink
;
2727 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2731 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2734 DPRINT("LdrShutdownThread() done\n");
2736 return STATUS_SUCCESS
;
2740 /***************************************************************************
2742 * LdrQueryProcessModuleInformation
2757 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2758 IN ULONG Size OPTIONAL
,
2759 OUT PULONG ReturnedSize
)
2761 PLIST_ENTRY ModuleListHead
;
2763 PLDR_DATA_TABLE_ENTRY Module
;
2764 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2765 NTSTATUS Status
= STATUS_SUCCESS
;
2766 ULONG UsedSize
= sizeof(ULONG
);
2767 ANSI_STRING AnsiString
;
2770 DPRINT("LdrQueryProcessModuleInformation() called\n");
2771 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2772 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2774 if (ModuleInformation
== NULL
|| Size
== 0)
2776 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2780 ModuleInformation
->NumberOfModules
= 0;
2781 ModulePtr
= &ModuleInformation
->Modules
[0];
2782 Status
= STATUS_SUCCESS
;
2785 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2786 Entry
= ModuleListHead
->Flink
;
2788 while (Entry
!= ModuleListHead
)
2790 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2792 DPRINT(" Module %wZ\n",
2793 &Module
->FullDllName
);
2795 if (UsedSize
> Size
)
2797 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2799 else if (ModuleInformation
!= NULL
)
2801 ModulePtr
->Section
= 0;
2802 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2803 ModulePtr
->ImageBase
= Module
->DllBase
;
2804 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2805 ModulePtr
->Flags
= Module
->Flags
;
2806 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2807 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2808 ModulePtr
->LoadCount
= Module
->LoadCount
;
2810 AnsiString
.Length
= 0;
2811 AnsiString
.MaximumLength
= 256;
2812 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2813 RtlUnicodeStringToAnsiString(&AnsiString
,
2814 &Module
->FullDllName
,
2817 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2819 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2821 ModulePtr
->OffsetToFileName
= 0;
2824 ModuleInformation
->NumberOfModules
++;
2826 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2828 Entry
= Entry
->Flink
;
2831 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2833 if (ReturnedSize
!= 0)
2834 *ReturnedSize
= UsedSize
;
2836 DPRINT("LdrQueryProcessModuleInformation() done\n");
2843 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2846 PIMAGE_NT_HEADERS Header
;
2853 Header
= RtlImageNtHeader (BaseAddress
);
2857 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
2862 Ptr
= (PUSHORT
) BaseAddress
;
2863 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
2866 if (HIWORD(Sum
) != 0)
2868 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2875 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
2876 if (HIWORD(Sum
) != 0)
2878 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
2882 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
2884 /* Subtract image checksum from calculated checksum. */
2885 /* fix low word of checksum */
2886 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
2888 CalcSum
-= LOWORD(HeaderSum
);
2892 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
2895 /* fix high word of checksum */
2896 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
2898 CalcSum
-= HIWORD(HeaderSum
);
2902 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
2905 /* add file length */
2906 CalcSum
+= ImageSize
;
2908 return (BOOLEAN
)(CalcSum
== HeaderSum
);
2912 * Compute size of an image as it is actually present in virt memory
2913 * (i.e. excluding NEVER_LOAD sections)
2916 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
2918 PIMAGE_SECTION_HEADER SectionHeader
;
2919 unsigned SectionIndex
;
2922 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
2923 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
2925 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
2927 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
2928 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
2930 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
2935 return ResidentSize
;
2939 /***************************************************************************
2941 * LdrVerifyImageMatchesChecksum
2956 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
2961 FILE_STANDARD_INFORMATION FileInfo
;
2962 IO_STATUS_BLOCK IoStatusBlock
;
2963 HANDLE SectionHandle
;
2969 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
2971 Status
= NtCreateSection (&SectionHandle
,
2978 if (!NT_SUCCESS(Status
))
2980 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
2986 Status
= NtMapViewOfSection (SectionHandle
,
2987 NtCurrentProcess (),
2996 if (!NT_SUCCESS(Status
))
2998 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
2999 NtClose (SectionHandle
);
3003 Status
= NtQueryInformationFile (FileHandle
,
3006 sizeof (FILE_STANDARD_INFORMATION
),
3007 FileStandardInformation
);
3008 if (!NT_SUCCESS(Status
))
3010 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3011 NtUnmapViewOfSection (NtCurrentProcess (),
3013 NtClose (SectionHandle
);
3017 Result
= LdrpCheckImageChecksum (BaseAddress
,
3018 FileInfo
.EndOfFile
.u
.LowPart
);
3019 if (Result
== FALSE
)
3021 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3024 NtUnmapViewOfSection (NtCurrentProcess (),
3027 NtClose (SectionHandle
);
3033 /***************************************************************************
3035 * LdrQueryImageFileExecutionOptions
3050 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3051 IN PCWSTR ValueName
,
3054 IN ULONG BufferSize
,
3055 OUT PULONG ReturnedLength OPTIONAL
)
3057 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3058 OBJECT_ATTRIBUTES ObjectAttributes
;
3059 UNICODE_STRING ValueNameString
;
3060 UNICODE_STRING KeyName
;
3061 WCHAR NameBuffer
[256];
3069 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3070 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3073 Ptr
= SubKey
->Buffer
;
3079 wcscat (NameBuffer
, Ptr
);
3080 RtlInitUnicodeString (&KeyName
,
3083 InitializeObjectAttributes (&ObjectAttributes
,
3085 OBJ_CASE_INSENSITIVE
,
3089 Status
= NtOpenKey (&KeyHandle
,
3092 if (!NT_SUCCESS(Status
))
3094 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3098 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3099 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3102 if (KeyInfo
== NULL
)
3104 NtClose (KeyHandle
);
3105 return STATUS_INSUFFICIENT_RESOURCES
;
3108 RtlInitUnicodeString (&ValueNameString
,
3110 Status
= NtQueryValueKey (KeyHandle
,
3112 KeyValuePartialInformation
,
3116 if (Status
== STATUS_BUFFER_OVERFLOW
)
3118 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3119 RtlFreeHeap (RtlGetProcessHeap(),
3122 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3125 if (KeyInfo
== NULL
)
3127 NtClose (KeyHandle
);
3128 return STATUS_INSUFFICIENT_RESOURCES
;
3131 Status
= NtQueryValueKey (KeyHandle
,
3133 KeyValuePartialInformation
,
3138 NtClose (KeyHandle
);
3140 if (!NT_SUCCESS(Status
))
3142 if (KeyInfo
!= NULL
)
3144 RtlFreeHeap (RtlGetProcessHeap(),
3151 if (KeyInfo
->Type
!= Type
)
3153 RtlFreeHeap (RtlGetProcessHeap(),
3156 return STATUS_OBJECT_TYPE_MISMATCH
;
3159 ResultSize
= BufferSize
;
3160 if (ResultSize
< KeyInfo
->DataLength
)
3162 Status
= STATUS_BUFFER_OVERFLOW
;
3166 ResultSize
= KeyInfo
->DataLength
;
3168 RtlCopyMemory (Buffer
,
3172 RtlFreeHeap (RtlGetProcessHeap(),
3176 if (ReturnedLength
!= NULL
)
3178 *ReturnedLength
= ResultSize
;
3185 PIMAGE_BASE_RELOCATION NTAPI
3186 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3188 IN PUSHORT TypeOffset
,
3197 for (i
= 0; i
< Count
; i
++)
3199 Offset
= *TypeOffset
& 0xFFF;
3200 Type
= *TypeOffset
>> 12;
3204 case IMAGE_REL_BASED_ABSOLUTE
:
3207 case IMAGE_REL_BASED_HIGH
:
3208 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3209 *ShortPtr
+= HIWORD(Delta
);
3212 case IMAGE_REL_BASED_LOW
:
3213 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3214 *ShortPtr
+= LOWORD(Delta
);
3217 case IMAGE_REL_BASED_HIGHLOW
:
3218 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3222 case IMAGE_REL_BASED_HIGHADJ
:
3223 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3225 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3232 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;