ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

region.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/mm/region.c
00005  * PURPOSE:         No purpose listed.
00006  *
00007  * PROGRAMMERS:     David Welch
00008  */
00009 
00010 /* INCLUDE *****************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* FUNCTIONS *****************************************************************/
00017 
00018 static VOID
00019 InsertAfterEntry(PLIST_ENTRY Previous,
00020                  PLIST_ENTRY Entry)
00021 /*
00022  * FUNCTION: Insert a list entry after another entry in the list
00023  */
00024 {
00025    Previous->Flink->Blink = Entry;
00026 
00027    Entry->Flink = Previous->Flink;
00028    Entry->Blink = Previous;
00029 
00030    Previous->Flink = Entry;
00031 }
00032 
00033 static PMM_REGION
00034 MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress,
00035               PVOID StartAddress, SIZE_T Length, ULONG NewType,
00036               ULONG NewProtect, PMMSUPPORT AddressSpace,
00037               PMM_ALTER_REGION_FUNC AlterFunc)
00038 {
00039    PMM_REGION NewRegion1;
00040    PMM_REGION NewRegion2;
00041    SIZE_T InternalLength;
00042 
00043    /* Allocate this in front otherwise the failure case is too difficult. */
00044    NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
00045                                       TAG_MM_REGION);
00046    if (NewRegion2 == NULL)
00047    {
00048       return(NULL);
00049    }
00050 
00051    /* Create the new region. */
00052    NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
00053                                       TAG_MM_REGION);
00054    if (NewRegion1 == NULL)
00055    {
00056       ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
00057       return(NULL);
00058    }
00059    NewRegion1->Type = NewType;
00060    NewRegion1->Protect = NewProtect;
00061    InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
00062    InternalLength = min(InternalLength, Length);
00063    NewRegion1->Length = InternalLength;
00064    InsertAfterEntry(&InitialRegion->RegionListEntry,
00065                     &NewRegion1->RegionListEntry);
00066 
00067    /*
00068     * Call our helper function to do the changes on the addresses contained
00069     * in the initial region.
00070     */
00071    AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
00072              InitialRegion->Protect, NewType, NewProtect);
00073 
00074    /*
00075     * If necessary create a new region for the portion of the initial region
00076     * beyond the range of addresses to alter.
00077     */
00078    if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
00079    {
00080       NewRegion2->Type = InitialRegion->Type;
00081       NewRegion2->Protect = InitialRegion->Protect;
00082       NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
00083                            ((char*)StartAddress + Length);
00084       InsertAfterEntry(&NewRegion1->RegionListEntry,
00085                        &NewRegion2->RegionListEntry);
00086    }
00087    else
00088    {
00089       ExFreePoolWithTag(NewRegion2, TAG_MM_REGION);
00090    }
00091 
00092    /* Either remove or shrink the initial region. */
00093    if (InitialBaseAddress == StartAddress)
00094    {
00095       RemoveEntryList(&InitialRegion->RegionListEntry);
00096       ExFreePoolWithTag(InitialRegion, TAG_MM_REGION);
00097    }
00098    else
00099    {
00100       InitialRegion->Length = (char*)StartAddress - (char*)InitialBaseAddress;
00101    }
00102 
00103    return(NewRegion1);
00104 }
00105 
00106 NTSTATUS
00107 NTAPI
00108 MmAlterRegion(PMMSUPPORT AddressSpace, PVOID BaseAddress,
00109               PLIST_ENTRY RegionListHead, PVOID StartAddress, SIZE_T Length,
00110               ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
00111 {
00112    PMM_REGION InitialRegion;
00113    PVOID InitialBaseAddress = NULL;
00114    PMM_REGION NewRegion;
00115    PLIST_ENTRY CurrentEntry;
00116    PMM_REGION CurrentRegion = NULL;
00117    PVOID CurrentBaseAddress;
00118    SIZE_T RemainingLength;
00119 
00120    /*
00121     * Find the first region containing part of the range of addresses to
00122     * be altered.
00123     */
00124    InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
00125                                 &InitialBaseAddress);
00126    /*
00127     * If necessary then split the region into the affected and unaffected parts.
00128     */
00129    if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
00130    {
00131       NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
00132                                 StartAddress, Length, NewType, NewProtect,
00133                                 AddressSpace, AlterFunc);
00134       if (NewRegion == NULL)
00135       {
00136          return(STATUS_NO_MEMORY);
00137       }
00138       if(NewRegion->Length < Length)
00139          RemainingLength = Length - NewRegion->Length;
00140       else
00141          RemainingLength = 0;
00142    }
00143    else
00144    {
00145       NewRegion = InitialRegion;
00146       if(((ULONG_PTR)InitialBaseAddress + NewRegion->Length) <
00147             ((ULONG_PTR)StartAddress + Length))
00148          RemainingLength = ((ULONG_PTR)StartAddress + Length) - ((ULONG_PTR)InitialBaseAddress + NewRegion->Length);
00149       else
00150          RemainingLength = 0;
00151    }
00152 
00153    /*
00154     * Free any complete regions that are containing in the range of addresses
00155     * and call the helper function to actually do the changes.
00156     */
00157    CurrentEntry = NewRegion->RegionListEntry.Flink;
00158    CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
00159                                      RegionListEntry);
00160    CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
00161    while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength &&
00162           CurrentEntry != RegionListHead)
00163    {
00164       if (CurrentRegion->Type != NewType ||
00165             CurrentRegion->Protect != NewProtect)
00166       {
00167          AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
00168                    CurrentRegion->Type, CurrentRegion->Protect,
00169                    NewType, NewProtect);
00170       }
00171 
00172       CurrentBaseAddress = (PVOID)((ULONG_PTR)CurrentBaseAddress + CurrentRegion->Length);
00173       NewRegion->Length += CurrentRegion->Length;
00174       RemainingLength -= CurrentRegion->Length;
00175       CurrentEntry = CurrentEntry->Flink;
00176       RemoveEntryList(&CurrentRegion->RegionListEntry);
00177       ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
00178       CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
00179                                         RegionListEntry);
00180    }
00181 
00182    /*
00183     * Split any final region.
00184     */
00185    if (RemainingLength > 0 && CurrentEntry != RegionListHead)
00186    {
00187       CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
00188                                         RegionListEntry);
00189       if (CurrentRegion->Type != NewType ||
00190             CurrentRegion->Protect != NewProtect)
00191       {
00192          AlterFunc(AddressSpace, CurrentBaseAddress, RemainingLength,
00193                    CurrentRegion->Type, CurrentRegion->Protect,
00194                    NewType, NewProtect);
00195       }
00196       NewRegion->Length += RemainingLength;
00197       CurrentRegion->Length -= RemainingLength;
00198    }
00199 
00200    /*
00201     * If the region after the new region has the same type then merge them.
00202     */
00203    if (NewRegion->RegionListEntry.Flink != RegionListHead)
00204    {
00205       CurrentEntry = NewRegion->RegionListEntry.Flink;
00206       CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
00207                                         RegionListEntry);
00208       if (CurrentRegion->Type == NewRegion->Type &&
00209             CurrentRegion->Protect == NewRegion->Protect)
00210       {
00211          NewRegion->Length += CurrentRegion->Length;
00212          RemoveEntryList(&CurrentRegion->RegionListEntry);
00213          ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
00214       }
00215    }
00216 
00217    /*
00218     * If the region before the new region has the same type then merge them.
00219     */
00220    if (NewRegion->RegionListEntry.Blink != RegionListHead)
00221    {
00222       CurrentEntry = NewRegion->RegionListEntry.Blink;
00223       CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
00224                                         RegionListEntry);
00225       if (CurrentRegion->Type == NewRegion->Type &&
00226             CurrentRegion->Protect == NewRegion->Protect)
00227       {
00228          NewRegion->Length += CurrentRegion->Length;
00229          RemoveEntryList(&CurrentRegion->RegionListEntry);
00230          ExFreePoolWithTag(CurrentRegion, TAG_MM_REGION);
00231       }
00232    }
00233 
00234    return(STATUS_SUCCESS);
00235 }
00236 
00237 VOID
00238 NTAPI
00239 MmInitializeRegion(PLIST_ENTRY RegionListHead, SIZE_T Length, ULONG Type,
00240                    ULONG Protect)
00241 {
00242    PMM_REGION Region;
00243 
00244    Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
00245                                   TAG_MM_REGION);
00246    if (!Region) return;
00247 
00248    Region->Type = Type;
00249    Region->Protect = Protect;
00250    Region->Length = Length;
00251    InitializeListHead(RegionListHead);
00252    InsertHeadList(RegionListHead, &Region->RegionListEntry);
00253 }
00254 
00255 PMM_REGION
00256 NTAPI
00257 MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address,
00258              PVOID* RegionBaseAddress)
00259 {
00260    PLIST_ENTRY current_entry;
00261    PMM_REGION current;
00262    PVOID StartAddress = BaseAddress;
00263 
00264    current_entry = RegionListHead->Flink;
00265    while (current_entry != RegionListHead)
00266    {
00267       current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
00268 
00269       if (StartAddress <= Address &&
00270             ((char*)StartAddress + current->Length) > (char*)Address)
00271       {
00272          if (RegionBaseAddress != NULL)
00273          {
00274             *RegionBaseAddress = StartAddress;
00275          }
00276          return(current);
00277       }
00278 
00279       current_entry = current_entry->Flink;
00280 
00281       StartAddress = (PVOID)((ULONG_PTR)StartAddress + current->Length);
00282 
00283    }
00284    return(NULL);
00285 }

Generated on Sat May 26 2012 04:22:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.