ULONG cbHeadersSize = 0;
ULONG nSectionAlignment;
ULONG nFileAlignment;
- ULONG_PTR ImageBase;
+ ULONG_PTR ImageBase = 0;
const IMAGE_DOS_HEADER * pidhDosHeader;
const IMAGE_NT_HEADERS32 * pinhNtHeader;
const IMAGE_OPTIONAL_HEADER32 * piohOptHeader;
SIZE_T nPrevVirtualEndOfSegment = 0;
ULONG nFileSizeOfHeaders = 0;
ULONG i;
+ ULONG AlignedLength;
ASSERT(FileHeader);
ASSERT(FileHeaderSize > 0);
#endif // _WIN64
break;
+#ifndef _WIN64
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ nStatus = STATUS_INVALID_IMAGE_WIN_64;
+#endif
default:
DIE(("Unrecognized optional header, Magic is %X\n", piohOptHeader->Magic));
}
pssSegments[0].Length.QuadPart = nPrevVirtualEndOfSegment;
pssSegments[0].RawLength.QuadPart = nFileSizeOfHeaders;
pssSegments[0].Image.VirtualAddress = 0;
- pssSegments[0].Image.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ pssSegments[0].Image.Characteristics = 0;
pssSegments[0].WriteCopy = TRUE;
/* skip the headers segment */
else
pssSegments[i].Length.QuadPart = pishSectionHeaders[i].Misc.VirtualSize;
- pssSegments[i].Length.LowPart = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
- /* FIXME: always false */
- if (pssSegments[i].Length.QuadPart < pssSegments[i].Length.QuadPart)
+ AlignedLength = ALIGN_UP_BY(pssSegments[i].Length.LowPart, nSectionAlignment);
+ if(AlignedLength < pssSegments[i].Length.LowPart)
DIE(("Cannot align the virtual size of section %u\n", i));
+ pssSegments[i].Length.LowPart = AlignedLength;
+
if(pssSegments[i].Length.QuadPart == 0)
DIE(("Virtual size of section %u is null\n", i));
NTSTATUS
NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
+MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
{
PEPROCESS Process;
- KIRQL Irql, Irql2;
- PVOID DestAddress, SrcAddress;
+ KIRQL Irql;
+ PVOID DestAddress;
Process = PsGetCurrentProcess();
DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
- SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
- if (DestAddress == NULL || SrcAddress == NULL)
+ if (DestAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
- MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
return(STATUS_SUCCESS);
}
}
#endif
+static VOID
+MmAlterViewAttributes(PMMSUPPORT AddressSpace,
+ PVOID BaseAddress,
+ SIZE_T RegionSize,
+ ULONG OldType,
+ ULONG OldProtect,
+ ULONG NewType,
+ ULONG NewProtect)
+{
+ PMEMORY_AREA MemoryArea;
+ PMM_SECTION_SEGMENT Segment;
+ BOOLEAN DoCOW = FALSE;
+ ULONG i;
+ PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+
+ MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
+ ASSERT(MemoryArea != NULL);
+ Segment = MemoryArea->Data.SectionData.Segment;
+ MmLockSectionSegment(Segment);
+
+ if ((Segment->WriteCopy) &&
+ (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
+ {
+ DoCOW = TRUE;
+ }
+
+ if (OldProtect != NewProtect)
+ {
+ for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
+ {
+ SWAPENTRY SwapEntry;
+ PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
+ ULONG Protect = NewProtect;
+
+ /* Wait for a wait entry to disappear */
+ do
+ {
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
+ if (SwapEntry != MM_WAIT_ENTRY)
+ break;
+ MiWaitForPageEvent(Process, Address);
+ }
+ while (TRUE);
+
+ /*
+ * If we doing COW for this segment then check if the page is
+ * already private.
+ */
+ if (DoCOW && MmIsPagePresent(Process, Address))
+ {
+ LARGE_INTEGER Offset;
+ ULONG_PTR Entry;
+ PFN_NUMBER Page;
+
+ Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
+ + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+ Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+ /*
+ * An MM_WAIT_ENTRY is ok in this case... It'll just count as
+ * IS_SWAP_FROM_SSE and we'll do the right thing.
+ */
+ Page = MmGetPfnForProcess(Process, Address);
+
+ Protect = PAGE_READONLY;
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
+ {
+ Protect = NewProtect;
+ }
+ }
+
+ if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
+ {
+ MmSetPageProtect(Process, Address,
+ Protect);
+ }
+ }
+ }
+
+ MmUnlockSectionSegment(Segment);
+}
+
NTSTATUS
NTAPI
MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
ASSERT(Region != NULL);
+
+ /* Check for a NOACCESS mapping */
+ if (Region->Protect & PAGE_NOACCESS)
+ {
+ return STATUS_ACCESS_VIOLATION;
+ }
+
+ if (Region->Protect & PAGE_GUARD)
+ {
+ /* Remove it */
+ Status = MmAlterRegion(AddressSpace, (PVOID)MA_GetStartingAddress(MemoryArea),
+ &MemoryArea->Data.SectionData.RegionListHead,
+ Address, PAGE_SIZE, Region->Type, Region->Protect & ~PAGE_GUARD,
+ MmAlterViewAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Removing PAGE_GUARD protection failed : 0x%08x.\n", Status);
+ }
+
+ return STATUS_GUARD_PAGE_VIOLATION;
+ }
+
/*
* Lock the segment
*/
* Check if someone else is already handling this fault, if so wait
* for them
*/
- if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
+ if (Entry && MM_IS_WAIT_PTE(Entry))
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
HasSwapEntry = MmIsPageSwapEntry(Process, Address);
+ /* See if we should use a private page */
if (HasSwapEntry)
{
SWAPENTRY DummyEntry;
/*
* Is it a wait entry?
*/
- MmGetPageFileMapping(Process, Address, &SwapEntry);
-
- if (SwapEntry == MM_WAIT_ENTRY)
+ if (HasSwapEntry)
{
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
- MiWaitForPageEvent(NULL, NULL);
- MmLockAddressSpace(AddressSpace);
- return STATUS_MM_RESTART_OPERATION;
- }
+ MmGetPageFileMapping(Process, Address, &SwapEntry);
- /*
- * Must be private page we have swapped out.
- */
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
+ }
- /*
- * Sanity check
- */
- if (Segment->Flags & MM_PAGEFILE_SEGMENT)
- {
- DPRINT1("Found a swaped out private page in a pagefile section.\n");
- KeBugCheck(MEMORY_MANAGEMENT);
+ /*
+ * Must be private page we have swapped out.
+ */
+
+ /*
+ * Sanity check
+ */
+ if (Segment->Flags & MM_PAGEFILE_SEGMENT)
+ {
+ DPRINT1("Found a swaped out private page in a pagefile section.\n");
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
+ MmDeletePageFileMapping(Process, Address, &SwapEntry);
}
MmUnlockSectionSegment(Segment);
- MmDeletePageFileMapping(Process, Address, &SwapEntry);
+
+ /* Tell everyone else we are serving the fault. */
MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
MmUnlockAddressSpace(AddressSpace);
KeBugCheck(MEMORY_MANAGEMENT);
}
- Status = MmReadFromSwapPage(SwapEntry, Page);
- if (!NT_SUCCESS(Status))
+ if (HasSwapEntry)
{
- DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
- KeBugCheck(MEMORY_MANAGEMENT);
+ Status = MmReadFromSwapPage(SwapEntry, Page);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
+ KeBugCheck(MEMORY_MANAGEMENT);
+ }
}
+
MmLockAddressSpace(AddressSpace);
MmDeletePageFileMapping(Process, PAddress, &DummyEntry);
Status = MmCreateVirtualMapping(Process,
/*
* Store the swap entry for later use.
*/
- MmSetSavedSwapEntryPage(Page, SwapEntry);
+ if (HasSwapEntry)
+ MmSetSavedSwapEntryPage(Page, SwapEntry);
/*
* Add the page to the process's working set
return(Status);
}
- /*
- * Mark the offset within the section as having valid, in-memory
- * data
- */
+ /* Lock both segment and process address space while we proceed. */
MmLockAddressSpace(AddressSpace);
MmLockSectionSegment(Segment);
- Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
- MmUnlockSectionSegment(Segment);
MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
ASSERT(MmIsPagePresent(Process, PAddress));
MmInsertRmap(Page, Process, Address);
+ /* Set this section offset has being backed by our new page. */
+ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+ MmUnlockSectionSegment(Segment);
+
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
SwapEntry = SWAPENTRY_FROM_SSE(Entry);
+ /* See if a page op is running on this segment. */
+ if (SwapEntry == MM_WAIT_ENTRY)
+ {
+ MmUnlockSectionSegment(Segment);
+ MmUnlockAddressSpace(AddressSpace);
+ MiWaitForPageEvent(NULL, NULL);
+ MmLockAddressSpace(AddressSpace);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+
/*
* Release all our locks and read in the page from disk
*/
KeBugCheck(MEMORY_MANAGEMENT);
}
- /*
- * Mark the offset within the section as having valid, in-memory
- * data
- */
- Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
- MmUnlockSectionSegment(Segment);
-
/*
* Save the swap entry.
*/
MmSetSavedSwapEntryPage(Page, SwapEntry);
+
+ /* Map the page into the process address space */
Status = MmCreateVirtualMapping(Process,
PAddress,
Region->Protect,
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
+
+ /*
+ * Mark the offset within the section as having valid, in-memory
+ * data
+ */
+ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+ MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+ MmUnlockSectionSegment(Segment);
+
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
}
else
{
- /*
- * If the section offset is already in-memory and valid then just
- * take another reference to the page
- */
-
+ /* We already have a page on this section offset. Map it into the process address space. */
Page = PFN_FROM_SSE(Entry);
- MmSharePageEntrySectionSegment(Segment, &Offset);
- MmUnlockSectionSegment(Segment);
-
Status = MmCreateVirtualMapping(Process,
PAddress,
Attributes,
KeBugCheck(MEMORY_MANAGEMENT);
}
MmInsertRmap(Page, Process, Address);
+
+ /* Take a reference on it */
+ MmSharePageEntrySectionSegment(Segment, &Offset);
+ MmUnlockSectionSegment(Segment);
+
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%p\n", Address);
return(STATUS_SUCCESS);
PMM_REGION Region;
ULONG_PTR Entry;
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
- SWAPENTRY SwapEntry;
DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
+ /* Make sure we have a page mapping for this address. */
+ Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This is invalid access ! */
+ return Status;
+ }
+
/*
* Check if the page has already been set readwrite
*/
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
ASSERT(Region != NULL);
- /*
- * Lock the segment
- */
- MmLockSectionSegment(Segment);
-
- OldPage = MmGetPfnForProcess(Process, Address);
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
-
- MmUnlockSectionSegment(Segment);
/*
* Check if we are doing COW
return(STATUS_ACCESS_VIOLATION);
}
- if (IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != OldPage)
- {
- /* This is a private page. We must only change the page protection. */
- MmSetPageProtect(Process, Address, Region->Protect);
- return(STATUS_SUCCESS);
- }
-
- if(OldPage == 0)
- DPRINT("OldPage == 0!\n");
-
- /*
- * Get or create a pageop
- */
+ /* Get the page mapping this section offset. */
MmLockSectionSegment(Segment);
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- /*
- * Wait for any other operations to complete
- */
- if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
+ /* Get the current page mapping for the process */
+ ASSERT(MmIsPagePresent(Process, PAddress));
+ OldPage = MmGetPfnForProcess(Process, PAddress);
+ ASSERT(OldPage != 0);
+
+ if (IS_SWAP_FROM_SSE(Entry) ||
+ PFN_FROM_SSE(Entry) != OldPage)
{
MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
- MiWaitForPageEvent(NULL, NULL);
- /*
- * Restart the operation
- */
- MmLockAddressSpace(AddressSpace);
- DPRINT("Address 0x%p\n", Address);
- return(STATUS_MM_RESTART_OPERATION);
+ /* This is a private page. We must only change the page protection. */
+ MmSetPageProtect(Process, PAddress, Region->Protect);
+ return(STATUS_SUCCESS);
}
- MmDeleteRmap(OldPage, Process, PAddress);
- MmDeleteVirtualMapping(Process, PAddress, NULL, NULL);
- MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
-
- /*
- * Release locks now we have the pageop
- */
- MmUnlockSectionSegment(Segment);
- MmUnlockAddressSpace(AddressSpace);
-
/*
* Allocate a page
*/
/*
* Copy the old page
*/
- MiCopyFromUserPage(NewPage, OldPage);
+ NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
- MmLockAddressSpace(AddressSpace);
+ /*
+ * Unshare the old page.
+ */
+ DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
+ MmDeleteVirtualMapping(Process, PAddress, NULL, NULL);
+ MmDeleteRmap(OldPage, Process, PAddress);
+ MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
+ MmUnlockSectionSegment(Segment);
/*
* Set the PTE to point to the new page
*/
- MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
Status = MmCreateVirtualMapping(Process,
PAddress,
Region->Protect,
KeBugCheck(MEMORY_MANAGEMENT);
return(Status);
}
-
- /*
- * Unshare the old page.
- */
- DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
MmInsertRmap(NewPage, Process, PAddress);
- MmLockSectionSegment(Segment);
- MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
- MmUnlockSectionSegment(Segment);
MiSetPageEvent(Process, Address);
DPRINT("Address 0x%p\n", Address);
*/
MmUnlockSectionSegment(Context.Segment);
Context.WasDirty = FALSE;
- if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
{
Context.Private = TRUE;
}
}
else
{
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ OldIrql = MiAcquirePfnLock();
MmReferencePage(Page);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiReleasePfnLock(OldIrql);
}
MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
else
{
ULONG_PTR OldEntry;
+
+ MmLockSectionSegment(Context.Segment);
+
/*
* For non-private pages if the page wasn't direct mapped then
* set it back into the section segment entry so we don't loose
Address);
// If we got here, the previous entry should have been a wait
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
- MmLockSectionSegment(Context.Segment);
OldEntry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
ASSERT(OldEntry == 0 || OldEntry == MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
}
else
{
+ MmLockSectionSegment(Context.Segment);
Status = MmCreateVirtualMapping(Process,
Address,
MemoryArea->Protect,
Address);
Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+ MmUnlockSectionSegment(Context.Segment);
}
MmUnlockAddressSpace(AddressSpace);
MiSetPageEvent(NULL, NULL);
/*
* Check for a private (COWed) page.
*/
- if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
+ if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page)
{
Private = TRUE;
}
ASSERT(SwapEntry == 0);
//SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
#ifndef NEWCC
- CcRosMarkDirtyVacb(SharedCacheMap, Offset.QuadPart);
+ CcRosMarkDirtyFile(SharedCacheMap, Offset.QuadPart);
#endif
MmLockSectionSegment(Segment);
MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
return(STATUS_SUCCESS);
}
-static VOID
-MmAlterViewAttributes(PMMSUPPORT AddressSpace,
- PVOID BaseAddress,
- SIZE_T RegionSize,
- ULONG OldType,
- ULONG OldProtect,
- ULONG NewType,
- ULONG NewProtect)
-{
- PMEMORY_AREA MemoryArea;
- PMM_SECTION_SEGMENT Segment;
- BOOLEAN DoCOW = FALSE;
- ULONG i;
- PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);
- ASSERT(MemoryArea != NULL);
- Segment = MemoryArea->Data.SectionData.Segment;
- MmLockSectionSegment(Segment);
-
- if ((Segment->WriteCopy) &&
- (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE))
- {
- DoCOW = TRUE;
- }
-
- if (OldProtect != NewProtect)
- {
- for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
- {
- SWAPENTRY SwapEntry;
- PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
- ULONG Protect = NewProtect;
-
- /* Wait for a wait entry to disappear */
- do
- {
- MmGetPageFileMapping(Process, Address, &SwapEntry);
- if (SwapEntry != MM_WAIT_ENTRY)
- break;
- MiWaitForPageEvent(Process, Address);
- }
- while (TRUE);
-
- /*
- * If we doing COW for this segment then check if the page is
- * already private.
- */
- if (DoCOW && MmIsPagePresent(Process, Address))
- {
- LARGE_INTEGER Offset;
- ULONG_PTR Entry;
- PFN_NUMBER Page;
-
- Offset.QuadPart = (ULONG_PTR)Address - MA_GetStartingAddress(MemoryArea)
- + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
- Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- /*
- * An MM_WAIT_ENTRY is ok in this case... It'll just count as
- * IS_SWAP_FROM_SSE and we'll do the right thing.
- */
- Page = MmGetPfnForProcess(Process, Address);
-
- Protect = PAGE_READONLY;
- if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
- IS_SWAP_FROM_SSE(Entry) ||
- PFN_FROM_SSE(Entry) != Page)
- {
- Protect = NewProtect;
- }
- }
-
- if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
- {
- MmSetPageProtect(Process, Address,
- Protect);
- }
- }
- }
-
- MmUnlockSectionSegment(Segment);
-}
-
NTSTATUS
NTAPI
MmProtectSectionView(PMMSUPPORT AddressSpace,
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
- HANDLE FileHandle)
+ PFILE_OBJECT FileObject)
/*
* Create a section backed by a data file
*/
PROS_SECTION_OBJECT Section;
NTSTATUS Status;
LARGE_INTEGER MaximumSize;
- PFILE_OBJECT FileObject;
PMM_SECTION_SEGMENT Segment;
- ULONG FileAccess;
- IO_STATUS_BLOCK Iosb;
- LARGE_INTEGER Offset;
- CHAR Buffer;
FILE_STANDARD_INFORMATION FileInfo;
ULONG Length;
(PVOID*)&Section);
if (!NT_SUCCESS(Status))
{
+ ObDereferenceObject(FileObject);
return(Status);
}
/*
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
- /*
- * Reference the file handle
- */
- FileAccess = MiArm3GetCorrectFileAccessMask(SectionPageProtection);
- Status = ObReferenceObjectByHandle(FileHandle,
- FileAccess,
- IoFileObjectType,
- ExGetPreviousMode(),
- (PVOID*)(PVOID)&FileObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Section);
- return(Status);
- }
-
/*
* FIXME: This is propably not entirely correct. We can't look into
* the standard FCB header because it might not be initialized yet
sizeof(FILE_STANDARD_INFORMATION),
&FileInfo,
&Length);
- Iosb.Information = Length;
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Section);
{
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
- return STATUS_FILE_INVALID;
+ return STATUS_MAPPED_FILE_SIZE_ZERO;
}
}
if (MaximumSize.QuadPart > FileInfo.EndOfFile.QuadPart)
{
Status = IoSetInformation(FileObject,
- FileAllocationInformation,
+ FileEndOfFileInformation,
sizeof(LARGE_INTEGER),
&MaximumSize);
if (!NT_SUCCESS(Status))
if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
- /*
- * Read a bit so caching is initiated for the file object.
- * This is only needed because MiReadPage currently cannot
- * handle non-cached streams.
- */
- Offset.QuadPart = 0;
- Status = ZwReadFile(FileHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- &Buffer,
- sizeof (Buffer),
- &Offset,
- 0);
- if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
- {
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return(Status);
- }
- if (FileObject->SectionObjectPointer == NULL ||
- FileObject->SectionObjectPointer->SharedCacheMap == NULL)
- {
- /* FIXME: handle this situation */
- ObDereferenceObject(Section);
- ObDereferenceObject(FileObject);
- return STATUS_INVALID_PARAMETER;
- }
+ ObDereferenceObject(Section);
+ ObDereferenceObject(FileObject);
+ return STATUS_INVALID_FILE_FOR_SECTION;
}
/*
IN PEXEFMT_CB_ALLOCATE_SEGMENTS AllocateSegmentsCb
);
-/* TODO: this is a standard DDK/PSDK macro */
-#ifndef RTL_NUMBER_OF
-#define RTL_NUMBER_OF(ARR_) (sizeof(ARR_) / sizeof((ARR_)[0]))
-#endif
-
static PEXEFMT_LOADER ExeFmtpLoaders[] =
{
PeFmtCreateSection,
return STATUS_INVALID_FILE_FOR_SECTION;
#ifndef NEWCC
- if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
+ if (!CcIsFileCached(FileObject))
{
DPRINT1("Denying section creation due to missing cache initialization\n");
return STATUS_INVALID_FILE_FOR_SECTION;
Section->SectionPageProtection = SectionPageProtection;
Section->AllocationAttributes = AllocationAttributes;
-#ifndef NEWCC
- /*
- * Initialized caching for this file object if previously caching
- * was initialized for the same on disk file
- */
- Status = CcTryToInitializeFileCache(FileObject);
-#else
- Status = STATUS_SUCCESS;
-#endif
-
- if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL)
+ if (FileObject->SectionObjectPointer->ImageSectionObject == NULL)
{
NTSTATUS StatusExeFmt;
if(ImageSectionObject->Segments != NULL)
ExFreePool(ImageSectionObject->Segments);
+ /*
+ * If image file is empty, then return that the file is invalid for section
+ */
+ Status = StatusExeFmt;
+ if (StatusExeFmt == STATUS_END_OF_FILE)
+ {
+ Status = STATUS_INVALID_FILE_FOR_SECTION;
+ }
+
ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
- return(StatusExeFmt);
+ return(Status);
}
Section->ImageSection = ImageSectionObject;
Segment = MemoryArea->Data.SectionData.Segment;
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
- while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
+ while (Entry && MM_IS_WAIT_PTE(Entry))
{
MmUnlockSectionSegment(Segment);
MmUnlockAddressSpace(AddressSpace);
#ifndef NEWCC
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
- CcRosMarkDirtyVacb(SharedCacheMap, Offset.QuadPart + Segment->Image.FileOffset);
+ CcRosMarkDirtyFile(SharedCacheMap, Offset.QuadPart + Segment->Image.FileOffset);
#endif
ASSERT(SwapEntry == 0);
}
NTAPI
MiRosUnmapViewOfSection(IN PEPROCESS Process,
IN PVOID BaseAddress,
- IN ULONG Flags)
+ IN BOOLEAN SkipDebuggerNotify)
{
NTSTATUS Status;
PMEMORY_AREA MemoryArea;
MmUnlockAddressSpace(AddressSpace);
/* Notify debugger */
- if (ImageBaseAddress) DbgkUnMapViewOfSection(ImageBaseAddress);
+ if (ImageBaseAddress && !SkipDebuggerNotify) DbgkUnMapViewOfSection(ImageBaseAddress);
return(STATUS_SUCCESS);
}
_In_ SIZE_T SectionInformationLength,
_Out_opt_ PSIZE_T ResultLength)
{
- PROS_SECTION_OBJECT Section;
+ PSECTION Section;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
PAGED_CODE();
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- return _SEH2_GetExceptionCode();
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
return Status;
}
- switch (SectionInformationClass)
+ if (MiIsRosSectionObject(Section))
{
- case SectionBasicInformation:
- {
- PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+ PROS_SECTION_OBJECT RosSection = (PROS_SECTION_OBJECT)Section;
- _SEH2_TRY
+ switch (SectionInformationClass)
+ {
+ case SectionBasicInformation:
{
- Sbi->Attributes = Section->AllocationAttributes;
- if (Section->AllocationAttributes & SEC_IMAGE)
+ PSECTION_BASIC_INFORMATION Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation;
+
+ _SEH2_TRY
{
- Sbi->BaseAddress = 0;
- Sbi->Size.QuadPart = 0;
+ Sbi->Attributes = RosSection->AllocationAttributes;
+ if (RosSection->AllocationAttributes & SEC_IMAGE)
+ {
+ Sbi->BaseAddress = 0;
+ Sbi->Size.QuadPart = 0;
+ }
+ else
+ {
+ Sbi->BaseAddress = (PVOID)RosSection->Segment->Image.VirtualAddress;
+ Sbi->Size.QuadPart = RosSection->Segment->Length.QuadPart;
+ }
+
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
}
- else
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Sbi->BaseAddress = (PVOID)Section->Segment->Image.VirtualAddress;
- Sbi->Size.QuadPart = Section->Segment->Length.QuadPart;
+ Status = _SEH2_GetExceptionCode();
}
+ _SEH2_END;
- if (ResultLength != NULL)
- {
- *ResultLength = sizeof(SECTION_BASIC_INFORMATION);
- }
- Status = STATUS_SUCCESS;
+ break;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+
+ case SectionImageInformation:
{
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
- break;
- }
+ _SEH2_TRY
+ {
+ if (RosSection->AllocationAttributes & SEC_IMAGE)
+ {
+ PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
+ ImageSectionObject = RosSection->ImageSection;
- case SectionImageInformation:
- {
- PSECTION_IMAGE_INFORMATION Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation;
+ *Sii = ImageSectionObject->ImageInformation;
+ }
- _SEH2_TRY
- {
- if (Section->AllocationAttributes & SEC_IMAGE)
+ if (ResultLength != NULL)
+ {
+ *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+ }
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- PMM_IMAGE_SECTION_OBJECT ImageSectionObject;
- ImageSectionObject = Section->ImageSection;
-
- *Sii = ImageSectionObject->ImageInformation;
+ Status = _SEH2_GetExceptionCode();
}
+ _SEH2_END;
- if (ResultLength != NULL)
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch(SectionInformationClass)
+ {
+ case SectionBasicInformation:
+ {
+ SECTION_BASIC_INFORMATION Sbi;
+
+ Sbi.Size = Section->SizeOfSection;
+ Sbi.BaseAddress = (PVOID)Section->Address.StartingVpn;
+
+ Sbi.Attributes = 0;
+ if (Section->u.Flags.Image)
+ Sbi.Attributes |= SEC_IMAGE;
+ if (Section->u.Flags.Commit)
+ Sbi.Attributes |= SEC_COMMIT;
+ if (Section->u.Flags.Reserve)
+ Sbi.Attributes |= SEC_RESERVE;
+ if (Section->u.Flags.File)
+ Sbi.Attributes |= SEC_FILE;
+ if (Section->u.Flags.Image)
+ Sbi.Attributes |= SEC_IMAGE;
+
+ /* FIXME : Complete/test the list of flags passed back from NtCreateSection */
+
+ _SEH2_TRY
{
- *ResultLength = sizeof(SECTION_IMAGE_INFORMATION);
+ *((SECTION_BASIC_INFORMATION*)SectionInformation) = Sbi;
+ if (ResultLength)
+ *ResultLength = sizeof(Sbi);
}
- Status = STATUS_SUCCESS;
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ break;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ case SectionImageInformation:
{
- Status = _SEH2_GetExceptionCode();
+ if (!Section->u.Flags.Image)
+ {
+ Status = STATUS_SECTION_NOT_IMAGE;
+ }
+ else
+ {
+ /* Currently not supported */
+ ASSERT(FALSE);
+ }
+ break;
}
- _SEH2_END;
-
- break;
}
}
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
{
DPRINT1("CC failure: %lx\n", Status);
+ if (FileObject)
+ ObDereferenceObject(FileObject);
return Status;
}
// Caching is initialized...
+
+ // Hack of the hack: actually, it might not be initialized if FSD init on effective right and if file is null-size
+ // In such case, force cache by initiating a write IRP
+ if (Status == STATUS_END_OF_FILE && !(AllocationAttributes & SEC_IMAGE) && FileObject != NULL &&
+ (FileObject->SectionObjectPointer == NULL || FileObject->SectionObjectPointer->SharedCacheMap == NULL))
+ {
+ Buffer = 0xdb;
+ Status = ZwWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &Buffer,
+ sizeof(Buffer),
+ &ByteOffset,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ LARGE_INTEGER Zero;
+ Zero.QuadPart = 0LL;
+
+ Status = IoSetInformation(FileObject,
+ FileEndOfFileInformation,
+ sizeof(LARGE_INTEGER),
+ &Zero);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ }
}
#endif
MaximumSize,
SectionPageProtection,
AllocationAttributes,
- FileHandle);
- if (FileObject)
- ObDereferenceObject(FileObject);
+ FileObject);
}
#else
else if (FileHandle != NULL || FileObject != NULL)
MaximumSize,
SectionPageProtection,
AllocationAttributes);
+ if (FileObject)
+ ObDereferenceObject(FileObject);
}
return Status;