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…
==============================================================================
--- 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…
==============================================================================
--- 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?re…
==============================================================================
--- 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=…
==============================================================================
--- 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(a)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?r…
==============================================================================
--- 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=…
==============================================================================
--- 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…
==============================================================================
--- 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>