ReactOS  0.4.14-dev-315-gbb6fece
filobsup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  FilObSup.c
8 
9 Abstract:
10 
11  This module implements the Fat File object support routines.
12 
13 
14 --*/
15 
16 #include "fatprocs.h"
17 
18 //
19 // The Bug check file id for this module
20 //
21 
22 #define BugCheckFileId (FAT_BUG_CHECK_FILOBSUP)
23 
24 //
25 // The debug trace level
26 //
27 
28 #define Dbg (DEBUG_TRACE_FILOBSUP)
29 
30 #ifdef ALLOC_PRAGMA
31 #pragma alloc_text(PAGE, FatForceCacheMiss)
32 #pragma alloc_text(PAGE, FatPurgeReferencedFileObjects)
33 #pragma alloc_text(PAGE, FatSetFileObject)
34 #pragma alloc_text(PAGE, FatDecodeFileObject)
35 #endif
36 
37 
38 VOID
42  IN PVOID VcbOrFcbOrDcb,
44  )
45 
46 /*++
47 
48 Routine Description:
49 
50  This routine sets the file system pointers within the file object
51 
52 Arguments:
53 
54  FileObject - Supplies a pointer to the file object being modified, and
55  can optionally be null.
56 
57  TypeOfOpen - Supplies the type of open denoted by the file object.
58  This is only used by this procedure for sanity checking.
59 
60  VcbOrFcbOrDcb - Supplies a pointer to either a vcb, fcb, or dcb
61 
62  Ccb - Optionally supplies a pointer to a ccb
63 
64 Return Value:
65 
66  None.
67 
68 --*/
69 
70 {
71  PAGED_CODE();
72 
73  DebugTrace(+1, Dbg, "FatSetFileObject, FileObject = %p\n", FileObject );
74 
75  NT_ASSERT((Ccb == NULL) || (NodeType(Ccb) == FAT_NTC_CCB));
76 
77 
79 
80  ||
81 
82  ((TypeOfOpen == UserFileOpen) &&
83  (NodeType(VcbOrFcbOrDcb) == FAT_NTC_FCB) &&
84  (Ccb != NULL))
85 
86  ||
87 
88  ((TypeOfOpen == EaFile) &&
89  (NodeType(VcbOrFcbOrDcb) == FAT_NTC_FCB) &&
90  (Ccb == NULL))
91 
92  ||
93 
95  ((NodeType(VcbOrFcbOrDcb) == FAT_NTC_DCB) || (NodeType(VcbOrFcbOrDcb) == FAT_NTC_ROOT_DCB)) &&
96  (Ccb != NULL))
97 
98  ||
99 
100  ((TypeOfOpen == UserVolumeOpen) &&
101  (NodeType(VcbOrFcbOrDcb) == FAT_NTC_VCB) &&
102  (Ccb != NULL))
103 
104  ||
105 
107  (NodeType(VcbOrFcbOrDcb) == FAT_NTC_VCB) &&
108  (Ccb == NULL))
109 
110  ||
111 
112  ((TypeOfOpen == DirectoryFile) &&
113  ((NodeType(VcbOrFcbOrDcb) == FAT_NTC_DCB) || (NodeType(VcbOrFcbOrDcb) == FAT_NTC_ROOT_DCB)) &&
114  (Ccb == NULL))
115  );
116 
117 
119 
120  //
121  // If we were given an Fcb, Dcb, or Vcb, we have some processing to do.
122  //
123 
124  NT_ASSERT((Ccb == NULL) || (NodeType(Ccb) == FAT_NTC_CCB));
125 
126  if ( VcbOrFcbOrDcb != NULL ) {
127 
128  //
129  // Set the Vpb field in the file object, and if we were given an
130  // Fcb or Dcb move the field over to point to the nonpaged Fcb/Dcb
131  //
132 
133  if (NodeType(VcbOrFcbOrDcb) == FAT_NTC_VCB) {
134 
135  FileObject->Vpb = ((PVCB)VcbOrFcbOrDcb)->Vpb;
136 
137  } else {
138 
139  FileObject->Vpb = ((PFCB)VcbOrFcbOrDcb)->Vcb->Vpb;
140 
141  //
142  // If this is a temporary file, note it in the FcbState
143  //
144 
145  if (FlagOn(((PFCB)VcbOrFcbOrDcb)->FcbState, FCB_STATE_TEMPORARY)) {
146 
148  }
149  }
150  }
151 
152  NT_ASSERT((Ccb == NULL) || (NodeType(Ccb) == FAT_NTC_CCB));
153 
154  //
155  // Now set the fscontext fields of the file object
156  //
157 
158  if (ARGUMENT_PRESENT( FileObject )) {
159 
160  FileObject->FsContext = VcbOrFcbOrDcb;
161  FileObject->FsContext2 = Ccb;
162  }
163 
164  NT_ASSERT((Ccb == NULL) || (NodeType(Ccb) == FAT_NTC_CCB));
165 
166  //
167  // And return to our caller
168  //
169 
170  DebugTrace(-1, Dbg, "FatSetFileObject -> VOID\n", 0);
171 
172  return;
173 }
174 
178  _Outptr_ PVCB *Vcb,
180  _Outptr_ PCCB *Ccb
181  )
182 
183 /*++
184 
185 Routine Description:
186 
187  This procedure takes a pointer to a file object, that has already been
188  opened by the Fat file system and figures out what really is opened.
189 
190 Arguments:
191 
192  FileObject - Supplies the file object pointer being interrogated
193 
194  Vcb - Receives a pointer to the Vcb for the file object.
195 
196  FcbOrDcb - Receives a pointer to the Fcb/Dcb for the file object, if
197  one exists.
198 
199  Ccb - Receives a pointer to the Ccb for the file object, if one exists.
200 
201 Return Value:
202 
203  TYPE_OF_OPEN - returns the type of file denoted by the input file object.
204 
205  UserFileOpen - The FO represents a user's opened data file.
206  Ccb, FcbOrDcb, and Vcb are set. FcbOrDcb points to an Fcb.
207 
208  UserDirectoryOpen - The FO represents a user's opened directory.
209  Ccb, FcbOrDcb, and Vcb are set. FcbOrDcb points to a Dcb/RootDcb
210 
211  UserVolumeOpen - The FO represents a user's opened volume.
212  Ccb and Vcb are set. FcbOrDcb is null.
213 
214  VirtualVolumeFile - The FO represents the special virtual volume file.
215  Vcb is set, and Ccb and FcbOrDcb are null.
216 
217  DirectoryFile - The FO represents a special directory file.
218  Vcb and FcbOrDcb are set. Ccb is null. FcbOrDcb points to a
219  Dcb/RootDcb.
220 
221  EaFile - The FO represents an Ea Io stream file.
222  FcbOrDcb, and Vcb are set. FcbOrDcb points to an Fcb, and Ccb is
223  null.
224 
225 --*/
226 
227 {
230  PVOID FsContext2;
231 
232  PAGED_CODE();
233 
234  DebugTrace(+1, Dbg, "FatDecodeFileObject, FileObject = %p\n", FileObject);
235 
236  //
237  // Reference the fs context fields of the file object, and zero out
238  // the out pointer parameters.
239  //
240 
241  FsContext = FileObject->FsContext;
242  FsContext2 = FileObject->FsContext2;
243 
244  //
245  // Special case the situation where FsContext is null
246  //
247 
248  if (FsContext == NULL) {
249 
250  *Ccb = NULL;
251  *FcbOrDcb = NULL;
252  *Vcb = NULL;
253 
255 
256  } else {
257 
258  //
259  // Now we can case on the node type code of the fscontext pointer
260  // and set the appropriate out pointers
261  //
262 
263  switch (NodeType(FsContext)) {
264 
265  case FAT_NTC_VCB:
266 
267  *Ccb = FsContext2;
268  *FcbOrDcb = NULL;
269  *Vcb = FsContext;
270 
272 
273  break;
274 
275  case FAT_NTC_ROOT_DCB:
276  case FAT_NTC_DCB:
277 
278  *Ccb = FsContext2;
279  *FcbOrDcb = FsContext;
280  *Vcb = (*FcbOrDcb)->Vcb;
281 
283 
284  DebugTrace(0, Dbg, "Referencing directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
285 
286  break;
287 
288  case FAT_NTC_FCB:
289 
290  *Ccb = FsContext2;
291  *FcbOrDcb = FsContext;
292  *Vcb = (*FcbOrDcb)->Vcb;
293 
294  if (*Ccb != NULL ) {
295 
297  DebugTrace(0, Dbg, "Referencing file: %wZ\n", &(*FcbOrDcb)->FullFileName);
298 
299  } else {
300 
301  //
302  // No Ccb means this is a special open.
303  //
304 
305 
306  if ( *FcbOrDcb == (*Vcb)->EaFcb ) {
307 
308  TypeOfOpen = EaFile;
309  DebugTrace(0, Dbg, "Referencing EA file: %wZ\n", &(*FcbOrDcb)->FullFileName);
310 
311  } else {
312 
313 #ifdef _MSC_VER
314 #pragma prefast(suppress:28159, "things are seriously wrong if we get here")
315 #endif
316  FatBugCheck( NodeType(FsContext), 0, 0 );
317 
318  }
319 
320  }
321 
322  break;
323 
324  default:
325 
326 #ifdef _MSC_VER
327 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
328 #endif
329  FatBugCheck( NodeType(FsContext), 0, 0 );
330  }
331  }
332 
333  //
334  // and return to our caller
335  //
336 
337  DebugTrace(0, Dbg, "FatDecodeFileObject -> VCB(%p)\n", *Vcb);
338  DebugTrace(0, Dbg, "FatDecodeFileObject -> FCB(%p)\n", *FcbOrDcb);
339  DebugTrace(0, Dbg, "FatDecodeFileObject -> CCB(%p)\n", *Ccb);
340  DebugTrace(-1, Dbg, "FatDecodeFileObject -> TypeOfOpen = %08lx\n", TypeOfOpen);
341 
342  return TypeOfOpen;
343 }
344 
345 _Requires_lock_held_(_Global_critical_region_)
346 VOID
347 FatPurgeReferencedFileObjects (
348  IN PIRP_CONTEXT IrpContext,
349  IN PFCB Fcb,
351  )
352 
353 /*++
354 
355 Routine Description:
356 
357  This routine non-recursively walks from the given FcbOrDcb and trys
358  to force Cc or Mm to close any sections it may be holding on to.
359 
360 Arguments:
361 
362  Fcb - Supplies a pointer to either an fcb or a dcb
363 
364  FlushType - Specifies the kind of flushing to perform
365 
366 Return Value:
367 
368  None.
369 
370 --*/
371 
372 {
373  PFCB OriginalFcb = Fcb;
374  PFCB NextFcb;
375 
376  PAGED_CODE();
377 
378  DebugTrace(+1, Dbg, "FatPurgeReferencedFileObjects, Fcb = %p\n", Fcb );
379 
380  NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
381 
382  //
383  // First, if we have a delayed close, force it closed.
384  //
385 
386  FatFspClose(Fcb->Vcb);
387 
388  //
389  // Walk the directory tree forcing sections closed.
390  //
391  // Note that it very important to get the next node to visit before
392  // acting on the current node. This is because acting on a node may
393  // make it, and an arbitrary number of direct ancestors, vanish.
394  // Since we never visit ancestors in our top-down enumeration scheme, we
395  // can safely continue the enumeration even when the tree is vanishing
396  // beneath us. This is way cool.
397  //
398 
399  while ( Fcb != NULL ) {
400 
401  NextFcb = FatGetNextFcbTopDown(IrpContext, Fcb, OriginalFcb);
402 
403  //
404  // Check for the EA file fcb
405  //
406 
408 
409  FatForceCacheMiss( IrpContext, Fcb, FlushType );
410  }
411 
412  Fcb = NextFcb;
413  }
414 
415  DebugTrace(-1, Dbg, "FatPurgeReferencedFileObjects (VOID)\n", 0 );
416 
417  return;
418 }
419 
420 
421 _Requires_lock_held_(_Global_critical_region_)
422 VOID
423 FatForceCacheMiss (
424  IN PIRP_CONTEXT IrpContext,
425  IN PFCB Fcb,
427  )
428 
429 /*++
430 
431 Routine Description:
432 
433  The following routine asks either Cc or Mm to get rid of any cached
434  pages on a file. Note that this will fail if a user has mapped a file.
435 
436  If there is a shared cache map, purge the cache section. Otherwise
437  we have to go and ask Mm to blow away the section.
438 
439  NOTE: This caller MUST own the Vcb exclusive.
440 
441 Arguments:
442 
443  Fcb - Supplies a pointer to an fcb
444 
445  FlushType - Specifies the kind of flushing to perform
446 
447 Return Value:
448 
449  None.
450 
451 --*/
452 
453 {
454  PVCB Vcb;
455  BOOLEAN ChildrenAcquired = FALSE;
456 
457  PAGED_CODE();
458 
459  //
460  // If we can't wait, bail.
461  //
462 
463  NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
465 
466  if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
467 
468  FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
469  }
470 
471  //
472  // If we are purging a directory file object, we must acquire all the
473  // FCBs exclusive so that the parent directory is not being pinned.
474  // Careful, we can collide with something acquiring up the tree like
475  // an unpin repinned flush (FsRtlAcquireFileForCcFlush ...) of a parent
476  // dir on extending writethrough of a child file (oops). So get things
477  // going up the tree, not down.
478  //
479 
480  if ((NodeType(Fcb) != FAT_NTC_FCB) &&
481  !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) {
482 
483  PLIST_ENTRY Links;
484  PFCB TempFcb;
485 
486  ChildrenAcquired = TRUE;
487 
488  for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
489  Links != &Fcb->Specific.Dcb.ParentDcbQueue;
490  Links = Links->Flink) {
491 
492  TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
493 
494  (VOID)FatAcquireExclusiveFcb( IrpContext, TempFcb );
495  }
496  }
497 
498  (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
499 
500  //
501  // We use this flag to indicate to a close beneath us that
502  // the Fcb resource should be freed before deleting the Fcb.
503  //
504 
505  Vcb = Fcb->Vcb;
506 
508 
510 
511  _SEH2_TRY {
512 
513  BOOLEAN DataSectionExists;
514  BOOLEAN ImageSectionExists;
515 
516  PSECTION_OBJECT_POINTERS Section;
517 
518  if ( FlushType ) {
519 
520  (VOID)FatFlushFile( IrpContext, Fcb, FlushType );
521  }
522 
523  //
524  // The Flush may have made the Fcb go away
525  //
526 
527  if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB)) {
528 
529  Section = &Fcb->NonPaged->SectionObjectPointers;
530 
531  DataSectionExists = (BOOLEAN)(Section->DataSectionObject != NULL);
532  ImageSectionExists = (BOOLEAN)(Section->ImageSectionObject != NULL);
533 
534  //
535  // Note, it is critical to do the Image section first as the
536  // purge of the data section may cause the image section to go
537  // away, but the opposite is not true.
538  //
539 
540  if (ImageSectionExists) {
541 
542  (VOID)MmFlushImageSection( Section, MmFlushForWrite );
543  }
544 
545  if (DataSectionExists) {
546 
547  CcPurgeCacheSection( Section, NULL, 0, FALSE );
548  }
549  }
550 
551  } _SEH2_FINALLY {
552 
553  //
554  // If we purging a directory file object, release all the Fcb
555  // resources that we acquired above. The Dcb cannot have vanished
556  // if there were Fcbs underneath it, and the Fcbs couldn't have gone
557  // away since I own the Vcb.
558  //
559 
560  if (ChildrenAcquired) {
561 
562  PLIST_ENTRY Links;
563  PFCB TempFcb;
564 
565  for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
566  Links != &Fcb->Specific.Dcb.ParentDcbQueue;
567  Links = Links->Flink) {
568 
569  TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
570 
571  FatReleaseFcb( IrpContext, TempFcb );
572  }
573  }
574 
575  //
576  // Since we have the Vcb exclusive we know that if any closes
577  // come in it is because the CcPurgeCacheSection caused the
578  // Fcb to go away. Also in close, the Fcb was released
579  // before being freed.
580  //
581 
582  if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {
583 
585 
586  FatReleaseFcb( (IRPCONTEXT), Fcb );
587  }
588  } _SEH2_END;
589 }
590 
591 
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
_Inout_ PLIST_ENTRY _In_ PVOID FsContext
Definition: fltkernel.h:2239
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:384
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
VOID FatSetFileObject(IN PFILE_OBJECT FileObject OPTIONAL, IN TYPE_OF_OPEN TypeOfOpen, IN PVOID VcbOrFcbOrDcb, IN PCCB Ccb OPTIONAL)
Definition: filobsup.c:39
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
Definition: cdstruc.h:1073
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define _Outptr_
Definition: no_sal2.h:396
#define FCB_STATE_TEMPORARY
Definition: fatstruc.h:1197
Definition: cdstruc.h:504
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:728
ULONG VcbState
Definition: cdstruc.h:546
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2965
#define FAT_NTC_CCB
Definition: nodetype.h:32
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
IN PFCB FcbOrDcb
Definition: fatprocs.h:297
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
UCHAR DirentFatFlags
Definition: fatstruc.h:1132
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:810
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NodeType
Definition: Node.h:5
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1071
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1635
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:558
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4798
enum _FAT_FLUSH_TYPE FAT_FLUSH_TYPE
FCB * PFCB
Definition: cdstruc.h:1046
#define ARGUMENT_PRESENT(ArgumentPointer)
#define Vcb
Definition: cdprocs.h:1425
* PFILE_OBJECT
Definition: iotypes.h:1955
union _FCB::@710 Specific
#define VOID
Definition: acefi.h:82
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
struct _VCB * PVCB
Definition: fatstruc.h:556
Definition: typedefs.h:117
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
#define _In_
Definition: no_sal2.h:204
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4424
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FO_TEMPORARY_FILE
Definition: iotypes.h:1748
#define VCB_STATE_FLAG_DELETED_FCB
Definition: fatstruc.h:564
_SEH2_FINALLY
Definition: create.c:4395
_Requires_lock_held_(_Global_critical_region_)
Definition: filobsup.c:345
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1486
#define FAT_DIRENT_ATTR_VOLUME_ID
Definition: fat.h:371
#define BOOLEAN
Definition: pedump.c:73
PVCB Vcb
Definition: cdstruc.h:939
#define FAT_NTC_VCB
Definition: nodetype.h:28
#define FCB_STATE_FORCE_MISS_IN_PROGRESS
Definition: fatstruc.h:1195
_In_ PFCB Fcb
Definition: cdprocs.h:151
struct _FCB::@710::@712 Dcb
#define Dbg
Definition: filobsup.c:28
ULONG FcbState
Definition: cdstruc.h:977
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
#define NT_ASSERT
Definition: rtlfuncs.h:3312
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
PFCB FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2626