#define TRACE_LDR(...) if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { DbgPrint("(LDR:%s:%d) ",__FILE__,__LINE__); DbgPrint(__VA_ARGS__); }
#endif
-typedef struct _TLS_DATA
-{
- PVOID StartAddressOfRawData;
- DWORD TlsDataSize;
- DWORD TlsZeroSize;
- PIMAGE_TLS_CALLBACK *TlsAddressOfCallBacks;
- PLDR_DATA_TABLE_ENTRY Module;
-} TLS_DATA, *PTLS_DATA;
-
static BOOLEAN LdrpDllShutdownInProgress = FALSE;
-static PTLS_DATA LdrpTlsArray = NULL;
-static ULONG LdrpTlsCount = 0;
-static ULONG LdrpTlsSize = 0;
static HANDLE LdrpKnownDllsDirHandle = NULL;
static UNICODE_STRING LdrpKnownDllPath = {0, 0, NULL};
static PLDR_DATA_TABLE_ENTRY LdrpLastModule = NULL;
return LoadCount;
}
-static __inline VOID LdrpAcquireTlsSlot(PLDR_DATA_TABLE_ENTRY Module, ULONG Size, BOOLEAN Locked)
-{
- if (!Locked)
- {
- RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
- }
- Module->TlsIndex = (SHORT)LdrpTlsCount;
- LdrpTlsCount++;
- LdrpTlsSize += Size;
- if (!Locked)
- {
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
- }
-}
-
-static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReason)
-{
- PIMAGE_TLS_CALLBACK *TlsCallback;
- if (Module->TlsIndex != 0xFFFF && Module->LoadCount == LDRP_PROCESS_CREATION_TIME)
- {
- TlsCallback = LdrpTlsArray[Module->TlsIndex].TlsAddressOfCallBacks;
- if (TlsCallback)
- {
- while (*TlsCallback)
- {
- TRACE_LDR("%wZ - Calling tls callback at %x\n",
- &Module->BaseDllName, *TlsCallback);
- (*TlsCallback)(Module->DllBase, dwReason, NULL);
- TlsCallback++;
- }
- }
- }
-}
-
-static BOOLEAN LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module, DWORD dwReason, PVOID lpReserved)
-{
- if (!(Module->Flags & LDRP_IMAGE_DLL) ||
- Module->EntryPoint == 0)
- {
- return TRUE;
- }
- LdrpTlsCallback(Module, dwReason);
- return ((PDLLMAIN_FUNC)Module->EntryPoint)(Module->DllBase, dwReason, lpReserved);
-}
-
static PWSTR
LdrpQueryAppPaths(IN PCWSTR ImageName)
{
return Path;
}
-static NTSTATUS
-LdrpInitializeTlsForThread(VOID)
-{
- PVOID* TlsPointers;
- PTLS_DATA TlsInfo;
- PVOID TlsData;
- ULONG i;
- PTEB Teb = NtCurrentTeb();
-
- DPRINT("LdrpInitializeTlsForThread() called for %wZ\n", &ExeModule->BaseDllName);
-
- Teb->StaticUnicodeString.Length = 0;
- Teb->StaticUnicodeString.MaximumLength = sizeof(Teb->StaticUnicodeBuffer);
- Teb->StaticUnicodeString.Buffer = Teb->StaticUnicodeBuffer;
-
- if (LdrpTlsCount > 0)
- {
- TlsPointers = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- LdrpTlsCount * sizeof(PVOID) + LdrpTlsSize);
- if (TlsPointers == NULL)
- {
- DPRINT1("failed to allocate thread tls data\n");
- return STATUS_NO_MEMORY;
- }
-
- TlsData = (PVOID)((ULONG_PTR)TlsPointers + LdrpTlsCount * sizeof(PVOID));
- Teb->ThreadLocalStoragePointer = TlsPointers;
-
- TlsInfo = LdrpTlsArray;
- for (i = 0; i < LdrpTlsCount; i++, TlsInfo++)
- {
- TRACE_LDR("Initialize tls data for %wZ\n", &TlsInfo->Module->BaseDllName);
- TlsPointers[i] = TlsData;
- if (TlsInfo->TlsDataSize)
- {
- memcpy(TlsData, TlsInfo->StartAddressOfRawData, TlsInfo->TlsDataSize);
- TlsData = (PVOID)((ULONG_PTR)TlsData + TlsInfo->TlsDataSize);
- }
- if (TlsInfo->TlsZeroSize)
- {
- memset(TlsData, 0, TlsInfo->TlsZeroSize);
- TlsData = (PVOID)((ULONG_PTR)TlsData + TlsInfo->TlsZeroSize);
- }
- }
- }
-
- DPRINT("LdrpInitializeTlsForThread() done\n");
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-LdrpInitializeTlsForProccess(VOID)
-{
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- PIMAGE_TLS_DIRECTORY TlsDirectory;
- PTLS_DATA TlsData;
- ULONG Size;
-
- DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule->BaseDllName);
-
- if (LdrpTlsCount > 0)
- {
- LdrpTlsArray = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- LdrpTlsCount * sizeof(TLS_DATA));
- if (LdrpTlsArray == NULL)
- {
- DPRINT1("Failed to allocate global tls data\n");
- return STATUS_NO_MEMORY;
- }
-
- ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- if (Module->LoadCount == LDRP_PROCESS_CREATION_TIME &&
- Module->TlsIndex != 0xFFFF)
- {
- TlsDirectory = (PIMAGE_TLS_DIRECTORY)
- RtlImageDirectoryEntryToData(Module->DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_TLS,
- &Size);
- ASSERT(Module->TlsIndex < LdrpTlsCount);
- TlsData = &LdrpTlsArray[Module->TlsIndex];
- TlsData->StartAddressOfRawData = (PVOID)TlsDirectory->StartAddressOfRawData;
- TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
- TlsData->TlsZeroSize = TlsDirectory->SizeOfZeroFill;
- if (TlsDirectory->AddressOfCallBacks)
- TlsData->TlsAddressOfCallBacks = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks;
- else
- TlsData->TlsAddressOfCallBacks = NULL;
- TlsData->Module = Module;
-#if 0
- DbgPrint("TLS directory for %wZ\n", &Module->BaseDllName);
- DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory->StartAddressOfRawData);
- DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory->EndAddressOfRawData);
- DbgPrint("SizeOfRawData: %d\n", TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
- DbgPrint("AddressOfIndex: %x\n", TlsDirectory->AddressOfIndex);
- DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory->AddressOfCallBacks);
- DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory->SizeOfZeroFill);
- DbgPrint("Characteristics: %x\n", TlsDirectory->Characteristics);
-#endif
- /*
- * FIXME:
- * Is this region allways writable ?
- */
- *(PULONG)TlsDirectory->AddressOfIndex = Module->TlsIndex;
- }
- Entry = Entry->Flink;
- }
- }
-
- DPRINT("LdrpInitializeTlsForProccess() done\n");
- return STATUS_SUCCESS;
-}
-
VOID
LdrpInitLoader(VOID)
{
}
}
- if (TlsDirectory && TlsSize > 0)
- {
- LdrpAcquireTlsSlot(Module, TlsSize, FALSE);
- }
-
if (Module->EntryPointActivationContext) RtlDeactivateActivationContext( 0, cookie );
return STATUS_SUCCESS;
}
DPRINT("Fixup done\n");
RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- Status = LdrpInitializeTlsForProccess();
+ Status = LdrpInitializeTls();
if (NT_SUCCESS(Status))
{
Status = LdrpAttachProcess();
}
if (NT_SUCCESS(Status))
{
- LdrpTlsCallback(*Module, DLL_PROCESS_ATTACH);
+ LdrpTlsCallback((*Module)->DllBase, DLL_PROCESS_ATTACH);
}
RtlFreeUnicodeString (&(*Module)->FullDllName);
RtlFreeUnicodeString (&(*Module)->BaseDllName);
RemoveEntryList (&(*Module)->InLoadOrderLinks);
- RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
return Status;
}
{
TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
&Module->BaseDllName, Module->EntryPoint);
- LdrpCallDllEntry(Module,
- DLL_PROCESS_DETACH,
- (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+
+ /* Check if it has TLS */
+ if (Module->TlsIndex)
+ {
+ /* Call TLS */
+ LdrpTlsCallback(Module->DllBase, DLL_PROCESS_ATTACH);
+ }
+
+ if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
+ {
+ LdrpCallDllEntry(Module->EntryPoint,
+ Module->DllBase,
+ DLL_PROCESS_DETACH,
+ (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+ }
}
else
{
Module->Flags |= LDRP_LOAD_IN_PROGRESS;
TRACE_LDR("%wZ loaded - Calling init routine at %x for process attaching\n",
&Module->BaseDllName, Module->EntryPoint);
- Result = LdrpCallDllEntry(Module, DLL_PROCESS_ATTACH, (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+
+ /* Check if it has TLS */
+ if (Module->TlsIndex && FALSE/*Context*/)
+ {
+ /* Call TLS */
+ LdrpTlsCallback(Module->DllBase, DLL_PROCESS_ATTACH);
+ }
+
+ if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
+ Result = LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_PROCESS_ATTACH, (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
+ else
+ Result = TRUE;
+
if (!Result)
{
Status = STATUS_DLL_INIT_FAILED;
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
- Status = LdrpInitializeTlsForThread();
+ Status = LdrpAllocateTls();
if (NT_SUCCESS(Status))
{
{
TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
&Module->BaseDllName, Module->EntryPoint);
- LdrpCallDllEntry(Module, DLL_THREAD_ATTACH, NULL);
+
+ /* Check if it has TLS */
+ if (Module->TlsIndex)
+ {
+ /* Call TLS */
+ LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
+ }
+
+ if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
+ LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_ATTACH, NULL);
}
Entry = Entry->Flink;
}
Entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- LdrpTlsCallback(Module, DLL_THREAD_ATTACH);
+ LdrpTlsCallback(Module->DllBase, DLL_THREAD_ATTACH);
}
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
{
TRACE_LDR("%wZ - Calling entry point at %x for thread detaching\n",
&Module->BaseDllName, Module->EntryPoint);
- LdrpCallDllEntry(Module, DLL_THREAD_DETACH, NULL);
+ /* Check if it has TLS */
+ if (Module->TlsIndex)
+ {
+ /* Call TLS */
+ LdrpTlsCallback(Module->DllBase, DLL_THREAD_DETACH);
+ }
+
+ if ((Module->Flags & LDRP_IMAGE_DLL) && Module->EntryPoint)
+ LdrpCallDllEntry(Module->EntryPoint, Module->DllBase, DLL_THREAD_DETACH, NULL);
}
Entry = Entry->Blink;
}
+ /* Free TLS */
+ LdrpFreeTls();
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
- if (LdrpTlsArray)
- {
- RtlFreeHeap (RtlGetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer);
- }
-
DPRINT("LdrShutdownThread() done\n");
return STATUS_SUCCESS;
return Status;
}
-
-/***************************************************************************
- * NAME EXPORTED
- * LdrQueryImageFileExecutionOptions
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrQueryImageFileExecutionOptions(IN PUNICODE_STRING SubKey,
- IN PCWSTR ValueName,
- IN ULONG Type,
- OUT PVOID Buffer,
- IN ULONG BufferSize,
- OUT PULONG ReturnedLength OPTIONAL)
-{
- PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
- CHAR KeyInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 32];
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING ValueNameString;
- UNICODE_STRING KeyName;
- WCHAR NameBuffer[256];
- HANDLE KeyHandle;
- ULONG KeyInfoSize;
- ULONG ResultSize;
- PWCHAR Ptr;
- NTSTATUS Status;
-
- wcscpy (NameBuffer,
- L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\");
- Ptr = wcsrchr (SubKey->Buffer, L'\\');
- if (Ptr == NULL)
- {
- Ptr = SubKey->Buffer;
- }
- else
- {
- Ptr++;
- }
- wcscat (NameBuffer, Ptr);
- RtlInitUnicodeString (&KeyName,
- NameBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenKey(&KeyHandle,
- KEY_READ,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- DPRINT ("NtOpenKey() failed (Status %lx)\n", Status);
- return Status;
- }
-
- KeyInfoSize = sizeof(KeyInfoBuffer);
- KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfoBuffer;
-
- RtlInitUnicodeString(&ValueNameString,
- (PWSTR)ValueName);
- Status = NtQueryValueKey(KeyHandle,
- &ValueNameString,
- KeyValuePartialInformation,
- KeyInfo,
- KeyInfoSize,
- &ResultSize);
- if (Status == STATUS_BUFFER_OVERFLOW)
- {
- /* We can allocate only if there is a process heap already */
- if (!RtlGetProcessHeap())
- {
- NtClose (KeyHandle);
- return STATUS_NO_MEMORY;
- }
- KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyInfo->DataLength;
- KeyInfo = RtlAllocateHeap (RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- KeyInfoSize);
- if (KeyInfo == NULL)
- {
- NtClose (KeyHandle);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- Status = NtQueryValueKey (KeyHandle,
- &ValueNameString,
- KeyValuePartialInformation,
- KeyInfo,
- KeyInfoSize,
- &ResultSize);
- }
- NtClose (KeyHandle);
-
- if (!NT_SUCCESS(Status))
- {
- if ((PCHAR)KeyInfo != KeyInfoBuffer)
- {
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
- }
- return Status;
- }
-
- if (KeyInfo->Type != Type)
- {
- if ((PCHAR)KeyInfo != KeyInfoBuffer)
- {
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
- }
- return STATUS_OBJECT_TYPE_MISMATCH;
- }
-
- ResultSize = BufferSize;
- if (ResultSize < KeyInfo->DataLength)
- {
- Status = STATUS_BUFFER_OVERFLOW;
- }
- else
- {
- ResultSize = KeyInfo->DataLength;
- }
- RtlCopyMemory (Buffer,
- &KeyInfo->Data,
- ResultSize);
-
- if ((PCHAR)KeyInfo != KeyInfoBuffer)
- {
- RtlFreeHeap (RtlGetProcessHeap(),
- 0,
- KeyInfo);
- }
-
- if (ReturnedLength != NULL)
- {
- *ReturnedLength = ResultSize;
- }
-
- return Status;
-}
-
-
PIMAGE_BASE_RELOCATION
NTAPI
LdrProcessRelocationBlock(
return LdrProcessRelocationBlockLongLong(Address, Count, TypeOffset, Delta);
}
-NTSTATUS
-NTAPI
-LdrLockLoaderLock(IN ULONG Flags,
- OUT PULONG Disposition OPTIONAL,
- OUT PULONG Cookie OPTIONAL)
-{
- NTSTATUS Status;
- BOOLEAN Ret;
- BOOLEAN CookieSet = FALSE;
-
- if ((Flags != 0x01) && (Flags != 0x02))
- return STATUS_INVALID_PARAMETER_1;
-
- if (!Cookie) return STATUS_INVALID_PARAMETER_3;
-
- /* Set some defaults for failure while verifying params */
- _SEH2_TRY
- {
- *Cookie = 0;
- CookieSet = TRUE;
- if (Disposition) *Disposition = 0;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- if (CookieSet)
- Status = STATUS_INVALID_PARAMETER_3;
- else
- Status = STATUS_INVALID_PARAMETER_2;
- }
- _SEH2_END;
-
- if (Flags == 0x01)
- {
- DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
- RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
- Status = STATUS_SUCCESS;
-
- }
- else
- {
- if (!Disposition) return STATUS_INVALID_PARAMETER_2;
-
- Ret = RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock);
-
- if (Ret)
- *Disposition = 0x01;
- else
- *Disposition = 0x02;
-
- Status = STATUS_SUCCESS;
- }
-
- /* FIXME: Cookie is based on part of the thread id */
- *Cookie = (ULONG)NtCurrentTeb()->RealClientId.UniqueThread;
- return Status;
-}
-
-NTSTATUS
-NTAPI
-LdrUnlockLoaderLock(IN ULONG Flags,
- IN ULONG Cookie OPTIONAL)
-{
- if (Flags != 0x01)
- return STATUS_INVALID_PARAMETER_1;
-
- if (Cookie != (ULONG)NtCurrentTeb()->RealClientId.UniqueThread)
- return STATUS_INVALID_PARAMETER_2;
-
- RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
-
- return STATUS_SUCCESS;
-}
-
BOOLEAN
NTAPI
LdrUnloadAlternateResourceModule(IN PVOID BaseAddress)