[NTDLL/LDR]
[reactos.git] / reactos / dll / ntdll / ldr / utils.c
index 4482f93..cd7c7d6 100644 (file)
 #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;
@@ -118,51 +106,6 @@ static __inline LONG LdrpIncrementLoadCount(PLDR_DATA_TABLE_ENTRY Module, BOOLEA
     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)
 {
@@ -269,127 +212,6 @@ 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)
 {
@@ -2093,11 +1915,6 @@ Success:
         }
     }
 
-    if (TlsDirectory && TlsSize > 0)
-    {
-        LdrpAcquireTlsSlot(Module, TlsSize, FALSE);
-    }
-
     if (Module->EntryPointActivationContext) RtlDeactivateActivationContext( 0, cookie );
 
     return STATUS_SUCCESS;
@@ -2216,14 +2033,14 @@ PEPFUNC LdrPEStartup (PVOID  ImageBase,
     }
     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);
     }
 
 
@@ -2394,7 +2211,6 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
             RtlFreeUnicodeString (&(*Module)->FullDllName);
             RtlFreeUnicodeString (&(*Module)->BaseDllName);
             RemoveEntryList (&(*Module)->InLoadOrderLinks);
-            RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
             return Status;
         }
 
@@ -2769,9 +2585,21 @@ LdrpDetachProcess(BOOLEAN UnloadAll)
             {
                 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
             {
@@ -2856,7 +2684,19 @@ LdrpAttachProcess(VOID)
             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;
@@ -2916,7 +2756,7 @@ LdrpAttachThread (VOID)
 
     RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
 
-    Status = LdrpInitializeTlsForThread();
+    Status = LdrpAllocateTls();
 
     if (NT_SUCCESS(Status))
     {
@@ -2932,14 +2772,23 @@ LdrpAttachThread (VOID)
             {
                 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);
@@ -2977,18 +2826,23 @@ LdrShutdownThread (VOID)
         {
             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;
@@ -3289,162 +3143,6 @@ LdrVerifyImageMatchesChecksum (IN HANDLE FileHandle,
     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(
@@ -3456,79 +3154,6 @@ 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)