|
|
Definition at line 108 of file region.c.
Referenced by MiRosAllocateVirtualMemory(), and MmProtectSectionView().
{
PMM_REGION InitialRegion;
PVOID InitialBaseAddress = NULL;
PMM_REGION NewRegion;
PLIST_ENTRY CurrentEntry;
PMM_REGION CurrentRegion = NULL;
PVOID CurrentBaseAddress;
SIZE_T RemainingLength;
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
&InitialBaseAddress);
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
{
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
StartAddress, Length, NewType, NewProtect,
AddressSpace, AlterFunc);
if (NewRegion == NULL)
{
return(STATUS_NO_MEMORY);
}
if(NewRegion->Length < Length)
RemainingLength = Length - NewRegion->Length;
else
RemainingLength = 0;
}
else
{
NewRegion = InitialRegion;
if(((ULONG_PTR)InitialBaseAddress + NewRegion->Length) <
((ULONG_PTR)StartAddress + Length))
RemainingLength = ((ULONG_PTR)StartAddress + Length) - ((ULONG_PTR)InitialBaseAddress + NewRegion->Length);
else
RemainingLength = 0;
}
CurrentEntry = NewRegion->RegionListEntry.Flink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength &&
CurrentEntry != RegionListHead)
{
if (CurrentRegion->Type != NewType ||
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
CurrentBaseAddress = (PVOID)((ULONG_PTR)CurrentBaseAddress + CurrentRegion->Length);
NewRegion->Length += CurrentRegion->Length;
RemainingLength -= CurrentRegion->Length;
CurrentEntry = CurrentEntry->Flink;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
}
if (RemainingLength > 0 && CurrentEntry != RegionListHead)
{
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type != NewType ||
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, RemainingLength,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
NewRegion->Length += RemainingLength;
CurrentRegion->Length -= RemainingLength;
}
if (NewRegion->RegionListEntry.Flink != RegionListHead)
{
CurrentEntry = NewRegion->RegionListEntry.Flink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type == NewRegion->Type &&
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
}
}
if (NewRegion->RegionListEntry.Blink != RegionListHead)
{
CurrentEntry = NewRegion->RegionListEntry.Blink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type == NewRegion->Type &&
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
}
}
return(STATUS_SUCCESS);
}
|