ReactOS  0.4.15-dev-3287-gfec35dc
strucsup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  StrucSup.c
8 
9 Abstract:
10 
11  This module implements the Fat in-memory data structure manipulation
12  routines
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 // The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId (FAT_BUG_CHECK_STRUCSUP)
24 
25 //
26 // The debug trace level
27 //
28 
29 #define Dbg (DEBUG_TRACE_STRUCSUP)
30 
31 #define FillMemory(BUF,SIZ,MASK) { \
32  ULONG i; \
33  for (i = 0; i < (((SIZ)/4) - 1); i += 2) { \
34  ((PULONG)(BUF))[i] = (MASK); \
35  ((PULONG)(BUF))[i+1] = (ULONG)PsGetCurrentThread(); \
36  } \
37 }
38 
39 #define IRP_CONTEXT_HEADER (sizeof( IRP_CONTEXT ) * 0x10000 + FAT_NTC_IRP_CONTEXT)
40 
41 //
42 // Local macros.
43 //
44 // Define our lookaside list allocators. For the time being, and perhaps
45 // permanently, the paged structures don't come off of lookasides. This
46 // is due to complications with clean unload as FAT can be in the paging
47 // path, making it really hard to find the right time to empty them.
48 //
49 // Fortunately, the hit rates on the Fcb/Ccb lists weren't stunning.
50 //
51 
52 #define FAT_FILL_FREE 0
53 
54 #ifdef __REACTOS__
55 static
56 #endif
57 INLINE
58 PCCB
60  )
61 {
62  return (PCCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(CCB), TAG_CCB );
63 }
64 
65 #ifdef __REACTOS__
66 static
67 #endif
68 INLINE
69 VOID
71  IN PCCB Ccb
72  )
73 {
74 #if FAT_FILL_FREE
76 #endif
77 
78  ExFreePool( Ccb );
79 }
80 
81 #ifdef __REACTOS__
82 static
83 #endif
84 INLINE
85 PFCB
87  )
88 {
89  return (PFCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(FCB), TAG_FCB );
90 }
91 
92 #ifdef __REACTOS__
93 static
94 #endif
95 INLINE
96 VOID
98  IN PFCB Fcb
99  )
100 {
101 #if FAT_FILL_FREE
103 #endif
104 
105  ExFreePool( Fcb );
106 }
107 
108 #ifdef __REACTOS__
109 static
110 #endif
111 INLINE
114  )
115 {
116  return (PNON_PAGED_FCB) ExAllocateFromNPagedLookasideList( &FatNonPagedFcbLookasideList );
117 }
118 
119 #ifdef __REACTOS__
120 static
121 #endif
122 INLINE
123 VOID
125  PNON_PAGED_FCB NonPagedFcb
126  )
127 {
128 #if FAT_FILL_FREE
129  RtlFillMemoryUlong(NonPagedFcb, sizeof(NON_PAGED_FCB), FAT_FILL_FREE);
130 #endif
131 
132  ExFreeToNPagedLookasideList( &FatNonPagedFcbLookasideList, (PVOID) NonPagedFcb );
133 }
134 
135 #ifdef __REACTOS__
136 static
137 #endif
138 INLINE
141  )
142 {
144 
145  Resource = (PERESOURCE) ExAllocateFromNPagedLookasideList( &FatEResourceLookasideList );
146 
148 
149  return Resource;
150 }
151 
152 #ifdef __REACTOS__
153 static
154 #endif
155 INLINE
156 VOID
159  )
160 {
162 
163 #if FAT_FILL_FREE
165 #endif
166 
167  ExFreeToNPagedLookasideList( &FatEResourceLookasideList, (PVOID) Resource );
168 }
169 
170 #ifdef __REACTOS__
171 static
172 #endif
173 INLINE
176  )
177 {
178  return (PIRP_CONTEXT) ExAllocateFromNPagedLookasideList( &FatIrpContextLookasideList );
179 }
180 
181 #ifdef __REACTOS__
182 static
183 #endif
184 INLINE
185 VOID
187  IN PIRP_CONTEXT IrpContext
188  )
189 {
190 #if FAT_FILL_FREE
191  RtlFillMemoryUlong(IrpContext, sizeof(IRP_CONTEXT), FAT_FILL_FREE);
192 #endif
193 
194  ExFreeToNPagedLookasideList( &FatIrpContextLookasideList, (PVOID) IrpContext );
195 }
196 
197 #ifdef ALLOC_PRAGMA
198 #pragma alloc_text(PAGE, FatInitializeVcb)
199 #pragma alloc_text(PAGE, FatTearDownVcb)
200 #pragma alloc_text(PAGE, FatDeleteVcb)
201 #pragma alloc_text(PAGE, FatCreateRootDcb)
202 #pragma alloc_text(PAGE, FatCreateFcb)
203 #pragma alloc_text(PAGE, FatCreateDcb)
204 #pragma alloc_text(PAGE, FatDeleteFcb)
205 #pragma alloc_text(PAGE, FatCreateCcb)
206 #pragma alloc_text(PAGE, FatDeallocateCcbStrings)
207 #pragma alloc_text(PAGE, FatDeleteCcb)
208 #pragma alloc_text(PAGE, FatGetNextFcbTopDown)
209 #pragma alloc_text(PAGE, FatGetNextFcbBottomUp)
210 #pragma alloc_text(PAGE, FatConstructNamesInFcb)
211 #pragma alloc_text(PAGE, FatCheckFreeDirentBitmap)
212 #pragma alloc_text(PAGE, FatCreateIrpContext)
213 #pragma alloc_text(PAGE, FatDeleteIrpContext_Real)
214 #pragma alloc_text(PAGE, FatIsHandleCountZero)
215 #pragma alloc_text(PAGE, FatAllocateCloseContext)
216 #pragma alloc_text(PAGE, FatPreallocateCloseContext)
217 #pragma alloc_text(PAGE, FatEnsureStringBufferEnough)
218 #pragma alloc_text(PAGE, FatFreeStringBuffer)
219 #pragma alloc_text(PAGE, FatScanForDataTrack)
220 #endif
221 
222 
223 _Requires_lock_held_(_Global_critical_region_)
224 VOID
225 FatInitializeVcb (
226  IN PIRP_CONTEXT IrpContext,
227  IN OUT PVCB Vcb,
229  IN PVPB Vpb,
231  )
232 
233 /*++
234 
235 Routine Description:
236 
237  This routine initializes and inserts a new Vcb record into the in-memory
238  data structure. The Vcb record "hangs" off the end of the Volume device
239  object and must be allocated by our caller.
240 
241 Arguments:
242 
243  Vcb - Supplies the address of the Vcb record being initialized.
244 
245  TargetDeviceObject - Supplies the address of the target device object to
246  associate with the Vcb record.
247 
248  Vpb - Supplies the address of the Vpb to associate with the Vcb record.
249 
250  FsDeviceObject - The filesystem device object that the mount was directed
251  too.
252 
253 Return Value:
254 
255  None.
256 
257 --*/
258 
259 {
261  PDEVICE_OBJECT RealDevice;
262  ULONG i;
263 
264  STORAGE_HOTPLUG_INFO HotplugInfo;
265  STORAGE_DEVICE_NUMBER StorDeviceNumber;
267 
268  //
269  // The following variables are used for abnormal unwind
270  //
271 
272  PLIST_ENTRY UnwindEntryList = NULL;
273  PERESOURCE UnwindResource = NULL;
274  PERESOURCE UnwindResource2 = NULL;
275  PFILE_OBJECT UnwindFileObject = NULL;
276  PFILE_OBJECT UnwindCacheMap = NULL;
277  BOOLEAN UnwindWeAllocatedMcb = FALSE;
278  PFILE_SYSTEM_STATISTICS UnwindStatistics = NULL;
279  BOOLEAN UnwindWeAllocatedBadBlockMap = FALSE;
280  BOOLEAN CloseContextAllocated = FALSE;
281 
282  PAGED_CODE();
284 
285  DebugTrace(+1, Dbg, "FatInitializeVcb, Vcb = %p\n", Vcb);
286 
287  _SEH2_TRY {
288 
289  //
290  // We start by first zeroing out all of the VCB, this will guarantee
291  // that any stale data is wiped clean
292  //
293 
294  RtlZeroMemory( Vcb, sizeof(VCB) );
295 
296  //
297  // Set the proper node type code and node byte size
298  //
299 
300  Vcb->VolumeFileHeader.NodeTypeCode = FAT_NTC_VCB;
301  Vcb->VolumeFileHeader.NodeByteSize = sizeof(VCB);
302 
303  //
304  // Initialize the tunneling cache
305  //
306 
308 
309  //
310  // Insert this Vcb record on the FatData.VcbQueue
311  //
312 
313  NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
314 
315 
316 #ifdef _MSC_VER
317 #pragma prefast( push )
318 #pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
319 #pragma prefast( disable: 28193, "this will always wait" )
320 #endif
321 
322  (VOID)FatAcquireExclusiveGlobal( IrpContext );
323 
324 #ifdef _MSC_VER
325 #pragma prefast( pop )
326 #endif
327 
328  InsertTailList( &FatData.VcbQueue, &Vcb->VcbLinks );
329  FatReleaseGlobal( IrpContext );
330  UnwindEntryList = &Vcb->VcbLinks;
331 
332  //
333  // Set the Target Device Object, Vpb, and Vcb State fields
334  //
335 
336 
338  Vcb->TargetDeviceObject = TargetDeviceObject;
339  Vcb->Vpb = Vpb;
340 
341  Vcb->CurrentDevice = Vpb->RealDevice;
342 
343  //
344  // Set the removable media and defflush flags based on the storage
345  // inquiry and the old characteristic bits.
346  //
347 
348  Status = FatPerformDevIoCtrl( IrpContext,
351  NULL,
352  0,
353  &HotplugInfo,
354  sizeof(HotplugInfo),
355  FALSE,
356  TRUE,
357  NULL );
358 
359  if (NT_SUCCESS( Status )) {
360 
361  if (HotplugInfo.MediaRemovable) {
362 
364  }
365 
366  //
367  // If the media or device is hot-pluggable, then set this flag.
368  //
369 
370  if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug) {
371 
373  }
374 
375  if (!HotplugInfo.WriteCacheEnableOverride) {
376 
377  //
378  // If the device or media is hotplug and the override is not
379  // set, force defflush behavior for the device.
380  //
381 
382  if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug) {
383 
385 
387 
388  //
389  // Now, for removables that claim to be lockable, lob a lock
390  // request and see if it works. There can unfortunately be
391  // transient, media dependent reasons that it can fail. If
392  // it does not, we must force defflush on.
393  //
394 
395  } else if (HotplugInfo.MediaRemovable &&
396  !HotplugInfo.MediaHotplug) {
397 
398  Status = FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
399 
400  if (!NT_SUCCESS( Status )) {
401 
403 
404  }
405 
406  (VOID)FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
407  }
408  }
409  }
410 
411  if (FlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) {
412 
414  }
415 
416  //
417  // Make sure we turn on deferred flushing for floppies like we always
418  // have.
419  //
420 
421  if (FlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) {
422 
424  }
425 
426  //
427  // Query the storage device number.
428  //
429 
430  Status = FatPerformDevIoCtrl( IrpContext,
433  NULL,
434  0,
435  &StorDeviceNumber,
436  sizeof(StorDeviceNumber),
437  FALSE,
438  TRUE,
439  NULL );
440 
441  if (NT_SUCCESS( Status )) {
442 
443  Vcb->DeviceNumber = StorDeviceNumber.DeviceNumber;
444 
445  } else {
446 
447  Vcb->DeviceNumber = (ULONG)(-1);
448  }
449 
451 
452  //
453  // Initialize the resource variable for the Vcb
454  //
455 
456  ExInitializeResourceLite( &Vcb->Resource );
457  UnwindResource = &Vcb->Resource;
458 
459  ExInitializeResourceLite( &Vcb->ChangeBitMapResource );
460  UnwindResource2 = &Vcb->ChangeBitMapResource;
461 
462  //
463  // Initialize the free cluster bitmap mutex.
464  //
465 
466  ExInitializeFastMutex( &Vcb->FreeClusterBitMapMutex );
467 
468  //
469  // Create the special file object for the virtual volume file with a close
470  // context, its pointers back to the Vcb and the section object pointer.
471  //
472  // We don't have to unwind the close context. That will happen in the close
473  // path automatically.
474  //
475 
476  RealDevice = Vcb->CurrentDevice;
477 
479  CloseContextAllocated = TRUE;
480 
481  Vcb->VirtualVolumeFile = UnwindFileObject = IoCreateStreamFileObject( NULL, RealDevice );
482 
483  FatSetFileObject( Vcb->VirtualVolumeFile,
485  Vcb,
486  NULL );
487 
488  //
489  // Remember this internal, residual open.
490  //
491 
492  InterlockedIncrement( (LONG*)&(Vcb->InternalOpenCount) );
493  InterlockedIncrement( (LONG*)&(Vcb->ResidualOpenCount) );
494 
495  Vcb->VirtualVolumeFile->SectionObjectPointer = &Vcb->SectionObjectPointers;
496 
497  Vcb->VirtualVolumeFile->ReadAccess = TRUE;
498  Vcb->VirtualVolumeFile->WriteAccess = TRUE;
499  Vcb->VirtualVolumeFile->DeleteAccess = TRUE;
500 
501  //
502  // Initialize the notify structures.
503  //
504 
505  InitializeListHead( &Vcb->DirNotifyList );
506 
507  FsRtlNotifyInitializeSync( &Vcb->NotifySync );
508 
509  //
510  // Initialize the Cache Map for the volume file. The size is
511  // initially set to that of our first read. It will be extended
512  // when we know how big the Fat is.
513  //
514 
518 
519  FatInitializeCacheMap( Vcb->VirtualVolumeFile,
520  &FileSizes,
521  TRUE,
523  Vcb );
524 
525  UnwindCacheMap = Vcb->VirtualVolumeFile;
526 
527  //
528  // Initialize the structure that will keep track of dirty fat sectors.
529  // The largest possible Mcb structures are less than 1K, so we use
530  // non paged pool.
531  //
532 
533  FsRtlInitializeLargeMcb( &Vcb->DirtyFatMcb, PagedPool );
534 
535  UnwindWeAllocatedMcb = TRUE;
536 
537  //
538  // Initialize the structure that will keep track of bad clusters on the volume.
539  //
540  // It will be empty until it is populated by FSCTL_GET_RETRIEVAL_POINTERS with a volume handle.
541  //
542 
543  FsRtlInitializeLargeMcb( &Vcb->BadBlockMcb, PagedPool );
544  UnwindWeAllocatedBadBlockMap = TRUE;
545 
546  //
547  // Set the cluster index hint to the first valid cluster of a fat: 2
548  //
549 
550  Vcb->ClusterHint = 2;
551 
552  //
553  // Initialize the directory stream file object creation event.
554  // This event is also "borrowed" for async non-cached writes.
555  //
556 
557  ExInitializeFastMutex( &Vcb->DirectoryFileCreationMutex );
558 
559  //
560  // Initialize the clean volume callback Timer and DPC.
561  //
562 
563  KeInitializeTimer( &Vcb->CleanVolumeTimer );
564 
565  KeInitializeDpc( &Vcb->CleanVolumeDpc, FatCleanVolumeDpc, Vcb );
566 
567  //
568  // Initialize the performance counters.
569  //
570 
571  Vcb->Statistics = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
573  TAG_VCB_STATS );
574  UnwindStatistics = Vcb->Statistics;
575 
577 
578  for (i = 0; i < FatData.NumberProcessors; i += 1) {
579  Vcb->Statistics[i].Common.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
580  Vcb->Statistics[i].Common.Version = 1;
581  Vcb->Statistics[i].Common.SizeOfCompleteStructure =
582  sizeof(FILE_SYSTEM_STATISTICS);
583  }
584 
585  //
586  // Pick up a VPB right now so we know we can pull this filesystem stack off
587  // of the storage stack on demand.
588  //
589 
590  Vcb->SwapVpb = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
591  sizeof( VPB ),
592  TAG_VPB );
593 
594  RtlZeroMemory( Vcb->SwapVpb, sizeof( VPB ) );
595 
596  //
597  // Initialize the close queue listheads.
598  //
599 
600  InitializeListHead( &Vcb->AsyncCloseList );
601  InitializeListHead( &Vcb->DelayedCloseList );
602 
603  //
604  // Initialize the Advanced FCB Header
605  //
606 
607  ExInitializeFastMutex( &Vcb->AdvancedFcbHeaderMutex );
608  FsRtlSetupAdvancedHeader( &Vcb->VolumeFileHeader,
609  &Vcb->AdvancedFcbHeaderMutex );
610 
611 
612  //
613  // With the Vcb now set up, set the IrpContext Vcb field.
614  //
615 
616  IrpContext->Vcb = Vcb;
617 
618  } _SEH2_FINALLY {
619 
620  DebugUnwind( FatInitializeVcb );
621 
622  //
623  // If this is an abnormal termination then undo our work
624  //
625 
627 
628  if (UnwindCacheMap != NULL) { FatSyncUninitializeCacheMap( IrpContext, UnwindCacheMap ); }
629  if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
630  if (UnwindResource != NULL) { FatDeleteResource( UnwindResource ); }
631  if (UnwindResource2 != NULL) { FatDeleteResource( UnwindResource2 ); }
632  if (UnwindWeAllocatedMcb) { FsRtlUninitializeLargeMcb( &Vcb->DirtyFatMcb ); }
633  if (UnwindWeAllocatedBadBlockMap) { FsRtlUninitializeLargeMcb(&Vcb->BadBlockMcb ); }
634  if (UnwindEntryList != NULL) {
635 #ifdef _MSC_VER
636 #pragma prefast( suppress: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
637 #endif
638  (VOID)FatAcquireExclusiveGlobal( IrpContext );
639  RemoveEntryList( UnwindEntryList );
640  FatReleaseGlobal( IrpContext );
641  }
642  if (UnwindStatistics != NULL) { ExFreePool( UnwindStatistics ); }
643 
644  //
645  // Cleanup the close context we preallocated above.
646  //
647 
648  if (CloseContextAllocated && (Vcb->VirtualVolumeFile == NULL)) {
649 
650  //
651  // FatAllocateCloseContext does not allocate memory, it
652  // pulls a close context off the preallocated slist queue.
653  //
654  // Doing this here is necessary to balance out the one we
655  // preallocated for the Vcb earlier in this function, but
656  // only if we failed to create the virtual volume file.
657  //
658  // If VirtualVolumeFile is not NULL, then this CloseContext
659  // will get cleaned up when the close comes in for it during
660  // Vcb teardown.
661  //
662 
664 
665  ExFreePool( CloseContext );
666  CloseContextAllocated = FALSE;
667  }
668  }
669 
670  DebugTrace(-1, Dbg, "FatInitializeVcb -> VOID\n", 0);
671  } _SEH2_END;
672 
673  //
674  // and return to our caller
675  //
676 
677  UNREFERENCED_PARAMETER( IrpContext );
678 
679  return;
680 }
681 
682 
683 VOID
685  IN PIRP_CONTEXT IrpContext,
686  IN PVCB Vcb
687  )
688 
689 /*++
690 
691 Routine Description:
692 
693  This routine tries to remove all internal opens from the volume.
694 
695 Arguments:
696 
697  IrpContext - Supplies the context for the overall request.
698 
699  Vcb - Supplies the Vcb to be torn down.
700 
701 Return Value:
702 
703  None
704 
705 --*/
706 
707 {
708  PFILE_OBJECT DirectoryFileObject;
709 
710 
711  PAGED_CODE();
712 
713  //
714  // Get rid of the virtual volume file, if we need to.
715  //
716 
717  if (Vcb->VirtualVolumeFile != NULL) {
718 
719  //
720  // Uninitialize the cache
721  //
722 
723  CcUninitializeCacheMap( Vcb->VirtualVolumeFile,
724  &FatLargeZero,
725  NULL );
726 
727  FsRtlTeardownPerStreamContexts( &Vcb->VolumeFileHeader );
728 
729  ObDereferenceObject( Vcb->VirtualVolumeFile );
730 
731  Vcb->VirtualVolumeFile = NULL;
732  }
733 
734  //
735  // Close down the EA file.
736  //
737 
738  FatCloseEaFile( IrpContext, Vcb, FALSE );
739 
740  //
741  // Close down the root directory stream..
742  //
743 
744  if (Vcb->RootDcb != NULL) {
745 
746  DirectoryFileObject = Vcb->RootDcb->Specific.Dcb.DirectoryFile;
747 
748  if (DirectoryFileObject != NULL) {
749 
750  //
751  // Tear down this directory file.
752  //
753 
754  CcUninitializeCacheMap( DirectoryFileObject,
755  &FatLargeZero,
756  NULL );
757 
758  Vcb->RootDcb->Specific.Dcb.DirectoryFile = NULL;
759  ObDereferenceObject( DirectoryFileObject );
760  }
761  }
762 
763  //
764  // The VCB can no longer be used.
765  //
766 
768 }
769 
770 
771 VOID
773  IN PIRP_CONTEXT IrpContext,
774  IN PVCB Vcb
775  )
776 
777 /*++
778 
779 Routine Description:
780 
781  This routine removes the Vcb record from Fat's in-memory data
782  structures. It also will remove all associated underlings
783  (i.e., FCB records).
784 
785 Arguments:
786 
787  Vcb - Supplies the Vcb to be removed
788 
789 Return Value:
790 
791  None
792 
793 --*/
794 
795 {
796  PFCB Fcb;
797 
798  PAGED_CODE();
799 
800  DebugTrace(+1, Dbg, "FatDeleteVcb, Vcb = %p\n", Vcb);
801 
802  //
803  // If the IrpContext points to the VCB being deleted NULL out the stail
804  // pointer.
805  //
806 
807  if (IrpContext->Vcb == Vcb) {
808 
809  IrpContext->Vcb = NULL;
810 
811  }
812 
813  //
814  // Chuck the backpocket Vpb we kept just in case.
815  //
816 
817  if (Vcb->SwapVpb) {
818 
819  ExFreePool( Vcb->SwapVpb );
820 
821  }
822 
823  //
824  // Free the VPB, if we need to.
825  //
826 
827  if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VPB_MUST_BE_FREED )) {
828 
829  //
830  // We swapped the VPB, so we need to free the main one.
831  //
832 
833  ExFreePool( Vcb->Vpb );
834  }
835 
836  if (Vcb->VolumeGuidPath.Buffer) {
837  ExFreePool( Vcb->VolumeGuidPath.Buffer );
838  Vcb->VolumeGuidPath.Buffer = NULL;
839  }
840 
841  //
842  // Remove this record from the global list of all Vcb records.
843  // Note that the global lock must already be held when calling
844  // this function.
845  //
846 
847  RemoveEntryList( &(Vcb->VcbLinks) );
848 
849  //
850  // Make sure the direct access open count is zero, and the open file count
851  // is also zero.
852  //
853 
854  if ((Vcb->DirectAccessOpenCount != 0) || (Vcb->OpenFileCount != 0)) {
855 
856 #ifdef _MSC_VER
857 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
858 #endif
859  FatBugCheck( 0, 0, 0 );
860  }
861 
862  //
863  // Remove the EaFcb and dereference the Fcb for the Ea file if it
864  // exists.
865  //
866 
867  if (Vcb->EaFcb != NULL) {
868 
869  Vcb->EaFcb->OpenCount = 0;
870  FatDeleteFcb( IrpContext, &Vcb->EaFcb );
871  }
872 
873  //
874  // Remove the Root Dcb
875  //
876 
877  if (Vcb->RootDcb != NULL) {
878 
879  //
880  // Rundown stale child Fcbs that may be hanging around. Yes, this
881  // can happen. No, the create path isn't perfectly defensive about
882  // tearing down branches built up on creates that don't wind up
883  // succeeding. Normal system operation usually winds up having
884  // cleaned them out through re-visiting, but ...
885  //
886  // Just pick off Fcbs from the bottom of the tree until we run out.
887  // Then we delete the root Dcb.
888  //
889 
890  while( (Fcb = FatGetNextFcbBottomUp( IrpContext, NULL, Vcb->RootDcb )) != Vcb->RootDcb ) {
891 
892  FatDeleteFcb( IrpContext, &Fcb );
893  }
894 
895  FatDeleteFcb( IrpContext, &Vcb->RootDcb );
896  }
897 
898  //
899  // Uninitialize the notify sychronization object.
900  //
901 
902  FsRtlNotifyUninitializeSync( &Vcb->NotifySync );
903 
904  //
905  // Uninitialize the resource variable for the Vcb
906  //
907 
908  FatDeleteResource( &Vcb->Resource );
909  FatDeleteResource( &Vcb->ChangeBitMapResource );
910 
911  //
912  // If allocation support has been setup, free it.
913  //
914 
915  if (Vcb->FreeClusterBitMap.Buffer != NULL) {
916 
917  FatTearDownAllocationSupport( IrpContext, Vcb );
918  }
919 
920  //
921  // UnInitialize the Mcb structure that kept track of dirty fat sectors.
922  //
923 
924  FsRtlUninitializeLargeMcb( &Vcb->DirtyFatMcb );
925 
926  //
927  // Uninitialize the Mcb structure that kept track of bad sectors.
928  //
929 
930  FsRtlUninitializeLargeMcb( &Vcb->BadBlockMcb );
931 
932  //
933  // Free the pool for the stached copy of the boot sector
934  //
935 
936  if ( Vcb->First0x24BytesOfBootSector ) {
937 
938  ExFreePool( Vcb->First0x24BytesOfBootSector );
939  Vcb->First0x24BytesOfBootSector = NULL;
940  }
941 
942  //
943  // Cancel the CleanVolume Timer and Dpc
944  //
945 
946  (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
947 
948  (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
949 
950  //
951  // Free the performance counters memory
952  //
953 
954  ExFreePool( Vcb->Statistics );
955 
956  //
957  // Clean out the tunneling cache
958  //
959 
960  FsRtlDeleteTunnelCache(&Vcb->Tunnel);
961 
962  //
963  // Dereference the target device object.
964  //
965 
966  ObDereferenceObject( Vcb->TargetDeviceObject );
967 
968  //
969  // We better have used all the close contexts we allocated. There could be
970  // one remaining if we're doing teardown due to a final close coming in on
971  // a directory file stream object. It will be freed on the way back up.
972  //
973 
974  NT_ASSERT( Vcb->CloseContextCount <= 1);
975 
976  //
977  // And zero out the Vcb, this will help ensure that any stale data is
978  // wiped clean
979  //
980 
981  RtlZeroMemory( Vcb, sizeof(VCB) );
982 
983  //
984  // return and tell the caller
985  //
986 
987  DebugTrace(-1, Dbg, "FatDeleteVcb -> VOID\n", 0);
988 
989  return;
990 }
991 
992 
993 _Requires_lock_held_(_Global_critical_region_)
994 VOID
995 FatCreateRootDcb (
996  IN PIRP_CONTEXT IrpContext,
997  IN PVCB Vcb
998  )
999 
1000 /*++
1001 
1002 Routine Description:
1003 
1004  This routine allocates, initializes, and inserts a new root DCB record
1005  into the in memory data structure.
1006 
1007 Arguments:
1008 
1009  Vcb - Supplies the Vcb to associate the new DCB under
1010 
1011 Return Value:
1012 
1013  None. The Vcb is modified in-place.
1014 
1015 --*/
1016 
1017 {
1018  PDCB Dcb = NULL;
1019 
1020  //
1021  // The following variables are used for abnormal unwind
1022  //
1023 
1024  PVOID UnwindStorage[2] = { NULL, NULL };
1025  PERESOURCE UnwindResource = NULL;
1026  PERESOURCE UnwindResource2 = NULL;
1027  PLARGE_MCB UnwindMcb = NULL;
1028  PFILE_OBJECT UnwindFileObject = NULL;
1029 
1030  PAGED_CODE();
1031 
1032  DebugTrace(+1, Dbg, "FatCreateRootDcb, Vcb = %p\n", Vcb);
1033 
1034  _SEH2_TRY {
1035 
1036  //
1037  // Make sure we don't already have a root dcb for this vcb
1038  //
1039 
1040  if (Vcb->RootDcb != NULL) {
1041 
1042  DebugDump("Error trying to create multiple root dcbs\n", 0, Vcb);
1043 #ifdef _MSC_VER
1044 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1045 #endif
1046  FatBugCheck( 0, 0, 0 );
1047  }
1048 
1049  //
1050  // Allocate a new DCB and zero it out, we use Dcb locally so we don't
1051  // have to continually reference through the Vcb
1052  //
1053 
1054  UnwindStorage[0] = Dcb = Vcb->RootDcb = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
1055  sizeof(DCB),
1056  TAG_FCB );
1057 
1058  RtlZeroMemory( Dcb, sizeof(DCB));
1059 
1060  UnwindStorage[1] =
1061  Dcb->NonPaged = FatAllocateNonPagedFcb();
1062 
1063  RtlZeroMemory( Dcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1064 
1065  //
1066  // Set the proper node type code, node byte size, and call backs
1067  //
1068 
1069  Dcb->Header.NodeTypeCode = FAT_NTC_ROOT_DCB;
1070  Dcb->Header.NodeByteSize = sizeof(DCB);
1071 
1072  Dcb->FcbCondition = FcbGood;
1073 
1074  //
1075  // The parent Dcb, initial state, open count, dirent location
1076  // information, and directory change count fields are already zero so
1077  // we can skip setting them
1078  //
1079 
1080  //
1081  // Initialize the resource variable
1082  //
1083 
1084  UnwindResource =
1085  Dcb->Header.Resource = FatAllocateResource();
1086 
1087  //
1088  // Initialize the PagingIo Resource. We no longer use the FsRtl common
1089  // shared pool because this led to a) deadlocks due to cases where files
1090  // and their parent directories shared a resource and b) there is no way
1091  // to anticipate inter-driver induced deadlock via recursive operation.
1092  //
1093 
1094  UnwindResource2 =
1095  Dcb->Header.PagingIoResource = FatAllocateResource();
1096 
1097  //
1098  // The root Dcb has an empty parent dcb links field
1099  //
1100 
1101  InitializeListHead( &Dcb->ParentDcbLinks );
1102 
1103  //
1104  // Set the Vcb
1105  //
1106 
1107  Dcb->Vcb = Vcb;
1108 
1109  //
1110  // initialize the parent dcb queue.
1111  //
1112 
1113  InitializeListHead( &Dcb->Specific.Dcb.ParentDcbQueue );
1114 
1115  //
1116  // Set the full file name up.
1117  //
1118 
1119  Dcb->FullFileName.Buffer = L"\\";
1120  Dcb->FullFileName.Length = (USHORT)2;
1121  Dcb->FullFileName.MaximumLength = (USHORT)4;
1122 
1123  Dcb->ShortName.Name.Oem.Buffer = "\\";
1124  Dcb->ShortName.Name.Oem.Length = (USHORT)1;
1125  Dcb->ShortName.Name.Oem.MaximumLength = (USHORT)2;
1126 
1127  //
1128  // Construct a lie about file properties since we don't
1129  // have a proper "." entry to look at.
1130  //
1131 
1132  Dcb->DirentFatFlags = FILE_ATTRIBUTE_DIRECTORY;
1133 
1134  //
1135  // Initialize Advanced FCB Header fields
1136  //
1137 
1138  ExInitializeFastMutex( &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1139  FsRtlSetupAdvancedHeader( &Dcb->Header,
1140  &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1141 
1142  //
1143  // Initialize the Mcb, and setup its mapping. Note that the root
1144  // directory is a fixed size so we can set it everything up now.
1145  //
1146 
1147  FsRtlInitializeLargeMcb( &Dcb->Mcb, NonPagedPoolNx );
1148  UnwindMcb = &Dcb->Mcb;
1149 
1150  if (FatIsFat32(Vcb)) {
1151 
1152  //
1153  // The first cluster of fat32 roots comes from the BPB
1154  //
1155 
1156  Dcb->FirstClusterOfFile = Vcb->Bpb.RootDirFirstCluster;
1157 
1158  } else {
1159 
1160  FatAddMcbEntry( Vcb, &Dcb->Mcb,
1161  0,
1162  FatRootDirectoryLbo( &Vcb->Bpb ),
1163  FatRootDirectorySize( &Vcb->Bpb ));
1164  }
1165 
1166  if (FatIsFat32(Vcb)) {
1167 
1168  //
1169  // Find the size of the fat32 root. As a side-effect, this will create
1170  // MCBs for the entire root. In the process of doing this, we may
1171  // discover that the FAT chain is bogus and raise corruption.
1172  //
1173 
1174  Dcb->Header.AllocationSize.LowPart = 0xFFFFFFFF;
1175  FatLookupFileAllocationSize( IrpContext, Dcb);
1176 
1177  Dcb->Header.FileSize.QuadPart =
1178  Dcb->Header.AllocationSize.QuadPart;
1179  } else {
1180 
1181  //
1182  // set the allocation size to real size of the root directory
1183  //
1184 
1185  Dcb->Header.FileSize.QuadPart =
1186  Dcb->Header.AllocationSize.QuadPart = FatRootDirectorySize( &Vcb->Bpb );
1187 
1188  }
1189 
1190  //
1191  // Set our two create dirent aids to represent that we have yet to
1192  // enumerate the directory for never used or deleted dirents.
1193  //
1194 
1195  Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
1196  Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
1197 
1198  //
1199  // Setup the free dirent bitmap buffer.
1200  //
1201 
1202  RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
1203  NULL,
1204  0 );
1205 
1206  FatCheckFreeDirentBitmap( IrpContext, Dcb );
1207 
1208 #if (NTDDI_VERSION >= NTDDI_WIN8)
1209  //
1210  // Initialize the oplock structure.
1211  //
1212 
1214 #endif
1215 
1216  } _SEH2_FINALLY {
1217 
1218  DebugUnwind( FatCreateRootDcb );
1219 
1220  //
1221  // If this is an abnormal termination then undo our work
1222  //
1223 
1224  if (_SEH2_AbnormalTermination()) {
1225 
1226  ULONG i;
1227 
1228  if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
1229  if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1230  if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1231  if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1232 
1233  for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1234  if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1235  }
1236 
1237  //
1238  // Re-zero the entry in the Vcb.
1239  //
1240 
1241  Vcb->RootDcb = NULL;
1242  }
1243 
1244  DebugTrace(-1, Dbg, "FatCreateRootDcb -> %p\n", Dcb);
1245  } _SEH2_END;
1246 
1247  return;
1248 }
1249 
1250 
1251 PFCB
1253  IN PIRP_CONTEXT IrpContext,
1254  IN PVCB Vcb,
1255  IN PDCB ParentDcb,
1256  IN ULONG LfnOffsetWithinDirectory,
1257  IN ULONG DirentOffsetWithinDirectory,
1258  IN PDIRENT Dirent,
1260  IN PUNICODE_STRING OrigLfn OPTIONAL,
1261  IN BOOLEAN IsPagingFile,
1262  IN BOOLEAN SingleResource
1263  )
1264 
1265 /*++
1266 
1267 Routine Description:
1268 
1269  This routine allocates, initializes, and inserts a new Fcb record into
1270  the in-memory data structures.
1271 
1272 Arguments:
1273 
1274  Vcb - Supplies the Vcb to associate the new FCB under.
1275 
1276  ParentDcb - Supplies the parent dcb that the new FCB is under.
1277 
1278  LfnOffsetWithinDirectory - Supplies the offset of the LFN. If there is
1279  no LFN associated with this file then this value is same as
1280  DirentOffsetWithinDirectory.
1281 
1282  DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
1283  start of the directory file where the dirent for the fcb is located
1284 
1285  Dirent - Supplies the dirent for the fcb being created
1286 
1287  Lfn - Supplies a long UNICODE name associated with this file.
1288 
1289  IsPagingFile - Indicates if we are creating an FCB for a paging file
1290  or some other type of file.
1291 
1292  SingleResource - Indicates if this Fcb should share a single resource
1293  as both main and paging.
1294 
1295 Return Value:
1296 
1297  PFCB - Returns a pointer to the newly allocated FCB
1298 
1299 --*/
1300 
1301 {
1302  PFCB Fcb = NULL;
1304 
1305  //
1306  // The following variables are used for abnormal unwind
1307  //
1308 
1309  PVOID UnwindStorage[2] = { NULL, NULL };
1310  PERESOURCE UnwindResource = NULL;
1311  PERESOURCE UnwindResource2 = NULL;
1312  PLIST_ENTRY UnwindEntryList = NULL;
1313  PLARGE_MCB UnwindMcb = NULL;
1314  PFILE_LOCK UnwindFileLock = NULL;
1315  POPLOCK UnwindOplock = NULL;
1316 
1317  PAGED_CODE();
1318 
1319  UNREFERENCED_PARAMETER( OrigLfn );
1320 
1321  DebugTrace(+1, Dbg, "FatCreateFcb\n", 0);
1322 
1323  _SEH2_TRY {
1324 
1325  //
1326  // Determine the pool type we should be using for the fcb and the
1327  // mcb structure
1328  //
1329 
1330  if (IsPagingFile) {
1331 
1332  PoolType = NonPagedPoolNx;
1333  Fcb = UnwindStorage[0] = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
1334  sizeof(FCB),
1335  TAG_FCB );
1336  } else {
1337 
1338  PoolType = PagedPool;
1339  Fcb = UnwindStorage[0] = FatAllocateFcb();
1340 
1341  }
1342 
1343  //
1344  // ... and zero it out
1345  //
1346 
1347  RtlZeroMemory( Fcb, sizeof(FCB) );
1348 
1349  UnwindStorage[1] =
1351 
1352  RtlZeroMemory( Fcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1353 
1354  //
1355  // Set the proper node type code, node byte size, and call backs
1356  //
1357 
1358  Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
1359  Fcb->Header.NodeByteSize = sizeof(FCB);
1360 
1362 
1363  //
1364  // Check to see if we need to set the Fcb state to indicate that this
1365  // is a paging/system file. This will prevent it from being opened
1366  // again.
1367  //
1368 
1369  if (IsPagingFile) {
1370 
1372  }
1373 
1374  //
1375  // The initial state, open count, and segment objects fields are already
1376  // zero so we can skip setting them
1377  //
1378 
1379  //
1380  // Initialize the resource variable
1381  //
1382 
1383 
1384  UnwindResource =
1385  Fcb->Header.Resource = FatAllocateResource();
1386 
1387  //
1388  // Initialize the PagingIo Resource. We no longer use the FsRtl common
1389  // shared pool because this led to a) deadlocks due to cases where files
1390  // and their parent directories shared a resource and b) there is no way
1391  // to anticipate inter-driver induced deadlock via recursive operation.
1392  //
1393 
1394  if (SingleResource) {
1395 
1396  Fcb->Header.PagingIoResource = Fcb->Header.Resource;
1397 
1398  } else {
1399 
1400  UnwindResource2 =
1401  Fcb->Header.PagingIoResource = FatAllocateResource();
1402  }
1403 
1404  //
1405  // Insert this fcb into our parent dcb's queue.
1406  //
1407  // There is a deep reason why this goes on the tail, to allow us
1408  // to easily enumerate all child directories before child files.
1409  // This is important to let us maintain whole-volume lockorder
1410  // via BottomUp enumeration.
1411  //
1412 
1413  InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
1414  &Fcb->ParentDcbLinks );
1415  UnwindEntryList = &Fcb->ParentDcbLinks;
1416 
1417  //
1418  // Point back to our parent dcb
1419  //
1420 
1421  Fcb->ParentDcb = ParentDcb;
1422 
1423  //
1424  // Set the Vcb
1425  //
1426 
1427  Fcb->Vcb = Vcb;
1428 
1429  //
1430  // Set the dirent offset within the directory
1431  //
1432 
1433  Fcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
1434  Fcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
1435 
1436  //
1437  // Set the DirentFatFlags and LastWriteTime
1438  //
1439 
1440  Fcb->DirentFatFlags = Dirent->Attributes;
1441 
1442  Fcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
1444  0 );
1445 
1446  //
1447  // These fields are only non-zero when in Chicago mode.
1448  //
1449 
1450  if (FatData.ChicagoMode) {
1451 
1452  LARGE_INTEGER FatSystemJanOne1980 = {0};
1453 
1454  //
1455  // If either date is possibly zero, get the system
1456  // version of 1/1/80.
1457  //
1458 
1459  if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {
1460 
1462  &FatSystemJanOne1980 );
1463  }
1464 
1465  //
1466  // Only do the really hard work if this field is non-zero.
1467  //
1468 
1469  if (((PUSHORT)Dirent)[9] != 0) {
1470 
1471  Fcb->LastAccessTime =
1472  FatFatDateToNtTime( IrpContext,
1473  Dirent->LastAccessDate );
1474 
1475  } else {
1476 
1477  Fcb->LastAccessTime = FatSystemJanOne1980;
1478  }
1479 
1480  //
1481  // Only do the really hard work if this field is non-zero.
1482  //
1483 
1484  if (((PUSHORT)Dirent)[8] != 0) {
1485 
1486  Fcb->CreationTime =
1487  FatFatTimeToNtTime( IrpContext,
1489  Dirent->CreationMSec );
1490 
1491  } else {
1492 
1493  Fcb->CreationTime = FatSystemJanOne1980;
1494  }
1495  }
1496 
1497  //
1498  // Initialize Advanced FCB Header fields
1499  //
1500 
1502  FsRtlSetupAdvancedHeader( &Fcb->Header,
1504 
1505  //
1506  // To make FAT match the present functionality of NTFS, disable
1507  // stream contexts on paging files
1508  //
1509 
1510  if (IsPagingFile) {
1511 
1514  }
1515 
1516  //
1517  // Initialize the Mcb
1518  //
1519 
1521  UnwindMcb = &Fcb->Mcb;
1522 
1523  //
1524  // Set the file size, valid data length, first cluster of file,
1525  // and allocation size based on the information stored in the dirent
1526  //
1527 
1528  Fcb->Header.FileSize.LowPart = Dirent->FileSize;
1529 
1530  Fcb->Header.ValidDataLength.LowPart = Dirent->FileSize;
1531 
1532  Fcb->ValidDataToDisk = Dirent->FileSize;
1533 
1535 
1536  if ( FatIsFat32(Vcb) ) {
1537 
1538  Fcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
1539  }
1540 
1541  if ( Fcb->FirstClusterOfFile == 0 ) {
1542 
1543  Fcb->Header.AllocationSize.QuadPart = 0;
1544 
1545  } else {
1546 
1547  Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
1548  }
1549 
1550 
1551  //
1552  // Initialize the Fcb's file lock record
1553  //
1554 
1555  FsRtlInitializeFileLock( &Fcb->Specific.Fcb.FileLock, NULL, NULL );
1556  UnwindFileLock = &Fcb->Specific.Fcb.FileLock;
1557 
1558  //
1559  // Initialize the oplock structure.
1560  //
1561 
1563  UnwindOplock = FatGetFcbOplock(Fcb);
1564 
1565  //
1566  // Indicate that Fast I/O is possible
1567  //
1568 
1569  Fcb->Header.IsFastIoPossible = TRUE;
1570 
1571  //
1572  // Set the file names. This must be the last thing we do.
1573  //
1574 
1575  FatConstructNamesInFcb( IrpContext,
1576  Fcb,
1577  Dirent,
1578  Lfn );
1579 
1580  //
1581  // Drop the shortname hint so prefix searches can figure out
1582  // what they found
1583  //
1584 
1586 
1587  } _SEH2_FINALLY {
1588 
1590 
1591  //
1592  // If this is an abnormal termination then undo our work
1593  //
1594 
1595  if (_SEH2_AbnormalTermination()) {
1596 
1597  ULONG i;
1598 
1599  if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
1600  if (UnwindFileLock != NULL) { FsRtlUninitializeFileLock( UnwindFileLock ); }
1601  if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1602  if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
1603  if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1604  if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1605 
1606  for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1607  if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1608  }
1609  }
1610 
1611  DebugTrace(-1, Dbg, "FatCreateFcb -> %p\n", Fcb);
1612  } _SEH2_END;
1613 
1614  //
1615  // return and tell the caller
1616  //
1617 
1618  return Fcb;
1619 }
1620 
1621 
1622 PDCB
1624  IN PIRP_CONTEXT IrpContext,
1625  IN PVCB Vcb,
1626  IN PDCB ParentDcb,
1627  IN ULONG LfnOffsetWithinDirectory,
1628  IN ULONG DirentOffsetWithinDirectory,
1629  IN PDIRENT Dirent,
1631  )
1632 
1633 /*++
1634 
1635 Routine Description:
1636 
1637  This routine allocates, initializes, and inserts a new Dcb record into
1638  the in memory data structures.
1639 
1640 Arguments:
1641 
1642  Vcb - Supplies the Vcb to associate the new DCB under.
1643 
1644  ParentDcb - Supplies the parent dcb that the new DCB is under.
1645 
1646  LfnOffsetWithinDirectory - Supplies the offset of the LFN. If there is
1647  no LFN associated with this file then this value is same as
1648  DirentOffsetWithinDirectory.
1649 
1650  DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
1651  start of the directory file where the dirent for the fcb is located
1652 
1653  Dirent - Supplies the dirent for the dcb being created
1654 
1655  FileName - Supplies the file name of the file relative to the directory
1656  it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
1657  the preceding backslash).
1658 
1659  Lfn - Supplies a long UNICODE name associated with this directory.
1660 
1661 Return Value:
1662 
1663  PDCB - Returns a pointer to the newly allocated DCB
1664 
1665 --*/
1666 
1667 {
1668  PDCB Dcb = NULL;
1669 
1670  //
1671  // The following variables are used for abnormal unwind
1672  //
1673 
1674  PVOID UnwindStorage[2] = { NULL, NULL };
1675  PERESOURCE UnwindResource = NULL;
1676  PERESOURCE UnwindResource2 = NULL;
1677  PLIST_ENTRY UnwindEntryList = NULL;
1678  PLARGE_MCB UnwindMcb = NULL;
1679  POPLOCK UnwindOplock = NULL;
1680 
1681  PAGED_CODE();
1682 
1683  DebugTrace(+1, Dbg, "FatCreateDcb\n", 0);
1684 
1685  _SEH2_TRY {
1686 
1687  //
1688  // assert that the only time we are called is if wait is true
1689  //
1690 
1691  NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
1692 
1693  //
1694  // Allocate a new DCB, and zero it out
1695  //
1696 
1697  UnwindStorage[0] = Dcb = FatAllocateFcb();
1698 
1699  RtlZeroMemory( Dcb, sizeof(DCB) );
1700 
1701  UnwindStorage[1] =
1702  Dcb->NonPaged = FatAllocateNonPagedFcb();
1703 
1704  RtlZeroMemory( Dcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1705 
1706  //
1707  // Set the proper node type code, node byte size and call backs
1708  //
1709 
1710  Dcb->Header.NodeTypeCode = FAT_NTC_DCB;
1711  Dcb->Header.NodeByteSize = sizeof(DCB);
1712 
1713  Dcb->FcbCondition = FcbGood;
1714 
1715  //
1716  // The initial state, open count, and directory change count fields are
1717  // already zero so we can skip setting them
1718  //
1719 
1720  //
1721  // Initialize the resource variable
1722  //
1723 
1724 
1725  UnwindResource =
1726  Dcb->Header.Resource = FatAllocateResource();
1727 
1728  //
1729  // Initialize the PagingIo Resource. We no longer use the FsRtl common
1730  // shared pool because this led to a) deadlocks due to cases where files
1731  // and their parent directories shared a resource and b) there is no way
1732  // to anticipate inter-driver induced deadlock via recursive operation.
1733  //
1734 
1735  UnwindResource2 =
1736  Dcb->Header.PagingIoResource = FatAllocateResource();
1737 
1738  //
1739  // Insert this Dcb into our parent dcb's queue
1740  //
1741  // There is a deep reason why this goes on the head, to allow us
1742  // to easily enumerate all child directories before child files.
1743  // This is important to let us maintain whole-volume lockorder
1744  // via BottomUp enumeration.
1745  //
1746 
1747  InsertHeadList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
1748  &Dcb->ParentDcbLinks );
1749  UnwindEntryList = &Dcb->ParentDcbLinks;
1750 
1751  //
1752  // Point back to our parent dcb
1753  //
1754 
1755  Dcb->ParentDcb = ParentDcb;
1756 
1757  //
1758  // Set the Vcb
1759  //
1760 
1761  Dcb->Vcb = Vcb;
1762 
1763  //
1764  // Set the dirent offset within the directory
1765  //
1766 
1767  Dcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
1768  Dcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
1769 
1770  //
1771  // Set the DirentFatFlags and LastWriteTime
1772  //
1773 
1774  Dcb->DirentFatFlags = Dirent->Attributes;
1775 
1776  Dcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
1778  0 );
1779 
1780  //
1781  // These fields are only non-zero when in Chicago mode.
1782  //
1783 
1784  if (FatData.ChicagoMode) {
1785 
1786  LARGE_INTEGER FatSystemJanOne1980 = {0};
1787 
1788  //
1789  // If either date is possibly zero, get the system
1790  // version of 1/1/80.
1791  //
1792 
1793  if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {
1794 
1796  &FatSystemJanOne1980 );
1797  }
1798 
1799  //
1800  // Only do the really hard work if this field is non-zero.
1801  //
1802 
1803  if (((PUSHORT)Dirent)[9] != 0) {
1804 
1805  Dcb->LastAccessTime =
1806  FatFatDateToNtTime( IrpContext,
1807  Dirent->LastAccessDate );
1808 
1809  } else {
1810 
1811  Dcb->LastAccessTime = FatSystemJanOne1980;
1812  }
1813 
1814  //
1815  // Only do the really hard work if this field is non-zero.
1816  //
1817 
1818  if (((PUSHORT)Dirent)[8] != 0) {
1819 
1820  Dcb->CreationTime =
1821  FatFatTimeToNtTime( IrpContext,
1823  Dirent->CreationMSec );
1824 
1825  } else {
1826 
1827  Dcb->CreationTime = FatSystemJanOne1980;
1828  }
1829  }
1830 
1831  //
1832  // Initialize Advanced FCB Header fields
1833  //
1834 
1835  ExInitializeFastMutex( &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1836  FsRtlSetupAdvancedHeader( &Dcb->Header,
1837  &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1838 
1839  //
1840  // Initialize the Mcb
1841  //
1842 
1844  UnwindMcb = &Dcb->Mcb;
1845 
1846  //
1847  // Set the file size, first cluster of file, and allocation size
1848  // based on the information stored in the dirent
1849  //
1850 
1851  Dcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;
1852 
1853  if ( FatIsFat32(Dcb->Vcb) ) {
1854 
1855  Dcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
1856  }
1857 
1858  if ( Dcb->FirstClusterOfFile == 0 ) {
1859 
1860  Dcb->Header.AllocationSize.QuadPart = 0;
1861 
1862  } else {
1863 
1864  Dcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
1865  }
1866 
1867 
1868  // initialize the notify queues, and the parent dcb queue.
1869  //
1870 
1871  InitializeListHead( &Dcb->Specific.Dcb.ParentDcbQueue );
1872 
1873  //
1874  // Setup the free dirent bitmap buffer. Since we don't know the
1875  // size of the directory, leave it zero for now.
1876  //
1877 
1878  RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
1879  NULL,
1880  0 );
1881 
1882  //
1883  // Set our two create dirent aids to represent that we have yet to
1884  // enumerate the directory for never used or deleted dirents.
1885  //
1886 
1887  Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
1888  Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
1889 
1890 #if (NTDDI_VERSION >= NTDDI_WIN8)
1891  //
1892  // Initialize the oplock structure.
1893  //
1894 
1896  UnwindOplock = FatGetFcbOplock(Dcb);
1897 #endif
1898 
1899  //
1900  // Postpone initializing the cache map until we need to do a read/write
1901  // of the directory file.
1902 
1903 
1904  //
1905  // set the file names. This must be the last thing we do.
1906  //
1907 
1908  FatConstructNamesInFcb( IrpContext,
1909  Dcb,
1910  Dirent,
1911  Lfn );
1912 
1913  Dcb->ShortName.FileNameDos = TRUE;
1914 
1915  } _SEH2_FINALLY {
1916 
1918 
1919  //
1920  // If this is an abnormal termination then undo our work
1921  //
1922 
1923  if (_SEH2_AbnormalTermination()) {
1924 
1925  ULONG i;
1926 
1927  if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
1928  if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1929  if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
1930  if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1931  if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1932 
1933  for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1934  if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1935  }
1936  }
1937 
1938  DebugTrace(-1, Dbg, "FatCreateDcb -> %p\n", Dcb);
1939  } _SEH2_END;
1940 
1941  //
1942  // return and tell the caller
1943  //
1944 
1945  DebugTrace(-1, Dbg, "FatCreateDcb -> %p\n", Dcb);
1946 
1947  return Dcb;
1948 }
1949 
1950 
1951 VOID
1953  IN PIRP_CONTEXT IrpContext,
1954  IN PFCB *FcbPtr
1955  )
1956 
1957 /*++
1958 
1959 Routine Description:
1960 
1961  This routine deallocates and removes an FCB, DCB, or ROOT DCB record
1962  from Fat's in-memory data structures. It also will remove all
1963  associated underlings (i.e., Notify irps, and child FCB/DCB records).
1964 
1965 Arguments:
1966 
1967  Fcb - Supplies the FCB/DCB/ROOT DCB to be removed
1968 
1969 Return Value:
1970 
1971  None
1972 
1973 --*/
1974 
1975 {
1976  PFCB Fcb = *FcbPtr;
1977 
1978  PAGED_CODE();
1979 
1980  DebugTrace(+1, Dbg, "FatDeleteFcb, Fcb = %p\n", Fcb);
1981 
1982  //
1983  // We can only delete this record if the open count is zero.
1984  //
1985 
1986  if (Fcb->OpenCount != 0) {
1987 
1988  DebugDump("Error deleting Fcb, Still Open\n", 0, Fcb);
1989 #ifdef _MSC_VER
1990 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1991 #endif
1992  FatBugCheck( 0, 0, 0 );
1993  }
1994 
1995  //
1996  // Better be an FCB/DCB.
1997  //
1998 
1999  if ((Fcb->Header.NodeTypeCode != FAT_NTC_DCB) &&
2000  (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) &&
2001  (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)) {
2002 
2003 #ifdef _MSC_VER
2004 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
2005 #endif
2006  FatBugCheck( 0, 0, 0 );
2007  }
2008 
2009  //
2010  // If this is a DCB then remove every Notify record from the two
2011  // notify queues
2012  //
2013 
2014  if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
2015  (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB)) {
2016 
2017  //
2018  // If we allocated a free dirent bitmap buffer, free it.
2019  //
2020 
2021  if ((Fcb->Specific.Dcb.FreeDirentBitmap.Buffer != NULL) &&
2022  (Fcb->Specific.Dcb.FreeDirentBitmap.Buffer !=
2023  &Fcb->Specific.Dcb.FreeDirentBitmapBuffer[0])) {
2024 
2025  ExFreePool(Fcb->Specific.Dcb.FreeDirentBitmap.Buffer);
2026  }
2027 
2028 #if (NTDDI_VERSION >= NTDDI_WIN8)
2029  //
2030  // Uninitialize the oplock.
2031  //
2032 
2034 #endif
2035 
2036  NT_ASSERT( Fcb->Specific.Dcb.DirectoryFileOpenCount == 0 );
2037  NT_ASSERT( IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) );
2038  NT_ASSERT( NULL == Fcb->Specific.Dcb.DirectoryFile);
2039 
2040  } else {
2041 
2042  //
2043  // Uninitialize the byte range file locks and opportunistic locks
2044  //
2045 
2046  FsRtlUninitializeFileLock( &Fcb->Specific.Fcb.FileLock );
2048  }
2049 
2050 
2051  //
2052  // Release any Filter Context structures associated with this FCB
2053  //
2054 
2056 
2057  //
2058  // Uninitialize the Mcb
2059  //
2060 
2062 
2063  //
2064  // If this is not the root dcb then we need to remove ourselves from
2065  // our parents Dcb queue
2066  //
2067 
2068  if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
2069 
2071  }
2072 
2073  //
2074  // Remove the entry from the splay table if there is still is one.
2075  //
2076 
2078 
2079  FatRemoveNames( IrpContext, Fcb );
2080  }
2081 
2082  //
2083  // Free the file name pool if allocated.
2084  //
2085 
2086  if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
2087 
2088  //
2089  // If we blew up at inconvenient times, the shortname
2090  // could be null even though you will *never* see this
2091  // normally. Rename is a good example of this case.
2092  //
2093 
2094  if (Fcb->ShortName.Name.Oem.Buffer) {
2095 
2096  ExFreePool( Fcb->ShortName.Name.Oem.Buffer );
2097  }
2098 
2099  if (Fcb->FullFileName.Buffer) {
2100 
2102  }
2103  }
2104 
2105  if (Fcb->ExactCaseLongName.Buffer) {
2106 
2108  }
2109 
2110 #ifdef SYSCACHE_COMPILE
2111 
2112  if (Fcb->WriteMask) {
2113 
2114  ExFreePool( Fcb->WriteMask );
2115  }
2116 
2117 #endif
2118 
2119  //
2120  // Finally deallocate the Fcb and non-paged fcb records
2121  //
2122 
2123  FatFreeResource( Fcb->Header.Resource );
2124 
2125  if (Fcb->Header.PagingIoResource != Fcb->Header.Resource) {
2126 
2127  FatFreeResource( Fcb->Header.PagingIoResource );
2128  }
2129 
2130  //
2131  // If an Event was allocated, get rid of it.
2132  //
2133 
2135 
2137  }
2138 
2140 
2141  Fcb->Header.NodeTypeCode = NTC_UNDEFINED;
2142 
2143  FatFreeFcb( Fcb );
2144  *FcbPtr = NULL;
2145 
2146  //
2147  // and return to our caller
2148  //
2149 
2150  DebugTrace(-1, Dbg, "FatDeleteFcb -> VOID\n", 0);
2151 }
2152 
2153 
2154 PCCB
2156  IN PIRP_CONTEXT IrpContext
2157  )
2158 
2159 /*++
2160 
2161 Routine Description:
2162 
2163  This routine creates a new CCB record
2164 
2165 Arguments:
2166 
2167 Return Value:
2168 
2169  CCB - returns a pointer to the newly allocate CCB
2170 
2171 --*/
2172 
2173 {
2174  PCCB Ccb;
2175 
2176  PAGED_CODE();
2177 
2178  DebugTrace(+1, Dbg, "FatCreateCcb\n", 0);
2179 
2180  //
2181  // Allocate a new CCB Record
2182  //
2183 
2184  Ccb = FatAllocateCcb();
2185 
2186  RtlZeroMemory( Ccb, sizeof(CCB) );
2187 
2188  //
2189  // Set the proper node type code and node byte size
2190  //
2191 
2192  Ccb->NodeTypeCode = FAT_NTC_CCB;
2193  Ccb->NodeByteSize = sizeof(CCB);
2194 
2195  //
2196  // return and tell the caller
2197  //
2198 
2199  DebugTrace(-1, Dbg, "FatCreateCcb -> %p\n", Ccb);
2200 
2201  UNREFERENCED_PARAMETER( IrpContext );
2202 
2203  return Ccb;
2204 }
2205 
2206 
2207 
2208 VOID
2210  IN PCCB Ccb
2211  )
2212 /*++
2213 
2214 Routine Description:
2215 
2216  This routine deallocates CCB query templates
2217 
2218 Arguments:
2219 
2220  Ccb - Supplies the CCB
2221 
2222 Return Value:
2223 
2224  None
2225 
2226 --*/
2227 {
2228  PAGED_CODE();
2229 
2230  //
2231  // If we allocated query template buffers, deallocate them now.
2232  //
2233 
2235 
2236  NT_ASSERT( Ccb->UnicodeQueryTemplate.Buffer);
2238  RtlFreeUnicodeString( &Ccb->UnicodeQueryTemplate );
2239  }
2240 
2242 
2243  NT_ASSERT( Ccb->OemQueryTemplate.Wild.Buffer );
2245  RtlFreeOemString( &Ccb->OemQueryTemplate.Wild );
2246  }
2247 
2249 }
2250 
2251 
2252 
2253 VOID
2255  IN PIRP_CONTEXT IrpContext,
2256  IN PCCB *Ccb
2257  )
2258 
2259 /*++
2260 
2261 Routine Description:
2262 
2263  This routine deallocates and removes the specified CCB record
2264  from the Fat in memory data structures
2265 
2266 Arguments:
2267 
2268  Ccb - Supplies the CCB to remove
2269 
2270 Return Value:
2271 
2272  None
2273 
2274 --*/
2275 
2276 {
2277  PAGED_CODE();
2278 
2279  DebugTrace(+1, Dbg, "FatDeleteCcb, Ccb = %p\n", *Ccb);
2280 
2282 
2283  //
2284  // Deallocate the Ccb record
2285  //
2286 
2287  FatFreeCcb( *Ccb );
2288  *Ccb = NULL;
2289 
2290  //
2291  // return and tell the caller
2292  //
2293 
2294  DebugTrace(-1, Dbg, "FatDeleteCcb -> VOID\n", 0);
2295 
2296  UNREFERENCED_PARAMETER( IrpContext );
2297 }
2298 
2299 
2302  IN PIRP Irp,
2303  IN BOOLEAN Wait
2304  )
2305 
2306 /*++
2307 
2308 Routine Description:
2309 
2310  This routine creates a new IRP_CONTEXT record
2311 
2312 Arguments:
2313 
2314  Irp - Supplies the originating Irp.
2315 
2316  Wait - Supplies the wait value to store in the context
2317 
2318 Return Value:
2319 
2320  PIRP_CONTEXT - returns a pointer to the newly allocate IRP_CONTEXT Record
2321 
2322 --*/
2323 
2324 {
2325  PIRP_CONTEXT IrpContext;
2327 
2328  PAGED_CODE();
2329 
2330  DebugTrace(+1, Dbg, "FatCreateIrpContext\n", 0);
2331 
2333 
2334  //
2335  // The only operations a filesystem device object should ever receive
2336  // are create/teardown of fsdo handles and operations which do not
2337  // occur in the context of fileobjects (i.e., mount).
2338  //
2339 
2341 
2342  if (IrpSp->FileObject != NULL &&
2346 
2348  }
2349 
2350  NT_ASSERT( IrpSp->FileObject != NULL ||
2351 
2354  IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES) ||
2355 
2358 
2360  }
2361 
2362  //
2363  // Attemtp to allocate from the region first and failing that allocate
2364  // from pool.
2365  //
2366 
2367  DebugDoit( FatFsdEntryCount += 1);
2368 
2369  IrpContext = FatAllocateIrpContext();
2370 
2371  //
2372  // Zero out the irp context.
2373  //
2374 
2375  RtlZeroMemory( IrpContext, sizeof(IRP_CONTEXT) );
2376 
2377  //
2378  // Set the proper node type code and node byte size
2379  //
2380 
2381  IrpContext->NodeTypeCode = FAT_NTC_IRP_CONTEXT;
2382  IrpContext->NodeByteSize = sizeof(IRP_CONTEXT);
2383 
2384  //
2385  // Set the originating Irp field
2386  //
2387 
2388  IrpContext->OriginatingIrp = Irp;
2389 
2390  //
2391  // Major/Minor Function codes
2392  //
2393 
2394  IrpContext->MajorFunction = IrpSp->MajorFunction;
2395  IrpContext->MinorFunction = IrpSp->MinorFunction;
2396 
2397  //
2398  // Copy RealDevice for workque algorithms, and also set Write Through
2399  // and Removable Media if there is a file object. Only file system
2400  // control Irps won't have a file object, and they should all have
2401  // a Vpb as the first IrpSp location.
2402  //
2403 
2404  if (IrpSp->FileObject != NULL) {
2405 
2407 
2408  IrpContext->RealDevice = FileObject->DeviceObject;
2409  IrpContext->Vcb = &((PVOLUME_DEVICE_OBJECT)(IrpSp->DeviceObject))->Vcb;
2410 
2411  //
2412  // See if the request is Write Through. Look for both FileObjects opened
2413  // as write through, and non-cached requests with the SL_WRITE_THROUGH flag set.
2414  //
2415  // The latter can only originate from kernel components. (Note - NtWriteFile()
2416  // does redundantly set the SL_W_T flag for all requests it issues on write
2417  // through file objects)
2418  //
2419 
2420  if (IsFileWriteThrough( FileObject, IrpContext->Vcb ) ||
2421  ( (IrpSp->MajorFunction == IRP_MJ_WRITE) &&
2422  BooleanFlagOn( Irp->Flags, IRP_NOCACHE) &&
2424 
2425  SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
2426  }
2427  } else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {
2428 
2429  IrpContext->RealDevice = IrpSp->Parameters.MountVolume.Vpb->RealDevice;
2430  }
2431 
2432  //
2433  // Set the wait parameter
2434  //
2435 
2436  if (Wait) { SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); }
2437 
2438  //
2439  // Set the recursive file system call parameter. We set it true if
2440  // the TopLevelIrp field in the thread local storage is not the current
2441  // irp, otherwise we leave it as FALSE.
2442  //
2443 
2444  if ( IoGetTopLevelIrp() != Irp) {
2445 
2446  SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL);
2447  }
2448 
2449  //
2450  // return and tell the caller
2451  //
2452 
2453  DebugTrace(-1, Dbg, "FatCreateIrpContext -> %p\n", IrpContext);
2454 
2455  return IrpContext;
2456 }
2457 
2458 
2459 
2460 VOID
2462  IN PIRP_CONTEXT IrpContext
2463  )
2464 
2465 /*++
2466 
2467 Routine Description:
2468 
2469  This routine deallocates and removes the specified IRP_CONTEXT record
2470  from the Fat in memory data structures. It should only be called
2471  by FatCompleteRequest.
2472 
2473 Arguments:
2474 
2475  IrpContext - Supplies the IRP_CONTEXT to remove
2476 
2477 Return Value:
2478 
2479  None
2480 
2481 --*/
2482 
2483 {
2484  PAGED_CODE();
2485 
2486  DebugTrace(+1, Dbg, "FatDeleteIrpContext, IrpContext = %p\n", IrpContext);
2487 
2488  NT_ASSERT( IrpContext->NodeTypeCode == FAT_NTC_IRP_CONTEXT );
2489  NT_ASSERT( IrpContext->PinCount == 0 );
2490 
2491 
2492  //
2493  // If there is a FatIoContext that was allocated, free it.
2494  //
2495 
2496  if (IrpContext->FatIoContext != NULL) {
2497 
2498  if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {
2499 
2500  if (IrpContext->FatIoContext->ZeroMdl) {
2501  IoFreeMdl( IrpContext->FatIoContext->ZeroMdl );
2502  }
2503 
2504  ExFreePool( IrpContext->FatIoContext );
2505  }
2506  }
2507 
2508  //
2509  // Drop the IrpContext.
2510  //
2511 
2512  FatFreeIrpContext( IrpContext );
2513 
2514  //
2515  // return and tell the caller
2516  //
2517 
2518  DebugTrace(-1, Dbg, "FatDeleteIrpContext -> VOID\n", 0);
2519 
2520  return;
2521 }
2522 
2523 
2524 PFCB
2526  IN PIRP_CONTEXT IrpContext,
2527  IN PFCB Fcb OPTIONAL,
2528  IN PFCB TerminationFcb
2529  )
2530 
2531 /*++
2532 
2533 Routine Description:
2534 
2535  This routine is used to iterate through Fcbs in a tree. In order to match
2536  the lockorder for getting multiple Fcbs (so this can be used for acquiring
2537  all Fcbs), this version does a bottom-up enumeration.
2538 
2539  This is different than the old one, now called TopDown. The problem with
2540  lockorder was very well hidden.
2541 
2542  The transition rule is still pretty simple:
2543 
2544  A) If you have an adjacent sibling, go to it
2545  1) Descend to its leftmost child
2546  B) Else go to your parent
2547 
2548  If this routine is called with in invalid TerminationFcb it will fail,
2549  badly.
2550 
2551  The TerminationFcb is the last Fcb returned in the enumeration.
2552 
2553  This method is incompatible with the possibility that ancestors may vanish
2554  based on operations done on the last returned node. For instance,
2555  FatPurgeReferencedFileObjects cannot use BottomUp enumeration.
2556 
2557 Arguments:
2558 
2559  Fcb - Supplies the current Fcb. This is NULL if enumeration is starting.
2560 
2561  TerminationFcb - The root Fcb of the tree in which the enumeration starts
2562  and at which it inclusively stops.
2563 
2564 Return Value:
2565 
2566  The next Fcb in the enumeration, or NULL if Fcb was the final one.
2567 
2568 --*/
2569 
2570 {
2571  PFCB NextFcb;
2572 
2573  PAGED_CODE();
2574  UNREFERENCED_PARAMETER( IrpContext );
2575 
2576  NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, TerminationFcb->Vcb ) ||
2577  FlagOn( TerminationFcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
2578 
2579  //
2580  // Do we need to begin the enumeration?
2581  //
2582 
2583  if (Fcb != NULL) {
2584 
2585  //
2586  // Did we complete?
2587  //
2588 
2589  if (Fcb == TerminationFcb) {
2590 
2591  return NULL;
2592  }
2593 
2594  //
2595  // Do we have a sibling to return?
2596  //
2597 
2598  NextFcb = FatGetNextSibling( Fcb );
2599 
2600  //
2601  // If not, return our parent. We are done with this branch.
2602  //
2603 
2604  if (NextFcb == NULL) {
2605 
2606  return Fcb->ParentDcb;
2607  }
2608 
2609  } else {
2610 
2611  NextFcb = TerminationFcb;
2612  }
2613 
2614  //
2615  // Decend to its furthest child (if it exists) and return it.
2616  //
2617 
2618  for (;
2619  NodeType( NextFcb ) != FAT_NTC_FCB && FatGetFirstChild( NextFcb ) != NULL;
2620  NextFcb = FatGetFirstChild( NextFcb )) {
2621  }
2622 
2623  return NextFcb;
2624 }
2625 
2626 PFCB
2628  IN PIRP_CONTEXT IrpContext,
2629  IN PFCB Fcb,
2630  IN PFCB TerminationFcb
2631  )
2632 
2633 /*++
2634 
2635 Routine Description:
2636 
2637  This routine is used to iterate through Fcbs in a tree, from the top down.
2638 
2639  The rule is very simple:
2640 
2641  A) If you have a child, go to it, else
2642  B) If you have an older sibling, go to it, else
2643  C) Go to your parent's older sibling.
2644 
2645  If this routine is called with in invalid TerminationFcb it will fail,
2646  badly.
2647 
2648  The Termination Fcb is never returned. If it is the root of the tree you
2649  are traversing, visit it first.
2650 
2651  This routine never returns direct ancestors of Fcb, and thus is useful when
2652  making Fcb's go away (which may tear up the tree).
2653 
2654 Arguments:
2655 
2656  Fcb - Supplies the current Fcb
2657 
2658  TerminationFcb - The Fcb at which the enumeration should (non-inclusivly)
2659  stop. Assumed to be a directory.
2660 
2661 Return Value:
2662 
2663  The next Fcb in the enumeration, or NULL if Fcb was the final one.
2664 
2665 --*/
2666 
2667 {
2668  PFCB Sibling;
2669 
2670  PAGED_CODE();
2671  UNREFERENCED_PARAMETER( IrpContext );
2672 
2673  NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
2675 
2676  //
2677  // If this was a directory (ie. not a file), get the child. If
2678  // there aren't any children and this is our termination Fcb,
2679  // return NULL.
2680  //
2681 
2682  if ( ((NodeType(Fcb) == FAT_NTC_DCB) ||
2683  (NodeType(Fcb) == FAT_NTC_ROOT_DCB)) &&
2684  !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) ) {
2685 
2686  return FatGetFirstChild( Fcb );
2687  }
2688 
2689  //
2690  // Were we only meant to do one iteration?
2691  //
2692 
2693  if ( Fcb == TerminationFcb ) {
2694 
2695  return NULL;
2696  }
2697 
2698  Sibling = FatGetNextSibling(Fcb);
2699 
2700  while (TRUE) {
2701 
2702  //
2703  // Do we still have an "older" sibling in this directory who is
2704  // not the termination Fcb?
2705  //
2706 
2707  if ( Sibling != NULL ) {
2708 
2709  return (Sibling != TerminationFcb) ? Sibling : NULL;
2710  }
2711 
2712  //
2713  // OK, let's move on to out parent and see if he is the termination
2714  // node or has any older siblings.
2715  //
2716 
2717  if ( Fcb->ParentDcb == TerminationFcb ) {
2718 
2719  return NULL;
2720  }
2721 
2722  Fcb = Fcb->ParentDcb;
2723 
2724  Sibling = FatGetNextSibling(Fcb);
2725  }
2726 }
2727 
2728 
2729 BOOLEAN
2731  IN PIRP_CONTEXT IrpContext,
2732  PVCB Vcb
2733  )
2734 
2735 /*++
2736 
2737 Routine Description:
2738 
2739  This routine swaps the VPB for this VCB if it has not been done already.
2740  This means the device object will get our spare VPB and we will cleanup
2741  the one used while the volume was mounted.
2742 
2743 Arguments:
2744 
2745  IrpContext - Supplies the context for the overall request.
2746 
2747  Vcb - Supplies the VCB to swap the VPB on.
2748 
2749 Return Value:
2750 
2751  TRUE - If the VPB was actually swapped.
2752 
2753  FALSE - If the VPB was already swapped.
2754 
2755 --*/
2756 
2757 {
2758  BOOLEAN Result = FALSE;
2759  PVPB OldVpb;
2761 
2762 
2763  //
2764  // Make sure we have not already swapped it.
2765  //
2766 
2767  OldVpb = Vcb->Vpb;
2768 
2769 #ifdef _MSC_VER
2770 #pragma prefast( push )
2771 #pragma prefast( disable: 28175, "touching Vpb is ok for a filesystem" )
2772 #endif
2773 
2774  if (!FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VPB_MUST_BE_FREED ) && OldVpb->RealDevice->Vpb == OldVpb) {
2775 
2776  //
2777  // If not the final reference and we are forcing the disconnect,
2778  // then swap out the Vpb. We must preserve the REMOVE_PENDING flag
2779  // so that the device is not remounted in the middle of a PnP remove
2780  // operation.
2781  //
2782 
2783  NT_ASSERT( Vcb->SwapVpb != NULL );
2784 
2785  Vcb->SwapVpb->Type = IO_TYPE_VPB;
2786  Vcb->SwapVpb->Size = sizeof( VPB );
2787  Vcb->SwapVpb->RealDevice = OldVpb->RealDevice;
2788 
2789  Vcb->SwapVpb->RealDevice->Vpb = Vcb->SwapVpb;
2790 
2791  Vcb->SwapVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING );
2792 
2793  //
2794  // If we are working on a mount request, we need to make sure we update
2795  // the VPB in the IRP, since the one it points to may no longer be valid.
2796  //
2797 
2798  if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) {
2799 
2800  //
2801  // Get the IRP stack.
2802  //
2803 
2804  IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
2805 
2806  NT_ASSERT( IrpSp->FileObject == NULL );
2807 
2808  //
2809  // Check the VPB in the IRP to see if it is the one we are swapping.
2810  //
2811 
2812  if (IrpSp->Parameters.MountVolume.Vpb == OldVpb) {
2813 
2814  //
2815  // Change the IRP to point to the swap VPB.
2816  //
2817 
2818  IrpSp->Parameters.MountVolume.Vpb = Vcb->SwapVpb;
2819  }
2820  }
2821 
2822 #ifdef _MSC_VER
2823 #pragma prefast( pop )
2824 #endif
2825 
2826  //
2827  // We place the volume in the Bad state (as opposed to NotMounted) so
2828  // that it is not eligible for a remount. Also indicate we used up
2829  // the swap.
2830  //
2831 
2832  Vcb->SwapVpb = NULL;
2835 
2836  Result = TRUE;
2837  }
2838 
2839  return Result;
2840 }
2841 
2842 
2843 _Requires_lock_held_(_Global_critical_region_)
2844 BOOLEAN
2845 FatCheckForDismount (
2846  IN PIRP_CONTEXT IrpContext,
2847  PVCB Vcb,
2848  IN BOOLEAN Force
2849  )
2850 
2851 /*++
2852 
2853 Routine Description:
2854 
2855  This routine determines if a volume is ready for deletion. It
2856  correctly synchronizes with creates en-route to the file system.
2857 
2858 Arguments:
2859 
2860  Vcb - Supplies the volume to examine
2861 
2862  Force - Specifies whether we want this Vcb forcibly disconnected
2863  from the driver stack if it will not be deleted (a new vpb will
2864  be installed if neccesary). Caller is responsible for making
2865  sure that the volume has been marked in such a way that attempts
2866  to operate through the realdevice are blocked (i.e., move the vcb
2867  out of the mounted state).
2868 
2869 Return Value:
2870 
2871  BOOLEAN - TRUE if the volume was deleted, FALSE otherwise.
2872 
2873 --*/
2874 
2875 {
2876  KIRQL SavedIrql;
2877  BOOLEAN VcbDeleted = FALSE;
2878 
2879 
2880  //
2881  // If the VCB condition is good and we are not forcing, just return.
2882  //
2883 
2884  if (Vcb->VcbCondition == VcbGood && !Force) {
2885 
2886  return FALSE;
2887  }
2888 
2889  //
2890  // Now check for a zero Vpb count on an unmounted volume. These
2891  // volumes will be deleted as they now have no file objects and
2892  // there are no creates en route to this volume.
2893  //
2894 
2895  IoAcquireVpbSpinLock( &SavedIrql );
2896 
2897  if (Vcb->Vpb->ReferenceCount == Vcb->ResidualOpenCount && Vcb->OpenFileCount == 0) {
2898 
2899  PVPB Vpb = Vcb->Vpb;
2900 
2901 #if DBG
2902  UNICODE_STRING VolumeLabel;
2903 
2904  //
2905  // Setup the VolumeLabel string
2906  //
2907 
2908  VolumeLabel.Length = Vcb->Vpb->VolumeLabelLength;
2910  VolumeLabel.Buffer = &Vcb->Vpb->VolumeLabel[0];
2911 
2914  "FASTFAT: Dismounting Volume %Z\n",
2915  &VolumeLabel));
2916 #endif // DBG
2917 
2918  //
2919  // Swap this VCB's VPB.
2920  //
2921 
2922  FatSwapVpb( IrpContext,
2923  Vcb );
2924 
2925  //
2926  // Clear the VPB_MOUNTED bit. New opens should not come in due
2927  // to the swapped VPB, but having the flag cleared helps debugging.
2928  // Note that we must leave the Vpb->DeviceObject field set until
2929  // after the FatTearDownVcb call as closes will have to make their
2930  // way back to us.
2931  //
2932 
2933  ClearFlag( Vpb->Flags, VPB_MOUNTED );
2934 
2935  //
2936  // If this Vpb was locked, clear this flag now.
2937  //
2938 
2940 
2941  IoReleaseVpbSpinLock( SavedIrql );
2942 
2943  //
2944  // We are going to attempt the dismount, so mark the VCB as having
2945  // a dismount in progress.
2946  //
2947 
2950 
2951  //
2952  // Close down our internal opens.
2953  //
2954 
2955  FatTearDownVcb( IrpContext,
2956  Vcb );
2957 
2958  //
2959  // Process any delayed closes.
2960  //
2961 
2962  FatFspClose( Vcb );
2963 
2964  //
2965  // Grab the VPB lock again so that we can recheck our counts.
2966  //
2967 
2968  IoAcquireVpbSpinLock( &SavedIrql );
2969 
2970  //
2971  // See if we can delete this VCB.
2972  //
2973 
2974  if (Vcb->Vpb->ReferenceCount == 0 && Vcb->InternalOpenCount == 0) {
2975 
2976  Vpb->DeviceObject = NULL;
2977 
2978  IoReleaseVpbSpinLock( SavedIrql );
2979 
2980  FatDeleteVcb( IrpContext, Vcb );
2981 
2985  Vcb ) );
2986 
2987  VcbDeleted = TRUE;
2988 
2989  } else {
2990 
2991  IoReleaseVpbSpinLock( SavedIrql );
2992 
2995  }
2996 
2997  } else if (Force) {
2998 
2999  //
3000  // The requester is forcing the issue. We need to swap the VPB with our spare.
3001  //
3002 
3003  FatSwapVpb( IrpContext,
3004  Vcb );
3005 
3006  IoReleaseVpbSpinLock( SavedIrql );
3007 
3008  } else {
3009 
3010  //
3011  // Just drop the Vpb spinlock.
3012  //
3013 
3014  IoReleaseVpbSpinLock( SavedIrql );
3015  }
3016 
3017  return VcbDeleted;
3018 }
3019 
3020 
3021 VOID
3023  IN PIRP_CONTEXT IrpContext,
3024  PFCB Fcb,
3025  PDIRENT Dirent,
3027  )
3028 
3029 /*++
3030 
3031 Routine Description:
3032 
3033  This routine places the short name in the dirent in the first set of
3034  STRINGs in the Fcb. If a long file name (Lfn) was specified, then
3035  we must decide whether we will store its Oem equivolent in the same
3036  prefix table as the short name, or rather just save the upcased
3037  version of the UNICODE string in the FCB.
3038 
3039  For looking up Fcbs, the first approach will be faster, so we want to
3040  do this as much as possible. Here are the rules that I have thought
3041  through extensively to determine when it is safe to store only Oem
3042  version of the UNICODE name.
3043 
3044  - If the UNICODE name contains no extended characters (>0x80), use Oem.
3045 
3046  - Let U be the upcased version of the UNICODE name.
3047  Let Up(x) be the function that upcases a UNICODE string.
3048  Let Down(x) be the function that upcases a UNICODE string.
3049  Let OemToUni(x) be the function that converts an Oem string to Unicode.
3050  Let UniToOem(x) be the function that converts a Unicode string to Oem.
3051  Let BestOemFit(x) be the function that creates the Best uppercase Oem
3052  fit for the UNICODE string x.
3053 
3054  BestOemFit(x) = UniToOem(Up(OemToUni(UniToOem(x)))) <1>
3055 
3056  if (BestOemFit(U) == BestOemFit(Down(U)) <2>
3057 
3058  then I know that there exists no UNICODE string Y such that:
3059 
3060  Up(Y) == Up(U) <3>
3061 
3062  AND
3063 
3064  BestOemFit(U) != BestOemFit(Y) <4>
3065 
3066  Consider string U as a collection of one character strings. The
3067  conjecture is clearly true for each sub-string, thus it is true
3068  for the entire string.
3069 
3070  Equation <1> is what we use to convert an incoming unicode name in
3071  FatCommonCreate() to Oem. The double conversion is done to provide
3072  better visual best fitting for characters in the Ansi code page but
3073  not in the Oem code page. A single Nls routine is provided to do
3074  this conversion efficiently.
3075 
3076  The idea is that with U, I only have to worry about a case varient Y
3077  matching it in a unicode compare, and I have shown that any case varient
3078  of U (the set Y defined in equation <3>), when filtered through <1>
3079  (as in create), will match the Oem string defined in <1>.
3080 
3081  Thus I do not have to worry about another UNICODE string missing in
3082  the prefix lookup, but matching when comparing LFNs in the directory.
3083 
3084 Arguments:
3085 
3086  Fcb - The Fcb we are supposed to fill in. Note that ParentDcb must
3087  already be filled in.
3088 
3089  Dirent - The gives up the short name.
3090 
3091  Lfn - If provided, this gives us the long name.
3092 
3093 Return Value:
3094 
3095  None
3096 
3097 --*/
3098 
3099 {
3100 #ifndef __REACTOS__
3101  NTSTATUS Status;
3102 #endif
3103  ULONG i;
3104 
3105 #ifndef __REACTOS__
3106  OEM_STRING OemA;
3107  OEM_STRING OemB;
3108 #endif
3109  UNICODE_STRING Unicode;
3111  POEM_STRING LongOemName;
3112  PUNICODE_STRING LongUniName;
3113 
3114  PAGED_CODE();
3115 
3117 
3118  NT_ASSERT( ShortName->Buffer == NULL );
3119 
3120  _SEH2_TRY {
3121 
3122  //
3123  // First do the short name.
3124  //
3125 
3126  //
3127  // Copy over the case flags for the short name of the file
3128  //
3129 
3131 
3133 
3134  } else {
3135 
3137  }
3138 
3140 
3142 
3143  } else {
3144 
3146  }
3147 
3148  ShortName->MaximumLength = 16;
3150  16,
3152 
3153  Fat8dot3ToString( IrpContext, Dirent, FALSE, ShortName );
3154 
3156 
3157  //
3158  // If no Lfn was specified, we are done. In either case, set the
3159  // final name length.
3160  //
3161 
3163 
3164  if (!ARGUMENT_PRESENT(Lfn) || (Lfn->Length == 0)) {
3165 
3168 
3169  try_return( NOTHING );
3170  }
3171 
3172  //
3173  // If we already set up the full filename, we could be in trouble. If the fast
3174  // path for doing it already fired, FatSetFullFileNameInFcb, it will have missed
3175  // this and could have built the full filename out of the shortname of the file.
3176  //
3177  // At that point, disaster could be inevitable since the final name length will not
3178  // match. We use this to tell the notify package what to do - FatNotifyReportChange.
3179  //
3180 
3182 
3183  //
3184  // We know now we have an Lfn, save away a copy.
3185  //
3186 
3188 
3191  Lfn->Length,
3194 
3195  //
3196  // First check for no extended characters.
3197  //
3198 
3199  for (i=0; i < Lfn->Length/sizeof(WCHAR); i++) {
3200 
3201  if (Lfn->Buffer[i] >= 0x80) {
3202 
3203  break;
3204  }
3205  }
3206 
3207  if (i == Lfn->Length/sizeof(WCHAR)) {
3208 
3209  //
3210  // Cool, I can go with the Oem, upcase it fast by hand.
3211  //
3212 
3213  LongOemName = &Fcb->LongName.Oem.Name.Oem;
3214 
3215 
3216  LongOemName->Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3217  Lfn->Length/sizeof(WCHAR),
3219  LongOemName->Length =
3220  LongOemName->MaximumLength = Lfn->Length/sizeof(WCHAR);
3221 
3222  for (i=0; i < Lfn->Length/sizeof(WCHAR); i++) {
3223 
3224  WCHAR c;
3225 
3226  c = Lfn->Buffer[i];
3227 
3228 #ifdef _MSC_VER
3229 #pragma warning( push )
3230 #pragma warning( disable:4244 )
3231 #endif
3232  LongOemName->Buffer[i] = c < 'a' ?
3233  (UCHAR)c :
3234  c <= 'z' ?
3235  c - (UCHAR)('a'-'A') :
3236  (UCHAR)c;
3237 #ifdef _MSC_VER
3238 #pragma warning( pop )
3239 #endif
3240  }
3241 
3242  //
3243  // If this name happens to be exactly the same as the short
3244  // name, don't add it to the splay table.
3245  //
3246 
3247  if (FatAreNamesEqual(IrpContext, *ShortName, *LongOemName) ||
3248  (FatFindFcb( IrpContext,
3249  &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3250  LongOemName,
3251  NULL) != NULL)) {
3252 
3253  ExFreePool( LongOemName->Buffer );
3254 
3255  LongOemName->Buffer = NULL;
3256  LongOemName->Length =
3257  LongOemName->MaximumLength = 0;
3258 
3259  } else {
3260 
3262  }
3263 
3264  try_return( NOTHING );
3265  }
3266 
3267  //
3268  // Now we have the fun part. Make a copy of the Lfn.
3269  //
3270 
3271 #ifndef __REACTOS__
3272  OemA.Buffer = NULL;
3273  OemB.Buffer = NULL;
3274 #endif
3275  Unicode.Buffer = NULL;
3276 
3277  Unicode.Length =
3278  Unicode.MaximumLength = Lfn->Length;
3280  Lfn->Length,
3282 
3283  RtlCopyMemory( Unicode.Buffer, Lfn->Buffer, Lfn->Length );
3284 
3285 #ifndef __REACTOS__
3287 #endif
3288 
3289 #if TRUE
3290  //
3291  // Unfortunately, this next block of code breaks down when you have
3292  // two long Unicode filenames that both map to the same Oem (and are,
3293  // well, long, i.e. are not the short names). In this case, with one
3294  // in the prefix table first, the other will hit the common Oem
3295  // representation. This leads to several forms of user astonishment.
3296  //
3297  // It isn't worth it, or probably even possible, to try to figure out
3298  // when this is really safe to go through. Simply omit the attempt.
3299  //
3300  // Ex: ANSI 0x82 and 0x84 in the 1252 ANSI->UNI and 437 UNI->OEM codepages.
3301  //
3302  // 0x82 => 0x201a => 0x2c
3303  // 0x84 => 0x201e => 0x2c
3304  //
3305  // 0x2c is comma, so is FAT Oem illegal and forces shortname generation.
3306  // Since it is otherwise well-formed by the rules articulated previously,
3307  // we would have put 0x2c in the Oem prefix tree. In terms of the
3308  // argument given above, even though there exist no Y and U s.t.
3309  //
3310  // Up(Y) == Up(U) && BestOemFit(U) != BestOemFit(Y)
3311  //
3312  // there most certainly exist Y and U s.t.
3313  //
3314  // Up(Y) != Up(U) && BestOemFit(U) == BestOemFit(Y)
3315  //
3316  // and that is enough to keep us from doing this. Note that the < 0x80
3317  // case is OK since we know that the mapping in the OEM codepages are
3318  // the identity in that range.
3319  //
3320  // We still need to monocase it, though. Do this through a full down/up
3321  // transition.
3322  //
3323 
3324  (VOID)RtlDowncaseUnicodeString( &Unicode, &Unicode, FALSE );
3325  (VOID)RtlUpcaseUnicodeString( &Unicode, &Unicode, FALSE );
3326 #else
3327  //
3328  // Downcase and convert to upcased Oem. Only continue if we can
3329  // convert without error. Any error other than UNMAPPABLE_CHAR
3330  // is a fatal error and we raise.
3331  //
3332  // Note that even if the conversion fails, we must leave Unicode
3333  // in an upcased state.
3334  //
3335  // NB: The Rtl doesn't NULL .Buffer on error.
3336  //
3337 
3338  (VOID)RtlDowncaseUnicodeString( &Unicode, &Unicode, FALSE );
3340  (VOID)RtlUpcaseUnicodeString( &Unicode, &Unicode, FALSE );
3341 
3342  if (!NT_SUCCESS(Status)) {
3343 
3345 
3347  ExFreePool(Unicode.Buffer);
3348  FatNormalizeAndRaiseStatus( IrpContext, Status );
3349  }
3350 
3351  } else {
3352 
3353  //
3354  // The same as above except upcase.
3355  //
3356 
3358 
3359  if (!NT_SUCCESS(Status)) {
3360 
3361  RtlFreeOemString( &OemA );
3362 
3364 
3366  ExFreePool(Unicode.Buffer);
3367  FatNormalizeAndRaiseStatus( IrpContext, Status );
3368  }
3369  }
3370  }
3371 
3372  //
3373  // If the final OemNames are equal, I can use save only the Oem
3374  // name. If the name did not map, then I have to go with the UNICODE
3375  // name because I could get a case varient that didn't convert
3376  // in create, but did match the LFN.
3377  //
3378 
3379  if (NT_SUCCESS(Status) && FatAreNamesEqual( IrpContext, OemA, OemB )) {
3380 
3381  //
3382  // Cool, I can go with the Oem. If we didn't convert correctly,
3383  // get a fresh convert from the original LFN.
3384  //
3385 
3386  ExFreePool(Unicode.Buffer);
3387 
3388  RtlFreeOemString( &OemB );
3389 
3390  Fcb->LongName.Oem.Name.Oem = OemA;
3391 
3392  //
3393  // If this name happens to be exactly the same as the short
3394  // name, or a similar short name already exists don't add it
3395  // to the splay table (note the final condition implies a
3396  // corrupt disk.
3397  //
3398 
3399  if (FatAreNamesEqual(IrpContext, *ShortName, OemA) ||
3400  (FatFindFcb( IrpContext,
3401  &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3402  &OemA,
3403  NULL) != NULL)) {
3404 
3405  RtlFreeOemString( &OemA );
3406 
3407  } else {
3408 
3410  }
3411 
3412  try_return( NOTHING );
3413  }
3414 
3415  //
3416  // The long name must be left in UNICODE. Free the two Oem strings
3417  // if we got here just because they weren't equal.
3418  //
3419 
3420  if (NT_SUCCESS(Status)) {
3421 
3422  RtlFreeOemString( &OemA );
3423  RtlFreeOemString( &OemB );
3424  }
3425 #endif
3426 
3427  LongUniName = &Fcb->LongName.Unicode.Name.Unicode;
3428 
3429  LongUniName->Length =
3430  LongUniName->MaximumLength = Unicode.Length;
3431  LongUniName->Buffer = Unicode.Buffer;
3432 
3434 
3435  try_exit: NOTHING;
3436  } _SEH2_FINALLY {
3437 
3438  if (_SEH2_AbnormalTermination()) {
3439 
3440  if (ShortName->Buffer != NULL) {
3441 
3442  ExFreePool( ShortName->Buffer );
3443  ShortName->Buffer = NULL;
3444  }
3445 
3446  } else {
3447 
3448  //
3449  // Creating all the names worked, so add all the names
3450  // to the splay tree.
3451  //
3452 
3453  FatInsertName( IrpContext,
3454  &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3455  &Fcb->ShortName );
3456 
3457  Fcb->ShortName.Fcb = Fcb;
3458 
3460 
3461  FatInsertName( IrpContext,
3462  &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3463  &Fcb->LongName.Oem );
3464 
3465  Fcb->LongName.Oem.Fcb = Fcb;
3466  }
3467 
3469 
3470  FatInsertName( IrpContext,
3471  &Fcb->ParentDcb->Specific.Dcb.RootUnicodeNode,
3472  &Fcb->LongName.Unicode );
3473 
3474  Fcb->LongName.Unicode.Fcb = Fcb;
3475  }
3476 
3478  }
3479  } _SEH2_END;
3480 
3481  return;
3482 }
3483 
3484 
3485 _Requires_lock_held_(_Global_critical_region_)
3486 VOID
3487 FatCheckFreeDirentBitmap (
3488  IN PIRP_CONTEXT IrpContext,
3489  IN PDCB Dcb
3490  )
3491 
3492 /*++
3493 
3494 Routine Description:
3495 
3496  This routine checks if the size of the free dirent bitmap is
3497  sufficient to for the current directory size. It is called
3498  whenever we grow a directory.
3499 
3500 Arguments:
3501 
3502  Dcb - Supplies the directory in question.
3503 
3504 Return Value:
3505 
3506  None
3507 
3508 --*/
3509 
3510 {
3511  ULONG OldNumberOfDirents;
3512  ULONG NewNumberOfDirents;
3513 
3514  PAGED_CODE();
3515  UNREFERENCED_PARAMETER( IrpContext );
3516 
3517  //
3518  // Setup the Bitmap buffer if it is not big enough already
3519  //
3520 
3521  NT_ASSERT( Dcb->Header.AllocationSize.QuadPart != FCB_LOOKUP_ALLOCATIONSIZE_HINT );
3522 
3523  OldNumberOfDirents = Dcb->Specific.Dcb.FreeDirentBitmap.SizeOfBitMap;
3524  NewNumberOfDirents = Dcb->Header.AllocationSize.LowPart / sizeof(DIRENT);
3525 
3526  //
3527  // Do the usual unsync/sync check.
3528  //
3529 
3530  if (NewNumberOfDirents > OldNumberOfDirents) {
3531 
3533 
3534  _SEH2_TRY {
3535 
3536  PULONG OldBitmapBuffer;
3538 
3539  ULONG BytesInBitmapBuffer;
3540  ULONG BytesInOldBitmapBuffer;
3541 
3542  OldNumberOfDirents = Dcb->Specific.Dcb.FreeDirentBitmap.SizeOfBitMap;
3543  NewNumberOfDirents = Dcb->Header.AllocationSize.LowPart / sizeof(DIRENT);
3544 
3545  if (NewNumberOfDirents > OldNumberOfDirents) {
3546 
3547  //
3548  // Remember the old bitmap
3549  //
3550 
3551  OldBitmapBuffer = Dcb->Specific.Dcb.FreeDirentBitmap.Buffer;
3552 
3553  //
3554  // Now make a new bitmap bufffer
3555  //
3556 
3557  BytesInBitmapBuffer = NewNumberOfDirents / 8;
3558 
3559  BytesInOldBitmapBuffer = OldNumberOfDirents / 8;
3560 
3561  if (DCB_UNION_SLACK_SPACE >= BytesInBitmapBuffer) {
3562 
3563  BitmapBuffer = &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0];
3564 
3565  } else {
3566 
3568  BytesInBitmapBuffer,
3570  }
3571 
3572  //
3573  // Copy the old buffer to the new buffer, free the old one, and zero
3574  // the rest of the new one. Only do the first two steps though if
3575  // we moved out of the initial buffer.
3576  //
3577 
3578  if ((OldNumberOfDirents != 0) &&
3579  (BitmapBuffer != &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0])) {
3580 
3582  OldBitmapBuffer,
3583  BytesInOldBitmapBuffer );
3584 
3585  if (OldBitmapBuffer != &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0]) {
3586 
3587  ExFreePool( OldBitmapBuffer );
3588  }
3589  }
3590 
3591  NT_ASSERT( BytesInBitmapBuffer > BytesInOldBitmapBuffer );
3592 
3593  RtlZeroMemory( (PUCHAR)BitmapBuffer + BytesInOldBitmapBuffer,
3594  BytesInBitmapBuffer - BytesInOldBitmapBuffer );
3595 
3596  //
3597  // Now initialize the new bitmap.
3598  //
3599 
3600  RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
3601  BitmapBuffer,
3602  NewNumberOfDirents );
3603  }
3604 
3605  } _SEH2_FINALLY {
3606 
3608  } _SEH2_END;
3609  }
3610 }
3611 
3612 
3613 BOOLEAN
3615  IN PIRP_CONTEXT IrpContext,
3616  IN PVCB Vcb
3617  )
3618 
3619 /*++
3620 
3621 Routine Description:
3622 
3623  This routine decides if the handle count on the volume is zero.
3624 
3625 Arguments:
3626 
3627  Vcb - The volume in question
3628 
3629 Return Value:
3630 
3631  BOOLEAN - TRUE if there are no open handles on the volume, FALSE
3632  otherwise.
3633 
3634 --*/
3635 
3636 {
3637  PFCB Fcb;
3638 
3639  PAGED_CODE();
3640 
3641  Fcb = Vcb->RootDcb;
3642 
3643  while (Fcb != NULL) {
3644 
3645  if (Fcb->UncleanCount != 0) {
3646 
3647  return FALSE;
3648  }
3649 
3650  Fcb = FatGetNextFcbTopDown(IrpContext, Fcb, Vcb->RootDcb);
3651  }
3652 
3653  return TRUE;
3654 }
3655 
3656 
3658 
3660  OPTIONAL PVCB Vcb
3661  )
3662 /*++
3663 
3664 Routine Description:
3665 
3666  This routine preallocates a close context, presumeably on behalf
3667  of a fileobject which does not have a structure we can embed one
3668  in.
3669 
3670 Arguments:
3671 
3672  None.
3673 
3674 Return Value:
3675 
3676  None.
3677 
3678 --*/
3679 {
3680  PAGED_CODE();
3682 
3683 #if DBG
3684  if (ARGUMENT_PRESENT(Vcb)) {
3685 
3686  NT_ASSERT( 0 != Vcb->CloseContextCount);
3687  InterlockedDecrement( (LONG*)&Vcb->CloseContextCount);
3688  }
3689 #endif
3692 }
3693 
3694 
3695 VOID
3697  PVCB Vcb
3698  )
3699 
3700 /*++
3701 
3702 Routine Description:
3703 
3704  This routine preallocates a close context, presumeably on behalf
3705  of a fileobject which does not have a structure we can embed one
3706  in.
3707 
3708 Arguments:
3709 
3710  None.
3711 
3712 Return Value:
3713 
3714  None.
3715 
3716 --*/
3717 
3718 {
3719  PCLOSE_CONTEXT CloseContext;
3720 
3721  PAGED_CODE();
3722 
3724 
3725  CloseContext = FsRtlAllocatePoolWithTag( PagedPool,
3726  sizeof(CLOSE_CONTEXT),
3728 
3730  (PSLIST_ENTRY) CloseContext,
3732 
3733  DbgDoit( InterlockedIncrement( (LONG*)&Vcb->CloseContextCount));
3734 }
3735 
3736 
3737 
3738 VOID
3741  _In_ USHORT DesiredBufferSize
3742  )
3743 
3744 /*++
3745 
3746 Routine Description:
3747 
3748  Ensures that a string string (STRING, UNICODE_STRING, ANSI_STRING, OEM_STRING)
3749  has a buffer >= DesiredBufferSize, allocating from pool if neccessary. Any
3750  existing pool buffer will be freed if a new one is allocated.
3751 
3752  NOTE: No copy of old buffer contents is performed on reallocation.
3753 
3754  Will raise on allocation failure.
3755 
3756 Arguments:
3757 
3758  String - pointer to string structure
3759 
3760  DesiredBufferSize - (bytes) minimum required buffer size
3761 
3762 --*/
3763 
3764 {
3765  PSTRING LocalString = String;
3766 
3767  PAGED_CODE();
3768 
3769  if (LocalString->MaximumLength < DesiredBufferSize) {
3770 
3771  FatFreeStringBuffer( LocalString);
3772 
3773  LocalString->Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3774  DesiredBufferSize,
3776  NT_ASSERT( LocalString->Buffer);
3777 
3778  LocalString->MaximumLength = DesiredBufferSize;
3779  }
3780 }
3781 
3782 
3783 VOID
3786  )
3787 
3788 /*++
3789 
3790 Routine Description:
3791 
3792  Frees the buffer of an string (STRING, UNICODE_STRING, ANSI_STRING, OEM_STRING)
3793  structure if it is not within the current thread's stack limits.
3794 
3795  Regardless of action performed, on exit String->Buffer will be set to NULL and
3796  String->MaximumLength to zero.
3797 
3798 Arguments:
3799 
3800  String - pointer to string structure
3801 
3802 --*/
3803 
3804 {
3805  ULONG_PTR High, Low;
3806  PSTRING LocalString = String;
3807 
3808  PAGED_CODE();
3809 
3810  if (NULL != LocalString->Buffer) {
3811 
3812  IoGetStackLimits( &Low, &High );
3813 
3814  if (((ULONG_PTR)(LocalString->Buffer) < Low) ||
3815  ((ULONG_PTR)(LocalString->Buffer) > High)) {
3816 
3817  ExFreePool( LocalString->Buffer);
3818  }
3819 
3820  LocalString->Buffer = NULL;
3821  }
3822 
3823  LocalString->MaximumLength = LocalString->Length = 0;
3824 }
3825 
3826 
3827 BOOLEAN
3829  IN PIRP_CONTEXT IrpContext,
3831  )
3832 
3833 /*++
3834 
3835 Routine Description:
3836 
3837  This routine is called to verify and process the TOC for this disk.
3838 
3839  FAT queries for the TOC to avoid trying to mount on CD-DA/CD-E media, Doing data reads on
3840  audio/leadin of that media sends a lot of drives into what could charitably be called
3841  "conniptions" which take a couple seconds to clear and would also convince FAT that the
3842  device was busted, and fail the mount (not letting CDFS get its crack).
3843 
3844  There is special handling of PD media. These things fail the TOC read, but return
3845  a special error code so FAT knows to continue to try the mount anyway.
3846 
3847 Arguments:
3848 
3849  TargetDeviceObject - Device object to send TOC request to.
3850 
3851 Return Value:
3852 
3853  BOOLEAN - TRUE if we found a TOC with a single data track.
3854 
3855 --*/
3856 
3857 {
3858  NTSTATUS Status;
3860 
3861  ULONG LocalTrackCount;
3862  ULONG LocalTocLength;
3863 
3864  PCDROM_TOC CdromToc;
3865  BOOLEAN Result = FALSE;
3866 
3867  PAGED_CODE();
3868 
3869  CdromToc = FsRtlAllocatePoolWithTag( PagedPool,
3870  sizeof( CDROM_TOC ),
3871  TAG_IO_BUFFER );
3872 
3873  RtlZeroMemory( CdromToc, sizeof( CDROM_TOC ));
3874 
3875  _SEH2_TRY {
3876 
3877  //
3878  // Go ahead and read the table of contents
3879  //
3880 
3881  Status = FatPerformDevIoCtrl( IrpContext,
3884  NULL,
3885  0,
3886  CdromToc,
3887  sizeof( CDROM_TOC ),
3888  FALSE,
3889  TRUE,
3890  &Iosb );
3891 
3892  //
3893  // Nothing to process if this request fails.
3894  //
3895 
3896  if (Status != STATUS_SUCCESS) {
3897 
3898  //
3899  // If we get the special error indicating a failed TOC read on PD media just
3900  // plow ahead with the mount (see comments above).
3901  //
3902 
3904 
3905  Result = TRUE;
3906 
3907  }
3908 
3909  try_leave( NOTHING );
3910  }
3911 
3912  //
3913  // Get the number of tracks and stated size of this structure.
3914  //
3915 
3916  LocalTrackCount = CdromToc->LastTrack - CdromToc->FirstTrack + 1;
3917  LocalTocLength = PtrOffset( CdromToc, &CdromToc->TrackData[LocalTrackCount + 1] );
3918 
3919  //
3920  // Get out if there is an immediate problem with the TOC, or more than
3921  // one track.
3922  //
3923 
3924  if ((LocalTocLength > Iosb.Information) ||
3925  (CdromToc->FirstTrack > CdromToc->LastTrack) ||
3926  (LocalTrackCount != 1)) {
3927 
3928  try_leave( NOTHING);
3929  }
3930 
3931  //
3932  // Is it a data track? DVD-RAM reports single, data, track.
3933  //
3934 
3935  Result = BooleanFlagOn( CdromToc->TrackData[ 0].Control, 0x04 );
3936  }
3937  _SEH2_FINALLY {
3938 
3939  ExFreePool( CdromToc);
3940  } _SEH2_END;
3941 
3942  return Result;
3943 }
3944 
3945 
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1303
PFCB FatGetNextFcbBottomUp(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb OPTIONAL, IN PFCB TerminationFcb)
Definition: strucsup.c:2525
struct _FCB * Fcb
Definition: fatstruc.h:685
#define DbgDoit(X)
Definition: fatdata.h:336
LONGLONG CreationTime
Definition: cdstruc.h:1030
#define FatReleaseDirectoryFileMutex(VCB)
Definition: fatprocs.h:1513
LARGE_INTEGER LastWriteTime
Definition: fatstruc.h:922
#define TAG_FCB
Definition: vfat.h:547
#define IN
Definition: typedefs.h:39
FatSetFileObject(FileObject, UserDirectoryOpen,(*Dcb), UnwindCcb=FatCreateCcb(IrpContext))
#define FCB_STATE_SYSTEM_FILE
Definition: fatstruc.h:1199
#define FatReleaseGlobal(IRPCONTEXT)
Definition: fatprocs.h:1636
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
VOID FatSyncUninitializeCacheMap(IN PIRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject)
Definition: cachesup.c:1812
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2995
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define TAG_DYNAMIC_NAME_BUFFER
Definition: nodetype.h:186
INLINE VOID FatFreeIrpContext(IN PIRP_CONTEXT IrpContext)
Definition: strucsup.c:186
#define _Inout_
Definition: ms_sal.h:378
#define FCB_LOOKUP_ALLOCATIONSIZE_HINT
Definition: fatstruc.h:1241
#define DebugDoit(X)
Definition: fatdata.h:316
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
USHORT Flags
Definition: iotypes.h:192
LARGE_INTEGER FatFatDateToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_DATE FatDate)
Definition: timesup.c:171
FILE_NAME_NODE Oem
Definition: fatstruc.h:1159
VOID FatTearDownVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: strucsup.c:684
#define VCB_STATE_FLAG_DEFERRED_FLUSH
Definition: fatstruc.h:568
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1266
UCHAR FirstTrack
Definition: ntddcdrm.h:197
#define PtrOffset(BASE, OFFSET)
Definition: cdprocs.h:1547
#define IRP_MJ_SHUTDOWN
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING Lfn
Definition: create.c:4137
#define Dbg
Definition: strucsup.c:29
BOOLEAN DeviceHotplug
Definition: imports.h:248
INLINE VOID FatFreeNonPagedFcb(PNON_PAGED_FCB NonPagedFcb)
Definition: strucsup.c:124
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
Definition: cdstruc.h:902
VOID Fat8dot3ToString(_In_ PIRP_CONTEXT IrpContext, _In_ PDIRENT Dirent, _In_ BOOLEAN RestoreCase, _Out_ POEM_STRING OutputString)
Definition: namesup.c:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1079
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1283
#define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS
Definition: fatstruc.h:575
#define IRP_CONTEXT_STACK_IO_CONTEXT
Definition: ext2fs.h:1084
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:167
#define CCB_FLAG_FREE_OEM_BEST_FIT
Definition: fatstruc.h:1259
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
Definition: cdstruc.h:1067
unsigned char * PUCHAR
Definition: retypes.h:3
#define FSRTL_FLAG2_IS_PAGING_FILE
Definition: fsrtltypes.h:57
struct _SINGLE_LIST_ENTRY *__fastcall ExInterlockedPushEntrySList(union _SLIST_HEADER *, struct _SINGLE_LIST_ENTRY *, unsigned long *)
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
LONG NTSTATUS
Definition: precomp.h:26
PFCB FatFindFcb(IN PIRP_CONTEXT IrpContext, IN OUT PRTL_SPLAY_LINKS *RootNode, IN PSTRING Name, OUT PBOOLEAN FileNameDos OPTIONAL)
Definition: splaysup.c:306
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3095
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
KSPIN_LOCK GeneralSpinLock
Definition: fatstruc.h:152
union _FCB::@704 Specific
FCB DCB
Definition: fatstruc.h:1184
union _FILE_NAME_NODE::@703 Name
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
#define IRP_NOCACHE
SLIST_HEADER FatCloseContextSList
Definition: fatdata.c:106
#define ExRaiseStatus
Definition: ntoskrnl.h:104
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
NTSTATUS NTAPI ExDeleteResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1456
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:878
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define FCB_STATE_3_LOWER_CASE
Definition: fatstruc.h:1211
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
#define FCB_STATE_HAS_UNICODE_LONG_NAME
Definition: fatstruc.h:1202
Definition: cdstruc.h:498
unsigned short Length
Definition: sprintf.c:451
Definition: strmini.h:380
VOID FatDeleteVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: strucsup.c:772
BOOLEAN ChicagoMode
Definition: fatstruc.h:87
static CC_FILE_SIZES FileSizes
VOID NTAPI FsRtlUninitializeOplock(IN POPLOCK Oplock)
Definition: oplock.c:1602
STRING OEM_STRING
Definition: umtypes.h:203
LIST_ENTRY ParentDcbLinks
Definition: fatstruc.h:828
ULONG VcbState
Definition: cdstruc.h:540
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB ParentDcb
Definition: create.c:4137
#define InsertTailList(ListHead, Entry)
NPAGED_LOOKASIDE_LIST FatNonPagedFcbLookasideList
Definition: fatdata.c:103
if(dx==0 &&dy==0)
Definition: linetemp.h:174
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:769
#define FAT_NTC_CCB
Definition: nodetype.h:32
VOID FatFreeStringBuffer(_Inout_ PVOID String)
Definition: strucsup.c:3784
struct _PACKED_BOOT_SECTOR PACKED_BOOT_SECTOR
struct _FCB * ParentDcb
Definition: fatstruc.h:836
#define TAG_VPB
Definition: cdprocs.h:106
KDEFERRED_ROUTINE FatCleanVolumeDpc
Definition: fatprocs.h:1981
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
INLINE VOID FatFreeCcb(IN PCCB Ccb)
Definition: strucsup.c:70
PDCB FatCreateDcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDCB ParentDcb, IN ULONG LfnOffsetWithinDirectory, IN ULONG DirentOffsetWithinDirectory, IN PDIRENT Dirent, IN PUNICODE_STRING Lfn OPTIONAL)
Definition: strucsup.c:1623
LARGE_INTEGER FileSize
Definition: cctypes.h:16
NPAGED_LOOKASIDE_LIST FatIrpContextLookasideList
Definition: fatdata.c:102
_SEH2_TRY
Definition: create.c:4226
#define KdPrintEx(_x_)
Definition: kdfuncs.h:114
INLINE PIRP_CONTEXT FatAllocateIrpContext()
Definition: strucsup.c:175
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FAT_DIRENT_NT_BYTE_8_LOWER_CASE
Definition: fat.h:361
BOOLEAN FileNameDos
Definition: fatstruc.h:704
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FatGetFirstChild(DIR)
Definition: fatprocs.h:1785
BOOLEAN MediaHotplug
Definition: imports.h:247
LARGE_INTEGER FatFatTimeToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_TIME_STAMP FatTime, _In_ UCHAR TenMilliSeconds)
Definition: timesup.c:233
NTSYSAPI NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN)
void * Buffer
Definition: sprintf.c:453
LARGE_INTEGER LastAccessTime
Definition: fatstruc.h:921
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define FCB_STATE_NAMES_IN_SPLAY_TREE
Definition: fatstruc.h:1200
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
struct _SINGLE_LIST_ENTRY *__fastcall ExInterlockedPopEntrySList(union _SLIST_HEADER *, unsigned long *)
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
ULONG NumberProcessors
Definition: fatstruc.h:81
#define FALSE
Definition: types.h:117
struct _VCB VCB
_In_ PIRP Irp
Definition: csq.h:116
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
long LONG
Definition: pedump.c:60
LARGE_INTEGER FatJanOne1980
Definition: fatdata.c:73
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1656
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define VPB_LOCKED
Definition: iotypes.h:1808
BOOLEAN FatScanForDataTrack(IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: strucsup.c:3828
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
UCHAR DirentFatFlags
Definition: fatstruc.h:1133
VOID FatDeleteCcb(IN PIRP_CONTEXT IrpContext, IN PCCB *Ccb)
Definition: strucsup.c:2254
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
VOID NTAPI FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, IN POOL_TYPE PoolType)
Definition: largemcb.c:451
#define NTC_UNDEFINED
Definition: nodetype.h:25
unsigned char BOOLEAN
struct _FCB FCB
FILE_NAME_NODE Unicode
Definition: fatstruc.h:1166
#define VCB_STATE_FLAG_HOTPLUGGABLE
Definition: fatstruc.h:577
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define FatRootDirectorySize(B)
Definition: fat.h:427
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define _In_
Definition: ms_sal.h:308
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define VCB_STATE_FLAG_REMOVABLE_MEDIA
Definition: fatstruc.h:560
PFCB FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2627
VOID FatTearDownAllocationSupport(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: allocsup.c:549
NodeType
Definition: Node.h:5
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
#define CCB_FLAG_FREE_UNICODE
Definition: fatstruc.h:1260
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
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
NTSTATUS FatPerformDevIoCtrl(IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
Definition: deviosup.c:3621
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186
#define FatAcquireDirectoryFileMutex(VCB)
Definition: fatprocs.h:1508
OEM_STRING Oem
Definition: fatstruc.h:693
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define RtlFillMemoryUlong(dst, len, val)
Definition: mkhive.h:55
#define try_leave(S)
Definition: cdprocs.h:2180
VOID FatRemoveNames(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: splaysup.c:222
Status
Definition: gdiplustypes.h:24
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
VOID FatDeleteIrpContext_Real(IN PIRP_CONTEXT IrpContext)
Definition: strucsup.c:2461
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define DebugUnwind(X)
Definition: fatdata.h:315
FAT_DATA FatData
Definition: fatdata.c:56
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
VOID NTAPI FsRtlTeardownPerStreamContexts(IN PFSRTL_ADVANCED_FCB_HEADER AdvFcbHeader)
Definition: filtrctx.c:368
#define INLINE
Definition: rosdhcp.h:56
PCLOSE_CONTEXT FatAllocateCloseContext(OPTIONAL PVCB Vcb)
Definition: strucsup.c:3659
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:559
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
__wchar_t WCHAR
Definition: xmlstorage.h:180
return Iosb
Definition: create.c:4402
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FatGetNextSibling(FILE)
Definition: fatprocs.h:1791
#define try_return(S)
Definition: cdprocs.h:2179
VOID FatInsertName(IN PIRP_CONTEXT IrpContext, IN PRTL_SPLAY_LINKS *RootNode, IN PFILE_NAME_NODE Name)
Definition: splaysup.c:39
INT POOL_TYPE
Definition: typedefs.h:78
#define ARGUMENT_PRESENT(ArgumentPointer)
VOID NTAPI FsRtlInitializeOplock(IN OUT POPLOCK Oplock)
Definition: oplock.c:1402
#define IRP_MJ_FILE_SYSTEM_CONTROL
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
VBO LfnOffsetWithinDirectory
Definition: fatstruc.h:913
FORCEINLINE VOID ExInitializeFastMutex(_Out_ PFAST_MUTEX FastMutex)
Definition: exfuncs.h:274
#define Vcb
Definition: cdprocs.h:1415
#define ObDereferenceObject
Definition: obfuncs.h:203
VOID NTAPI FsRtlInitializeTunnelCache(IN PTUNNEL Cache)
Definition: tunnel.c:892
const GLubyte * c
Definition: glext.h:8905
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS
Definition: fsrtltypes.h:55
BOOLEAN FatSwapVpb(IN PIRP_CONTEXT IrpContext, PVCB Vcb)
Definition: strucsup.c:2730
#define PSLIST_ENTRY
Definition: rtltypes.h:134
#define TAG_FILENAME_BUFFER
Definition: nodetype.h:167
VOID FatDeleteFcb(IN PIRP_CONTEXT IrpContext, IN PFCB *FcbPtr)
Definition: strucsup.c:1952
#define TAG_CCB
Definition: cdprocs.h:85
* PFILE_OBJECT
Definition: iotypes.h:1998
struct _IRP_CONTEXT IRP_CONTEXT
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
NPAGED_LOOKASIDE_LIST FatEResourceLookasideList
Definition: fatdata.c:104
UNICODE_STRING FullFileName
Definition: fatstruc.h:1122
Definition: strmini.h:378
#define FAT_FILL_FREE
Definition: strucsup.c:52
ULONG Flags
Definition: ntfs.h:536
UCHAR LastTrack
Definition: ntddcdrm.h:198
static ULONG BitmapBuffer[(XMS_BLOCKS+31)/32]
Definition: himem.c:86
CD_MCB Mcb
Definition: cdstruc.h:1016
FAST_MUTEX AdvancedFcbHeaderMutex
Definition: fatstruc.h:750
unsigned char UCHAR
Definition: xmlstorage.h:181
INLINE VOID FatFreeResource(IN PERESOURCE Resource)
Definition: strucsup.c:157
VOID FatPreallocateCloseContext(PVCB Vcb)
Definition: strucsup.c:3696
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define TAG_DIRENT_BITMAP
Definition: nodetype.h:159
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedDecrement
Definition: armddk.h:52
#define DCB_UNION_SLACK_SPACE
Definition: fatstruc.h:1230
#define FAT_NTC_IRP_CONTEXT
Definition: nodetype.h:33
UCHAR Control
Definition: ntddcdrm.h:137
#define VOID
Definition: acefi.h:82
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB IN PDEVICE_OBJECT FsDeviceObject
Definition: fatprocs.h:1673
CLONG UncleanCount
Definition: fatstruc.h:873
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:588
struct _CCB CCB
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
#define FCB_STATE_8_LOWER_CASE
Definition: fatstruc.h:1210
#define NOTHING
Definition: env_spec_w32.h:461
Definition: typedefs.h:119
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define FatAreNamesEqual(IRPCONTEXT, NAMEA, NAMEB)
Definition: fatprocs.h:1158
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
#define FatSetVcbCondition(V, X)
Definition: fatprocs.h:1438
#define FCB_STATE_HAS_OEM_LONG_NAME
Definition: fatstruc.h:1201
NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeStringToCountedOemString(STRING *, const UNICODE_STRING *, BOOLEAN)
#define IO_TYPE_VPB
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
PFCB FatCreateFcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDCB ParentDcb, IN ULONG LfnOffsetWithinDirectory, IN ULONG DirentOffsetWithinDirectory, IN PDIRENT Dirent, IN PUNICODE_STRING Lfn OPTIONAL, IN PUNICODE_STRING OrigLfn OPTIONAL, IN BOOLEAN IsPagingFile, IN BOOLEAN SingleResource)
Definition: strucsup.c:1252
struct _VPB VPB
INLINE VOID FatFreeFcb(IN PFCB Fcb)
Definition: strucsup.c:97
BOOLEAN FatAddMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, IN LBO Lbo, IN ULONG SectorCount)
Definition: fsctrl.c:364
LIST_ENTRY VcbQueue
Definition: fatstruc.h:49
INLINE PFCB FatAllocateFcb()
Definition: strucsup.c:86
UNICODE_STRING Unicode
Definition: fatstruc.h:695
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
VOID FatInitializeCacheMap(_In_ PFILE_OBJECT FileObject, _In_ PCC_FILE_SIZES FileSizes, _In_ BOOLEAN PinAccess, _In_ PCACHE_MANAGER_CALLBACKS Callbacks, _In_ PVOID LazyWriteContext)
Definition: cachesup.c:62
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
#define FAT_DIRENT_NT_BYTE_3_LOWER_CASE
Definition: fat.h:362
_SEH2_END
Definition: create.c:4400
VBO DirentOffsetWithinDirectory
Definition: fatstruc.h:906
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
#define InterlockedIncrement
Definition: armddk.h:53
#define STATUS_UNMAPPABLE_CHARACTER
Definition: ntstatus.h:590
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG ValidDataToDisk
Definition: fatstruc.h:928
unsigned short USHORT
Definition: pedump.c:61
PCCB FatCreateCcb(IN PIRP_CONTEXT IrpContext)
Definition: strucsup.c:2155
LARGE_INTEGER FatMaxLarge
Definition: fatdata.c:63
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
#define ExLocalTimeToSystemTime(LocTime, SysTime)
Definition: env_spec_w32.h:738
INLINE PCCB FatAllocateCcb()
Definition: strucsup.c:59
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PKEVENT OutstandingAsyncEvent
Definition: fatstruc.h:743
#define VCB_STATE_FLAG_VPB_MUST_BE_FREED
Definition: fatstruc.h:574
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
VOID FatDeallocateCcbStrings(IN PCCB Ccb)
Definition: strucsup.c:2209
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define IsFileWriteThrough(FO, VCB)
Definition: fatprocs.h:2796
_SEH2_FINALLY
Definition: create.c:4371
VOID NTAPI FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:1096
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
VOID NTAPI IoGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit)
Definition: util.c:78
CLONG OpenCount
Definition: fatstruc.h:881
#define TAG_IO_BUFFER
Definition: cdprocs.h:95
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define FAT_NTC_DCB
Definition: nodetype.h:30
ULONG FirstClusterOfFile
Definition: fatstruc.h:818
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1495
VOID NTAPI RtlFreeOemString(POEM_STRING OemString)
#define IRP_MJ_CLEANUP
VOID FatCloseEaFile(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN FlushFirst)
Definition: cachesup.c:1079
VOID NTAPI FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
Definition: notify.c:1561
Definition: iotypes.h:189
#define OUT
Definition: typedefs.h:40
#define ObReferenceObject
Definition: obfuncs.h:204
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3810
#define DIRENT
Definition: fatfs.h:187
#define c
Definition: ke_i.h:80
ULONG ERESOURCE
Definition: env_spec_w32.h:594
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]
Definition: ntddcdrm.h:199
unsigned int ULONG
Definition: retypes.h:1
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:424
#define IRP_CONTEXT_FLAG_RECURSIVE_CALL
Definition: fatstruc.h:1566
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PVCB Vcb
Definition: cdstruc.h:933
#define FAT_NTC_VCB
Definition: nodetype.h:28
#define FatRootDirectoryLbo(B)
Definition: fat.h:445
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define TAG_VCB_STATS
Definition: nodetype.h:171
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
VOID NTAPI FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync)
Definition: notify.c:1639
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
struct _FILE_SYSTEM_STATISTICS FILE_SYSTEM_STATISTICS
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define FILE_FLOPPY_DISKETTE
Definition: nt_native.h:809
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
VOID NTAPI FsRtlDeleteTunnelCache(IN PTUNNEL Cache)
Definition: tunnel.c:691
BOOLEAN MediaRemovable
Definition: imports.h:246
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1673
#define TAG_FAT_CLOSE_CONTEXT
Definition: nodetype.h:164
unsigned short MaximumLength
Definition: sprintf.c:452
struct _FCB::@704::@706 Dcb
USHORT FinalNameLength
Definition: fatstruc.h:1124
#define VPB_MOUNTED
Definition: iotypes.h:1807
INLINE PERESOURCE FatAllocateResource()
Definition: strucsup.c:140
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
union _FCB::@705 LongName
_Requires_lock_held_(_Global_critical_region_)
Definition: strucsup.c:1915
#define CCB_FLAG_CLOSE_CONTEXT
Definition: fatstruc.h:1324
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB * Dcb
Definition: create.c:4137
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
#define FatDeleteResource(RESRC)
Definition: fatprocs.h:1632
ULONG FcbState
Definition: cdstruc.h:971
unsigned short * PUSHORT
Definition: retypes.h:2
INLINE PNON_PAGED_FCB FatAllocateNonPagedFcb()
Definition: strucsup.c:113
#define FAT_NTC_FCB
Definition: nodetype.h:29
UNICODE_STRING ExactCaseLongName
Definition: fatstruc.h:1139
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1673
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define FILESYSTEM_STATISTICS_TYPE_FAT
Definition: winioctl.h:751
#define RtlOemStringToCountedUnicodeSize(STRING)
VOID FatConstructNamesInFcb(IN PIRP_CONTEXT IrpContext, PFCB Fcb, PDIRENT Dirent, PUNICODE_STRING Lfn OPTIONAL)
Definition: strucsup.c:3022
struct _FCB::@704::@707 Fcb
LONGLONG QuadPart
Definition: typedefs.h:114
VOID FatEnsureStringBufferEnough(_Inout_ PVOID String, _In_ USHORT DesiredBufferSize)
Definition: strucsup.c:3739
#define FatAcquireExclusiveGlobal(IRPCONTEXT)
Definition: fatprocs.h:1387
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1415
#define PAGED_CODE()
#define DebugDump(STR, LEVEL, PTR)
Definition: fatdata.h:314
#define NT_ASSERT
Definition: rtlfuncs.h:3310
BOOLEAN FatIsHandleCountZero(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: strucsup.c:3614
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks
Definition: fatstruc.h:160