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