Author: ion
Date: Wed Feb 21 21:43:57 2007
New Revision: 25868
URL:
http://svn.reactos.org/svn/reactos?rev=25868&view=rev
Log:
- Implement ExpQueryModuleInformation to handle SystemModuleInformation, instead of
LdrpQueryModleInformation. This version properly fills out all the data required and also
supports (but doesn't yet handle) user-mode modules.
- Start work on supporting NT-compatible System Loader that properly fills out
LDR_DATA_TABLE_ENTRY and handles imports correctly. Modified LdpPEProcessModule to
properly build the data table entry and create the base name and directory name.
- Add stub for MiResolveImageRefernces.
Modified:
trunk/reactos/ntoskrnl/ex/sysinfo.c
trunk/reactos/ntoskrnl/ldr/loader.c
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/sysinfo.c (original)
+++ trunk/reactos/ntoskrnl/ex/sysinfo.c Wed Feb 21 21:43:57 2007
@@ -24,6 +24,123 @@
FAST_MUTEX ExpEnvironmentLock;
ERESOURCE ExpFirmwareTableResource;
LIST_ENTRY ExpFirmwareTableProviderListHead;
+
+NTSTATUS
+NTAPI
+ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList,
+ IN PLIST_ENTRY UserModeList,
+ OUT PRTL_PROCESS_MODULES Modules,
+ IN ULONG Length,
+ OUT PULONG ReturnLength)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG RequiredLength;
+ PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ ANSI_STRING ModuleName;
+ ULONG ModuleCount = 0;
+ PLIST_ENTRY NextEntry;
+ PCHAR p;
+
+ /* Setup defaults */
+ RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules);
+ ModuleInfo = &Modules->Modules[0];
+
+ /* Loop the kernel list */
+ NextEntry = KernelModeList->Flink;
+ while (NextEntry != KernelModeList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Update size and check if we can manage one more entry */
+ RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION);
+ if (Length >= RequiredLength)
+ {
+ /* Fill it out */
+ ModuleInfo->MappedBase = NULL;
+ ModuleInfo->ImageBase = LdrEntry->DllBase;
+ ModuleInfo->ImageSize = LdrEntry->SizeOfImage;
+ ModuleInfo->Flags = LdrEntry->Flags;
+ ModuleInfo->LoadCount = LdrEntry->LoadCount;
+ ModuleInfo->LoadOrderIndex = ModuleCount;
+ ModuleInfo->InitOrderIndex = 0;
+
+ /* Setup name */
+ RtlInitEmptyAnsiString(&ModuleName,
+ ModuleInfo->FullPathName,
+ sizeof(ModuleInfo->FullPathName));
+
+ /* Convert it */
+ Status = RtlUnicodeStringToAnsiString(&ModuleName,
+ &LdrEntry->FullDllName,
+ FALSE);
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+ {
+ /* Calculate offset to name */
+ p = ModuleName.Buffer + ModuleName.Length;
+ while ((p > ModuleName.Buffer) && (*--p))
+ {
+ /* Check if we found the separator */
+ if (*p == OBJ_NAME_PATH_SEPARATOR)
+ {
+ /* We did, break out */
+ p++;
+ break;
+ }
+ }
+
+ /* Set the offset */
+ ModuleInfo->OffsetToFileName = p - ModuleName.Buffer;
+ }
+ else
+ {
+ /* Return empty name */
+ ModuleInfo->FullPathName[0] = ANSI_NULL;
+ ModuleInfo->OffsetToFileName = 0;
+ }
+
+ /* Go to the next module */
+ ModuleInfo++;
+ }
+ else
+ {
+ /* Set error code */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Update count and move to next entry */
+ ModuleCount++;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Check if caller also wanted user modules */
+ if (UserModeList)
+ {
+ /* FIXME: TODO */
+ DPRINT1("User-mode list not yet supported in ReactOS!\n");
+ }
+
+ /* Update return length */
+ if (ReturnLength) *ReturnLength = RequiredLength;
+
+ /* Validate the length again */
+ if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules))
+ {
+ /* Set the final count */
+ Modules->NumberOfModules = ModuleCount;
+ }
+ else
+ {
+ /* Otherwise, we failed */
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ /* Done */
+ return Status;
+}
/* FUNCTIONS *****************************************************************/
@@ -835,7 +952,12 @@
/* Class 11 - Module Information */
QSI_DEF(SystemModuleInformation)
{
- return LdrpQueryModuleInformation(Buffer, Size, ReqSize);
+ extern LIST_ENTRY ModuleListHead;
+ return ExpQueryModuleInformation(&ModuleListHead,
+ NULL,
+ (PRTL_PROCESS_MODULES)Buffer,
+ Size,
+ ReqSize);
}
/* Class 12 - Locks Information */
Modified: trunk/reactos/ntoskrnl/ldr/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ldr/loader.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ldr/loader.c (original)
+++ trunk/reactos/ntoskrnl/ldr/loader.c Wed Feb 21 21:43:57 2007
@@ -438,6 +438,25 @@
return STATUS_SUCCESS;
}
+typedef struct _LOAD_IMPORTS
+{
+ SIZE_T Count;
+ PLDR_DATA_TABLE_ENTRY Entry[1];
+} LOAD_IMPORTS, *PLOAD_IMPORTS;
+
+NTSTATUS
+NTAPI
+MiResolveImageReferences(IN PVOID ImageBase,
+ IN PUNICODE_STRING ImageFileDirectory,
+ IN PUNICODE_STRING NamePrefix OPTIONAL,
+ OUT PCHAR *MissingApi,
+ OUT PWCHAR *MissingDriver,
+ OUT PLOAD_IMPORTS *LoadImports)
+{
+ /* We don't do anything for now */
+ return STATUS_SUCCESS;
+}
+
static NTSTATUS
LdrPEFixupImports (IN PVOID DllBase,
IN PWCHAR DllName)
@@ -490,15 +509,23 @@
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_NT_HEADERS PENtHeaders;
PIMAGE_SECTION_HEADER PESectionHeaders;
- PLDR_DATA_TABLE_ENTRY CreatedModuleObject;
NTSTATUS Status;
KIRQL Irql;
+ PIMAGE_NT_HEADERS NtHeader;
+ UNICODE_STRING BaseName, BaseDirectory, PrefixName;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ ULONG EntrySize;
+ PLOAD_IMPORTS LoadedImports = (PVOID)-2;
+ PWSTR NameBuffer;
+ PCHAR MissingApiName, Buffer;
+ PWCHAR MissingDriverName;
DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
/* Get header pointers */
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
PENtHeaders = RtlImageNtHeader(ModuleLoadBase);
+ NtHeader = PENtHeaders;
PESectionHeaders = IMAGE_FIRST_SECTION(PENtHeaders);
@@ -578,78 +605,165 @@
}
}
- /* Perform relocation fixups */
- Status = LdrRelocateImageWithBias(DriverBase, 0, "", STATUS_SUCCESS,
- STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
+ /* Relocate the driver */
+ Status = LdrRelocateImageWithBias(DriverBase,
+ 0,
+ "SYSLDR",
+ STATUS_SUCCESS,
+ STATUS_CONFLICTING_ADDRESSES,
+ STATUS_INVALID_IMAGE_FORMAT);
if (!NT_SUCCESS(Status))
{
- // MmFreeSection(DriverBase);
+ /* Fail */
return Status;
}
- /* Create the module */
- CreatedModuleObject = ExAllocatePoolWithTag (
- NonPagedPool, sizeof(LDR_DATA_TABLE_ENTRY), TAG_MODULE_OBJECT );
- if (CreatedModuleObject == NULL)
- {
- // MmFreeSection(DriverBase);
+ /* Allocate a buffer we'll use for names */
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
+ if (!Buffer)
+ {
+ /* Fail */
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory(CreatedModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
-
- /* Initialize ModuleObject data */
- CreatedModuleObject->DllBase = DriverBase;
-
- CreatedModuleObject->FullDllName.Length = 0;
- CreatedModuleObject->FullDllName.MaximumLength = FileName->Length +
sizeof(UNICODE_NULL);
- CreatedModuleObject->FullDllName.Buffer =
- ExAllocatePoolWithTag(PagedPool,
CreatedModuleObject->FullDllName.MaximumLength, TAG_LDR_WSTR);
- if (CreatedModuleObject->FullDllName.Buffer == NULL)
- {
- ExFreePool(CreatedModuleObject);
- // MmFreeSection(DriverBase);
+ /* Check for a separator */
+ if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
+ {
+ PWCHAR p;
+ ULONG BaseLength;
+
+ /* Loop the path until we get to the base name */
+ p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
+ while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
+
+ /* Get the length */
+ BaseLength = (ULONG)(&FileName->Buffer[FileName->Length /
sizeof(WCHAR)] - p);
+ BaseLength *= sizeof(WCHAR);
+
+ /* Setup the string */
+ BaseName.Length = BaseLength;
+ BaseName.Buffer = p;
+ }
+ else
+ {
+ /* Otherwise, we already have a base name */
+ BaseName.Length = FileName->Length;
+ BaseName.Buffer = FileName->Buffer;
+ }
+
+ /* Setup the maximum length */
+ BaseName.MaximumLength = BaseName.Length;
+
+ /* Now compute the base directory */
+ BaseDirectory = *FileName;
+ BaseDirectory.Length -= BaseName.Length;
+ BaseDirectory.MaximumLength = BaseDirectory.Length;
+
+ /* And the prefix */
+ PrefixName = *FileName;
+
+ /* Calculate the size we'll need for the entry and allocate it */
+ EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
+ BaseName.Length +
+ sizeof(UNICODE_NULL);
+
+ /* Allocate the entry */
+ LdrEntry = ExAllocatePoolWithTag(NonPagedPool, EntrySize, TAG_MODULE_OBJECT);
+ if (!LdrEntry)
+ {
+ /* Fail */
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlCopyUnicodeString(&CreatedModuleObject->FullDllName, FileName);
- CreatedModuleObject->FullDllName.Buffer[FileName->Length / sizeof(WCHAR)] = 0;
- LdrpBuildModuleBaseName(&CreatedModuleObject->BaseDllName,
- &CreatedModuleObject->FullDllName);
-
- CreatedModuleObject->EntryPoint =
- (PVOID)((ULONG_PTR)DriverBase +
- PENtHeaders->OptionalHeader.AddressOfEntryPoint);
- CreatedModuleObject->SizeOfImage = DriverSize;
- DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint);
-
- /* Perform import fixups */
- Status = LdrPEFixupImports(CreatedModuleObject->DllBase,
- CreatedModuleObject->FullDllName.Buffer);
+ /* Setup the entry */
+ LdrEntry->Flags = LDRP_LOAD_IN_PROGRESS;
+ LdrEntry->LoadCount = 1;
+ LdrEntry->LoadedImports = LoadedImports;
+ LdrEntry->PatchInformation = NULL;
+
+ /* Check the version */
+ if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion >= 5) &&
+ (NtHeader->OptionalHeader.MajorImageVersion >= 5))
+ {
+ /* Mark this image as a native image */
+ LdrEntry->Flags |= 0x80000000;
+ }
+
+ /* We'll put the name after the entry */
+ NameBuffer = (PVOID)(LdrEntry + 1);
+
+ /* Setup the rest of the entry */
+ LdrEntry->DllBase = DriverBase;
+ LdrEntry->EntryPoint = (PVOID)((ULONG_PTR)DriverBase +
+ NtHeader->OptionalHeader.AddressOfEntryPoint);
+ LdrEntry->SizeOfImage = DriverSize;
+ LdrEntry->CheckSum = NtHeader->OptionalHeader.CheckSum;
+ LdrEntry->SectionPointer = NULL; // FIXME
+
+ /* Now write the DLL name */
+ LdrEntry->BaseDllName.Buffer = NameBuffer;
+ LdrEntry->BaseDllName.Length = BaseName.Length;
+ LdrEntry->BaseDllName.MaximumLength = BaseName.Length;
+
+ /* Copy and null-terminate it */
+ RtlCopyMemory(LdrEntry->BaseDllName.Buffer,
+ BaseName.Buffer,
+ BaseName.Length);
+ LdrEntry->BaseDllName.Buffer[BaseName.Length / 2] = UNICODE_NULL;
+
+ /* Now allocate the full name */
+ LdrEntry->FullDllName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ PrefixName.Length +
+ sizeof(UNICODE_NULL),
+ TAG_LDR_WSTR);
+ if (!LdrEntry->FullDllName.Buffer)
+ {
+ /* Don't fail, just set it to zero */
+ LdrEntry->FullDllName.Length = 0;
+ LdrEntry->FullDllName.MaximumLength = 0;
+ }
+ else
+ {
+ /* Set it up */
+ LdrEntry->FullDllName.Length = PrefixName.Length;
+ LdrEntry->FullDllName.MaximumLength = PrefixName.Length;
+
+ /* Copy and null-terminate */
+ RtlCopyMemory(LdrEntry->FullDllName.Buffer,
+ PrefixName.Buffer,
+ PrefixName.Length);
+ LdrEntry->FullDllName.Buffer[PrefixName.Length / 2] = UNICODE_NULL;
+ }
+
+ /* Insert the entry */
+ KeAcquireSpinLock(&ModuleListLock, &Irql);
+ InsertTailList(&ModuleListHead, &LdrEntry->InLoadOrderLinks);
+ KeReleaseSpinLock(&ModuleListLock, Irql);
+
+ /* Resolve imports */
+ MissingApiName = Buffer;
+ Status = MiResolveImageReferences(DriverBase,
+ &BaseDirectory,
+ NULL,
+ &MissingApiName,
+ &MissingDriverName,
+ &LoadedImports);
+
+ /* Resolve imports */
+ Status = LdrPEFixupImports(LdrEntry->DllBase,
+ LdrEntry->FullDllName.Buffer);
if (!NT_SUCCESS(Status))
{
- // MmFreeSection(DriverBase);
- ExFreePool(CreatedModuleObject->FullDllName.Buffer);
- ExFreePool(CreatedModuleObject);
+ /* Fail */
+ ExFreePool(LdrEntry->FullDllName.Buffer);
+ ExFreePool(LdrEntry);
return Status;
}
- /* Insert module */
- KeAcquireSpinLock(&ModuleListLock, &Irql);
- InsertTailList(&ModuleListHead,
- &CreatedModuleObject->InLoadOrderLinks);
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- *ModuleObject = CreatedModuleObject;
-
- DPRINT("Loading Module %wZ...\n", FileName);
-
- DPRINT("Module %wZ loaded at 0x%.08x.\n",
- FileName, CreatedModuleObject->DllBase);
-
+ /* Return */
+ *ModuleObject = LdrEntry;
return STATUS_SUCCESS;
}
-
VOID
INIT_FUNCTION
@@ -897,114 +1011,4 @@
return(STATUS_SUCCESS);
}
-//
-// Used by NtSetSystemInformation
-//
-NTSTATUS
-NTAPI
-LdrpQueryModuleInformation (
- PVOID Buffer,
- ULONG Size,
- PULONG ReqSize )
-{
- PLIST_ENTRY current_entry;
- PLDR_DATA_TABLE_ENTRY current;
- ULONG ModuleCount = 0;
- PRTL_PROCESS_MODULES Smi;
- ANSI_STRING AnsiName;
- PCHAR p;
- KIRQL Irql;
- PUNICODE_STRING UnicodeName;
- ULONG tmpBufferSize = 0;
- PWCHAR tmpNameBuffer;
-
- KeAcquireSpinLock(&ModuleListLock,&Irql);
-
- /* calculate required size */
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
- {
- ModuleCount++;
- current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
- tmpBufferSize += current->FullDllName.Length + sizeof(WCHAR) +
sizeof(UNICODE_STRING);
- current_entry = current_entry->Flink;
- }
-
- *ReqSize = sizeof(RTL_PROCESS_MODULES)+
- (ModuleCount - 1) * sizeof(RTL_PROCESS_MODULE_INFORMATION);
-
- if (Size < *ReqSize)
- {
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return(STATUS_INFO_LENGTH_MISMATCH);
- }
-
- /* allocate a temp buffer to store the module names */
- UnicodeName = ExAllocatePool(NonPagedPool, tmpBufferSize);
- if (UnicodeName == NULL)
- {
- KeReleaseSpinLock(&ModuleListLock, Irql);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- tmpNameBuffer = (PWCHAR)((ULONG_PTR)UnicodeName + ModuleCount *
sizeof(UNICODE_STRING));
-
- /* fill the buffer */
- memset(Buffer, '=', Size);
-
- Smi = (PRTL_PROCESS_MODULES)Buffer;
- Smi->NumberOfModules = ModuleCount;
-
- ModuleCount = 0;
- current_entry = ModuleListHead.Flink;
- while (current_entry != (&ModuleListHead))
- {
- current =
CONTAINING_RECORD(current_entry,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
-
- Smi->Modules[ModuleCount].Section = 0; /* Always 0 */
- Smi->Modules[ModuleCount].MappedBase = 0; /* Always 0 */
- Smi->Modules[ModuleCount].ImageBase = current->DllBase;
- Smi->Modules[ModuleCount].ImageSize = current->SizeOfImage;
- Smi->Modules[ModuleCount].Flags = 0; /* Flags ??? (GN) */
- Smi->Modules[ModuleCount].LoadOrderIndex = (USHORT)ModuleCount;
- Smi->Modules[ModuleCount].InitOrderIndex = 0;
- Smi->Modules[ModuleCount].LoadCount = 0; /* FIXME */
- UnicodeName[ModuleCount].Buffer = tmpNameBuffer;
- UnicodeName[ModuleCount].MaximumLength = current->FullDllName.Length +
sizeof(WCHAR);
- tmpNameBuffer += UnicodeName[ModuleCount].MaximumLength / sizeof(WCHAR);
- RtlCopyUnicodeString(&UnicodeName[ModuleCount],
¤t->FullDllName);
-
- ModuleCount++;
- current_entry = current_entry->Flink;
- }
-
- KeReleaseSpinLock(&ModuleListLock, Irql);
-
- for (ModuleCount = 0; ModuleCount < Smi->NumberOfModules; ModuleCount++)
- {
- AnsiName.Length = 0;
- AnsiName.MaximumLength = 255;
- AnsiName.Buffer = Smi->Modules[ModuleCount].FullPathName;
- RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeName[ModuleCount],
FALSE);
- AnsiName.Buffer[AnsiName.Length] = 0;
- Smi->Modules[ModuleCount].InitOrderIndex = AnsiName.Length;
-
- p = strrchr(AnsiName.Buffer, '\\');
- if (p == NULL)
- {
- Smi->Modules[ModuleCount].OffsetToFileName = 0;
- }
- else
- {
- p++;
- Smi->Modules[ModuleCount].OffsetToFileName = p - AnsiName.Buffer;
- }
- }
-
- ExFreePool(UnicodeName);
-
- return(STATUS_SUCCESS);
-}
-
-
-
/* EOF */