test: extsect.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# extsect.c File Reference

`#include "mi.h"`

Go to the source code of this file.

## Functions

NTSTATUS | NtExtendSection (IN HANDLE SectionHandle, IN OUT PLARGE_INTEGER NewSectionSize)
NTSTATUS | MmExtendSection (IN PVOID SectionToExtend, IN OUT PLARGE_INTEGER NewSectionSize, IN ULONG IgnoreFileSizeChecking)
PMMPTE FASTCALL | MiGetProtoPteAddressExtended (IN PMMVAD Vad, IN ULONG_PTR Vpn)
PSUBSECTION FASTCALL | MiLocateSubsection (IN PMMVAD Vad, IN ULONG_PTR Vpn)

## Function Documentation

PMMPTE FASTCALL MiGetProtoPteAddressExtended | ( | IN PMMVAD | Vad,
|  | IN ULONG_PTR | Vpn
| ) |

Definition at line 685 of file extsect.c.

References ASSERT, _SUBSECTION::NextSubsection, NULL, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, and _CONTROL_AREA::u.

    00692                    :
    00693
    00694     This function calculates the address of the prototype PTE
    00695     for the corresponding virtual address.
    00696
    00697 Arguments:
    00698
    00699
    00700     Vad - Supplies a pointer to the virtual address desciptor which
    00701           encompasses the virtual address.
    00702
    00703     Vpn - Supplies the virtual page number to locate a prototype PTE
    00704                      for.
    00705
    00706 Return Value:
    00707
    00708     The corresponding prototype PTE address.
    00709
    00710 --*/
    00711
    00712 {
    00713     PSUBSECTION Subsection;
    00714     PCONTROL_AREA ControlArea;
    00715     ULONG PteOffset;
    00716
    00717     ControlArea = Vad->ControlArea;
    00718
    00719     if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
    00720         Subsection = (PSUBSECTION)(ControlArea + 1);
    00721     }
    00722     else {
    00723         Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1);
    00724     }
    00725
    00726     //
    00727     // Locate the subsection which contains the First Prototype PTE
    00728     // for this VAD.
    00729     //
    00730
    00731     while ((Vad->FirstPrototypePte < Subsection->SubsectionBase) ||
    00732            (Vad->FirstPrototypePte >=
    00733                &Subsection->SubsectionBase[Subsection->PtesInSubsection])) {
    00734
    00735         //
    00736         // Get the next subsection.
    00737         //
    00738
    00739         Subsection = Subsection->NextSubsection;
    00740         if (Subsection == NULL) {
    00741             return NULL;
    00742         }
    00743     }
    00744
    00745     //
    00746     // How many PTEs beyond this subsection must we go?
    00747     //
    00748
    00749     PteOffset = (ULONG) (((Vpn - Vad->StartingVpn) +
    00750                  (ULONG)(Vad->FirstPrototypePte - Subsection->SubsectionBase)) -
    00751                  Subsection->PtesInSubsection);
    00752
    00753 // DbgPrint("map extended subsection offset = %lx\n",PteOffset);
    00754
    00755     ASSERT (PteOffset < 0xF0000000);
    00756
    00757     PteOffset += Subsection->PtesInSubsection;
    00758
    00759     //
    00760     // Locate the subsection which contains the prototype PTEs.
    00761     //
    00762
    00763     while (PteOffset >= Subsection->PtesInSubsection) {
    00764         PteOffset -= Subsection->PtesInSubsection;
    00765         Subsection = Subsection->NextSubsection;
    00766         if (Subsection == NULL) {
    00767             return NULL;
    00768         }
    00769     }
    00770
    00771     //
    00772     // The PTEs are in this subsection.
    00773     //
    00774
    00775     ASSERT (PteOffset < Subsection->PtesInSubsection);
    00776
    00777     return &Subsection->SubsectionBase[PteOffset];
    00778
    00779 }

PSUBSECTION FASTCALL MiLocateSubsection | ( | IN PMMVAD | Vad,
|  | IN ULONG_PTR | Vpn
| ) |

Definition at line 783 of file extsect.c.

