ReactOS 0.4.16-dev-197-g92996da
filobsup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 FilObSup.c
8
9Abstract:
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
38VOID
42 IN PVOID VcbOrFcbOrDcb,
44 )
45
46/*++
47
48Routine Description:
49
50 This routine sets the file system pointers within the file object
51
52Arguments:
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
64Return Value:
65
66 None.
67
68--*/
69
70{
71 PAGED_CODE();
72
73 DebugTrace(+1, Dbg, "FatSetFileObject, FileObject = %p\n", FileObject );
74
76
77
79
80 ||
81
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
101 (NodeType(VcbOrFcbOrDcb) == FAT_NTC_VCB) &&
102 (Ccb != NULL))
103
104 ||
105
107 (NodeType(VcbOrFcbOrDcb) == FAT_NTC_VCB) &&
108 (Ccb == NULL))
109
110 ||
111
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
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
181 )
182
183/*++
184
185Routine 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
190Arguments:
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
201Return 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;
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;
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
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
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
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_)
346VOID
347FatPurgeReferencedFileObjects (
348 IN PIRP_CONTEXT IrpContext,
349 IN PFCB Fcb,
351 )
352
353/*++
354
355Routine 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
360Arguments:
361
362 Fcb - Supplies a pointer to either an fcb or a dcb
363
364 FlushType - Specifies the kind of flushing to perform
365
366Return 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_)
422VOID
423FatForceCacheMiss (
424 IN PIRP_CONTEXT IrpContext,
425 IN PFCB Fcb,
427 )
428
429/*++
430
431Routine 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
441Arguments:
442
443 Fcb - Supplies a pointer to an fcb
444
445 FlushType - Specifies the kind of flushing to perform
446
447Return 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
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
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
#define PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
@ UnopenedFileObject
Definition: cdprocs.h:573
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
struct _VCB * PVCB
Definition: fatstruc.h:557
FCB * PFCB
Definition: cdstruc.h:1040
#define _Requires_lock_held_(lock)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NodeType(P)
Definition: nodetype.h:51
#define FAT_DIRENT_ATTR_VOLUME_ID
Definition: fat.h:371
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define FAT_NTC_CCB
Definition: nodetype.h:32
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define FAT_NTC_VCB
Definition: nodetype.h:28
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
VOID FatSetFileObject(IN PFILE_OBJECT FileObject OPTIONAL, IN TYPE_OF_OPEN TypeOfOpen, IN PVOID VcbOrFcbOrDcb, IN PCCB Ccb OPTIONAL)
Definition: filobsup.c:39
#define Dbg
Definition: filobsup.c:28
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1496
PFCB FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2627
@ DirectoryFile
Definition: fatprocs.h:1047
@ VirtualVolumeFile
Definition: fatprocs.h:1046
@ EaFile
Definition: fatprocs.h:1048
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1645
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1083
enum _FAT_FLUSH_TYPE FAT_FLUSH_TYPE
IN PFCB FcbOrDcb
Definition: fatprocs.h:307
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2978
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:559
#define VCB_STATE_FLAG_DELETED_FCB
Definition: fatstruc.h:565
#define FCB_STATE_TEMPORARY
Definition: fatstruc.h:1198
#define FCB_STATE_FORCE_MISS_IN_PROGRESS
Definition: fatstruc.h:1196
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_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:386
#define _Outptr_
Definition: ms_sal.h:427
#define _In_
Definition: ms_sal.h:308
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define ARGUMENT_PRESENT(ArgumentPointer)
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define BOOLEAN
Definition: pedump.c:73
#define Vcb
Definition: cdprocs.h:1415
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4361
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: cdstruc.h:1067
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
union _FCB::@729 Specific
struct _FCB::@729::@731 Dcb
ULONG FcbState
Definition: cdstruc.h:971
UCHAR DirentFatFlags
Definition: fatstruc.h:1133
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
Definition: cdstruc.h:498
ULONG VcbState
Definition: cdstruc.h:540
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FO_TEMPORARY_FILE
Definition: iotypes.h:1791
* PFILE_OBJECT
Definition: iotypes.h:1998
#define NT_ASSERT
Definition: rtlfuncs.h:3324