typedef struct _SEGMENT {
struct _CONTROL_AREA *ControlArea;
ULONG TotalNumberOfPtes;
ULONG NonExtendedPtes;
ULONG Spare0;
UINT64 SizeOfSegment;
MMPTE SegmentPteTemplate;
SIZE_T NumberOfCommittedPages;
PMMEXTEND_INFO ExtendInfo;
SEGMENT_FLAGS SegmentFlags;
PVOID BasedAddress;//映象基地址
//
// The fields below are for image & pagefile-backed sections only.
// Common fields are above and new common entries must be added to
// both the SEGMENT and MAPPED_FILE_SEGMENT declarations.
//
union {
SIZE_T ImageCommitment; // for image-backed sections only
PEPROCESS CreatingProcess; // for pagefile-backed sections only
} u1;
union {
PSECTION_IMAGE_INFORMATION ImageInformation; // for images only
PVOID FirstMappedVa; // for pagefile-backed sections only
} u2;
PMMPTE PrototypePte;
MMPTE ThePtes[MM_PROTO_PTE_ALIGNMENT / PAGE_SIZE];
} SEGMENT, *PSEGMENT;
NTSTATUS MiCreateImageFileMap ( IN PFILE_OBJECT File, OUT PSEGMENT *Segment )
{
PageFrameNumber = MiGetPageForHeader (TRUE);
Base = MiCopyHeaderIfResident (File, PageFrameNumber);
if(base==NULL)
{
IoPageRead()
}
在这判断File是不是image文件
接着
FileHeader = &NtHeader->FileHeader;
FileHeaderNumberOfSections = FileHeader->NumberOfSections;
NumberOfSubsections = FileHeader->NumberOfSections;
//
// The image alignment is less than the page size,
// map the image with a single subsection.
//
ControlArea = ExAllocatePoolWithTag (NonPagedPool,
sizeof(CONTROL_AREA) + sizeof(SUBSECTION),
MMCONTROL);
SubsectionsAllocated = 1;
SingleSubsection = TRUE;
Subsection = (PSUBSECTION)(ControlArea + 1);
SizeOfSegment = sizeof(SEGMENT) + (sizeof(MMPTE) * ((ULONG)NumberOfPtes - 1)) +
sizeof(SECTION_IMAGE_INFORMATION);
NewSegment = ExAllocatePoolWithTag (PagedPool | POOL_MM_ALLOCATION,
SizeOfSegment,
MMSECT);
*Segment = NewSegment;
RtlZeroMemory (NewSegment, sizeof(SEGMENT));
NewSegment->PrototypePte = &NewSegment->ThePtes[0];
PointerPte = &NewSegment->ThePtes[0];
ImageAlignment = NtHeader32->OptionalHeader.SectionAlignment;
FileAlignment = NtHeader32->OptionalHeader.FileAlignment - 1;
SizeOfImage = NtHeader32->OptionalHeader.SizeOfImage;
LoaderFlags = NtHeader32->OptionalHeader.LoaderFlags;
ImageBase = NtHeader32->OptionalHeader.ImageBase;
SizeOfHeaders = NtHeader32->OptionalHeader.SizeOfHeaders;
NumberOfPtes = BYTES_TO_PAGES (SizeOfImage);//算出映像大小
Pfn1->u2.Blink = (PFN_NUMBER) PointerPte; //pfn1是MiCopyHeaderIfResident函数的ImagePageFrameNumber参数对应的PFN结构
NewSegment->ControlArea = ControlArea;
NewSegment->u2.ImageInformation =
(PSECTION_IMAGE_INFORMATION)((PCHAR)NewSegment + sizeof(SEGMENT) +
(sizeof(MMPTE) * (NumberOfPtes - 1)));
NewSegment->TotalNumberOfPtes = (ULONG) NumberOfPtes;
NewSegment->NonExtendedPtes = (ULONG) NumberOfPtes;
NewSegment->SizeOfSegment = NumberOfPtes * PAGE_SIZE;
PointerPte = NewSegment->PrototypePte;
Subsection->SubsectionBase = PointerPte; //Subsection是ControlArea结构后面的那个,
ControlArea->Segment = NewSegment;
//在这里就会判断下文件是不是在U盘,网络文件,或者floppy等介质上面
if ((ActiveDataReferences == TRUE) ||
(IoIsDeviceEjectable(File->DeviceObject)) ||
((FileHeader->Characteristics &
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) &&
(FILE_REMOVABLE_MEDIA & File->DeviceObject->Characteristics)) ||
((FileHeader->Characteristics &
IMAGE_FILE_NET_RUN_FROM_SWAP) &&
(FILE_REMOTE_DEVICE & File->DeviceObject->Characteristics))) {
//
// This file resides on a floppy disk or a removable media or
// network with flags set indicating it should be copied
// to the paging file.
//
ControlArea->u.Flags.FloppyMedia = 1;
}
if (FILE_REMOTE_DEVICE & File->DeviceObject->Characteristics) {
//
// This file resides on a redirected drive.
//
ControlArea->u.Flags.Networked = 1;
}
}
PVOID MiCopyHeaderIfResident ( IN PFILE_OBJECT File, IN PFN_NUMBER ImagePageFrameNumber )
{
//MiCopyHeaderIfResident函数作用就是把对应文件的一个头先copy出来,作法是这样的:
//ImagePageFrameNumber 是事先调用者调用MiGetPageForHeader函数找到一个空闲物理页
//第一步,找一个buffer来返回要copy的数据,这个buffer就是返回值ImagePage了
//先用MiReserveSystemPtes函数获取一个PTE,再把里面的PFN改成ImagePageFrameNumber
//接着使用MiGetVirtualAddressMappedByPte就可以获取对应的虚拟地址ImagePage了。这个有点手工打造物理映射的味道
//第二步,查找目标数据,但目标现在只有fileobject参数。作法如下
//ControlArea = (PCONTROL_AREA) fileobject->SectionObjectPointer->DataSectionObject;
/*
if (ControlArea->u.Flags.Rom == 0) {
Subsection = (PSUBSECTION) (ControlArea + 1);
}
else {
Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1);
}
PointerPte = Subsection->SubsectionBase;
DataPage = MiMapPageInHyperSpaceAtDpc (Process, PageFrameIndex);//PageFrameIndex是从PointerPte中获取的
*/
//最后RtlCopyMemory (ImagePage, DataPage, PAGE_SIZE);就完成了
ControlArea = (PCONTROL_AREA) SectionObjectPointer->DataSectionObject;
ImagePte = MiReserveSystemPtes (1, SystemPteSpace);
if (ImagePte == NULL) {
return NULL;
}
ImagePage = MiGetVirtualAddressMappedByPte (ImagePte);
ASSERT (ImagePte->u.Hard.Valid == 0);
PteContents = ValidKernelPte;
PteContents.u.Hard.PageFrameNumber = ImagePageFrameNumber;
MI_WRITE_VALID_PTE (ImagePte, PteContents);
if (ControlArea->u.Flags.Rom == 0) {
Subsection = (PSUBSECTION) (ControlArea + 1);
}
else {
Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1);
}
PointerPte = Subsection->SubsectionBase;
DataPage = MiMapPageInHyperSpaceAtDpc (Process, PageFrameIndex);//PageFrameIndex是从PointerPte中获取的
RtlCopyMemory (ImagePage, DataPage, PAGE_SIZE);
}