References ASSERT, _SUBSECTION::NextSubsection, NULL, _SUBSECTION::PtesInSubsection, _SUBSECTION::SubsectionBase, and _CONTROL_AREA::u.

Referenced by MiDeleteVirtualAddresses(), and MmFlushVirtualMemory().

    00790                    :
    00791
    00792     This function calculates the address of the subsection
    00793     for the corresponding virtual address.
    00794
    00795     This function only works for mapped files NOT mapped images.
    00796
    00797 Arguments:
    00798
    00799
    00800     Vad - Supplies a pointer to the virtual address desciptor which
    00801           encompasses the virtual address.
    00802
    00803     Vpn - Supplies the virtual page number to locate a prototype PTE
    00804                      for.
    00805
    00806 Return Value:
    00807
    00808     The corresponding prototype subsection.
    00809
    00810 --*/
    00811
    00812 {
    00813     PSUBSECTION Subsection;
    00814     PCONTROL_AREA ControlArea;
    00815     ULONG PteOffset;
    00816
    00817     ControlArea = Vad->ControlArea;
    00818
    00819     if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
    00820         Subsection = (PSUBSECTION)(ControlArea + 1);
    00821     }
    00822     else {
    00823         Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1);
    00824     }
    00825
    00826     Subsection = (PSUBSECTION)(ControlArea + 1);
    00827
    00828 #if 0
    00829     if (Subsection->NextSubsection == NULL) {
    00830
    00831         //
    00832         // There is only one subsection, don't look any further.
    00833         //
    00834
    00835         return Subsection;
    00836     }
    00837 #endif //0
    00838
    00839     if (ControlArea->u.Flags.Image) {
    00840
    00841         //
    00842         // There is only one subsection, don't look any further.
    00843         //
    00844
    00845         return Subsection;
    00846     }
    00847
    00848     //
    00849     // Locate the subsection which contains the First Prototype PTE
    00850     // for this VAD.
    00851     //
    00852
    00853     while ((Vad->FirstPrototypePte < Subsection->SubsectionBase) ||
    00854            (Vad->FirstPrototypePte >=
    00855                &Subsection->SubsectionBase[Subsection->PtesInSubsection])) {
    00856
    00857         //
    00858         // Get the next subsection.
    00859         //
    00860
    00861         Subsection = Subsection->NextSubsection;
    00862         if (Subsection == NULL) {
    00863             return NULL;
    00864         }
    00865     }
    00866
    00867     //
    00868     // How many PTEs beyond this subsection must we go?
    00869     //
    00870
    00871     PteOffset = (ULONG)((Vpn - Vad->StartingVpn) +
    00872          (ULONG)(Vad->FirstPrototypePte - Subsection->SubsectionBase));
    00873
    00874     ASSERT (PteOffset < 0xF0000000);
    00875
    00876     //
    00877     // Locate the subsection which contains the prototype PTEs.
    00878     //
    00879
    00880     while (PteOffset >= Subsection->PtesInSubsection) {
    00881         PteOffset -= Subsection->PtesInSubsection;
    00882         Subsection = Subsection->NextSubsection;
    00883         if (Subsection == NULL) {
    00884             return NULL;
    00885         }
    00886     }
    00887
    00888     //
    00889     // The PTEs are in this subsection.
    00890     //
    00891
    00892     return Subsection;
    00893 }
    }

NTSTATUS MmExtendSection | ( | IN PVOID | SectionToExtend,
|  | IN OUT PLARGE_INTEGER | NewSectionSize,
|  | IN ULONG | IgnoreFileSizeChecking
| ) |

Definition at line 201 of file extsect.c.

