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 *******************************************************************/
31 #define TRACE_LDR(args...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); }
32 #elif defined(_MSC_VER)
33 #define TRACE_LDR(args, ...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
36 #define TRACE_LDR(args...) do { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0)
39 typedef struct _TLS_DATA
41 PVOID StartAddressOfRawData
;
44 PIMAGE_TLS_CALLBACK
*TlsAddressOfCallBacks
;
45 PLDR_DATA_TABLE_ENTRY Module
;
46 } TLS_DATA
, *PTLS_DATA
;
48 static BOOLEAN LdrpDllShutdownInProgress
= FALSE
;
49 static PTLS_DATA LdrpTlsArray
= NULL
;
50 static ULONG LdrpTlsCount
= 0;
51 static ULONG LdrpTlsSize
= 0;
52 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
53 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
54 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
55 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
57 /* PROTOTYPES ****************************************************************/
59 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
60 static PVOID
LdrFixupForward(PCHAR ForwardName
);
61 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
62 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
64 IN PUNICODE_STRING Name
,
65 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
66 OUT PVOID
*BaseAddress OPTIONAL
);
67 static NTSTATUS
LdrpAttachProcess(VOID
);
68 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
70 /* FUNCTIONS *****************************************************************/
72 #if DBG || defined(KDBG)
75 LdrpLoadUserModuleSymbols(PLDR_DATA_TABLE_ENTRY LdrModule
)
86 #endif /* DBG || KDBG */
89 LdrMappedAsDataFile(PVOID
*BaseAddress
)
91 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
93 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
100 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
105 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
107 LoadCount
= Module
->LoadCount
;
108 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
114 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
119 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
124 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
126 LoadCount
= Module
->LoadCount
;
127 if (Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
133 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
138 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
142 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
144 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
149 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
153 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
155 PIMAGE_TLS_CALLBACK
*TlsCallback
;
156 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
)
158 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
163 TRACE_LDR("%wZ - Calling tls callback at %x\n",
164 &Module
->BaseDllName
, *TlsCallback
);
165 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
172 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
174 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
175 Module
->EntryPoint
== 0)
179 LdrpTlsCallback(Module
, dwReason
);
180 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
184 LdrpQueryAppPaths(IN PCWSTR ImageName
)
186 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
187 OBJECT_ATTRIBUTES ObjectAttributes
;
188 WCHAR SearchPathBuffer
[5*MAX_PATH
];
189 UNICODE_STRING ValueNameString
;
190 UNICODE_STRING KeyName
;
191 WCHAR NameBuffer
[MAX_PATH
];
199 _snwprintf(NameBuffer
,
200 sizeof(NameBuffer
) / sizeof(WCHAR
),
201 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
204 RtlInitUnicodeString(&KeyName
, NameBuffer
);
206 InitializeObjectAttributes(&ObjectAttributes
,
208 OBJ_CASE_INSENSITIVE
,
212 Status
= NtOpenKey(&KeyHandle
,
215 if (!NT_SUCCESS(Status
))
217 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
221 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 256 * sizeof(WCHAR
);
223 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize
);
226 DPRINT("RtlAllocateHeap() failed\n");
231 RtlInitUnicodeString(&ValueNameString
,
234 Status
= NtQueryValueKey(KeyHandle
,
236 KeyValuePartialInformation
,
241 if (!NT_SUCCESS(Status
))
244 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
248 RtlCopyMemory(SearchPathBuffer
,
250 KeyInfo
->DataLength
);
252 /* Free KeyInfo memory, we won't need it anymore */
253 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
255 /* Close the key handle */
258 /* get application running path */
259 wcscat(SearchPathBuffer
, L
";");
260 wcscat(SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
); // FIXME: Don't rely on it being NULL-terminated!!!
262 /* Remove trailing backslash */
263 Backslash
= wcsrchr(SearchPathBuffer
, L
'\\');
264 if (Backslash
) Backslash
= L
'\0';
266 wcscat(SearchPathBuffer
, L
";");
268 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
269 wcscat(SearchPathBuffer
, L
"\\system32;");
270 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
271 wcscat(SearchPathBuffer
, L
";.");
273 /* Copy it to the heap allocd memory */
274 Path
= RtlAllocateHeap(RtlGetProcessHeap(),
276 wcslen(SearchPathBuffer
) * sizeof(WCHAR
));
280 DPRINT1("RtlAllocateHeap() failed\n");
284 wcscpy(Path
, SearchPathBuffer
);
290 LdrpInitializeTlsForThread(VOID
)
296 PTEB Teb
= NtCurrentTeb();
298 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
300 Teb
->StaticUnicodeString
.Length
= 0;
301 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
302 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
304 if (LdrpTlsCount
> 0)
306 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
308 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
309 if (TlsPointers
== NULL
)
311 DPRINT1("failed to allocate thread tls data\n");
312 return STATUS_NO_MEMORY
;
315 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
316 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
318 TlsInfo
= LdrpTlsArray
;
319 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
321 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
322 TlsPointers
[i
] = TlsData
;
323 if (TlsInfo
->TlsDataSize
)
325 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
326 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
328 if (TlsInfo
->TlsZeroSize
)
330 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
331 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
336 DPRINT("LdrpInitializeTlsForThread() done\n");
337 return STATUS_SUCCESS
;
341 LdrpInitializeTlsForProccess(VOID
)
343 PLIST_ENTRY ModuleListHead
;
345 PLDR_DATA_TABLE_ENTRY Module
;
346 PIMAGE_TLS_DIRECTORY TlsDirectory
;
350 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
352 if (LdrpTlsCount
> 0)
354 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
356 LdrpTlsCount
* sizeof(TLS_DATA
));
357 if (LdrpTlsArray
== NULL
)
359 DPRINT1("Failed to allocate global tls data\n");
360 return STATUS_NO_MEMORY
;
363 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
364 Entry
= ModuleListHead
->Flink
;
365 while (Entry
!= ModuleListHead
)
367 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
368 if (Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
&&
369 Module
->TlsIndex
!= 0xFFFF)
371 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
372 RtlImageDirectoryEntryToData(Module
->DllBase
,
374 IMAGE_DIRECTORY_ENTRY_TLS
,
376 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
377 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
378 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
379 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
380 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
381 if (TlsDirectory
->AddressOfCallBacks
)
382 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
384 TlsData
->TlsAddressOfCallBacks
= NULL
;
385 TlsData
->Module
= Module
;
387 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
388 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
389 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
390 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
391 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
392 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
393 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
394 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
398 * Is this region allways writable ?
400 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
402 Entry
= Entry
->Flink
;
406 DPRINT("LdrpInitializeTlsForProccess() done\n");
407 return STATUS_SUCCESS
;
413 OBJECT_ATTRIBUTES ObjectAttributes
;
414 UNICODE_STRING LinkTarget
;
420 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
422 /* Get handle to the 'KnownDlls' directory */
423 RtlInitUnicodeString(&Name
,
425 InitializeObjectAttributes(&ObjectAttributes
,
427 OBJ_CASE_INSENSITIVE
,
430 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
431 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
433 if (!NT_SUCCESS(Status
))
435 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
436 LdrpKnownDllsDirHandle
= NULL
;
440 /* Allocate target name string */
441 LinkTarget
.Length
= 0;
442 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
443 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
445 MAX_PATH
* sizeof(WCHAR
));
446 if (LinkTarget
.Buffer
== NULL
)
448 NtClose(LdrpKnownDllsDirHandle
);
449 LdrpKnownDllsDirHandle
= NULL
;
453 RtlInitUnicodeString(&Name
,
455 InitializeObjectAttributes(&ObjectAttributes
,
457 OBJ_CASE_INSENSITIVE
,
458 LdrpKnownDllsDirHandle
,
460 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
461 SYMBOLIC_LINK_ALL_ACCESS
,
463 if (!NT_SUCCESS(Status
))
465 RtlFreeUnicodeString(&LinkTarget
);
466 NtClose(LdrpKnownDllsDirHandle
);
467 LdrpKnownDllsDirHandle
= NULL
;
471 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
475 if (!NT_SUCCESS(Status
))
477 RtlFreeUnicodeString(&LinkTarget
);
478 NtClose(LdrpKnownDllsDirHandle
);
479 LdrpKnownDllsDirHandle
= NULL
;
482 RtlCreateUnicodeString(&LdrpKnownDllPath
,
485 RtlFreeUnicodeString(&LinkTarget
);
487 DPRINT("LdrpInitLoader() done\n");
491 /***************************************************************************
496 * Adjusts the name of a dll to a fully qualified name.
499 * FullDllName: Pointer to caller supplied storage for the fully
500 * qualified dll name.
501 * DllName: Pointer to the dll name.
502 * BaseName: TRUE: Only the file name is passed to FullDllName
503 * FALSE: The full path is preserved in FullDllName
511 * A given path is not affected by the adjustment, but the file
513 * ntdll --> ntdll.dll
515 * ntdll.xyz --> ntdll.xyz
518 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
519 PUNICODE_STRING DllName
,
522 WCHAR Buffer
[MAX_PATH
];
527 Length
= DllName
->Length
/ sizeof(WCHAR
);
531 /* get the base dll name */
532 Pointer
= DllName
->Buffer
+ Length
;
539 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
542 Length
= Extension
- Pointer
;
543 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
544 Buffer
[Length
] = L
'\0';
548 /* get the full dll name */
549 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
550 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
553 /* Build the DLL's absolute name */
554 Extension
= wcsrchr (Buffer
, L
'.');
555 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
557 /* with extension - remove dot if it's the last character */
558 if (Buffer
[Length
- 1] == L
'.')
564 /* name without extension - assume that it is .dll */
565 memmove (Buffer
+ Length
, L
".dll", 10);
568 RtlCreateUnicodeString(FullDllName
, Buffer
);
571 PLDR_DATA_TABLE_ENTRY
572 LdrAddModuleEntry(PVOID ImageBase
,
573 PIMAGE_NT_HEADERS NTHeaders
,
576 PLDR_DATA_TABLE_ENTRY Module
;
578 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
580 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
581 Module
->DllBase
= (PVOID
)ImageBase
;
582 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
583 if (Module
->EntryPoint
!= 0)
584 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
585 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
586 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
588 /* loading while app is running */
589 Module
->LoadCount
= 1;
592 * loading while app is initializing
593 * dll must not be unloaded
595 Module
->LoadCount
= LDRP_PROCESS_CREATION_TIME
;
599 Module
->TlsIndex
= -1;
600 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
601 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
603 RtlCreateUnicodeString (&Module
->FullDllName
,
605 RtlCreateUnicodeString (&Module
->BaseDllName
,
606 wcsrchr(FullDosName
, L
'\\') + 1);
607 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
609 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
610 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
611 &Module
->InLoadOrderLinks
);
612 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
619 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
620 OUT PUNICODE_STRING FullDosName
,
621 OUT PHANDLE SectionHandle
)
623 OBJECT_ATTRIBUTES ObjectAttributes
;
626 DPRINT("LdrpMapKnownDll() called\n");
628 if (LdrpKnownDllsDirHandle
== NULL
)
630 DPRINT("Invalid 'KnownDlls' directory\n");
631 return STATUS_UNSUCCESSFUL
;
634 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
636 InitializeObjectAttributes(&ObjectAttributes
,
638 OBJ_CASE_INSENSITIVE
,
639 LdrpKnownDllsDirHandle
,
641 Status
= NtOpenSection(SectionHandle
,
642 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
644 if (!NT_SUCCESS(Status
))
646 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
650 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
651 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
652 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
654 FullDosName
->MaximumLength
);
655 if (FullDosName
->Buffer
== NULL
)
657 FullDosName
->Length
= 0;
658 FullDosName
->MaximumLength
= 0;
659 return STATUS_SUCCESS
;
662 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
663 wcscat(FullDosName
->Buffer
, L
"\\");
664 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
666 DPRINT("FullDosName '%wZ'\n", FullDosName
);
668 DPRINT("LdrpMapKnownDll() done\n");
670 return STATUS_SUCCESS
;
675 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
676 IN PUNICODE_STRING DllName
,
677 OUT PUNICODE_STRING FullDosName
,
678 IN BOOLEAN MapAsDataFile
,
679 OUT PHANDLE SectionHandle
)
681 WCHAR SearchPathBuffer
[MAX_PATH
];
682 WCHAR DosName
[MAX_PATH
];
683 UNICODE_STRING FullNtFileName
;
684 OBJECT_ATTRIBUTES FileObjectAttributes
;
686 char BlockBuffer
[1024];
687 PIMAGE_DOS_HEADER DosHeader
;
688 PIMAGE_NT_HEADERS NTHeaders
;
689 IO_STATUS_BLOCK IoStatusBlock
;
693 DPRINT("LdrpMapDllImageFile() called\n");
695 if (SearchPath
== NULL
)
697 /* get application running path */
699 wcscpy (SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
);
701 len
= wcslen (SearchPathBuffer
);
703 while (len
&& SearchPathBuffer
[len
- 1] != L
'\\')
706 if (len
) SearchPathBuffer
[len
-1] = L
'\0';
708 wcscat (SearchPathBuffer
, L
";");
710 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
711 wcscat (SearchPathBuffer
, L
"\\system32;");
712 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
713 wcscat (SearchPathBuffer
, L
";.");
715 SearchPath
= SearchPathBuffer
;
718 if (RtlDosSearchPath_U (SearchPath
,
724 return STATUS_DLL_NOT_FOUND
;
726 if (!RtlDosPathNameToNtPathName_U (DosName
,
730 return STATUS_DLL_NOT_FOUND
;
732 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
734 InitializeObjectAttributes(&FileObjectAttributes
,
740 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
742 Status
= NtOpenFile(&FileHandle
,
743 GENERIC_READ
|SYNCHRONIZE
,
744 &FileObjectAttributes
,
747 FILE_SYNCHRONOUS_IO_NONALERT
);
748 if (!NT_SUCCESS(Status
))
750 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
751 &FullNtFileName
, Status
);
752 RtlFreeHeap (RtlGetProcessHeap (),
754 FullNtFileName
.Buffer
);
757 RtlFreeHeap (RtlGetProcessHeap (),
759 FullNtFileName
.Buffer
);
764 Status
= NtReadFile(FileHandle
,
773 if (!NT_SUCCESS(Status
))
775 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
781 * Overlay DOS and NT headers structures to the
782 * buffer with DLL's header raw data.
784 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
785 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
787 * Check it is a PE image file.
789 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
790 || (DosHeader
->e_lfanew
== 0L)
791 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
793 DPRINT("NTDLL format invalid\n");
796 return STATUS_UNSUCCESSFUL
;
801 * Create a section for dll.
803 Status
= NtCreateSection(SectionHandle
,
808 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
812 if (!NT_SUCCESS(Status
))
814 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
818 RtlCreateUnicodeString(FullDosName
,
826 /***************************************************************************
843 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
844 IN PULONG LoadFlags OPTIONAL
,
845 IN PUNICODE_STRING Name
,
846 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
849 PLDR_DATA_TABLE_ENTRY Module
;
851 PPEB Peb
= NtCurrentPeb();
853 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
855 SearchPath
? L
" from " : L
"",
856 SearchPath
? SearchPath
: L
"");
858 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
860 if (NT_SUCCESS(Status
) &&
861 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
863 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
865 RtlEnterCriticalSection(Peb
->LoaderLock
);
866 Status
= LdrpAttachProcess();
867 RtlLeaveCriticalSection(Peb
->LoaderLock
);
871 if ((!Module
) && (NT_SUCCESS(Status
)))
874 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
880 /***************************************************************************
882 * LdrFindEntryForAddress
897 LdrFindEntryForAddress(PVOID Address
,
898 PLDR_DATA_TABLE_ENTRY
*Module
)
900 PLIST_ENTRY ModuleListHead
;
902 PLDR_DATA_TABLE_ENTRY ModulePtr
;
904 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
906 if (NtCurrentPeb()->Ldr
== NULL
)
907 return(STATUS_NO_MORE_ENTRIES
);
909 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
910 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
911 Entry
= ModuleListHead
->Flink
;
912 if (Entry
== ModuleListHead
)
914 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
915 return(STATUS_NO_MORE_ENTRIES
);
918 while (Entry
!= ModuleListHead
)
920 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
922 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
924 if ((Address
>= ModulePtr
->DllBase
) &&
925 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
928 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
929 return(STATUS_SUCCESS
);
932 Entry
= Entry
->Flink
;
935 DPRINT("Failed to find module entry.\n");
937 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
938 return(STATUS_NO_MORE_ENTRIES
);
942 /***************************************************************************
944 * LdrFindEntryForName
958 LdrFindEntryForName(PUNICODE_STRING Name
,
959 PLDR_DATA_TABLE_ENTRY
*Module
,
962 PLIST_ENTRY ModuleListHead
;
964 PLDR_DATA_TABLE_ENTRY ModulePtr
;
965 BOOLEAN ContainsPath
;
966 UNICODE_STRING AdjustedName
;
968 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
970 if (NtCurrentPeb()->Ldr
== NULL
)
971 return(STATUS_NO_MORE_ENTRIES
);
973 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
974 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
975 Entry
= ModuleListHead
->Flink
;
976 if (Entry
== ModuleListHead
)
978 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
979 return(STATUS_NO_MORE_ENTRIES
);
982 // NULL is the current process
986 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
987 return(STATUS_SUCCESS
);
990 ContainsPath
= (Name
->Length
>= 2 * sizeof(WCHAR
) && L
':' == Name
->Buffer
[1]);
991 LdrAdjustDllName (&AdjustedName
, Name
, !ContainsPath
);
995 if ((! ContainsPath
&&
996 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
998 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
1000 *Module
= LdrpLastModule
;
1001 if (Ref
&& (*Module
)->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1003 (*Module
)->LoadCount
++;
1005 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1006 RtlFreeUnicodeString(&AdjustedName
);
1007 return(STATUS_SUCCESS
);
1010 while (Entry
!= ModuleListHead
)
1012 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1014 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
1016 if ((! ContainsPath
&&
1017 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1019 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
1021 *Module
= LdrpLastModule
= ModulePtr
;
1022 if (Ref
&& ModulePtr
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1024 ModulePtr
->LoadCount
++;
1026 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1027 RtlFreeUnicodeString(&AdjustedName
);
1028 return(STATUS_SUCCESS
);
1031 Entry
= Entry
->Flink
;
1034 DPRINT("Failed to find dll %wZ\n", Name
);
1035 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1036 RtlFreeUnicodeString(&AdjustedName
);
1037 return(STATUS_NO_MORE_ENTRIES
);
1040 /**********************************************************************
1056 LdrFixupForward(PCHAR ForwardName
)
1058 CHAR NameBuffer
[128];
1059 UNICODE_STRING DllName
;
1062 PLDR_DATA_TABLE_ENTRY Module
;
1065 strcpy(NameBuffer
, ForwardName
);
1066 p
= strchr(NameBuffer
, '.');
1071 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
1072 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1075 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1077 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
1079 if (!NT_SUCCESS(Status
))
1081 Status
= LdrLoadDll(NULL
,
1085 if (NT_SUCCESS(Status
))
1087 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1090 RtlFreeUnicodeString (&DllName
);
1091 if (!NT_SUCCESS(Status
))
1093 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
1097 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1099 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1106 /**********************************************************************
1108 * LdrGetExportByOrdinal
1122 LdrGetExportByOrdinal (
1127 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1128 ULONG ExportDirSize
;
1129 PDWORD
* ExFunctions
;
1132 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1133 RtlImageDirectoryEntryToData (BaseAddress
,
1135 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1139 ExFunctions
= (PDWORD
*)
1142 ExportDir
->AddressOfFunctions
1145 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1147 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1150 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1151 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1154 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1155 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1157 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1158 Function
= LdrFixupForward((PCHAR
)Function
);
1165 /**********************************************************************
1167 * LdrGetExportByName
1178 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1179 * both with NumberOfNames entries.
1183 LdrGetExportByName(PVOID BaseAddress
,
1187 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1188 PDWORD
* ExFunctions
;
1190 USHORT
* ExOrdinals
;
1195 ULONG ExportDirSize
;
1197 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1199 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1200 RtlImageDirectoryEntryToData(BaseAddress
,
1202 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1204 if (ExportDir
== NULL
)
1206 DPRINT1("LdrGetExportByName(): no export directory, "
1207 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1212 //The symbol names may be missing entirely
1213 if (ExportDir
->AddressOfNames
== 0)
1215 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1220 * Get header pointers
1222 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1223 ExportDir
->AddressOfNames
);
1224 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1225 ExportDir
->AddressOfNameOrdinals
);
1226 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1227 ExportDir
->AddressOfFunctions
);
1230 * Check the hint first
1232 if (Hint
< ExportDir
->NumberOfNames
)
1234 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1235 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1237 Ordinal
= ExOrdinals
[Hint
];
1238 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1239 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1240 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1242 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1243 Function
= LdrFixupForward((PCHAR
)Function
);
1244 if (Function
== NULL
)
1246 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1250 if (Function
!= NULL
)
1259 maxn
= ExportDir
->NumberOfNames
- 1;
1260 while (minn
<= maxn
)
1265 mid
= (minn
+ maxn
) / 2;
1267 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1268 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1271 Ordinal
= ExOrdinals
[mid
];
1272 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1273 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1274 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1276 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1277 Function
= LdrFixupForward((PCHAR
)Function
);
1278 if (Function
== NULL
)
1280 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1284 if (Function
!= NULL
)
1287 else if (minn
== maxn
)
1289 DPRINT("LdrGetExportByName(): binary search failed\n");
1302 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1307 /**********************************************************************
1309 * LdrPerformRelocations
1312 * Relocate a DLL's memory image.
1324 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1327 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1328 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1329 ULONG Count
, OldProtect
, OldProtect2
;
1331 PVOID Page
, ProtectPage
, ProtectPage2
;
1336 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1338 return STATUS_SUCCESS
;
1342 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1344 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1346 return STATUS_SUCCESS
;
1349 ProtectSize
= PAGE_SIZE
;
1350 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1351 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1352 RelocationDDir
->VirtualAddress
);
1353 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1354 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1356 while (RelocationDir
< RelocationEnd
&&
1357 RelocationDir
->SizeOfBlock
> 0)
1359 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1361 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1362 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1364 /* Unprotect the page(s) we're about to relocate. */
1366 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1371 if (!NT_SUCCESS(Status
))
1373 DPRINT1("Failed to unprotect relocation target.\n");
1377 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1378 NTHeaders
->OptionalHeader
.SizeOfImage
)
1380 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1381 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1386 if (!NT_SUCCESS(Status
))
1388 DPRINT1("Failed to unprotect relocation target (2).\n");
1389 NtProtectVirtualMemory(NtCurrentProcess(),
1399 ProtectPage2
= NULL
;
1402 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1406 if (RelocationDir
== NULL
)
1407 return STATUS_UNSUCCESSFUL
;
1409 /* Restore old page protection. */
1410 NtProtectVirtualMemory(NtCurrentProcess(),
1416 if (ProtectPage2
!= NULL
)
1418 NtProtectVirtualMemory(NtCurrentProcess(),
1426 return STATUS_SUCCESS
;
1430 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1432 PLDR_DATA_TABLE_ENTRY
* Module
,
1435 ANSI_STRING AnsiDllName
;
1436 UNICODE_STRING DllName
;
1439 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1441 RtlInitAnsiString(&AnsiDllName
, Name
);
1442 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1443 if (!NT_SUCCESS(Status
))
1448 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1449 if (Load
&& !NT_SUCCESS(Status
))
1451 Status
= LdrpLoadModule(SearchPath
,
1456 if (NT_SUCCESS(Status
))
1458 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1460 if (!NT_SUCCESS(Status
))
1462 ULONG ErrorResponse
;
1463 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1465 DPRINT1("failed to load %wZ\n", &DllName
);
1466 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1474 RtlFreeUnicodeString (&DllName
);
1479 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1481 ULONG ErrorResponse
;
1482 ULONG_PTR ErrorParameters
[2];
1483 ANSI_STRING ProcNameAnsi
;
1484 UNICODE_STRING ProcName
;
1489 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1493 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1494 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1495 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1496 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1497 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1503 RtlFreeUnicodeString(&ProcName
);
1507 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1508 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1509 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1512 PVOID
* ImportAddressList
;
1513 PULONG FunctionNameList
;
1519 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1521 return STATUS_UNSUCCESSFUL
;
1524 /* Get the import address list. */
1525 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1527 /* Get the list of functions to import. */
1528 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1530 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1534 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1537 /* Get the size of IAT. */
1539 while (FunctionNameList
[IATSize
] != 0L)
1544 /* Unprotect the region we are about to write into. */
1545 IATBase
= (PVOID
)ImportAddressList
;
1546 IATSize
*= sizeof(PVOID
*);
1547 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1552 if (!NT_SUCCESS(Status
))
1554 DPRINT1("Failed to unprotect IAT.\n");
1558 /* Walk through function list and fixup addresses. */
1559 while (*FunctionNameList
!= 0L)
1561 if ((*FunctionNameList
) & 0x80000000)
1563 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1564 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1565 if ((*ImportAddressList
) == NULL
)
1567 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1568 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1569 return STATUS_ENTRYPOINT_NOT_FOUND
;
1574 IMAGE_IMPORT_BY_NAME
*pe_name
;
1575 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1576 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1577 if ((*ImportAddressList
) == NULL
)
1579 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1580 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1581 return STATUS_ENTRYPOINT_NOT_FOUND
;
1584 ImportAddressList
++;
1588 /* Protect the region we are about to write into. */
1589 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1594 if (!NT_SUCCESS(Status
))
1596 DPRINT1("Failed to protect IAT.\n");
1600 return STATUS_SUCCESS
;
1604 LdrpProcessImportDirectory(
1605 PLDR_DATA_TABLE_ENTRY Module
,
1606 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1610 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1614 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1615 Module
, &Module
->BaseDllName
, ImportedName
);
1618 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1619 RtlImageDirectoryEntryToData(Module
->DllBase
,
1621 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1623 if (ImportModuleDirectory
== NULL
)
1625 return STATUS_UNSUCCESSFUL
;
1628 while (ImportModuleDirectory
->Name
)
1630 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1631 if (0 == _stricmp(Name
, ImportedName
))
1633 Status
= LdrpProcessImportDirectoryEntry(Module
,
1635 ImportModuleDirectory
);
1636 if (!NT_SUCCESS(Status
))
1641 ImportModuleDirectory
++;
1645 return STATUS_SUCCESS
;
1650 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1651 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1654 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1656 PVOID
* ImportAddressList
;
1659 PULONG FunctionNameList
;
1664 PIMAGE_NT_HEADERS NTHeaders
;
1668 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1669 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1671 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1672 RtlImageDirectoryEntryToData(Module
->DllBase
,
1674 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1676 if (ImportModuleDirectory
== NULL
)
1678 return STATUS_UNSUCCESSFUL
;
1681 while (ImportModuleDirectory
->Name
)
1683 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1684 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1687 /* Get the import address list. */
1688 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1690 /* Get the list of functions to import. */
1691 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1693 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1697 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1700 /* Get the size of IAT. */
1702 while (FunctionNameList
[IATSize
] != 0L)
1707 /* Unprotect the region we are about to write into. */
1708 IATBase
= (PVOID
)ImportAddressList
;
1709 IATSize
*= sizeof(PVOID
*);
1710 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1715 if (!NT_SUCCESS(Status
))
1717 DPRINT1("Failed to unprotect IAT.\n");
1721 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1722 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1723 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1724 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1726 /* Walk through function list and fixup addresses. */
1727 while (*FunctionNameList
!= 0L)
1729 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1731 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1733 ImportAddressList
++;
1737 /* Protect the region we are about to write into. */
1738 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1743 if (!NT_SUCCESS(Status
))
1745 DPRINT1("Failed to protect IAT.\n");
1749 ImportModuleDirectory
++;
1751 return STATUS_SUCCESS
;
1755 /**********************************************************************
1760 * Compute the entry point for every symbol the DLL imports
1761 * from other modules.
1773 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1774 IN PLDR_DATA_TABLE_ENTRY Module
)
1776 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1777 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1778 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1779 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1780 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1783 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1788 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1790 /* Check for tls data */
1791 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1792 RtlImageDirectoryEntryToData(Module
->DllBase
,
1794 IMAGE_DIRECTORY_ENTRY_TLS
,
1798 TlsSize
= TlsDirectory
->EndAddressOfRawData
1799 - TlsDirectory
->StartAddressOfRawData
1800 + TlsDirectory
->SizeOfZeroFill
;
1802 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1804 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1805 &Module
->BaseDllName
);
1806 TlsDirectory
= NULL
;
1811 * Process each import module.
1813 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1814 RtlImageDirectoryEntryToData(Module
->DllBase
,
1816 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1819 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1820 RtlImageDirectoryEntryToData(Module
->DllBase
,
1822 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1825 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1827 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1828 return STATUS_UNSUCCESSFUL
;
1830 if (BoundImportDescriptor
)
1832 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1834 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1835 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1837 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1838 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1839 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1840 if (!NT_SUCCESS(Status
))
1842 DPRINT1("failed to load %s\n", ImportedName
);
1845 if (Module
== ImportedModule
)
1847 LdrpDecrementLoadCount(Module
, FALSE
);
1849 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1851 TRACE_LDR("%wZ has stale binding to %wZ\n",
1852 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1853 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1854 if (!NT_SUCCESS(Status
))
1856 DPRINT1("failed to import %s\n", ImportedName
);
1862 BOOLEAN WrongForwarder
;
1863 WrongForwarder
= FALSE
;
1864 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1866 TRACE_LDR("%wZ has stale binding to %s\n",
1867 &Module
->BaseDllName
, ImportedName
);
1871 TRACE_LDR("%wZ has correct binding to %wZ\n",
1872 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1874 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1876 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1878 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1879 PCHAR ForwarderName
;
1881 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1882 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1884 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1885 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1886 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1887 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1888 if (!NT_SUCCESS(Status
))
1890 DPRINT1("failed to load %s\n", ForwarderName
);
1893 if (Module
== ImportedModule
)
1895 LdrpDecrementLoadCount(Module
, FALSE
);
1897 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1898 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1900 TRACE_LDR("%wZ has stale binding to %s\n",
1901 &Module
->BaseDllName
, ForwarderName
);
1902 WrongForwarder
= TRUE
;
1906 TRACE_LDR("%wZ has correct binding to %s\n",
1907 &Module
->BaseDllName
, ForwarderName
);
1911 if (WrongForwarder
||
1912 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1914 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1915 if (!NT_SUCCESS(Status
))
1917 DPRINT1("failed to import %s\n", ImportedName
);
1921 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1923 TRACE_LDR("Adjust imports for %s from %wZ\n",
1924 ImportedName
, &Module
->BaseDllName
);
1925 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1926 if (!NT_SUCCESS(Status
))
1928 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
1932 else if (WrongForwarder
)
1936 * Update only forwarders
1938 TRACE_LDR("Stale BIND %s from %wZ\n",
1939 ImportedName
, &Module
->BaseDllName
);
1940 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1941 if (!NT_SUCCESS(Status
))
1943 DPRINT1("faild to import %s\n", ImportedName
);
1952 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
1955 else if (ImportModuleDirectory
)
1957 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
1959 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
1960 while (ImportModuleDirectoryCurrent
->Name
)
1962 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
1963 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
1965 if (SearchPath
== NULL
)
1967 ModulePath
= LdrpQueryAppPaths(Module
->BaseDllName
.Buffer
);
1969 Status
= LdrpGetOrLoadModule(ModulePath
, ImportedName
, &ImportedModule
, TRUE
);
1970 if (ModulePath
!= NULL
) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath
);
1971 if (NT_SUCCESS(Status
)) goto Success
;
1974 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1975 if (!NT_SUCCESS(Status
))
1977 DPRINT1("failed to load %s\n", ImportedName
);
1981 if (Module
== ImportedModule
)
1983 LdrpDecrementLoadCount(Module
, FALSE
);
1986 TRACE_LDR("Initializing imports for %wZ from %s\n",
1987 &Module
->BaseDllName
, ImportedName
);
1988 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
1989 if (!NT_SUCCESS(Status
))
1991 DPRINT1("failed to import %s\n", ImportedName
);
1994 ImportModuleDirectoryCurrent
++;
1998 if (TlsDirectory
&& TlsSize
> 0)
2000 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
2003 return STATUS_SUCCESS
;
2007 /**********************************************************************
2012 * 1. Relocate, if needed the EXE.
2013 * 2. Fixup any imported symbol.
2014 * 3. Compute the EXE's entry point.
2018 * Address at which the EXE's image
2022 * Handle of the section that contains
2026 * NULL on error; otherwise the entry point
2027 * to call for initializing the DLL.
2032 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
2033 * Currently the function is only used for the exe.
2035 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
2036 HANDLE SectionHandle
,
2037 PLDR_DATA_TABLE_ENTRY
* Module
,
2041 PEPFUNC EntryPoint
= NULL
;
2042 PIMAGE_DOS_HEADER DosHeader
;
2043 PIMAGE_NT_HEADERS NTHeaders
;
2044 PLDR_DATA_TABLE_ENTRY tmpModule
;
2046 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
2047 ImageBase
, SectionHandle
);
2050 * Overlay DOS and WNT headers structures
2051 * to the DLL's image.
2053 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
2054 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
2057 * If the base address is different from the
2058 * one the DLL is actually loaded, perform any
2061 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2063 DPRINT("LDR: Performing relocations\n");
2064 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
2065 if (!NT_SUCCESS(Status
))
2067 DPRINT1("LdrPerformRelocations() failed\n");
2074 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
2075 (*Module
)->SectionPointer
= SectionHandle
;
2079 Module
= &tmpModule
;
2080 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
2081 if (!NT_SUCCESS(Status
))
2087 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2089 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2093 * If the DLL's imports symbols from other
2094 * modules, fixup the imported calls entry points.
2096 DPRINT("About to fixup imports\n");
2097 Status
= LdrFixupImports(NULL
, *Module
);
2098 if (!NT_SUCCESS(Status
))
2100 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
2103 DPRINT("Fixup done\n");
2104 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2105 Status
= LdrpInitializeTlsForProccess();
2106 if (NT_SUCCESS(Status
))
2108 Status
= LdrpAttachProcess();
2110 if (NT_SUCCESS(Status
))
2112 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2116 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2117 if (!NT_SUCCESS(Status
))
2123 * Compute the DLL's entry point's address.
2125 DPRINT("ImageBase = %p\n", ImageBase
);
2126 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2127 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2129 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2130 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2132 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2137 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2139 IN PUNICODE_STRING Name
,
2140 PLDR_DATA_TABLE_ENTRY
*Module
,
2141 PVOID
*BaseAddress OPTIONAL
)
2143 UNICODE_STRING AdjustedName
;
2144 UNICODE_STRING FullDosName
;
2146 PLDR_DATA_TABLE_ENTRY tmpModule
;
2147 HANDLE SectionHandle
;
2150 PIMAGE_NT_HEADERS NtHeaders
;
2151 BOOLEAN MappedAsDataFile
;
2152 PVOID ArbitraryUserPointer
;
2156 Module
= &tmpModule
;
2158 /* adjust the full dll name */
2159 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2161 DPRINT("%wZ\n", &AdjustedName
);
2163 MappedAsDataFile
= FALSE
;
2164 /* Test if dll is already loaded */
2165 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2166 if (NT_SUCCESS(Status
))
2168 RtlFreeUnicodeString(&AdjustedName
);
2169 if (NULL
!= BaseAddress
)
2171 *BaseAddress
= (*Module
)->DllBase
;
2176 /* Open or create dll image section */
2177 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2178 if (!NT_SUCCESS(Status
))
2180 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2181 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2182 MappedAsDataFile
, &SectionHandle
);
2184 if (!NT_SUCCESS(Status
))
2186 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2187 RtlFreeUnicodeString(&AdjustedName
);
2190 RtlFreeUnicodeString(&AdjustedName
);
2191 /* Map the dll into the process */
2194 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2195 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2196 Status
= NtMapViewOfSection(SectionHandle
,
2206 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2207 if (!NT_SUCCESS(Status
))
2209 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2210 RtlFreeUnicodeString(&FullDosName
);
2211 NtClose(SectionHandle
);
2214 if (NULL
!= BaseAddress
)
2216 *BaseAddress
= ImageBase
;
2218 if (!MappedAsDataFile
)
2220 /* Get and check the NT headers */
2221 NtHeaders
= RtlImageNtHeader(ImageBase
);
2222 if (NtHeaders
== NULL
)
2224 DPRINT1("RtlImageNtHeaders() failed\n");
2225 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2226 NtClose (SectionHandle
);
2227 RtlFreeUnicodeString(&FullDosName
);
2228 return STATUS_UNSUCCESSFUL
;
2231 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2232 if (MappedAsDataFile
)
2234 ASSERT(NULL
!= BaseAddress
);
2235 if (NULL
!= BaseAddress
)
2237 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2240 RtlFreeUnicodeString(&FullDosName
);
2241 NtClose(SectionHandle
);
2242 return STATUS_SUCCESS
;
2244 /* If the base address is different from the
2245 * one the DLL is actually loaded, perform any
2247 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2249 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2250 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2251 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2252 if (!NT_SUCCESS(Status
))
2254 DPRINT1("LdrPerformRelocations() failed\n");
2255 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2256 NtClose (SectionHandle
);
2257 RtlFreeUnicodeString(&FullDosName
);
2258 return STATUS_UNSUCCESSFUL
;
2261 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2262 (*Module
)->SectionPointer
= SectionHandle
;
2263 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2265 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2267 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2269 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2271 /* fixup the imported calls entry points */
2272 Status
= LdrFixupImports(SearchPath
, *Module
);
2273 if (!NT_SUCCESS(Status
))
2275 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2278 #if DBG || defined(KDBG)
2279 LdrpLoadUserModuleSymbols(*Module
);
2280 #endif /* DBG || KDBG */
2281 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2282 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2283 &(*Module
)->InInitializationOrderLinks
);
2284 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2286 return STATUS_SUCCESS
;
2290 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2293 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2294 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2295 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2297 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2304 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2307 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2309 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2313 /* ?????????????????? */
2315 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2317 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2318 RtlImageDirectoryEntryToData(Module
->DllBase
,
2320 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2322 if (BoundImportDescriptor
)
2324 /* dereferencing all imported modules, use the bound import descriptor */
2325 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2326 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2328 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2329 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2330 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2331 if (!NT_SUCCESS(Status
))
2333 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2337 if (Module
!= ImportedModule
)
2339 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2340 if (!NT_SUCCESS(Status
))
2342 DPRINT1("unable to unload %s\n", ImportedName
);
2346 BoundImportDescriptorCurrent
++;
2351 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2352 RtlImageDirectoryEntryToData(Module
->DllBase
,
2354 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2356 if (ImportModuleDirectory
)
2358 /* dereferencing all imported modules, use the import descriptor */
2359 while (ImportModuleDirectory
->Name
)
2361 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2362 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2363 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2364 if (!NT_SUCCESS(Status
))
2366 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2370 if (Module
!= ImportedModule
)
2372 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2373 if (!NT_SUCCESS(Status
))
2375 DPRINT1("unable to unload %s\n", ImportedName
);
2379 ImportModuleDirectory
++;
2387 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2389 LdrpDetachProcess(FALSE
);
2392 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2394 return STATUS_SUCCESS
;
2402 LdrUnloadDll (IN PVOID BaseAddress
)
2404 PLDR_DATA_TABLE_ENTRY Module
;
2407 if (BaseAddress
== NULL
)
2408 return STATUS_SUCCESS
;
2410 if (LdrMappedAsDataFile(&BaseAddress
))
2412 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2416 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2417 if (NT_SUCCESS(Status
))
2419 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2420 Status
= LdrpUnloadModule(Module
, TRUE
);
2431 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2433 PLIST_ENTRY ModuleListHead
;
2435 PLDR_DATA_TABLE_ENTRY Module
;
2438 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2440 Status
= STATUS_DLL_NOT_FOUND
;
2441 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2442 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2443 Entry
= ModuleListHead
->Flink
;
2444 while (Entry
!= ModuleListHead
)
2446 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2448 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2450 if (Module
->DllBase
== BaseAddress
)
2452 if (Module
->TlsIndex
== 0xFFFF)
2454 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2455 Status
= STATUS_SUCCESS
;
2459 Entry
= Entry
->Flink
;
2461 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2469 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2470 IN PULONG DllCharacteristics
,
2471 IN PUNICODE_STRING DllName
,
2472 OUT PVOID
*DllHandle
)
2474 PLDR_DATA_TABLE_ENTRY Module
;
2477 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2478 DllName
, DllPath
? DllPath
: L
"");
2480 /* NULL is the current executable */
2481 if (DllName
== NULL
)
2483 *DllHandle
= ExeModule
->DllBase
;
2484 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2485 return STATUS_SUCCESS
;
2488 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2489 if (NT_SUCCESS(Status
))
2491 *DllHandle
= Module
->DllBase
;
2492 return STATUS_SUCCESS
;
2495 DPRINT("Failed to find dll %wZ\n", DllName
);
2497 return STATUS_DLL_NOT_FOUND
;
2504 LdrAddRefDll(IN ULONG Flags
,
2505 IN PVOID BaseAddress
)
2507 PLIST_ENTRY ModuleListHead
;
2509 PLDR_DATA_TABLE_ENTRY Module
;
2512 if (Flags
& ~(LDR_PIN_MODULE
))
2514 return STATUS_INVALID_PARAMETER
;
2517 Status
= STATUS_DLL_NOT_FOUND
;
2518 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2519 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2520 Entry
= ModuleListHead
->Flink
;
2521 while (Entry
!= ModuleListHead
)
2523 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2525 if (Module
->DllBase
== BaseAddress
)
2527 if (Flags
& LDR_PIN_MODULE
)
2529 Module
->Flags
|= LDRP_STATIC_LINK
;
2533 LdrpIncrementLoadCount(Module
,
2536 Status
= STATUS_SUCCESS
;
2539 Entry
= Entry
->Flink
;
2541 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2549 RtlPcToFileHeader(IN PVOID PcValue
,
2552 PLIST_ENTRY ModuleListHead
;
2554 PLDR_DATA_TABLE_ENTRY Module
;
2555 PVOID ImageBase
= NULL
;
2557 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2558 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2559 Entry
= ModuleListHead
->Flink
;
2560 while (Entry
!= ModuleListHead
)
2562 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2564 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2565 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2567 ImageBase
= Module
->DllBase
;
2570 Entry
= Entry
->Flink
;
2572 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2574 *BaseOfImage
= ImageBase
;
2582 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2583 IN PANSI_STRING Name
,
2585 OUT PVOID
*ProcedureAddress
)
2587 NTSTATUS Status
= STATUS_PROCEDURE_NOT_FOUND
;
2588 if (Name
&& Name
->Length
)
2590 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2594 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2597 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2598 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2602 if (Name
&& Name
->Length
)
2605 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2606 if (*ProcedureAddress
!= NULL
)
2608 Status
= STATUS_SUCCESS
;
2610 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2615 Ordinal
&= 0x0000FFFF;
2616 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2617 if (*ProcedureAddress
)
2619 Status
= STATUS_SUCCESS
;
2621 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2626 Status
= STATUS_DLL_NOT_FOUND
;
2633 /**********************************************************************
2638 * Unload dll's which are no longer referenced from others dll's
2649 * The loader lock must be held on enty.
2652 LdrpDetachProcess(BOOLEAN UnloadAll
)
2654 PLIST_ENTRY ModuleListHead
;
2656 PLDR_DATA_TABLE_ENTRY Module
;
2657 static ULONG CallingCount
= 0;
2659 DPRINT("LdrpDetachProcess() called for %wZ\n",
2660 &ExeModule
->BaseDllName
);
2663 LdrpDllShutdownInProgress
= TRUE
;
2667 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2668 Entry
= ModuleListHead
->Blink
;
2669 while (Entry
!= ModuleListHead
)
2671 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2672 if (((UnloadAll
&& Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0) &&
2673 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2674 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2676 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2677 if (Module
== LdrpLastModule
)
2679 LdrpLastModule
= NULL
;
2681 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2683 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2684 &Module
->BaseDllName
, Module
->EntryPoint
);
2685 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2689 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2691 Entry
= ModuleListHead
->Blink
;
2695 Entry
= Entry
->Blink
;
2699 if (CallingCount
== 1)
2701 Entry
= ModuleListHead
->Blink
;
2702 while (Entry
!= ModuleListHead
)
2704 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2705 Entry
= Entry
->Blink
;
2706 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2707 ((UnloadAll
&& Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0))
2709 /* remove the module entry from the list */
2710 RemoveEntryList (&Module
->InLoadOrderLinks
);
2711 RemoveEntryList (&Module
->InInitializationOrderLinks
);
2713 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2714 NtClose (Module
->SectionPointer
);
2716 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2718 RtlFreeUnicodeString (&Module
->FullDllName
);
2719 RtlFreeUnicodeString (&Module
->BaseDllName
);
2721 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2726 DPRINT("LdrpDetachProcess() done\n");
2729 /**********************************************************************
2734 * Initialize all dll's which are prepered for loading
2745 * The loader lock must be held on entry.
2749 LdrpAttachProcess(VOID
)
2751 PLIST_ENTRY ModuleListHead
;
2753 PLDR_DATA_TABLE_ENTRY Module
;
2755 NTSTATUS Status
= STATUS_SUCCESS
;
2757 DPRINT("LdrpAttachProcess() called for %wZ\n",
2758 &ExeModule
->BaseDllName
);
2760 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2761 Entry
= ModuleListHead
->Flink
;
2762 while (Entry
!= ModuleListHead
)
2764 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2765 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2767 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2768 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2769 &Module
->BaseDllName
, Module
->EntryPoint
);
2770 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2773 Status
= STATUS_DLL_INIT_FAILED
;
2776 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2778 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2782 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2784 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2786 Entry
= Entry
->Flink
;
2789 DPRINT("LdrpAttachProcess() done\n");
2798 RtlDllShutdownInProgress (VOID
)
2800 return LdrpDllShutdownInProgress
;
2807 LdrShutdownProcess (VOID
)
2809 LdrpDetachProcess(TRUE
);
2810 return STATUS_SUCCESS
;
2818 LdrpAttachThread (VOID
)
2820 PLIST_ENTRY ModuleListHead
;
2822 PLDR_DATA_TABLE_ENTRY Module
;
2825 DPRINT("LdrpAttachThread() called for %wZ\n",
2826 &ExeModule
->BaseDllName
);
2828 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2830 Status
= LdrpInitializeTlsForThread();
2832 if (NT_SUCCESS(Status
))
2834 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2835 Entry
= ModuleListHead
->Flink
;
2837 while (Entry
!= ModuleListHead
)
2839 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2840 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2841 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2842 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2844 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2845 &Module
->BaseDllName
, Module
->EntryPoint
);
2846 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2848 Entry
= Entry
->Flink
;
2851 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2852 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2853 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2856 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2858 DPRINT("LdrpAttachThread() done\n");
2868 LdrShutdownThread (VOID
)
2870 PLIST_ENTRY ModuleListHead
;
2872 PLDR_DATA_TABLE_ENTRY Module
;
2874 DPRINT("LdrShutdownThread() called for %wZ\n",
2875 &ExeModule
->BaseDllName
);
2877 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2879 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2880 Entry
= ModuleListHead
->Blink
;
2881 while (Entry
!= ModuleListHead
)
2883 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2885 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2886 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2887 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2889 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2890 &Module
->BaseDllName
, Module
->EntryPoint
);
2891 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2893 Entry
= Entry
->Blink
;
2896 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2900 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2903 DPRINT("LdrShutdownThread() done\n");
2905 return STATUS_SUCCESS
;
2909 /***************************************************************************
2911 * LdrQueryProcessModuleInformation
2926 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
2927 IN ULONG Size OPTIONAL
,
2928 OUT PULONG ReturnedSize
)
2930 PLIST_ENTRY ModuleListHead
;
2932 PLDR_DATA_TABLE_ENTRY Module
;
2933 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
2934 NTSTATUS Status
= STATUS_SUCCESS
;
2935 ULONG UsedSize
= sizeof(ULONG
);
2936 ANSI_STRING AnsiString
;
2939 DPRINT("LdrQueryProcessModuleInformation() called\n");
2940 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
2941 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2943 if (ModuleInformation
== NULL
|| Size
== 0)
2945 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2949 ModuleInformation
->NumberOfModules
= 0;
2950 ModulePtr
= &ModuleInformation
->Modules
[0];
2951 Status
= STATUS_SUCCESS
;
2954 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2955 Entry
= ModuleListHead
->Flink
;
2957 while (Entry
!= ModuleListHead
)
2959 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2961 DPRINT(" Module %wZ\n",
2962 &Module
->FullDllName
);
2964 if (UsedSize
> Size
)
2966 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2968 else if (ModuleInformation
!= NULL
)
2970 ModulePtr
->Section
= 0;
2971 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
2972 ModulePtr
->ImageBase
= Module
->DllBase
;
2973 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
2974 ModulePtr
->Flags
= Module
->Flags
;
2975 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
2976 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
2977 ModulePtr
->LoadCount
= Module
->LoadCount
;
2979 AnsiString
.Length
= 0;
2980 AnsiString
.MaximumLength
= 256;
2981 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
2982 RtlUnicodeStringToAnsiString(&AnsiString
,
2983 &Module
->FullDllName
,
2986 p
= strrchr(ModulePtr
->FullPathName
, '\\');
2988 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
2990 ModulePtr
->OffsetToFileName
= 0;
2993 ModuleInformation
->NumberOfModules
++;
2995 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
2997 Entry
= Entry
->Flink
;
3000 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
3002 if (ReturnedSize
!= 0)
3003 *ReturnedSize
= UsedSize
;
3005 DPRINT("LdrQueryProcessModuleInformation() done\n");
3012 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
3015 PIMAGE_NT_HEADERS Header
;
3022 Header
= RtlImageNtHeader (BaseAddress
);
3026 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
3031 Ptr
= (PUSHORT
) BaseAddress
;
3032 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
3035 if (HIWORD(Sum
) != 0)
3037 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3044 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
3045 if (HIWORD(Sum
) != 0)
3047 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3051 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
3053 /* Subtract image checksum from calculated checksum. */
3054 /* fix low word of checksum */
3055 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
3057 CalcSum
-= LOWORD(HeaderSum
);
3061 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
3064 /* fix high word of checksum */
3065 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
3067 CalcSum
-= HIWORD(HeaderSum
);
3071 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
3074 /* add file length */
3075 CalcSum
+= ImageSize
;
3077 return (BOOLEAN
)(CalcSum
== HeaderSum
);
3081 * Compute size of an image as it is actually present in virt memory
3082 * (i.e. excluding NEVER_LOAD sections)
3085 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
3087 PIMAGE_SECTION_HEADER SectionHeader
;
3088 unsigned SectionIndex
;
3091 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
3092 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
3094 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
3096 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
3097 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
3099 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
3104 return ResidentSize
;
3108 /***************************************************************************
3110 * LdrVerifyImageMatchesChecksum
3125 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3130 FILE_STANDARD_INFORMATION FileInfo
;
3131 IO_STATUS_BLOCK IoStatusBlock
;
3132 HANDLE SectionHandle
;
3138 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3140 Status
= NtCreateSection (&SectionHandle
,
3147 if (!NT_SUCCESS(Status
))
3149 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3155 Status
= NtMapViewOfSection (SectionHandle
,
3156 NtCurrentProcess (),
3165 if (!NT_SUCCESS(Status
))
3167 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3168 NtClose (SectionHandle
);
3172 Status
= NtQueryInformationFile (FileHandle
,
3175 sizeof (FILE_STANDARD_INFORMATION
),
3176 FileStandardInformation
);
3177 if (!NT_SUCCESS(Status
))
3179 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3180 NtUnmapViewOfSection (NtCurrentProcess (),
3182 NtClose (SectionHandle
);
3186 Result
= LdrpCheckImageChecksum (BaseAddress
,
3187 FileInfo
.EndOfFile
.u
.LowPart
);
3188 if (Result
== FALSE
)
3190 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3193 NtUnmapViewOfSection (NtCurrentProcess (),
3196 NtClose (SectionHandle
);
3202 /***************************************************************************
3204 * LdrQueryImageFileExecutionOptions
3219 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3220 IN PCWSTR ValueName
,
3223 IN ULONG BufferSize
,
3224 OUT PULONG ReturnedLength OPTIONAL
)
3226 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3227 OBJECT_ATTRIBUTES ObjectAttributes
;
3228 UNICODE_STRING ValueNameString
;
3229 UNICODE_STRING KeyName
;
3230 WCHAR NameBuffer
[256];
3238 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3239 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3242 Ptr
= SubKey
->Buffer
;
3248 wcscat (NameBuffer
, Ptr
);
3249 RtlInitUnicodeString (&KeyName
,
3252 InitializeObjectAttributes (&ObjectAttributes
,
3254 OBJ_CASE_INSENSITIVE
,
3258 Status
= NtOpenKey (&KeyHandle
,
3261 if (!NT_SUCCESS(Status
))
3263 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3267 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3268 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3271 if (KeyInfo
== NULL
)
3273 NtClose (KeyHandle
);
3274 return STATUS_INSUFFICIENT_RESOURCES
;
3277 RtlInitUnicodeString (&ValueNameString
,
3279 Status
= NtQueryValueKey (KeyHandle
,
3281 KeyValuePartialInformation
,
3285 if (Status
== STATUS_BUFFER_OVERFLOW
)
3287 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3288 RtlFreeHeap (RtlGetProcessHeap(),
3291 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3294 if (KeyInfo
== NULL
)
3296 NtClose (KeyHandle
);
3297 return STATUS_INSUFFICIENT_RESOURCES
;
3300 Status
= NtQueryValueKey (KeyHandle
,
3302 KeyValuePartialInformation
,
3307 NtClose (KeyHandle
);
3309 if (!NT_SUCCESS(Status
))
3311 if (KeyInfo
!= NULL
)
3313 RtlFreeHeap (RtlGetProcessHeap(),
3320 if (KeyInfo
->Type
!= Type
)
3322 RtlFreeHeap (RtlGetProcessHeap(),
3325 return STATUS_OBJECT_TYPE_MISMATCH
;
3328 ResultSize
= BufferSize
;
3329 if (ResultSize
< KeyInfo
->DataLength
)
3331 Status
= STATUS_BUFFER_OVERFLOW
;
3335 ResultSize
= KeyInfo
->DataLength
;
3337 RtlCopyMemory (Buffer
,
3341 RtlFreeHeap (RtlGetProcessHeap(),
3345 if (ReturnedLength
!= NULL
)
3347 *ReturnedLength
= ResultSize
;
3354 PIMAGE_BASE_RELOCATION NTAPI
3355 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3357 IN PUSHORT TypeOffset
,
3366 for (i
= 0; i
< Count
; i
++)
3368 Offset
= *TypeOffset
& 0xFFF;
3369 Type
= *TypeOffset
>> 12;
3373 case IMAGE_REL_BASED_ABSOLUTE
:
3376 case IMAGE_REL_BASED_HIGH
:
3377 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3378 *ShortPtr
+= HIWORD(Delta
);
3381 case IMAGE_REL_BASED_LOW
:
3382 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3383 *ShortPtr
+= LOWORD(Delta
);
3386 case IMAGE_REL_BASED_HIGHLOW
:
3387 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3391 case IMAGE_REL_BASED_DIR64
:
3392 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3397 case IMAGE_REL_BASED_HIGHADJ
:
3398 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3400 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3407 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3412 LdrLockLoaderLock(IN ULONG Flags
,
3413 OUT PULONG Disposition OPTIONAL
,
3414 OUT PULONG Cookie OPTIONAL
)
3417 return STATUS_NOT_IMPLEMENTED
;
3422 LdrUnlockLoaderLock(IN ULONG Flags
,
3423 IN ULONG Cookie OPTIONAL
)
3426 return STATUS_NOT_IMPLEMENTED
;
3431 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)