diff --git a/reactos/include/ndk/ldrtypes.h b/reactos/include/ndk/ldrtypes.h index f4447d67957..f5043084953 100644 --- a/reactos/include/ndk/ldrtypes.h +++ b/reactos/include/ndk/ldrtypes.h @@ -49,8 +49,14 @@ Author: #define LDRP_IMAGE_NOT_AT_BASE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 #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_NON_PAGED_DEBUG_INFO 0x20000000 +#define LDRP_MM_LOADED 0x40000000 +#define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 // // Dll Characteristics for LdrLoadDll diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 29c56656955..c1bebb70ba0 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -201,11 +201,71 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName, PLOAD_IMPORTS LoadedImports = (PVOID)-2; PCHAR MissingApiName, Buffer; 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 (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 */ InitializeObjectAttributes(&ObjectAttributes, @@ -370,50 +430,6 @@ MmLoadSystemImage(IN PUNICODE_STRING FileName, 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 */ EntrySize = sizeof(LDR_DATA_TABLE_ENTRY) + BaseName.Length + diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index ac42a1c1e0b..e478f84ede1 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -453,6 +453,7 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr, } BOOLEAN RmapReady, PageOpReady, SectionsReady, PagingReady; +extern KMUTANT MmSystemLoadLock; BOOLEAN NTAPI @@ -461,6 +462,9 @@ MmInitSystem(IN ULONG Phase, { if (Phase == 0) { + /* Initialize the Loader Lock */ + KeInitializeMutant(&MmSystemLoadLock, FALSE); + /* Reload boot drivers */ MiReloadBootLoadedDrivers(LoaderBlock); diff --git a/reactos/ntoskrnl/mm/pe.c b/reactos/ntoskrnl/mm/pe.c index 3055e9cf33a..41502117a5c 100644 --- a/reactos/ntoskrnl/mm/pe.c +++ b/reactos/ntoskrnl/mm/pe.c @@ -677,108 +677,4 @@ l_Return: 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 */ diff --git a/reactos/ntoskrnl/mm/sysldr.c b/reactos/ntoskrnl/mm/sysldr.c index f5f847d65c6..a844b85b5be 100644 --- a/reactos/ntoskrnl/mm/sysldr.c +++ b/reactos/ntoskrnl/mm/sysldr.c @@ -17,6 +17,7 @@ LIST_ENTRY PsLoadedModuleList; KSPIN_LOCK PsLoadedModuleSpinLock; PVOID PsNtosImageBase; +KMUTANT MmSystemLoadLock; /* FUNCTIONS *****************************************************************/ @@ -914,3 +915,107 @@ MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* We're done */ 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; +}