References ASSERT, _MMEXTEND_INFO::CommittedSize, _SUBSECTION::ControlArea, _SEGMENT::ControlArea, DbgPrint, _CONTROL_AREA::DereferenceList, EX_REAL_POOL_USAGE, ExAcquireResourceExclusive, ExAllocatePoolWithTag, ExFreePool(), ExReleaseResource, _SEGMENT::ExtendInfo, FALSE, _CONTROL_AREA::FilePointer, FsRtlGetFileSize(), FsRtlSetFileSize(), KeEnterCriticalRegion, KeLeaveCriticalRegion, Mi4KStartForSubsection, Mi4KStartFromSubsection, MI_GET_PROTECTION_FROM_SOFT_PTE, MI_MAXIMUM_SECTION_SIZE, MI_WRITE_INVALID_PTE, MiGetSubsectionAddressForPte, MM4K_MASK, MM4K_SHIFT, MMPTE, MmSectionBasedMutex, MmSectionExtendResource, MmSectionExtendSetResource, _SUBSECTION::NextSubsection, NonPagedPool, _CONTROL_AREA::NonPagedPoolUsage, NT_SUCCESS, NTSTATUS(), NULL, _SUBSECTION::NumberOfFullSectors, PAGE_SHIFT, PAGE_SIZE, PAGED_CODE, PagedPool, _CONTROL_AREA::PagedPoolUsage, PSECTION, _SUBSECTION::PtesInSubsection, ROUND_TO_PAGES, _CONTROL_AREA::Segment, _SEGMENT::SegmentPteTemplate, _SEGMENT::SizeOfSegment, Status, SUBSECTION, _SUBSECTION::SubsectionBase, _SEGMENT::TotalNumberOfPtes, TRUE, _MMPTE::u, _SUBSECTION::u, _CONTROL_AREA::u, and _SUBSECTION::UnusedPtes.

