mirror of
https://github.com/reactos/reactos.git
synced 2024-08-02 01:21:00 +00:00
- Move some Mm routines from pe.c to sysldr.c where they belong.
- Create and initialize Mm Loader lock. - Re-arrange some code in MmLoadSystemImage, no code changes yet. - Add new LDRP_ flags for LDR_DATA_TABLE_ENTRY to the NDK. svn path=/trunk/; revision=25881
This commit is contained in:
parent
50b11bc313
commit
e81f8006bb
|
@ -49,8 +49,14 @@ Author:
|
||||||
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
|
#define LDRP_IMAGE_NOT_AT_BASE 0x00200000
|
||||||
#define LDRP_COR_IMAGE 0x00400000
|
#define LDRP_COR_IMAGE 0x00400000
|
||||||
#define LDR_COR_OWNS_UNMAP 0x00800000
|
#define LDR_COR_OWNS_UNMAP 0x00800000
|
||||||
#define LDRP_DRIVER_VERIFYING 0x02000000
|
#define LDRP_SYSTEM_MAPPED 0x01000000
|
||||||
|
#define LDRP_IMAGE_VERIFYING 0x02000000
|
||||||
|
#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000
|
||||||
|
#define LDRP_ENTRY_NATIVE 0x08800000
|
||||||
#define LDRP_REDIRECTED 0x10000000
|
#define LDRP_REDIRECTED 0x10000000
|
||||||
|
#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000
|
||||||
|
#define LDRP_MM_LOADED 0x40000000
|
||||||
|
#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000
|
||||||
|
|
||||||
//
|
//
|
||||||
// Dll Characteristics for LdrLoadDll
|
// Dll Characteristics for LdrLoadDll
|
||||||
|
|
|
@ -201,11 +201,71 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName,
|
||||||
PLOAD_IMPORTS LoadedImports = (PVOID)-2;
|
PLOAD_IMPORTS LoadedImports = (PVOID)-2;
|
||||||
PCHAR MissingApiName, Buffer;
|
PCHAR MissingApiName, Buffer;
|
||||||
PWCHAR MissingDriverName;
|
PWCHAR MissingDriverName;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Detect session-load */
|
||||||
|
if (Flags)
|
||||||
|
{
|
||||||
|
/* Sanity checks */
|
||||||
|
ASSERT(NamePrefix == NULL);
|
||||||
|
ASSERT(LoadedName == NULL);
|
||||||
|
|
||||||
|
/* Make sure the process is in session too */
|
||||||
|
if (!PsGetCurrentProcess()->ProcessInSession) return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
if (ModuleObject) *ModuleObject = NULL;
|
if (ModuleObject) *ModuleObject = NULL;
|
||||||
if (ImageBaseAddress) *ImageBaseAddress = NULL;
|
if (ImageBaseAddress) *ImageBaseAddress = NULL;
|
||||||
|
|
||||||
DPRINT("Loading Module %wZ...\n", FileName);
|
/* Allocate a buffer we'll use for names */
|
||||||
|
Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 = (USHORT)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, which for now is just the name itself */
|
||||||
|
PrefixName = *FileName;
|
||||||
|
|
||||||
|
/* Check if we have a prefix */
|
||||||
|
if (NamePrefix) DPRINT1("Prefixed images are not yet supported!\n");
|
||||||
|
|
||||||
|
/* Check if we already have a name, use it instead */
|
||||||
|
if (LoadedName) BaseName = *LoadedName;
|
||||||
|
|
||||||
/* Open the Module */
|
/* Open the Module */
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
@ -370,50 +430,6 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate a buffer we'll use for names */
|
|
||||||
Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR);
|
|
||||||
if (!Buffer)
|
|
||||||
{
|
|
||||||
/* Fail */
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 = (USHORT)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 */
|
/* Calculate the size we'll need for the entry and allocate it */
|
||||||
EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
|
EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) +
|
||||||
BaseName.Length +
|
BaseName.Length +
|
||||||
|
|
|
@ -453,6 +453,7 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN RmapReady, PageOpReady, SectionsReady, PagingReady;
|
BOOLEAN RmapReady, PageOpReady, SectionsReady, PagingReady;
|
||||||
|
extern KMUTANT MmSystemLoadLock;
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -461,6 +462,9 @@ MmInitSystem(IN ULONG Phase,
|
||||||
{
|
{
|
||||||
if (Phase == 0)
|
if (Phase == 0)
|
||||||
{
|
{
|
||||||
|
/* Initialize the Loader Lock */
|
||||||
|
KeInitializeMutant(&MmSystemLoadLock, FALSE);
|
||||||
|
|
||||||
/* Reload boot drivers */
|
/* Reload boot drivers */
|
||||||
MiReloadBootLoadedDrivers(LoaderBlock);
|
MiReloadBootLoadedDrivers(LoaderBlock);
|
||||||
|
|
||||||
|
|
|
@ -677,108 +677,4 @@ l_Return:
|
||||||
return nStatus;
|
return nStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
MmVerifyImageIsOkForMpUse(IN PVOID BaseAddress)
|
|
||||||
{
|
|
||||||
PIMAGE_NT_HEADERS NtHeader;
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
/* Get NT Headers */
|
|
||||||
NtHeader = RtlImageNtHeader(BaseAddress);
|
|
||||||
if (NtHeader)
|
|
||||||
{
|
|
||||||
/* Check if this image is only safe for UP while we have 2+ CPUs */
|
|
||||||
if ((KeNumberProcessors > 1) &&
|
|
||||||
(NtHeader->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY))
|
|
||||||
{
|
|
||||||
/* Fail */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, it's safe */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
MmCheckSystemImage(IN HANDLE ImageHandle,
|
|
||||||
IN BOOLEAN PurgeSection)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
HANDLE SectionHandle;
|
|
||||||
PVOID ViewBase = NULL;
|
|
||||||
SIZE_T ViewSize = 0;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
FILE_STANDARD_INFORMATION FileStandardInfo;
|
|
||||||
KAPC_STATE ApcState;
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
/* Create a section for the DLL */
|
|
||||||
Status = ZwCreateSection(&SectionHandle,
|
|
||||||
SECTION_MAP_EXECUTE,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
PAGE_EXECUTE,
|
|
||||||
SEC_COMMIT,
|
|
||||||
ImageHandle);
|
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
|
||||||
/* Make sure we're in the system process */
|
|
||||||
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
|
|
||||||
|
|
||||||
/* Map it */
|
|
||||||
Status = ZwMapViewOfSection(SectionHandle,
|
|
||||||
NtCurrentProcess(),
|
|
||||||
&ViewBase,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
&ViewSize,
|
|
||||||
ViewShare,
|
|
||||||
0,
|
|
||||||
PAGE_EXECUTE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* We failed, close the handle and return */
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
ZwClose(SectionHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now query image information */
|
|
||||||
Status = ZwQueryInformationFile(ImageHandle,
|
|
||||||
&IoStatusBlock,
|
|
||||||
&FileStandardInfo,
|
|
||||||
sizeof(FileStandardInfo),
|
|
||||||
FileStandardInformation);
|
|
||||||
if ( NT_SUCCESS(Status) )
|
|
||||||
{
|
|
||||||
/* First, verify the checksum */
|
|
||||||
if (!LdrVerifyMappedImageMatchesChecksum(ViewBase,
|
|
||||||
FileStandardInfo.
|
|
||||||
EndOfFile.LowPart,
|
|
||||||
FileStandardInfo.
|
|
||||||
EndOfFile.LowPart))
|
|
||||||
{
|
|
||||||
/* Set checksum failure */
|
|
||||||
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that it's a valid SMP image if we have more then one CPU */
|
|
||||||
if (!MmVerifyImageIsOkForMpUse(ViewBase))
|
|
||||||
{
|
|
||||||
/* Otherwise it's not the right image */
|
|
||||||
Status = STATUS_IMAGE_MP_UP_MISMATCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmap the section, close the handle, and return status */
|
|
||||||
ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
ZwClose(SectionHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
LIST_ENTRY PsLoadedModuleList;
|
LIST_ENTRY PsLoadedModuleList;
|
||||||
KSPIN_LOCK PsLoadedModuleSpinLock;
|
KSPIN_LOCK PsLoadedModuleSpinLock;
|
||||||
PVOID PsNtosImageBase;
|
PVOID PsNtosImageBase;
|
||||||
|
KMUTANT MmSystemLoadLock;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -914,3 +915,107 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
/* We're done */
|
/* We're done */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
MmVerifyImageIsOkForMpUse(IN PVOID BaseAddress)
|
||||||
|
{
|
||||||
|
PIMAGE_NT_HEADERS NtHeader;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Get NT Headers */
|
||||||
|
NtHeader = RtlImageNtHeader(BaseAddress);
|
||||||
|
if (NtHeader)
|
||||||
|
{
|
||||||
|
/* Check if this image is only safe for UP while we have 2+ CPUs */
|
||||||
|
if ((KeNumberProcessors > 1) &&
|
||||||
|
(NtHeader->FileHeader.Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, it's safe */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MmCheckSystemImage(IN HANDLE ImageHandle,
|
||||||
|
IN BOOLEAN PurgeSection)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE SectionHandle;
|
||||||
|
PVOID ViewBase = NULL;
|
||||||
|
SIZE_T ViewSize = 0;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
FILE_STANDARD_INFORMATION FileStandardInfo;
|
||||||
|
KAPC_STATE ApcState;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Create a section for the DLL */
|
||||||
|
Status = ZwCreateSection(&SectionHandle,
|
||||||
|
SECTION_MAP_EXECUTE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
PAGE_EXECUTE,
|
||||||
|
SEC_COMMIT,
|
||||||
|
ImageHandle);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Make sure we're in the system process */
|
||||||
|
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
|
||||||
|
|
||||||
|
/* Map it */
|
||||||
|
Status = ZwMapViewOfSection(SectionHandle,
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&ViewBase,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
&ViewSize,
|
||||||
|
ViewShare,
|
||||||
|
0,
|
||||||
|
PAGE_EXECUTE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* We failed, close the handle and return */
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
ZwClose(SectionHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now query image information */
|
||||||
|
Status = ZwQueryInformationFile(ImageHandle,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileStandardInfo,
|
||||||
|
sizeof(FileStandardInfo),
|
||||||
|
FileStandardInformation);
|
||||||
|
if ( NT_SUCCESS(Status) )
|
||||||
|
{
|
||||||
|
/* First, verify the checksum */
|
||||||
|
if (!LdrVerifyMappedImageMatchesChecksum(ViewBase,
|
||||||
|
FileStandardInfo.
|
||||||
|
EndOfFile.LowPart,
|
||||||
|
FileStandardInfo.
|
||||||
|
EndOfFile.LowPart))
|
||||||
|
{
|
||||||
|
/* Set checksum failure */
|
||||||
|
Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that it's a valid SMP image if we have more then one CPU */
|
||||||
|
if (!MmVerifyImageIsOkForMpUse(ViewBase))
|
||||||
|
{
|
||||||
|
/* Otherwise it's not the right image */
|
||||||
|
Status = STATUS_IMAGE_MP_UP_MISMATCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmap the section, close the handle, and return status */
|
||||||
|
ZwUnmapViewOfSection(NtCurrentProcess(), ViewBase);
|
||||||
|
KeUnstackDetachProcess(&ApcState);
|
||||||
|
ZwClose(SectionHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue