[ros-diffs] [fireball] 51065: [NTDLL/LDR] - Rewrite LdrQueryProcessModuleInformation. - Start committing PE loader related code (quite a lot of it, and still not all parts yet), unused right now so won't break...

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Mar 16 14:22:16 UTC 2011


Author: fireball
Date: Wed Mar 16 14:22:15 2011
New Revision: 51065

URL: http://svn.reactos.org/svn/reactos?rev=51065&view=rev
Log:
[NTDLL/LDR]
- Rewrite LdrQueryProcessModuleInformation.
- Start committing PE loader related code (quite a lot of it, and still not all parts yet), unused right now so won't break anything.

Added:
    trunk/reactos/dll/ntdll/ldr/ldrpe.c   (with props)
Modified:
    trunk/reactos/dll/ntdll/include/ntdllp.h
    trunk/reactos/dll/ntdll/ldr/ldrapi.c
    trunk/reactos/dll/ntdll/ldr/ldrinit.c
    trunk/reactos/dll/ntdll/ldr/ldrutils.c
    trunk/reactos/dll/ntdll/ldr/utils.c
    trunk/reactos/dll/ntdll/ntdll.rbuild

Modified: trunk/reactos/dll/ntdll/include/ntdllp.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/include/ntdllp.h?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/include/ntdllp.h [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/include/ntdllp.h [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -23,14 +23,42 @@
 
 /* Global data */
 extern RTL_CRITICAL_SECTION LdrpLoaderLock;
+extern BOOLEAN LdrpInLdrInit;
 
 /* ldrinit.c */
+NTSTATUS NTAPI LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL);
 NTSTATUS NTAPI LdrpInitializeTls(VOID);
 NTSTATUS NTAPI LdrpAllocateTls(VOID);
 VOID NTAPI LdrpFreeTls(VOID);
 VOID NTAPI LdrpTlsCallback(PVOID BaseAddress, ULONG Reason);
 BOOLEAN NTAPI LdrpCallDllEntry(PDLLMAIN_FUNC EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
 
+/* ldrpe.c */
+NTSTATUS
+NTAPI
+LdrpSnapThunk(IN PVOID ExportBase,
+              IN PVOID ImportBase,
+              IN PIMAGE_THUNK_DATA OriginalThunk,
+              IN OUT PIMAGE_THUNK_DATA Thunk,
+              IN PIMAGE_EXPORT_DIRECTORY ExportEntry,
+              IN ULONG ExportSize,
+              IN BOOLEAN Static,
+              IN LPSTR DllName);
+
+/* ldrutils.c */
+NTSTATUS NTAPI
+LdrpGetProcedureAddress(IN PVOID BaseAddress,
+                        IN PANSI_STRING Name,
+                        IN ULONG Ordinal,
+                        OUT PVOID *ProcedureAddress,
+                        IN BOOLEAN ExecuteInit);
+NTSTATUS NTAPI
+LdrpLoadDll(IN BOOLEAN Redirected,
+            IN PWSTR DllPath OPTIONAL,
+            IN PULONG DllCharacteristics OPTIONAL,
+            IN PUNICODE_STRING DllName,
+            OUT PVOID *BaseAddress,
+            IN BOOLEAN CallInit);
 
 /* FIXME: Cleanup this mess */
 typedef NTSTATUS (NTAPI *PEPFUNC)(PPEB);

Modified: trunk/reactos/dll/ntdll/ldr/ldrapi.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrapi.c?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrapi.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/ldrapi.c [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -109,8 +109,7 @@
 {
     LONG OldCount;
     NTSTATUS Status = STATUS_SUCCESS;
-    BOOLEAN InInit = FALSE; // FIXME
-    //BOOLEAN InInit = LdrpInLdrInit;
+    BOOLEAN InInit = LdrpInLdrInit;
 
     DPRINT("LdrLockLoaderLock(%x %p %p)\n", Flags, Result, Cookie);
 
@@ -378,4 +377,157 @@
     return !Result ? STATUS_IMAGE_CHECKSUM_MISMATCH : Status;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrGetProcedureAddress_(IN PVOID BaseAddress,
+                       IN PANSI_STRING Name,
+                       IN ULONG Ordinal,
+                       OUT PVOID *ProcedureAddress)
+{
+    /* Call the internal routine and tell it to execute DllInit */
+    return LdrpGetProcedureAddress(BaseAddress, Name, Ordinal, ProcedureAddress, TRUE);
+}
+
+
+NTSTATUS
+NTAPI
+LdrQueryProcessModuleInformationEx(IN ULONG ProcessId,
+                                   IN ULONG Reserved,
+                                   IN PRTL_PROCESS_MODULES ModuleInformation,
+                                   IN ULONG Size,
+                                   OUT PULONG ReturnedSize OPTIONAL)
+{
+    PLIST_ENTRY ModuleListHead, InitListHead;
+    PLIST_ENTRY Entry, InitEntry;
+    PLDR_DATA_TABLE_ENTRY Module, InitModule;
+    PRTL_PROCESS_MODULE_INFORMATION ModulePtr = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG UsedSize = sizeof(ULONG);
+    ANSI_STRING AnsiString;
+    PCHAR p;
+
+    DPRINT("LdrQueryProcessModuleInformation() called\n");
+
+    /* Acquire loader lock */
+    RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
+
+    /* Check if we were given enough space */
+    if (Size < UsedSize)
+    {
+        Status = STATUS_INFO_LENGTH_MISMATCH;
+    }
+    else
+    {
+        ModuleInformation->NumberOfModules = 0;
+        ModulePtr = &ModuleInformation->Modules[0];
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Traverse the list of modules */
+    _SEH2_TRY
+    {
+        ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+        Entry = ModuleListHead->Flink;
+
+        while (Entry != ModuleListHead)
+        {
+            Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+
+            DPRINT("  Module %wZ\n", &Module->FullDllName);
+
+            /* Increase the used size */
+            UsedSize += sizeof(RTL_PROCESS_MODULE_INFORMATION);
+
+            if (UsedSize > Size)
+            {
+                Status = STATUS_INFO_LENGTH_MISMATCH;
+            }
+            else
+            {
+                ModulePtr->ImageBase = Module->DllBase;
+                ModulePtr->ImageSize = Module->SizeOfImage;
+                ModulePtr->Flags = Module->Flags;
+                ModulePtr->LoadCount = Module->LoadCount;
+                ModulePtr->MappedBase = NULL;
+                ModulePtr->InitOrderIndex = 0;
+                ModulePtr->LoadOrderIndex = ModuleInformation->NumberOfModules;
+
+                /* Now get init order index by traversing init list */
+                InitListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
+                InitEntry = InitListHead->Flink;
+
+                while (InitEntry != InitListHead)
+                {
+                    InitModule = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+
+                    /* Increase the index */
+                    ModulePtr->InitOrderIndex++;
+
+                    /* Quit the loop if our module is found */
+                    if (InitModule == Module) break;
+
+                    /* Advance to the next entry */
+                    InitEntry = InitEntry->Flink;
+                }
+
+                /* Prepare ANSI string with the module's name */
+                AnsiString.Length = 0;
+                AnsiString.MaximumLength = sizeof(ModulePtr->FullPathName);
+                AnsiString.Buffer = ModulePtr->FullPathName;
+                RtlUnicodeStringToAnsiString(&AnsiString,
+                                             &Module->FullDllName,
+                                             FALSE);
+
+                /* Calculate OffsetToFileName field */
+                p = strrchr(ModulePtr->FullPathName, '\\');
+                if (p != NULL)
+                    ModulePtr->OffsetToFileName = p - ModulePtr->FullPathName + 1;
+                else
+                    ModulePtr->OffsetToFileName = 0;
+
+                /* Advance to the next module in the output list */
+                ModulePtr++;
+
+                /* Increase number of modules */
+                if (ModuleInformation)
+                    ModuleInformation->NumberOfModules++;
+            }
+
+            /* Go to the next entry in the modules list */
+            Entry = Entry->Flink;
+        }
+
+        /* Set returned size if it was provided */
+        if (ReturnedSize)
+            *ReturnedSize = UsedSize;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Ignoring the exception */
+    } _SEH2_END;
+
+    /* Release the lock */
+    RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
+
+    DPRINT("LdrQueryProcessModuleInformation() done\n");
+
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation,
+                                 IN ULONG Size,
+                                 OUT PULONG ReturnedSize OPTIONAL)
+{
+    /* Call Ex version of the API */
+    return LdrQueryProcessModuleInformationEx(0, 0, ModuleInformation, Size, ReturnedSize);
+}
+
 /* EOF */

Modified: trunk/reactos/dll/ntdll/ldr/ldrinit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrinit.c?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/ldrinit.c [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -19,6 +19,10 @@
 HKEY Wow64ExecOptionsKey;
 UNICODE_STRING ImageExecOptionsString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options");
 UNICODE_STRING Wow64OptionsString = RTL_CONSTANT_STRING(L"");
+
+BOOLEAN LdrpInLdrInit;
+
+PLDR_DATA_TABLE_ENTRY LdrpImageEntry;
 
 //RTL_BITMAP TlsBitMap;
 //RTL_BITMAP TlsExpansionBitMap;
@@ -331,6 +335,267 @@
 
 NTSTATUS
 NTAPI
+LdrpRunInitializeRoutines(IN PCONTEXT Context OPTIONAL)
+{
+#if 0
+    PLDR_DATA_TABLE_ENTRY LocalArray[16];
+    PLIST_ENTRY ListHead;
+    PLIST_ENTRY NextEntry;
+    PLDR_DATA_TABLE_ENTRY LdrEntry, *LdrRootEntry, OldInitializer;
+    PVOID EntryPoint;
+    ULONG Count, i;
+    //ULONG BreakOnInit;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PPEB Peb = NtCurrentPeb();
+    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx;
+    ULONG BreakOnDllLoad;
+    PTEB OldTldTeb;
+
+    DPRINT1("LdrpRunInitializeRoutines() called for %wZ\n", &LdrpImageEntry->BaseDllName);
+
+    /* Check the Loader Lock */
+    LdrpEnsureLoaderLockIsHeld();
+
+     /* Get the number of entries to call */
+    if ((Count = LdrpClearLoadInProgress()))
+    {
+        /* Check if we can use our local buffer */
+        if (Count > 16)
+        {
+            /* Allocate space for all the entries */
+            LdrRootEntry = RtlAllocateHeap(RtlGetProcessHeap(),
+                                           0,
+                                           Count * sizeof(LdrRootEntry));
+            if (!LdrRootEntry) return STATUS_NO_MEMORY;
+        }
+        else
+        {
+            /* Use our local array */
+            LdrRootEntry = LocalArray;
+        }
+    }
+    else
+    {
+        /* Don't need one */
+        LdrRootEntry = NULL;
+    }
+
+    /* Show debug message */
+    if (ShowSnaps)
+    {
+        DPRINT1("[%x,%x] LDR: Real INIT LIST for Process %wZ pid %u %0x%x\n",
+                NtCurrentTeb()->RealClientId.UniqueThread,
+                NtCurrentTeb()->RealClientId.UniqueProcess,
+                Peb->ProcessParameters->ImagePathName,
+                NtCurrentTeb()->RealClientId.UniqueThread,
+                NtCurrentTeb()->RealClientId.UniqueProcess);
+    }
+
+    /* Loop in order */
+    ListHead = &Peb->Ldr->InInitializationOrderModuleList;
+    NextEntry = ListHead->Flink;
+    i = 0;
+    while (NextEntry != ListHead)
+    {
+        /* Get the Data Entry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+
+        /* Check if we have a Root Entry */
+        if (LdrRootEntry)
+        {
+            /* Check flags */
+            if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
+            {
+                /* Setup the Cookie for the DLL */
+                //LdrpInitSecurityCookie(LdrEntry);
+                UNIMPLEMENTED;
+
+                /* Check for valid entrypoint */
+                if (LdrEntry->EntryPoint)
+                {
+                    /* Write in array */
+                    LdrRootEntry[i] = LdrEntry;
+
+                    /* Display debug message */
+                    if (ShowSnaps)
+                    {
+                        DPRINT1("[%x,%x] LDR: %wZ init routine %p\n",
+                                NtCurrentTeb()->RealClientId.UniqueThread,
+                                NtCurrentTeb()->RealClientId.UniqueProcess,
+                                &LdrEntry->FullDllName,
+                                LdrEntry->EntryPoint);
+                    }
+                    i++;
+                }
+            }
+        }
+
+        /* Set the flag */
+        LdrEntry->Flags |= LDRP_ENTRY_PROCESSED;
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* If we got a context, then we have to call Kernel32 for TS support */
+    if (Context)
+    {
+        /* Check if we have one */
+        //if (Kernel32ProcessInitPostImportfunction)
+        //{
+            /* Call it */
+            //Kernel32ProcessInitPostImportfunction();
+        //}
+
+        /* Clear it */
+        //Kernel32ProcessInitPostImportfunction = NULL;
+        UNIMPLEMENTED;
+    }
+
+    /* No root entry? return */
+    if (!LdrRootEntry) return STATUS_SUCCESS;
+
+    /* Set the TLD TEB */
+    OldTldTeb = LdrpTopLevelDllBeingLoadedTeb;
+    LdrpTopLevelDllBeingLoadedTeb = NtCurrentTeb();
+
+    /* Loop */
+    i = 0;
+    while (i < Count)
+    {
+        /* Get an entry */
+        LdrEntry = LdrRootEntry[i];
+
+        /* FIXME: Verifiy NX Compat */
+
+        /* Move to next entry */
+        i++;
+
+        /* Get its entrypoint */
+        EntryPoint = LdrEntry->EntryPoint;
+
+        /* Are we being debugged? */
+        BreakOnDllLoad = 0;
+        if (Peb->BeingDebugged || Peb->ReadImageFileExecOptions)
+        {
+            /* Check if we should break on load */
+            Status = LdrQueryImageFileExecutionOptions(&LdrEntry->BaseDllName,
+                                                       L"BreakOnDllLoad",
+                                                       REG_DWORD,
+                                                       &BreakOnDllLoad,
+                                                       sizeof(ULONG),
+                                                       NULL);
+            if (!NT_SUCCESS(Status)) BreakOnDllLoad = 0;
+        }
+
+        /* Break if aksed */
+        if (BreakOnDllLoad)
+        {
+            /* Check if we should show a message */
+            if (ShowSnaps)
+            {
+                DPRINT1("LDR: %wZ loaded.", &LdrEntry->BaseDllName);
+                DPRINT1(" - About to call init routine at %lx\n", EntryPoint);
+            }
+
+            /* Break in debugger */
+            DbgBreakPoint();
+        }
+
+        /* Make sure we have an entrypoint */
+        if (EntryPoint)
+        {
+            /* Save the old Dll Initializer and write the current one */
+            OldInitializer = LdrpCurrentDllInitializer;
+            LdrpCurrentDllInitializer = LdrEntry;
+
+            /* Set up the Act Ctx */
+            ActCtx.Size = sizeof(ActCtx);
+            ActCtx.Frame.Flags = ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID;
+            RtlZeroMemory(&ActCtx, sizeof(ActCtx));
+
+            /* Activate the ActCtx */
+            RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                                   LdrEntry->EntryPointActivationContext);
+
+            /* Check if it has TLS */
+            if (LdrEntry->TlsIndex && Context)
+            {
+                /* Call TLS */
+                LdrpTlsCallback(LdrEntry->DllBase, DLL_PROCESS_ATTACH);
+            }
+
+            /* Call the Entrypoint */
+            DPRINT1("%wZ - Calling entry point at %x for thread attaching\n",
+                    &LdrEntry->BaseDllName, EntryPoint);
+            LdrpCallDllEntry(EntryPoint,
+                             LdrEntry->DllBase,
+                             DLL_PROCESS_ATTACH,
+                             Context);
+
+            /* Deactivate the ActCtx */
+            RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+
+            /* Save the Current DLL Initializer */
+            LdrpCurrentDllInitializer = OldInitializer;
+
+            /* Mark the entry as processed */
+            LdrEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED;
+        }
+    }
+
+    /* Loop in order */
+    ListHead = &Peb->Ldr->InInitializationOrderModuleList;
+    NextEntry = NextEntry->Flink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the Data Entrry */
+        LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
+
+        /* FIXME: Verify NX Compat */
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Check for TLS */
+    if (LdrpImageHasTls && Context)
+    {
+        /* Set up the Act Ctx */
+        ActCtx.Size = sizeof(ActCtx);
+        ActCtx.Frame.Flags = ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID;
+        RtlZeroMemory(&ActCtx, sizeof(ActCtx));
+
+        /* Activate the ActCtx */
+        RtlActivateActivationContextUnsafeFast(&ActCtx,
+                                               LdrpImageEntry->EntryPointActivationContext);
+
+        /* Do TLS callbacks */
+        LdrpTlsCallback(Peb->ImageBaseAddress, DLL_PROCESS_DETACH);
+
+        /* Deactivate the ActCtx */
+        RtlDeactivateActivationContextUnsafeFast(&ActCtx);
+    }
+
+    /* Restore old TEB */
+    LdrpTopLevelDllBeingLoadedTeb = OldTldTeb;
+
+    /* Check if the array is in the heap */
+    if (LdrRootEntry != LocalArray)
+    {
+        /* Free the array */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, LdrRootEntry);
+    }
+
+    /* Return to caller */
+    DPRINT("LdrpAttachProcess() done\n");
+    return Status;
+#else
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+#endif
+}
+
+NTSTATUS
+NTAPI
 LdrpInitializeTls(VOID)
 {
     PLIST_ENTRY NextEntry, ListHead;

Added: trunk/reactos/dll/ntdll/ldr/ldrpe.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrpe.c?rev=51065&view=auto
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrpe.c (added)
+++ trunk/reactos/dll/ntdll/ldr/ldrpe.c [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -1,0 +1,273 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            lib/ntdll/ldr/ldrpe.c
+ * PURPOSE:         Loader Functions dealing low-level PE Format structures
+ * PROGRAMMERS:     Alex Ionescu (alex at relsoft.net)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ntdll.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+ULONG LdrpFatalHardErrorCount;
+PVOID LdrpManifestProberRoutine;
+
+/* PROTOTYPES ****************************************************************/
+
+#define IMAGE_REL_BASED_HIGH3ADJ 11
+
+NTSTATUS
+NTAPI
+LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL,
+                     IN LPSTR ImportName,
+                     IN PVOID DllBase,
+                     OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry,
+                     OUT PBOOLEAN Existing);
+
+/* FUNCTIONS *****************************************************************/
+
+USHORT NTAPI
+LdrpNameToOrdinal(LPSTR ImportName,
+                  ULONG NumberOfNames,
+                  PVOID ExportBase,
+                  PULONG NameTable,
+                  PUSHORT OrdinalTable)
+{
+    UNIMPLEMENTED;
+    return 0;
+}
+
+
+NTSTATUS
+NTAPI
+LdrpSnapThunk(IN PVOID ExportBase,
+              IN PVOID ImportBase,
+              IN PIMAGE_THUNK_DATA OriginalThunk,
+              IN OUT PIMAGE_THUNK_DATA Thunk,
+              IN PIMAGE_EXPORT_DIRECTORY ExportEntry,
+              IN ULONG ExportSize,
+              IN BOOLEAN Static,
+              IN LPSTR DllName)
+{
+    BOOLEAN IsOrdinal;
+    USHORT Ordinal;
+    ULONG OriginalOrdinal = 0;
+    PIMAGE_IMPORT_BY_NAME AddressOfData;
+    PULONG NameTable;
+    PUSHORT OrdinalTable;
+    LPSTR ImportName;
+    USHORT Hint;
+    NTSTATUS Status;
+    ULONG_PTR HardErrorParameters[3];
+    UNICODE_STRING HardErrorDllName, HardErrorEntryPointName;
+    ANSI_STRING TempString;
+    ULONG Mask;
+    ULONG Response;
+    PULONG AddressOfFunctions;
+    UNICODE_STRING TempUString;
+    ANSI_STRING ForwarderName;
+    PANSI_STRING ForwardName;
+    PVOID ForwarderHandle;
+    ULONG ForwardOrdinal;
+
+    /* Check if the snap is by ordinal */
+    if ((IsOrdinal = IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal)))
+    {
+        /* Get the ordinal number, and its normalized version */
+        OriginalOrdinal = IMAGE_ORDINAL(OriginalThunk->u1.Ordinal);
+        Ordinal = (USHORT)(OriginalOrdinal - ExportEntry->Base);
+    }
+    else
+    {
+        /* First get the data VA */
+        AddressOfData = (PIMAGE_IMPORT_BY_NAME)
+                        ((ULONG_PTR)ImportBase +
+                        ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xffffffff));
+
+        /* Get the name */
+        ImportName = (LPSTR)AddressOfData->Name;
+
+        /* Now get the VA of the Name and Ordinal Tables */
+        NameTable = (PULONG)((ULONG_PTR)ExportBase +
+                             (ULONG_PTR)ExportEntry->AddressOfNames);
+        OrdinalTable = (PUSHORT)((ULONG_PTR)ExportBase +
+                                 (ULONG_PTR)ExportEntry->AddressOfNameOrdinals);
+
+        /* Get the hint */
+        Hint = AddressOfData->Hint;
+
+        /* Try to get a match by using the hint */
+        if (((ULONG)Hint < ExportEntry->NumberOfNames) &&
+             (!strcmp(ImportName, ((LPSTR)((ULONG_PTR)ExportBase + NameTable[Hint])))))
+        {
+            /* We got a match, get the Ordinal from the hint */
+            Ordinal = OrdinalTable[Hint];
+        }
+        else
+        {
+            /* Well bummer, hint didn't work, do it the long way */
+            Ordinal = LdrpNameToOrdinal(ImportName,
+                                        ExportEntry->NumberOfNames,
+                                        ExportBase,
+                                        NameTable,
+                                        OrdinalTable);
+        }
+    }
+
+    /* Check if the ordinal is invalid */
+    if ((ULONG)Ordinal >= ExportEntry->NumberOfFunctions)
+    {
+FailurePath:
+        /* Is this a static snap? */
+        if (Static)
+        {
+            /* These are critical errors. Setup a string for the DLL name */
+            RtlInitAnsiString(&TempString, DllName ? DllName : "Unknown");
+            RtlAnsiStringToUnicodeString(&HardErrorDllName, &TempString, TRUE);
+
+            /* Set it as the parameter */
+            HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllName;
+            Mask = 2;
+
+            /* Check if we have an ordinal */
+            if (IsOrdinal)
+            {
+                /* Then set the ordinal as the 1st parameter */
+                HardErrorParameters[0] = OriginalOrdinal;
+            }
+            else
+            {
+                /* We don't, use the entrypoint. Set up a string for it */
+                RtlInitAnsiString(&TempString, ImportName);
+                RtlAnsiStringToUnicodeString(&HardErrorEntryPointName,
+                                             &TempString,
+                                             TRUE);
+
+                /* Set it as the parameter */
+                HardErrorParameters[0] = (ULONG_PTR)&HardErrorEntryPointName;
+                Mask = 3;
+            }
+
+            /* Raise the error */
+            NtRaiseHardError(IsOrdinal ? STATUS_ORDINAL_NOT_FOUND :
+                                         STATUS_ENTRYPOINT_NOT_FOUND,
+                             2,
+                             Mask,
+                             HardErrorParameters,
+                             OptionOk,
+                             &Response);
+
+            /* Increase the error count */
+            if (LdrpInLdrInit) LdrpFatalHardErrorCount++;
+
+            /* Free our string */
+            RtlFreeUnicodeString(&HardErrorDllName);
+            if (!IsOrdinal)
+            {
+                /* Free our second string. Return entrypoint error */
+                RtlFreeUnicodeString(&HardErrorEntryPointName);
+                RtlRaiseStatus(STATUS_ENTRYPOINT_NOT_FOUND);
+            }
+
+            /* Return ordinal error */
+            RtlRaiseStatus(STATUS_ORDINAL_NOT_FOUND);
+        }
+
+        /* Set this as a bad DLL */
+        Thunk->u1.Function = (ULONG_PTR)0xffbadd11;
+
+        /* Return the right error code */
+        Status = IsOrdinal ? STATUS_ORDINAL_NOT_FOUND :
+                             STATUS_ENTRYPOINT_NOT_FOUND;
+    }
+    else
+    {
+        /* The ordinal seems correct, get the AddressOfFunctions VA */
+        AddressOfFunctions = (PULONG)
+                             ((ULONG_PTR)ExportBase +
+                              (ULONG_PTR)ExportEntry->AddressOfFunctions);
+
+        /* Write the function pointer*/
+        Thunk->u1.Function = (ULONG_PTR)ExportBase + AddressOfFunctions[Ordinal];
+
+        /* Make sure it's within the exports */
+        if ((Thunk->u1.Function > (ULONG_PTR)ExportEntry) &&
+            (Thunk->u1.Function < ((ULONG_PTR)ExportEntry + ExportSize)))
+        {
+            /* Get the Import and Forwarder Names */
+            ImportName = (LPSTR)Thunk->u1.Function;
+            ForwarderName.Buffer = ImportName;
+            ForwarderName.Length = (USHORT)(strchr(ImportName, '.') - ImportName);
+            ForwarderName.MaximumLength = ForwarderName.Length;
+            Status = RtlAnsiStringToUnicodeString(&TempUString,
+                                                  &ForwarderName,
+                                                  TRUE);
+
+            /* Make sure the conversion was OK */
+            if (NT_SUCCESS(Status))
+            {
+                /* Load the forwarder, free the temp string */
+                Status = LdrpLoadDll(FALSE,
+                                     NULL,
+                                     NULL,
+                                     &TempUString,
+                                     &ForwarderHandle,
+                                     FALSE);
+                RtlFreeUnicodeString(&TempUString);
+            }
+
+            /* If the load or conversion failed, use the failure path */
+            if (!NT_SUCCESS(Status)) goto FailurePath;
+
+            /* Now set up a name for the actual forwarder dll */
+            RtlInitAnsiString(&ForwarderName,
+                              ImportName + ForwarderName.Length + sizeof(CHAR));
+
+            /* Check if it's an ordinal forward */
+            if ((ForwarderName.Length > 1) && (*ForwarderName.Buffer == '#'))
+            {
+                /* We don't have an actual function name */
+                ForwardName = NULL;
+
+                /* Convert the string into an ordinal */
+                Status = RtlCharToInteger(ForwarderName.Buffer + sizeof(CHAR),
+                                          0,
+                                          &ForwardOrdinal);
+
+                /* If this fails, then error out */
+                if (!NT_SUCCESS(Status)) goto FailurePath;
+            }
+            else
+            {
+                /* Import by name */
+                ForwardName = &ForwarderName;
+            }
+
+            /* Get the pointer */
+            Status = LdrpGetProcedureAddress(ForwarderHandle,
+                                             ForwardName,
+                                             ForwardOrdinal,
+                                             (PVOID*)&Thunk->u1.Function,
+                                             FALSE);
+            /* If this fails, then error out */
+            if (!NT_SUCCESS(Status)) goto FailurePath;
+        }
+        else
+        {
+            /* It's not within the exports, let's hope it's valid */
+            if (!AddressOfFunctions[Ordinal]) goto FailurePath;
+        }
+
+        /* If we got here, then it's success */
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/* EOF */

Propchange: trunk/reactos/dll/ntdll/ldr/ldrpe.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/ntdll/ldr/ldrutils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/ldrutils.c?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/ldrutils.c [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -15,6 +15,8 @@
 
 /* GLOBALS *******************************************************************/
 
+PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache;
+
 /* FUNCTIONS *****************************************************************/
 
 BOOLEAN
@@ -80,4 +82,248 @@
     _SEH2_END;
 }
 
+BOOLEAN
+NTAPI
+LdrpCheckForLoadedDllHandle(IN PVOID Base,
+                            OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
+{
+    PLDR_DATA_TABLE_ENTRY Current;
+    PLIST_ENTRY ListHead, Next;
+
+    /* Check the cache first */
+    if (LdrpLoadedDllHandleCache && LdrpLoadedDllHandleCache->DllBase == Base)
+    {
+        /* We got lucky, return the cached entry */
+        *LdrEntry = LdrpLoadedDllHandleCache;
+        return TRUE;
+    }
+
+    /* Time for a lookup */
+    ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
+    Next = ListHead->Flink;
+    while(Next != ListHead)
+    {
+        /* Get the current entry */
+        Current =  CONTAINING_RECORD(Next,
+                                     LDR_DATA_TABLE_ENTRY,
+                                     InLoadOrderLinks);
+
+        /* Make sure it's not unloading and check for a match */
+        if ((Current->InMemoryOrderModuleList.Flink) && (Base == Current->DllBase))
+        {
+            /* Save in cache */
+            LdrpLoadedDllHandleCache = Current;
+
+            /* Return it */
+            *LdrEntry = Current;
+            return TRUE;
+        }
+
+        /* Move to the next one */
+        Next = Next->Flink;
+    }
+
+    /* Nothing found */
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+LdrpCheckForLoadedDll(IN PWSTR DllPath,
+                      IN PUNICODE_STRING DllName,
+                      IN BOOLEAN Flag,
+                      IN BOOLEAN RedirectedDll,
+                      OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
+
+NTSTATUS
+NTAPI
+LdrpGetProcedureAddress(IN PVOID BaseAddress,
+                        IN PANSI_STRING Name,
+                        IN ULONG Ordinal,
+                        OUT PVOID *ProcedureAddress,
+                        IN BOOLEAN ExecuteInit)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    UCHAR ImportBuffer[64];
+    PLDR_DATA_TABLE_ENTRY LdrEntry;
+    IMAGE_THUNK_DATA Thunk;
+    PVOID ImageBase;
+    PIMAGE_IMPORT_BY_NAME ImportName = NULL;
+    PIMAGE_EXPORT_DIRECTORY ExportDir;
+    ULONG ExportDirSize;
+    PLIST_ENTRY Entry;
+
+    /* Show debug message */
+    if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by ");
+
+    /* Check if we got a name */
+    if (Name)
+    {
+        /* Show debug message */
+        if (ShowSnaps) DPRINT1("NAME - %s\n", Name->Buffer);
+
+        /* Make sure it's not too long */
+        if ((Name->Length + sizeof(CHAR) + sizeof(USHORT)) > MAXLONG)
+        {
+            /* Won't have enough space to add the hint */
+            return STATUS_NAME_TOO_LONG;
+        }
+
+        /* Check if our buffer is large enough */
+        if (Name->Length >= (sizeof(ImportBuffer) - sizeof(CHAR)))
+        {
+            /* Allocate from heap, plus 2 bytes for the Hint */
+            ImportName = RtlAllocateHeap(RtlGetProcessHeap(),
+                0,
+                Name->Length + sizeof(CHAR) +
+                sizeof(USHORT));
+        }
+        else
+        {
+            /* Use our internal buffer */
+            ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer;
+        }
+
+        /* Clear the hint */
+        ImportName->Hint = 0;
+
+        /* Copy the name and null-terminate it */
+        RtlMoveMemory(&ImportName->Name, Name->Buffer, Name->Length);
+        ImportName->Name[Name->Length + 1] = 0;
+
+        /* Clear the high bit */
+        ImageBase = ImportName;
+        Thunk.u1.AddressOfData = 0;
+    }
+    else
+    {
+        /* Do it by ordinal */
+        ImageBase = NULL;
+
+        /* Show debug message */
+        if (ShowSnaps) DPRINT1("ORDINAL - %lx\n", Ordinal);
+
+        if (Ordinal)
+        {
+            Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG;
+        }
+        else
+        {
+            /* No ordinal */
+            DPRINT1("No ordinal and no name\n");
+            return STATUS_INVALID_PARAMETER;
+        }
+    }
+
+    /* Acquire lock unless we are initting */
+    if (!LdrpInLdrInit) RtlEnterCriticalSection(&LdrpLoaderLock);
+
+    _SEH2_TRY
+    {
+        /* Try to find the loaded DLL */
+        if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry))
+        {
+            /* Invalid base */
+            DPRINT1("Invalid base address\n");
+            Status = STATUS_DLL_NOT_FOUND;
+            _SEH2_YIELD(goto Quickie;)
+        }
+
+        /* Get the pointer to the export directory */
+        ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+                                                 TRUE,
+                                                 IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                                 &ExportDirSize);
+
+        if (!ExportDir)
+        {
+            DPRINT1("Image has no exports\n");
+            Status = STATUS_PROCEDURE_NOT_FOUND;
+            _SEH2_YIELD(goto Quickie;)
+        }
+
+        /* Now get the thunk */
+        Status = LdrpSnapThunk(LdrEntry->DllBase,
+                               ImageBase,
+                               &Thunk,
+                               &Thunk,
+                               ExportDir,
+                               ExportDirSize,
+                               FALSE,
+                               NULL);
+
+        /* Finally, see if we're supposed to run the init routines */
+        if (ExecuteInit)
+        {
+            /*
+            * It's possible a forwarded entry had us load the DLL. In that case,
+            * then we will call its DllMain. Use the last loaded DLL for this.
+            */
+            Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
+            LdrEntry = CONTAINING_RECORD(Entry,
+                                         LDR_DATA_TABLE_ENTRY,
+                                         InInitializationOrderModuleList);
+
+            /* Make sure we didn't process it yet*/
+            if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED))
+            {
+                /* Call the init routine */
+                _SEH2_TRY
+                {
+                    Status = LdrpRunInitializeRoutines(NULL);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    /* Get the exception code */
+                    Status = _SEH2_GetExceptionCode();
+                }
+                _SEH2_END;
+            }
+        }
+
+        /* Make sure we're OK till here */
+        if (NT_SUCCESS(Status))
+        {
+            /* Return the address */
+            *ProcedureAddress = (PVOID)Thunk.u1.Function;
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Just ignore exceptions */
+    }
+    _SEH2_END;
+
+Quickie:
+    /* Cleanup */
+    if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer))
+    {
+        /* We allocated from heap, free it */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName);
+    }
+
+    /* Release the CS if we entered it */
+    if (!LdrpInLdrInit) RtlLeaveCriticalSection(&LdrpLoaderLock);
+
+    /* We're done */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+LdrpLoadDll(IN BOOLEAN Redirected,
+            IN PWSTR DllPath OPTIONAL,
+            IN PULONG DllCharacteristics OPTIONAL,
+            IN PUNICODE_STRING DllName,
+            OUT PVOID *BaseAddress,
+            IN BOOLEAN CallInit)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 /* EOF */

Modified: trunk/reactos/dll/ntdll/ldr/utils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ldr/utils.c?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/ldr/utils.c [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ldr/utils.c [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -2848,108 +2848,6 @@
     return STATUS_SUCCESS;
 }
 
-
-/***************************************************************************
- * NAME                                                         EXPORTED
- *      LdrQueryProcessModuleInformation
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * NOTE
- *
- * @implemented
- */
-NTSTATUS NTAPI
-LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation OPTIONAL,
-                                 IN ULONG Size OPTIONAL,
-                                 OUT PULONG ReturnedSize)
-{
-    PLIST_ENTRY ModuleListHead;
-    PLIST_ENTRY Entry;
-    PLDR_DATA_TABLE_ENTRY Module;
-    PRTL_PROCESS_MODULE_INFORMATION ModulePtr = NULL;
-    NTSTATUS Status = STATUS_SUCCESS;
-    ULONG UsedSize = sizeof(ULONG);
-    ANSI_STRING AnsiString;
-    PCHAR p;
-
-    DPRINT("LdrQueryProcessModuleInformation() called\n");
-// FIXME: This code is ultra-duplicated. see lib\rtl\dbgbuffer.c
-    RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    if (ModuleInformation == NULL || Size == 0)
-    {
-        Status = STATUS_INFO_LENGTH_MISMATCH;
-    }
-    else
-    {
-        ModuleInformation->NumberOfModules = 0;
-        ModulePtr = &ModuleInformation->Modules[0];
-        Status = STATUS_SUCCESS;
-    }
-
-    ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
-    Entry = ModuleListHead->Flink;
-
-    while (Entry != ModuleListHead)
-    {
-        Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-
-        DPRINT("  Module %wZ\n",
-               &Module->FullDllName);
-
-        if (UsedSize > Size)
-        {
-            Status = STATUS_INFO_LENGTH_MISMATCH;
-        }
-        else if (ModuleInformation != NULL)
-        {
-            ModulePtr->Section = 0;
-            ModulePtr->MappedBase = NULL;      // FIXME: ??
-            ModulePtr->ImageBase = Module->DllBase;
-            ModulePtr->ImageSize = Module->SizeOfImage;
-            ModulePtr->Flags = Module->Flags;
-            ModulePtr->LoadOrderIndex = 0;      // FIXME:  ??
-            ModulePtr->InitOrderIndex = 0;      // FIXME: ??
-            ModulePtr->LoadCount = Module->LoadCount;
-
-            AnsiString.Length = 0;
-            AnsiString.MaximumLength = 256;
-            AnsiString.Buffer = ModulePtr->FullPathName;
-            RtlUnicodeStringToAnsiString(&AnsiString,
-                                         &Module->FullDllName,
-                                         FALSE);
-
-            p = strrchr(ModulePtr->FullPathName, '\\');
-            if (p != NULL)
-                ModulePtr->OffsetToFileName = p - ModulePtr->FullPathName + 1;
-            else
-                ModulePtr->OffsetToFileName = 0;
-
-            ModulePtr++;
-            ModuleInformation->NumberOfModules++;
-        }
-        UsedSize += sizeof(RTL_PROCESS_MODULE_INFORMATION);
-
-        Entry = Entry->Flink;
-    }
-
-    RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
-
-    if (ReturnedSize != 0)
-        *ReturnedSize = UsedSize;
-
-    DPRINT("LdrQueryProcessModuleInformation() done\n");
-
-    return(Status);
-}
-
 /*
  * Compute size of an image as it is actually present in virt memory
  * (i.e. excluding NEVER_LOAD sections)

Modified: trunk/reactos/dll/ntdll/ntdll.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/ntdll/ntdll.rbuild?rev=51065&r1=51064&r2=51065&view=diff
==============================================================================
--- trunk/reactos/dll/ntdll/ntdll.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/ntdll/ntdll.rbuild [iso-8859-1] Wed Mar 16 14:22:15 2011
@@ -49,6 +49,7 @@
 		<directory name="ldr">
 			<file>ldrapi.c</file>
 			<file>ldrinit.c</file>
+			<file>ldrpe.c</file>
 			<file>ldrutils.c</file>
 			<file>startup.c</file>
 			<file>utils.c</file>




More information about the Ros-diffs mailing list