Referenced by CcInitializeCacheMap(), CcSetFileSizes(), MmCreateSection(), NtAllocateVirtualMemory(), and NtExtendSection().

    00209                    :
    00210
    00211     This function extends the size of the specified section.  If
    00212     the current size of the section is greater than or equal to the
    00213     specified section size, the size is not updated.
    00214
    00215 Arguments:
    00216
    00217     Section - Supplies a pointer to a referenced section object.
    00218
    00219     NewSectionSize - Supplies the new size for the section object.
    00220
    00221     IgnoreFileSizeChecking -  Supplies the value TRUE is file size
    00222                               checking should be ignored (i.e., it
    00223                               is being called from a file system which
    00224                               has already done the checks).  FALSE
    00225                               if the checks still need to be made.
    00226
    00227 Return Value:
    00228
    00229     Returns the status
    00230
    00231     TBS
    00232
    00233
    00234 --*/
    00235
    00236 {
    00237     PMMPTE PointerPte;
    00238     PMMPTE LastPte;
    00239     PMMPTE ExtendedPtes;
    00240     MMPTE TempPte;
    00241     PCONTROL_AREA ControlArea;
    00242     PSECTION Section;
    00243     PSUBSECTION LastSubsection;
    00244     PSUBSECTION ExtendedSubsection;
    00245     ULONG RequiredPtes;
    00246     ULONG NumberOfPtes;
    00247     ULONG PtesUsed;
    00248     ULONG AllocationSize;
    00249     UINT64 EndOfFile;
    00250     UINT64 NumberOfPtesForEntireFile;
    00251     NTSTATUS Status;
    00252     LARGE_INTEGER NumberOf4KsForEntireFile;
    00253     LARGE_INTEGER Starting4K;
    00254     LARGE_INTEGER Last4KChunk;
    00255
    00256     PAGED_CODE();
    00257
    00258     Section = (PSECTION)SectionToExtend;
    00259
    00260     //
    00261     // Make sure the section is really extendable - physical and
    00262     // image sections are not.
    00263     //
    00264
    00265     ControlArea = Section->Segment->ControlArea;
    00266
    00267     if ((ControlArea->u.Flags.PhysicalMemory || ControlArea->u.Flags.Image) ||
    00268          (ControlArea->FilePointer == NULL)) {
    00269         return STATUS_SECTION_NOT_EXTENDED;
    00270     }
    00271
    00272     //
    00273     // Acquire the section extension mutex, this blocks other threads from
    00274     // updating the size at the same time.
    00275     //
    00276
    00277     KeEnterCriticalRegion ();
    00278     ExAcquireResourceExclusive (&MmSectionExtendResource, TRUE);
    00279
    00280     //
    00281     // Each subsection is limited to 16TB - 64K because the NumberOfFullSectors
    00282     // and various other fields in the subsection are ULONGs.  For NT64, the
    00283     // allocation could be split into multiple subsections as needed to
    00284     // conform to this limit - this is not worth doing for NT32 unless
    00285     // sparse prototype PTE allocations are supported.
    00286     //
    00287
    00288     // This must be a multiple of the size of prototype pte allocation so any
    00289     // given prototype pte allocation will have the same subsection for all
    00290     // PTEs.
    00291     //
    00292     // The total section size is limited to 16PB - 4K because of the
    00293     // StartingSector4132 field in each subsection.
    00294     //
    00295
    00296     NumberOfPtesForEntireFile = (NewSectionSize->QuadPart + PAGE_SIZE - 1) >> PAGE_SHIFT;
    00297
    00298     NumberOfPtes = (ULONG)NumberOfPtesForEntireFile;
    00299
    00300     if (NewSectionSize->QuadPart > MI_MAXIMUM_SECTION_SIZE) {
    00301         Status = STATUS_SECTION_TOO_BIG;
    00302         goto ReleaseAndReturn;
    00303     }
    00304
    00305     if (NumberOfPtesForEntireFile > (UINT64)((MAXULONG_PTR / sizeof(MMPTE)) - sizeof (SEGMENT))) {
    00306         Status = STATUS_SECTION_TOO_BIG;
    00307         goto ReleaseAndReturn;
    00308     }
    00309
    00310     if (NumberOfPtesForEntireFile > (UINT64)NewSectionSize->QuadPart) {
    00311         Status = STATUS_SECTION_TOO_BIG;
    00312         goto ReleaseAndReturn;
    00313     }
    00314
    00315     if (ControlArea->u.Flags.WasPurged == 0) {
    00316
    00317         if ((UINT64)NewSectionSize->QuadPart <= (UINT64)Section->SizeOfSection.QuadPart) {
    00318             *NewSectionSize = Section->SizeOfSection;
    00319             goto ReleaseAndReturnSuccess;
    00320         }
    00321     }
    00322
    00323     //
    00324     // If a file handle was specified, set the allocation size of the file.
    00325     //
    00326
    00327     if (IgnoreFileSizeChecking == FALSE) {
    00328
    00329         //
    00330         // Release the resource so we don't deadlock with the file
    00331         // system trying to extend this section at the same time.
    00332         //
    00333
    00334         ExReleaseResource (&MmSectionExtendResource);
    00335
    00336         //
    00337         // Get a different resource to single thread query/set operations.
    00338         //
    00339
    00340         ExAcquireResourceExclusive (&MmSectionExtendSetResource, TRUE);
    00341
    00342         //
    00343         // Query the file size to see if this file really needs extending.
    00344         //
    00345         // If the specified size is less than the current size, return
    00346         // the current size.
    00347         //
    00348
    00349         Status = FsRtlGetFileSize (ControlArea->FilePointer,
    00350                                    (PLARGE_INTEGER)&EndOfFile);
    00351
    00352         if (!NT_SUCCESS (Status)) {
    00353             ExReleaseResource (&MmSectionExtendSetResource);
    00354             KeLeaveCriticalRegion ();
    00355             return Status;
    00356         }
    00357
    00358         if ((UINT64)NewSectionSize->QuadPart > EndOfFile) {
    00359
    00360             //
    00361             // Don't allow section extension unless the section was originally
    00362             // created with write access.  The check couldn't be done at create
    00363             // time without breaking existing binaries, so the caller gets the
    00364             // error at this point instead.
    00365             //
    00366
    00367             if (((Section->InitialPageProtection & PAGE_READWRITE) |
    00368                 (Section->InitialPageProtection & PAGE_EXECUTE_READWRITE)) == 0) {
    00369 #if DBG
    00370                     DbgPrint("Section extension failed %x\n", Section);
    00371 #endif
    00372                     ExReleaseResource (&MmSectionExtendSetResource);
    00373                     KeLeaveCriticalRegion ();
    00374                     return STATUS_SECTION_NOT_EXTENDED;
    00375             }
    00376
    00377             //
    00378             // Current file is smaller, attempt to set a new end of file.
    00379             //
    00380
    00381             EndOfFile = *(PUINT64)NewSectionSize;
    00382
    00383             Status = FsRtlSetFileSize (ControlArea->FilePointer,
    00384                                        (PLARGE_INTEGER)&EndOfFile);
    00385
    00386             if (!NT_SUCCESS (Status)) {
    00387                 ExReleaseResource (&MmSectionExtendSetResource);
    00388                 KeLeaveCriticalRegion ();
    00389                 return Status;
    00390             }
    00391         }
    00392
    00393         if (ControlArea->Segment->ExtendInfo) {
    00394             ExAcquireFastMutex (&MmSectionBasedMutex);
    00395             if (ControlArea->Segment->ExtendInfo) {
    00396                 ControlArea->Segment->ExtendInfo->CommittedSize = EndOfFile;
    00397             }
    00398             ExReleaseFastMutex (&MmSectionBasedMutex);
    00399         }
    00400
    00401         //
    00402         // Release the query/set resource and reacquire the extend section
    00403         // resource.
    00404         //
    00405
    00406         ExReleaseResource (&MmSectionExtendSetResource);
    00407         ExAcquireResourceExclusive (&MmSectionExtendResource, TRUE);
    00408     }
    00409
    00410     //
    00411     // Find the last subsection.
    00412     //
    00413
    00414     ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0);
    00415
    00416     LastSubsection = (PSUBSECTION)(ControlArea + 1);
    00417
    00418     while (LastSubsection->NextSubsection != NULL ) {
    00419         ASSERT (LastSubsection->UnusedPtes == 0);
    00420         LastSubsection = LastSubsection->NextSubsection;
    00421     }
    00422
    00423 #if DBG
    00424     MiSubsectionConsistent(LastSubsection);
    00425 #endif
    00426
    00427     //
    00428     // Does the structure need extending?
    00429     //
    00430
    00431     if (NumberOfPtes <= Section->Segment->TotalNumberOfPtes) {
    00432
    00433         //
    00434         // The segment is already large enough, just update
    00435         // the section size and return.
    00436         //
    00437
    00438         Section->SizeOfSection = *NewSectionSize;
    00439         if (Section->Segment->SizeOfSegment < (UINT64)NewSectionSize->QuadPart) {
    00440             //
    00441             // Only update if it is really bigger.
    00442             //
    00443
    00444             Section->Segment->SizeOfSegment = *(PUINT64)NewSectionSize;
    00445
    00446             Mi4KStartFromSubsection(&Starting4K, LastSubsection);
    00447
    00448             Last4KChunk.QuadPart = (NewSectionSize->QuadPart >> MM4K_SHIFT) - Starting4K.QuadPart;
    00449
    00450             ASSERT (Last4KChunk.HighPart == 0);
    00451
    00452             LastSubsection->NumberOfFullSectors = Last4KChunk.LowPart;
    00453             LastSubsection->u.SubsectionFlags.SectorEndOffset =
    00454                                         NewSectionSize->LowPart & MM4K_MASK;
    00455 #if DBG
    00456             MiSubsectionConsistent(LastSubsection);
    00457 #endif
    00458         }
    00459         goto ReleaseAndReturnSuccess;
    00460     }
    00461
    00462     //
    00463     // Add new structures to the section - locate the last subsection
    00464     // and add there.
    00465     //
    00466
    00467     RequiredPtes = NumberOfPtes - Section->Segment->TotalNumberOfPtes;
    00468     PtesUsed = 0;
    00469
    00470     if (RequiredPtes < LastSubsection->UnusedPtes) {
    00471
    00472         //
    00473         // There are ample PTEs to extend the section already allocated.
    00474         //
    00475
    00476         PtesUsed = RequiredPtes;
    00477         RequiredPtes = 0;
    00478
    00479     } else {
    00480         PtesUsed = LastSubsection->UnusedPtes;
    00481         RequiredPtes -= PtesUsed;
    00482     }
    00483
    00484     LastSubsection->PtesInSubsection += PtesUsed;
    00485     LastSubsection->UnusedPtes -= PtesUsed;
    00486     ControlArea->Segment->SizeOfSegment += (ULONG_PTR)PtesUsed * PAGE_SIZE;
    00487     ControlArea->Segment->TotalNumberOfPtes += PtesUsed;
    00488
    00489     if (RequiredPtes == 0) {
    00490
    00491         //
    00492         // There is no extension necessary, update the high VBN.
    00493         //
    00494
    00495         Mi4KStartFromSubsection(&Starting4K, LastSubsection);
    00496
    00497         Last4KChunk.QuadPart = (NewSectionSize->QuadPart >> MM4K_SHIFT) - Starting4K.QuadPart;
    00498
    00499         ASSERT (Last4KChunk.HighPart == 0);
    00500
    00501         LastSubsection->NumberOfFullSectors = Last4KChunk.LowPart;
    00502
    00503         LastSubsection->u.SubsectionFlags.SectorEndOffset =
    00504                                     NewSectionSize->LowPart & MM4K_MASK;
    00505 #if DBG
    00506         MiSubsectionConsistent(LastSubsection);
    00507 #endif
    00508     } else {
    00509
    00510         //
    00511         // An extension is required.  Allocate paged pool
    00512         // and populate it with prototype PTEs.
    00513         //
    00514
    00515         AllocationSize = (ULONG) ROUND_TO_PAGES (RequiredPtes * sizeof(MMPTE));
    00516
    00517         ExtendedPtes = (PMMPTE)ExAllocatePoolWithTag (PagedPool,
    00518                                                       AllocationSize,
    00519                                                       'ppmM');
    00520
    00521         if (ExtendedPtes == NULL) {
    00522
    00523             //
    00524             // The required pool could not be allocated.  Reset
    00525             // the subsection and control area fields to their
    00526             // original values.
    00527             //
    00528
    00529             LastSubsection->PtesInSubsection -= PtesUsed;
    00530             LastSubsection->UnusedPtes += PtesUsed;
    00531             ControlArea->Segment->TotalNumberOfPtes -= PtesUsed;
    00532             ControlArea->Segment->SizeOfSegment -= ((ULONG_PTR)PtesUsed * PAGE_SIZE);
    00533             Status = STATUS_INSUFFICIENT_RESOURCES;
    00534             goto ReleaseAndReturn;
    00535         }
    00536
    00537         //
    00538         // Allocate an extended subsection descriptor.
    00539         //
    00540
    00541         ExtendedSubsection = (PSUBSECTION)ExAllocatePoolWithTag (NonPagedPool,
    00542                                                      sizeof(SUBSECTION),
    00543                                                      'bSmM'
    00544                                                      );
    00545         if (ExtendedSubsection == NULL) {
    00546
    00547             //
    00548             // The required pool could not be allocated.  Reset
    00549             // the subsection and control area fields to their
    00550             // original values.
    00551             //
    00552
    00553             LastSubsection->PtesInSubsection -= PtesUsed;
    00554             LastSubsection->UnusedPtes += PtesUsed;
    00555             ControlArea->Segment->TotalNumberOfPtes -= PtesUsed;
    00556             ControlArea->Segment->SizeOfSegment -= ((ULONG_PTR)PtesUsed * PAGE_SIZE);
    00557             ExFreePool (ExtendedPtes);
    00558             Status = STATUS_INSUFFICIENT_RESOURCES;
    00559             goto ReleaseAndReturn;
    00560         }
    00561
    00562         ControlArea->NonPagedPoolUsage += EX_REAL_POOL_USAGE(sizeof(SUBSECTION));
    00563         ControlArea->PagedPoolUsage += AllocationSize;
    00564
    00565         ASSERT (ControlArea->DereferenceList.Flink == NULL);
    00566
    00567         NumberOf4KsForEntireFile.QuadPart =
    00568             ControlArea->Segment->SizeOfSegment >> MM4K_SHIFT;
    00569
    00570         Mi4KStartFromSubsection(&Starting4K, LastSubsection);
    00571
    00572         Last4KChunk.QuadPart = NumberOf4KsForEntireFile.QuadPart -
    00573                                    Starting4K.QuadPart;
    00574
    00575         if (LastSubsection->u.SubsectionFlags.SectorEndOffset) {
    00576             Last4KChunk.QuadPart += 1;
    00577         }
    00578
    00579         ASSERT(Last4KChunk.HighPart == 0);
    00580
    00581         LastSubsection->NumberOfFullSectors = Last4KChunk.LowPart;
    00582         LastSubsection->u.SubsectionFlags.SectorEndOffset = 0;
    00583
    00584         //
    00585         // If the number of sectors doesn't completely fill the PTEs (this can
    00586         // only happen when the page size is not MM4K), then fill it now.
    00587         //
    00588
    00589         if (LastSubsection->NumberOfFullSectors & ((1 << (PAGE_SHIFT - MM4K_SHIFT)) - 1)) {
    00590             LastSubsection->NumberOfFullSectors += 1;
    00591         }
    00592
    00593 #if DBG
    00594         MiSubsectionConsistent(LastSubsection);
    00595 #endif
    00596
    00597         ExtendedSubsection->u.LongFlags = 0;
    00598         ExtendedSubsection->NextSubsection = NULL;
    00599         ExtendedSubsection->UnusedPtes = (AllocationSize / sizeof(MMPTE)) -
    00600                                                     RequiredPtes;
    00601
    00602         ExtendedSubsection->ControlArea = ControlArea;
    00603         ExtendedSubsection->PtesInSubsection = RequiredPtes;
    00604
    00605         Starting4K.QuadPart += LastSubsection->NumberOfFullSectors;
    00606
    00607         Mi4KStartForSubsection(&Starting4K, ExtendedSubsection);
    00608
    00609         Last4KChunk.QuadPart =
    00610             (NewSectionSize->QuadPart >> MM4K_SHIFT) - Starting4K.QuadPart;
    00611
    00612         ASSERT(Last4KChunk.HighPart == 0);
    00613
    00614         ExtendedSubsection->NumberOfFullSectors = Last4KChunk.LowPart;
    00615         ExtendedSubsection->u.SubsectionFlags.SectorEndOffset =
    00616                                     NewSectionSize->LowPart & MM4K_MASK;
    00617
    00618 #if DBG
    00619         MiSubsectionConsistent(ExtendedSubsection);
    00620 #endif
    00621
    00622         ExtendedSubsection->SubsectionBase = ExtendedPtes;
    00623
    00624         PointerPte = ExtendedPtes;
    00625         LastPte = ExtendedPtes + (AllocationSize / sizeof(MMPTE));
    00626
    00627         if (ControlArea->FilePointer != NULL) {
    00628             TempPte.u.Long = MiGetSubsectionAddressForPte(ExtendedSubsection);
    00629         }
    00630 #if DBG
    00631         else {
    00632             DbgPrint("MM: Extend with no control area file pointer %x %x\n",
    00633                 ExtendedSubsection, ControlArea);
    00634             DbgBreakPoint();
    00635         }
    00636 #endif
    00637
    00638         TempPte.u.Soft.Protection = ControlArea->Segment->SegmentPteTemplate.u.Soft.Protection;
    00639         TempPte.u.Soft.Prototype = 1;
    00640         ExtendedSubsection->u.SubsectionFlags.Protection =
    00641             MI_GET_PROTECTION_FROM_SOFT_PTE(&TempPte);
    00642
    00643         while (PointerPte < LastPte) {
    00644             MI_WRITE_INVALID_PTE (PointerPte, TempPte);
    00645             PointerPte += 1;
    00646         }
    00647
    00648         //
    00649         // Link this into the list.
    00650         //
    00651
    00652         LastSubsection->NextSubsection = ExtendedSubsection;
    00653         ControlArea->Segment->TotalNumberOfPtes += RequiredPtes;
    00654
    00655 #if defined(_ALPHA_) && !defined(NT_UP)
    00656         //
    00657         // A memory barrier is required here to synchronize with
    00658         // NtMapViewOfSection, which validates the specified offset against
    00659         // the section object without holding lock synchronization.
    00660         // This memory barrier forces the subsection chaining to be correct
    00661         // before increasing the size in the section object.
    00662         //
    00663         __MB();
    00664 #endif
    00665
    00666     }
    00667
    00668     ControlArea->Segment->SizeOfSegment = *(PUINT64)NewSectionSize;
    00669     Section->SizeOfSection = *NewSectionSize;
    00670
    00671 ReleaseAndReturnSuccess:
    00672
    00673     Status = STATUS_SUCCESS;
    00674
    00675 ReleaseAndReturn:
    00676
    00677     ExReleaseResource (&MmSectionExtendResource);
    00678     KeLeaveCriticalRegion ();
    00679
    00680     return Status;
    00681 }

