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 *****************************************************************/
67 LdrMappedAsDataFile(PVOID
*BaseAddress
)
69 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
71 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
78 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
83 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
85 LoadCount
= Module
->LoadCount
;
86 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
92 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
97 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
102 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
104 LoadCount
= Module
->LoadCount
;
105 if (Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
111 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
116 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
120 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
122 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
127 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
131 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
133 PIMAGE_TLS_CALLBACK
*TlsCallback
;
134 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
)
136 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
141 TRACE_LDR("%wZ - Calling tls callback at %x\n",
142 &Module
->BaseDllName
, *TlsCallback
);
143 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
150 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
152 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
153 Module
->EntryPoint
== 0)
157 LdrpTlsCallback(Module
, dwReason
);
158 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
162 LdrpQueryAppPaths(IN PCWSTR ImageName
)
164 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
165 OBJECT_ATTRIBUTES ObjectAttributes
;
166 WCHAR SearchPathBuffer
[5*MAX_PATH
];
167 UNICODE_STRING ValueNameString
;
168 UNICODE_STRING KeyName
;
169 WCHAR NameBuffer
[MAX_PATH
];
177 _snwprintf(NameBuffer
,
178 sizeof(NameBuffer
) / sizeof(WCHAR
),
179 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
182 RtlInitUnicodeString(&KeyName
, NameBuffer
);
184 InitializeObjectAttributes(&ObjectAttributes
,
186 OBJ_CASE_INSENSITIVE
,
190 Status
= NtOpenKey(&KeyHandle
,
193 if (!NT_SUCCESS(Status
))
195 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
199 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 256 * sizeof(WCHAR
);
201 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize
);
204 DPRINT("RtlAllocateHeap() failed\n");
209 RtlInitUnicodeString(&ValueNameString
,
212 Status
= NtQueryValueKey(KeyHandle
,
214 KeyValuePartialInformation
,
219 if (!NT_SUCCESS(Status
))
222 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
226 RtlCopyMemory(SearchPathBuffer
,
228 KeyInfo
->DataLength
);
230 /* Free KeyInfo memory, we won't need it anymore */
231 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
233 /* Close the key handle */
236 /* get application running path */
237 wcscat(SearchPathBuffer
, L
";");
238 wcscat(SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
); // FIXME: Don't rely on it being NULL-terminated!!!
240 /* Remove trailing backslash */
241 Backslash
= wcsrchr(SearchPathBuffer
, L
'\\');
242 if (Backslash
) Backslash
= L
'\0';
244 wcscat(SearchPathBuffer
, L
";");
246 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
247 wcscat(SearchPathBuffer
, L
"\\system32;");
248 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
249 wcscat(SearchPathBuffer
, L
";.");
251 /* Copy it to the heap allocd memory */
252 Path
= RtlAllocateHeap(RtlGetProcessHeap(),
254 wcslen(SearchPathBuffer
) * sizeof(WCHAR
));
258 DPRINT1("RtlAllocateHeap() failed\n");
262 wcscpy(Path
, SearchPathBuffer
);
268 LdrpInitializeTlsForThread(VOID
)
274 PTEB Teb
= NtCurrentTeb();
276 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
278 Teb
->StaticUnicodeString
.Length
= 0;
279 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
280 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
282 if (LdrpTlsCount
> 0)
284 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
286 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
287 if (TlsPointers
== NULL
)
289 DPRINT1("failed to allocate thread tls data\n");
290 return STATUS_NO_MEMORY
;
293 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
294 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
296 TlsInfo
= LdrpTlsArray
;
297 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
299 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
300 TlsPointers
[i
] = TlsData
;
301 if (TlsInfo
->TlsDataSize
)
303 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
304 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
306 if (TlsInfo
->TlsZeroSize
)
308 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
309 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
314 DPRINT("LdrpInitializeTlsForThread() done\n");
315 return STATUS_SUCCESS
;
319 LdrpInitializeTlsForProccess(VOID
)
321 PLIST_ENTRY ModuleListHead
;
323 PLDR_DATA_TABLE_ENTRY Module
;
324 PIMAGE_TLS_DIRECTORY TlsDirectory
;
328 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
330 if (LdrpTlsCount
> 0)
332 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
334 LdrpTlsCount
* sizeof(TLS_DATA
));
335 if (LdrpTlsArray
== NULL
)
337 DPRINT1("Failed to allocate global tls data\n");
338 return STATUS_NO_MEMORY
;
341 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
342 Entry
= ModuleListHead
->Flink
;
343 while (Entry
!= ModuleListHead
)
345 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
346 if (Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
&&
347 Module
->TlsIndex
!= 0xFFFF)
349 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
350 RtlImageDirectoryEntryToData(Module
->DllBase
,
352 IMAGE_DIRECTORY_ENTRY_TLS
,
354 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
355 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
356 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
357 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
358 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
359 if (TlsDirectory
->AddressOfCallBacks
)
360 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
362 TlsData
->TlsAddressOfCallBacks
= NULL
;
363 TlsData
->Module
= Module
;
365 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
366 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
367 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
368 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
369 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
370 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
371 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
372 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
376 * Is this region allways writable ?
378 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
380 Entry
= Entry
->Flink
;
384 DPRINT("LdrpInitializeTlsForProccess() done\n");
385 return STATUS_SUCCESS
;
391 OBJECT_ATTRIBUTES ObjectAttributes
;
392 UNICODE_STRING LinkTarget
;
398 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
400 /* Get handle to the 'KnownDlls' directory */
401 RtlInitUnicodeString(&Name
,
403 InitializeObjectAttributes(&ObjectAttributes
,
405 OBJ_CASE_INSENSITIVE
,
408 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
409 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
411 if (!NT_SUCCESS(Status
))
413 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
414 LdrpKnownDllsDirHandle
= NULL
;
418 /* Allocate target name string */
419 LinkTarget
.Length
= 0;
420 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
421 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
423 MAX_PATH
* sizeof(WCHAR
));
424 if (LinkTarget
.Buffer
== NULL
)
426 NtClose(LdrpKnownDllsDirHandle
);
427 LdrpKnownDllsDirHandle
= NULL
;
431 RtlInitUnicodeString(&Name
,
433 InitializeObjectAttributes(&ObjectAttributes
,
435 OBJ_CASE_INSENSITIVE
,
436 LdrpKnownDllsDirHandle
,
438 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
439 SYMBOLIC_LINK_ALL_ACCESS
,
441 if (!NT_SUCCESS(Status
))
443 RtlFreeUnicodeString(&LinkTarget
);
444 NtClose(LdrpKnownDllsDirHandle
);
445 LdrpKnownDllsDirHandle
= NULL
;
449 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
453 if (!NT_SUCCESS(Status
))
455 RtlFreeUnicodeString(&LinkTarget
);
456 NtClose(LdrpKnownDllsDirHandle
);
457 LdrpKnownDllsDirHandle
= NULL
;
460 RtlCreateUnicodeString(&LdrpKnownDllPath
,
463 RtlFreeUnicodeString(&LinkTarget
);
465 DPRINT("LdrpInitLoader() done\n");
469 /***************************************************************************
474 * Adjusts the name of a dll to a fully qualified name.
477 * FullDllName: Pointer to caller supplied storage for the fully
478 * qualified dll name.
479 * DllName: Pointer to the dll name.
480 * BaseName: TRUE: Only the file name is passed to FullDllName
481 * FALSE: The full path is preserved in FullDllName
489 * A given path is not affected by the adjustment, but the file
491 * ntdll --> ntdll.dll
493 * ntdll.xyz --> ntdll.xyz
496 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
497 PUNICODE_STRING DllName
,
500 WCHAR Buffer
[MAX_PATH
];
505 Length
= DllName
->Length
/ sizeof(WCHAR
);
509 /* get the base dll name */
510 Pointer
= DllName
->Buffer
+ Length
;
517 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
520 Length
= Extension
- Pointer
;
521 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
522 Buffer
[Length
] = L
'\0';
526 /* get the full dll name */
527 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
528 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
531 /* Build the DLL's absolute name */
532 Extension
= wcsrchr (Buffer
, L
'.');
533 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
535 /* with extension - remove dot if it's the last character */
536 if (Buffer
[Length
- 1] == L
'.')
542 /* name without extension - assume that it is .dll */
543 memmove (Buffer
+ Length
, L
".dll", 10);
546 RtlCreateUnicodeString(FullDllName
, Buffer
);
549 PLDR_DATA_TABLE_ENTRY
550 LdrAddModuleEntry(PVOID ImageBase
,
551 PIMAGE_NT_HEADERS NTHeaders
,
554 PLDR_DATA_TABLE_ENTRY Module
;
556 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
558 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
559 Module
->DllBase
= (PVOID
)ImageBase
;
560 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
561 if (Module
->EntryPoint
!= 0)
562 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
563 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
564 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
566 /* loading while app is running */
567 Module
->LoadCount
= 1;
570 * loading while app is initializing
571 * dll must not be unloaded
573 Module
->LoadCount
= LDRP_PROCESS_CREATION_TIME
;
577 Module
->TlsIndex
= -1;
578 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
579 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
581 RtlCreateUnicodeString (&Module
->FullDllName
,
583 RtlCreateUnicodeString (&Module
->BaseDllName
,
584 wcsrchr(FullDosName
, L
'\\') + 1);
585 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
587 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
588 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
589 &Module
->InLoadOrderLinks
);
590 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
597 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
598 OUT PUNICODE_STRING FullDosName
,
599 OUT PHANDLE SectionHandle
)
601 OBJECT_ATTRIBUTES ObjectAttributes
;
604 DPRINT("LdrpMapKnownDll() called\n");
606 if (LdrpKnownDllsDirHandle
== NULL
)
608 DPRINT("Invalid 'KnownDlls' directory\n");
609 return STATUS_UNSUCCESSFUL
;
612 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
614 InitializeObjectAttributes(&ObjectAttributes
,
616 OBJ_CASE_INSENSITIVE
,
617 LdrpKnownDllsDirHandle
,
619 Status
= NtOpenSection(SectionHandle
,
620 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
622 if (!NT_SUCCESS(Status
))
624 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
628 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
629 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
630 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
632 FullDosName
->MaximumLength
);
633 if (FullDosName
->Buffer
== NULL
)
635 FullDosName
->Length
= 0;
636 FullDosName
->MaximumLength
= 0;
637 return STATUS_SUCCESS
;
640 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
641 wcscat(FullDosName
->Buffer
, L
"\\");
642 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
644 DPRINT("FullDosName '%wZ'\n", FullDosName
);
646 DPRINT("LdrpMapKnownDll() done\n");
648 return STATUS_SUCCESS
;
653 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
654 IN PUNICODE_STRING DllName
,
655 OUT PUNICODE_STRING FullDosName
,
656 IN BOOLEAN MapAsDataFile
,
657 OUT PHANDLE SectionHandle
)
659 WCHAR SearchPathBuffer
[MAX_PATH
];
660 WCHAR DosName
[MAX_PATH
];
661 UNICODE_STRING FullNtFileName
;
662 OBJECT_ATTRIBUTES FileObjectAttributes
;
664 char BlockBuffer
[1024];
665 PIMAGE_DOS_HEADER DosHeader
;
666 PIMAGE_NT_HEADERS NTHeaders
;
667 IO_STATUS_BLOCK IoStatusBlock
;
671 DPRINT("LdrpMapDllImageFile() called\n");
673 if (SearchPath
== NULL
)
675 /* get application running path */
677 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
679 len
= wcslen (SearchPathBuffer
);
681 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
684 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
686 wcscat (SearchPathBuffer
, L
";");
688 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
689 wcscat (SearchPathBuffer
, L
"\\system32;");
690 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
691 wcscat (SearchPathBuffer
, L
";.");
693 SearchPath
= SearchPathBuffer
;
696 if (RtlDosSearchPath_U (SearchPath
,
702 return STATUS_DLL_NOT_FOUND
;
704 if (!RtlDosPathNameToNtPathName_U (DosName
,
708 return STATUS_DLL_NOT_FOUND
;
710 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
712 InitializeObjectAttributes(&FileObjectAttributes
,
718 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
720 Status
= NtOpenFile(&FileHandle
,
721 GENERIC_READ
|SYNCHRONIZE
,
722 &FileObjectAttributes
,
725 FILE_SYNCHRONOUS_IO_NONALERT
);
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
729 &FullNtFileName
, Status
);
730 RtlFreeHeap (RtlGetProcessHeap (),
732 FullNtFileName
.Buffer
);
735 RtlFreeHeap (RtlGetProcessHeap (),
737 FullNtFileName
.Buffer
);
742 Status
= NtReadFile(FileHandle
,
751 if (!NT_SUCCESS(Status
))
753 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
759 * Overlay DOS and NT headers structures to the
760 * buffer with DLL's header raw data.
762 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
763 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
765 * Check it is a PE image file.
767 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
768 || (DosHeader
->e_lfanew
== 0L)
769 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
771 DPRINT("NTDLL format invalid\n");
774 return STATUS_UNSUCCESSFUL
;
779 * Create a section for dll.
781 Status
= NtCreateSection(SectionHandle
,
786 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
790 if (!NT_SUCCESS(Status
))
792 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
796 RtlCreateUnicodeString(FullDosName
,
804 /***************************************************************************
821 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
822 IN PULONG LoadFlags OPTIONAL
,
823 IN PUNICODE_STRING Name
,
824 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
827 PLDR_DATA_TABLE_ENTRY Module
;
829 PPEB Peb
= NtCurrentPeb();
831 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
833 SearchPath
? L
" from " : L
"",
834 SearchPath
? SearchPath
: L
"");
836 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
838 if (NT_SUCCESS(Status
) &&
839 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
841 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
843 RtlEnterCriticalSection(Peb
->LoaderLock
);
844 Status
= LdrpAttachProcess();
845 RtlLeaveCriticalSection(Peb
->LoaderLock
);
849 if ((!Module
) && (NT_SUCCESS(Status
)))
852 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
858 /***************************************************************************
860 * LdrFindEntryForAddress
875 LdrFindEntryForAddress(PVOID Address
,
876 PLDR_DATA_TABLE_ENTRY
*Module
)
878 PLIST_ENTRY ModuleListHead
;
880 PLDR_DATA_TABLE_ENTRY ModulePtr
;
882 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
884 if (NtCurrentPeb()->Ldr
== NULL
)
885 return(STATUS_NO_MORE_ENTRIES
);
887 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
888 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
889 Entry
= ModuleListHead
->Flink
;
890 if (Entry
== ModuleListHead
)
892 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
893 return(STATUS_NO_MORE_ENTRIES
);
896 while (Entry
!= ModuleListHead
)
898 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
900 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
902 if ((Address
>= ModulePtr
->DllBase
) &&
903 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
906 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
907 return(STATUS_SUCCESS
);
910 Entry
= Entry
->Flink
;
913 DPRINT("Failed to find module entry.\n");
915 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
916 return(STATUS_NO_MORE_ENTRIES
);
920 /***************************************************************************
922 * LdrFindEntryForName
936 LdrFindEntryForName(PUNICODE_STRING Name
,
937 PLDR_DATA_TABLE_ENTRY
*Module
,
940 PLIST_ENTRY ModuleListHead
;
942 PLDR_DATA_TABLE_ENTRY ModulePtr
;
943 BOOLEAN ContainsPath
;
944 UNICODE_STRING AdjustedName
;
946 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
948 if (NtCurrentPeb()->Ldr
== NULL
)
949 return(STATUS_NO_MORE_ENTRIES
);
951 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
952 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
953 Entry
= ModuleListHead
->Flink
;
954 if (Entry
== ModuleListHead
)
956 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
957 return(STATUS_NO_MORE_ENTRIES
);
960 // NULL is the current process
964 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
965 return(STATUS_SUCCESS
);
968 ContainsPath
= (Name
->Length
>= 2 * sizeof(WCHAR
) && L
':' == Name
->Buffer
[1]);
969 LdrAdjustDllName (&AdjustedName
, Name
, !ContainsPath
);
973 if ((! ContainsPath
&&
974 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
976 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
978 *Module
= LdrpLastModule
;
979 if (Ref
&& (*Module
)->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
981 (*Module
)->LoadCount
++;
983 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
984 RtlFreeUnicodeString(&AdjustedName
);
985 return(STATUS_SUCCESS
);
988 while (Entry
!= ModuleListHead
)
990 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
992 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
994 if ((! ContainsPath
&&
995 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
997 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
999 *Module
= LdrpLastModule
= ModulePtr
;
1000 if (Ref
&& ModulePtr
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1002 ModulePtr
->LoadCount
++;
1004 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1005 RtlFreeUnicodeString(&AdjustedName
);
1006 return(STATUS_SUCCESS
);
1009 Entry
= Entry
->Flink
;
1012 DPRINT("Failed to find dll %wZ\n", Name
);
1013 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1014 RtlFreeUnicodeString(&AdjustedName
);
1015 return(STATUS_NO_MORE_ENTRIES
);
1018 /**********************************************************************
1034 LdrFixupForward(PCHAR ForwardName
)
1036 CHAR NameBuffer
[128];
1037 UNICODE_STRING DllName
;
1040 PLDR_DATA_TABLE_ENTRY Module
;
1043 strcpy(NameBuffer
, ForwardName
);
1044 p
= strchr(NameBuffer
, '.');
1049 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
1050 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1053 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1055 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
1057 if (!NT_SUCCESS(Status
))
1059 Status
= LdrLoadDll(NULL
,
1063 if (NT_SUCCESS(Status
))
1065 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1068 RtlFreeUnicodeString (&DllName
);
1069 if (!NT_SUCCESS(Status
))
1071 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
1075 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1077 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1084 /**********************************************************************
1086 * LdrGetExportByOrdinal
1100 LdrGetExportByOrdinal (
1105 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1106 ULONG ExportDirSize
;
1107 PDWORD
* ExFunctions
;
1110 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1111 RtlImageDirectoryEntryToData (BaseAddress
,
1113 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1117 ExFunctions
= (PDWORD
*)
1120 ExportDir
->AddressOfFunctions
1123 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1125 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1128 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1129 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1132 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1133 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1135 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1136 Function
= LdrFixupForward((PCHAR
)Function
);
1143 /**********************************************************************
1145 * LdrGetExportByName
1156 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1157 * both with NumberOfNames entries.
1161 LdrGetExportByName(PVOID BaseAddress
,
1165 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1166 PDWORD
* ExFunctions
;
1168 USHORT
* ExOrdinals
;
1173 ULONG ExportDirSize
;
1175 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1177 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1178 RtlImageDirectoryEntryToData(BaseAddress
,
1180 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1182 if (ExportDir
== NULL
)
1184 DPRINT1("LdrGetExportByName(): no export directory, "
1185 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1190 //The symbol names may be missing entirely
1191 if (ExportDir
->AddressOfNames
== 0)
1193 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1198 * Get header pointers
1200 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1201 ExportDir
->AddressOfNames
);
1202 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1203 ExportDir
->AddressOfNameOrdinals
);
1204 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1205 ExportDir
->AddressOfFunctions
);
1208 * Check the hint first
1210 if (Hint
< ExportDir
->NumberOfNames
)
1212 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1213 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1215 Ordinal
= ExOrdinals
[Hint
];
1216 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1217 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1218 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1220 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1221 Function
= LdrFixupForward((PCHAR
)Function
);
1222 if (Function
== NULL
)
1224 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1228 if (Function
!= NULL
)
1237 maxn
= ExportDir
->NumberOfNames
- 1;
1238 while (minn
<= maxn
)
1243 mid
= (minn
+ maxn
) / 2;
1245 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1246 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1249 Ordinal
= ExOrdinals
[mid
];
1250 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1251 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1252 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1254 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1255 Function
= LdrFixupForward((PCHAR
)Function
);
1256 if (Function
== NULL
)
1258 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1262 if (Function
!= NULL
)
1265 else if (minn
== maxn
)
1267 DPRINT("LdrGetExportByName(): binary search failed\n");
1280 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1285 /**********************************************************************
1287 * LdrPerformRelocations
1290 * Relocate a DLL's memory image.
1302 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1305 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1306 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1307 ULONG Count
, OldProtect
, OldProtect2
;
1309 PVOID Page
, ProtectPage
, ProtectPage2
;
1314 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1316 return STATUS_SUCCESS
;
1320 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1322 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1324 return STATUS_SUCCESS
;
1327 ProtectSize
= PAGE_SIZE
;
1328 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1329 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1330 RelocationDDir
->VirtualAddress
);
1331 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1332 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1334 while (RelocationDir
< RelocationEnd
&&
1335 RelocationDir
->SizeOfBlock
> 0)
1337 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1339 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1340 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1342 /* Unprotect the page(s) we're about to relocate. */
1344 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1349 if (!NT_SUCCESS(Status
))
1351 DPRINT1("Failed to unprotect relocation target.\n");
1355 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1356 NTHeaders
->OptionalHeader
.SizeOfImage
)
1358 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1359 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1364 if (!NT_SUCCESS(Status
))
1366 DPRINT1("Failed to unprotect relocation target (2).\n");
1367 NtProtectVirtualMemory(NtCurrentProcess(),
1377 ProtectPage2
= NULL
;
1380 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1384 if (RelocationDir
== NULL
)
1385 return STATUS_UNSUCCESSFUL
;
1387 /* Restore old page protection. */
1388 NtProtectVirtualMemory(NtCurrentProcess(),
1394 if (ProtectPage2
!= NULL
)
1396 NtProtectVirtualMemory(NtCurrentProcess(),
1404 return STATUS_SUCCESS
;
1408 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1410 PLDR_DATA_TABLE_ENTRY
* Module
,
1413 ANSI_STRING AnsiDllName
;
1414 UNICODE_STRING DllName
;
1417 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1419 RtlInitAnsiString(&AnsiDllName
, Name
);
1420 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1421 if (!NT_SUCCESS(Status
))
1426 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1427 if (Load
&& !NT_SUCCESS(Status
))
1429 Status
= LdrpLoadModule(SearchPath
,
1434 if (NT_SUCCESS(Status
))
1436 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1438 if (!NT_SUCCESS(Status
))
1440 ULONG ErrorResponse
;
1441 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1443 DPRINT1("failed to load %wZ\n", &DllName
);
1444 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1452 RtlFreeUnicodeString (&DllName
);
1457 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1459 ULONG ErrorResponse
;
1460 ULONG_PTR ErrorParameters
[2];
1461 ANSI_STRING ProcNameAnsi
;
1462 UNICODE_STRING ProcName
;
1467 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1471 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1472 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1473 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1474 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1475 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1481 RtlFreeUnicodeString(&ProcName
);
1485 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1486 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1487 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1490 PVOID
* ImportAddressList
;
1491 PULONG FunctionNameList
;
1497 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1499 return STATUS_UNSUCCESSFUL
;
1502 /* Get the import address list. */
1503 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1505 /* Get the list of functions to import. */
1506 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1508 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1512 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1515 /* Get the size of IAT. */
1517 while (FunctionNameList
[IATSize
] != 0L)
1522 /* Unprotect the region we are about to write into. */
1523 IATBase
= (PVOID
)ImportAddressList
;
1524 IATSize
*= sizeof(PVOID
*);
1525 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1530 if (!NT_SUCCESS(Status
))
1532 DPRINT1("Failed to unprotect IAT.\n");
1536 /* Walk through function list and fixup addresses. */
1537 while (*FunctionNameList
!= 0L)
1539 if ((*FunctionNameList
) & 0x80000000)
1541 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1542 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1543 if ((*ImportAddressList
) == NULL
)
1545 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1546 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1547 return STATUS_ENTRYPOINT_NOT_FOUND
;
1552 IMAGE_IMPORT_BY_NAME
*pe_name
;
1553 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1554 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1555 if ((*ImportAddressList
) == NULL
)
1557 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1558 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1559 return STATUS_ENTRYPOINT_NOT_FOUND
;
1562 ImportAddressList
++;
1566 /* Protect the region we are about to write into. */
1567 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1572 if (!NT_SUCCESS(Status
))
1574 DPRINT1("Failed to protect IAT.\n");
1578 return STATUS_SUCCESS
;
1582 LdrpProcessImportDirectory(
1583 PLDR_DATA_TABLE_ENTRY Module
,
1584 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1588 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1592 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1593 Module
, &Module
->BaseDllName
, ImportedName
);
1596 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1597 RtlImageDirectoryEntryToData(Module
->DllBase
,
1599 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1601 if (ImportModuleDirectory
== NULL
)
1603 return STATUS_UNSUCCESSFUL
;
1606 while (ImportModuleDirectory
->Name
)
1608 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1609 if (0 == _stricmp(Name
, ImportedName
))
1611 Status
= LdrpProcessImportDirectoryEntry(Module
,
1613 ImportModuleDirectory
);
1614 if (!NT_SUCCESS(Status
))
1619 ImportModuleDirectory
++;
1623 return STATUS_SUCCESS
;
1628 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1629 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1632 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1634 PVOID
* ImportAddressList
;
1637 PULONG FunctionNameList
;
1642 PIMAGE_NT_HEADERS NTHeaders
;
1646 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1647 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1649 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1650 RtlImageDirectoryEntryToData(Module
->DllBase
,
1652 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1654 if (ImportModuleDirectory
== NULL
)
1656 return STATUS_UNSUCCESSFUL
;
1659 while (ImportModuleDirectory
->Name
)
1661 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1662 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1665 /* Get the import address list. */
1666 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1668 /* Get the list of functions to import. */
1669 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1671 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1675 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1678 /* Get the size of IAT. */
1680 while (FunctionNameList
[IATSize
] != 0L)
1685 /* Unprotect the region we are about to write into. */
1686 IATBase
= (PVOID
)ImportAddressList
;
1687 IATSize
*= sizeof(PVOID
*);
1688 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1693 if (!NT_SUCCESS(Status
))
1695 DPRINT1("Failed to unprotect IAT.\n");
1699 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1700 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1701 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1702 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1704 /* Walk through function list and fixup addresses. */
1705 while (*FunctionNameList
!= 0L)
1707 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1709 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1711 ImportAddressList
++;
1715 /* Protect the region we are about to write into. */
1716 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1721 if (!NT_SUCCESS(Status
))
1723 DPRINT1("Failed to protect IAT.\n");
1727 ImportModuleDirectory
++;
1729 return STATUS_SUCCESS
;
1733 /**********************************************************************
1738 * Compute the entry point for every symbol the DLL imports
1739 * from other modules.
1751 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1752 IN PLDR_DATA_TABLE_ENTRY Module
)
1754 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1755 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1756 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1757 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1758 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1761 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1766 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1768 /* Check for tls data */
1769 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1770 RtlImageDirectoryEntryToData(Module
->DllBase
,
1772 IMAGE_DIRECTORY_ENTRY_TLS
,
1776 TlsSize
= TlsDirectory
->EndAddressOfRawData
1777 - TlsDirectory
->StartAddressOfRawData
1778 + TlsDirectory
->SizeOfZeroFill
;
1780 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1782 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1783 &Module
->BaseDllName
);
1784 TlsDirectory
= NULL
;
1789 * Process each import module.
1791 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1792 RtlImageDirectoryEntryToData(Module
->DllBase
,
1794 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1797 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1798 RtlImageDirectoryEntryToData(Module
->DllBase
,
1800 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1803 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1805 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1806 return STATUS_UNSUCCESSFUL
;
1808 if (BoundImportDescriptor
)
1810 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1812 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1813 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1815 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1816 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1817 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1818 if (!NT_SUCCESS(Status
))
1820 DPRINT1("failed to load %s\n", ImportedName
);
1823 if (Module
== ImportedModule
)
1825 LdrpDecrementLoadCount(Module
, FALSE
);
1827 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1829 TRACE_LDR("%wZ has stale binding to %wZ\n",
1830 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1831 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1832 if (!NT_SUCCESS(Status
))
1834 DPRINT1("failed to import %s\n", ImportedName
);
1840 BOOLEAN WrongForwarder
;
1841 WrongForwarder
= FALSE
;
1842 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1844 TRACE_LDR("%wZ has stale binding to %s\n",
1845 &Module
->BaseDllName
, ImportedName
);
1849 TRACE_LDR("%wZ has correct binding to %wZ\n",
1850 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1852 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1854 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1856 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1857 PCHAR ForwarderName
;
1859 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1860 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1862 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1863 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1864 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1865 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1866 if (!NT_SUCCESS(Status
))
1868 DPRINT1("failed to load %s\n", ForwarderName
);
1871 if (Module
== ImportedModule
)
1873 LdrpDecrementLoadCount(Module
, FALSE
);
1875 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1876 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1878 TRACE_LDR("%wZ has stale binding to %s\n",
1879 &Module
->BaseDllName
, ForwarderName
);
1880 WrongForwarder
= TRUE
;
1884 TRACE_LDR("%wZ has correct binding to %s\n",
1885 &Module
->BaseDllName
, ForwarderName
);
1889 if (WrongForwarder
||
1890 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1892 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1893 if (!NT_SUCCESS(Status
))
1895 DPRINT1("failed to import %s\n", ImportedName
);
1899 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1901 TRACE_LDR("Adjust imports for %s from %wZ\n",
1902 ImportedName
, &Module
->BaseDllName
);
1903 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1904 if (!NT_SUCCESS(Status
))
1906 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1910 else if (WrongForwarder
)
1914 * Update only forwarders
1916 TRACE_LDR("Stale BIND %s from %wZ\n",
1917 ImportedName
, &Module
->BaseDllName
);
1918 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1919 if (!NT_SUCCESS(Status
))
1921 DPRINT1("faild to import %s\n", ImportedName
);
1930 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1933 else if (ImportModuleDirectory
)
1935 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1937 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1938 while (ImportModuleDirectoryCurrent
->Name
)
1940 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1941 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1943 if (SearchPath
== NULL
)
1945 ModulePath
= LdrpQueryAppPaths(Module
->BaseDllName
.Buffer
);
1947 Status
= LdrpGetOrLoadModule(ModulePath
, ImportedName
, &ImportedModule
, TRUE
);
1948 if (ModulePath
!= NULL
) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath
);
1949 if (NT_SUCCESS(Status
)) goto Success
;
1952 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1953 if (!NT_SUCCESS(Status
))
1955 DPRINT1("failed to load %s\n", ImportedName
);
1959 if (Module
== ImportedModule
)
1961 LdrpDecrementLoadCount(Module
, FALSE
);
1964 TRACE_LDR("Initializing imports for %wZ from %s\n",
1965 &Module
->BaseDllName
, ImportedName
);
1966 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1967 if (!NT_SUCCESS(Status
))
1969 DPRINT1("failed to import %s\n", ImportedName
);
1972 ImportModuleDirectoryCurrent
++;
1976 if (TlsDirectory
&& TlsSize
> 0)
1978 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
1981 return STATUS_SUCCESS
;
1985 /**********************************************************************
1990 * 1. Relocate, if needed the EXE.
1991 * 2. Fixup any imported symbol.
1992 * 3. Compute the EXE's entry point.
1996 * Address at which the EXE's image
2000 * Handle of the section that contains
2004 * NULL on error; otherwise the entry point
2005 * to call for initializing the DLL.
2010 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
2011 * Currently the function is only used for the exe.
2013 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
2014 HANDLE SectionHandle
,
2015 PLDR_DATA_TABLE_ENTRY
* Module
,
2019 PEPFUNC EntryPoint
= NULL
;
2020 PIMAGE_DOS_HEADER DosHeader
;
2021 PIMAGE_NT_HEADERS NTHeaders
;
2022 PLDR_DATA_TABLE_ENTRY tmpModule
;
2024 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
2025 ImageBase
, SectionHandle
);
2028 * Overlay DOS and WNT headers structures
2029 * to the DLL's image.
2031 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
2032 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
2035 * If the base address is different from the
2036 * one the DLL is actually loaded, perform any
2039 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2041 DPRINT("LDR: Performing relocations\n");
2042 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
2043 if (!NT_SUCCESS(Status
))
2045 DPRINT1("LdrPerformRelocations() failed\n");
2052 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
2053 (*Module
)->SectionPointer
= SectionHandle
;
2057 Module
= &tmpModule
;
2058 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
2059 if (!NT_SUCCESS(Status
))
2065 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2067 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2071 * If the DLL's imports symbols from other
2072 * modules, fixup the imported calls entry points.
2074 DPRINT("About to fixup imports\n");
2075 Status
= LdrFixupImports(NULL
, *Module
);
2076 if (!NT_SUCCESS(Status
))
2078 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
2081 DPRINT("Fixup done\n");
2082 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2083 Status
= LdrpInitializeTlsForProccess();
2084 if (NT_SUCCESS(Status
))
2086 Status
= LdrpAttachProcess();
2088 if (NT_SUCCESS(Status
))
2090 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2094 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2095 if (!NT_SUCCESS(Status
))
2101 * Compute the DLL's entry point's address.
2103 DPRINT("ImageBase = %p\n", ImageBase
);
2104 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2105 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2107 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2108 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2110 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2115 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2117 IN PUNICODE_STRING Name
,
2118 PLDR_DATA_TABLE_ENTRY
*Module
,
2119 PVOID
*BaseAddress OPTIONAL
)
2121 UNICODE_STRING AdjustedName
;
2122 UNICODE_STRING FullDosName
;
2124 PLDR_DATA_TABLE_ENTRY tmpModule
;
2125 HANDLE SectionHandle
;
2128 PIMAGE_NT_HEADERS NtHeaders
;
2129 BOOLEAN MappedAsDataFile
;
2130 PVOID ArbitraryUserPointer
;
2134 Module
= &tmpModule
;
2136 /* adjust the full dll name */
2137 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2139 DPRINT("%wZ\n", &AdjustedName
);
2141 MappedAsDataFile
= FALSE
;
2142 /* Test if dll is already loaded */
2143 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2144 if (NT_SUCCESS(Status
))
2146 RtlFreeUnicodeString(&AdjustedName
);
2147 if (NULL
!= BaseAddress
)
2149 *BaseAddress
= (*Module
)->DllBase
;
2154 /* Open or create dll image section */
2155 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2156 if (!NT_SUCCESS(Status
))
2158 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2159 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2160 MappedAsDataFile
, &SectionHandle
);
2162 if (!NT_SUCCESS(Status
))
2164 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2165 RtlFreeUnicodeString(&AdjustedName
);
2168 RtlFreeUnicodeString(&AdjustedName
);
2169 /* Map the dll into the process */
2172 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2173 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2174 Status
= NtMapViewOfSection(SectionHandle
,
2184 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2185 if (!NT_SUCCESS(Status
))
2187 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2188 RtlFreeUnicodeString(&FullDosName
);
2189 NtClose(SectionHandle
);
2192 if (NULL
!= BaseAddress
)
2194 *BaseAddress
= ImageBase
;
2196 if (!MappedAsDataFile
)
2198 /* Get and check the NT headers */
2199 NtHeaders
= RtlImageNtHeader(ImageBase
);
2200 if (NtHeaders
== NULL
)
2202 DPRINT1("RtlImageNtHeaders() failed\n");
2203 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2204 NtClose (SectionHandle
);
2205 RtlFreeUnicodeString(&FullDosName
);
2206 return STATUS_UNSUCCESSFUL
;
2209 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2210 if (MappedAsDataFile
)
2212 ASSERT(NULL
!= BaseAddress
);
2213 if (NULL
!= BaseAddress
)
2215 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2218 RtlFreeUnicodeString(&FullDosName
);
2219 NtClose(SectionHandle
);
2220 return STATUS_SUCCESS
;
2222 /* If the base address is different from the
2223 * one the DLL is actually loaded, perform any
2225 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2227 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2228 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2229 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2230 if (!NT_SUCCESS(Status
))
2232 DPRINT1("LdrPerformRelocations() failed\n");
2233 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2234 NtClose (SectionHandle
);
2235 RtlFreeUnicodeString(&FullDosName
);
2236 return STATUS_UNSUCCESSFUL
;
2239 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2240 (*Module
)->SectionPointer
= SectionHandle
;
2241 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2243 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2245 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2247 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2249 /* fixup the imported calls entry points */
2250 Status
= LdrFixupImports(SearchPath
, *Module
);
2251 if (!NT_SUCCESS(Status
))
2253 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2257 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2258 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2259 &(*Module
)->InInitializationOrderLinks
);
2260 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2262 return STATUS_SUCCESS
;
2266 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2269 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2270 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2271 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2273 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2280 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2283 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2285 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2289 /* ?????????????????? */
2291 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2293 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2294 RtlImageDirectoryEntryToData(Module
->DllBase
,
2296 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2298 if (BoundImportDescriptor
)
2300 /* dereferencing all imported modules, use the bound import descriptor */
2301 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2302 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2304 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2305 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2306 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2307 if (!NT_SUCCESS(Status
))
2309 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2313 if (Module
!= ImportedModule
)
2315 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2316 if (!NT_SUCCESS(Status
))
2318 DPRINT1("unable to unload %s\n", ImportedName
);
2322 BoundImportDescriptorCurrent
++;
2327 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2328 RtlImageDirectoryEntryToData(Module
->DllBase
,
2330 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2332 if (ImportModuleDirectory
)
2334 /* dereferencing all imported modules, use the import descriptor */
2335 while (ImportModuleDirectory
->Name
)
2337 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2338 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2339 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2340 if (!NT_SUCCESS(Status
))
2342 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2346 if (Module
!= ImportedModule
)
2348 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2349 if (!NT_SUCCESS(Status
))
2351 DPRINT1("unable to unload %s\n", ImportedName
);
2355 ImportModuleDirectory
++;
2363 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2365 LdrpDetachProcess(FALSE
);
2368 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2370 return STATUS_SUCCESS
;
2378 LdrUnloadDll (IN PVOID BaseAddress
)
2380 PLDR_DATA_TABLE_ENTRY Module
;
2383 if (BaseAddress
== NULL
)
2384 return STATUS_SUCCESS
;
2386 if (LdrMappedAsDataFile(&BaseAddress
))
2388 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2392 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2393 if (NT_SUCCESS(Status
))
2395 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2396 Status
= LdrpUnloadModule(Module
, TRUE
);
2407 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2409 PLIST_ENTRY ModuleListHead
;
2411 PLDR_DATA_TABLE_ENTRY Module
;
2414 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2416 Status
= STATUS_DLL_NOT_FOUND
;
2417 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2418 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2419 Entry
= ModuleListHead
->Flink
;
2420 while (Entry
!= ModuleListHead
)
2422 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2424 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2426 if (Module
->DllBase
== BaseAddress
)
2428 if (Module
->TlsIndex
== 0xFFFF)
2430 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2431 Status
= STATUS_SUCCESS
;
2435 Entry
= Entry
->Flink
;
2437 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2445 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2446 IN PULONG DllCharacteristics
,
2447 IN PUNICODE_STRING DllName
,
2448 OUT PVOID
*DllHandle
)
2450 PLDR_DATA_TABLE_ENTRY Module
;
2453 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2454 DllName
, DllPath
? DllPath
: L
"");
2456 /* NULL is the current executable */
2457 if (DllName
== NULL
)
2459 *DllHandle
= ExeModule
->DllBase
;
2460 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2461 return STATUS_SUCCESS
;
2464 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2465 if (NT_SUCCESS(Status
))
2467 *DllHandle
= Module
->DllBase
;
2468 return STATUS_SUCCESS
;
2471 DPRINT("Failed to find dll %wZ\n", DllName
);
2473 return STATUS_DLL_NOT_FOUND
;
2480 LdrAddRefDll(IN ULONG Flags
,
2481 IN PVOID BaseAddress
)
2483 PLIST_ENTRY ModuleListHead
;
2485 PLDR_DATA_TABLE_ENTRY Module
;
2488 if (Flags
& ~(LDR_PIN_MODULE
))
2490 return STATUS_INVALID_PARAMETER
;
2493 Status
= STATUS_DLL_NOT_FOUND
;
2494 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2495 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2496 Entry
= ModuleListHead
->Flink
;
2497 while (Entry
!= ModuleListHead
)
2499 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2501 if (Module
->DllBase
== BaseAddress
)
2503 if (Flags
& LDR_PIN_MODULE
)
2505 Module
->Flags
|= LDRP_STATIC_LINK
;
2509 LdrpIncrementLoadCount(Module
,
2512 Status
= STATUS_SUCCESS
;
2515 Entry
= Entry
->Flink
;
2517 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2525 RtlPcToFileHeader(IN PVOID PcValue
,
2528 PLIST_ENTRY ModuleListHead
;
2530 PLDR_DATA_TABLE_ENTRY Module
;
2531 PVOID ImageBase
= NULL
;
2533 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2534 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2535 Entry
= ModuleListHead
->Flink
;
2536 while (Entry
!= ModuleListHead
)
2538 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2540 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2541 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2543 ImageBase
= Module
->DllBase
;
2546 Entry
= Entry
->Flink
;
2548 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2550 *BaseOfImage
= ImageBase
;
2558 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2559 IN PANSI_STRING Name
,
2561 OUT PVOID
*ProcedureAddress
)
2563 NTSTATUS Status
= STATUS_PROCEDURE_NOT_FOUND
;
2564 if (Name
&& Name
->Length
)
2566 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2570 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2573 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2574 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2578 if (Name
&& Name
->Length
)
2581 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2582 if (*ProcedureAddress
!= NULL
)
2584 Status
= STATUS_SUCCESS
;
2586 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2591 Ordinal
&= 0x0000FFFF;
2592 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2593 if (*ProcedureAddress
)
2595 Status
= STATUS_SUCCESS
;
2597 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2602 Status
= STATUS_DLL_NOT_FOUND
;
2609 /**********************************************************************
2614 * Unload dll's which are no longer referenced from others dll's
2625 * The loader lock must be held on enty.
2628 LdrpDetachProcess(BOOLEAN UnloadAll
)
2630 PLIST_ENTRY ModuleListHead
;
2632 PLDR_DATA_TABLE_ENTRY Module
;
2633 static ULONG CallingCount
= 0;
2635 DPRINT("LdrpDetachProcess() called for %wZ\n",
2636 &ExeModule
->BaseDllName
);
2639 LdrpDllShutdownInProgress
= TRUE
;
2643 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2644 Entry
= ModuleListHead
->Blink
;
2645 while (Entry
!= ModuleListHead
)
2647 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2648 if (((UnloadAll
&& Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0) &&
2649 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2650 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2652 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2653 if (Module
== LdrpLastModule
)
2655 LdrpLastModule
= NULL
;
2657 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2659 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2660 &Module
->BaseDllName
, Module
->EntryPoint
);
2661 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2665 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2667 Entry
= ModuleListHead
->Blink
;
2671 Entry
= Entry
->Blink
;
2675 if (CallingCount
== 1)
2677 Entry
= ModuleListHead
->Blink
;
2678 while (Entry
!= ModuleListHead
)
2680 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2681 Entry
= Entry
->Blink
;
2682 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2683 ((UnloadAll
&& Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0))
2685 /* remove the module entry from the list */
2686 RemoveEntryList (&Module
->InLoadOrderLinks
);
2687 RemoveEntryList (&Module
->InInitializationOrderLinks
);
2689 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2690 NtClose (Module
->SectionPointer
);
2692 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2694 RtlFreeUnicodeString (&Module
->FullDllName
);
2695 RtlFreeUnicodeString (&Module
->BaseDllName
);
2697 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2702 DPRINT("LdrpDetachProcess() done\n");
2705 /**********************************************************************
2710 * Initialize all dll's which are prepered for loading
2721 * The loader lock must be held on entry.
2725 LdrpAttachProcess(VOID
)
2727 PLIST_ENTRY ModuleListHead
;
2729 PLDR_DATA_TABLE_ENTRY Module
;
2731 NTSTATUS Status
= STATUS_SUCCESS
;
2733 DPRINT("LdrpAttachProcess() called for %wZ\n",
2734 &ExeModule
->BaseDllName
);
2736 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2737 Entry
= ModuleListHead
->Flink
;
2738 while (Entry
!= ModuleListHead
)
2740 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2741 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2743 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2744 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2745 &Module
->BaseDllName
, Module
->EntryPoint
);
2746 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2749 Status
= STATUS_DLL_INIT_FAILED
;
2752 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2754 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2758 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2760 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2762 Entry
= Entry
->Flink
;
2765 DPRINT("LdrpAttachProcess() done\n");
2774 RtlDllShutdownInProgress (VOID
)
2776 return LdrpDllShutdownInProgress
;
2783 LdrShutdownProcess (VOID
)
2785 LdrpDetachProcess(TRUE
);
2786 return STATUS_SUCCESS
;
2794 LdrpAttachThread (VOID
)
2796 PLIST_ENTRY ModuleListHead
;
2798 PLDR_DATA_TABLE_ENTRY Module
;
2801 DPRINT("LdrpAttachThread() called for %wZ\n",
2802 &ExeModule
->BaseDllName
);
2804 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2806 Status
= LdrpInitializeTlsForThread();
2808 if (NT_SUCCESS(Status
))
2810 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2811 Entry
= ModuleListHead
->Flink
;
2813 while (Entry
!= ModuleListHead
)
2815 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2816 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2817 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2818 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2820 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2821 &Module
->BaseDllName
, Module
->EntryPoint
);
2822 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2824 Entry
= Entry
->Flink
;
2827 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2828 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2829 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2832 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2834 DPRINT("LdrpAttachThread() done\n");
2844 LdrShutdownThread (VOID
)
2846 PLIST_ENTRY ModuleListHead
;
2848 PLDR_DATA_TABLE_ENTRY Module
;
2850 DPRINT("LdrShutdownThread() called for %wZ\n",
2851 &ExeModule
->BaseDllName
);
2853 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2855 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2856 Entry
= ModuleListHead
->Blink
;
2857 while (Entry
!= ModuleListHead
)
2859 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2861 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2862 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2863 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2865 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2866 &Module
->BaseDllName
, Module
->EntryPoint
);
2867 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2869 Entry
= Entry
->Blink
;
2872 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2876 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2879 DPRINT("LdrShutdownThread() done\n");
2881 return STATUS_SUCCESS
;
2885 /***************************************************************************
2887 * LdrQueryProcessModuleInformation
2902 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2903 IN ULONG Size OPTIONAL
,
2904 OUT PULONG ReturnedSize
)
2906 PLIST_ENTRY ModuleListHead
;
2908 PLDR_DATA_TABLE_ENTRY Module
;
2909 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2910 NTSTATUS Status
= STATUS_SUCCESS
;
2911 ULONG UsedSize
= sizeof(ULONG
);
2912 ANSI_STRING AnsiString
;
2915 DPRINT("LdrQueryProcessModuleInformation() called\n");
2916 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2917 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2919 if (ModuleInformation
== NULL
|| Size
== 0)
2921 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2925 ModuleInformation
->NumberOfModules
= 0;
2926 ModulePtr
= &ModuleInformation
->Modules
[0];
2927 Status
= STATUS_SUCCESS
;
2930 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2931 Entry
= ModuleListHead
->Flink
;
2933 while (Entry
!= ModuleListHead
)
2935 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2937 DPRINT(" Module %wZ\n",
2938 &Module
->FullDllName
);
2940 if (UsedSize
> Size
)
2942 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2944 else if (ModuleInformation
!= NULL
)
2946 ModulePtr
->Section
= 0;
2947 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2948 ModulePtr
->ImageBase
= Module
->DllBase
;
2949 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2950 ModulePtr
->Flags
= Module
->Flags
;
2951 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2952 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2953 ModulePtr
->LoadCount
= Module
->LoadCount
;
2955 AnsiString
.Length
= 0;
2956 AnsiString
.MaximumLength
= 256;
2957 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2958 RtlUnicodeStringToAnsiString(&AnsiString
,
2959 &Module
->FullDllName
,
2962 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2964 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2966 ModulePtr
->OffsetToFileName
= 0;
2969 ModuleInformation
->NumberOfModules
++;
2971 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2973 Entry
= Entry
->Flink
;
2976 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2978 if (ReturnedSize
!= 0)
2979 *ReturnedSize
= UsedSize
;
2981 DPRINT("LdrQueryProcessModuleInformation() done\n");
2988 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
2991 PIMAGE_NT_HEADERS Header
;
2998 Header
= RtlImageNtHeader (BaseAddress
);
3002 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
3007 Ptr
= (PUSHORT
) BaseAddress
;
3008 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
3011 if (HIWORD(Sum
) != 0)
3013 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3020 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
3021 if (HIWORD(Sum
) != 0)
3023 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3027 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
3029 /* Subtract image checksum from calculated checksum. */
3030 /* fix low word of checksum */
3031 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
3033 CalcSum
-= LOWORD(HeaderSum
);
3037 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
3040 /* fix high word of checksum */
3041 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
3043 CalcSum
-= HIWORD(HeaderSum
);
3047 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
3050 /* add file length */
3051 CalcSum
+= ImageSize
;
3053 return (BOOLEAN
)(CalcSum
== HeaderSum
);
3057 * Compute size of an image as it is actually present in virt memory
3058 * (i.e. excluding NEVER_LOAD sections)
3061 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
3063 PIMAGE_SECTION_HEADER SectionHeader
;
3064 unsigned SectionIndex
;
3067 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
3068 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
3070 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
3072 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
3073 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
3075 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
3080 return ResidentSize
;
3084 /***************************************************************************
3086 * LdrVerifyImageMatchesChecksum
3101 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3106 FILE_STANDARD_INFORMATION FileInfo
;
3107 IO_STATUS_BLOCK IoStatusBlock
;
3108 HANDLE SectionHandle
;
3114 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3116 Status
= NtCreateSection (&SectionHandle
,
3123 if (!NT_SUCCESS(Status
))
3125 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3131 Status
= NtMapViewOfSection (SectionHandle
,
3132 NtCurrentProcess (),
3141 if (!NT_SUCCESS(Status
))
3143 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3144 NtClose (SectionHandle
);
3148 Status
= NtQueryInformationFile (FileHandle
,
3151 sizeof (FILE_STANDARD_INFORMATION
),
3152 FileStandardInformation
);
3153 if (!NT_SUCCESS(Status
))
3155 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3156 NtUnmapViewOfSection (NtCurrentProcess (),
3158 NtClose (SectionHandle
);
3162 Result
= LdrpCheckImageChecksum (BaseAddress
,
3163 FileInfo
.EndOfFile
.u
.LowPart
);
3164 if (Result
== FALSE
)
3166 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3169 NtUnmapViewOfSection (NtCurrentProcess (),
3172 NtClose (SectionHandle
);
3178 /***************************************************************************
3180 * LdrQueryImageFileExecutionOptions
3195 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3196 IN PCWSTR ValueName
,
3199 IN ULONG BufferSize
,
3200 OUT PULONG ReturnedLength OPTIONAL
)
3202 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3203 OBJECT_ATTRIBUTES ObjectAttributes
;
3204 UNICODE_STRING ValueNameString
;
3205 UNICODE_STRING KeyName
;
3206 WCHAR NameBuffer
[256];
3214 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3215 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3218 Ptr
= SubKey
->Buffer
;
3224 wcscat (NameBuffer
, Ptr
);
3225 RtlInitUnicodeString (&KeyName
,
3228 InitializeObjectAttributes (&ObjectAttributes
,
3230 OBJ_CASE_INSENSITIVE
,
3234 Status
= NtOpenKey (&KeyHandle
,
3237 if (!NT_SUCCESS(Status
))
3239 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3243 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3244 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3247 if (KeyInfo
== NULL
)
3249 NtClose (KeyHandle
);
3250 return STATUS_INSUFFICIENT_RESOURCES
;
3253 RtlInitUnicodeString (&ValueNameString
,
3255 Status
= NtQueryValueKey (KeyHandle
,
3257 KeyValuePartialInformation
,
3261 if (Status
== STATUS_BUFFER_OVERFLOW
)
3263 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3264 RtlFreeHeap (RtlGetProcessHeap(),
3267 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3270 if (KeyInfo
== NULL
)
3272 NtClose (KeyHandle
);
3273 return STATUS_INSUFFICIENT_RESOURCES
;
3276 Status
= NtQueryValueKey (KeyHandle
,
3278 KeyValuePartialInformation
,
3283 NtClose (KeyHandle
);
3285 if (!NT_SUCCESS(Status
))
3287 if (KeyInfo
!= NULL
)
3289 RtlFreeHeap (RtlGetProcessHeap(),
3296 if (KeyInfo
->Type
!= Type
)
3298 RtlFreeHeap (RtlGetProcessHeap(),
3301 return STATUS_OBJECT_TYPE_MISMATCH
;
3304 ResultSize
= BufferSize
;
3305 if (ResultSize
< KeyInfo
->DataLength
)
3307 Status
= STATUS_BUFFER_OVERFLOW
;
3311 ResultSize
= KeyInfo
->DataLength
;
3313 RtlCopyMemory (Buffer
,
3317 RtlFreeHeap (RtlGetProcessHeap(),
3321 if (ReturnedLength
!= NULL
)
3323 *ReturnedLength
= ResultSize
;
3330 PIMAGE_BASE_RELOCATION NTAPI
3331 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3333 IN PUSHORT TypeOffset
,
3342 for (i
= 0; i
< Count
; i
++)
3344 Offset
= *TypeOffset
& 0xFFF;
3345 Type
= *TypeOffset
>> 12;
3349 case IMAGE_REL_BASED_ABSOLUTE
:
3352 case IMAGE_REL_BASED_HIGH
:
3353 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3354 *ShortPtr
+= HIWORD(Delta
);
3357 case IMAGE_REL_BASED_LOW
:
3358 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3359 *ShortPtr
+= LOWORD(Delta
);
3362 case IMAGE_REL_BASED_HIGHLOW
:
3363 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3367 case IMAGE_REL_BASED_DIR64
:
3368 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3373 case IMAGE_REL_BASED_HIGHADJ
:
3374 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3376 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3383 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3388 LdrLockLoaderLock(IN ULONG Flags
,
3389 OUT PULONG Disposition OPTIONAL
,
3390 OUT PULONG Cookie OPTIONAL
)
3393 return STATUS_NOT_IMPLEMENTED
;
3398 LdrUnlockLoaderLock(IN ULONG Flags
,
3399 IN ULONG Cookie OPTIONAL
)
3402 return STATUS_NOT_IMPLEMENTED
;
3407 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)