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