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)
13 * - Handle loading flags correctly
14 * - Handle errors correctly (unload dll's)
15 * - Implement a faster way to find modules (hash table)
19 /* INCLUDES *****************************************************************/
25 #define LDRP_PROCESS_CREATION_TIME 0xffff
26 #define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
28 /* GLOBALS *******************************************************************/
31 #define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
34 typedef struct _TLS_DATA
36 PVOID StartAddressOfRawData
;
39 PIMAGE_TLS_CALLBACK
*TlsAddressOfCallBacks
;
40 PLDR_DATA_TABLE_ENTRY Module
;
41 } TLS_DATA
, *PTLS_DATA
;
43 static BOOLEAN LdrpDllShutdownInProgress
= FALSE
;
44 static PTLS_DATA LdrpTlsArray
= NULL
;
45 static ULONG LdrpTlsCount
= 0;
46 static ULONG LdrpTlsSize
= 0;
47 static HANDLE LdrpKnownDllsDirHandle
= NULL
;
48 static UNICODE_STRING LdrpKnownDllPath
= {0, 0, NULL
};
49 static PLDR_DATA_TABLE_ENTRY LdrpLastModule
= NULL
;
50 extern PLDR_DATA_TABLE_ENTRY ExeModule
;
52 /* PROTOTYPES ****************************************************************/
54 static NTSTATUS
LdrFindEntryForName(PUNICODE_STRING Name
, PLDR_DATA_TABLE_ENTRY
*Module
, BOOLEAN Ref
);
55 static PVOID
LdrFixupForward(PCHAR ForwardName
);
56 static PVOID
LdrGetExportByName(PVOID BaseAddress
, PUCHAR SymbolName
, USHORT Hint
);
57 static NTSTATUS
LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
59 IN PUNICODE_STRING Name
,
60 OUT PLDR_DATA_TABLE_ENTRY
*Module
,
61 OUT PVOID
*BaseAddress OPTIONAL
);
62 static NTSTATUS
LdrpAttachProcess(VOID
);
63 static VOID
LdrpDetachProcess(BOOLEAN UnloadAll
);
65 NTSTATUS
find_actctx_dll( LPCWSTR libname
, WCHAR
*fulldosname
);
66 NTSTATUS
create_module_activation_context( LDR_DATA_TABLE_ENTRY
*module
);
68 /* FUNCTIONS *****************************************************************/
71 LdrMappedAsDataFile(PVOID
*BaseAddress
)
73 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
75 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
82 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
87 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
89 LoadCount
= Module
->LoadCount
;
90 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
96 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
101 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
106 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
108 LoadCount
= Module
->LoadCount
;
109 if (Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
115 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
120 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
124 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
126 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
131 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
135 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
137 PIMAGE_TLS_CALLBACK
*TlsCallback
;
138 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
)
140 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
145 TRACE_LDR("%wZ - Calling tls callback at %x\n",
146 &Module
->BaseDllName
, *TlsCallback
);
147 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
154 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
156 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
157 Module
->EntryPoint
== 0)
161 LdrpTlsCallback(Module
, dwReason
);
162 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
166 LdrpQueryAppPaths(IN PCWSTR ImageName
)
168 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
169 OBJECT_ATTRIBUTES ObjectAttributes
;
170 WCHAR SearchPathBuffer
[5*MAX_PATH
];
171 UNICODE_STRING ValueNameString
;
172 UNICODE_STRING KeyName
;
173 WCHAR NameBuffer
[MAX_PATH
];
181 _snwprintf(NameBuffer
,
182 sizeof(NameBuffer
) / sizeof(WCHAR
),
183 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
186 RtlInitUnicodeString(&KeyName
, NameBuffer
);
188 InitializeObjectAttributes(&ObjectAttributes
,
190 OBJ_CASE_INSENSITIVE
,
194 Status
= NtOpenKey(&KeyHandle
,
197 if (!NT_SUCCESS(Status
))
199 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
203 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 256 * sizeof(WCHAR
);
205 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize
);
208 DPRINT("RtlAllocateHeap() failed\n");
213 RtlInitUnicodeString(&ValueNameString
,
216 Status
= NtQueryValueKey(KeyHandle
,
218 KeyValuePartialInformation
,
223 if (!NT_SUCCESS(Status
))
226 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
230 RtlCopyMemory(SearchPathBuffer
,
232 KeyInfo
->DataLength
);
234 /* Free KeyInfo memory, we won't need it anymore */
235 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
237 /* Close the key handle */
240 /* get application running path */
241 wcscat(SearchPathBuffer
, L
";");
242 wcscat(SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
); // FIXME: Don't rely on it being NULL-terminated!!!
244 /* Remove trailing backslash */
245 Backslash
= wcsrchr(SearchPathBuffer
, L
'\\');
246 if (Backslash
) Backslash
= L
'\0';
248 wcscat(SearchPathBuffer
, L
";");
250 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
251 wcscat(SearchPathBuffer
, L
"\\system32;");
252 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
253 wcscat(SearchPathBuffer
, L
";.");
255 /* Copy it to the heap allocd memory */
256 Path
= RtlAllocateHeap(RtlGetProcessHeap(),
258 wcslen(SearchPathBuffer
) * sizeof(WCHAR
));
262 DPRINT1("RtlAllocateHeap() failed\n");
266 wcscpy(Path
, SearchPathBuffer
);
272 LdrpInitializeTlsForThread(VOID
)
278 PTEB Teb
= NtCurrentTeb();
280 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
282 Teb
->StaticUnicodeString
.Length
= 0;
283 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
284 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
286 if (LdrpTlsCount
> 0)
288 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
290 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
291 if (TlsPointers
== NULL
)
293 DPRINT1("failed to allocate thread tls data\n");
294 return STATUS_NO_MEMORY
;
297 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
298 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
300 TlsInfo
= LdrpTlsArray
;
301 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
303 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
304 TlsPointers
[i
] = TlsData
;
305 if (TlsInfo
->TlsDataSize
)
307 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
308 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
310 if (TlsInfo
->TlsZeroSize
)
312 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
313 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
318 DPRINT("LdrpInitializeTlsForThread() done\n");
319 return STATUS_SUCCESS
;
323 LdrpInitializeTlsForProccess(VOID
)
325 PLIST_ENTRY ModuleListHead
;
327 PLDR_DATA_TABLE_ENTRY Module
;
328 PIMAGE_TLS_DIRECTORY TlsDirectory
;
332 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
334 if (LdrpTlsCount
> 0)
336 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
338 LdrpTlsCount
* sizeof(TLS_DATA
));
339 if (LdrpTlsArray
== NULL
)
341 DPRINT1("Failed to allocate global tls data\n");
342 return STATUS_NO_MEMORY
;
345 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
346 Entry
= ModuleListHead
->Flink
;
347 while (Entry
!= ModuleListHead
)
349 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
350 if (Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
&&
351 Module
->TlsIndex
!= 0xFFFF)
353 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
354 RtlImageDirectoryEntryToData(Module
->DllBase
,
356 IMAGE_DIRECTORY_ENTRY_TLS
,
358 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
359 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
360 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
361 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
362 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
363 if (TlsDirectory
->AddressOfCallBacks
)
364 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
366 TlsData
->TlsAddressOfCallBacks
= NULL
;
367 TlsData
->Module
= Module
;
369 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
370 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
371 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
372 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
373 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
374 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
375 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
376 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
380 * Is this region allways writable ?
382 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
384 Entry
= Entry
->Flink
;
388 DPRINT("LdrpInitializeTlsForProccess() done\n");
389 return STATUS_SUCCESS
;
395 OBJECT_ATTRIBUTES ObjectAttributes
;
396 UNICODE_STRING LinkTarget
;
402 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
404 /* Get handle to the 'KnownDlls' directory */
405 RtlInitUnicodeString(&Name
,
407 InitializeObjectAttributes(&ObjectAttributes
,
409 OBJ_CASE_INSENSITIVE
,
412 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
413 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
415 if (!NT_SUCCESS(Status
))
417 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
418 LdrpKnownDllsDirHandle
= NULL
;
422 /* Allocate target name string */
423 LinkTarget
.Length
= 0;
424 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
425 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
427 MAX_PATH
* sizeof(WCHAR
));
428 if (LinkTarget
.Buffer
== NULL
)
430 NtClose(LdrpKnownDllsDirHandle
);
431 LdrpKnownDllsDirHandle
= NULL
;
435 RtlInitUnicodeString(&Name
,
437 InitializeObjectAttributes(&ObjectAttributes
,
439 OBJ_CASE_INSENSITIVE
,
440 LdrpKnownDllsDirHandle
,
442 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
443 SYMBOLIC_LINK_ALL_ACCESS
,
445 if (!NT_SUCCESS(Status
))
447 RtlFreeUnicodeString(&LinkTarget
);
448 NtClose(LdrpKnownDllsDirHandle
);
449 LdrpKnownDllsDirHandle
= NULL
;
453 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
457 if (!NT_SUCCESS(Status
))
459 RtlFreeUnicodeString(&LinkTarget
);
460 NtClose(LdrpKnownDllsDirHandle
);
461 LdrpKnownDllsDirHandle
= NULL
;
464 RtlCreateUnicodeString(&LdrpKnownDllPath
,
467 RtlFreeUnicodeString(&LinkTarget
);
469 DPRINT("LdrpInitLoader() done\n");
473 /***************************************************************************
478 * Adjusts the name of a dll to a fully qualified name.
481 * FullDllName: Pointer to caller supplied storage for the fully
482 * qualified dll name.
483 * DllName: Pointer to the dll name.
484 * BaseName: TRUE: Only the file name is passed to FullDllName
485 * FALSE: The full path is preserved in FullDllName
493 * A given path is not affected by the adjustment, but the file
495 * ntdll --> ntdll.dll
497 * ntdll.xyz --> ntdll.xyz
500 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
501 PUNICODE_STRING DllName
,
504 WCHAR Buffer
[MAX_PATH
];
509 Length
= DllName
->Length
/ sizeof(WCHAR
);
513 /* get the base dll name */
514 Pointer
= DllName
->Buffer
+ Length
;
521 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
524 Length
= Extension
- Pointer
;
525 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
526 Buffer
[Length
] = L
'\0';
530 /* get the full dll name */
531 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
532 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
535 /* Build the DLL's absolute name */
536 Extension
= wcsrchr (Buffer
, L
'.');
537 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
539 /* with extension - remove dot if it's the last character */
540 if (Buffer
[Length
- 1] == L
'.')
546 /* name without extension - assume that it is .dll */
547 memmove (Buffer
+ Length
, L
".dll", 10);
550 RtlCreateUnicodeString(FullDllName
, Buffer
);
553 PLDR_DATA_TABLE_ENTRY
554 LdrAddModuleEntry(PVOID ImageBase
,
555 PIMAGE_NT_HEADERS NTHeaders
,
558 PLDR_DATA_TABLE_ENTRY Module
;
560 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
562 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
563 Module
->DllBase
= (PVOID
)ImageBase
;
564 Module
->EntryPoint
= (PVOID
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
565 if (Module
->EntryPoint
!= 0)
566 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
567 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
568 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
570 /* loading while app is running */
571 Module
->LoadCount
= 1;
574 * loading while app is initializing
575 * dll must not be unloaded
577 Module
->LoadCount
= LDRP_PROCESS_CREATION_TIME
;
581 Module
->TlsIndex
= -1;
582 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
583 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
585 RtlCreateUnicodeString (&Module
->FullDllName
,
587 RtlCreateUnicodeString (&Module
->BaseDllName
,
588 wcsrchr(FullDosName
, L
'\\') + 1);
589 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
591 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
592 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
593 &Module
->InLoadOrderLinks
);
594 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
601 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
602 OUT PUNICODE_STRING FullDosName
,
603 OUT PHANDLE SectionHandle
)
605 OBJECT_ATTRIBUTES ObjectAttributes
;
608 DPRINT("LdrpMapKnownDll() called\n");
610 if (LdrpKnownDllsDirHandle
== NULL
)
612 DPRINT("Invalid 'KnownDlls' directory\n");
613 return STATUS_UNSUCCESSFUL
;
616 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
618 InitializeObjectAttributes(&ObjectAttributes
,
620 OBJ_CASE_INSENSITIVE
,
621 LdrpKnownDllsDirHandle
,
623 Status
= NtOpenSection(SectionHandle
,
624 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
626 if (!NT_SUCCESS(Status
))
628 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
632 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
633 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
634 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
636 FullDosName
->MaximumLength
);
637 if (FullDosName
->Buffer
== NULL
)
639 FullDosName
->Length
= 0;
640 FullDosName
->MaximumLength
= 0;
641 return STATUS_SUCCESS
;
644 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
645 wcscat(FullDosName
->Buffer
, L
"\\");
646 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
648 DPRINT("FullDosName '%wZ'\n", FullDosName
);
650 DPRINT("LdrpMapKnownDll() done\n");
652 return STATUS_SUCCESS
;
657 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
658 IN PUNICODE_STRING DllName
,
659 OUT PUNICODE_STRING FullDosName
,
660 IN BOOLEAN MapAsDataFile
,
661 OUT PHANDLE SectionHandle
)
663 WCHAR
*SearchPathBuffer
= NULL
;
664 WCHAR
*ImagePathNameBufferPtr
= NULL
;
665 WCHAR DosName
[MAX_PATH
];
666 UNICODE_STRING FullNtFileName
;
667 UNICODE_STRING PathEnvironmentVar_U
;
668 UNICODE_STRING PathName_U
;
669 OBJECT_ATTRIBUTES FileObjectAttributes
;
671 char BlockBuffer
[1024];
672 PIMAGE_DOS_HEADER DosHeader
;
673 PIMAGE_NT_HEADERS NTHeaders
;
674 IO_STATUS_BLOCK IoStatusBlock
;
679 DPRINT("LdrpMapDllImageFile() called\n");
681 if (SearchPath
== NULL
)
683 /* get application running path */
684 ImagePathNameBufferPtr
= NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
;
686 /* Length of ImagePathName */
687 ImagePathLen
= wcslen(ImagePathNameBufferPtr
);
689 /* Subtract application name leaveing only the directory length */
690 while (ImagePathLen
&& ImagePathNameBufferPtr
[ImagePathLen
- 1] != L
'\\')
693 /* Length of directory + semicolon */
694 len
= ImagePathLen
+ 1;
696 /* Length of SystemRoot + "//system32" + semicolon*/
697 len
+= wcslen(SharedUserData
->NtSystemRoot
) + 10;
698 /* Length of SystemRoot + semicolon */
699 len
+= wcslen(SharedUserData
->NtSystemRoot
) + 1;
701 RtlInitUnicodeString (&PathName_U
, L
"PATH");
702 PathEnvironmentVar_U
.Length
= 0;
703 PathEnvironmentVar_U
.MaximumLength
= 0;
704 PathEnvironmentVar_U
.Buffer
= NULL
;
706 /* Get the path environment variable */
707 Status
= RtlQueryEnvironmentVariable_U(NULL
, &PathName_U
, &PathEnvironmentVar_U
);
709 /* Check that valid information was returned */
710 if ((Status
== STATUS_BUFFER_TOO_SMALL
) && (PathEnvironmentVar_U
.Length
> 0))
712 /* Allocate memory for the path env var */
713 PathEnvironmentVar_U
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, PathEnvironmentVar_U
.Length
+ sizeof(WCHAR
));
714 if (!PathEnvironmentVar_U
.Buffer
)
716 DPRINT1("Fatal! Out of Memory!!\n");
717 return STATUS_NO_MEMORY
;
719 PathEnvironmentVar_U
.MaximumLength
= PathEnvironmentVar_U
.Length
+ sizeof(WCHAR
);
722 Status
= RtlQueryEnvironmentVariable_U(NULL
, &PathName_U
, &PathEnvironmentVar_U
);
724 if (!NT_SUCCESS(Status
))
726 DPRINT1("Unable to get path environment string!\n");
729 /* Length of path evn var + semicolon */
730 len
+= (PathEnvironmentVar_U
.Length
/ sizeof(WCHAR
)) + 1;
733 /* Allocate the size needed to hold all the above paths + period */
734 SearchPathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, (len
+ 2) * sizeof(WCHAR
));
735 if (!SearchPathBuffer
)
737 DPRINT1("Fatal! Out of Memory!!\n");
738 return STATUS_NO_MEMORY
;
741 wcsncpy(SearchPathBuffer
, ImagePathNameBufferPtr
, ImagePathLen
);
742 wcscat (SearchPathBuffer
, L
";");
743 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
744 wcscat (SearchPathBuffer
, L
"\\system32;");
745 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
746 wcscat (SearchPathBuffer
, L
";");
748 if (PathEnvironmentVar_U
.Buffer
)
750 wcscat (SearchPathBuffer
, PathEnvironmentVar_U
.Buffer
);
751 wcscat (SearchPathBuffer
, L
";");
752 RtlFreeHeap(RtlGetProcessHeap(), 0, PathEnvironmentVar_U
.Buffer
);
754 wcscat (SearchPathBuffer
, L
".");
756 SearchPath
= SearchPathBuffer
;
759 if (RtlDosSearchPath_U (SearchPath
,
766 /* try to find active context dll */
767 Status
= find_actctx_dll(DllName
->Buffer
, DosName
);
768 if(Status
== STATUS_SUCCESS
)
769 DPRINT("found %S for %S\n", DosName
,DllName
->Buffer
);
771 return STATUS_DLL_NOT_FOUND
;
774 if (!RtlDosPathNameToNtPathName_U (DosName
,
779 DPRINT("Dll %wZ not found!\n", DllName
);
780 return STATUS_DLL_NOT_FOUND
;
783 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
785 InitializeObjectAttributes(&FileObjectAttributes
,
791 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
793 Status
= NtOpenFile(&FileHandle
,
794 GENERIC_READ
|SYNCHRONIZE
,
795 &FileObjectAttributes
,
798 FILE_SYNCHRONOUS_IO_NONALERT
);
799 if (!NT_SUCCESS(Status
))
801 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
802 &FullNtFileName
, Status
);
803 RtlFreeHeap (RtlGetProcessHeap (),
805 FullNtFileName
.Buffer
);
808 RtlFreeHeap (RtlGetProcessHeap (),
810 FullNtFileName
.Buffer
);
815 Status
= NtReadFile(FileHandle
,
824 if (!NT_SUCCESS(Status
))
826 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
832 * Overlay DOS and NT headers structures to the
833 * buffer with DLL's header raw data.
835 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
836 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
838 * Check it is a PE image file.
840 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
841 || (DosHeader
->e_lfanew
== 0L)
842 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
844 DPRINT("NTDLL format invalid\n");
847 return STATUS_UNSUCCESSFUL
;
852 * Create a section for dll.
854 Status
= NtCreateSection(SectionHandle
,
859 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
863 if (!NT_SUCCESS(Status
))
865 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
869 RtlCreateUnicodeString(FullDosName
,
877 /***************************************************************************
894 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
895 IN PULONG LoadFlags OPTIONAL
,
896 IN PUNICODE_STRING Name
,
897 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
900 PLDR_DATA_TABLE_ENTRY Module
;
902 PPEB Peb
= NtCurrentPeb();
904 TRACE_LDR("LdrLoadDll, loading %wZ%s%S\n",
906 SearchPath
? L
" from " : L
"",
907 SearchPath
? SearchPath
: L
"");
909 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
911 if (NT_SUCCESS(Status
) &&
912 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
914 if (!create_module_activation_context( Module
))
916 RtlActivateActivationContext(0, Module
->EntryPointActivationContext
, &cookie
);
919 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
921 RtlEnterCriticalSection(Peb
->LoaderLock
);
922 Status
= LdrpAttachProcess();
923 RtlLeaveCriticalSection(Peb
->LoaderLock
);
925 if (Module
->EntryPointActivationContext
) RtlDeactivateActivationContext(0, cookie
);
928 if ((!Module
) && (NT_SUCCESS(Status
)))
931 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
937 /***************************************************************************
939 * LdrFindEntryForAddress
954 LdrFindEntryForAddress(PVOID Address
,
955 PLDR_DATA_TABLE_ENTRY
*Module
)
957 PLIST_ENTRY ModuleListHead
;
959 PLDR_DATA_TABLE_ENTRY ModulePtr
;
961 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
963 if (NtCurrentPeb()->Ldr
== NULL
)
964 return(STATUS_NO_MORE_ENTRIES
);
966 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
967 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
968 Entry
= ModuleListHead
->Flink
;
969 if (Entry
== ModuleListHead
)
971 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
972 return(STATUS_NO_MORE_ENTRIES
);
975 while (Entry
!= ModuleListHead
)
977 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
979 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
981 if ((Address
>= ModulePtr
->DllBase
) &&
982 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
985 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
986 return(STATUS_SUCCESS
);
989 Entry
= Entry
->Flink
;
992 DPRINT("Failed to find module entry.\n");
994 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
995 return(STATUS_NO_MORE_ENTRIES
);
999 /***************************************************************************
1001 * LdrFindEntryForName
1015 LdrFindEntryForName(PUNICODE_STRING Name
,
1016 PLDR_DATA_TABLE_ENTRY
*Module
,
1019 PLIST_ENTRY ModuleListHead
;
1021 PLDR_DATA_TABLE_ENTRY ModulePtr
;
1022 BOOLEAN ContainsPath
;
1023 UNICODE_STRING AdjustedName
;
1025 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
1027 if (NtCurrentPeb()->Ldr
== NULL
)
1028 return(STATUS_NO_MORE_ENTRIES
);
1030 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1031 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1032 Entry
= ModuleListHead
->Flink
;
1033 if (Entry
== ModuleListHead
)
1035 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1036 return(STATUS_NO_MORE_ENTRIES
);
1039 // NULL is the current process
1042 *Module
= ExeModule
;
1043 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1044 return(STATUS_SUCCESS
);
1047 ContainsPath
= (Name
->Length
>= 2 * sizeof(WCHAR
) && L
':' == Name
->Buffer
[1]);
1048 LdrAdjustDllName (&AdjustedName
, Name
, !ContainsPath
);
1052 if ((! ContainsPath
&&
1053 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1055 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
1057 *Module
= LdrpLastModule
;
1058 if (Ref
&& (*Module
)->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1060 (*Module
)->LoadCount
++;
1062 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1063 RtlFreeUnicodeString(&AdjustedName
);
1064 return(STATUS_SUCCESS
);
1067 while (Entry
!= ModuleListHead
)
1069 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1071 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
1073 if ((! ContainsPath
&&
1074 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1076 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
1078 *Module
= LdrpLastModule
= ModulePtr
;
1079 if (Ref
&& ModulePtr
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1081 ModulePtr
->LoadCount
++;
1083 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1084 RtlFreeUnicodeString(&AdjustedName
);
1085 return(STATUS_SUCCESS
);
1088 Entry
= Entry
->Flink
;
1091 DPRINT("Failed to find dll %wZ\n", Name
);
1092 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1093 RtlFreeUnicodeString(&AdjustedName
);
1094 return(STATUS_NO_MORE_ENTRIES
);
1097 /**********************************************************************
1113 LdrFixupForward(PCHAR ForwardName
)
1115 CHAR NameBuffer
[128];
1116 UNICODE_STRING DllName
;
1119 PLDR_DATA_TABLE_ENTRY Module
;
1122 strcpy(NameBuffer
, ForwardName
);
1123 p
= strchr(NameBuffer
, '.');
1128 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
1129 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1132 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1134 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
1136 if (!NT_SUCCESS(Status
))
1138 Status
= LdrLoadDll(NULL
,
1142 if (NT_SUCCESS(Status
))
1144 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1147 RtlFreeUnicodeString (&DllName
);
1148 if (!NT_SUCCESS(Status
))
1150 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
1154 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1156 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1163 /**********************************************************************
1165 * LdrGetExportByOrdinal
1179 LdrGetExportByOrdinal (
1184 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1185 ULONG ExportDirSize
;
1186 PDWORD
* ExFunctions
;
1189 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1190 RtlImageDirectoryEntryToData (BaseAddress
,
1192 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1196 ExFunctions
= (PDWORD
*)
1199 ExportDir
->AddressOfFunctions
1202 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1204 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1207 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1208 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1211 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1212 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1214 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1215 Function
= LdrFixupForward((PCHAR
)Function
);
1222 /**********************************************************************
1224 * LdrGetExportByName
1235 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1236 * both with NumberOfNames entries.
1240 LdrGetExportByName(PVOID BaseAddress
,
1244 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1245 PDWORD
* ExFunctions
;
1247 USHORT
* ExOrdinals
;
1252 ULONG ExportDirSize
;
1254 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1256 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1257 RtlImageDirectoryEntryToData(BaseAddress
,
1259 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1261 if (ExportDir
== NULL
)
1263 DPRINT1("LdrGetExportByName(): no export directory, "
1264 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1269 //The symbol names may be missing entirely
1270 if (ExportDir
->AddressOfNames
== 0)
1272 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1277 * Get header pointers
1279 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1280 ExportDir
->AddressOfNames
);
1281 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1282 ExportDir
->AddressOfNameOrdinals
);
1283 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1284 ExportDir
->AddressOfFunctions
);
1287 * Check the hint first
1289 if (Hint
< ExportDir
->NumberOfNames
)
1291 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1292 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1294 Ordinal
= ExOrdinals
[Hint
];
1295 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1296 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1297 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1299 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1300 Function
= LdrFixupForward((PCHAR
)Function
);
1301 if (Function
== NULL
)
1303 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1307 if (Function
!= NULL
)
1316 maxn
= ExportDir
->NumberOfNames
- 1;
1317 while (minn
<= maxn
)
1322 mid
= (minn
+ maxn
) / 2;
1324 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1325 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1328 Ordinal
= ExOrdinals
[mid
];
1329 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1330 if (((ULONG
)Function
>= (ULONG
)ExportDir
) &&
1331 ((ULONG
)Function
< (ULONG
)ExportDir
+ (ULONG
)ExportDirSize
))
1333 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1334 Function
= LdrFixupForward((PCHAR
)Function
);
1335 if (Function
== NULL
)
1337 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1341 if (Function
!= NULL
)
1344 else if (minn
== maxn
)
1346 DPRINT("LdrGetExportByName(): binary search failed\n");
1359 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1364 /**********************************************************************
1366 * LdrPerformRelocations
1369 * Relocate a DLL's memory image.
1381 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1384 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1385 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1386 ULONG Count
, ProtectSize
, OldProtect
, OldProtect2
;
1387 PVOID Page
, ProtectPage
, ProtectPage2
;
1392 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1394 return STATUS_SUCCESS
;
1398 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1400 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1402 return STATUS_SUCCESS
;
1405 ProtectSize
= PAGE_SIZE
;
1406 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1407 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1408 RelocationDDir
->VirtualAddress
);
1409 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1410 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1412 while (RelocationDir
< RelocationEnd
&&
1413 RelocationDir
->SizeOfBlock
> 0)
1415 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1417 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1418 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1420 /* Unprotect the page(s) we're about to relocate. */
1422 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1427 if (!NT_SUCCESS(Status
))
1429 DPRINT1("Failed to unprotect relocation target.\n");
1433 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1434 NTHeaders
->OptionalHeader
.SizeOfImage
)
1436 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1437 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1442 if (!NT_SUCCESS(Status
))
1444 DPRINT1("Failed to unprotect relocation target (2).\n");
1445 NtProtectVirtualMemory(NtCurrentProcess(),
1455 ProtectPage2
= NULL
;
1458 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1462 if (RelocationDir
== NULL
)
1463 return STATUS_UNSUCCESSFUL
;
1465 /* Restore old page protection. */
1466 NtProtectVirtualMemory(NtCurrentProcess(),
1472 if (ProtectPage2
!= NULL
)
1474 NtProtectVirtualMemory(NtCurrentProcess(),
1482 return STATUS_SUCCESS
;
1486 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1488 PLDR_DATA_TABLE_ENTRY
* Module
,
1491 ANSI_STRING AnsiDllName
;
1492 UNICODE_STRING DllName
;
1495 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1497 RtlInitAnsiString(&AnsiDllName
, Name
);
1498 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1499 if (!NT_SUCCESS(Status
))
1504 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1505 if (Load
&& !NT_SUCCESS(Status
))
1507 Status
= LdrpLoadModule(SearchPath
,
1512 if (NT_SUCCESS(Status
))
1514 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1516 if (!NT_SUCCESS(Status
))
1518 ULONG ErrorResponse
;
1519 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1521 DPRINT1("failed to load %wZ\n", &DllName
);
1523 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1531 RtlFreeUnicodeString (&DllName
);
1536 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1538 ULONG ErrorResponse
;
1539 ULONG_PTR ErrorParameters
[2];
1540 ANSI_STRING ProcNameAnsi
;
1541 UNICODE_STRING ProcName
;
1546 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1550 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1551 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1552 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1553 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1554 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1560 RtlFreeUnicodeString(&ProcName
);
1564 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1565 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1566 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1569 PVOID
* ImportAddressList
;
1570 PULONG FunctionNameList
;
1576 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1578 return STATUS_UNSUCCESSFUL
;
1581 /* Get the import address list. */
1582 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1584 /* Get the list of functions to import. */
1585 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1587 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1591 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1594 /* Get the size of IAT. */
1596 while (FunctionNameList
[IATSize
] != 0L)
1601 /* Unprotect the region we are about to write into. */
1602 IATBase
= (PVOID
)ImportAddressList
;
1603 IATSize
*= sizeof(PVOID
*);
1604 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1609 if (!NT_SUCCESS(Status
))
1611 DPRINT1("Failed to unprotect IAT.\n");
1615 /* Walk through function list and fixup addresses. */
1616 while (*FunctionNameList
!= 0L)
1618 if ((*FunctionNameList
) & 0x80000000)
1620 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1621 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1622 if ((*ImportAddressList
) == NULL
)
1624 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1625 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1626 return STATUS_ENTRYPOINT_NOT_FOUND
;
1631 IMAGE_IMPORT_BY_NAME
*pe_name
;
1632 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1633 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1634 if ((*ImportAddressList
) == NULL
)
1636 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1637 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1638 return STATUS_ENTRYPOINT_NOT_FOUND
;
1641 ImportAddressList
++;
1645 /* Protect the region we are about to write into. */
1646 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1651 if (!NT_SUCCESS(Status
))
1653 DPRINT1("Failed to protect IAT.\n");
1657 return STATUS_SUCCESS
;
1661 LdrpProcessImportDirectory(
1662 PLDR_DATA_TABLE_ENTRY Module
,
1663 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1667 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1671 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1672 Module
, &Module
->BaseDllName
, ImportedName
);
1675 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1676 RtlImageDirectoryEntryToData(Module
->DllBase
,
1678 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1680 if (ImportModuleDirectory
== NULL
)
1682 return STATUS_UNSUCCESSFUL
;
1685 while (ImportModuleDirectory
->Name
)
1687 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1688 if (0 == _stricmp(Name
, ImportedName
))
1690 Status
= LdrpProcessImportDirectoryEntry(Module
,
1692 ImportModuleDirectory
);
1693 if (!NT_SUCCESS(Status
))
1698 ImportModuleDirectory
++;
1702 return STATUS_SUCCESS
;
1707 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1708 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1711 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1713 PVOID
* ImportAddressList
;
1716 PULONG FunctionNameList
;
1721 PIMAGE_NT_HEADERS NTHeaders
;
1725 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1726 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1728 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1729 RtlImageDirectoryEntryToData(Module
->DllBase
,
1731 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1733 if (ImportModuleDirectory
== NULL
)
1735 return STATUS_UNSUCCESSFUL
;
1738 while (ImportModuleDirectory
->Name
)
1740 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1741 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1744 /* Get the import address list. */
1745 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1747 /* Get the list of functions to import. */
1748 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1750 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1754 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1757 /* Get the size of IAT. */
1759 while (FunctionNameList
[IATSize
] != 0L)
1764 /* Unprotect the region we are about to write into. */
1765 IATBase
= (PVOID
)ImportAddressList
;
1766 IATSize
*= sizeof(PVOID
*);
1767 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1772 if (!NT_SUCCESS(Status
))
1774 DPRINT1("Failed to unprotect IAT.\n");
1778 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1779 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1780 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1781 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1783 /* Walk through function list and fixup addresses. */
1784 while (*FunctionNameList
!= 0L)
1786 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1788 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1790 ImportAddressList
++;
1794 /* Protect the region we are about to write into. */
1795 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1800 if (!NT_SUCCESS(Status
))
1802 DPRINT1("Failed to protect IAT.\n");
1806 ImportModuleDirectory
++;
1808 return STATUS_SUCCESS
;
1812 /**********************************************************************
1817 * Compute the entry point for every symbol the DLL imports
1818 * from other modules.
1830 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1831 IN PLDR_DATA_TABLE_ENTRY Module
)
1833 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1834 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1835 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1836 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1837 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1840 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1846 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1848 /* Check for tls data */
1849 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1850 RtlImageDirectoryEntryToData(Module
->DllBase
,
1852 IMAGE_DIRECTORY_ENTRY_TLS
,
1856 TlsSize
= TlsDirectory
->EndAddressOfRawData
1857 - TlsDirectory
->StartAddressOfRawData
1858 + TlsDirectory
->SizeOfZeroFill
;
1860 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1862 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1863 &Module
->BaseDllName
);
1864 TlsDirectory
= NULL
;
1868 if (!create_module_activation_context( Module
))
1870 if (Module
->EntryPointActivationContext
== NULL
)
1872 DPRINT("EntryPointActivationContext has not be allocated\n");
1873 DPRINT("Module->DllBaseName %wZ\n", Module
->BaseDllName
);
1875 RtlActivateActivationContext( 0, Module
->EntryPointActivationContext
, &cookie
);
1879 * Process each import module.
1881 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1882 RtlImageDirectoryEntryToData(Module
->DllBase
,
1884 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1887 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1888 RtlImageDirectoryEntryToData(Module
->DllBase
,
1890 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1893 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1895 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1896 return STATUS_UNSUCCESSFUL
;
1898 if (BoundImportDescriptor
)
1900 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1902 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1903 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1905 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1906 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1907 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT1("failed to load %s\n", ImportedName
);
1913 if (Module
== ImportedModule
)
1915 LdrpDecrementLoadCount(Module
, FALSE
);
1917 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1919 TRACE_LDR("%wZ has stale binding to %wZ\n",
1920 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1921 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1922 if (!NT_SUCCESS(Status
))
1924 DPRINT1("failed to import %s\n", ImportedName
);
1930 BOOLEAN WrongForwarder
;
1931 WrongForwarder
= FALSE
;
1932 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1934 TRACE_LDR("%wZ has stale binding to %s\n",
1935 &Module
->BaseDllName
, ImportedName
);
1939 TRACE_LDR("%wZ has correct binding to %wZ\n",
1940 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1942 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1944 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1946 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1947 PCHAR ForwarderName
;
1949 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1950 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1952 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1953 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1954 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1955 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1956 if (!NT_SUCCESS(Status
))
1958 DPRINT1("failed to load %s\n", ForwarderName
);
1961 if (Module
== ImportedModule
)
1963 LdrpDecrementLoadCount(Module
, FALSE
);
1965 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1966 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1968 TRACE_LDR("%wZ has stale binding to %s\n",
1969 &Module
->BaseDllName
, ForwarderName
);
1970 WrongForwarder
= TRUE
;
1974 TRACE_LDR("%wZ has correct binding to %s\n",
1975 &Module
->BaseDllName
, ForwarderName
);
1979 if (WrongForwarder
||
1980 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1982 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1983 if (!NT_SUCCESS(Status
))
1985 DPRINT1("failed to import %s\n", ImportedName
);
1989 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1991 TRACE_LDR("Adjust imports for %s from %wZ\n",
1992 ImportedName
, &Module
->BaseDllName
);
1993 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
1994 if (!NT_SUCCESS(Status
))
1996 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
2000 else if (WrongForwarder
)
2004 * Update only forwarders
2006 TRACE_LDR("Stale BIND %s from %wZ\n",
2007 ImportedName
, &Module
->BaseDllName
);
2008 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
2009 if (!NT_SUCCESS(Status
))
2011 DPRINT1("faild to import %s\n", ImportedName
);
2020 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
2023 else if (ImportModuleDirectory
)
2025 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
2027 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
2028 while (ImportModuleDirectoryCurrent
->Name
)
2030 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
2031 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
2033 if (SearchPath
== NULL
)
2035 ModulePath
= LdrpQueryAppPaths(Module
->BaseDllName
.Buffer
);
2037 Status
= LdrpGetOrLoadModule(ModulePath
, ImportedName
, &ImportedModule
, TRUE
);
2038 if (ModulePath
!= NULL
) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath
);
2039 if (NT_SUCCESS(Status
)) goto Success
;
2042 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
2043 if (!NT_SUCCESS(Status
))
2045 DPRINT1("failed to load %s\n", ImportedName
);
2049 if (Module
== ImportedModule
)
2051 LdrpDecrementLoadCount(Module
, FALSE
);
2054 TRACE_LDR("Initializing imports for %wZ from %s\n",
2055 &Module
->BaseDllName
, ImportedName
);
2056 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
2057 if (!NT_SUCCESS(Status
))
2059 DPRINT1("failed to import %s\n", ImportedName
);
2062 ImportModuleDirectoryCurrent
++;
2066 if (TlsDirectory
&& TlsSize
> 0)
2068 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
2071 if (Module
->EntryPointActivationContext
) RtlDeactivateActivationContext( 0, cookie
);
2073 return STATUS_SUCCESS
;
2077 /**********************************************************************
2082 * 1. Relocate, if needed the EXE.
2083 * 2. Fixup any imported symbol.
2084 * 3. Compute the EXE's entry point.
2088 * Address at which the EXE's image
2092 * Handle of the section that contains
2096 * NULL on error; otherwise the entry point
2097 * to call for initializing the DLL.
2102 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
2103 * Currently the function is only used for the exe.
2105 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
2106 HANDLE SectionHandle
,
2107 PLDR_DATA_TABLE_ENTRY
* Module
,
2111 PEPFUNC EntryPoint
= NULL
;
2112 PIMAGE_DOS_HEADER DosHeader
;
2113 PIMAGE_NT_HEADERS NTHeaders
;
2114 PLDR_DATA_TABLE_ENTRY tmpModule
;
2115 PVOID ActivationContextStack
;
2117 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
2118 ImageBase
, SectionHandle
);
2121 * Overlay DOS and WNT headers structures
2122 * to the DLL's image.
2124 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
2125 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
2128 * If the base address is different from the
2129 * one the DLL is actually loaded, perform any
2132 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2134 DPRINT("LDR: Performing relocations\n");
2135 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
2136 if (!NT_SUCCESS(Status
))
2138 DPRINT1("LdrPerformRelocations() failed\n");
2145 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
2146 (*Module
)->SectionPointer
= SectionHandle
;
2150 Module
= &tmpModule
;
2151 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
2152 if (!NT_SUCCESS(Status
))
2158 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2160 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2163 /* Allocate memory for the ActivationContextStack */
2164 /* FIXME: Verify RtlAllocateActivationContextStack behavior */
2165 Status
= RtlAllocateActivationContextStack(&ActivationContextStack
);
2166 if (NT_SUCCESS(Status
))
2168 DPRINT("ActivationContextStack %x\n",ActivationContextStack
);
2169 DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK
)ActivationContextStack
)->ActiveFrame
);
2170 NtCurrentTeb()->ActivationContextStackPointer
= ActivationContextStack
;
2171 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NULL
;
2174 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
2177 * If the DLL's imports symbols from other
2178 * modules, fixup the imported calls entry points.
2180 DPRINT("About to fixup imports\n");
2181 Status
= LdrFixupImports(NULL
, *Module
);
2182 if (!NT_SUCCESS(Status
))
2184 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
2187 DPRINT("Fixup done\n");
2188 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2189 Status
= LdrpInitializeTlsForProccess();
2190 if (NT_SUCCESS(Status
))
2192 Status
= LdrpAttachProcess();
2194 if (NT_SUCCESS(Status
))
2196 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2200 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2201 if (!NT_SUCCESS(Status
))
2207 * Compute the DLL's entry point's address.
2209 DPRINT("ImageBase = %p\n", ImageBase
);
2210 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2211 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2213 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2214 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2216 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2221 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2223 IN PUNICODE_STRING Name
,
2224 PLDR_DATA_TABLE_ENTRY
*Module
,
2225 PVOID
*BaseAddress OPTIONAL
)
2227 UNICODE_STRING AdjustedName
;
2228 UNICODE_STRING FullDosName
;
2230 PLDR_DATA_TABLE_ENTRY tmpModule
;
2231 HANDLE SectionHandle
;
2234 PIMAGE_NT_HEADERS NtHeaders
;
2235 BOOLEAN MappedAsDataFile
;
2236 PVOID ArbitraryUserPointer
;
2240 Module
= &tmpModule
;
2242 /* adjust the full dll name */
2243 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2245 DPRINT("%wZ\n", &AdjustedName
);
2247 MappedAsDataFile
= FALSE
;
2248 /* Test if dll is already loaded */
2249 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2250 if (NT_SUCCESS(Status
))
2252 RtlFreeUnicodeString(&AdjustedName
);
2253 if (NULL
!= BaseAddress
)
2255 *BaseAddress
= (*Module
)->DllBase
;
2260 /* Open or create dll image section */
2261 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2262 if (!NT_SUCCESS(Status
))
2264 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2265 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2266 MappedAsDataFile
, &SectionHandle
);
2268 if (!NT_SUCCESS(Status
))
2270 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2271 RtlFreeUnicodeString(&AdjustedName
);
2274 RtlFreeUnicodeString(&AdjustedName
);
2275 /* Map the dll into the process */
2278 ArbitraryUserPointer
= NtCurrentTeb()->Tib
.ArbitraryUserPointer
;
2279 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2280 Status
= NtMapViewOfSection(SectionHandle
,
2290 NtCurrentTeb()->Tib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2291 if (!NT_SUCCESS(Status
))
2293 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2294 RtlFreeUnicodeString(&FullDosName
);
2295 NtClose(SectionHandle
);
2298 if (NULL
!= BaseAddress
)
2300 *BaseAddress
= ImageBase
;
2302 if (!MappedAsDataFile
)
2304 /* Get and check the NT headers */
2305 NtHeaders
= RtlImageNtHeader(ImageBase
);
2306 if (NtHeaders
== NULL
)
2308 DPRINT1("RtlImageNtHeaders() failed\n");
2309 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2310 NtClose (SectionHandle
);
2311 RtlFreeUnicodeString(&FullDosName
);
2312 return STATUS_UNSUCCESSFUL
;
2315 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2316 if (MappedAsDataFile
)
2318 ASSERT(NULL
!= BaseAddress
);
2319 if (NULL
!= BaseAddress
)
2321 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2324 RtlFreeUnicodeString(&FullDosName
);
2325 NtClose(SectionHandle
);
2326 return STATUS_SUCCESS
;
2328 /* If the base address is different from the
2329 * one the DLL is actually loaded, perform any
2331 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2333 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2334 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2335 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2336 if (!NT_SUCCESS(Status
))
2338 DPRINT1("LdrPerformRelocations() failed\n");
2339 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2340 NtClose (SectionHandle
);
2341 RtlFreeUnicodeString(&FullDosName
);
2342 return STATUS_UNSUCCESSFUL
;
2345 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2346 (*Module
)->SectionPointer
= SectionHandle
;
2347 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2349 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2351 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2353 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2355 /* fixup the imported calls entry points */
2356 Status
= LdrFixupImports(SearchPath
, *Module
);
2357 if (!NT_SUCCESS(Status
))
2359 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2363 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2364 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2365 &(*Module
)->InInitializationOrderModuleList
);
2366 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2368 return STATUS_SUCCESS
;
2372 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2375 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2376 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2377 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2379 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2386 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2389 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2391 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2395 /* ?????????????????? */
2397 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2399 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2400 RtlImageDirectoryEntryToData(Module
->DllBase
,
2402 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2404 if (BoundImportDescriptor
)
2406 /* dereferencing all imported modules, use the bound import descriptor */
2407 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2408 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2410 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2411 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2412 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2413 if (!NT_SUCCESS(Status
))
2415 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2419 if (Module
!= ImportedModule
)
2421 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2422 if (!NT_SUCCESS(Status
))
2424 DPRINT1("unable to unload %s\n", ImportedName
);
2428 BoundImportDescriptorCurrent
++;
2433 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2434 RtlImageDirectoryEntryToData(Module
->DllBase
,
2436 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2438 if (ImportModuleDirectory
)
2440 /* dereferencing all imported modules, use the import descriptor */
2441 while (ImportModuleDirectory
->Name
)
2443 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2444 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2445 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2446 if (!NT_SUCCESS(Status
))
2448 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2452 if (Module
!= ImportedModule
)
2454 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2455 if (!NT_SUCCESS(Status
))
2457 DPRINT1("unable to unload %s\n", ImportedName
);
2461 ImportModuleDirectory
++;
2469 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2471 LdrpDetachProcess(FALSE
);
2474 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2476 return STATUS_SUCCESS
;
2484 LdrUnloadDll (IN PVOID BaseAddress
)
2486 PLDR_DATA_TABLE_ENTRY Module
;
2489 if (BaseAddress
== NULL
)
2490 return STATUS_SUCCESS
;
2492 if (LdrMappedAsDataFile(&BaseAddress
))
2494 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2498 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2499 if (NT_SUCCESS(Status
))
2501 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2502 Status
= LdrpUnloadModule(Module
, TRUE
);
2513 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2515 PLIST_ENTRY ModuleListHead
;
2517 PLDR_DATA_TABLE_ENTRY Module
;
2520 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2522 Status
= STATUS_DLL_NOT_FOUND
;
2523 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2524 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2525 Entry
= ModuleListHead
->Flink
;
2526 while (Entry
!= ModuleListHead
)
2528 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2530 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2532 if (Module
->DllBase
== BaseAddress
)
2534 if (Module
->TlsIndex
== 0xFFFF)
2536 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2537 Status
= STATUS_SUCCESS
;
2541 Entry
= Entry
->Flink
;
2543 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2551 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2552 IN PULONG DllCharacteristics
,
2553 IN PUNICODE_STRING DllName
,
2554 OUT PVOID
*DllHandle
)
2556 PLDR_DATA_TABLE_ENTRY Module
;
2559 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2560 DllName
, DllPath
? DllPath
: L
"");
2562 /* NULL is the current executable */
2563 if (DllName
== NULL
)
2565 *DllHandle
= ExeModule
->DllBase
;
2566 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2567 return STATUS_SUCCESS
;
2570 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2571 if (NT_SUCCESS(Status
))
2573 *DllHandle
= Module
->DllBase
;
2574 return STATUS_SUCCESS
;
2577 DPRINT("Failed to find dll %wZ\n", DllName
);
2579 return STATUS_DLL_NOT_FOUND
;
2586 LdrAddRefDll(IN ULONG Flags
,
2587 IN PVOID BaseAddress
)
2589 PLIST_ENTRY ModuleListHead
;
2591 PLDR_DATA_TABLE_ENTRY Module
;
2594 if (Flags
& ~(LDR_PIN_MODULE
))
2596 return STATUS_INVALID_PARAMETER
;
2599 Status
= STATUS_DLL_NOT_FOUND
;
2600 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2601 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2602 Entry
= ModuleListHead
->Flink
;
2603 while (Entry
!= ModuleListHead
)
2605 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2607 if (Module
->DllBase
== BaseAddress
)
2609 if (Flags
& LDR_PIN_MODULE
)
2611 Module
->Flags
|= LDRP_STATIC_LINK
;
2615 LdrpIncrementLoadCount(Module
,
2618 Status
= STATUS_SUCCESS
;
2621 Entry
= Entry
->Flink
;
2623 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2631 RtlPcToFileHeader(IN PVOID PcValue
,
2634 PLIST_ENTRY ModuleListHead
;
2636 PLDR_DATA_TABLE_ENTRY Module
;
2637 PVOID ImageBase
= NULL
;
2639 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2640 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2641 Entry
= ModuleListHead
->Flink
;
2642 while (Entry
!= ModuleListHead
)
2644 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2646 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2647 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2649 ImageBase
= Module
->DllBase
;
2652 Entry
= Entry
->Flink
;
2654 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2656 *BaseOfImage
= ImageBase
;
2664 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2665 IN PANSI_STRING Name
,
2667 OUT PVOID
*ProcedureAddress
)
2669 NTSTATUS Status
= STATUS_PROCEDURE_NOT_FOUND
;
2670 if (Name
&& Name
->Length
)
2672 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2676 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2679 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2680 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2684 if (Name
&& Name
->Length
)
2687 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2688 if (*ProcedureAddress
!= NULL
)
2690 Status
= STATUS_SUCCESS
;
2692 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2697 Ordinal
&= 0x0000FFFF;
2698 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2699 if (*ProcedureAddress
)
2701 Status
= STATUS_SUCCESS
;
2703 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2706 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2708 Status
= STATUS_DLL_NOT_FOUND
;
2715 /**********************************************************************
2720 * Unload dll's which are no longer referenced from others dll's
2731 * The loader lock must be held on enty.
2734 LdrpDetachProcess(BOOLEAN UnloadAll
)
2736 PLIST_ENTRY ModuleListHead
;
2738 PLDR_DATA_TABLE_ENTRY Module
;
2739 static ULONG CallingCount
= 0;
2741 DPRINT("LdrpDetachProcess() called for %wZ\n",
2742 &ExeModule
->BaseDllName
);
2745 LdrpDllShutdownInProgress
= TRUE
;
2749 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2750 Entry
= ModuleListHead
->Blink
;
2751 while (Entry
!= ModuleListHead
)
2753 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2754 if (((UnloadAll
&& Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0) &&
2755 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2756 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2758 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2759 if (Module
== LdrpLastModule
)
2761 LdrpLastModule
= NULL
;
2763 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2765 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2766 &Module
->BaseDllName
, Module
->EntryPoint
);
2767 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2771 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2773 Entry
= ModuleListHead
->Blink
;
2777 Entry
= Entry
->Blink
;
2781 if (CallingCount
== 1)
2783 Entry
= ModuleListHead
->Blink
;
2784 while (Entry
!= ModuleListHead
)
2786 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2787 Entry
= Entry
->Blink
;
2788 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2789 ((UnloadAll
&& Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0))
2791 /* remove the module entry from the list */
2792 RemoveEntryList (&Module
->InLoadOrderLinks
);
2793 RemoveEntryList (&Module
->InInitializationOrderModuleList
);
2795 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2796 NtClose (Module
->SectionPointer
);
2798 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2800 RtlFreeUnicodeString (&Module
->FullDllName
);
2801 RtlFreeUnicodeString (&Module
->BaseDllName
);
2803 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2808 DPRINT("LdrpDetachProcess() done\n");
2811 /**********************************************************************
2816 * Initialize all dll's which are prepered for loading
2827 * The loader lock must be held on entry.
2831 LdrpAttachProcess(VOID
)
2833 PLIST_ENTRY ModuleListHead
;
2835 PLDR_DATA_TABLE_ENTRY Module
;
2837 NTSTATUS Status
= STATUS_SUCCESS
;
2839 DPRINT("LdrpAttachProcess() called for %wZ\n",
2840 &ExeModule
->BaseDllName
);
2842 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2843 Entry
= ModuleListHead
->Flink
;
2844 while (Entry
!= ModuleListHead
)
2846 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2847 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2849 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2850 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2851 &Module
->BaseDllName
, Module
->EntryPoint
);
2852 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2855 Status
= STATUS_DLL_INIT_FAILED
;
2858 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2860 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2864 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2866 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2868 Entry
= Entry
->Flink
;
2871 DPRINT("LdrpAttachProcess() done\n");
2880 RtlDllShutdownInProgress (VOID
)
2882 return LdrpDllShutdownInProgress
;
2889 LdrShutdownProcess (VOID
)
2891 LdrpDetachProcess(TRUE
);
2892 return STATUS_SUCCESS
;
2900 LdrpAttachThread (VOID
)
2902 PLIST_ENTRY ModuleListHead
;
2904 PLDR_DATA_TABLE_ENTRY Module
;
2907 DPRINT("LdrpAttachThread() called for %wZ\n",
2908 &ExeModule
->BaseDllName
);
2910 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2912 Status
= LdrpInitializeTlsForThread();
2914 if (NT_SUCCESS(Status
))
2916 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2917 Entry
= ModuleListHead
->Flink
;
2919 while (Entry
!= ModuleListHead
)
2921 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2922 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2923 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2924 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2926 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2927 &Module
->BaseDllName
, Module
->EntryPoint
);
2928 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2930 Entry
= Entry
->Flink
;
2933 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2934 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2935 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2938 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2940 DPRINT("LdrpAttachThread() done\n");
2950 LdrShutdownThread (VOID
)
2952 PLIST_ENTRY ModuleListHead
;
2954 PLDR_DATA_TABLE_ENTRY Module
;
2956 DPRINT("LdrShutdownThread() called for %wZ\n",
2957 &ExeModule
->BaseDllName
);
2959 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2961 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2962 Entry
= ModuleListHead
->Blink
;
2963 while (Entry
!= ModuleListHead
)
2965 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderModuleList
);
2967 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2968 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2969 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2971 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
2972 &Module
->BaseDllName
, Module
->EntryPoint
);
2973 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
2975 Entry
= Entry
->Blink
;
2978 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2982 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
2985 DPRINT("LdrShutdownThread() done\n");
2987 return STATUS_SUCCESS
;
2991 /***************************************************************************
2993 * LdrQueryProcessModuleInformation
3008 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
3009 IN ULONG Size OPTIONAL
,
3010 OUT PULONG ReturnedSize
)
3012 PLIST_ENTRY ModuleListHead
;
3014 PLDR_DATA_TABLE_ENTRY Module
;
3015 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
3016 NTSTATUS Status
= STATUS_SUCCESS
;
3017 ULONG UsedSize
= sizeof(ULONG
);
3018 ANSI_STRING AnsiString
;
3021 DPRINT("LdrQueryProcessModuleInformation() called\n");
3022 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
3023 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
3025 if (ModuleInformation
== NULL
|| Size
== 0)
3027 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3031 ModuleInformation
->NumberOfModules
= 0;
3032 ModulePtr
= &ModuleInformation
->Modules
[0];
3033 Status
= STATUS_SUCCESS
;
3036 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
3037 Entry
= ModuleListHead
->Flink
;
3039 while (Entry
!= ModuleListHead
)
3041 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
3043 DPRINT(" Module %wZ\n",
3044 &Module
->FullDllName
);
3046 if (UsedSize
> Size
)
3048 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3050 else if (ModuleInformation
!= NULL
)
3052 ModulePtr
->Section
= 0;
3053 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
3054 ModulePtr
->ImageBase
= Module
->DllBase
;
3055 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
3056 ModulePtr
->Flags
= Module
->Flags
;
3057 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
3058 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
3059 ModulePtr
->LoadCount
= Module
->LoadCount
;
3061 AnsiString
.Length
= 0;
3062 AnsiString
.MaximumLength
= 256;
3063 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
3064 RtlUnicodeStringToAnsiString(&AnsiString
,
3065 &Module
->FullDllName
,
3068 p
= strrchr(ModulePtr
->FullPathName
, '\\');
3070 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
3072 ModulePtr
->OffsetToFileName
= 0;
3075 ModuleInformation
->NumberOfModules
++;
3077 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
3079 Entry
= Entry
->Flink
;
3082 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
3084 if (ReturnedSize
!= 0)
3085 *ReturnedSize
= UsedSize
;
3087 DPRINT("LdrQueryProcessModuleInformation() done\n");
3094 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
3097 PIMAGE_NT_HEADERS Header
;
3104 Header
= RtlImageNtHeader (BaseAddress
);
3108 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
3113 Ptr
= (PUSHORT
) BaseAddress
;
3114 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
3117 if (HIWORD(Sum
) != 0)
3119 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3126 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
3127 if (HIWORD(Sum
) != 0)
3129 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3133 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
3135 /* Subtract image checksum from calculated checksum. */
3136 /* fix low word of checksum */
3137 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
3139 CalcSum
-= LOWORD(HeaderSum
);
3143 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
3146 /* fix high word of checksum */
3147 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
3149 CalcSum
-= HIWORD(HeaderSum
);
3153 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
3156 /* add file length */
3157 CalcSum
+= ImageSize
;
3159 return (BOOLEAN
)(CalcSum
== HeaderSum
);
3163 * Compute size of an image as it is actually present in virt memory
3164 * (i.e. excluding NEVER_LOAD sections)
3167 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
3169 PIMAGE_SECTION_HEADER SectionHeader
;
3170 unsigned SectionIndex
;
3173 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
3174 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
3176 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
3178 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
3179 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
3181 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
3186 return ResidentSize
;
3190 /***************************************************************************
3192 * LdrVerifyImageMatchesChecksum
3207 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3212 FILE_STANDARD_INFORMATION FileInfo
;
3213 IO_STATUS_BLOCK IoStatusBlock
;
3214 HANDLE SectionHandle
;
3220 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3222 Status
= NtCreateSection (&SectionHandle
,
3229 if (!NT_SUCCESS(Status
))
3231 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3237 Status
= NtMapViewOfSection (SectionHandle
,
3238 NtCurrentProcess (),
3247 if (!NT_SUCCESS(Status
))
3249 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3250 NtClose (SectionHandle
);
3254 Status
= NtQueryInformationFile (FileHandle
,
3257 sizeof (FILE_STANDARD_INFORMATION
),
3258 FileStandardInformation
);
3259 if (!NT_SUCCESS(Status
))
3261 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3262 NtUnmapViewOfSection (NtCurrentProcess (),
3264 NtClose (SectionHandle
);
3268 Result
= LdrpCheckImageChecksum (BaseAddress
,
3269 FileInfo
.EndOfFile
.u
.LowPart
);
3270 if (Result
== FALSE
)
3272 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3275 NtUnmapViewOfSection (NtCurrentProcess (),
3278 NtClose (SectionHandle
);
3284 /***************************************************************************
3286 * LdrQueryImageFileExecutionOptions
3301 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3302 IN PCWSTR ValueName
,
3305 IN ULONG BufferSize
,
3306 OUT PULONG ReturnedLength OPTIONAL
)
3308 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3309 OBJECT_ATTRIBUTES ObjectAttributes
;
3310 UNICODE_STRING ValueNameString
;
3311 UNICODE_STRING KeyName
;
3312 WCHAR NameBuffer
[256];
3320 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3321 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3324 Ptr
= SubKey
->Buffer
;
3330 wcscat (NameBuffer
, Ptr
);
3331 RtlInitUnicodeString (&KeyName
,
3334 InitializeObjectAttributes (&ObjectAttributes
,
3336 OBJ_CASE_INSENSITIVE
,
3340 Status
= NtOpenKey (&KeyHandle
,
3343 if (!NT_SUCCESS(Status
))
3345 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3349 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3350 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3353 if (KeyInfo
== NULL
)
3355 NtClose (KeyHandle
);
3356 return STATUS_INSUFFICIENT_RESOURCES
;
3359 RtlInitUnicodeString (&ValueNameString
,
3361 Status
= NtQueryValueKey (KeyHandle
,
3363 KeyValuePartialInformation
,
3367 if (Status
== STATUS_BUFFER_OVERFLOW
)
3369 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3370 RtlFreeHeap (RtlGetProcessHeap(),
3373 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3376 if (KeyInfo
== NULL
)
3378 NtClose (KeyHandle
);
3379 return STATUS_INSUFFICIENT_RESOURCES
;
3382 Status
= NtQueryValueKey (KeyHandle
,
3384 KeyValuePartialInformation
,
3389 NtClose (KeyHandle
);
3391 if (!NT_SUCCESS(Status
))
3393 if (KeyInfo
!= NULL
)
3395 RtlFreeHeap (RtlGetProcessHeap(),
3402 if (KeyInfo
->Type
!= Type
)
3404 RtlFreeHeap (RtlGetProcessHeap(),
3407 return STATUS_OBJECT_TYPE_MISMATCH
;
3410 ResultSize
= BufferSize
;
3411 if (ResultSize
< KeyInfo
->DataLength
)
3413 Status
= STATUS_BUFFER_OVERFLOW
;
3417 ResultSize
= KeyInfo
->DataLength
;
3419 RtlCopyMemory (Buffer
,
3423 RtlFreeHeap (RtlGetProcessHeap(),
3427 if (ReturnedLength
!= NULL
)
3429 *ReturnedLength
= ResultSize
;
3436 PIMAGE_BASE_RELOCATION NTAPI
3437 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3439 IN PUSHORT TypeOffset
,
3448 for (i
= 0; i
< Count
; i
++)
3450 Offset
= *TypeOffset
& 0xFFF;
3451 Type
= *TypeOffset
>> 12;
3455 case IMAGE_REL_BASED_ABSOLUTE
:
3458 case IMAGE_REL_BASED_HIGH
:
3459 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3460 *ShortPtr
+= HIWORD(Delta
);
3463 case IMAGE_REL_BASED_LOW
:
3464 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3465 *ShortPtr
+= LOWORD(Delta
);
3468 case IMAGE_REL_BASED_HIGHLOW
:
3469 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3473 case IMAGE_REL_BASED_HIGHADJ
:
3474 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3476 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3483 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3488 LdrLockLoaderLock(IN ULONG Flags
,
3489 OUT PULONG Disposition OPTIONAL
,
3490 OUT PULONG Cookie OPTIONAL
)
3494 BOOLEAN CookieSet
= FALSE
;
3496 if ((Flags
!= 0x01) && (Flags
!= 0x02))
3497 return STATUS_INVALID_PARAMETER_1
;
3499 if (!Cookie
) return STATUS_INVALID_PARAMETER_3
;
3501 /* Set some defaults for failure while verifying params */
3506 if (Disposition
) *Disposition
= 0;
3508 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3511 Status
= STATUS_INVALID_PARAMETER_3
;
3513 Status
= STATUS_INVALID_PARAMETER_2
;
3519 DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
3520 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
3521 Status
= STATUS_SUCCESS
;
3526 if (!Disposition
) return STATUS_INVALID_PARAMETER_2
;
3528 Ret
= RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
3531 *Disposition
= 0x01;
3533 *Disposition
= 0x02;
3535 Status
= STATUS_SUCCESS
;
3538 /* FIXME: Cookie is based on part of the thread id */
3539 *Cookie
= (ULONG
)NtCurrentTeb()->RealClientId
.UniqueThread
;
3545 LdrUnlockLoaderLock(IN ULONG Flags
,
3546 IN ULONG Cookie OPTIONAL
)
3549 return STATUS_INVALID_PARAMETER_1
;
3551 if (Cookie
!= (ULONG
)NtCurrentTeb()->RealClientId
.UniqueThread
)
3552 return STATUS_INVALID_PARAMETER_2
;
3554 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
3556 return STATUS_SUCCESS
;
3561 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)