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 0xffff
25 #define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
27 /* GLOBALS *******************************************************************/
30 #define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
33 typedef struct _TLS_DATA
35 PVOID StartAddressOfRawData
;
38 PIMAGE_TLS_CALLBACK
*TlsAddressOfCallBacks
;
39 PLDR_DATA_TABLE_ENTRY Module
;
40 } TLS_DATA
, *PTLS_DATA
;
42 static BOOLEAN LdrpDllShutdownInProgress
= FALSE
;
43 static PTLS_DATA LdrpTlsArray
= NULL
;
44 static ULONG LdrpTlsCount
= 0;
45 static ULONG LdrpTlsSize
= 0;
46 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
47 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
48 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
49 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
51 /* PROTOTYPES ****************************************************************/
53 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
54 static PVOID
LdrFixupForward(PCHAR ForwardName
);
55 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
56 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
58 IN PUNICODE_STRING Name
,
59 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
60 OUT PVOID
*BaseAddress OPTIONAL
);
61 static NTSTATUS
LdrpAttachProcess(VOID
);
62 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
64 /* FUNCTIONS *****************************************************************/
66 #if DBG || defined(KDBG)
69 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule
)
80 #endif /* DBG || KDBG */
83 LdrMappedAsDataFile(PVOID
*BaseAddress
)
85 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
87 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
94 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
99 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
101 LoadCount
= Module
->LoadCount
;
102 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
108 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
113 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
118 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
120 LoadCount
= Module
->LoadCount
;
121 if (Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
127 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
132 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
136 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
138 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
143 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
147 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
149 PIMAGE_TLS_CALLBACK
*TlsCallback
;
150 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
)
152 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
157 TRACE_LDR("%wZ - Calling tls callback at %x\n",
158 &Module
->BaseDllName
, *TlsCallback
);
159 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
166 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
168 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
169 Module
->EntryPoint
== 0)
173 LdrpTlsCallback(Module
, dwReason
);
174 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
178 LdrpQueryAppPaths(IN PCWSTR ImageName
)
180 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
181 OBJECT_ATTRIBUTES ObjectAttributes
;
182 WCHAR SearchPathBuffer
[5*MAX_PATH
];
183 UNICODE_STRING ValueNameString
;
184 UNICODE_STRING KeyName
;
185 WCHAR NameBuffer
[MAX_PATH
];
193 _snwprintf(NameBuffer
,
194 sizeof(NameBuffer
) / sizeof(WCHAR
),
195 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
198 RtlInitUnicodeString(&KeyName
, NameBuffer
);
200 InitializeObjectAttributes(&ObjectAttributes
,
202 OBJ_CASE_INSENSITIVE
,
206 Status
= NtOpenKey(&KeyHandle
,
209 if (!NT_SUCCESS(Status
))
211 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
215 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 256 * sizeof(WCHAR
);
217 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize
);
220 DPRINT("RtlAllocateHeap() failed\n");
225 RtlInitUnicodeString(&ValueNameString
,
228 Status
= NtQueryValueKey(KeyHandle
,
230 KeyValuePartialInformation
,
235 if (!NT_SUCCESS(Status
))
238 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
242 RtlCopyMemory(SearchPathBuffer
,
244 KeyInfo
->DataLength
);
246 /* Free KeyInfo memory, we won't need it anymore */
247 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
249 /* Close the key handle */
252 /* get application running path */
253 wcscat(SearchPathBuffer
, L
";");
254 wcscat(SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
); // FIXME: Don't rely on it being NULL-terminated!!!
256 /* Remove trailing backslash */
257 Backslash
= wcsrchr(SearchPathBuffer
, L
'\\');
258 if (Backslash
) Backslash
= L
'\0';
260 wcscat(SearchPathBuffer
, L
";");
262 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
263 wcscat(SearchPathBuffer
, L
"\\system32;");
264 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
265 wcscat(SearchPathBuffer
, L
";.");
267 /* Copy it to the heap allocd memory */
268 Path
= RtlAllocateHeap(RtlGetProcessHeap(),
270 wcslen(SearchPathBuffer
) * sizeof(WCHAR
));
274 DPRINT1("RtlAllocateHeap() failed\n");
278 wcscpy(Path
, SearchPathBuffer
);
284 LdrpInitializeTlsForThread(VOID
)
290 PTEB Teb
= NtCurrentTeb();
292 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
294 Teb
->StaticUnicodeString
.Length
= 0;
295 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
296 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
298 if (LdrpTlsCount
> 0)
300 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
302 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
303 if (TlsPointers
== NULL
)
305 DPRINT1("failed to allocate thread tls data\n");
306 return STATUS_NO_MEMORY
;
309 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
310 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
312 TlsInfo
= LdrpTlsArray
;
313 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
315 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
316 TlsPointers
[i
] = TlsData
;
317 if (TlsInfo
->TlsDataSize
)
319 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
320 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
322 if (TlsInfo
->TlsZeroSize
)
324 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
325 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
330 DPRINT("LdrpInitializeTlsForThread() done\n");
331 return STATUS_SUCCESS
;
335 LdrpInitializeTlsForProccess(VOID
)
337 PLIST_ENTRY ModuleListHead
;
339 PLDR_DATA_TABLE_ENTRY Module
;
340 PIMAGE_TLS_DIRECTORY TlsDirectory
;
344 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
346 if (LdrpTlsCount
> 0)
348 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
350 LdrpTlsCount
* sizeof(TLS_DATA
));
351 if (LdrpTlsArray
== NULL
)
353 DPRINT1("Failed to allocate global tls data\n");
354 return STATUS_NO_MEMORY
;
357 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
358 Entry
= ModuleListHead
->Flink
;
359 while (Entry
!= ModuleListHead
)
361 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
362 if (Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
&&
363 Module
->TlsIndex
!= 0xFFFF)
365 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
366 RtlImageDirectoryEntryToData(Module
->DllBase
,
368 IMAGE_DIRECTORY_ENTRY_TLS
,
370 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
371 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
372 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
373 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
374 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
375 if (TlsDirectory
->AddressOfCallBacks
)
376 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
378 TlsData
->TlsAddressOfCallBacks
= NULL
;
379 TlsData
->Module
= Module
;
381 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
382 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
383 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
384 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
385 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
386 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
387 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
388 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
392 * Is this region allways writable ?
394 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
396 Entry
= Entry
->Flink
;
400 DPRINT("LdrpInitializeTlsForProccess() done\n");
401 return STATUS_SUCCESS
;
407 OBJECT_ATTRIBUTES ObjectAttributes
;
408 UNICODE_STRING LinkTarget
;
414 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
416 /* Get handle to the 'KnownDlls' directory */
417 RtlInitUnicodeString(&Name
,
419 InitializeObjectAttributes(&ObjectAttributes
,
421 OBJ_CASE_INSENSITIVE
,
424 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
425 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
427 if (!NT_SUCCESS(Status
))
429 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
430 LdrpKnownDllsDirHandle
= NULL
;
434 /* Allocate target name string */
435 LinkTarget
.Length
= 0;
436 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
437 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
439 MAX_PATH
* sizeof(WCHAR
));
440 if (LinkTarget
.Buffer
== NULL
)
442 NtClose(LdrpKnownDllsDirHandle
);
443 LdrpKnownDllsDirHandle
= NULL
;
447 RtlInitUnicodeString(&Name
,
449 InitializeObjectAttributes(&ObjectAttributes
,
451 OBJ_CASE_INSENSITIVE
,
452 LdrpKnownDllsDirHandle
,
454 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
455 SYMBOLIC_LINK_ALL_ACCESS
,
457 if (!NT_SUCCESS(Status
))
459 RtlFreeUnicodeString(&LinkTarget
);
460 NtClose(LdrpKnownDllsDirHandle
);
461 LdrpKnownDllsDirHandle
= NULL
;
465 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
469 if (!NT_SUCCESS(Status
))
471 RtlFreeUnicodeString(&LinkTarget
);
472 NtClose(LdrpKnownDllsDirHandle
);
473 LdrpKnownDllsDirHandle
= NULL
;
476 RtlCreateUnicodeString(&LdrpKnownDllPath
,
479 RtlFreeUnicodeString(&LinkTarget
);
481 DPRINT("LdrpInitLoader() done\n");
485 /***************************************************************************
490 * Adjusts the name of a dll to a fully qualified name.
493 * FullDllName: Pointer to caller supplied storage for the fully
494 * qualified dll name.
495 * DllName: Pointer to the dll name.
496 * BaseName: TRUE: Only the file name is passed to FullDllName
497 * FALSE: The full path is preserved in FullDllName
505 * A given path is not affected by the adjustment, but the file
507 * ntdll --> ntdll.dll
509 * ntdll.xyz --> ntdll.xyz
512 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
513 PUNICODE_STRING DllName
,
516 WCHAR Buffer
[MAX_PATH
];
521 Length
= DllName
->Length
/ sizeof(WCHAR
);
525 /* get the base dll name */
526 Pointer
= DllName
->Buffer
+ Length
;
533 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
536 Length
= Extension
- Pointer
;
537 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
538 Buffer
[Length
] = L
'\0';
542 /* get the full dll name */
543 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
544 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
547 /* Build the DLL's absolute name */
548 Extension
= wcsrchr (Buffer
, L
'.');
549 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
551 /* with extension - remove dot if it's the last character */
552 if (Buffer
[Length
- 1] == L
'.')
558 /* name without extension - assume that it is .dll */
559 memmove (Buffer
+ Length
, L
".dll", 10);
562 RtlCreateUnicodeString(FullDllName
, Buffer
);
565 PLDR_DATA_TABLE_ENTRY
566 LdrAddModuleEntry(PVOID ImageBase
,
567 PIMAGE_NT_HEADERS NTHeaders
,
570 PLDR_DATA_TABLE_ENTRY Module
;
572 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
574 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
575 Module
->DllBase
= (PVOID
)ImageBase
;
576 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
577 if (Module
->EntryPoint
!= 0)
578 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
579 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
580 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
582 /* loading while app is running */
583 Module
->LoadCount
= 1;
586 * loading while app is initializing
587 * dll must not be unloaded
589 Module
->LoadCount
= LDRP_PROCESS_CREATION_TIME
;
593 Module
->TlsIndex
= -1;
594 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
595 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
597 RtlCreateUnicodeString (&Module
->FullDllName
,
599 RtlCreateUnicodeString (&Module
->BaseDllName
,
600 wcsrchr(FullDosName
, L
'\\') + 1);
601 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
603 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
604 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
605 &Module
->InLoadOrderLinks
);
606 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
613 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
614 OUT PUNICODE_STRING FullDosName
,
615 OUT PHANDLE SectionHandle
)
617 OBJECT_ATTRIBUTES ObjectAttributes
;
620 DPRINT("LdrpMapKnownDll() called\n");
622 if (LdrpKnownDllsDirHandle
== NULL
)
624 DPRINT("Invalid 'KnownDlls' directory\n");
625 return STATUS_UNSUCCESSFUL
;
628 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
630 InitializeObjectAttributes(&ObjectAttributes
,
632 OBJ_CASE_INSENSITIVE
,
633 LdrpKnownDllsDirHandle
,
635 Status
= NtOpenSection(SectionHandle
,
636 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
638 if (!NT_SUCCESS(Status
))
640 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
644 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
645 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
646 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
648 FullDosName
->MaximumLength
);
649 if (FullDosName
->Buffer
== NULL
)
651 FullDosName
->Length
= 0;
652 FullDosName
->MaximumLength
= 0;
653 return STATUS_SUCCESS
;
656 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
657 wcscat(FullDosName
->Buffer
, L
"\\");
658 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
660 DPRINT("FullDosName '%wZ'\n", FullDosName
);
662 DPRINT("LdrpMapKnownDll() done\n");
664 return STATUS_SUCCESS
;
669 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
670 IN PUNICODE_STRING DllName
,
671 OUT PUNICODE_STRING FullDosName
,
672 IN BOOLEAN MapAsDataFile
,
673 OUT PHANDLE SectionHandle
)
675 WCHAR SearchPathBuffer
[MAX_PATH
];
676 WCHAR DosName
[MAX_PATH
];
677 UNICODE_STRING FullNtFileName
;
678 OBJECT_ATTRIBUTES FileObjectAttributes
;
680 char BlockBuffer
[1024];
681 PIMAGE_DOS_HEADER DosHeader
;
682 PIMAGE_NT_HEADERS NTHeaders
;
683 IO_STATUS_BLOCK IoStatusBlock
;
687 DPRINT("LdrpMapDllImageFile() called\n");
689 if (SearchPath
== NULL
)
691 /* get application running path */
693 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
695 len
= wcslen (SearchPathBuffer
);
697 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
700 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
702 wcscat (SearchPathBuffer
, L
";");
704 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
705 wcscat (SearchPathBuffer
, L
"\\system32;");
706 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
707 wcscat (SearchPathBuffer
, L
";.");
709 SearchPath
= SearchPathBuffer
;
712 if (RtlDosSearchPath_U (SearchPath
,
718 return STATUS_DLL_NOT_FOUND
;
720 if (!RtlDosPathNameToNtPathName_U (DosName
,
724 return STATUS_DLL_NOT_FOUND
;
726 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
728 InitializeObjectAttributes(&FileObjectAttributes
,
734 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
736 Status
= NtOpenFile(&FileHandle
,
737 GENERIC_READ
|SYNCHRONIZE
,
738 &FileObjectAttributes
,
741 FILE_SYNCHRONOUS_IO_NONALERT
);
742 if (!NT_SUCCESS(Status
))
744 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
745 &FullNtFileName
, Status
);
746 RtlFreeHeap (RtlGetProcessHeap (),
748 FullNtFileName
.Buffer
);
751 RtlFreeHeap (RtlGetProcessHeap (),
753 FullNtFileName
.Buffer
);
758 Status
= NtReadFile(FileHandle
,
767 if (!NT_SUCCESS(Status
))
769 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
775 * Overlay DOS and NT headers structures to the
776 * buffer with DLL's header raw data.
778 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
779 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
781 * Check it is a PE image file.
783 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
784 || (DosHeader
->e_lfanew
== 0L)
785 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
787 DPRINT("NTDLL format invalid\n");
790 return STATUS_UNSUCCESSFUL
;
795 * Create a section for dll.
797 Status
= NtCreateSection(SectionHandle
,
802 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
806 if (!NT_SUCCESS(Status
))
808 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
812 RtlCreateUnicodeString(FullDosName
,
820 /***************************************************************************
837 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
838 IN PULONG LoadFlags OPTIONAL
,
839 IN PUNICODE_STRING Name
,
840 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
843 PLDR_DATA_TABLE_ENTRY Module
;
845 PPEB Peb
= NtCurrentPeb();
847 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
849 SearchPath
? L
" from " : L
"",
850 SearchPath
? SearchPath
: L
"");
852 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
854 if (NT_SUCCESS(Status
) &&
855 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
857 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
859 RtlEnterCriticalSection(Peb
->LoaderLock
);
860 Status
= LdrpAttachProcess();
861 RtlLeaveCriticalSection(Peb
->LoaderLock
);
865 if ((!Module
) && (NT_SUCCESS(Status
)))
868 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
874 /***************************************************************************
876 * LdrFindEntryForAddress
891 LdrFindEntryForAddress(PVOID Address
,
892 PLDR_DATA_TABLE_ENTRY
*Module
)
894 PLIST_ENTRY ModuleListHead
;
896 PLDR_DATA_TABLE_ENTRY ModulePtr
;
898 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
900 if (NtCurrentPeb()->Ldr
== NULL
)
901 return(STATUS_NO_MORE_ENTRIES
);
903 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
904 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
905 Entry
= ModuleListHead
->Flink
;
906 if (Entry
== ModuleListHead
)
908 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
909 return(STATUS_NO_MORE_ENTRIES
);
912 while (Entry
!= ModuleListHead
)
914 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
916 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
918 if ((Address
>= ModulePtr
->DllBase
) &&
919 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
922 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
923 return(STATUS_SUCCESS
);
926 Entry
= Entry
->Flink
;
929 DPRINT("Failed to find module entry.\n");
931 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
932 return(STATUS_NO_MORE_ENTRIES
);
936 /***************************************************************************
938 * LdrFindEntryForName
952 LdrFindEntryForName(PUNICODE_STRING Name
,
953 PLDR_DATA_TABLE_ENTRY
*Module
,
956 PLIST_ENTRY ModuleListHead
;
958 PLDR_DATA_TABLE_ENTRY ModulePtr
;
959 BOOLEAN ContainsPath
;
960 UNICODE_STRING AdjustedName
;
962 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
964 if (NtCurrentPeb()->Ldr
== NULL
)
965 return(STATUS_NO_MORE_ENTRIES
);
967 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
968 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
969 Entry
= ModuleListHead
->Flink
;
970 if (Entry
== ModuleListHead
)
972 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
973 return(STATUS_NO_MORE_ENTRIES
);
976 // NULL is the current process
980 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
981 return(STATUS_SUCCESS
);
984 ContainsPath
= (Name
->Length
>= 2 * sizeof(WCHAR
) && L
':' == Name
->Buffer
[1]);
985 LdrAdjustDllName (&AdjustedName
, Name
, !ContainsPath
);
989 if ((! ContainsPath
&&
990 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
992 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
994 *Module
= LdrpLastModule
;
995 if (Ref
&& (*Module
)->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
997 (*Module
)->LoadCount
++;
999 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1000 RtlFreeUnicodeString(&AdjustedName
);
1001 return(STATUS_SUCCESS
);
1004 while (Entry
!= ModuleListHead
)
1006 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1008 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
1010 if ((! ContainsPath
&&
1011 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1013 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
1015 *Module
= LdrpLastModule
= ModulePtr
;
1016 if (Ref
&& ModulePtr
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1018 ModulePtr
->LoadCount
++;
1020 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1021 RtlFreeUnicodeString(&AdjustedName
);
1022 return(STATUS_SUCCESS
);
1025 Entry
= Entry
->Flink
;
1028 DPRINT("Failed to find dll %wZ\n", Name
);
1029 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1030 RtlFreeUnicodeString(&AdjustedName
);
1031 return(STATUS_NO_MORE_ENTRIES
);
1034 /**********************************************************************
1050 LdrFixupForward(PCHAR ForwardName
)
1052 CHAR NameBuffer
[128];
1053 UNICODE_STRING DllName
;
1056 PLDR_DATA_TABLE_ENTRY Module
;
1059 strcpy(NameBuffer
, ForwardName
);
1060 p
= strchr(NameBuffer
, '.');
1065 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
1066 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1069 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1071 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
1073 if (!NT_SUCCESS(Status
))
1075 Status
= LdrLoadDll(NULL
,
1079 if (NT_SUCCESS(Status
))
1081 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1084 RtlFreeUnicodeString (&DllName
);
1085 if (!NT_SUCCESS(Status
))
1087 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
1091 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1093 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1100 /**********************************************************************
1102 * LdrGetExportByOrdinal
1116 LdrGetExportByOrdinal (
1121 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1122 ULONG ExportDirSize
;
1123 PDWORD
* ExFunctions
;
1126 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1127 RtlImageDirectoryEntryToData (BaseAddress
,
1129 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1133 ExFunctions
= (PDWORD
*)
1136 ExportDir
->AddressOfFunctions
1139 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1141 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1144 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1145 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1148 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1149 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1151 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1152 Function
= LdrFixupForward((PCHAR
)Function
);
1159 /**********************************************************************
1161 * LdrGetExportByName
1172 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1173 * both with NumberOfNames entries.
1177 LdrGetExportByName(PVOID BaseAddress
,
1181 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1182 PDWORD
* ExFunctions
;
1184 USHORT
* ExOrdinals
;
1189 ULONG ExportDirSize
;
1191 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1193 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1194 RtlImageDirectoryEntryToData(BaseAddress
,
1196 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1198 if (ExportDir
== NULL
)
1200 DPRINT1("LdrGetExportByName(): no export directory, "
1201 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1206 //The symbol names may be missing entirely
1207 if (ExportDir
->AddressOfNames
== 0)
1209 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1214 * Get header pointers
1216 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1217 ExportDir
->AddressOfNames
);
1218 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1219 ExportDir
->AddressOfNameOrdinals
);
1220 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1221 ExportDir
->AddressOfFunctions
);
1224 * Check the hint first
1226 if (Hint
< ExportDir
->NumberOfNames
)
1228 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1229 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1231 Ordinal
= ExOrdinals
[Hint
];
1232 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1233 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1234 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1236 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1237 Function
= LdrFixupForward((PCHAR
)Function
);
1238 if (Function
== NULL
)
1240 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1244 if (Function
!= NULL
)
1253 maxn
= ExportDir
->NumberOfNames
- 1;
1254 while (minn
<= maxn
)
1259 mid
= (minn
+ maxn
) / 2;
1261 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1262 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1265 Ordinal
= ExOrdinals
[mid
];
1266 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1267 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1268 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1270 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1271 Function
= LdrFixupForward((PCHAR
)Function
);
1272 if (Function
== NULL
)
1274 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1278 if (Function
!= NULL
)
1281 else if (minn
== maxn
)
1283 DPRINT("LdrGetExportByName(): binary search failed\n");
1296 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1301 /**********************************************************************
1303 * LdrPerformRelocations
1306 * Relocate a DLL's memory image.
1318 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1321 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1322 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1323 ULONG Count
, OldProtect
, OldProtect2
;
1325 PVOID Page
, ProtectPage
, ProtectPage2
;
1330 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1332 return STATUS_SUCCESS
;
1336 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1338 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1340 return STATUS_SUCCESS
;
1343 ProtectSize
= PAGE_SIZE
;
1344 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1345 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1346 RelocationDDir
->VirtualAddress
);
1347 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1348 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1350 while (RelocationDir
< RelocationEnd
&&
1351 RelocationDir
->SizeOfBlock
> 0)
1353 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1355 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1356 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1358 /* Unprotect the page(s) we're about to relocate. */
1360 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1365 if (!NT_SUCCESS(Status
))
1367 DPRINT1("Failed to unprotect relocation target.\n");
1371 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1372 NTHeaders
->OptionalHeader
.SizeOfImage
)
1374 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1375 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1380 if (!NT_SUCCESS(Status
))
1382 DPRINT1("Failed to unprotect relocation target (2).\n");
1383 NtProtectVirtualMemory(NtCurrentProcess(),
1393 ProtectPage2
= NULL
;
1396 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1400 if (RelocationDir
== NULL
)
1401 return STATUS_UNSUCCESSFUL
;
1403 /* Restore old page protection. */
1404 NtProtectVirtualMemory(NtCurrentProcess(),
1410 if (ProtectPage2
!= NULL
)
1412 NtProtectVirtualMemory(NtCurrentProcess(),
1420 return STATUS_SUCCESS
;
1424 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1426 PLDR_DATA_TABLE_ENTRY
* Module
,
1429 ANSI_STRING AnsiDllName
;
1430 UNICODE_STRING DllName
;
1433 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1435 RtlInitAnsiString(&AnsiDllName
, Name
);
1436 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1437 if (!NT_SUCCESS(Status
))
1442 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1443 if (Load
&& !NT_SUCCESS(Status
))
1445 Status
= LdrpLoadModule(SearchPath
,
1450 if (NT_SUCCESS(Status
))
1452 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1454 if (!NT_SUCCESS(Status
))
1456 ULONG ErrorResponse
;
1457 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1459 DPRINT1("failed to load %wZ\n", &DllName
);
1460 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1468 RtlFreeUnicodeString (&DllName
);
1473 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1475 ULONG ErrorResponse
;
1476 ULONG_PTR ErrorParameters
[2];
1477 ANSI_STRING ProcNameAnsi
;
1478 UNICODE_STRING ProcName
;
1483 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1487 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1488 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1489 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1490 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1491 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1497 RtlFreeUnicodeString(&ProcName
);
1501 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1502 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1503 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1506 PVOID
* ImportAddressList
;
1507 PULONG FunctionNameList
;
1513 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1515 return STATUS_UNSUCCESSFUL
;
1518 /* Get the import address list. */
1519 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1521 /* Get the list of functions to import. */
1522 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1524 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1528 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1531 /* Get the size of IAT. */
1533 while (FunctionNameList
[IATSize
] != 0L)
1538 /* Unprotect the region we are about to write into. */
1539 IATBase
= (PVOID
)ImportAddressList
;
1540 IATSize
*= sizeof(PVOID
*);
1541 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1546 if (!NT_SUCCESS(Status
))
1548 DPRINT1("Failed to unprotect IAT.\n");
1552 /* Walk through function list and fixup addresses. */
1553 while (*FunctionNameList
!= 0L)
1555 if ((*FunctionNameList
) & 0x80000000)
1557 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1558 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1559 if ((*ImportAddressList
) == NULL
)
1561 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1562 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1563 return STATUS_ENTRYPOINT_NOT_FOUND
;
1568 IMAGE_IMPORT_BY_NAME
*pe_name
;
1569 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1570 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1571 if ((*ImportAddressList
) == NULL
)
1573 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1574 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1575 return STATUS_ENTRYPOINT_NOT_FOUND
;
1578 ImportAddressList
++;
1582 /* Protect the region we are about to write into. */
1583 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1588 if (!NT_SUCCESS(Status
))
1590 DPRINT1("Failed to protect IAT.\n");
1594 return STATUS_SUCCESS
;
1598 LdrpProcessImportDirectory(
1599 PLDR_DATA_TABLE_ENTRY Module
,
1600 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1604 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1608 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1609 Module
, &Module
->BaseDllName
, ImportedName
);
1612 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1613 RtlImageDirectoryEntryToData(Module
->DllBase
,
1615 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1617 if (ImportModuleDirectory
== NULL
)
1619 return STATUS_UNSUCCESSFUL
;
1622 while (ImportModuleDirectory
->Name
)
1624 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1625 if (0 == _stricmp(Name
, ImportedName
))
1627 Status
= LdrpProcessImportDirectoryEntry(Module
,
1629 ImportModuleDirectory
);
1630 if (!NT_SUCCESS(Status
))
1635 ImportModuleDirectory
++;
1639 return STATUS_SUCCESS
;
1644 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1645 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1648 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1650 PVOID
* ImportAddressList
;
1653 PULONG FunctionNameList
;
1658 PIMAGE_NT_HEADERS NTHeaders
;
1662 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1663 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1665 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1666 RtlImageDirectoryEntryToData(Module
->DllBase
,
1668 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1670 if (ImportModuleDirectory
== NULL
)
1672 return STATUS_UNSUCCESSFUL
;
1675 while (ImportModuleDirectory
->Name
)
1677 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1678 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1681 /* Get the import address list. */
1682 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1684 /* Get the list of functions to import. */
1685 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1687 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1691 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1694 /* Get the size of IAT. */
1696 while (FunctionNameList
[IATSize
] != 0L)
1701 /* Unprotect the region we are about to write into. */
1702 IATBase
= (PVOID
)ImportAddressList
;
1703 IATSize
*= sizeof(PVOID
*);
1704 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1709 if (!NT_SUCCESS(Status
))
1711 DPRINT1("Failed to unprotect IAT.\n");
1715 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1716 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1717 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1718 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1720 /* Walk through function list and fixup addresses. */
1721 while (*FunctionNameList
!= 0L)
1723 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1725 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1727 ImportAddressList
++;
1731 /* Protect the region we are about to write into. */
1732 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1737 if (!NT_SUCCESS(Status
))
1739 DPRINT1("Failed to protect IAT.\n");
1743 ImportModuleDirectory
++;
1745 return STATUS_SUCCESS
;
1749 /**********************************************************************
1754 * Compute the entry point for every symbol the DLL imports
1755 * from other modules.
1767 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1768 IN PLDR_DATA_TABLE_ENTRY Module
)
1770 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1771 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1772 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1773 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1774 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1777 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1782 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1784 /* Check for tls data */
1785 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1786 RtlImageDirectoryEntryToData(Module
->DllBase
,
1788 IMAGE_DIRECTORY_ENTRY_TLS
,
1792 TlsSize
= TlsDirectory
->EndAddressOfRawData
1793 - TlsDirectory
->StartAddressOfRawData
1794 + TlsDirectory
->SizeOfZeroFill
;
1796 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1798 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1799 &Module
->BaseDllName
);
1800 TlsDirectory
= NULL
;
1805 * Process each import module.
1807 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1808 RtlImageDirectoryEntryToData(Module
->DllBase
,
1810 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1813 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1814 RtlImageDirectoryEntryToData(Module
->DllBase
,
1816 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1819 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1821 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1822 return STATUS_UNSUCCESSFUL
;
1824 if (BoundImportDescriptor
)
1826 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1828 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1829 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1831 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1832 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1833 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1834 if (!NT_SUCCESS(Status
))
1836 DPRINT1("failed to load %s\n", ImportedName
);
1839 if (Module
== ImportedModule
)
1841 LdrpDecrementLoadCount(Module
, FALSE
);
1843 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1845 TRACE_LDR("%wZ has stale binding to %wZ\n",
1846 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1847 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1848 if (!NT_SUCCESS(Status
))
1850 DPRINT1("failed to import %s\n", ImportedName
);
1856 BOOLEAN WrongForwarder
;
1857 WrongForwarder
= FALSE
;
1858 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1860 TRACE_LDR("%wZ has stale binding to %s\n",
1861 &Module
->BaseDllName
, ImportedName
);
1865 TRACE_LDR("%wZ has correct binding to %wZ\n",
1866 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1868 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1870 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1872 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1873 PCHAR ForwarderName
;
1875 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1876 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1878 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1879 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1880 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1881 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1882 if (!NT_SUCCESS(Status
))
1884 DPRINT1("failed to load %s\n", ForwarderName
);
1887 if (Module
== ImportedModule
)
1889 LdrpDecrementLoadCount(Module
, FALSE
);
1891 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1892 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1894 TRACE_LDR("%wZ has stale binding to %s\n",
1895 &Module
->BaseDllName
, ForwarderName
);
1896 WrongForwarder
= TRUE
;
1900 TRACE_LDR("%wZ has correct binding to %s\n",
1901 &Module
->BaseDllName
, ForwarderName
);
1905 if (WrongForwarder
||
1906 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1908 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1909 if (!NT_SUCCESS(Status
))
1911 DPRINT1("failed to import %s\n", ImportedName
);
1915 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1917 TRACE_LDR("Adjust imports for %s from %wZ\n",
1918 ImportedName
, &Module
->BaseDllName
);
1919 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1920 if (!NT_SUCCESS(Status
))
1922 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1926 else if (WrongForwarder
)
1930 * Update only forwarders
1932 TRACE_LDR("Stale BIND %s from %wZ\n",
1933 ImportedName
, &Module
->BaseDllName
);
1934 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1935 if (!NT_SUCCESS(Status
))
1937 DPRINT1("faild to import %s\n", ImportedName
);
1946 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1949 else if (ImportModuleDirectory
)
1951 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1953 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1954 while (ImportModuleDirectoryCurrent
->Name
)
1956 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1957 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1959 if (SearchPath
== NULL
)
1961 ModulePath
= LdrpQueryAppPaths(Module
->BaseDllName
.Buffer
);
1963 Status
= LdrpGetOrLoadModule(ModulePath
, ImportedName
, &ImportedModule
, TRUE
);
1964 if (ModulePath
!= NULL
) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath
);
1965 if (NT_SUCCESS(Status
)) goto Success
;
1968 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1969 if (!NT_SUCCESS(Status
))
1971 DPRINT1("failed to load %s\n", ImportedName
);
1975 if (Module
== ImportedModule
)
1977 LdrpDecrementLoadCount(Module
, FALSE
);
1980 TRACE_LDR("Initializing imports for %wZ from %s\n",
1981 &Module
->BaseDllName
, ImportedName
);
1982 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1983 if (!NT_SUCCESS(Status
))
1985 DPRINT1("failed to import %s\n", ImportedName
);
1988 ImportModuleDirectoryCurrent
++;
1992 if (TlsDirectory
&& TlsSize
> 0)
1994 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1997 return STATUS_SUCCESS
;
2001 /**********************************************************************
2006 * 1. Relocate, if needed the EXE.
2007 * 2. Fixup any imported symbol.
2008 * 3. Compute the EXE's entry point.
2012 * Address at which the EXE's image
2016 * Handle of the section that contains
2020 * NULL on error; otherwise the entry point
2021 * to call for initializing the DLL.
2026 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
2027 * Currently the function is only used for the exe.
2029 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
2030 HANDLE SectionHandle
,
2031 PLDR_DATA_TABLE_ENTRY
* Module
,
2035 PEPFUNC EntryPoint
= NULL
;
2036 PIMAGE_DOS_HEADER DosHeader
;
2037 PIMAGE_NT_HEADERS NTHeaders
;
2038 PLDR_DATA_TABLE_ENTRY tmpModule
;
2040 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
2041 ImageBase
, SectionHandle
);
2044 * Overlay DOS and WNT headers structures
2045 * to the DLL's image.
2047 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
2048 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
2051 * If the base address is different from the
2052 * one the DLL is actually loaded, perform any
2055 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2057 DPRINT("LDR: Performing relocations\n");
2058 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
2059 if (!NT_SUCCESS(Status
))
2061 DPRINT1("LdrPerformRelocations() failed\n");
2068 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
2069 (*Module
)->SectionPointer
= SectionHandle
;
2073 Module
= &tmpModule
;
2074 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
2075 if (!NT_SUCCESS(Status
))
2081 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2083 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2087 * If the DLL's imports symbols from other
2088 * modules, fixup the imported calls entry points.
2090 DPRINT("About to fixup imports\n");
2091 Status
= LdrFixupImports(NULL
, *Module
);
2092 if (!NT_SUCCESS(Status
))
2094 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
2097 DPRINT("Fixup done\n");
2098 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2099 Status
= LdrpInitializeTlsForProccess();
2100 if (NT_SUCCESS(Status
))
2102 Status
= LdrpAttachProcess();
2104 if (NT_SUCCESS(Status
))
2106 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2110 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2111 if (!NT_SUCCESS(Status
))
2117 * Compute the DLL's entry point's address.
2119 DPRINT("ImageBase = %p\n", ImageBase
);
2120 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2121 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2123 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2124 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2126 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2131 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2133 IN PUNICODE_STRING Name
,
2134 PLDR_DATA_TABLE_ENTRY
*Module
,
2135 PVOID
*BaseAddress OPTIONAL
)
2137 UNICODE_STRING AdjustedName
;
2138 UNICODE_STRING FullDosName
;
2140 PLDR_DATA_TABLE_ENTRY tmpModule
;
2141 HANDLE SectionHandle
;
2144 PIMAGE_NT_HEADERS NtHeaders
;
2145 BOOLEAN MappedAsDataFile
;
2146 PVOID ArbitraryUserPointer
;
2150 Module
= &tmpModule
;
2152 /* adjust the full dll name */
2153 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2155 DPRINT("%wZ\n", &AdjustedName
);
2157 MappedAsDataFile
= FALSE
;
2158 /* Test if dll is already loaded */
2159 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2160 if (NT_SUCCESS(Status
))
2162 RtlFreeUnicodeString(&AdjustedName
);
2163 if (NULL
!= BaseAddress
)
2165 *BaseAddress
= (*Module
)->DllBase
;
2170 /* Open or create dll image section */
2171 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2172 if (!NT_SUCCESS(Status
))
2174 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2175 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2176 MappedAsDataFile
, &SectionHandle
);
2178 if (!NT_SUCCESS(Status
))
2180 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2181 RtlFreeUnicodeString(&AdjustedName
);
2184 RtlFreeUnicodeString(&AdjustedName
);
2185 /* Map the dll into the process */
2188 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2189 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2190 Status
= NtMapViewOfSection(SectionHandle
,
2200 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2201 if (!NT_SUCCESS(Status
))
2203 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2204 RtlFreeUnicodeString(&FullDosName
);
2205 NtClose(SectionHandle
);
2208 if (NULL
!= BaseAddress
)
2210 *BaseAddress
= ImageBase
;
2212 if (!MappedAsDataFile
)
2214 /* Get and check the NT headers */
2215 NtHeaders
= RtlImageNtHeader(ImageBase
);
2216 if (NtHeaders
== NULL
)
2218 DPRINT1("RtlImageNtHeaders() failed\n");
2219 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2220 NtClose (SectionHandle
);
2221 RtlFreeUnicodeString(&FullDosName
);
2222 return STATUS_UNSUCCESSFUL
;
2225 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2226 if (MappedAsDataFile
)
2228 ASSERT(NULL
!= BaseAddress
);
2229 if (NULL
!= BaseAddress
)
2231 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2234 RtlFreeUnicodeString(&FullDosName
);
2235 NtClose(SectionHandle
);
2236 return STATUS_SUCCESS
;
2238 /* If the base address is different from the
2239 * one the DLL is actually loaded, perform any
2241 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2243 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2244 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2245 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2246 if (!NT_SUCCESS(Status
))
2248 DPRINT1("LdrPerformRelocations() failed\n");
2249 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2250 NtClose (SectionHandle
);
2251 RtlFreeUnicodeString(&FullDosName
);
2252 return STATUS_UNSUCCESSFUL
;
2255 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2256 (*Module
)->SectionPointer
= SectionHandle
;
2257 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2259 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2261 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2263 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2265 /* fixup the imported calls entry points */
2266 Status
= LdrFixupImports(SearchPath
, *Module
);
2267 if (!NT_SUCCESS(Status
))
2269 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2272 #if DBG || defined(KDBG)
2273 LdrpLoadUserModuleSymbols(*Module
);
2274 #endif /* DBG || KDBG */
2275 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2276 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2277 &(*Module
)->InInitializationOrderLinks
);
2278 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2280 return STATUS_SUCCESS
;
2284 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2287 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2288 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2289 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2291 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2298 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2301 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2303 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2307 /* ?????????????????? */
2309 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2311 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2312 RtlImageDirectoryEntryToData(Module
->DllBase
,
2314 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2316 if (BoundImportDescriptor
)
2318 /* dereferencing all imported modules, use the bound import descriptor */
2319 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2320 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2322 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2323 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2324 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2325 if (!NT_SUCCESS(Status
))
2327 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2331 if (Module
!= ImportedModule
)
2333 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2334 if (!NT_SUCCESS(Status
))
2336 DPRINT1("unable to unload %s\n", ImportedName
);
2340 BoundImportDescriptorCurrent
++;
2345 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2346 RtlImageDirectoryEntryToData(Module
->DllBase
,
2348 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2350 if (ImportModuleDirectory
)
2352 /* dereferencing all imported modules, use the import descriptor */
2353 while (ImportModuleDirectory
->Name
)
2355 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2356 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2357 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2358 if (!NT_SUCCESS(Status
))
2360 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2364 if (Module
!= ImportedModule
)
2366 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2367 if (!NT_SUCCESS(Status
))
2369 DPRINT1("unable to unload %s\n", ImportedName
);
2373 ImportModuleDirectory
++;
2381 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2383 LdrpDetachProcess(FALSE
);
2386 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2388 return STATUS_SUCCESS
;
2396 LdrUnloadDll (IN PVOID BaseAddress
)
2398 PLDR_DATA_TABLE_ENTRY Module
;
2401 if (BaseAddress
== NULL
)
2402 return STATUS_SUCCESS
;
2404 if (LdrMappedAsDataFile(&BaseAddress
))
2406 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2410 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2411 if (NT_SUCCESS(Status
))
2413 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2414 Status
= LdrpUnloadModule(Module
, TRUE
);
2425 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2427 PLIST_ENTRY ModuleListHead
;
2429 PLDR_DATA_TABLE_ENTRY Module
;
2432 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2434 Status
= STATUS_DLL_NOT_FOUND
;
2435 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2436 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2437 Entry
= ModuleListHead
->Flink
;
2438 while (Entry
!= ModuleListHead
)
2440 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2442 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2444 if (Module
->DllBase
== BaseAddress
)
2446 if (Module
->TlsIndex
== 0xFFFF)
2448 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2449 Status
= STATUS_SUCCESS
;
2453 Entry
= Entry
->Flink
;
2455 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2463 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2464 IN PULONG DllCharacteristics
,
2465 IN PUNICODE_STRING DllName
,
2466 OUT PVOID
*DllHandle
)
2468 PLDR_DATA_TABLE_ENTRY Module
;
2471 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2472 DllName
, DllPath
? DllPath
: L
"");
2474 /* NULL is the current executable */
2475 if (DllName
== NULL
)
2477 *DllHandle
= ExeModule
->DllBase
;
2478 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2479 return STATUS_SUCCESS
;
2482 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2483 if (NT_SUCCESS(Status
))
2485 *DllHandle
= Module
->DllBase
;
2486 return STATUS_SUCCESS
;
2489 DPRINT("Failed to find dll %wZ\n", DllName
);
2491 return STATUS_DLL_NOT_FOUND
;
2498 LdrAddRefDll(IN ULONG Flags
,
2499 IN PVOID BaseAddress
)
2501 PLIST_ENTRY ModuleListHead
;
2503 PLDR_DATA_TABLE_ENTRY Module
;
2506 if (Flags
& ~(LDR_PIN_MODULE
))
2508 return STATUS_INVALID_PARAMETER
;
2511 Status
= STATUS_DLL_NOT_FOUND
;
2512 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2513 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2514 Entry
= ModuleListHead
->Flink
;
2515 while (Entry
!= ModuleListHead
)
2517 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2519 if (Module
->DllBase
== BaseAddress
)
2521 if (Flags
& LDR_PIN_MODULE
)
2523 Module
->Flags
|= LDRP_STATIC_LINK
;
2527 LdrpIncrementLoadCount(Module
,
2530 Status
= STATUS_SUCCESS
;
2533 Entry
= Entry
->Flink
;
2535 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2543 RtlPcToFileHeader(IN PVOID PcValue
,
2546 PLIST_ENTRY ModuleListHead
;
2548 PLDR_DATA_TABLE_ENTRY Module
;
2549 PVOID ImageBase
= NULL
;
2551 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2552 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2553 Entry
= ModuleListHead
->Flink
;
2554 while (Entry
!= ModuleListHead
)
2556 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2558 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2559 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2561 ImageBase
= Module
->DllBase
;
2564 Entry
= Entry
->Flink
;
2566 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2568 *BaseOfImage
= ImageBase
;
2576 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2577 IN PANSI_STRING Name
,
2579 OUT PVOID
*ProcedureAddress
)
2581 NTSTATUS Status
= STATUS_PROCEDURE_NOT_FOUND
;
2582 if (Name
&& Name
->Length
)
2584 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2588 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2591 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2592 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2596 if (Name
&& Name
->Length
)
2599 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2600 if (*ProcedureAddress
!= NULL
)
2602 Status
= STATUS_SUCCESS
;
2604 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2609 Ordinal
&= 0x0000FFFF;
2610 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2611 if (*ProcedureAddress
)
2613 Status
= STATUS_SUCCESS
;
2615 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2618 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2620 Status
= STATUS_DLL_NOT_FOUND
;
2627 /**********************************************************************
2632 * Unload dll's which are no longer referenced from others dll's
2643 * The loader lock must be held on enty.
2646 LdrpDetachProcess(BOOLEAN UnloadAll
)
2648 PLIST_ENTRY ModuleListHead
;
2650 PLDR_DATA_TABLE_ENTRY Module
;
2651 static ULONG CallingCount
= 0;
2653 DPRINT("LdrpDetachProcess() called for %wZ\n",
2654 &ExeModule
->BaseDllName
);
2657 LdrpDllShutdownInProgress
= TRUE
;
2661 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2662 Entry
= ModuleListHead
->Blink
;
2663 while (Entry
!= ModuleListHead
)
2665 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2666 if (((UnloadAll
&& Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0) &&
2667 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2668 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2670 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2671 if (Module
== LdrpLastModule
)
2673 LdrpLastModule
= NULL
;
2675 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2677 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2678 &Module
->BaseDllName
, Module
->EntryPoint
);
2679 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2683 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2685 Entry
= ModuleListHead
->Blink
;
2689 Entry
= Entry
->Blink
;
2693 if (CallingCount
== 1)
2695 Entry
= ModuleListHead
->Blink
;
2696 while (Entry
!= ModuleListHead
)
2698 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2699 Entry
= Entry
->Blink
;
2700 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2701 ((UnloadAll
&& Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0))
2703 /* remove the module entry from the list */
2704 RemoveEntryList (&Module
->InLoadOrderLinks
);
2705 RemoveEntryList (&Module
->InInitializationOrderLinks
);
2707 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2708 NtClose (Module
->SectionPointer
);
2710 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2712 RtlFreeUnicodeString (&Module
->FullDllName
);
2713 RtlFreeUnicodeString (&Module
->BaseDllName
);
2715 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2720 DPRINT("LdrpDetachProcess() done\n");
2723 /**********************************************************************
2728 * Initialize all dll's which are prepered for loading
2739 * The loader lock must be held on entry.
2743 LdrpAttachProcess(VOID
)
2745 PLIST_ENTRY ModuleListHead
;
2747 PLDR_DATA_TABLE_ENTRY Module
;
2749 NTSTATUS Status
= STATUS_SUCCESS
;
2751 DPRINT("LdrpAttachProcess() called for %wZ\n",
2752 &ExeModule
->BaseDllName
);
2754 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2755 Entry
= ModuleListHead
->Flink
;
2756 while (Entry
!= ModuleListHead
)
2758 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2759 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2761 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2762 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2763 &Module
->BaseDllName
, Module
->EntryPoint
);
2764 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2767 Status
= STATUS_DLL_INIT_FAILED
;
2770 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2772 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2776 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2778 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2780 Entry
= Entry
->Flink
;
2783 DPRINT("LdrpAttachProcess() done\n");
2792 RtlDllShutdownInProgress (VOID
)
2794 return LdrpDllShutdownInProgress
;
2801 LdrShutdownProcess (VOID
)
2803 LdrpDetachProcess(TRUE
);
2804 return STATUS_SUCCESS
;
2812 LdrpAttachThread (VOID
)
2814 PLIST_ENTRY ModuleListHead
;
2816 PLDR_DATA_TABLE_ENTRY Module
;
2819 DPRINT("LdrpAttachThread() called for %wZ\n",
2820 &ExeModule
->BaseDllName
);
2822 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2824 Status
= LdrpInitializeTlsForThread();
2826 if (NT_SUCCESS(Status
))
2828 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2829 Entry
= ModuleListHead
->Flink
;
2831 while (Entry
!= ModuleListHead
)
2833 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2834 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2835 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2836 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2838 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2839 &Module
->BaseDllName
, Module
->EntryPoint
);
2840 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2842 Entry
= Entry
->Flink
;
2845 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2846 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2847 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2850 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2852 DPRINT("LdrpAttachThread() done\n");
2862 LdrShutdownThread (VOID
)
2864 PLIST_ENTRY ModuleListHead
;
2866 PLDR_DATA_TABLE_ENTRY Module
;
2868 DPRINT("LdrShutdownThread() called for %wZ\n",
2869 &ExeModule
->BaseDllName
);
2871 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2873 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2874 Entry
= ModuleListHead
->Blink
;
2875 while (Entry
!= ModuleListHead
)
2877 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2879 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2880 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2881 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2883 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2884 &Module
->BaseDllName
, Module
->EntryPoint
);
2885 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2887 Entry
= Entry
->Blink
;
2890 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2894 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2897 DPRINT("LdrShutdownThread() done\n");
2899 return STATUS_SUCCESS
;
2903 /***************************************************************************
2905 * LdrQueryProcessModuleInformation
2920 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2921 IN ULONG Size OPTIONAL
,
2922 OUT PULONG ReturnedSize
)
2924 PLIST_ENTRY ModuleListHead
;
2926 PLDR_DATA_TABLE_ENTRY Module
;
2927 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2928 NTSTATUS Status
= STATUS_SUCCESS
;
2929 ULONG UsedSize
= sizeof(ULONG
);
2930 ANSI_STRING AnsiString
;
2933 DPRINT("LdrQueryProcessModuleInformation() called\n");
2934 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2935 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2937 if (ModuleInformation
== NULL
|| Size
== 0)
2939 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2943 ModuleInformation
->NumberOfModules
= 0;
2944 ModulePtr
= &ModuleInformation
->Modules
[0];
2945 Status
= STATUS_SUCCESS
;
2948 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2949 Entry
= ModuleListHead
->Flink
;
2951 while (Entry
!= ModuleListHead
)
2953 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2955 DPRINT(" Module %wZ\n",
2956 &Module
->FullDllName
);
2958 if (UsedSize
> Size
)
2960 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2962 else if (ModuleInformation
!= NULL
)
2964 ModulePtr
->Section
= 0;
2965 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2966 ModulePtr
->ImageBase
= Module
->DllBase
;
2967 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2968 ModulePtr
->Flags
= Module
->Flags
;
2969 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2970 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2971 ModulePtr
->LoadCount
= Module
->LoadCount
;
2973 AnsiString
.Length
= 0;
2974 AnsiString
.MaximumLength
= 256;
2975 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2976 RtlUnicodeStringToAnsiString(&AnsiString
,
2977 &Module
->FullDllName
,
2980 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2982 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2984 ModulePtr
->OffsetToFileName
= 0;
2987 ModuleInformation
->NumberOfModules
++;
2989 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2991 Entry
= Entry
->Flink
;
2994 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2996 if (ReturnedSize
!= 0)
2997 *ReturnedSize
= UsedSize
;
2999 DPRINT("LdrQueryProcessModuleInformation() done\n");
3006 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
3009 PIMAGE_NT_HEADERS Header
;
3016 Header
= RtlImageNtHeader (BaseAddress
);
3020 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
3025 Ptr
= (PUSHORT
) BaseAddress
;
3026 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
3029 if (HIWORD(Sum
) != 0)
3031 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3038 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
3039 if (HIWORD(Sum
) != 0)
3041 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3045 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
3047 /* Subtract image checksum from calculated checksum. */
3048 /* fix low word of checksum */
3049 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
3051 CalcSum
-= LOWORD(HeaderSum
);
3055 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
3058 /* fix high word of checksum */
3059 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
3061 CalcSum
-= HIWORD(HeaderSum
);
3065 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
3068 /* add file length */
3069 CalcSum
+= ImageSize
;
3071 return (BOOLEAN
)(CalcSum
== HeaderSum
);
3075 * Compute size of an image as it is actually present in virt memory
3076 * (i.e. excluding NEVER_LOAD sections)
3079 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
3081 PIMAGE_SECTION_HEADER SectionHeader
;
3082 unsigned SectionIndex
;
3085 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
3086 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
3088 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
3090 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
3091 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
3093 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
3098 return ResidentSize
;
3102 /***************************************************************************
3104 * LdrVerifyImageMatchesChecksum
3119 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3124 FILE_STANDARD_INFORMATION FileInfo
;
3125 IO_STATUS_BLOCK IoStatusBlock
;
3126 HANDLE SectionHandle
;
3132 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3134 Status
= NtCreateSection (&SectionHandle
,
3141 if (!NT_SUCCESS(Status
))
3143 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3149 Status
= NtMapViewOfSection (SectionHandle
,
3150 NtCurrentProcess (),
3159 if (!NT_SUCCESS(Status
))
3161 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3162 NtClose (SectionHandle
);
3166 Status
= NtQueryInformationFile (FileHandle
,
3169 sizeof (FILE_STANDARD_INFORMATION
),
3170 FileStandardInformation
);
3171 if (!NT_SUCCESS(Status
))
3173 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3174 NtUnmapViewOfSection (NtCurrentProcess (),
3176 NtClose (SectionHandle
);
3180 Result
= LdrpCheckImageChecksum (BaseAddress
,
3181 FileInfo
.EndOfFile
.u
.LowPart
);
3182 if (Result
== FALSE
)
3184 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3187 NtUnmapViewOfSection (NtCurrentProcess (),
3190 NtClose (SectionHandle
);
3196 /***************************************************************************
3198 * LdrQueryImageFileExecutionOptions
3213 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3214 IN PCWSTR ValueName
,
3217 IN ULONG BufferSize
,
3218 OUT PULONG ReturnedLength OPTIONAL
)
3220 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3221 OBJECT_ATTRIBUTES ObjectAttributes
;
3222 UNICODE_STRING ValueNameString
;
3223 UNICODE_STRING KeyName
;
3224 WCHAR NameBuffer
[256];
3232 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3233 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3236 Ptr
= SubKey
->Buffer
;
3242 wcscat (NameBuffer
, Ptr
);
3243 RtlInitUnicodeString (&KeyName
,
3246 InitializeObjectAttributes (&ObjectAttributes
,
3248 OBJ_CASE_INSENSITIVE
,
3252 Status
= NtOpenKey (&KeyHandle
,
3255 if (!NT_SUCCESS(Status
))
3257 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3261 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3262 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3265 if (KeyInfo
== NULL
)
3267 NtClose (KeyHandle
);
3268 return STATUS_INSUFFICIENT_RESOURCES
;
3271 RtlInitUnicodeString (&ValueNameString
,
3273 Status
= NtQueryValueKey (KeyHandle
,
3275 KeyValuePartialInformation
,
3279 if (Status
== STATUS_BUFFER_OVERFLOW
)
3281 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3282 RtlFreeHeap (RtlGetProcessHeap(),
3285 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3288 if (KeyInfo
== NULL
)
3290 NtClose (KeyHandle
);
3291 return STATUS_INSUFFICIENT_RESOURCES
;
3294 Status
= NtQueryValueKey (KeyHandle
,
3296 KeyValuePartialInformation
,
3301 NtClose (KeyHandle
);
3303 if (!NT_SUCCESS(Status
))
3305 if (KeyInfo
!= NULL
)
3307 RtlFreeHeap (RtlGetProcessHeap(),
3314 if (KeyInfo
->Type
!= Type
)
3316 RtlFreeHeap (RtlGetProcessHeap(),
3319 return STATUS_OBJECT_TYPE_MISMATCH
;
3322 ResultSize
= BufferSize
;
3323 if (ResultSize
< KeyInfo
->DataLength
)
3325 Status
= STATUS_BUFFER_OVERFLOW
;
3329 ResultSize
= KeyInfo
->DataLength
;
3331 RtlCopyMemory (Buffer
,
3335 RtlFreeHeap (RtlGetProcessHeap(),
3339 if (ReturnedLength
!= NULL
)
3341 *ReturnedLength
= ResultSize
;
3348 PIMAGE_BASE_RELOCATION NTAPI
3349 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3351 IN PUSHORT TypeOffset
,
3360 for (i
= 0; i
< Count
; i
++)
3362 Offset
= *TypeOffset
& 0xFFF;
3363 Type
= *TypeOffset
>> 12;
3367 case IMAGE_REL_BASED_ABSOLUTE
:
3370 case IMAGE_REL_BASED_HIGH
:
3371 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3372 *ShortPtr
+= HIWORD(Delta
);
3375 case IMAGE_REL_BASED_LOW
:
3376 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3377 *ShortPtr
+= LOWORD(Delta
);
3380 case IMAGE_REL_BASED_HIGHLOW
:
3381 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3385 case IMAGE_REL_BASED_DIR64
:
3386 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3391 case IMAGE_REL_BASED_HIGHADJ
:
3392 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3394 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3401 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3406 LdrLockLoaderLock(IN ULONG Flags
,
3407 OUT PULONG Disposition OPTIONAL
,
3408 OUT PULONG Cookie OPTIONAL
)
3411 return STATUS_NOT_IMPLEMENTED
;
3416 LdrUnlockLoaderLock(IN ULONG Flags
,
3417 IN ULONG Cookie OPTIONAL
)
3420 return STATUS_NOT_IMPLEMENTED
;
3425 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)