Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenregion.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
1.7.6.1
|