> about the original FileObject (why not to use it for consequent paging
I/O?) and also SectionObject which had only 1 reference before
ZwClose()?
SectionObject is a tiny structure which has a) page protection flags b) reference to the “data control area” (MmCa).
MmCa is the real structure which owns the physical pages of the file. There can be only 0 or 1 existing data control areas per FCB (but there can be many section objects - each ZwCreateSection creates one). One of the pointers in SECTION_OBJECT_POINTERS in the FCB points at MmCa (and can be NULL).
MmCa is not an Ob’s object and cannot have handles to it, but it holds a ref on the file object it was created for, the file object in turn holds a ref to FCB (maintained by FSD), and FCB’s SECTION_OBJECT_POINTERS holds a weak ref back to MmCa.
So:
- CreateFile create a file object and a handle to it (File 0 ref 1 handle).
- CreateFileMapping creates MmCa and a section object (Sect 0 ref 1 handle, MmCa 1 ref, File 1 ref 1 handle - 1 ref from MmCa).
- CloseHandle of the file handle causes MJ_CLEANUP, after this: File 1 ref (from MmCa) 0 handle.
- MapViewOfFile creates a VAD which references the MmCa (MmCa 2 refs, File 1 ref 0 handle).
- CloseHandle for the section destroys Sect and derefs MmCa once (MmCa 1 ref from mapped VAD, File 1 ref from MmCa 0 handle).
After this, all paging IO initiated by MM goes thru the file object referenced by MmCa, i.e. original file object created in CreateFile.
As about the physical pages associated with the file data - they are actually the innerworkings of MmCa.
Now let’s add Cc to picture. Cc’s shared cache map holds a ref to MmCa. As about the life time of CcSc itself - it is governed a) by lack of CcUninitializeCacheMap, before this CcSc cannot die, and this is called in MJ_CLEANUP b) by the garbage collection inside Cc which will allow the idle CcSc+MmCa to live for some time (and to survive quick reopens of the same file - next CcInitializeCacheMap will just pick existing CcSc from the GC list and resurrect it), and be garbage-collected later.
So, until Cc will do the garbage collection, CcSc/MmCa pair is alive and holds a ref on the file object. That’s why MJ_CLOSE can be delayed a lot after MJ_CLEANUP.
I don’t know how stream file objects go to this picture. I think they are only used to register the metadata streams with Cc - MFT, bitmaps, FATs and so on. More so, even directories must have a stream file object, since the directory file object exposed to user mode (result of ZwCreateFile for a directory) is just an enumeration context for ZwQueryDirectoryFile and is hardly the file object suitable for Cc.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com