NTSTATUS NtExtendSection | ( | IN HANDLE | SectionHandle,
|  | IN OUT PLARGE_INTEGER | NewSectionSize
| ) |

Definition at line 85 of file extsect.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, KernelMode, KPROCESSOR_MODE, MmExtendSection(), MmSectionObjectType, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForWrite(), PSECTION, and Status.

    00092                    :
    00093
    00094     This function extends the size of the specified section.  If
    00095     the current size of the section is greater than or equal to the
    00096     specified section size, the size is not updated.
    00097
    00098 Arguments:
    00099
    00100     SectionHandle - Supplies an open handle to a section object.
    00101
    00102     NewSectionSize - Supplies the new size for the section object.
    00103
    00104 Return Value:
    00105
    00106     Returns the status
    00107
    00108     TBS
    00109
    00110
    00111 --*/
    00112
    00113 {
    00114     KPROCESSOR_MODE PreviousMode;
    00115     PVOID Section;
    00116     NTSTATUS Status;
    00117     LARGE_INTEGER CapturedNewSectionSize;
    00118
    00119     PAGED_CODE();
    00120
    00121     //
    00122     // Check to make sure the new section size is accessible.
    00123     //
    00124
    00125     PreviousMode = KeGetPreviousMode();
    00126
    00127     if (PreviousMode != KernelMode) {
    00128
    00129         try {
    00130
    00131             ProbeForWrite (NewSectionSize,
    00132                            sizeof(LARGE_INTEGER),
    00133                            sizeof(ULONG ));
    00134
    00135             CapturedNewSectionSize = *NewSectionSize;
    00136
    00137         } except (EXCEPTION_EXECUTE_HANDLER) {
    00138
    00139             //
    00140             // If an exception occurs during the probe or capture
    00141             // of the initial values, then handle the exception and
    00142             // return the exception code as the status value.
    00143             //
    00144
    00145             return GetExceptionCode();
    00146         }
    00147
    00148     } else {
    00149
    00150         CapturedNewSectionSize = *NewSectionSize;
    00151     }
    00152
    00153     //
    00154     // Reference the section object.
    00155     //
    00156
    00157     Status = ObReferenceObjectByHandle ( SectionHandle,
    00158                                          SECTION_EXTEND_SIZE,
    00159                                          MmSectionObjectType,
    00160                                          PreviousMode,
    00161                                          (PVOID *)&Section,
    00162                                          NULL );
    00163
    00164     if (!NT_SUCCESS(Status)) {
    00165         return Status;
    00166     }
    00167
    00168     //
    00169     // Make sure this section is backed by a file.
    00170     //
    00171
    00172     if (((PSECTION)Section)->Segment->ControlArea->FilePointer == NULL) {
    00173         ObDereferenceObject (Section);
    00174         return STATUS_SECTION_NOT_EXTENDED;
    00175     }
    00176
    00177     Status = MmExtendSection (Section, &CapturedNewSectionSize, FALSE);
    00178
    00179     ObDereferenceObject (Section);
    00180
    00181     //
    00182     // Update the NewSectionSize field.
    00183     //
    00184
    00185     try {
    00186
    00187         //
    00188         // Return the captured section size.
    00189         //
    00190
    00191         *NewSectionSize = CapturedNewSectionSize;
    00192
    00193     } except (EXCEPTION_EXECUTE_HANDLER) {
    00194         NOTHING;
    00195     }
    00196
    00197     return Status;
    00198 }