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
);
64 static NTSTATUS
LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Unload
);
66 NTSTATUS
find_actctx_dll( LPCWSTR libname
, WCHAR
*fulldosname
);
67 NTSTATUS
create_module_activation_context( LDR_DATA_TABLE_ENTRY
*module
);
69 /* FUNCTIONS *****************************************************************/
72 LdrMappedAsDataFile(PVOID
*BaseAddress
)
74 if (0 != ((DWORD_PTR
) *BaseAddress
& (PAGE_SIZE
- 1)))
76 *BaseAddress
= (PVOID
) ((DWORD_PTR
) *BaseAddress
& ~ ((DWORD_PTR
) PAGE_SIZE
- 1));
83 static __inline LONG
LdrpDecrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
88 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
90 LoadCount
= Module
->LoadCount
;
91 if (Module
->LoadCount
> 0 && Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
97 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
102 static __inline LONG
LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module
, BOOLEAN Locked
)
107 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
109 LoadCount
= Module
->LoadCount
;
110 if (Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
116 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
121 static __inline VOID
LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module
, ULONG Size
, BOOLEAN Locked
)
125 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
127 Module
->TlsIndex
= (SHORT
)LdrpTlsCount
;
132 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
136 static __inline VOID
LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module
, ULONG dwReason
)
138 PIMAGE_TLS_CALLBACK
*TlsCallback
;
139 if (Module
->TlsIndex
!= 0xFFFF && Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
)
141 TlsCallback
= LdrpTlsArray
[Module
->TlsIndex
].TlsAddressOfCallBacks
;
146 TRACE_LDR("%wZ - Calling tls callback at %x\n",
147 &Module
->BaseDllName
, *TlsCallback
);
148 (*TlsCallback
)(Module
->DllBase
, dwReason
, NULL
);
155 static BOOLEAN
LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module
, DWORD dwReason
, PVOID lpReserved
)
157 if (!(Module
->Flags
& LDRP_IMAGE_DLL
) ||
158 Module
->EntryPoint
== 0)
162 LdrpTlsCallback(Module
, dwReason
);
163 return ((PDLLMAIN_FUNC
)Module
->EntryPoint
)(Module
->DllBase
, dwReason
, lpReserved
);
167 LdrpQueryAppPaths(IN PCWSTR ImageName
)
169 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
170 OBJECT_ATTRIBUTES ObjectAttributes
;
171 WCHAR SearchPathBuffer
[5*MAX_PATH
];
172 UNICODE_STRING ValueNameString
;
173 UNICODE_STRING KeyName
;
174 WCHAR NameBuffer
[MAX_PATH
];
182 _snwprintf(NameBuffer
,
183 sizeof(NameBuffer
) / sizeof(WCHAR
),
184 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s",
187 RtlInitUnicodeString(&KeyName
, NameBuffer
);
189 InitializeObjectAttributes(&ObjectAttributes
,
191 OBJ_CASE_INSENSITIVE
,
195 Status
= NtOpenKey(&KeyHandle
,
198 if (!NT_SUCCESS(Status
))
200 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
204 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 256 * sizeof(WCHAR
);
206 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize
);
209 DPRINT("RtlAllocateHeap() failed\n");
214 RtlInitUnicodeString(&ValueNameString
,
217 Status
= NtQueryValueKey(KeyHandle
,
219 KeyValuePartialInformation
,
224 if (!NT_SUCCESS(Status
))
227 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
231 RtlCopyMemory(SearchPathBuffer
,
233 KeyInfo
->DataLength
);
235 /* Free KeyInfo memory, we won't need it anymore */
236 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
238 /* Close the key handle */
241 /* get application running path */
242 wcscat(SearchPathBuffer
, L
";");
243 wcscat(SearchPathBuffer
, NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
); // FIXME: Don't rely on it being NULL-terminated!!!
245 /* Remove trailing backslash */
246 Backslash
= wcsrchr(SearchPathBuffer
, L
'\\');
247 if (Backslash
) Backslash
= L
'\0';
249 wcscat(SearchPathBuffer
, L
";");
251 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
252 wcscat(SearchPathBuffer
, L
"\\system32;");
253 wcscat(SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
254 wcscat(SearchPathBuffer
, L
";.");
256 /* Copy it to the heap allocd memory */
257 Path
= RtlAllocateHeap(RtlGetProcessHeap(),
259 wcslen(SearchPathBuffer
) * sizeof(WCHAR
));
263 DPRINT1("RtlAllocateHeap() failed\n");
267 wcscpy(Path
, SearchPathBuffer
);
273 LdrpInitializeTlsForThread(VOID
)
279 PTEB Teb
= NtCurrentTeb();
281 DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule
->BaseDllName
);
283 Teb
->StaticUnicodeString
.Length
= 0;
284 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
285 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
287 if (LdrpTlsCount
> 0)
289 TlsPointers
= RtlAllocateHeap(RtlGetProcessHeap(),
291 LdrpTlsCount
* sizeof(PVOID
) + LdrpTlsSize
);
292 if (TlsPointers
== NULL
)
294 DPRINT1("failed to allocate thread tls data\n");
295 return STATUS_NO_MEMORY
;
298 TlsData
= (PVOID
)((ULONG_PTR
)TlsPointers
+ LdrpTlsCount
* sizeof(PVOID
));
299 Teb
->ThreadLocalStoragePointer
= TlsPointers
;
301 TlsInfo
= LdrpTlsArray
;
302 for (i
= 0; i
< LdrpTlsCount
; i
++, TlsInfo
++)
304 TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo
->Module
->BaseDllName
);
305 TlsPointers
[i
] = TlsData
;
306 if (TlsInfo
->TlsDataSize
)
308 memcpy(TlsData
, TlsInfo
->StartAddressOfRawData
, TlsInfo
->TlsDataSize
);
309 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsDataSize
);
311 if (TlsInfo
->TlsZeroSize
)
313 memset(TlsData
, 0, TlsInfo
->TlsZeroSize
);
314 TlsData
= (PVOID
)((ULONG_PTR
)TlsData
+ TlsInfo
->TlsZeroSize
);
319 DPRINT("LdrpInitializeTlsForThread() done\n");
320 return STATUS_SUCCESS
;
324 LdrpInitializeTlsForProccess(VOID
)
326 PLIST_ENTRY ModuleListHead
;
328 PLDR_DATA_TABLE_ENTRY Module
;
329 PIMAGE_TLS_DIRECTORY TlsDirectory
;
333 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule
->BaseDllName
);
335 if (LdrpTlsCount
> 0)
337 LdrpTlsArray
= RtlAllocateHeap(RtlGetProcessHeap(),
339 LdrpTlsCount
* sizeof(TLS_DATA
));
340 if (LdrpTlsArray
== NULL
)
342 DPRINT1("Failed to allocate global tls data\n");
343 return STATUS_NO_MEMORY
;
346 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
347 Entry
= ModuleListHead
->Flink
;
348 while (Entry
!= ModuleListHead
)
350 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
351 if (Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
&&
352 Module
->TlsIndex
!= 0xFFFF)
354 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
355 RtlImageDirectoryEntryToData(Module
->DllBase
,
357 IMAGE_DIRECTORY_ENTRY_TLS
,
359 ASSERT(Module
->TlsIndex
< LdrpTlsCount
);
360 TlsData
= &LdrpTlsArray
[Module
->TlsIndex
];
361 TlsData
->StartAddressOfRawData
= (PVOID
)TlsDirectory
->StartAddressOfRawData
;
362 TlsData
->TlsDataSize
= TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
;
363 TlsData
->TlsZeroSize
= TlsDirectory
->SizeOfZeroFill
;
364 if (TlsDirectory
->AddressOfCallBacks
)
365 TlsData
->TlsAddressOfCallBacks
= (PIMAGE_TLS_CALLBACK
*)TlsDirectory
->AddressOfCallBacks
;
367 TlsData
->TlsAddressOfCallBacks
= NULL
;
368 TlsData
->Module
= Module
;
370 DbgPrint("TLS directory for %wZ\n", &Module
->BaseDllName
);
371 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory
->StartAddressOfRawData
);
372 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory
->EndAddressOfRawData
);
373 DbgPrint("SizeOfRawData: %d\n", TlsDirectory
->EndAddressOfRawData
- TlsDirectory
->StartAddressOfRawData
);
374 DbgPrint("AddressOfIndex: %x\n", TlsDirectory
->AddressOfIndex
);
375 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory
->AddressOfCallBacks
);
376 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory
->SizeOfZeroFill
);
377 DbgPrint("Characteristics: %x\n", TlsDirectory
->Characteristics
);
381 * Is this region allways writable ?
383 *(PULONG
)TlsDirectory
->AddressOfIndex
= Module
->TlsIndex
;
385 Entry
= Entry
->Flink
;
389 DPRINT("LdrpInitializeTlsForProccess() done\n");
390 return STATUS_SUCCESS
;
396 OBJECT_ATTRIBUTES ObjectAttributes
;
397 UNICODE_STRING LinkTarget
;
403 DPRINT("LdrpInitLoader() called for %wZ\n", &ExeModule
->BaseDllName
);
405 /* Get handle to the 'KnownDlls' directory */
406 RtlInitUnicodeString(&Name
,
408 InitializeObjectAttributes(&ObjectAttributes
,
410 OBJ_CASE_INSENSITIVE
,
413 Status
= NtOpenDirectoryObject(&LdrpKnownDllsDirHandle
,
414 DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
,
416 if (!NT_SUCCESS(Status
))
418 DPRINT("NtOpenDirectoryObject() failed (Status %lx)\n", Status
);
419 LdrpKnownDllsDirHandle
= NULL
;
423 /* Allocate target name string */
424 LinkTarget
.Length
= 0;
425 LinkTarget
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
426 LinkTarget
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
428 MAX_PATH
* sizeof(WCHAR
));
429 if (LinkTarget
.Buffer
== NULL
)
431 NtClose(LdrpKnownDllsDirHandle
);
432 LdrpKnownDllsDirHandle
= NULL
;
436 RtlInitUnicodeString(&Name
,
438 InitializeObjectAttributes(&ObjectAttributes
,
440 OBJ_CASE_INSENSITIVE
,
441 LdrpKnownDllsDirHandle
,
443 Status
= NtOpenSymbolicLinkObject(&LinkHandle
,
444 SYMBOLIC_LINK_ALL_ACCESS
,
446 if (!NT_SUCCESS(Status
))
448 RtlFreeUnicodeString(&LinkTarget
);
449 NtClose(LdrpKnownDllsDirHandle
);
450 LdrpKnownDllsDirHandle
= NULL
;
454 Status
= NtQuerySymbolicLinkObject(LinkHandle
,
458 if (!NT_SUCCESS(Status
))
460 RtlFreeUnicodeString(&LinkTarget
);
461 NtClose(LdrpKnownDllsDirHandle
);
462 LdrpKnownDllsDirHandle
= NULL
;
465 RtlCreateUnicodeString(&LdrpKnownDllPath
,
468 RtlFreeUnicodeString(&LinkTarget
);
470 DPRINT("LdrpInitLoader() done\n");
474 /***************************************************************************
479 * Adjusts the name of a dll to a fully qualified name.
482 * FullDllName: Pointer to caller supplied storage for the fully
483 * qualified dll name.
484 * DllName: Pointer to the dll name.
485 * BaseName: TRUE: Only the file name is passed to FullDllName
486 * FALSE: The full path is preserved in FullDllName
494 * A given path is not affected by the adjustment, but the file
496 * ntdll --> ntdll.dll
498 * ntdll.xyz --> ntdll.xyz
501 LdrAdjustDllName (PUNICODE_STRING FullDllName
,
502 PUNICODE_STRING DllName
,
505 WCHAR Buffer
[MAX_PATH
];
510 Length
= DllName
->Length
/ sizeof(WCHAR
);
514 /* get the base dll name */
515 Pointer
= DllName
->Buffer
+ Length
;
522 while (Pointer
>= DllName
->Buffer
&& *Pointer
!= L
'\\' && *Pointer
!= L
'/');
525 Length
= Extension
- Pointer
;
526 memmove (Buffer
, Pointer
, Length
* sizeof(WCHAR
));
527 Buffer
[Length
] = L
'\0';
531 /* get the full dll name */
532 memmove (Buffer
, DllName
->Buffer
, DllName
->Length
);
533 Buffer
[DllName
->Length
/ sizeof(WCHAR
)] = L
'\0';
536 /* Build the DLL's absolute name */
537 Extension
= wcsrchr (Buffer
, L
'.');
538 if ((Extension
!= NULL
) && (*Extension
== L
'.'))
540 /* with extension - remove dot if it's the last character */
541 if (Buffer
[Length
- 1] == L
'.')
547 /* name without extension - assume that it is .dll */
548 memmove (Buffer
+ Length
, L
".dll", 10);
551 RtlCreateUnicodeString(FullDllName
, Buffer
);
554 PLDR_DATA_TABLE_ENTRY
555 LdrAddModuleEntry(PVOID ImageBase
,
556 PIMAGE_NT_HEADERS NTHeaders
,
559 PLDR_DATA_TABLE_ENTRY Module
;
561 Module
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (LDR_DATA_TABLE_ENTRY
));
563 memset(Module
, 0, sizeof(LDR_DATA_TABLE_ENTRY
));
564 Module
->DllBase
= (PVOID
)ImageBase
;
565 Module
->EntryPoint
= (PVOID
)(ULONG_PTR
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
;
566 if (Module
->EntryPoint
!= 0)
567 Module
->EntryPoint
= (PVOID
)((ULONG_PTR
)Module
->EntryPoint
+ (ULONG_PTR
)Module
->DllBase
);
568 Module
->SizeOfImage
= LdrpGetResidentSize(NTHeaders
);
569 if (NtCurrentPeb()->Ldr
->Initialized
== TRUE
)
571 /* loading while app is running */
572 Module
->LoadCount
= 1;
575 * loading while app is initializing
576 * dll must not be unloaded
578 Module
->LoadCount
= LDRP_PROCESS_CREATION_TIME
;
582 Module
->TlsIndex
= -1;
583 Module
->CheckSum
= NTHeaders
->OptionalHeader
.CheckSum
;
584 Module
->TimeDateStamp
= NTHeaders
->FileHeader
.TimeDateStamp
;
586 RtlCreateUnicodeString (&Module
->FullDllName
,
588 RtlCreateUnicodeString (&Module
->BaseDllName
,
589 wcsrchr(FullDosName
, L
'\\') + 1);
590 DPRINT ("BaseDllName %wZ\n", &Module
->BaseDllName
);
592 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
593 InsertTailList(&NtCurrentPeb()->Ldr
->InLoadOrderModuleList
,
594 &Module
->InLoadOrderLinks
);
595 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
602 LdrpMapKnownDll(IN PUNICODE_STRING DllName
,
603 OUT PUNICODE_STRING FullDosName
,
604 OUT PHANDLE SectionHandle
)
606 OBJECT_ATTRIBUTES ObjectAttributes
;
609 DPRINT("LdrpMapKnownDll() called\n");
611 if (LdrpKnownDllsDirHandle
== NULL
)
613 DPRINT("Invalid 'KnownDlls' directory\n");
614 return STATUS_UNSUCCESSFUL
;
617 DPRINT("LdrpKnownDllPath '%wZ'\n", &LdrpKnownDllPath
);
619 InitializeObjectAttributes(&ObjectAttributes
,
621 OBJ_CASE_INSENSITIVE
,
622 LdrpKnownDllsDirHandle
,
624 Status
= NtOpenSection(SectionHandle
,
625 SECTION_MAP_READ
| SECTION_MAP_WRITE
| SECTION_MAP_EXECUTE
,
627 if (!NT_SUCCESS(Status
))
629 DPRINT("NtOpenSection() failed for '%wZ' (Status 0x%08lx)\n", DllName
, Status
);
633 FullDosName
->Length
= LdrpKnownDllPath
.Length
+ DllName
->Length
+ sizeof(WCHAR
);
634 FullDosName
->MaximumLength
= FullDosName
->Length
+ sizeof(WCHAR
);
635 FullDosName
->Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
637 FullDosName
->MaximumLength
);
638 if (FullDosName
->Buffer
== NULL
)
640 FullDosName
->Length
= 0;
641 FullDosName
->MaximumLength
= 0;
642 return STATUS_SUCCESS
;
645 wcscpy(FullDosName
->Buffer
, LdrpKnownDllPath
.Buffer
);
646 wcscat(FullDosName
->Buffer
, L
"\\");
647 wcscat(FullDosName
->Buffer
, DllName
->Buffer
);
649 DPRINT("FullDosName '%wZ'\n", FullDosName
);
651 DPRINT("LdrpMapKnownDll() done\n");
653 return STATUS_SUCCESS
;
658 LdrpMapDllImageFile(IN PWSTR SearchPath OPTIONAL
,
659 IN PUNICODE_STRING DllName
,
660 OUT PUNICODE_STRING FullDosName
,
661 IN BOOLEAN MapAsDataFile
,
662 OUT PHANDLE SectionHandle
)
664 WCHAR
*SearchPathBuffer
= NULL
;
665 WCHAR
*ImagePathNameBufferPtr
= NULL
;
666 WCHAR DosName
[MAX_PATH
];
667 UNICODE_STRING FullNtFileName
;
668 UNICODE_STRING PathEnvironmentVar_U
;
669 UNICODE_STRING PathName_U
;
670 OBJECT_ATTRIBUTES FileObjectAttributes
;
672 char BlockBuffer
[1024];
673 PIMAGE_DOS_HEADER DosHeader
;
674 PIMAGE_NT_HEADERS NTHeaders
;
675 IO_STATUS_BLOCK IoStatusBlock
;
680 DPRINT("LdrpMapDllImageFile() called\n");
682 if (SearchPath
== NULL
)
684 /* get application running path */
685 ImagePathNameBufferPtr
= NtCurrentPeb()->ProcessParameters
->ImagePathName
.Buffer
;
687 /* Length of ImagePathName */
688 ImagePathLen
= wcslen(ImagePathNameBufferPtr
);
690 /* Subtract application name leaveing only the directory length */
691 while (ImagePathLen
&& ImagePathNameBufferPtr
[ImagePathLen
- 1] != L
'\\')
694 /* Length of directory + semicolon */
695 len
= ImagePathLen
+ 1;
697 /* Length of SystemRoot + "//system32" + semicolon*/
698 len
+= wcslen(SharedUserData
->NtSystemRoot
) + 10;
699 /* Length of SystemRoot + semicolon */
700 len
+= wcslen(SharedUserData
->NtSystemRoot
) + 1;
702 RtlInitUnicodeString (&PathName_U
, L
"PATH");
703 PathEnvironmentVar_U
.Length
= 0;
704 PathEnvironmentVar_U
.MaximumLength
= 0;
705 PathEnvironmentVar_U
.Buffer
= NULL
;
707 /* Get the path environment variable */
708 Status
= RtlQueryEnvironmentVariable_U(NULL
, &PathName_U
, &PathEnvironmentVar_U
);
710 /* Check that valid information was returned */
711 if ((Status
== STATUS_BUFFER_TOO_SMALL
) && (PathEnvironmentVar_U
.Length
> 0))
713 /* Allocate memory for the path env var */
714 PathEnvironmentVar_U
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, PathEnvironmentVar_U
.Length
+ sizeof(WCHAR
));
715 if (!PathEnvironmentVar_U
.Buffer
)
717 DPRINT1("Fatal! Out of Memory!!\n");
718 return STATUS_NO_MEMORY
;
720 PathEnvironmentVar_U
.MaximumLength
= PathEnvironmentVar_U
.Length
+ sizeof(WCHAR
);
723 Status
= RtlQueryEnvironmentVariable_U(NULL
, &PathName_U
, &PathEnvironmentVar_U
);
725 if (!NT_SUCCESS(Status
))
727 DPRINT1("Unable to get path environment string!\n");
730 /* Length of path evn var + semicolon */
731 len
+= (PathEnvironmentVar_U
.Length
/ sizeof(WCHAR
)) + 1;
734 /* Allocate the size needed to hold all the above paths + period */
735 SearchPathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, (len
+ 2) * sizeof(WCHAR
));
736 if (!SearchPathBuffer
)
738 DPRINT1("Fatal! Out of Memory!!\n");
739 return STATUS_NO_MEMORY
;
742 wcsncpy(SearchPathBuffer
, ImagePathNameBufferPtr
, ImagePathLen
);
743 wcscat (SearchPathBuffer
, L
";");
744 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
745 wcscat (SearchPathBuffer
, L
"\\system32;");
746 wcscat (SearchPathBuffer
, SharedUserData
->NtSystemRoot
);
747 wcscat (SearchPathBuffer
, L
";");
749 if (PathEnvironmentVar_U
.Buffer
)
751 wcscat (SearchPathBuffer
, PathEnvironmentVar_U
.Buffer
);
752 wcscat (SearchPathBuffer
, L
";");
753 RtlFreeHeap(RtlGetProcessHeap(), 0, PathEnvironmentVar_U
.Buffer
);
755 wcscat (SearchPathBuffer
, L
".");
757 SearchPath
= SearchPathBuffer
;
760 if (RtlDosSearchPath_U (SearchPath
,
767 /* try to find active context dll */
768 Status
= find_actctx_dll(DllName
->Buffer
, DosName
);
769 if(Status
== STATUS_SUCCESS
)
770 DPRINT("found %S for %S\n", DosName
,DllName
->Buffer
);
772 return STATUS_DLL_NOT_FOUND
;
775 if (!RtlDosPathNameToNtPathName_U (DosName
,
780 DPRINT("Dll %wZ not found!\n", DllName
);
781 return STATUS_DLL_NOT_FOUND
;
784 DPRINT("FullNtFileName %wZ\n", &FullNtFileName
);
786 InitializeObjectAttributes(&FileObjectAttributes
,
792 DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName
);
794 Status
= NtOpenFile(&FileHandle
,
795 GENERIC_READ
|SYNCHRONIZE
,
796 &FileObjectAttributes
,
799 FILE_SYNCHRONOUS_IO_NONALERT
);
800 if (!NT_SUCCESS(Status
))
802 DPRINT1("Dll open of %wZ failed: Status = 0x%08lx\n",
803 &FullNtFileName
, Status
);
804 RtlFreeHeap (RtlGetProcessHeap (),
806 FullNtFileName
.Buffer
);
809 RtlFreeHeap (RtlGetProcessHeap (),
811 FullNtFileName
.Buffer
);
816 Status
= NtReadFile(FileHandle
,
825 if (!NT_SUCCESS(Status
))
827 DPRINT("Dll header read failed: Status = 0x%08lx\n", Status
);
833 * Overlay DOS and NT headers structures to the
834 * buffer with DLL's header raw data.
836 DosHeader
= (PIMAGE_DOS_HEADER
) BlockBuffer
;
837 NTHeaders
= (PIMAGE_NT_HEADERS
) (BlockBuffer
+ DosHeader
->e_lfanew
);
839 * Check it is a PE image file.
841 if ((DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
842 || (DosHeader
->e_lfanew
== 0L)
843 || (*(PULONG
)(NTHeaders
) != IMAGE_NT_SIGNATURE
))
845 DPRINT("NTDLL format invalid\n");
848 return STATUS_UNSUCCESSFUL
;
853 * Create a section for dll.
855 Status
= NtCreateSection(SectionHandle
,
860 MapAsDataFile
? SEC_COMMIT
: SEC_IMAGE
,
864 if (!NT_SUCCESS(Status
))
866 DPRINT("NTDLL create section failed: Status = 0x%08lx\n", Status
);
870 RtlCreateUnicodeString(FullDosName
,
878 /***************************************************************************
895 LdrLoadDll (IN PWSTR SearchPath OPTIONAL
,
896 IN PULONG LoadFlags OPTIONAL
,
897 IN PUNICODE_STRING Name
,
898 OUT PVOID
*BaseAddress
/* also known as HMODULE*, and PHANDLE 'DllHandle' */)
901 PLDR_DATA_TABLE_ENTRY Module
;
903 PPEB Peb
= NtCurrentPeb();
905 TRACE_LDR("LdrLoadDll loading %wZ%S%S with flags %d\n",
907 SearchPath
? L
" from " : L
"",
908 SearchPath
? SearchPath
: L
"",
909 LoadFlags
? *LoadFlags
: 0);
911 Status
= LdrpLoadModule(SearchPath
, LoadFlags
? *LoadFlags
: 0, Name
, &Module
, BaseAddress
);
913 if (NT_SUCCESS(Status
) &&
914 (!LoadFlags
|| 0 == (*LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
)))
916 if (!create_module_activation_context( Module
))
918 RtlActivateActivationContext(0, Module
->EntryPointActivationContext
, &cookie
);
921 if (!(Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
))
923 RtlEnterCriticalSection(Peb
->LoaderLock
);
924 Status
= LdrpAttachProcess();
925 RtlLeaveCriticalSection(Peb
->LoaderLock
);
927 if (Module
->EntryPointActivationContext
) RtlDeactivateActivationContext(0, cookie
);
930 if ((!Module
) && (NT_SUCCESS(Status
)))
933 *BaseAddress
= NT_SUCCESS(Status
) ? Module
->DllBase
: NULL
;
939 /***************************************************************************
941 * LdrFindEntryForAddress
956 LdrFindEntryForAddress(PVOID Address
,
957 PLDR_DATA_TABLE_ENTRY
*Module
)
959 PLIST_ENTRY ModuleListHead
;
961 PLDR_DATA_TABLE_ENTRY ModulePtr
;
963 DPRINT("LdrFindEntryForAddress(Address %p)\n", Address
);
965 if (NtCurrentPeb()->Ldr
== NULL
)
966 return(STATUS_NO_MORE_ENTRIES
);
968 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
969 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
970 Entry
= ModuleListHead
->Flink
;
971 if (Entry
== ModuleListHead
)
973 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
974 return(STATUS_NO_MORE_ENTRIES
);
977 while (Entry
!= ModuleListHead
)
979 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
981 DPRINT("Scanning %wZ at %p\n", &ModulePtr
->BaseDllName
, ModulePtr
->DllBase
);
983 if ((Address
>= ModulePtr
->DllBase
) &&
984 ((ULONG_PTR
)Address
<= ((ULONG_PTR
)ModulePtr
->DllBase
+ ModulePtr
->SizeOfImage
)))
987 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
988 return(STATUS_SUCCESS
);
991 Entry
= Entry
->Flink
;
994 DPRINT("Failed to find module entry.\n");
996 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
997 return(STATUS_NO_MORE_ENTRIES
);
1001 /***************************************************************************
1003 * LdrFindEntryForName
1017 LdrFindEntryForName(PUNICODE_STRING Name
,
1018 PLDR_DATA_TABLE_ENTRY
*Module
,
1021 PLIST_ENTRY ModuleListHead
;
1023 PLDR_DATA_TABLE_ENTRY ModulePtr
;
1024 BOOLEAN ContainsPath
;
1025 UNICODE_STRING AdjustedName
;
1027 DPRINT("LdrFindEntryForName(Name %wZ)\n", Name
);
1029 if (NtCurrentPeb()->Ldr
== NULL
)
1030 return(STATUS_NO_MORE_ENTRIES
);
1032 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
1033 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
1034 Entry
= ModuleListHead
->Flink
;
1035 if (Entry
== ModuleListHead
)
1037 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1038 return(STATUS_NO_MORE_ENTRIES
);
1041 // NULL is the current process
1044 *Module
= ExeModule
;
1045 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1046 return(STATUS_SUCCESS
);
1049 ContainsPath
= (Name
->Length
>= 2 * sizeof(WCHAR
) && L
':' == Name
->Buffer
[1]);
1050 LdrAdjustDllName (&AdjustedName
, Name
, !ContainsPath
);
1054 if ((! ContainsPath
&&
1055 0 == RtlCompareUnicodeString(&LdrpLastModule
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1057 0 == RtlCompareUnicodeString(&LdrpLastModule
->FullDllName
, &AdjustedName
, TRUE
)))
1059 *Module
= LdrpLastModule
;
1060 if (Ref
&& (*Module
)->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1062 (*Module
)->LoadCount
++;
1064 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1065 RtlFreeUnicodeString(&AdjustedName
);
1066 return(STATUS_SUCCESS
);
1069 while (Entry
!= ModuleListHead
)
1071 ModulePtr
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
1073 DPRINT("Scanning %wZ %wZ\n", &ModulePtr
->BaseDllName
, &AdjustedName
);
1075 if ((! ContainsPath
&&
1076 0 == RtlCompareUnicodeString(&ModulePtr
->BaseDllName
, &AdjustedName
, TRUE
)) ||
1078 0 == RtlCompareUnicodeString(&ModulePtr
->FullDllName
, &AdjustedName
, TRUE
)))
1080 *Module
= LdrpLastModule
= ModulePtr
;
1081 if (Ref
&& ModulePtr
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
)
1083 ModulePtr
->LoadCount
++;
1085 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1086 RtlFreeUnicodeString(&AdjustedName
);
1087 return(STATUS_SUCCESS
);
1090 Entry
= Entry
->Flink
;
1093 DPRINT("Failed to find dll %wZ\n", Name
);
1094 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
1095 RtlFreeUnicodeString(&AdjustedName
);
1096 return(STATUS_NO_MORE_ENTRIES
);
1099 /**********************************************************************
1115 LdrFixupForward(PCHAR ForwardName
)
1117 CHAR NameBuffer
[128];
1118 UNICODE_STRING DllName
;
1121 PLDR_DATA_TABLE_ENTRY Module
;
1124 strcpy(NameBuffer
, ForwardName
);
1125 p
= strchr(NameBuffer
, '.');
1130 DPRINT("Dll: %s Function: %s\n", NameBuffer
, p
+1);
1131 RtlCreateUnicodeStringFromAsciiz (&DllName
,
1134 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1136 * The caller (or the image) is responsible for loading of the dll, where the function is forwarded.
1138 if (!NT_SUCCESS(Status
))
1140 Status
= LdrLoadDll(NULL
,
1144 if (NT_SUCCESS(Status
))
1146 Status
= LdrFindEntryForName (&DllName
, &Module
, FALSE
);
1149 RtlFreeUnicodeString (&DllName
);
1150 if (!NT_SUCCESS(Status
))
1152 DPRINT1("LdrFixupForward: failed to load %s\n", NameBuffer
);
1156 DPRINT("BaseAddress: %p\n", Module
->DllBase
);
1158 return LdrGetExportByName(Module
->DllBase
, (PUCHAR
)(p
+1), -1);
1165 /**********************************************************************
1167 * LdrGetExportByOrdinal
1181 LdrGetExportByOrdinal (
1186 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1187 ULONG ExportDirSize
;
1188 PDWORD
* ExFunctions
;
1191 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1192 RtlImageDirectoryEntryToData (BaseAddress
,
1194 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1198 ExFunctions
= (PDWORD
*)
1201 ExportDir
->AddressOfFunctions
1204 "LdrGetExportByOrdinal(Ordinal %lu) = %p\n",
1206 RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1209 Function
= (0 != ExFunctions
[Ordinal
- ExportDir
->Base
]
1210 ? RVA(BaseAddress
, ExFunctions
[Ordinal
- ExportDir
->Base
] )
1213 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1214 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1216 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1217 Function
= LdrFixupForward((PCHAR
)Function
);
1224 /**********************************************************************
1226 * LdrGetExportByName
1237 * AddressOfNames and AddressOfNameOrdinals are paralell tables,
1238 * both with NumberOfNames entries.
1242 LdrGetExportByName(PVOID BaseAddress
,
1246 PIMAGE_EXPORT_DIRECTORY ExportDir
;
1247 PDWORD
* ExFunctions
;
1249 USHORT
* ExOrdinals
;
1254 ULONG ExportDirSize
;
1256 DPRINT("LdrGetExportByName %p %s %hu\n", BaseAddress
, SymbolName
, Hint
);
1258 ExportDir
= (PIMAGE_EXPORT_DIRECTORY
)
1259 RtlImageDirectoryEntryToData(BaseAddress
,
1261 IMAGE_DIRECTORY_ENTRY_EXPORT
,
1263 if (ExportDir
== NULL
)
1265 DPRINT1("LdrGetExportByName(): no export directory, "
1266 "can't lookup %s/%hu!\n", SymbolName
, Hint
);
1271 //The symbol names may be missing entirely
1272 if (ExportDir
->AddressOfNames
== 0)
1274 DPRINT("LdrGetExportByName(): symbol names missing entirely\n");
1279 * Get header pointers
1281 ExNames
= (PDWORD
*)RVA(BaseAddress
,
1282 ExportDir
->AddressOfNames
);
1283 ExOrdinals
= (USHORT
*)RVA(BaseAddress
,
1284 ExportDir
->AddressOfNameOrdinals
);
1285 ExFunctions
= (PDWORD
*)RVA(BaseAddress
,
1286 ExportDir
->AddressOfFunctions
);
1289 * Check the hint first
1291 if (Hint
< ExportDir
->NumberOfNames
)
1293 ExName
= RVA(BaseAddress
, ExNames
[Hint
]);
1294 if (strcmp(ExName
, (PCHAR
)SymbolName
) == 0)
1296 Ordinal
= ExOrdinals
[Hint
];
1297 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1298 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1299 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1301 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1302 Function
= LdrFixupForward((PCHAR
)Function
);
1303 if (Function
== NULL
)
1305 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1309 if (Function
!= NULL
)
1318 maxn
= ExportDir
->NumberOfNames
- 1;
1319 while (minn
<= maxn
)
1324 mid
= (minn
+ maxn
) / 2;
1326 ExName
= RVA(BaseAddress
, ExNames
[mid
]);
1327 res
= strcmp(ExName
, (PCHAR
)SymbolName
);
1330 Ordinal
= ExOrdinals
[mid
];
1331 Function
= RVA(BaseAddress
, ExFunctions
[Ordinal
]);
1332 if (((ULONG_PTR
)Function
>= (ULONG_PTR
)ExportDir
) &&
1333 ((ULONG_PTR
)Function
< (ULONG_PTR
)ExportDir
+ (ULONG_PTR
)ExportDirSize
))
1335 DPRINT("Forward: %s\n", (PCHAR
)Function
);
1336 Function
= LdrFixupForward((PCHAR
)Function
);
1337 if (Function
== NULL
)
1339 DPRINT1("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1343 if (Function
!= NULL
)
1346 else if (minn
== maxn
)
1348 DPRINT("LdrGetExportByName(): binary search failed\n");
1361 DPRINT("LdrGetExportByName(): failed to find %s\n",SymbolName
);
1366 /**********************************************************************
1368 * LdrPerformRelocations
1371 * Relocate a DLL's memory image.
1383 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders
,
1386 PIMAGE_DATA_DIRECTORY RelocationDDir
;
1387 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
1388 ULONG Count
, OldProtect
, OldProtect2
;
1390 PVOID Page
, ProtectPage
, ProtectPage2
;
1395 if (NTHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
1397 return STATUS_SUCCESS
;
1401 &NTHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1403 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
1405 return STATUS_SUCCESS
;
1408 ProtectSize
= PAGE_SIZE
;
1409 Delta
= (ULONG_PTR
)ImageBase
- NTHeaders
->OptionalHeader
.ImageBase
;
1410 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1411 RelocationDDir
->VirtualAddress
);
1412 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)ImageBase
+
1413 RelocationDDir
->VirtualAddress
+ RelocationDDir
->Size
);
1415 while (RelocationDir
< RelocationEnd
&&
1416 RelocationDir
->SizeOfBlock
> 0)
1418 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) /
1420 Page
= (PVOID
)((ULONG_PTR
)ImageBase
+ (ULONG_PTR
)RelocationDir
->VirtualAddress
);
1421 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
1423 /* Unprotect the page(s) we're about to relocate. */
1425 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1430 if (!NT_SUCCESS(Status
))
1432 DPRINT1("Failed to unprotect relocation target.\n");
1436 if (RelocationDir
->VirtualAddress
+ PAGE_SIZE
<
1437 NTHeaders
->OptionalHeader
.SizeOfImage
)
1439 ProtectPage2
= (PVOID
)((ULONG_PTR
)ProtectPage
+ PAGE_SIZE
);
1440 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1445 if (!NT_SUCCESS(Status
))
1447 DPRINT1("Failed to unprotect relocation target (2).\n");
1448 NtProtectVirtualMemory(NtCurrentProcess(),
1458 ProtectPage2
= NULL
;
1461 RelocationDir
= LdrProcessRelocationBlock((ULONG_PTR
)Page
,
1465 if (RelocationDir
== NULL
)
1466 return STATUS_UNSUCCESSFUL
;
1468 /* Restore old page protection. */
1469 NtProtectVirtualMemory(NtCurrentProcess(),
1475 if (ProtectPage2
!= NULL
)
1477 NtProtectVirtualMemory(NtCurrentProcess(),
1485 return STATUS_SUCCESS
;
1489 LdrpGetOrLoadModule(PWCHAR SearchPath
,
1491 PLDR_DATA_TABLE_ENTRY
* Module
,
1494 ANSI_STRING AnsiDllName
;
1495 UNICODE_STRING DllName
;
1498 DPRINT("LdrpGetOrLoadModule() called for %s\n", Name
);
1500 RtlInitAnsiString(&AnsiDllName
, Name
);
1501 Status
= RtlAnsiStringToUnicodeString(&DllName
, &AnsiDllName
, TRUE
);
1502 if (!NT_SUCCESS(Status
))
1507 Status
= LdrFindEntryForName (&DllName
, Module
, Load
);
1508 if (Load
&& !NT_SUCCESS(Status
))
1510 Status
= LdrpLoadModule(SearchPath
,
1515 if (NT_SUCCESS(Status
))
1517 Status
= LdrFindEntryForName (&DllName
, Module
, FALSE
);
1519 if (!NT_SUCCESS(Status
))
1521 ULONG ErrorResponse
;
1522 ULONG_PTR ErrorParameter
= (ULONG_PTR
)&DllName
;
1524 DPRINT1("failed to load %wZ\n", &DllName
);
1526 NtRaiseHardError(STATUS_DLL_NOT_FOUND
,
1534 RtlFreeUnicodeString (&DllName
);
1539 RtlpRaiseImportNotFound(CHAR
*FuncName
, ULONG Ordinal
, PUNICODE_STRING DllName
)
1541 ULONG ErrorResponse
;
1542 ULONG_PTR ErrorParameters
[2];
1543 ANSI_STRING ProcNameAnsi
;
1544 UNICODE_STRING ProcName
;
1549 _snprintf(Buffer
, 8, "# %ld", Ordinal
);
1553 RtlInitAnsiString(&ProcNameAnsi
, FuncName
);
1554 RtlAnsiStringToUnicodeString(&ProcName
, &ProcNameAnsi
, TRUE
);
1555 ErrorParameters
[0] = (ULONG_PTR
)&ProcName
;
1556 ErrorParameters
[1] = (ULONG_PTR
)DllName
;
1557 NtRaiseHardError(STATUS_ENTRYPOINT_NOT_FOUND
,
1563 RtlFreeUnicodeString(&ProcName
);
1567 LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module
,
1568 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1569 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
)
1572 PVOID
* ImportAddressList
;
1573 PULONG FunctionNameList
;
1579 if (ImportModuleDirectory
== NULL
|| ImportModuleDirectory
->Name
== 0)
1581 return STATUS_UNSUCCESSFUL
;
1584 /* Get the import address list. */
1585 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1587 /* Get the list of functions to import. */
1588 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1590 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1594 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1597 /* Get the size of IAT. */
1599 while (FunctionNameList
[IATSize
] != 0L)
1604 /* No need to fixup anything if IAT is empty */
1605 if (IATSize
== 0) return STATUS_SUCCESS
;
1607 /* Unprotect the region we are about to write into. */
1608 IATBase
= (PVOID
)ImportAddressList
;
1609 IATSize
*= sizeof(PVOID
*);
1610 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1615 if (!NT_SUCCESS(Status
))
1617 DPRINT1("Failed to unprotect IAT.\n");
1621 /* Walk through function list and fixup addresses. */
1622 while (*FunctionNameList
!= 0L)
1624 if ((*FunctionNameList
) & 0x80000000)
1626 Ordinal
= (*FunctionNameList
) & 0x7fffffff;
1627 *ImportAddressList
= LdrGetExportByOrdinal(ImportedModule
->DllBase
, Ordinal
);
1628 if ((*ImportAddressList
) == NULL
)
1630 DPRINT1("Failed to import #%ld from %wZ\n", Ordinal
, &ImportedModule
->FullDllName
);
1631 RtlpRaiseImportNotFound(NULL
, Ordinal
, &ImportedModule
->FullDllName
);
1632 return STATUS_ENTRYPOINT_NOT_FOUND
;
1637 IMAGE_IMPORT_BY_NAME
*pe_name
;
1638 pe_name
= RVA(Module
->DllBase
, *FunctionNameList
);
1639 *ImportAddressList
= LdrGetExportByName(ImportedModule
->DllBase
, pe_name
->Name
, pe_name
->Hint
);
1640 if ((*ImportAddressList
) == NULL
)
1642 DPRINT1("Failed to import %s from %wZ\n", pe_name
->Name
, &ImportedModule
->FullDllName
);
1643 RtlpRaiseImportNotFound((CHAR
*)pe_name
->Name
, 0, &ImportedModule
->FullDllName
);
1644 return STATUS_ENTRYPOINT_NOT_FOUND
;
1647 ImportAddressList
++;
1651 /* Protect the region we are about to write into. */
1652 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1657 if (!NT_SUCCESS(Status
))
1659 DPRINT1("Failed to protect IAT.\n");
1663 return STATUS_SUCCESS
;
1667 LdrpProcessImportDirectory(
1668 PLDR_DATA_TABLE_ENTRY Module
,
1669 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1673 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1677 DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
1678 Module
, &Module
->BaseDllName
, ImportedName
);
1681 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1682 RtlImageDirectoryEntryToData(Module
->DllBase
,
1684 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1686 if (ImportModuleDirectory
== NULL
)
1688 return STATUS_UNSUCCESSFUL
;
1691 while (ImportModuleDirectory
->Name
)
1693 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1694 if (0 == _stricmp(Name
, ImportedName
))
1696 Status
= LdrpProcessImportDirectoryEntry(Module
,
1698 ImportModuleDirectory
);
1699 if (!NT_SUCCESS(Status
))
1704 ImportModuleDirectory
++;
1708 return STATUS_SUCCESS
;
1713 LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module
,
1714 PLDR_DATA_TABLE_ENTRY ImportedModule
,
1717 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1719 PVOID
* ImportAddressList
;
1722 PULONG FunctionNameList
;
1727 PIMAGE_NT_HEADERS NTHeaders
;
1731 DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
1732 Module
, &Module
->BaseDllName
, ImportedModule
, &ImportedModule
->BaseDllName
, ImportedName
);
1734 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1735 RtlImageDirectoryEntryToData(Module
->DllBase
,
1737 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1739 if (ImportModuleDirectory
== NULL
)
1741 return STATUS_UNSUCCESSFUL
;
1744 while (ImportModuleDirectory
->Name
)
1746 Name
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
1747 if (0 == _stricmp(Name
, (PCHAR
)ImportedName
))
1750 /* Get the import address list. */
1751 ImportAddressList
= (PVOID
*)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1753 /* Get the list of functions to import. */
1754 if (ImportModuleDirectory
->OriginalFirstThunk
!= 0)
1756 FunctionNameList
= (PULONG
) ((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->OriginalFirstThunk
);
1760 FunctionNameList
= (PULONG
)((ULONG_PTR
)Module
->DllBase
+ (ULONG_PTR
)ImportModuleDirectory
->FirstThunk
);
1763 /* Get the size of IAT. */
1765 while (FunctionNameList
[IATSize
] != 0L)
1770 /* Unprotect the region we are about to write into. */
1771 IATBase
= (PVOID
)ImportAddressList
;
1772 IATSize
*= sizeof(PVOID
*);
1773 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1778 if (!NT_SUCCESS(Status
))
1780 DPRINT1("Failed to unprotect IAT.\n");
1784 NTHeaders
= RtlImageNtHeader (ImportedModule
->DllBase
);
1785 Start
= (PVOID
)NTHeaders
->OptionalHeader
.ImageBase
;
1786 End
= (PVOID
)((ULONG_PTR
)Start
+ ImportedModule
->SizeOfImage
);
1787 Offset
= (ULONG
)((ULONG_PTR
)ImportedModule
->DllBase
- (ULONG_PTR
)Start
);
1789 /* Walk through function list and fixup addresses. */
1790 while (*FunctionNameList
!= 0L)
1792 if (*ImportAddressList
>= Start
&& *ImportAddressList
< End
)
1794 (*ImportAddressList
) = (PVOID
)((ULONG_PTR
)(*ImportAddressList
) + Offset
);
1796 ImportAddressList
++;
1800 /* Protect the region we are about to write into. */
1801 Status
= NtProtectVirtualMemory(NtCurrentProcess(),
1806 if (!NT_SUCCESS(Status
))
1808 DPRINT1("Failed to protect IAT.\n");
1812 ImportModuleDirectory
++;
1814 return STATUS_SUCCESS
;
1818 /**********************************************************************
1823 * Compute the entry point for every symbol the DLL imports
1824 * from other modules.
1836 LdrFixupImports(IN PWSTR SearchPath OPTIONAL
,
1837 IN PLDR_DATA_TABLE_ENTRY Module
)
1839 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
1840 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectoryCurrent
;
1841 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
1842 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
1843 PIMAGE_TLS_DIRECTORY TlsDirectory
;
1845 NTSTATUS Status
= STATUS_SUCCESS
;
1846 PLDR_DATA_TABLE_ENTRY ImportedModule
;
1852 DPRINT("LdrFixupImports(SearchPath %S, Module %p)\n", SearchPath
, Module
);
1854 /* Check for tls data */
1855 TlsDirectory
= (PIMAGE_TLS_DIRECTORY
)
1856 RtlImageDirectoryEntryToData(Module
->DllBase
,
1858 IMAGE_DIRECTORY_ENTRY_TLS
,
1862 TlsSize
= TlsDirectory
->EndAddressOfRawData
1863 - TlsDirectory
->StartAddressOfRawData
1864 + TlsDirectory
->SizeOfZeroFill
;
1866 if (TlsSize
> 0 && NtCurrentPeb()->Ldr
->Initialized
)
1868 TRACE_LDR("Trying to dynamically load %wZ which contains a TLS directory\n",
1869 &Module
->BaseDllName
);
1870 TlsDirectory
= NULL
;
1874 if (!create_module_activation_context( Module
))
1876 if (Module
->EntryPointActivationContext
== NULL
)
1878 DPRINT("EntryPointActivationContext has not be allocated\n");
1879 DPRINT("Module->DllBaseName %wZ\n", Module
->BaseDllName
);
1881 RtlActivateActivationContext( 0, Module
->EntryPointActivationContext
, &cookie
);
1885 * Process each import module.
1887 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
1888 RtlImageDirectoryEntryToData(Module
->DllBase
,
1890 IMAGE_DIRECTORY_ENTRY_IMPORT
,
1893 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
1894 RtlImageDirectoryEntryToData(Module
->DllBase
,
1896 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
1899 if (BoundImportDescriptor
!= NULL
&& ImportModuleDirectory
== NULL
)
1901 DPRINT1("%wZ has only a bound import directory\n", &Module
->BaseDllName
);
1902 return STATUS_UNSUCCESSFUL
;
1904 if (BoundImportDescriptor
)
1906 DPRINT("BoundImportDescriptor %p\n", BoundImportDescriptor
);
1908 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
1909 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
1911 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
1912 TRACE_LDR("%wZ bound to %s\n", &Module
->BaseDllName
, ImportedName
);
1913 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
1914 if (!NT_SUCCESS(Status
))
1916 DPRINT1("failed to load %s\n", ImportedName
);
1919 if (Module
== ImportedModule
)
1921 LdrpDecrementLoadCount(Module
, FALSE
);
1923 if (ImportedModule
->TimeDateStamp
!= BoundImportDescriptorCurrent
->TimeDateStamp
)
1925 TRACE_LDR("%wZ has stale binding to %wZ\n",
1926 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1927 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1928 if (!NT_SUCCESS(Status
))
1930 DPRINT1("failed to import %s\n", ImportedName
);
1936 BOOLEAN WrongForwarder
;
1937 WrongForwarder
= FALSE
;
1938 if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1940 TRACE_LDR("%wZ has stale binding to %s\n",
1941 &Module
->BaseDllName
, ImportedName
);
1945 TRACE_LDR("%wZ has correct binding to %wZ\n",
1946 &Module
->BaseDllName
, &ImportedModule
->BaseDllName
);
1948 if (BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
)
1950 PIMAGE_BOUND_FORWARDER_REF BoundForwarderRef
;
1952 PLDR_DATA_TABLE_ENTRY ForwarderModule
;
1953 PCHAR ForwarderName
;
1955 BoundForwarderRef
= (PIMAGE_BOUND_FORWARDER_REF
)(BoundImportDescriptorCurrent
+ 1);
1956 for (i
= 0; i
< BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
; i
++, BoundForwarderRef
++)
1958 ForwarderName
= (PCHAR
)BoundImportDescriptor
+ BoundForwarderRef
->OffsetModuleName
;
1959 TRACE_LDR("%wZ bound to %s via forwardes from %s\n",
1960 &Module
->BaseDllName
, ForwarderName
, ImportedName
);
1961 Status
= LdrpGetOrLoadModule(SearchPath
, ForwarderName
, &ForwarderModule
, TRUE
);
1962 if (!NT_SUCCESS(Status
))
1964 DPRINT1("failed to load %s\n", ForwarderName
);
1967 if (Module
== ImportedModule
)
1969 LdrpDecrementLoadCount(Module
, FALSE
);
1971 if (ForwarderModule
->TimeDateStamp
!= BoundForwarderRef
->TimeDateStamp
||
1972 ForwarderModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1974 TRACE_LDR("%wZ has stale binding to %s\n",
1975 &Module
->BaseDllName
, ForwarderName
);
1976 WrongForwarder
= TRUE
;
1980 TRACE_LDR("%wZ has correct binding to %s\n",
1981 &Module
->BaseDllName
, ForwarderName
);
1985 if (WrongForwarder
||
1986 ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1988 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
1989 if (!NT_SUCCESS(Status
))
1991 DPRINT1("failed to import %s\n", ImportedName
);
1995 else if (ImportedModule
->Flags
& LDRP_IMAGE_NOT_AT_BASE
)
1997 TRACE_LDR("Adjust imports for %s from %wZ\n",
1998 ImportedName
, &Module
->BaseDllName
);
1999 Status
= LdrpAdjustImportDirectory(Module
, ImportedModule
, ImportedName
);
2000 if (!NT_SUCCESS(Status
))
2002 DPRINT1("failed to adjust import entries for %s\n", ImportedName
);
2006 else if (WrongForwarder
)
2010 * Update only forwarders
2012 TRACE_LDR("Stale BIND %s from %wZ\n",
2013 ImportedName
, &Module
->BaseDllName
);
2014 Status
= LdrpProcessImportDirectory(Module
, ImportedModule
, ImportedName
);
2015 if (!NT_SUCCESS(Status
))
2017 DPRINT1("faild to import %s\n", ImportedName
);
2026 BoundImportDescriptorCurrent
+= BoundImportDescriptorCurrent
->NumberOfModuleForwarderRefs
+ 1;
2029 else if (ImportModuleDirectory
)
2031 DPRINT("ImportModuleDirectory %p\n", ImportModuleDirectory
);
2033 ImportModuleDirectoryCurrent
= ImportModuleDirectory
;
2034 while (ImportModuleDirectoryCurrent
->Name
)
2036 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
2037 TRACE_LDR("%wZ imports functions from %s\n", &Module
->BaseDllName
, ImportedName
);
2039 if (SearchPath
== NULL
)
2041 ModulePath
= LdrpQueryAppPaths(Module
->BaseDllName
.Buffer
);
2043 Status
= LdrpGetOrLoadModule(ModulePath
, ImportedName
, &ImportedModule
, TRUE
);
2044 if (ModulePath
!= NULL
) RtlFreeHeap(RtlGetProcessHeap(), 0, ModulePath
);
2045 if (NT_SUCCESS(Status
)) goto Success
;
2048 Status
= LdrpGetOrLoadModule(SearchPath
, ImportedName
, &ImportedModule
, TRUE
);
2049 if (!NT_SUCCESS(Status
))
2051 DPRINT1("failed to load %s\n", ImportedName
);
2055 if (Module
== ImportedModule
)
2057 LdrpDecrementLoadCount(Module
, FALSE
);
2060 TRACE_LDR("Initializing imports for %wZ from %s\n",
2061 &Module
->BaseDllName
, ImportedName
);
2062 Status
= LdrpProcessImportDirectoryEntry(Module
, ImportedModule
, ImportModuleDirectoryCurrent
);
2063 if (!NT_SUCCESS(Status
))
2065 DPRINT1("failed to import %s\n", ImportedName
);
2068 ImportModuleDirectoryCurrent
++;
2071 if (!NT_SUCCESS(Status
))
2073 NTSTATUS errorStatus
= Status
;
2075 while (ImportModuleDirectoryCurrent
>= ImportModuleDirectory
)
2077 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectoryCurrent
->Name
;
2079 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2080 if (NT_SUCCESS(Status
) && Module
!= ImportedModule
)
2082 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2083 if (!NT_SUCCESS(Status
)) DPRINT1("unable to unload %s\n", ImportedName
);
2085 ImportModuleDirectoryCurrent
--;
2091 if (TlsDirectory
&& TlsSize
> 0)
2093 LdrpAcquireTlsSlot(Module
, TlsSize
, FALSE
);
2096 if (Module
->EntryPointActivationContext
) RtlDeactivateActivationContext( 0, cookie
);
2098 return STATUS_SUCCESS
;
2102 /**********************************************************************
2107 * 1. Relocate, if needed the EXE.
2108 * 2. Fixup any imported symbol.
2109 * 3. Compute the EXE's entry point.
2113 * Address at which the EXE's image
2117 * Handle of the section that contains
2121 * NULL on error; otherwise the entry point
2122 * to call for initializing the DLL.
2127 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
2128 * Currently the function is only used for the exe.
2130 PEPFUNC
LdrPEStartup (PVOID ImageBase
,
2131 HANDLE SectionHandle
,
2132 PLDR_DATA_TABLE_ENTRY
* Module
,
2136 PEPFUNC EntryPoint
= NULL
;
2137 PIMAGE_DOS_HEADER DosHeader
;
2138 PIMAGE_NT_HEADERS NTHeaders
;
2139 PLDR_DATA_TABLE_ENTRY tmpModule
;
2140 PVOID ActivationContextStack
;
2142 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
2143 ImageBase
, SectionHandle
);
2146 * Overlay DOS and WNT headers structures
2147 * to the DLL's image.
2149 DosHeader
= (PIMAGE_DOS_HEADER
) ImageBase
;
2150 NTHeaders
= (PIMAGE_NT_HEADERS
) ((ULONG_PTR
)ImageBase
+ DosHeader
->e_lfanew
);
2153 * If the base address is different from the
2154 * one the DLL is actually loaded, perform any
2157 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2159 DPRINT("LDR: Performing relocations\n");
2160 Status
= LdrPerformRelocations(NTHeaders
, ImageBase
);
2161 if (!NT_SUCCESS(Status
))
2163 DPRINT1("LdrPerformRelocations() failed\n");
2170 *Module
= LdrAddModuleEntry(ImageBase
, NTHeaders
, FullDosName
);
2171 (*Module
)->SectionPointer
= SectionHandle
;
2175 Module
= &tmpModule
;
2176 Status
= LdrFindEntryForAddress(ImageBase
, Module
);
2177 if (!NT_SUCCESS(Status
))
2183 if (ImageBase
!= (PVOID
) NTHeaders
->OptionalHeader
.ImageBase
)
2185 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2188 /* Allocate memory for the ActivationContextStack */
2189 /* FIXME: Verify RtlAllocateActivationContextStack behavior */
2190 Status
= RtlAllocateActivationContextStack(&ActivationContextStack
);
2191 if (NT_SUCCESS(Status
))
2193 DPRINT("ActivationContextStack %x\n",ActivationContextStack
);
2194 DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK
)ActivationContextStack
)->ActiveFrame
);
2195 NtCurrentTeb()->ActivationContextStackPointer
= ActivationContextStack
;
2196 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NULL
;
2199 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
2202 * If the DLL's imports symbols from other
2203 * modules, fixup the imported calls entry points.
2205 DPRINT("About to fixup imports\n");
2206 Status
= LdrFixupImports(NULL
, *Module
);
2207 if (!NT_SUCCESS(Status
))
2209 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module
)->BaseDllName
);
2212 DPRINT("Fixup done\n");
2213 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2214 Status
= LdrpInitializeTlsForProccess();
2215 if (NT_SUCCESS(Status
))
2217 Status
= LdrpAttachProcess();
2219 if (NT_SUCCESS(Status
))
2221 LdrpTlsCallback(*Module
, DLL_PROCESS_ATTACH
);
2225 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
2226 if (!NT_SUCCESS(Status
))
2232 * Compute the DLL's entry point's address.
2234 DPRINT("ImageBase = %p\n", ImageBase
);
2235 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG
)NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2236 if (NTHeaders
->OptionalHeader
.AddressOfEntryPoint
!= 0)
2238 EntryPoint
= (PEPFUNC
) ((ULONG_PTR
)ImageBase
2239 + NTHeaders
->OptionalHeader
.AddressOfEntryPoint
);
2241 DPRINT("LdrPEStartup() = %p\n",EntryPoint
);
2246 LdrpLoadModule(IN PWSTR SearchPath OPTIONAL
,
2248 IN PUNICODE_STRING Name
,
2249 PLDR_DATA_TABLE_ENTRY
*Module
,
2250 PVOID
*BaseAddress OPTIONAL
)
2252 UNICODE_STRING AdjustedName
;
2253 UNICODE_STRING FullDosName
;
2255 PLDR_DATA_TABLE_ENTRY tmpModule
;
2256 HANDLE SectionHandle
;
2259 PIMAGE_NT_HEADERS NtHeaders
;
2260 BOOLEAN MappedAsDataFile
;
2261 PVOID ArbitraryUserPointer
;
2265 Module
= &tmpModule
;
2267 /* adjust the full dll name */
2268 LdrAdjustDllName(&AdjustedName
, Name
, FALSE
);
2270 DPRINT("%wZ\n", &AdjustedName
);
2272 MappedAsDataFile
= FALSE
;
2273 /* Test if dll is already loaded */
2274 Status
= LdrFindEntryForName(&AdjustedName
, Module
, TRUE
);
2275 if (NT_SUCCESS(Status
))
2277 RtlFreeUnicodeString(&AdjustedName
);
2278 if (NULL
!= BaseAddress
)
2280 *BaseAddress
= (*Module
)->DllBase
;
2285 /* Open or create dll image section */
2286 Status
= LdrpMapKnownDll(&AdjustedName
, &FullDosName
, &SectionHandle
);
2287 if (!NT_SUCCESS(Status
))
2289 MappedAsDataFile
= (0 != (LoadFlags
& LOAD_LIBRARY_AS_DATAFILE
));
2290 Status
= LdrpMapDllImageFile(SearchPath
, &AdjustedName
, &FullDosName
,
2291 MappedAsDataFile
, &SectionHandle
);
2293 if (!NT_SUCCESS(Status
))
2295 DPRINT1("Failed to create or open dll section of '%wZ' (Status %lx)\n", &AdjustedName
, Status
);
2296 RtlFreeUnicodeString(&AdjustedName
);
2299 RtlFreeUnicodeString(&AdjustedName
);
2300 /* Map the dll into the process */
2303 ArbitraryUserPointer
= NtCurrentTeb()->NtTib
.ArbitraryUserPointer
;
2304 NtCurrentTeb()->NtTib
.ArbitraryUserPointer
= FullDosName
.Buffer
;
2305 Status
= NtMapViewOfSection(SectionHandle
,
2315 NtCurrentTeb()->NtTib
.ArbitraryUserPointer
= ArbitraryUserPointer
;
2316 if (!NT_SUCCESS(Status
))
2318 DPRINT1("map view of section failed (Status 0x%08lx)\n", Status
);
2319 RtlFreeUnicodeString(&FullDosName
);
2320 NtClose(SectionHandle
);
2323 if (NULL
!= BaseAddress
)
2325 *BaseAddress
= ImageBase
;
2327 if (!MappedAsDataFile
)
2329 /* Get and check the NT headers */
2330 NtHeaders
= RtlImageNtHeader(ImageBase
);
2331 if (NtHeaders
== NULL
)
2333 DPRINT1("RtlImageNtHeaders() failed\n");
2334 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2335 NtClose (SectionHandle
);
2336 RtlFreeUnicodeString(&FullDosName
);
2337 return STATUS_UNSUCCESSFUL
;
2340 DPRINT("Mapped %wZ at %x\n", &FullDosName
, ImageBase
);
2341 if (MappedAsDataFile
)
2343 ASSERT(NULL
!= BaseAddress
);
2344 if (NULL
!= BaseAddress
)
2346 *BaseAddress
= (PVOID
) ((char *) *BaseAddress
+ 1);
2349 RtlFreeUnicodeString(&FullDosName
);
2350 NtClose(SectionHandle
);
2351 return STATUS_SUCCESS
;
2353 /* If the base address is different from the
2354 * one the DLL is actually loaded, perform any
2356 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2358 DPRINT1("Relocating (%lx -> %p) %wZ\n",
2359 NtHeaders
->OptionalHeader
.ImageBase
, ImageBase
, &FullDosName
);
2360 Status
= LdrPerformRelocations(NtHeaders
, ImageBase
);
2361 if (!NT_SUCCESS(Status
))
2363 DPRINT1("LdrPerformRelocations() failed\n");
2364 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2365 NtClose (SectionHandle
);
2366 RtlFreeUnicodeString(&FullDosName
);
2367 return STATUS_UNSUCCESSFUL
;
2370 *Module
= LdrAddModuleEntry(ImageBase
, NtHeaders
, FullDosName
.Buffer
);
2371 (*Module
)->SectionPointer
= SectionHandle
;
2372 if (ImageBase
!= (PVOID
) NtHeaders
->OptionalHeader
.ImageBase
)
2374 (*Module
)->Flags
|= LDRP_IMAGE_NOT_AT_BASE
;
2376 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2378 (*Module
)->Flags
|= LDRP_IMAGE_DLL
;
2380 /* fixup the imported calls entry points */
2381 Status
= LdrFixupImports(SearchPath
, *Module
);
2382 if (!NT_SUCCESS(Status
))
2384 DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module
)->BaseDllName
, Status
);
2385 NtUnmapViewOfSection (NtCurrentProcess (), ImageBase
);
2386 NtClose (SectionHandle
);
2387 RtlFreeUnicodeString (&FullDosName
);
2388 RtlFreeUnicodeString (&(*Module
)->FullDllName
);
2389 RtlFreeUnicodeString (&(*Module
)->BaseDllName
);
2390 RemoveEntryList (&(*Module
)->InLoadOrderLinks
);
2391 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2395 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2396 InsertTailList(&NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
,
2397 &(*Module
)->InInitializationOrderLinks
);
2398 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2400 return STATUS_SUCCESS
;
2404 LdrpUnloadModule(PLDR_DATA_TABLE_ENTRY Module
,
2407 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory
;
2408 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor
;
2409 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent
;
2411 PLDR_DATA_TABLE_ENTRY ImportedModule
;
2412 NTSTATUS Status
= 0;
2418 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
2421 LoadCount
= LdrpDecrementLoadCount(Module
, Unload
);
2423 TRACE_LDR("Unload %wZ, LoadCount %d\n", &Module
->BaseDllName
, LoadCount
);
2427 /* ?????????????????? */
2429 else if (!(Module
->Flags
& LDRP_STATIC_LINK
) && LoadCount
== 1)
2431 BoundImportDescriptor
= (PIMAGE_BOUND_IMPORT_DESCRIPTOR
)
2432 RtlImageDirectoryEntryToData(Module
->DllBase
,
2434 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
,
2436 if (BoundImportDescriptor
)
2438 /* dereferencing all imported modules, use the bound import descriptor */
2439 BoundImportDescriptorCurrent
= BoundImportDescriptor
;
2440 while (BoundImportDescriptorCurrent
->OffsetModuleName
)
2442 ImportedName
= (PCHAR
)BoundImportDescriptor
+ BoundImportDescriptorCurrent
->OffsetModuleName
;
2443 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2444 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2445 if (!NT_SUCCESS(Status
))
2447 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2451 if (Module
!= ImportedModule
)
2453 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2454 if (!NT_SUCCESS(Status
))
2456 DPRINT1("unable to unload %s\n", ImportedName
);
2460 BoundImportDescriptorCurrent
++;
2465 ImportModuleDirectory
= (PIMAGE_IMPORT_DESCRIPTOR
)
2466 RtlImageDirectoryEntryToData(Module
->DllBase
,
2468 IMAGE_DIRECTORY_ENTRY_IMPORT
,
2470 if (ImportModuleDirectory
)
2472 /* dereferencing all imported modules, use the import descriptor */
2473 while (ImportModuleDirectory
->Name
)
2475 ImportedName
= (PCHAR
)Module
->DllBase
+ ImportModuleDirectory
->Name
;
2476 TRACE_LDR("%wZ trys to unload %s\n", &Module
->BaseDllName
, ImportedName
);
2477 Status
= LdrpGetOrLoadModule(NULL
, ImportedName
, &ImportedModule
, FALSE
);
2478 if (!NT_SUCCESS(Status
))
2480 DPRINT1("unable to found imported modul %s\n", ImportedName
);
2484 if (Module
!= ImportedModule
)
2486 Status
= LdrpUnloadModule(ImportedModule
, FALSE
);
2487 if (!NT_SUCCESS(Status
))
2489 DPRINT1("unable to unload %s\n", ImportedName
);
2493 ImportModuleDirectory
++;
2501 if (!(Module
->Flags
& LDRP_STATIC_LINK
))
2503 LdrpDetachProcess(FALSE
);
2506 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2508 return STATUS_SUCCESS
;
2516 LdrUnloadDll (IN PVOID BaseAddress
)
2518 PLDR_DATA_TABLE_ENTRY Module
;
2521 if (BaseAddress
== NULL
)
2522 return STATUS_SUCCESS
;
2524 if (LdrMappedAsDataFile(&BaseAddress
))
2526 Status
= NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress
);
2530 Status
= LdrFindEntryForAddress(BaseAddress
, &Module
);
2531 if (NT_SUCCESS(Status
))
2533 TRACE_LDR("LdrUnloadDll, , unloading %wZ\n", &Module
->BaseDllName
);
2534 Status
= LdrpUnloadModule(Module
, TRUE
);
2545 LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress
)
2547 PLIST_ENTRY ModuleListHead
;
2549 PLDR_DATA_TABLE_ENTRY Module
;
2552 DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %p)\n", BaseAddress
);
2554 Status
= STATUS_DLL_NOT_FOUND
;
2555 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2556 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2557 Entry
= ModuleListHead
->Flink
;
2558 while (Entry
!= ModuleListHead
)
2560 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2562 DPRINT("BaseDllName %wZ BaseAddress %p\n", &Module
->BaseDllName
, Module
->DllBase
);
2564 if (Module
->DllBase
== BaseAddress
)
2566 if (Module
->TlsIndex
== 0xFFFF)
2568 Module
->Flags
|= LDRP_DONT_CALL_FOR_THREADS
;
2569 Status
= STATUS_SUCCESS
;
2573 Entry
= Entry
->Flink
;
2575 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2583 LdrGetDllHandle(IN PWSTR DllPath OPTIONAL
,
2584 IN PULONG DllCharacteristics
,
2585 IN PUNICODE_STRING DllName
,
2586 OUT PVOID
*DllHandle
)
2588 PLDR_DATA_TABLE_ENTRY Module
;
2591 TRACE_LDR("LdrGetDllHandle, searching for %wZ from %S\n",
2592 DllName
, DllPath
? DllPath
: L
"");
2594 /* NULL is the current executable */
2595 if (DllName
== NULL
)
2597 *DllHandle
= ExeModule
->DllBase
;
2598 DPRINT("BaseAddress 0x%lx\n", *DllHandle
);
2599 return STATUS_SUCCESS
;
2602 Status
= LdrFindEntryForName(DllName
, &Module
, FALSE
);
2603 if (NT_SUCCESS(Status
))
2605 *DllHandle
= Module
->DllBase
;
2606 return STATUS_SUCCESS
;
2609 DPRINT("Failed to find dll %wZ\n", DllName
);
2611 return STATUS_DLL_NOT_FOUND
;
2618 LdrAddRefDll(IN ULONG Flags
,
2619 IN PVOID BaseAddress
)
2621 PLIST_ENTRY ModuleListHead
;
2623 PLDR_DATA_TABLE_ENTRY Module
;
2626 if (Flags
& ~(LDR_PIN_MODULE
))
2628 return STATUS_INVALID_PARAMETER
;
2631 Status
= STATUS_DLL_NOT_FOUND
;
2632 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2633 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2634 Entry
= ModuleListHead
->Flink
;
2635 while (Entry
!= ModuleListHead
)
2637 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2639 if (Module
->DllBase
== BaseAddress
)
2641 if (Flags
& LDR_PIN_MODULE
)
2643 Module
->Flags
|= LDRP_STATIC_LINK
;
2647 LdrpIncrementLoadCount(Module
,
2650 Status
= STATUS_SUCCESS
;
2653 Entry
= Entry
->Flink
;
2655 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2663 RtlPcToFileHeader(IN PVOID PcValue
,
2666 PLIST_ENTRY ModuleListHead
;
2668 PLDR_DATA_TABLE_ENTRY Module
;
2669 PVOID ImageBase
= NULL
;
2671 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2672 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
2673 Entry
= ModuleListHead
->Flink
;
2674 while (Entry
!= ModuleListHead
)
2676 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2678 if ((ULONG_PTR
)PcValue
>= (ULONG_PTR
)Module
->DllBase
&&
2679 (ULONG_PTR
)PcValue
< (ULONG_PTR
)Module
->DllBase
+ Module
->SizeOfImage
)
2681 ImageBase
= Module
->DllBase
;
2684 Entry
= Entry
->Flink
;
2686 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2688 *BaseOfImage
= ImageBase
;
2696 LdrGetProcedureAddress (IN PVOID BaseAddress
,
2697 IN PANSI_STRING Name
,
2699 OUT PVOID
*ProcedureAddress
)
2701 NTSTATUS Status
= STATUS_PROCEDURE_NOT_FOUND
;
2702 if (Name
&& Name
->Length
)
2704 TRACE_LDR("LdrGetProcedureAddress by NAME - %Z\n", Name
);
2708 TRACE_LDR("LdrGetProcedureAddress by ORDINAL - %d\n", Ordinal
);
2711 DPRINT("LdrGetProcedureAddress (BaseAddress %p Name %Z Ordinal %lu ProcedureAddress %p)\n",
2712 BaseAddress
, Name
, Ordinal
, ProcedureAddress
);
2716 if (Name
&& Name
->Length
)
2719 *ProcedureAddress
= LdrGetExportByName(BaseAddress
, (PUCHAR
)Name
->Buffer
, 0xffff);
2720 if (*ProcedureAddress
!= NULL
)
2722 Status
= STATUS_SUCCESS
;
2724 DPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name
);
2729 Ordinal
&= 0x0000FFFF;
2730 *ProcedureAddress
= LdrGetExportByOrdinal(BaseAddress
, (WORD
)Ordinal
);
2731 if (*ProcedureAddress
)
2733 Status
= STATUS_SUCCESS
;
2735 DPRINT("LdrGetProcedureAddress: Can't resolve symbol @%lu\n", Ordinal
);
2738 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2740 Status
= STATUS_DLL_NOT_FOUND
;
2747 /**********************************************************************
2752 * Unload dll's which are no longer referenced from others dll's
2763 * The loader lock must be held on enty.
2766 LdrpDetachProcess(BOOLEAN UnloadAll
)
2768 PLIST_ENTRY ModuleListHead
;
2770 PLDR_DATA_TABLE_ENTRY Module
;
2771 static ULONG CallingCount
= 0;
2773 DPRINT("LdrpDetachProcess() called for %wZ\n",
2774 &ExeModule
->BaseDllName
);
2777 LdrpDllShutdownInProgress
= TRUE
;
2781 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2782 Entry
= ModuleListHead
->Blink
;
2783 while (Entry
!= ModuleListHead
)
2785 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2786 if (((UnloadAll
&& Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0) &&
2787 Module
->Flags
& LDRP_ENTRY_PROCESSED
&&
2788 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2790 Module
->Flags
|= LDRP_UNLOAD_IN_PROGRESS
;
2791 if (Module
== LdrpLastModule
)
2793 LdrpLastModule
= NULL
;
2795 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
)
2797 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
2798 &Module
->BaseDllName
, Module
->EntryPoint
);
2799 LdrpCallDllEntry(Module
, DLL_PROCESS_DETACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2803 TRACE_LDR("Unload %wZ\n", &Module
->BaseDllName
);
2805 Entry
= ModuleListHead
->Blink
;
2809 Entry
= Entry
->Blink
;
2813 if (CallingCount
== 1)
2815 Entry
= ModuleListHead
->Blink
;
2816 while (Entry
!= ModuleListHead
)
2818 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2819 Entry
= Entry
->Blink
;
2820 if (Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
&&
2821 ((UnloadAll
&& Module
->LoadCount
!= LDRP_PROCESS_CREATION_TIME
) || Module
->LoadCount
== 0))
2823 /* remove the module entry from the list */
2824 RemoveEntryList (&Module
->InLoadOrderLinks
);
2825 RemoveEntryList (&Module
->InInitializationOrderLinks
);
2827 NtUnmapViewOfSection (NtCurrentProcess (), Module
->DllBase
);
2828 NtClose (Module
->SectionPointer
);
2830 TRACE_LDR("%wZ unloaded\n", &Module
->BaseDllName
);
2832 RtlFreeUnicodeString (&Module
->FullDllName
);
2833 RtlFreeUnicodeString (&Module
->BaseDllName
);
2835 RtlFreeHeap (RtlGetProcessHeap (), 0, Module
);
2840 DPRINT("LdrpDetachProcess() done\n");
2843 /**********************************************************************
2848 * Initialize all dll's which are prepered for loading
2859 * The loader lock must be held on entry.
2863 LdrpAttachProcess(VOID
)
2865 PLIST_ENTRY ModuleListHead
;
2867 PLDR_DATA_TABLE_ENTRY Module
;
2869 NTSTATUS Status
= STATUS_SUCCESS
;
2871 DPRINT("LdrpAttachProcess() called for %wZ\n",
2872 &ExeModule
->BaseDllName
);
2874 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2875 Entry
= ModuleListHead
->Flink
;
2876 while (Entry
!= ModuleListHead
)
2878 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2879 if (!(Module
->Flags
& (LDRP_LOAD_IN_PROGRESS
|LDRP_UNLOAD_IN_PROGRESS
|LDRP_ENTRY_PROCESSED
)))
2881 Module
->Flags
|= LDRP_LOAD_IN_PROGRESS
;
2882 TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
2883 &Module
->BaseDllName
, Module
->EntryPoint
);
2884 Result
= LdrpCallDllEntry(Module
, DLL_PROCESS_ATTACH
, (PVOID
)(INT_PTR
)(Module
->LoadCount
== LDRP_PROCESS_CREATION_TIME
? 1 : 0));
2887 Status
= STATUS_DLL_INIT_FAILED
;
2890 if (Module
->Flags
& LDRP_IMAGE_DLL
&& Module
->EntryPoint
!= 0)
2892 Module
->Flags
|= LDRP_PROCESS_ATTACH_CALLED
|LDRP_ENTRY_PROCESSED
;
2896 Module
->Flags
|= LDRP_ENTRY_PROCESSED
;
2898 Module
->Flags
&= ~LDRP_LOAD_IN_PROGRESS
;
2900 Entry
= Entry
->Flink
;
2903 DPRINT("LdrpAttachProcess() done\n");
2912 RtlDllShutdownInProgress (VOID
)
2914 return LdrpDllShutdownInProgress
;
2921 LdrShutdownProcess (VOID
)
2923 LdrpDetachProcess(TRUE
);
2924 return STATUS_SUCCESS
;
2932 LdrpAttachThread (VOID
)
2934 PLIST_ENTRY ModuleListHead
;
2936 PLDR_DATA_TABLE_ENTRY Module
;
2939 DPRINT("LdrpAttachThread() called for %wZ\n",
2940 &ExeModule
->BaseDllName
);
2942 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2944 Status
= LdrpInitializeTlsForThread();
2946 if (NT_SUCCESS(Status
))
2948 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2949 Entry
= ModuleListHead
->Flink
;
2951 while (Entry
!= ModuleListHead
)
2953 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2954 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
2955 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
2956 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
2958 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
2959 &Module
->BaseDllName
, Module
->EntryPoint
);
2960 LdrpCallDllEntry(Module
, DLL_THREAD_ATTACH
, NULL
);
2962 Entry
= Entry
->Flink
;
2965 Entry
= NtCurrentPeb()->Ldr
->InLoadOrderModuleList
.Flink
;
2966 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
2967 LdrpTlsCallback(Module
, DLL_THREAD_ATTACH
);
2970 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
2972 DPRINT("LdrpAttachThread() done\n");
2982 LdrShutdownThread (VOID
)
2984 PLIST_ENTRY ModuleListHead
;
2986 PLDR_DATA_TABLE_ENTRY Module
;
2988 DPRINT("LdrShutdownThread() called for %wZ\n",
2989 &ExeModule
->BaseDllName
);
2991 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
2993 ModuleListHead
= &NtCurrentPeb()->Ldr
->InInitializationOrderModuleList
;
2994 Entry
= ModuleListHead
->Blink
;
2995 while (Entry
!= ModuleListHead
)
2997 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InInitializationOrderLinks
);
2999 if (Module
->Flags
& LDRP_PROCESS_ATTACH_CALLED
&&
3000 !(Module
->Flags
& LDRP_DONT_CALL_FOR_THREADS
) &&
3001 !(Module
->Flags
& LDRP_UNLOAD_IN_PROGRESS
))
3003 TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
3004 &Module
->BaseDllName
, Module
->EntryPoint
);
3005 LdrpCallDllEntry(Module
, DLL_THREAD_DETACH
, NULL
);
3007 Entry
= Entry
->Blink
;
3010 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
3014 RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer
);
3017 DPRINT("LdrShutdownThread() done\n");
3019 return STATUS_SUCCESS
;
3023 /***************************************************************************
3025 * LdrQueryProcessModuleInformation
3040 LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL
,
3041 IN ULONG Size OPTIONAL
,
3042 OUT PULONG ReturnedSize
)
3044 PLIST_ENTRY ModuleListHead
;
3046 PLDR_DATA_TABLE_ENTRY Module
;
3047 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
3048 NTSTATUS Status
= STATUS_SUCCESS
;
3049 ULONG UsedSize
= sizeof(ULONG
);
3050 ANSI_STRING AnsiString
;
3053 DPRINT("LdrQueryProcessModuleInformation() called\n");
3054 // FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
3055 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock
);
3057 if (ModuleInformation
== NULL
|| Size
== 0)
3059 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3063 ModuleInformation
->NumberOfModules
= 0;
3064 ModulePtr
= &ModuleInformation
->Modules
[0];
3065 Status
= STATUS_SUCCESS
;
3068 ModuleListHead
= &NtCurrentPeb()->Ldr
->InLoadOrderModuleList
;
3069 Entry
= ModuleListHead
->Flink
;
3071 while (Entry
!= ModuleListHead
)
3073 Module
= CONTAINING_RECORD(Entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
3075 DPRINT(" Module %wZ\n",
3076 &Module
->FullDllName
);
3078 if (UsedSize
> Size
)
3080 Status
= STATUS_INFO_LENGTH_MISMATCH
;
3082 else if (ModuleInformation
!= NULL
)
3084 ModulePtr
->Section
= 0;
3085 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
3086 ModulePtr
->ImageBase
= Module
->DllBase
;
3087 ModulePtr
->ImageSize
= Module
->SizeOfImage
;
3088 ModulePtr
->Flags
= Module
->Flags
;
3089 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
3090 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
3091 ModulePtr
->LoadCount
= Module
->LoadCount
;
3093 AnsiString
.Length
= 0;
3094 AnsiString
.MaximumLength
= 256;
3095 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
3096 RtlUnicodeStringToAnsiString(&AnsiString
,
3097 &Module
->FullDllName
,
3100 p
= strrchr(ModulePtr
->FullPathName
, '\\');
3102 ModulePtr
->OffsetToFileName
= p
- ModulePtr
->FullPathName
+ 1;
3104 ModulePtr
->OffsetToFileName
= 0;
3107 ModuleInformation
->NumberOfModules
++;
3109 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
3111 Entry
= Entry
->Flink
;
3114 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock
);
3116 if (ReturnedSize
!= 0)
3117 *ReturnedSize
= UsedSize
;
3119 DPRINT("LdrQueryProcessModuleInformation() done\n");
3126 LdrpCheckImageChecksum (IN PVOID BaseAddress
,
3129 PIMAGE_NT_HEADERS Header
;
3136 Header
= RtlImageNtHeader (BaseAddress
);
3140 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
3145 Ptr
= (PUSHORT
) BaseAddress
;
3146 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
3149 if (HIWORD(Sum
) != 0)
3151 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3158 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
3159 if (HIWORD(Sum
) != 0)
3161 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
3165 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
3167 /* Subtract image checksum from calculated checksum. */
3168 /* fix low word of checksum */
3169 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
3171 CalcSum
-= LOWORD(HeaderSum
);
3175 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
3178 /* fix high word of checksum */
3179 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
3181 CalcSum
-= HIWORD(HeaderSum
);
3185 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
3188 /* add file length */
3189 CalcSum
+= ImageSize
;
3191 return (BOOLEAN
)(CalcSum
== HeaderSum
);
3195 * Compute size of an image as it is actually present in virt memory
3196 * (i.e. excluding NEVER_LOAD sections)
3199 LdrpGetResidentSize(PIMAGE_NT_HEADERS NTHeaders
)
3201 PIMAGE_SECTION_HEADER SectionHeader
;
3202 unsigned SectionIndex
;
3205 SectionHeader
= (PIMAGE_SECTION_HEADER
)((char *) &NTHeaders
->OptionalHeader
3206 + NTHeaders
->FileHeader
.SizeOfOptionalHeader
);
3208 for (SectionIndex
= 0; SectionIndex
< NTHeaders
->FileHeader
.NumberOfSections
; SectionIndex
++)
3210 if (0 == (SectionHeader
->Characteristics
& IMAGE_SCN_LNK_REMOVE
)
3211 && ResidentSize
< SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
)
3213 ResidentSize
= SectionHeader
->VirtualAddress
+ SectionHeader
->Misc
.VirtualSize
;
3218 return ResidentSize
;
3222 /***************************************************************************
3224 * LdrVerifyImageMatchesChecksum
3239 LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle
,
3244 FILE_STANDARD_INFORMATION FileInfo
;
3245 IO_STATUS_BLOCK IoStatusBlock
;
3246 HANDLE SectionHandle
;
3252 DPRINT ("LdrVerifyImageMatchesChecksum() called\n");
3254 Status
= NtCreateSection (&SectionHandle
,
3261 if (!NT_SUCCESS(Status
))
3263 DPRINT1 ("NtCreateSection() failed (Status %lx)\n", Status
);
3269 Status
= NtMapViewOfSection (SectionHandle
,
3270 NtCurrentProcess (),
3279 if (!NT_SUCCESS(Status
))
3281 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3282 NtClose (SectionHandle
);
3286 Status
= NtQueryInformationFile (FileHandle
,
3289 sizeof (FILE_STANDARD_INFORMATION
),
3290 FileStandardInformation
);
3291 if (!NT_SUCCESS(Status
))
3293 DPRINT1 ("NtMapViewOfSection() failed (Status %lx)\n", Status
);
3294 NtUnmapViewOfSection (NtCurrentProcess (),
3296 NtClose (SectionHandle
);
3300 Result
= LdrpCheckImageChecksum (BaseAddress
,
3301 FileInfo
.EndOfFile
.u
.LowPart
);
3302 if (Result
== FALSE
)
3304 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
3307 NtUnmapViewOfSection (NtCurrentProcess (),
3310 NtClose (SectionHandle
);
3316 /***************************************************************************
3318 * LdrQueryImageFileExecutionOptions
3333 LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey
,
3334 IN PCWSTR ValueName
,
3337 IN ULONG BufferSize
,
3338 OUT PULONG ReturnedLength OPTIONAL
)
3340 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
3341 OBJECT_ATTRIBUTES ObjectAttributes
;
3342 UNICODE_STRING ValueNameString
;
3343 UNICODE_STRING KeyName
;
3344 WCHAR NameBuffer
[256];
3352 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
3353 Ptr
= wcsrchr (SubKey
->Buffer
, L
'\\');
3356 Ptr
= SubKey
->Buffer
;
3362 wcscat (NameBuffer
, Ptr
);
3363 RtlInitUnicodeString (&KeyName
,
3366 InitializeObjectAttributes (&ObjectAttributes
,
3368 OBJ_CASE_INSENSITIVE
,
3372 Status
= NtOpenKey (&KeyHandle
,
3375 if (!NT_SUCCESS(Status
))
3377 DPRINT ("NtOpenKey() failed (Status %lx)\n", Status
);
3381 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 32;
3382 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3385 if (KeyInfo
== NULL
)
3387 NtClose (KeyHandle
);
3388 return STATUS_INSUFFICIENT_RESOURCES
;
3391 RtlInitUnicodeString (&ValueNameString
,
3393 Status
= NtQueryValueKey (KeyHandle
,
3395 KeyValuePartialInformation
,
3399 if (Status
== STATUS_BUFFER_OVERFLOW
)
3401 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyInfo
->DataLength
;
3402 RtlFreeHeap (RtlGetProcessHeap(),
3405 KeyInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
3408 if (KeyInfo
== NULL
)
3410 NtClose (KeyHandle
);
3411 return STATUS_INSUFFICIENT_RESOURCES
;
3414 Status
= NtQueryValueKey (KeyHandle
,
3416 KeyValuePartialInformation
,
3421 NtClose (KeyHandle
);
3423 if (!NT_SUCCESS(Status
))
3425 if (KeyInfo
!= NULL
)
3427 RtlFreeHeap (RtlGetProcessHeap(),
3434 if (KeyInfo
->Type
!= Type
)
3436 RtlFreeHeap (RtlGetProcessHeap(),
3439 return STATUS_OBJECT_TYPE_MISMATCH
;
3442 ResultSize
= BufferSize
;
3443 if (ResultSize
< KeyInfo
->DataLength
)
3445 Status
= STATUS_BUFFER_OVERFLOW
;
3449 ResultSize
= KeyInfo
->DataLength
;
3451 RtlCopyMemory (Buffer
,
3455 RtlFreeHeap (RtlGetProcessHeap(),
3459 if (ReturnedLength
!= NULL
)
3461 *ReturnedLength
= ResultSize
;
3468 PIMAGE_BASE_RELOCATION NTAPI
3469 LdrProcessRelocationBlock(IN ULONG_PTR Address
,
3471 IN PUSHORT TypeOffset
,
3480 for (i
= 0; i
< Count
; i
++)
3482 Offset
= *TypeOffset
& 0xFFF;
3483 Type
= *TypeOffset
>> 12;
3487 case IMAGE_REL_BASED_ABSOLUTE
:
3490 case IMAGE_REL_BASED_HIGH
:
3491 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3492 *ShortPtr
+= HIWORD(Delta
);
3495 case IMAGE_REL_BASED_LOW
:
3496 ShortPtr
= (PUSHORT
)((ULONG_PTR
)Address
+ Offset
);
3497 *ShortPtr
+= LOWORD(Delta
);
3500 case IMAGE_REL_BASED_HIGHLOW
:
3501 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3505 case IMAGE_REL_BASED_DIR64
:
3506 LongPtr
= (PULONG
)((ULONG_PTR
)Address
+ Offset
);
3511 case IMAGE_REL_BASED_HIGHADJ
:
3512 case IMAGE_REL_BASED_MIPS_JMPADDR
:
3514 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
3521 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
3526 LdrLockLoaderLock(IN ULONG Flags
,
3527 OUT PULONG Disposition OPTIONAL
,
3528 OUT PULONG Cookie OPTIONAL
)
3532 BOOLEAN CookieSet
= FALSE
;
3534 if ((Flags
!= 0x01) && (Flags
!= 0x02))
3535 return STATUS_INVALID_PARAMETER_1
;
3537 if (!Cookie
) return STATUS_INVALID_PARAMETER_3
;
3539 /* Set some defaults for failure while verifying params */
3544 if (Disposition
) *Disposition
= 0;
3546 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
3549 Status
= STATUS_INVALID_PARAMETER_3
;
3551 Status
= STATUS_INVALID_PARAMETER_2
;
3557 DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
3558 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
3559 Status
= STATUS_SUCCESS
;
3564 if (!Disposition
) return STATUS_INVALID_PARAMETER_2
;
3566 Ret
= RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock
);
3569 *Disposition
= 0x01;
3571 *Disposition
= 0x02;
3573 Status
= STATUS_SUCCESS
;
3576 /* FIXME: Cookie is based on part of the thread id */
3577 *Cookie
= (ULONG_PTR
)NtCurrentTeb()->RealClientId
.UniqueThread
;
3583 LdrUnlockLoaderLock(IN ULONG Flags
,
3584 IN ULONG Cookie OPTIONAL
)
3587 return STATUS_INVALID_PARAMETER_1
;
3589 if (Cookie
!= (ULONG_PTR
)NtCurrentTeb()->RealClientId
.UniqueThread
)
3590 return STATUS_INVALID_PARAMETER_2
;
3592 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock
);
3594 return STATUS_SUCCESS
;
3599 LdrUnloadAlternateResourceModule(IN PVOID BaseAddress
)