ReactOS 0.4.15-dev-7788-g1ad9096
create.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 Create.c
8
9Abstract:
10
11 This module implements the File Create routine for Fat called by the
12 dispatch driver.
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_CREATE)
24
25//
26// The debug trace level
27//
28
29#define Dbg (DEBUG_TRACE_CREATE)
30
31
32//
33// Macros for incrementing performance counters.
34//
35
36#define CollectCreateHitStatistics(VCB) { \
37 PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber() % FatData.NumberProcessors]; \
38 Stats->Fat.CreateHits += 1; \
39}
40
41#define CollectCreateStatistics(VCB,STATUS) { \
42 PFILE_SYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber() % FatData.NumberProcessors]; \
43 if ((STATUS) == STATUS_SUCCESS) { \
44 Stats->Fat.SuccessfulCreates += 1; \
45 } else { \
46 Stats->Fat.FailedCreates += 1; \
47 } \
48}
49
51
52//
53// local procedure prototypes
54//
55
56_Requires_lock_held_(_Global_critical_region_)
59 _In_ PIRP_CONTEXT IrpContext,
65 );
66
67_Requires_lock_held_(_Global_critical_region_)
69FatOpenRootDcb (
70 _In_ PIRP_CONTEXT IrpContext,
76 );
77
78_Requires_lock_held_(_Global_critical_region_)
80FatOpenExistingDcb (
81 _In_ PIRP_CONTEXT IrpContext,
93 _Out_ PBOOLEAN OplockPostIrp
94 );
95
96_Requires_lock_held_(_Global_critical_region_)
98FatOpenExistingFcb (
99 _In_ PIRP_CONTEXT IrpContext,
115 _Out_ PBOOLEAN OplockPostIrp
116 );
117
118_Requires_lock_held_(_Global_critical_region_)
120FatOpenTargetDirectory (
121 _In_ PIRP_CONTEXT IrpContext,
126 _In_ BOOLEAN DoesNameExist,
128 );
129
131_Requires_lock_held_(_Global_critical_region_)
133FatOpenExistingDirectory (
134 _In_ PIRP_CONTEXT IrpContext,
151 );
152
153_Requires_lock_held_(_Global_critical_region_)
155FatOpenExistingFile (
156 _In_ PIRP_CONTEXT IrpContext,
165 _In_ PUNICODE_STRING OrigLfn,
173 _In_ BOOLEAN IsPagingFile,
178 );
179
180_Requires_lock_held_(_Global_critical_region_)
182FatCreateNewDirectory (
183 _In_ PIRP_CONTEXT IrpContext,
198 );
199
200_Requires_lock_held_(_Global_critical_region_)
202FatCreateNewFile (
203 _In_ PIRP_CONTEXT IrpContext,
216 _In_ PUNICODE_STRING LfnBuffer,
217 _In_ BOOLEAN IsPagingFile,
221 _In_ BOOLEAN TemporaryFile
222 );
223
224
225_Requires_lock_held_(_Global_critical_region_)
227FatSupersedeOrOverwriteFile (
228 _In_ PIRP_CONTEXT IrpContext,
237 );
238
241 _In_ PIRP_CONTEXT IrpContext
242 );
243
246 _In_ PIRP_CONTEXT IrpContext,
248 _In_ PFCB Fcb,
251 );
252
253#ifdef ALLOC_PRAGMA
254#pragma alloc_text(PAGE, FatCheckShareAccess)
255#pragma alloc_text(PAGE, FatCheckSystemSecurityAccess)
256#pragma alloc_text(PAGE, FatCommonCreate)
257
258#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
259#pragma alloc_text(PAGE, FatCommonCreateOnNewStack)
260#pragma alloc_text(PAGE, FatCommonCreateCallout)
261#endif
262
263#pragma alloc_text(PAGE, FatCreateNewDirectory)
264#pragma alloc_text(PAGE, FatCreateNewFile)
265#pragma alloc_text(PAGE, FatFsdCreate)
266#pragma alloc_text(PAGE, FatOpenExistingDcb)
267#pragma alloc_text(PAGE, FatOpenExistingDirectory)
268#pragma alloc_text(PAGE, FatOpenExistingFcb)
269#pragma alloc_text(PAGE, FatOpenExistingFile)
270#pragma alloc_text(PAGE, FatOpenRootDcb)
271#pragma alloc_text(PAGE, FatOpenTargetDirectory)
272#pragma alloc_text(PAGE, FatOpenVolume)
273#pragma alloc_text(PAGE, FatSupersedeOrOverwriteFile)
274#pragma alloc_text(PAGE, FatSetFullNameInFcb)
275#endif
276
277
281NTAPI
282FatFsdCreate (
283 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
285 )
286
287/*++
288
289Routine Description:
290
291 This routine implements the FSD part of the NtCreateFile and NtOpenFile
292 API calls.
293
294Arguments:
295
296 VolumeDeviceObject - Supplies the volume device object where the
297 file/directory exists that we are trying to open/create
298
299 Irp - Supplies the Irp being processed
300
301Return Value:
302
303 NTSTATUS - The Fsd status for the Irp
304
305--*/
306
307{
309 PIRP_CONTEXT IrpContext = NULL;
310
312 BOOLEAN ExceptionCompletedIrp = FALSE;
313
314
315 PAGED_CODE();
316
317 //
318 // If we were called with our file system device object instead of a
319 // volume device object, just complete this request with STATUS_SUCCESS
320 //
321
322 if ( FatDeviceIsFatFsdo( VolumeDeviceObject)) {
323
324 Irp->IoStatus.Status = STATUS_SUCCESS;
325 Irp->IoStatus.Information = FILE_OPENED;
326
328
329 return STATUS_SUCCESS;
330 }
331
333
334 DebugTrace(+1, Dbg, "FatFsdCreate\n", 0);
335
336 //
337 // Call the common create routine, with block allowed if the operation
338 // is synchronous.
339 //
340
342
344
345 _SEH2_TRY {
346
347 IrpContext = FatCreateIrpContext( Irp, TRUE );
348
349#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
350 Status = FatCommonCreateOnNewStack( IrpContext, Irp );
351#else
352 Status = FatCommonCreate( IrpContext, Irp );
353#endif
354
356
357 //
358 // We had some trouble trying to perform the requested
359 // operation, so we'll abort the I/O request with
360 // the error status that we get back from the
361 // execption code
362 //
363
364 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
365 ExceptionCompletedIrp = TRUE;
366 } _SEH2_END;
367
368 if (TopLevel) { IoSetTopLevelIrp( NULL ); }
369
371
372
373 //
374 // Complete the request, unless we had an exception, in which case it
375 // was completed in FatProcessException (and the IrpContext freed).
376 //
377 // IrpContext is freed inside FatCompleteRequest.
378 //
379
380 if (!ExceptionCompletedIrp && Status != STATUS_PENDING) {
381 FatCompleteRequest( IrpContext, Irp, Status );
382 }
383
384 //
385 // And return to our caller
386 //
387
388 DebugTrace(-1, Dbg, "FatFsdCreate -> %08lx\n", Status );
389
390 TimerStop(Dbg,"FatFsdCreate");
391
392 UNREFERENCED_PARAMETER( VolumeDeviceObject );
393
394 return Status;
395}
396
397#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
398_Requires_lock_held_(_Global_critical_region_)
399VOID
400FatCommonCreateCallout (
401 _In_ PFAT_CALLOUT_PARAMETERS CalloutParameters
402 )
403
404/*++
405
406Routine Description:
407
408 This function is the callout routine that will execute on a new stack when
409 processing a create. It simply calls FatCommonCreate() with the parameters
410 in the context and stores the return value in the context.
411
412Arguments:
413
414 Context - Supplies an opaque pointer to this function's context. It is actually
415 an FAT_CALLOUT_PARAMETERS structure.
416
417Return Value:
418
419 None.
420
421--*/
422
423{
424 PAGED_CODE();
425
426 //
427 // Call FatCommonCreate() with the passed parameters and store the result.
428 // Exceptions cannot be raised across stack boundaries, so we need to catch
429 // exceptions here and deal with them.
430 //
431
432 try {
433
434 CalloutParameters->IrpStatus = FatCommonCreate( CalloutParameters->Create.IrpContext,
435 CalloutParameters->Create.Irp );
436
437 } except (FatExceptionFilter( CalloutParameters->Create.IrpContext, GetExceptionInformation() )) {
438
439 //
440 // Return the resulting status.
441 //
442
443 CalloutParameters->ExceptionStatus = GetExceptionCode();
444 }
445
446}
447
448
449_Requires_lock_held_(_Global_critical_region_)
451FatCommonCreateOnNewStack (
452 _In_ PIRP_CONTEXT IrpContext,
454 )
455
456/*++
457
458Routine Description:
459
460 This routine sets up a switch to a new stack and call to FatCommonCreate().
461
462Arguments:
463
464 IrpContext - Supplies the context structure for the overall request.
465
466 Irp - Supplies the IRP being processed.
467
468 CreateContext - Supplies a pointer on the old stack that is used to
469 store context information for the create itself.
470
471Return Value:
472
473 NTSTATUS - The status from FatCommonCreate().
474
475--*/
476{
477 FAT_CALLOUT_PARAMETERS CalloutParameters;
479
480 PAGED_CODE();
481
482 //
483 // Create requests consume a lot of stack space. As such, we always switch to a
484 // new stack when processing a create. Setup the callout parameters and make the
485 // call. Note that this cannot fail, since we pass a stack context for a reserve stack.
486 //
487
488 CalloutParameters.Create.IrpContext = IrpContext;
489 CalloutParameters.Create.Irp = Irp;
490 CalloutParameters.ExceptionStatus = CalloutParameters.IrpStatus = STATUS_SUCCESS;
491
492 //
493 // Mark that we are swapping the stack
494 //
495
496 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK );
497
498 status = KeExpandKernelStackAndCalloutEx( FatCommonCreateCallout,
499 &CalloutParameters,
501 FALSE,
502 NULL );
503
504 //
505 // Mark that the stack is no longer swapped. Note that there are paths
506 // that may clear this flag before returning.
507 //
508
509 if (status != STATUS_PENDING) {
510
511 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_SWAPPED_STACK );
512 }
513
514 //
515 // If we had an exception occur, re-raise the exception.
516 //
517
518 if (!NT_SUCCESS( CalloutParameters.ExceptionStatus )) {
519 FatRaiseStatus( IrpContext, CalloutParameters.ExceptionStatus );
520 }
521
522 //
523 // If the call to KeExpandKernelStackAndCalloutEx returns an error this
524 // means that the callout routine (FatCommonCreateCallout) was never
525 // called. Translate that error, and return it.
526 //
527
528 if (!NT_SUCCESS( status )) {
529
530 //
531 // Translate to an expected error value
532 //
533
534 if (status == STATUS_NO_MEMORY) {
535
537 }
538
539 return status;
540 }
541
542 //
543 // Return the status given to us by the callout.
544 //
545
546 return CalloutParameters.IrpStatus;
547}
548#endif
549
550_Requires_lock_held_(_Global_critical_region_)
552FatCommonCreate (
553 _Inout_ PIRP_CONTEXT IrpContext,
555 )
556
557/*++
558
559Routine Description:
560
561 This is the common routine for creating/opening a file called by
562 both the fsd and fsp threads.
563
564Arguments:
565
566 Irp - Supplies the Irp to process
567
568Return Value:
569
570 NTSTATUS - the return status for the operation
571
572--*/
573
574{
576 IO_STATUS_BLOCK Iosb = {0};
578
580 PFILE_OBJECT RelatedFileObject;
589
591 BOOLEAN NoIntermediateBuffering;
593 BOOLEAN IsPagingFile;
594 BOOLEAN OpenTargetDirectory;
596 BOOLEAN NonDirectoryFile;
600 BOOLEAN TemporaryFile;
602
604
605 PVCB Vcb;
606 PFCB Fcb = NULL;
607 PCCB Ccb;
609 PDCB FinalDcb = NULL;
610
611 UNICODE_STRING FinalName = {0};
613 UNICODE_STRING NextRemainingPart = {0};
614 UNICODE_STRING UpcasedFinalName;
616
617 OEM_STRING OemFinalName;
619
621 PBCB DirentBcb = NULL;
624
625 BOOLEAN PostIrp = FALSE;
626 BOOLEAN OplockPostIrp = FALSE;
627 BOOLEAN TrailingBackslash;
628 BOOLEAN FirstLoop = TRUE;
629
630 ULONG MatchFlags = 0;
631
632 CCB LocalCcb;
634 UNICODE_STRING OrigLfn = {0};
635
637
638 PAGED_CODE();
639
640 //
641 // Get the current IRP stack location
642 //
643
645
646 DebugTrace(+1, Dbg, "FatCommonCreate\n", 0 );
647 DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
648 DebugTrace( 0, Dbg, "->Flags = %08lx\n", Irp->Flags );
649 DebugTrace( 0, Dbg, "->FileObject = %p\n", IrpSp->FileObject );
650 DebugTrace( 0, Dbg, " ->RelatedFileObject = %p\n", IrpSp->FileObject->RelatedFileObject );
651 DebugTrace( 0, Dbg, " ->FileName = %wZ\n", &IrpSp->FileObject->FileName );
652 DebugTrace( 0, Dbg, " ->FileName.Length = 0n%d\n", IrpSp->FileObject->FileName.Length );
653 DebugTrace( 0, Dbg, "->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
654 DebugTrace( 0, Dbg, "->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
655 DebugTrace( 0, Dbg, "->SystemBuffer = %p\n", Irp->AssociatedIrp.SystemBuffer );
656 DebugTrace( 0, Dbg, "->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
657 DebugTrace( 0, Dbg, "->Options = %08lx\n", IrpSp->Parameters.Create.Options );
658 DebugTrace( 0, Dbg, "->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
659 DebugTrace( 0, Dbg, "->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
660 DebugTrace( 0, Dbg, "->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
661
662 //
663 // This is here because the Win32 layer can't avoid sending me double
664 // beginning backslashes.
665 //
666
667 if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
668 (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
669 (IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
670
671 IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
672
673 RtlMoveMemory( &IrpSp->FileObject->FileName.Buffer[0],
674 &IrpSp->FileObject->FileName.Buffer[1],
675 IrpSp->FileObject->FileName.Length );
676
677 //
678 // If there are still two beginning backslashes, the name is bogus.
679 //
680
681 if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
682 (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
683 (IrpSp->FileObject->FileName.Buffer[0] == L'\\')) {
684
685 DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_OBJECT_NAME_INVALID\n", 0);
687 }
688 }
689
690 //
691 // Reference our input parameters to make things easier
692 //
693
694 NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
695
697 FileName = FileObject->FileName;
698 RelatedFileObject = FileObject->RelatedFileObject;
699 AllocationSize = Irp->Overlay.AllocationSize.LowPart;
700 EaBuffer = Irp->AssociatedIrp.SystemBuffer;
701 DesiredAccess = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
702 Options = IrpSp->Parameters.Create.Options;
703 FileAttributes = IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
704 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
705 EaLength = IrpSp->Parameters.Create.EaLength;
706
707 //
708 // Set up the file object's Vpb pointer in case anything happens.
709 // This will allow us to get a reasonable pop-up.
710 //
711
712 if ( RelatedFileObject != NULL ) {
713 FileObject->Vpb = RelatedFileObject->Vpb;
714 }
715
716 //
717 // Force setting the archive bit in the attributes byte to follow OS/2,
718 // & DOS semantics. Also mask out any extraneous bits, note that
719 // we can't use the ATTRIBUTE_VALID_FLAGS constant because that has
720 // the control and normal flags set.
721 //
722 // Delay setting ARCHIVE in case this is a directory: 2/16/95
723 //
724
730
731 //
732 // Locate the volume device object and Vcb that we are trying to access
733 //
734
736
737 //
738 // Decipher Option flags and values
739 //
740
741 //
742 // If this is an open by fileid operation, just fail it explicitly. FAT's
743 // source of fileids is not reversible for open operations.
744 //
745
747
749 }
750
752 NonDirectoryFile = BooleanFlagOn( Options, FILE_NON_DIRECTORY_FILE );
753 NoIntermediateBuffering = BooleanFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
756#if (NTDDI_VERSION >= NTDDI_WIN7)
758#else
760#endif
761
762 TemporaryFile = BooleanFlagOn( IrpSp->Parameters.Create.FileAttributes,
764
765 CreateDisposition = (Options >> 24) & 0x000000ff;
766
767 IsPagingFile = BooleanFlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE );
768 OpenTargetDirectory = BooleanFlagOn( IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY );
769
773
777
778
779 //
780 // Make sure the input large integer is valid and that the dir/nondir
781 // indicates a storage type we understand.
782 //
783
784 if (Irp->Overlay.AllocationSize.HighPart != 0 ||
785 (DirectoryFile && NonDirectoryFile)) {
786
787 DebugTrace(-1, Dbg, "FatCommonCreate -> STATUS_INVALID_PARAMETER\n", 0);
789 }
790
791 //
792 // Acquire exclusive access to the vcb, and enqueue the Irp if
793 // we didn't get it.
794 //
795
796 if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {
797
798 DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);
799
800 Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
801
802 DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status );
803 return Iosb.Status;
804 }
805
806 //
807 // Make sure we haven't been called recursively by a filter inside an existing
808 // create request.
809 //
810
812
813#ifdef _MSC_VER
814#pragma prefast( suppress:28159, "this is a serious programming error if it happens" )
815#endif
816 FatBugCheck( 0, 0, 0);
817 }
818
819 //
820 // Initialize the DirentBcb to null
821 //
822
823 DirentBcb = NULL;
824
825 //
826 // Initialize our temp strings with their stack buffers.
827 //
828
829 OemFinalName.Length = 0;
830 OemFinalName.MaximumLength = sizeof( OemBuffer);
831 OemFinalName.Buffer = (PCHAR)OemBuffer;
832
833 UpcasedFinalName.Length = 0;
834 UpcasedFinalName.MaximumLength = sizeof( UpcasedBuffer);
835 UpcasedFinalName.Buffer = UpcasedBuffer;
836
837 Lfn.Length = 0;
838 Lfn.MaximumLength = sizeof( LfnBuffer);
839 Lfn.Buffer = LfnBuffer;
840
841 _SEH2_TRY {
842
843 //
844 // Make sure the vcb is in a usable condition. This will raise
845 // and error condition if the volume is unusable
846 //
847
848 FatVerifyVcb( IrpContext, Vcb );
849
850 //
851 // If the Vcb is locked then we cannot open another file
852 //
853
854 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {
855
856 DebugTrace(0, Dbg, "Volume is locked\n", 0);
857
859 if (Vcb->VcbCondition != VcbGood) {
860
862 }
863 try_return( Iosb.Status = Status );
864 }
865
866 //
867 // Don't allow the DELETE_ON_CLOSE option if the volume is
868 // write-protected.
869 //
870
872
873 //
874 // Set the real device for the pop-up info, and set the verify
875 // bit in the device object, so that we will force a verify
876 // in case the user put the correct media back in.
877 //
878
879 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
880 Vcb->Vpb->RealDevice );
881
882 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
883
885 }
886
887 //
888 // If this is a fat32 volume, EA's are not supported.
889 //
890
891 if (EaBuffer != NULL) {
892
894 }
895
896 //
897 // Check if we are opening the volume and not a file/directory.
898 // We are opening the volume if the name is empty and there
899 // isn't a related file object. If there is a related file object
900 // then it is the Vcb itself.
901 //
902
903 if (FileName.Length == 0) {
904
905 PVCB DecodeVcb = NULL;
906
907 if (RelatedFileObject == NULL ||
908 FatDecodeFileObject( RelatedFileObject,
909 &DecodeVcb,
910 &Fcb,
911 &Ccb ) == UserVolumeOpen) {
912
913 NT_ASSERT( RelatedFileObject == NULL || Vcb == DecodeVcb );
914
915 //
916 // Check if we were to open a directory
917 //
918
919 if (DirectoryFile) {
920
921 DebugTrace(0, Dbg, "Cannot open volume as a directory\n", 0);
922
924 }
925
926 //
927 // Can't open the TargetDirectory of the DASD volume.
928 //
929
930 if (OpenTargetDirectory) {
931
933 }
934
935 DebugTrace(0, Dbg, "Opening the volume, Vcb = %p\n", Vcb);
936
938
939 Iosb = FatOpenVolume( IrpContext,
941 Vcb,
945
946 Irp->IoStatus.Information = Iosb.Information;
947 try_return( Iosb.Status );
948 }
949 }
950
951 //
952 // If there is a related file object then this is a relative open.
953 // The related file object is the directory to start our search at.
954 // Return an error if it is not a directory.
955 //
956
957 if (RelatedFileObject != NULL) {
958
959 PVCB RelatedVcb;
960 PDCB RelatedDcb;
961 PCCB RelatedCcb;
963
964 TypeOfOpen = FatDecodeFileObject( RelatedFileObject,
965 &RelatedVcb,
966 &RelatedDcb,
967 &RelatedCcb );
968
969 if (TypeOfOpen != UserFileOpen &&
971
972 DebugTrace(0, Dbg, "Invalid related file object\n", 0);
973
975 }
976
977 //
978 // A relative open must be via a relative path.
979 //
980
981 if (FileName.Length != 0 &&
982 FileName.Buffer[0] == L'\\') {
983
985 }
986
987 //
988 // Set up the file object's Vpb pointer in case anything happens.
989 //
990
991 NT_ASSERT( Vcb == RelatedVcb );
992
993 FileObject->Vpb = RelatedFileObject->Vpb;
994
995 //
996 // Now verify the related Fcb so we don't get in trouble later
997 // by assuming its in good shape.
998 //
999
1000 FatVerifyFcb( IrpContext, RelatedDcb );
1001
1002 ParentDcb = RelatedDcb;
1003
1004 } else {
1005
1006 //
1007 // This is not a relative open, so check if we're
1008 // opening the root dcb
1009 //
1010
1011 if ((FileName.Length == sizeof(WCHAR)) &&
1012 (FileName.Buffer[0] == L'\\')) {
1013
1014 //
1015 // Check if we were not supposed to open a directory
1016 //
1017
1018 if (NonDirectoryFile) {
1019
1020 DebugTrace(0, Dbg, "Cannot open root directory as a file\n", 0);
1021
1023 }
1024
1025 //
1026 // Can't open the TargetDirectory of the root directory.
1027 //
1028
1029 if (OpenTargetDirectory) {
1030
1032 }
1033
1034 //
1035 // Not allowed to delete root directory.
1036 //
1037
1038 if (DeleteOnClose) {
1039
1041 }
1042
1043 DebugTrace(0, Dbg, "Opening root dcb\n", 0);
1044
1046
1047 Iosb = FatOpenRootDcb( IrpContext,
1048 FileObject,
1049 Vcb,
1053
1054 Irp->IoStatus.Information = Iosb.Information;
1055 try_return( Iosb.Status );
1056 }
1057
1058 //
1059 // Nope, we will be opening relative to the root directory.
1060 //
1061
1062 ParentDcb = Vcb->RootDcb;
1063
1064 //
1065 // Now verify the root Dcb so we don't get in trouble later
1066 // by assuming its in good shape.
1067 //
1068
1069 FatVerifyFcb( IrpContext, ParentDcb );
1070 }
1071
1072 //
1073 // FatCommonCreate(): trailing backslash check
1074 //
1075
1076
1077 if ((FileName.Length != 0) &&
1078 (FileName.Buffer[FileName.Length/sizeof(WCHAR)-1] == L'\\')) {
1079
1080 FileName.Length -= sizeof(WCHAR);
1081 TrailingBackslash = TRUE;
1082
1083 } else {
1084
1085 TrailingBackslash = FALSE;
1086 }
1087
1088 //
1089 // Check for max path. We might want to tighten this down to DOS MAX_PATH
1090 // for maximal interchange with non-NT platforms, but for now defer to the
1091 // possibility of something depending on it.
1092 //
1093
1094 if (ParentDcb->FullFileName.Buffer == NULL) {
1095
1096 FatSetFullFileNameInFcb( IrpContext, ParentDcb );
1097 }
1098
1099 if ((USHORT) (ParentDcb->FullFileName.Length + sizeof(WCHAR) + FileName.Length) <= FileName.Length) {
1100
1102 }
1103
1104 //
1105 // We loop here until we land on an Fcb that is in a good
1106 // condition. This way we can reopen files that have stale handles
1107 // to files of the same name but are now different.
1108 //
1109
1110 while ( TRUE ) {
1111
1112 Fcb = ParentDcb;
1114
1115 //
1116 // Now walk down the Dcb tree looking for the longest prefix.
1117 // This one exit condition in the while() is to handle a
1118 // special case condition (relative NULL name open), the main
1119 // exit conditions are at the bottom of the loop.
1120 //
1121
1122 while (RemainingPart.Length != 0) {
1123
1124 PFCB NextFcb;
1125
1127 &FinalName,
1128 &NextRemainingPart );
1129
1130 //
1131 // If RemainingPart starts with a backslash the name is
1132 // invalid.
1133 // Check for no more than 255 characters in FinalName
1134 //
1135
1136 if (((NextRemainingPart.Length != 0) && (NextRemainingPart.Buffer[0] == L'\\')) ||
1137 (FinalName.Length > 255*sizeof(WCHAR))) {
1138
1140 }
1141
1142 //
1143 // Now, try to convert this one component into Oem and search
1144 // the splay tree. If it works then that's great, otherwise
1145 // we have to try with the UNICODE name instead.
1146 //
1147
1148 FatEnsureStringBufferEnough( &OemFinalName,
1149 FinalName.Length);
1150
1151 Status = RtlUpcaseUnicodeStringToCountedOemString( &OemFinalName, &FinalName, FALSE );
1152
1153
1154 if (NT_SUCCESS(Status)) {
1155
1156 NextFcb = FatFindFcb( IrpContext,
1157 &Fcb->Specific.Dcb.RootOemNode,
1158 (PSTRING)&OemFinalName,
1160
1161 } else {
1162
1163 NextFcb = NULL;
1164 OemFinalName.Length = 0;
1165
1167
1168 try_return( Iosb.Status = Status );
1169 }
1170 }
1171
1172 //
1173 // If we didn't find anything searching the Oem space, we
1174 // have to try the Unicode space. To save cycles in the
1175 // common case that this tree is empty, we do a quick check
1176 // here.
1177 //
1178
1179 if ((NextFcb == NULL) && Fcb->Specific.Dcb.RootUnicodeNode) {
1180
1181 //
1182 // First downcase, then upcase the string, because this
1183 // is what happens when putting names into the tree (see
1184 // strucsup.c, FatConstructNamesInFcb()).
1185 //
1186
1187 FatEnsureStringBufferEnough( &UpcasedFinalName,
1188 FinalName.Length);
1189
1190 Status = RtlDowncaseUnicodeString(&UpcasedFinalName, &FinalName, FALSE );
1192
1193 Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &UpcasedFinalName, FALSE );
1195
1196
1197 NextFcb = FatFindFcb( IrpContext,
1198 &Fcb->Specific.Dcb.RootUnicodeNode,
1199 (PSTRING)&UpcasedFinalName,
1201 }
1202
1203 //
1204 // If we got back an Fcb then we consumed the FinalName
1205 // legitimately, so the remaining name is now RemainingPart.
1206 //
1207
1208 if (NextFcb != NULL) {
1209 Fcb = NextFcb;
1210 RemainingPart = NextRemainingPart;
1211 }
1212
1213 if ((NextFcb == NULL) ||
1214 (NodeType(NextFcb) == FAT_NTC_FCB) ||
1215 (NextRemainingPart.Length == 0)) {
1216
1217 break;
1218 }
1219 }
1220
1221 //
1222 // Remaining name cannot start with a backslash
1223 //
1224
1225 if (RemainingPart.Length && (RemainingPart.Buffer[0] == L'\\')) {
1226
1227 RemainingPart.Length -= sizeof(WCHAR);
1228 RemainingPart.Buffer += 1;
1229 }
1230
1231 //
1232 // Now verify that everybody up to the longest found prefix is valid.
1233 //
1234
1235 _SEH2_TRY {
1236
1237 FatVerifyFcb( IrpContext, Fcb );
1238
1242
1243 FatResetExceptionState( IrpContext );
1244 } _SEH2_END;
1245
1246 if ( Fcb->FcbCondition == FcbGood ) {
1247
1248 //
1249 // If we are trying to open a paging file and have happened
1250 // upon the DelayedCloseFcb, make it go away, and try again.
1251 //
1252
1253 if (IsPagingFile && FirstLoop &&
1254 (NodeType(Fcb) == FAT_NTC_FCB) &&
1257
1258 FatFspClose(Vcb);
1259
1260 FirstLoop = FALSE;
1261
1262 continue;
1263
1264 } else {
1265
1266 break;
1267 }
1268
1269 } else {
1270
1271 FatRemoveNames( IrpContext, Fcb );
1272 }
1273 }
1274
1276
1277 //
1278 // If there is already an Fcb for a paging file open and
1279 // it was not already opened as a paging file, we cannot
1280 // continue as it is too difficult to move a live Fcb to
1281 // non-paged pool.
1282 //
1283
1284 if (IsPagingFile) {
1285
1286 if (NodeType(Fcb) == FAT_NTC_FCB &&
1288
1290 }
1291
1292 //
1293 // Check for a system file.
1294 //
1295
1296 } else if (FlagOn( Fcb->FcbState, FCB_STATE_SYSTEM_FILE )) {
1297
1299 }
1300
1301 //
1302 // If the longest prefix is pending delete (either the file or
1303 // some higher level directory), we cannot continue.
1304 //
1305
1307
1309 }
1310
1311 //
1312 // Now that we've found the longest matching prefix we'll
1313 // check if there isn't any remaining part because that means
1314 // we've located an existing fcb/dcb to open and we can do the open
1315 // without going to the disk
1316 //
1317
1318 if (RemainingPart.Length == 0) {
1319
1320 //
1321 // First check if the user wanted to open the target directory
1322 // and if so then call the subroutine to finish the open.
1323 //
1324
1325 if (OpenTargetDirectory) {
1326
1328
1329 Iosb = FatOpenTargetDirectory( IrpContext,
1330 FileObject,
1331 Fcb->ParentDcb,
1334 TRUE,
1336 Irp->IoStatus.Information = Iosb.Information;
1337 try_return( Iosb.Status );
1338 }
1339
1340 //
1341 // We can open an existing fcb/dcb, now we only need to case
1342 // on which type to open.
1343 //
1344
1346
1347 //
1348 // This is a directory we're opening up so check if
1349 // we were not to open a directory
1350 //
1351
1352 if (NonDirectoryFile) {
1353
1354 DebugTrace(0, Dbg, "Cannot open directory as a file\n", 0);
1355
1357 }
1358
1359 DebugTrace(0, Dbg, "Open existing dcb, Dcb = %p\n", Fcb);
1360
1362
1363 Iosb = FatOpenExistingDcb( IrpContext,
1364 IrpSp,
1365 FileObject,
1366 Vcb,
1367 (PDCB)Fcb,
1375 &OplockPostIrp );
1376
1377 if (Iosb.Status != STATUS_PENDING) {
1378
1379 Irp->IoStatus.Information = Iosb.Information;
1380
1381 } else {
1382
1383 DebugTrace(0, Dbg, "Enqueue Irp to FSP\n", 0);
1384
1385 PostIrp = TRUE;
1386 }
1387
1388 try_return( Iosb.Status );
1389 }
1390
1391 //
1392 // Check if we're trying to open an existing Fcb and that
1393 // the user didn't want to open a directory. Note that this
1394 // call might actually come back with status_pending because
1395 // the user wanted to supersede or overwrite the file and we
1396 // cannot block. If it is pending then we do not complete the
1397 // request, and we fall through the bottom to the code that
1398 // dispatches the request to the fsp.
1399 //
1400
1401 if (NodeType(Fcb) == FAT_NTC_FCB) {
1402
1403 //
1404 // Check if we were only to open a directory
1405 //
1406
1407 if (OpenDirectory) {
1408
1409 DebugTrace(0, Dbg, "Cannot open file as directory\n", 0);
1410
1412 }
1413
1414 DebugTrace(0, Dbg, "Open existing fcb, Fcb = %p\n", Fcb);
1415
1416 if ( TrailingBackslash ) {
1418 }
1419
1421
1422 Iosb = FatOpenExistingFcb( IrpContext,
1423 IrpSp,
1424 FileObject,
1425 Vcb,
1426 Fcb,
1430 EaBuffer,
1431 EaLength,
1438 &OplockPostIrp );
1439
1440 if (Iosb.Status != STATUS_PENDING) {
1441
1442 //
1443 // Check if we need to set the cache support flag in
1444 // the file object
1445 //
1446
1447 if (NT_SUCCESS( Iosb.Status) && !NoIntermediateBuffering) {
1448
1450 }
1451
1452 Irp->IoStatus.Information = Iosb.Information;
1453
1454 } else {
1455
1456 DebugTrace(0, Dbg, "Enqueue Irp to FSP\n", 0);
1457
1458 PostIrp = TRUE;
1459 }
1460
1461 try_return( Iosb.Status );
1462 }
1463
1464 //
1465 // Not and Fcb or a Dcb so we bug check
1466 //
1467
1468#ifdef _MSC_VER
1469#pragma prefast( suppress:28159, "this is a serious corruption if it happens" )
1470#endif
1472 }
1473
1474 //
1475 // There is more in the name to parse than we have in existing
1476 // fcbs/dcbs. So now make sure that fcb we got for the largest
1477 // matching prefix is really a dcb otherwise we can't go any
1478 // further
1479 //
1480
1481 if ((NodeType(Fcb) != FAT_NTC_DCB) && (NodeType(Fcb) != FAT_NTC_ROOT_DCB)) {
1482
1483 DebugTrace(0, Dbg, "Cannot open file as subdirectory, Fcb = %p\n", Fcb);
1484
1486 }
1487
1488 //
1489 // Otherwise we continue on processing the Irp and allowing ourselves
1490 // to block for I/O as necessary. Find/create additional dcb's for
1491 // the one we're trying to open. We loop until either remaining part
1492 // is empty or we get a bad filename. When we exit FinalName is
1493 // the last name in the string we're after, and ParentDcb is the
1494 // parent directory that will contain the opened/created
1495 // file/directory.
1496 //
1497 // Make sure the rest of the name is valid in at least the LFN
1498 // character set (which just happens to be that of HPFS).
1499 //
1500 // If we are not in ChicagoMode, use FAT semantics.
1501 //
1502
1503 ParentDcb = Fcb;
1504 FirstLoop = TRUE;
1505
1506 while (TRUE) {
1507
1508 //
1509 // We do one little optimization here on the first iteration of
1510 // the loop since we know that we have already tried to convert
1511 // FinalOemName from the original UNICODE.
1512 //
1513
1514 if (FirstLoop) {
1515
1516 FirstLoop = FALSE;
1517 RemainingPart = NextRemainingPart;
1519
1520 } else {
1521
1522 //
1523 // Dissect the remaining part.
1524 //
1525
1526 DebugTrace(0, Dbg, "Dissecting the name %wZ\n", &RemainingPart);
1527
1529 &FinalName,
1530 &RemainingPart );
1531
1532 //
1533 // If RemainingPart starts with a backslash the name is
1534 // invalid.
1535 // Check for no more than 255 characters in FinalName
1536 //
1537
1538 if (((RemainingPart.Length != 0) && (RemainingPart.Buffer[0] == L'\\')) ||
1539 (FinalName.Length > 255*sizeof(WCHAR))) {
1540
1542 }
1543
1544 //
1545 // Now, try to convert this one component into Oem. If it works
1546 // then that's great, otherwise we have to try with the UNICODE
1547 // name instead.
1548 //
1549
1550 FatEnsureStringBufferEnough( &OemFinalName,
1551 FinalName.Length);
1552
1553 Status = RtlUpcaseUnicodeStringToCountedOemString( &OemFinalName, &FinalName, FALSE );
1554 }
1555
1556 if (NT_SUCCESS(Status)) {
1557
1558 //
1559 // We'll start by trying to locate the dirent for the name. Note
1560 // that we already know that there isn't an Fcb/Dcb for the file
1561 // otherwise we would have found it when we did our prefix lookup.
1562 //
1563
1564 if (FatIsNameShortOemValid( IrpContext, OemFinalName, FALSE, FALSE, FALSE )) {
1565
1566 FatStringTo8dot3( IrpContext,
1567 OemFinalName,
1568 &LocalCcb.OemQueryTemplate.Constant );
1569
1570 LocalCcb.Flags = 0;
1571
1572 } else {
1573
1575 }
1576
1577 } else {
1578
1580
1582
1583 try_return( Iosb.Status = Status );
1584 }
1585 }
1586
1587 //
1588 // Now we know a lot about the final name, so do legal name
1589 // checking here.
1590 //
1591
1592 if (FatData.ChicagoMode) {
1593
1594 if (!FatIsNameLongUnicodeValid( IrpContext, &FinalName, FALSE, FALSE, FALSE )) {
1595
1597 }
1598
1599 } else {
1600
1602
1604 }
1605 }
1606
1607 DebugTrace(0, Dbg, "FinalName is %wZ\n", &FinalName);
1608 DebugTrace(0, Dbg, "RemainingPart is %wZ\n", &RemainingPart);
1609
1610 FatEnsureStringBufferEnough( &UpcasedFinalName,
1611 FinalName.Length);
1612
1613 if (!NT_SUCCESS(Status = RtlUpcaseUnicodeString( &UpcasedFinalName, &FinalName, FALSE))) {
1614
1615 try_return( Iosb.Status = Status );
1616 }
1617
1618 LocalCcb.UnicodeQueryTemplate = UpcasedFinalName;
1619 LocalCcb.ContainsWildCards = FALSE;
1620
1621 Lfn.Length = 0;
1622
1623
1624 FatLocateDirent( IrpContext,
1625 ParentDcb,
1626 &LocalCcb,
1627 0,
1628 &MatchFlags,
1629 &Dirent,
1630 &DirentBcb,
1633 &Lfn,
1634 &OrigLfn);
1635
1636 //
1637 // Remember we read this Dcb for error recovery.
1638 //
1639
1640 FinalDcb = ParentDcb;
1641
1642 //
1643 // If the remaining part is now empty then this is the last name
1644 // in the string and the one we want to open
1645 //
1646
1647 if (RemainingPart.Length == 0) {
1648
1649
1650 break;
1651 }
1652
1653 //
1654 // We didn't find a dirent, bail.
1655 //
1656
1657 if (Dirent == NULL) {
1658
1660 try_return( Iosb.Status );
1661 }
1662
1663 //
1664 // We now have a dirent, make sure it is a directory
1665 //
1666
1667 if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
1668
1670 try_return( Iosb.Status );
1671 }
1672
1673 //
1674 // Compute the LfnByteOffset.
1675 //
1676
1678 FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT);
1679
1680 //
1681 // Create a dcb for the new directory
1682 //
1683
1684 ParentDcb = FatCreateDcb( IrpContext,
1685 Vcb,
1686 ParentDcb,
1689 Dirent,
1690 &Lfn );
1691
1692 //
1693 // Remember we created this Dcb for error recovery.
1694 //
1695
1696 FinalDcb = ParentDcb;
1697
1698 FatSetFullNameInFcb( IrpContext, ParentDcb, &FinalName );
1699 }
1700
1701 //
1702 // First check if the user wanted to open the target directory
1703 // and if so then call the subroutine to finish the open.
1704 //
1705
1706 if (OpenTargetDirectory) {
1707
1708 Iosb = FatOpenTargetDirectory( IrpContext,
1709 FileObject,
1710 ParentDcb,
1713 Dirent ? TRUE : FALSE,
1715
1716 Irp->IoStatus.Information = Iosb.Information;
1717 try_return( Iosb.Status );
1718 }
1719
1720 if (Dirent != NULL) {
1721
1722 //
1723 // Compute the LfnByteOffset.
1724 //
1725
1727 FAT_LFN_DIRENTS_NEEDED(&OrigLfn) * sizeof(LFN_DIRENT);
1728
1729 //
1730 // We were able to locate an existing dirent entry, so now
1731 // see if it is a directory that we're trying to open.
1732 //
1733
1734 if (FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
1735
1736 //
1737 // Make sure its okay to open a directory
1738 //
1739
1740 if (NonDirectoryFile) {
1741
1742 DebugTrace(0, Dbg, "Cannot open directory as a file\n", 0);
1743
1745 }
1746
1747 DebugTrace(0, Dbg, "Open existing directory\n", 0);
1748
1749 Iosb = FatOpenExistingDirectory( IrpContext,
1750 IrpSp,
1751 FileObject,
1752 Vcb,
1753 &Fcb,
1754 ParentDcb,
1755 Dirent,
1758 &Lfn,
1766
1767 Irp->IoStatus.Information = Iosb.Information;
1768 try_return( Iosb.Status );
1769 }
1770
1771 //
1772 // Otherwise we're trying to open and existing file, and we
1773 // need to check if the user only wanted to open a directory.
1774 //
1775
1776 if (OpenDirectory) {
1777
1778 DebugTrace(0, Dbg, "Cannot open file as directory\n", 0);
1779
1781 }
1782
1783 DebugTrace(0, Dbg, "Open existing file\n", 0);
1784
1785 if ( TrailingBackslash ) {
1787 }
1788
1789
1790 Iosb = FatOpenExistingFile( IrpContext,
1791 FileObject,
1792 Vcb,
1793 &Fcb,
1794 ParentDcb,
1795 Dirent,
1798 &Lfn,
1799 &OrigLfn,
1803 EaBuffer,
1804 EaLength,
1807 IsPagingFile,
1812
1813 //
1814 // Check if we need to set the cache support flag in
1815 // the file object
1816 //
1817
1818 if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering) {
1819
1821 }
1822
1823 Irp->IoStatus.Information = Iosb.Information;
1824 try_return( Iosb.Status );
1825 }
1826
1827 //
1828 // We can't locate a dirent so this is a new file.
1829 //
1830
1831 //
1832 // Now check to see if we wanted to only open an existing file.
1833 // And then case on whether we wanted to create a file or a directory.
1834 //
1835
1836 if ((CreateDisposition == FILE_OPEN) ||
1838
1839 DebugTrace( 0, Dbg, "Cannot open nonexisting file\n", 0);
1840
1842 }
1843
1844 //
1845 // Skip a few cycles later if we know now that the Oem name is not
1846 // valid 8.3.
1847 //
1848
1850
1851 OemFinalName.Length = 0;
1852 }
1853
1854 //
1855 // Determine the granted access for this operation now.
1856 //
1857
1858 if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
1859
1860 try_return( Iosb );
1861 }
1862
1863 if (CreateDirectory) {
1864
1865 DebugTrace(0, Dbg, "Create new directory\n", 0);
1866
1867 //
1868 // If this media is write protected, don't even try the create.
1869 //
1870
1871 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
1872
1873 //
1874 // Set the real device for the pop-up info, and set the verify
1875 // bit in the device object, so that we will force a verify
1876 // in case the user put the correct media back in.
1877 //
1878
1879
1880 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
1881 Vcb->Vpb->RealDevice );
1882
1883 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
1884
1886 }
1887
1888 //
1889 // Don't allow people to create directories with the
1890 // temporary bit set.
1891 //
1892
1893 if (TemporaryFile) {
1894
1896 }
1897
1898 Iosb = FatCreateNewDirectory( IrpContext,
1899 IrpSp,
1900 FileObject,
1901 Vcb,
1902 ParentDcb,
1903 &OemFinalName,
1904 &FinalName,
1907 EaBuffer,
1908 EaLength,
1913
1914 Irp->IoStatus.Information = Iosb.Information;
1915 try_return( Iosb.Status );
1916 }
1917
1918 DebugTrace(0, Dbg, "Create new file\n", 0);
1919
1920 if ( TrailingBackslash ) {
1921
1923 }
1924
1925 //
1926 // If this media is write protected, don't even try the create.
1927 //
1928
1929 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
1930
1931 //
1932 // Set the real device for the pop-up info, and set the verify
1933 // bit in the device object, so that we will force a verify
1934 // in case the user put the correct media back in.
1935 //
1936
1937
1938 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
1939 Vcb->Vpb->RealDevice );
1940
1941 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
1942
1944 }
1945
1946
1947 Iosb = FatCreateNewFile( IrpContext,
1948 IrpSp,
1949 FileObject,
1950 Vcb,
1951 ParentDcb,
1952 &OemFinalName,
1953 &FinalName,
1957 EaBuffer,
1958 EaLength,
1960 &Lfn,
1961 IsPagingFile,
1965 TemporaryFile );
1966
1967 //
1968 // Check if we need to set the cache support flag in
1969 // the file object
1970 //
1971
1972 if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering) {
1973
1975 }
1976
1977 Irp->IoStatus.Information = Iosb.Information;
1978
1979 try_exit: NOTHING;
1980
1981 //
1982 // This is a Beta Fix. Do this at a better place later.
1983 //
1984
1985 if (NT_SUCCESS(Iosb.Status) && !OpenTargetDirectory) {
1986
1987 PFCB LocalFcb;
1988
1989 //
1990 // If there is an Fcb/Dcb, set the long file name.
1991 //
1992
1993 LocalFcb = FileObject->FsContext;
1994
1995 if (LocalFcb &&
1996 ((NodeType(LocalFcb) == FAT_NTC_FCB) ||
1997 (NodeType(LocalFcb) == FAT_NTC_DCB)) &&
1998 (LocalFcb->FullFileName.Buffer == NULL)) {
1999
2000 FatSetFullNameInFcb( IrpContext, LocalFcb, &FinalName );
2001 }
2002 }
2003
2004 } _SEH2_FINALLY {
2005
2006 DebugUnwind( FatCommonCreate );
2007
2008#if (NTDDI_VERSION >= NTDDI_WIN7)
2009
2010 //
2011 // If we're not getting out with success, and if the caller wanted
2012 // atomic create-with-oplock semantics make sure we back out any
2013 // oplock that may have been granted.
2014 //
2015
2016 if ((AbnormalTermination() ||
2017 !NT_SUCCESS( Iosb.Status )) &&
2019 (Iosb.Status != STATUS_CANNOT_BREAK_OPLOCK) &&
2020 (IrpContext->ExceptionStatus != STATUS_CANNOT_BREAK_OPLOCK) &&
2021 (Fcb != NULL) &&
2023
2024 FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
2025 IrpContext->OriginatingIrp,
2027 NULL,
2028 NULL,
2029 NULL );
2030 }
2031#endif
2032
2033 //
2034 // There used to be a test here - the ASSERT replaces it. We will
2035 // never have begun enumerating directories if we post the IRP for
2036 // oplock reasons.
2037 //
2038
2039 NT_ASSERT( !OplockPostIrp || DirentBcb == NULL );
2040
2041 FatUnpinBcb( IrpContext, DirentBcb );
2042
2043 //
2044 // If we are in an error path, check for any created subdir Dcbs that
2045 // have to be unwound. Don't whack the root directory.
2046 //
2047 // Note this will leave a branch of Dcbs dangling if the directory file
2048 // had not been built on the leaf (case: opening path which has an
2049 // element containing an invalid character name).
2050 //
2051
2052 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Iosb.Status)) {
2053
2054 ULONG SavedFlags;
2055
2056 //
2057 // Before doing the uninitialize, we have to unpin anything
2058 // that has been repinned, but disable writethrough first. We
2059 // disable raise from unpin-repin since we're already failing.
2060 //
2061
2062 SavedFlags = IrpContext->Flags;
2063
2064 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE |
2066
2067 FatUnpinRepinnedBcbs( IrpContext );
2068
2069 if ((FinalDcb != NULL) &&
2070 (NodeType(FinalDcb) == FAT_NTC_DCB) &&
2071 IsListEmpty(&FinalDcb->Specific.Dcb.ParentDcbQueue) &&
2072 (FinalDcb->OpenCount == 0) &&
2073 (FinalDcb->Specific.Dcb.DirectoryFile != NULL)) {
2074
2075 PFILE_OBJECT DirectoryFileObject;
2076
2077 DirectoryFileObject = FinalDcb->Specific.Dcb.DirectoryFile;
2078
2079 FinalDcb->Specific.Dcb.DirectoryFile = NULL;
2080
2081 CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
2082
2083 ObDereferenceObject( DirectoryFileObject );
2084 }
2085
2086 IrpContext->Flags = SavedFlags;
2087 }
2088
2090
2091 FatReleaseVcb( IrpContext, Vcb );
2092 }
2093
2094 //
2095 // Free up any string buffers we allocated
2096 //
2097
2098 FatFreeStringBuffer( &OemFinalName);
2099
2100 FatFreeStringBuffer( &UpcasedFinalName);
2101
2103 } _SEH2_END;
2104
2105 //
2106 // The following code is only executed if we are exiting the
2107 // procedure through a normal termination. We complete the request
2108 // and if for any reason that bombs out then we need to unreference
2109 // and possibly delete the fcb and ccb.
2110 //
2111
2112 _SEH2_TRY {
2113
2114 if (PostIrp) {
2115
2116 //
2117 // If the Irp hasn't already been posted, do it now.
2118 //
2119
2120 if (!OplockPostIrp) {
2121
2122 Iosb.Status = FatFsdPostRequest( IrpContext, Irp );
2123 }
2124
2125 } else {
2126
2127 FatUnpinRepinnedBcbs( IrpContext );
2128 }
2129
2130 } _SEH2_FINALLY {
2131
2132 DebugUnwind( FatCommonCreate-in-FatCompleteRequest );
2133
2135
2136 PVCB LocalVcb;
2137 PFCB LocalFcb;
2138 PCCB LocalCcb2;
2139 PFILE_OBJECT DirectoryFileObject;
2140
2141 //
2142 // Unwind all of our counts. Note that if a write failed, then
2143 // the volume has been marked for verify, and all volume
2144 // structures will be cleaned up automatically.
2145 //
2146
2147 (VOID) FatDecodeFileObject( FileObject, &LocalVcb, &LocalFcb, &LocalCcb2 );
2148
2149 LocalFcb->UncleanCount -= 1;
2150 LocalFcb->OpenCount -= 1;
2151 LocalVcb->OpenFileCount -= 1;
2152
2153 if (IsFileObjectReadOnly(FileObject)) { LocalVcb->ReadOnlyCount -= 1; }
2154
2155
2156 //
2157 // WinSE #307418 "Occasional data corruption when standby/resume
2158 // while copying files to removable FAT formatted media".
2159 // If new file creation request was interrupted by system suspend
2160 // operation we should revert the changes we made to the parent
2161 // directory and to the allocation table.
2162 //
2163
2164 if (IrpContext->ExceptionStatus == STATUS_VERIFY_REQUIRED &&
2165 NodeType( LocalFcb ) == FAT_NTC_FCB) {
2166
2167 FatTruncateFileAllocation( IrpContext, LocalFcb, 0 );
2168
2169 FatDeleteDirent( IrpContext, LocalFcb, NULL, TRUE );
2170 }
2171
2172 //
2173 // If we leafed out on a new Fcb we should get rid of it at this point.
2174 //
2175 // Since the object isn't being opened, we have to do all of the teardown
2176 // here. Our close path will not occur for this fileobject. Note this
2177 // will leave a branch of Dcbs dangling since we do it by hand and don't
2178 // chase to the root.
2179 //
2180
2181 if (LocalFcb->OpenCount == 0 &&
2182 (NodeType( LocalFcb ) == FAT_NTC_FCB ||
2183 IsListEmpty(&LocalFcb->Specific.Dcb.ParentDcbQueue))) {
2184
2185 NT_ASSERT( NodeType( LocalFcb ) != FAT_NTC_ROOT_DCB );
2186
2187 if ( (NodeType( LocalFcb ) == FAT_NTC_DCB) &&
2188 (LocalFcb->Specific.Dcb.DirectoryFile != NULL) ) {
2189
2190 DirectoryFileObject = LocalFcb->Specific.Dcb.DirectoryFile;
2191 LocalFcb->Specific.Dcb.DirectoryFile = NULL;
2192
2193 CcUninitializeCacheMap( DirectoryFileObject,
2194 &FatLargeZero,
2195 NULL );
2196
2197 ObDereferenceObject( DirectoryFileObject );
2198
2199 } else {
2201 FileObject->SectionObjectPointer = NULL;
2202 }
2203 FatDeleteFcb( IrpContext, &LocalFcb );
2204 }
2205 }
2206
2207 FatDeleteCcb( IrpContext, &LocalCcb2 );
2208
2209 FatReleaseVcb( IrpContext, LocalVcb );
2210
2211 } else {
2212
2213 FatReleaseVcb( IrpContext, Vcb );
2214
2215 if ( !PostIrp ) {
2216
2217 //
2218 // If this request is successful and the file was opened
2219 // for FILE_EXECUTE access, then set the FileObject bit.
2220 //
2221
2222 NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
2224
2226 }
2227
2228 //
2229 // Lock volume in drive if we opened a paging file, allocating a
2230 // reserve MDL to guarantee paging file operations can always
2231 // go forward.
2232 //
2233
2234 if (IsPagingFile && NT_SUCCESS(Iosb.Status)) {
2235
2236#ifdef _MSC_VER
2237#pragma prefast( suppress:28112, "this should be safe" )
2238#endif
2239 if (!FatReserveMdl) {
2240
2241 PMDL ReserveMdl = IoAllocateMdl( NULL,
2243 TRUE,
2244 FALSE,
2245 NULL );
2246
2247 //
2248 // Stash the MDL, and if it turned out there was already one there
2249 // just free what we got.
2250 //
2251
2252#ifndef __REACTOS__
2254#else
2255 InterlockedCompareExchangePointer( (void * volatile*)&FatReserveMdl, ReserveMdl, NULL );
2256#endif
2257
2258#ifdef _MSC_VER
2259#pragma prefast( suppress:28112, "this should be safe" )
2260#endif
2261 if (FatReserveMdl != ReserveMdl) {
2262
2263 IoFreeMdl( ReserveMdl );
2264 }
2265 }
2266
2268
2269 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {
2270
2271 FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
2272 }
2273 }
2274
2275 }
2276 }
2277
2278 DebugTrace(-1, Dbg, "FatCommonCreate -> %08lx\n", Iosb.Status);
2279 } _SEH2_END;
2280
2282
2283 return Iosb.Status;
2284}
2285
2286//
2287// Internal support routine
2288//
2289
2290_Requires_lock_held_(_Global_critical_region_)
2293 _In_ PIRP_CONTEXT IrpContext,
2299 )
2300
2301/*++
2302
2303Routine Description:
2304
2305 This routine opens the specified volume for DASD access
2306
2307Arguments:
2308
2309 FileObject - Supplies the File object
2310
2311 Vcb - Supplies the Vcb denoting the volume being opened
2312
2313 DesiredAccess - Supplies the desired access of the caller
2314
2315 ShareAccess - Supplies the share access of the caller
2316
2317 CreateDisposition - Supplies the create disposition for this operation
2318
2319Return Value:
2320
2321 IO_STATUS_BLOCK - Returns the completion status for the operation
2322
2323--*/
2324
2325{
2328
2329#ifndef __REACTOS__
2330 IO_STATUS_BLOCK Iosb = {0,0};
2331#else
2332 IO_STATUS_BLOCK Iosb = {{0}};
2333#endif
2334
2335 BOOLEAN CleanedVolume = FALSE;
2336
2337 //
2338 // The following variables are for abnormal termination
2339 //
2340
2341 BOOLEAN UnwindShareAccess = FALSE;
2343 BOOLEAN UnwindCounts = FALSE;
2344 BOOLEAN UnwindVolumeLock = FALSE;
2345
2346 PAGED_CODE();
2347
2348 DebugTrace(+1, Dbg, "FatOpenVolume...\n", 0);
2349
2350 _SEH2_TRY {
2351
2352 //
2353 // Check for proper desired access and rights
2354 //
2355
2356 if ((CreateDisposition != FILE_OPEN) &&
2358
2360 }
2361
2362 //
2363 // If the user does not want to share write or delete then we will try
2364 // and take out a lock on the volume.
2365 //
2366
2369
2370#if (NTDDI_VERSION >= NTDDI_VISTA)
2371 //
2372 // See if the user has requested write access. If so, they cannot share
2373 // read. There is one exception to this. We allow autochk to get an
2374 // implicit lock on the volume while still allowing readers. Once the
2375 // the system is booted, though, we do not allow this type of access.
2376 //
2377
2379 FsRtlAreVolumeStartupApplicationsComplete()) {
2380
2382 }
2383#endif
2384
2385 //
2386 // Do a quick check here for handles on exclusive open.
2387 //
2388
2390 !FatIsHandleCountZero( IrpContext, Vcb )) {
2391
2393 }
2394
2395 //
2396 // Force Mm to get rid of its referenced file objects.
2397 //
2398
2399 FatFlushFat( IrpContext, Vcb );
2400
2401 FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
2402
2403 //
2404 // If the user also does not want to share read then we check
2405 // if anyone is already using the volume, and if so then we
2406 // deny the access. If the user wants to share read then
2407 // we allow the current opens to stay provided they are only
2408 // readonly opens and deny further opens.
2409 //
2410
2412
2413 if (Vcb->OpenFileCount != 0) {
2414
2416 }
2417
2418 } else {
2419
2420 if (Vcb->ReadOnlyCount != Vcb->OpenFileCount) {
2421
2423 }
2424 }
2425
2426 //
2427 // Lock the volume
2428 //
2429
2430 Vcb->VcbState |= VCB_STATE_FLAG_LOCKED;
2431 Vcb->FileObjectWithVcbLocked = FileObject;
2432 UnwindVolumeLock = TRUE;
2433
2434 //
2435 // Clean the volume
2436 //
2437
2438 CleanedVolume = TRUE;
2439
2441
2442 //
2443 // Flush the volume and let ourselves push the clean bit out if everything
2444 // worked.
2445 //
2446
2447 if (NT_SUCCESS( FatFlushVolume( IrpContext, Vcb, Flush ))) {
2448
2449 CleanedVolume = TRUE;
2450 }
2451 }
2452
2453 //
2454 // Clean the volume if we believe it safe and reasonable.
2455 //
2456
2457 if (CleanedVolume &&
2458 FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY ) &&
2459 !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY ) &&
2460 !CcIsThereDirtyData(Vcb->Vpb)) {
2461
2462 //
2463 // Cancel any pending clean volumes.
2464 //
2465
2466 (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
2467 (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
2468
2469 FatMarkVolume( IrpContext, Vcb, VolumeClean );
2471
2472 //
2473 // Unlock the volume if it is removable.
2474 //
2475
2476 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
2478
2479 FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
2480 }
2481 }
2482
2483 //
2484 // If the volume is already opened by someone then we need to check
2485 // the share access
2486 //
2487
2488 if (Vcb->DirectAccessOpenCount > 0) {
2489
2492 FileObject,
2493 &Vcb->ShareAccess,
2494 TRUE ))) {
2495
2496 try_return( Iosb.Status );
2497 }
2498
2499 } else {
2500
2503 FileObject,
2504 &Vcb->ShareAccess );
2505 }
2506
2507 UnwindShareAccess = TRUE;
2508
2509 //
2510 // Set up the context and section object pointers, and update
2511 // our reference counts
2512 //
2513
2516 Vcb,
2517 UnwindCcb = FatCreateCcb( IrpContext ));
2518
2519 FileObject->SectionObjectPointer = &Vcb->SectionObjectPointers;
2520
2521 Vcb->DirectAccessOpenCount += 1;
2522 Vcb->OpenFileCount += 1;
2523 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
2524 UnwindCounts = TRUE;
2526
2527 //
2528 // At this point the open will succeed, so check if the user is getting explicit access
2529 // to the device. If not, we will note this so we can deny modifying FSCTL to it.
2530 //
2531
2532 IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
2534 Vcb->Vpb->RealDevice,
2535 IrpSp->Parameters.Create.SecurityContext->AccessState,
2537 UserMode :
2538 IrpContext->OriginatingIrp->RequestorMode ));
2539
2540 if (NT_SUCCESS( Status )) {
2541
2543 }
2544
2545 //
2546 // And set our status to success
2547 //
2548
2549 Iosb.Status = STATUS_SUCCESS;
2550 Iosb.Information = FILE_OPENED;
2551
2552 try_exit: NOTHING;
2553 } _SEH2_FINALLY {
2554
2556
2557 //
2558 // If this is an abnormal termination then undo our work
2559 //
2560
2561 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Iosb.Status)) {
2562
2563 if (UnwindCounts) {
2564 Vcb->DirectAccessOpenCount -= 1;
2565 Vcb->OpenFileCount -= 1;
2566 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
2567 }
2568 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
2569 if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Vcb->ShareAccess ); }
2570 if (UnwindVolumeLock) { Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED; }
2571 }
2572
2573 DebugTrace(-1, Dbg, "FatOpenVolume -> Iosb.Status = %08lx\n", Iosb.Status);
2574 } _SEH2_END;
2575
2576 return Iosb;
2577}
2578
2579
2580//
2581// Internal support routine
2582//
2583
2584_Requires_lock_held_(_Global_critical_region_)
2586FatOpenRootDcb (
2587 _In_ PIRP_CONTEXT IrpContext,
2593 )
2594
2595/*++
2596
2597Routine Description:
2598
2599 This routine opens the root dcb for the volume
2600
2601Arguments:
2602
2603 FileObject - Supplies the File object
2604
2605 Vcb - Supplies the Vcb denoting the volume whose dcb is being opened.
2606
2607 DesiredAccess - Supplies the desired access of the caller
2608
2609 ShareAccess - Supplies the share access of the caller
2610
2611 CreateDisposition - Supplies the create disposition for this operation
2612
2613Return Value:
2614
2615 IO_STATUS_BLOCK - Returns the completion status for the operation
2616
2617Arguments:
2618
2619--*/
2620
2621{
2622 PDCB RootDcb;
2623 IO_STATUS_BLOCK Iosb = {0};
2624
2625 //
2626 // The following variables are for abnormal termination
2627 //
2628
2629 BOOLEAN UnwindShareAccess = FALSE;
2631 BOOLEAN UnwindCounts = FALSE;
2632 BOOLEAN RootDcbAcquired = FALSE;
2633
2634 PAGED_CODE();
2635
2636 DebugTrace(+1, Dbg, "FatOpenRootDcb...\n", 0);
2637
2638 //
2639 // Locate the root dcb
2640 //
2641
2642 RootDcb = Vcb->RootDcb;
2643
2644 //
2645 // Get the Dcb exlcusive. This is important as cleanup does not
2646 // acquire the Vcb.
2647 //
2648
2649 (VOID)FatAcquireExclusiveFcb( IrpContext, RootDcb );
2650 RootDcbAcquired = TRUE;
2651
2652 _SEH2_TRY {
2653
2654 //
2655 // Check the create disposition and desired access
2656 //
2657
2658 if ((CreateDisposition != FILE_OPEN) &&
2660
2661 Iosb.Status = STATUS_ACCESS_DENIED;
2662 try_return( Iosb );
2663 }
2664
2665 if (!FatCheckFileAccess( IrpContext,
2666 RootDcb->DirentFatFlags,
2667 DesiredAccess)) {
2668
2669 Iosb.Status = STATUS_ACCESS_DENIED;
2670 try_return( Iosb );
2671 }
2672
2673 //
2674 // If the Root dcb is already opened by someone then we need
2675 // to check the share access
2676 //
2677
2678 if (RootDcb->OpenCount > 0) {
2679
2682 FileObject,
2683 &RootDcb->ShareAccess,
2684 TRUE ))) {
2685
2686 try_return( Iosb );
2687 }
2688
2689 } else {
2690
2693 FileObject,
2694 &RootDcb->ShareAccess );
2695 }
2696
2697 UnwindShareAccess = TRUE;
2698
2699 //
2700 // Setup the context and section object pointers, and update
2701 // our reference counts
2702 //
2703
2706 RootDcb,
2707 UnwindCcb = FatCreateCcb( IrpContext ));
2708
2709 RootDcb->UncleanCount += 1;
2710 RootDcb->OpenCount += 1;
2711 Vcb->OpenFileCount += 1;
2712 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
2713 UnwindCounts = TRUE;
2714
2715 //
2716 // And set our status to success
2717 //
2718
2719 Iosb.Status = STATUS_SUCCESS;
2720 Iosb.Information = FILE_OPENED;
2721
2722 try_exit: NOTHING;
2723 } _SEH2_FINALLY {
2724
2725 DebugUnwind( FatOpenRootDcb );
2726
2727 //
2728 // If this is an abnormal termination then undo our work
2729 //
2730
2732
2733 if (UnwindCounts) {
2734 RootDcb->UncleanCount -= 1;
2735 RootDcb->OpenCount -= 1;
2736 Vcb->OpenFileCount -= 1;
2737 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
2738 }
2739 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
2740 if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &RootDcb->ShareAccess ); }
2741 }
2742
2743 if (RootDcbAcquired) {
2744
2745 FatReleaseFcb( IrpContext, RootDcb );
2746 }
2747
2748 DebugTrace(-1, Dbg, "FatOpenRootDcb -> Iosb.Status = %08lx\n", Iosb.Status);
2749 } _SEH2_END;
2750
2751 return Iosb;
2752}
2753
2754
2755//
2756// Internal support routine
2757//
2758
2759_Requires_lock_held_(_Global_critical_region_)
2761FatOpenExistingDcb (
2762 _In_ PIRP_CONTEXT IrpContext,
2774 _Out_ PBOOLEAN OplockPostIrp
2775 )
2776
2777/*++
2778
2779Routine Description:
2780
2781 This routine opens the specified existing dcb
2782
2783Arguments:
2784
2785 FileObject - Supplies the File object
2786
2787 Vcb - Supplies the Vcb denoting the volume containing the dcb
2788
2789 Dcb - Supplies the already existing dcb
2790
2791 DesiredAccess - Supplies the desired access of the caller
2792
2793 ShareAccess - Supplies the share access of the caller
2794
2795 CreateDisposition - Supplies the create disposition for this operation
2796
2797 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
2798 open if the file has NeedEa's.
2799
2800 DeleteOnClose - The caller wants the file gone when the handle is closed
2801
2802Return Value:
2803
2804 IO_STATUS_BLOCK - Returns the completion status for the operation
2805
2806--*/
2807
2808{
2809 IO_STATUS_BLOCK Iosb = {0};
2810 PBCB DirentBcb = NULL;
2812
2813 //
2814 // The following variables are for abnormal termination
2815 //
2816
2817 BOOLEAN UnwindShareAccess = FALSE;
2819 BOOLEAN DcbAcquired = FALSE;
2820
2821#if (NTDDI_VERSION <= NTDDI_WIN7)
2823#endif
2824
2826
2827 PAGED_CODE();
2828
2829 DebugTrace(+1, Dbg, "FatOpenExistingDcb...\n", 0);
2830
2831 //
2832 // Get the Dcb exlcusive. This is important as cleanup does not
2833 // acquire the Vcb.
2834 //
2835
2836 (VOID)FatAcquireExclusiveFcb( IrpContext, Dcb );
2837 DcbAcquired = TRUE;
2838
2839 _SEH2_TRY {
2840
2841
2842 *OplockPostIrp = FALSE;
2843
2844 //
2845 // Before spending any noticeable effort, see if we have the odd case
2846 // of someone trying to delete-on-close the root dcb. This will only
2847 // happen if we're hit with a null-filename relative open via the root.
2848 //
2849
2851
2852 Iosb.Status = STATUS_CANNOT_DELETE;
2853 try_return( Iosb );
2854 }
2855
2856#if (NTDDI_VERSION >= NTDDI_WIN8)
2857
2858 //
2859 // Let's make sure that if the caller provided an oplock key that it
2860 // gets stored in the file object.
2861 //
2862
2863 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Dcb),
2864 IrpContext->OriginatingIrp,
2866 NULL,
2867 NULL,
2868 NULL );
2869
2870 if (Iosb.Status != STATUS_SUCCESS) {
2871
2873 }
2874
2875#endif
2876 //
2877 // If the caller has no Ea knowledge, we immediately check for
2878 // Need Ea's on the file. We don't need to check for ea's on the
2879 // root directory, because it never has any. Fat32 doesn't have
2880 // any, either.
2881 //
2882
2884 !FatIsFat32(Vcb)) {
2885
2887
2888 //
2889 // Get the dirent for the file and then check that the need
2890 // ea count is 0.
2891 //
2892
2893 FatGetDirentFromFcbOrDcb( IrpContext,
2894 Dcb,
2895 FALSE,
2896 &Dirent,
2897 &DirentBcb );
2898
2899 FatGetNeedEaCount( IrpContext,
2900 Vcb,
2901 Dirent,
2902 &NeedEaCount );
2903
2904 FatUnpinBcb( IrpContext, DirentBcb );
2905
2906 if (NeedEaCount != 0) {
2907
2908 Iosb.Status = STATUS_ACCESS_DENIED;
2909 try_return( Iosb );
2910 }
2911 }
2912
2913 //
2914 // Check the create disposition and desired access
2915 //
2916
2917 if ((CreateDisposition != FILE_OPEN) &&
2919
2921 try_return( Iosb );
2922 }
2923
2924 if (!FatCheckFileAccess( IrpContext,
2925 Dcb->DirentFatFlags,
2926 DesiredAccess)) {
2927
2928 Iosb.Status = STATUS_ACCESS_DENIED;
2929 try_return( Iosb );
2930 }
2931
2932 //
2933 // If the dcb is already opened by someone then we need
2934 // to check the share access
2935 //
2936
2937 if (Dcb->OpenCount > 0) {
2938
2939 if (!NT_SUCCESS(Iosb.Status = FatCheckShareAccess( IrpContext,
2940 FileObject,
2941 Dcb,
2943 ShareAccess ))) {
2944#if (NTDDI_VERSION >= NTDDI_WIN8)
2945
2946 NTSTATUS OplockBreakStatus = STATUS_SUCCESS;
2947
2948 //
2949 // If we got a sharing violation try to break outstanding handle
2950 // oplocks and retry the sharing check. If the caller specified
2951 // FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock;
2952 // we just return the sharing violation.
2953 //
2954
2955 if ((Iosb.Status == STATUS_SHARING_VIOLATION) &&
2957
2958 OplockBreakStatus = FsRtlOplockBreakH( FatGetFcbOplock(Dcb),
2959 IrpContext->OriginatingIrp,
2960 0,
2961 IrpContext,
2963 FatPrePostIrp );
2964
2965 //
2966 // If FsRtlOplockBreakH returned STATUS_PENDING, then the IRP
2967 // has been posted and we need to stop working.
2968 //
2969
2970 if (OplockBreakStatus == STATUS_PENDING) {
2971
2972 Iosb.Status = STATUS_PENDING;
2973 *OplockPostIrp = TRUE;
2975
2976 //
2977 // If FsRtlOplockBreakH returned an error we want to return that now.
2978 //
2979
2980 } else if (!NT_SUCCESS( OplockBreakStatus )) {
2981
2982 Iosb.Status = OplockBreakStatus;
2983 try_return( Iosb );
2984
2985 //
2986 // Otherwise FsRtlOplockBreakH returned STATUS_SUCCESS, indicating
2987 // that there is no oplock to be broken. The sharing violation is
2988 // returned in that case.
2989 //
2990
2991 } else {
2992
2993 NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS );
2994
2995 try_return( Iosb );
2996 }
2997
2998 //
2999 // The initial sharing check failed with something other than sharing
3000 // violation (which should never happen, but let's be future-proof),
3001 // or we *did* get a sharing violation and the caller specified
3002 // FILE_COMPLETE_IF_OPLOCKED. Either way this create is over.
3003 //
3004
3005 } else {
3006
3007 try_return( Iosb );
3008 }
3009#else
3010
3011 try_return( Iosb );
3012#endif
3013 }
3014 }
3015
3016#if (NTDDI_VERSION >= NTDDI_WIN8)
3017
3018 //
3019 // Now check that we can continue based on the oplock state of the
3020 // directory. If there are no open handles yet we don't need to do
3021 // this check; oplocks can only exist when there are handles.
3022 //
3023
3024 if (Dcb->UncleanCount != 0) {
3025
3027 IrpContext->OriginatingIrp,
3028 IrpContext,
3030 FatPrePostIrp );
3031 }
3032
3033 //
3034 // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
3035 // to service an oplock break and we need to leave now.
3036 //
3037
3038 if (Iosb.Status == STATUS_PENDING) {
3039
3040 *OplockPostIrp = TRUE;
3042 }
3043
3044 //
3045 // If the caller wants atomic create-with-oplock semantics, tell
3046 // the oplock package. We haven't incremented the Fcb's UncleanCount
3047 // for this create yet, so add that in on the call.
3048 //
3049
3050 if (OpenRequiringOplock &&
3051 (Iosb.Status == STATUS_SUCCESS)) {
3052
3054 IrpContext->OriginatingIrp,
3055 (Dcb->UncleanCount + 1) );
3056 }
3057
3058 //
3059 // If we've encountered a failure we need to leave. FsRtlCheckOplock
3060 // will have returned STATUS_OPLOCK_BREAK_IN_PROGRESS if it initiated
3061 // and oplock break and the caller specified FILE_COMPLETE_IF_OPLOCKED
3062 // on the create call. That's an NT_SUCCESS code, so we need to keep
3063 // going.
3064 //
3065
3066 if ((Iosb.Status != STATUS_SUCCESS) &&
3068
3070 }
3071
3072#endif
3073
3074 //
3075 // Now that we're done with the oplock work update the share counts.
3076 // If the Dcb isn't yet opened we just set the share access rather than
3077 // update it.
3078 //
3079
3080 if (Dcb->OpenCount > 0) {
3081
3083
3084 } else {
3085
3088 FileObject,
3089 &Dcb->ShareAccess );
3090 }
3091
3092 UnwindShareAccess = TRUE;
3093
3094 //
3095 // Setup the context and section object pointers, and update
3096 // our reference counts
3097 //
3098
3101 Dcb,
3102 UnwindCcb = FatCreateCcb( IrpContext ));
3103
3104 Dcb->UncleanCount += 1;
3105 Dcb->OpenCount += 1;
3106 Vcb->OpenFileCount += 1;
3107 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
3108
3109 //
3110 // Mark the delete on close bit if the caller asked for that.
3111 //
3112
3113 {
3114 PCCB Ccb = (PCCB)FileObject->FsContext2;
3115
3116
3117 if (DeleteOnClose) {
3118
3120 }
3121 if (FileNameOpenedDos) {
3122
3124 }
3125
3126 }
3127
3128
3129 //
3130 // In case this was set, clear it now.
3131 //
3132
3134
3135 //
3136 // And set our status to success
3137 //
3138
3139 Iosb.Status = STATUS_SUCCESS;
3140 Iosb.Information = FILE_OPENED;
3141
3142 try_exit: NOTHING;
3143 } _SEH2_FINALLY {
3144
3145 DebugUnwind( FatOpenExistingDcb );
3146
3147 //
3148 // Unpin the Dirent Bcb if pinned.
3149 //
3150
3151 FatUnpinBcb( IrpContext, DirentBcb );
3152
3153 //
3154 // If this is an abnormal termination then undo our work
3155 //
3156
3158
3159 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
3160 if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Dcb->ShareAccess ); }
3161 }
3162
3163 if (DcbAcquired) {
3164
3165 FatReleaseFcb( IrpContext, Dcb );
3166 }
3167
3168 DebugTrace(-1, Dbg, "FatOpenExistingDcb -> Iosb.Status = %08lx\n", Iosb.Status);
3169 } _SEH2_END;
3170
3171 return Iosb;
3172}
3173
3174
3175//
3176// Internal support routine
3177//
3178
3179_Requires_lock_held_(_Global_critical_region_)
3181FatOpenExistingFcb (
3182 _In_ PIRP_CONTEXT IrpContext,
3198 _Out_ PBOOLEAN OplockPostIrp
3199 )
3200
3201/*++
3202
3203Routine Description:
3204
3205 This routine opens the specified existing fcb
3206
3207Arguments:
3208
3209 FileObject - Supplies the File object
3210
3211 Vcb - Supplies the Vcb denoting the volume containing the Fcb
3212
3213 Fcb - Supplies the already existing fcb
3214
3215 DesiredAccess - Supplies the desired access of the caller
3216
3217 ShareAccess - Supplies the share access of the caller
3218
3219 AllocationSize - Supplies the initial allocation if the file is being
3220 superseded or overwritten
3221
3222 EaBuffer - Supplies the Ea set if the file is being superseded or
3223 overwritten
3224
3225 EaLength - Supplies the size, in byte, of the EaBuffer
3226
3227 FileAttributes - Supplies file attributes to use if the file is being
3228 superseded or overwritten
3229
3230 CreateDisposition - Supplies the create disposition for this operation
3231
3232 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
3233 open if the file has NeedEa's.
3234
3235 DeleteOnClose - The caller wants the file gone when the handle is closed
3236
3237 OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
3238
3239 FileNameOpenedDos - The caller hit the short side of the name pair finding
3240 this file
3241
3242 OplockPostIrp - Address to store boolean indicating if the Irp needs to
3243 be posted to the Fsp.
3244
3245Return Value:
3246
3247 IO_STATUS_BLOCK - Returns the completion status for the operation
3248
3249--*/
3250
3251{
3252 IO_STATUS_BLOCK Iosb = {0};
3253
3254 PBCB DirentBcb = NULL;
3256
3257 ACCESS_MASK AddedAccess = 0;
3258
3259 //
3260 // The following variables are for abnormal termination
3261 //
3262
3263 BOOLEAN UnwindShareAccess = FALSE;
3265 BOOLEAN DecrementFcbOpenCount = FALSE;
3266 BOOLEAN FcbAcquired = FALSE;
3267
3268
3269 PAGED_CODE();
3270
3271 DebugTrace(+1, Dbg, "FatOpenExistingFcb...\n", 0);
3272
3273 //
3274 // Get the Fcb exlcusive. This is important as cleanup does not
3275 // acquire the Vcb.
3276 //
3277
3278 (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
3279 FcbAcquired = TRUE;
3280
3281 _SEH2_TRY {
3282
3283
3284 *OplockPostIrp = FALSE;
3285
3286#if (NTDDI_VERSION >= NTDDI_WIN7)
3287
3288 //
3289 // Let's make sure that if the caller provided an oplock key that it
3290 // gets stored in the file object.
3291 //
3292
3293 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
3294 IrpContext->OriginatingIrp,
3296 NULL,
3297 NULL,
3298 NULL );
3299
3300 if (Iosb.Status != STATUS_SUCCESS) {
3301
3303 }
3304#endif
3305
3306 //
3307 // Take special action if there is a current batch oplock or
3308 // batch oplock break in process on the Fcb.
3309 //
3310
3312
3313 //
3314 // We remember if a batch oplock break is underway for the
3315 // case where the sharing check fails.
3316 //
3317
3318 Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;
3319
3321 IrpContext->OriginatingIrp,
3322 IrpContext,
3324 FatPrePostIrp );
3325
3326 //
3327 // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
3328 // to service an oplock break and we need to leave now.
3329 //
3330
3331 if (Iosb.Status == STATUS_PENDING) {
3332
3333 *OplockPostIrp = TRUE;
3335 }
3336 }
3337
3338 //
3339 // Check if the user wanted to create the file, also special case
3340 // the supersede and overwrite options. Those add additional,
3341 // possibly only implied, desired accesses to the caller, which
3342 // we must be careful to pull back off if the caller did not actually
3343 // request them.
3344 //
3345 // In other words, check against the implied access, but do not modify
3346 // share access as a result.
3347 //
3348
3350
3352 try_return( Iosb );
3353
3354 } else if (CreateDisposition == FILE_SUPERSEDE) {
3355
3356 SetFlag( AddedAccess,
3357 DELETE & ~(*DesiredAccess) );
3358
3360
3361 } else if ((CreateDisposition == FILE_OVERWRITE) ||
3363
3364 SetFlag( AddedAccess,
3366
3368 }
3369
3370 //
3371 // Check the desired access
3372 //
3373
3374 if (!FatCheckFileAccess( IrpContext,
3376 DesiredAccess )) {
3377
3378 Iosb.Status = STATUS_ACCESS_DENIED;
3379 try_return( Iosb );
3380 }
3381
3382
3383 //
3384 // Check for trying to delete a read only file.
3385 //
3386
3387 if (DeleteOnClose &&
3389
3390 Iosb.Status = STATUS_CANNOT_DELETE;
3391 try_return( Iosb );
3392 }
3393
3394 //
3395 // If we are asked to do an overwrite or supersede operation then
3396 // deny access for files where the file attributes for system and
3397 // hidden do not match
3398 //
3399
3403
3406
3409
3410 if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
3412
3413 DebugTrace(0, Dbg, "The hidden and/or system bits do not match\n", 0);
3414
3415
3416 Iosb.Status = STATUS_ACCESS_DENIED;
3417 try_return( Iosb );
3418 }
3419
3420 //
3421 // If this media is write protected, don't even try the create.
3422 //
3423
3424 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
3425
3426 //
3427 // Set the real device for the pop-up info, and set the verify
3428 // bit in the device object, so that we will force a verify
3429 // in case the user put the correct media back in.
3430 //
3431
3432 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
3433 Vcb->Vpb->RealDevice );
3434
3435 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
3436
3438 }
3439 }
3440
3441 //
3442 // Check if the Fcb has the proper share access. This routine will also
3443 // check for writable user secions if the user did not allow write sharing.
3444 //
3445
3446 if (!NT_SUCCESS(Iosb.Status = FatCheckShareAccess( IrpContext,
3447 FileObject,
3448 Fcb,
3450 ShareAccess ))) {
3451
3452#if (NTDDI_VERSION >= NTDDI_WIN7)
3453
3454 NTSTATUS OplockBreakStatus = STATUS_SUCCESS;
3455
3456 //
3457 // If we got a sharing violation try to break outstanding handle
3458 // oplocks and retry the sharing check. If the caller specified
3459 // FILE_COMPLETE_IF_OPLOCKED we don't bother breaking the oplock;
3460 // we just return the sharing violation.
3461 //
3462
3463 if ((Iosb.Status == STATUS_SHARING_VIOLATION) &&
3465
3466 OplockBreakStatus = FsRtlOplockBreakH( FatGetFcbOplock(Fcb),
3467 IrpContext->OriginatingIrp,
3468 0,
3469 IrpContext,
3471 FatPrePostIrp );
3472
3473 //
3474 // If FsRtlOplockBreakH returned STATUS_PENDING, then the IRP
3475 // has been posted and we need to stop working.
3476 //
3477
3478 if (OplockBreakStatus == STATUS_PENDING) {
3479
3480 Iosb.Status = STATUS_PENDING;
3481 *OplockPostIrp = TRUE;
3483
3484 //
3485 // If FsRtlOplockBreakH returned an error we want to return that now.
3486 //
3487
3488 } else if (!NT_SUCCESS( OplockBreakStatus )) {
3489
3490 Iosb.Status = OplockBreakStatus;
3491 try_return( Iosb );
3492
3493 //
3494 // Otherwise FsRtlOplockBreakH returned STATUS_SUCCESS, indicating
3495 // that there is no oplock to be broken. The sharing violation is
3496 // returned in that case.
3497 //
3498
3499 } else {
3500
3501 NT_ASSERT( OplockBreakStatus == STATUS_SUCCESS );
3502
3503 try_return( Iosb );
3504 }
3505
3506 //
3507 // The initial sharing check failed with something other than sharing
3508 // violation (which should never happen, but let's be future-proof),
3509 // or we *did* get a sharing violation and the caller specified
3510 // FILE_COMPLETE_IF_OPLOCKED. Either way this create is over.
3511 //
3512
3513 } else {
3514
3515 try_return( Iosb );
3516 }
3517
3518#else
3519
3520 try_return( Iosb );
3521
3522#endif
3523 }
3524
3525 //
3526 // Now check that we can continue based on the oplock state of the
3527 // file. If there are no open handles yet we don't need to do this
3528 // check; oplocks can only exist when there are handles.
3529 //
3530 // It is important that we modified the DesiredAccess in place so
3531 // that the Oplock check proceeds against any added access we had
3532 // to give the caller.
3533 //
3534
3535 if (Fcb->UncleanCount != 0) {
3536
3538 IrpContext->OriginatingIrp,
3539 IrpContext,
3541 FatPrePostIrp );
3542 }
3543
3544 //
3545 // if FsRtlCheckOplock returns STATUS_PENDING the IRP has been posted
3546 // to service an oplock break and we need to leave now.
3547 //
3548
3549 if (Iosb.Status == STATUS_PENDING) {
3550
3551 *OplockPostIrp = TRUE;
3553 }
3554
3555 //
3556 // If the caller wants atomic create-with-oplock semantics, tell
3557 // the oplock package. We haven't incremented the Fcb's UncleanCount
3558 // for this create yet, so add that in on the call.
3559 //
3560
3561 if (OpenRequiringOplock &&
3562 (Iosb.Status == STATUS_SUCCESS)) {
3563
3565 IrpContext->OriginatingIrp,
3566 (Fcb->UncleanCount + 1) );
3567 }
3568
3569 //
3570 // If we've encountered a failure we need to leave. FsRtlCheckOplock
3571 // will have returned STATUS_OPLOCK_BREAK_IN_PROGRESS if it initiated
3572 // and oplock break and the caller specified FILE_COMPLETE_IF_OPLOCKED
3573 // on the create call. That's an NT_SUCCESS code, so we need to keep
3574 // going.
3575 //
3576
3577 if ((Iosb.Status != STATUS_SUCCESS) &&
3579
3581 }
3582
3583 //
3584 // Set the flag indicating if Fast I/O is possible
3585 //
3586
3587 Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
3588
3589 //
3590 // If the user wants write access access to the file make sure there
3591 // is not a process mapping this file as an image. Any attempt to
3592 // delete the file will be stopped in fileinfo.c
3593 //
3594 // If the user wants to delete on close, we must check at this
3595 // point though.
3596 //
3597
3599
3600 Fcb->OpenCount += 1;
3601 DecrementFcbOpenCount = TRUE;
3602
3604 MmFlushForWrite )) {
3605
3608 try_return( Iosb );
3609 }
3610 }
3611
3612 //
3613 // If this is a non-cached open on a non-paging file, and there
3614 // are no open cached handles, but there is a still a data
3615 // section, attempt a flush and purge operation to avoid cache
3616 // coherency overhead later. We ignore any I/O errors from
3617 // the flush.
3618 //
3619 // We set the CREATE_IN_PROGRESS flag to prevent the Fcb from
3620 // going away out from underneath us.
3621 //
3622
3627
3629
3631
3632 //
3633 // Grab and release PagingIo to serialize ourselves with the lazy writer.
3634 // This will work to ensure that all IO has completed on the cached
3635 // data and we will succesfully tear away the cache section.
3636 //
3637
3638 ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
3639 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
3640
3642 NULL,
3643 0,
3644 FALSE );
3645
3647 }
3648
3649 //
3650 // Check if the user only wanted to open the file
3651 //
3652
3653 if ((CreateDisposition == FILE_OPEN) ||
3655
3656 DebugTrace(0, Dbg, "Doing open operation\n", 0);
3657
3658 //
3659 // If the caller has no Ea knowledge, we immediately check for
3660 // Need Ea's on the file.
3661 //
3662
3663 if (NoEaKnowledge && !FatIsFat32(Vcb)) {
3664
3666
3667 //
3668 // Get the dirent for the file and then check that the need
3669 // ea count is 0.
3670 //
3671
3672 FatGetDirentFromFcbOrDcb( IrpContext,
3673 Fcb,
3674 FALSE,
3675 &Dirent,
3676 &DirentBcb );
3677
3678 FatGetNeedEaCount( IrpContext,
3679 Vcb,
3680 Dirent,
3681 &NeedEaCount );
3682
3683 FatUnpinBcb( IrpContext, DirentBcb );
3684
3685 if (NeedEaCount != 0) {
3686
3687 Iosb.Status = STATUS_ACCESS_DENIED;
3688 try_return( Iosb );
3689 }
3690 }
3691
3692 //
3693 // Everything checks out okay, so setup the context and
3694 // section object pointers.
3695 //
3696
3699 Fcb,
3700 UnwindCcb = FatCreateCcb( IrpContext ));
3701
3702 FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
3703
3704 //
3705 // Fill in the information field, the status field is already
3706 // set.
3707 //
3708
3709 Iosb.Information = FILE_OPENED;
3710
3711 try_return( Iosb );
3712 }
3713
3714 //
3715 // Check if we are to supersede/overwrite the file, we can wait for
3716 // any I/O at this point
3717 //
3718
3722
3723 NTSTATUS OldStatus;
3724
3725 DebugTrace(0, Dbg, "Doing supersede/overwrite operation\n", 0);
3726
3727 //
3728 // We remember the previous status code because it may contain
3729 // information about the oplock status.
3730 //
3731
3732 OldStatus = Iosb.Status;
3733
3734 //
3735 // Determine the granted access for this operation now.
3736 //
3737
3738 if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
3739
3740 try_return( Iosb );
3741 }
3742
3743 //
3744 // And overwrite the file.
3745 //
3746
3747 Iosb = FatSupersedeOrOverwriteFile( IrpContext,
3748 FileObject,
3749 Fcb,
3751 EaBuffer,
3752 EaLength,
3755 NoEaKnowledge );
3756
3757 if (Iosb.Status == STATUS_SUCCESS) {
3758
3759 Iosb.Status = OldStatus;
3760 }
3761
3762 try_return( Iosb );
3763 }
3764
3765 //
3766 // If we ever get here then the I/O system gave us some bad input
3767 //
3768
3769#ifdef _MSC_VER
3770#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
3771#endif
3773
3774 try_exit: NOTHING;
3775
3776 //
3777 // Update the share access and counts if successful
3778 //
3779
3780 if ((Iosb.Status != STATUS_PENDING) && NT_SUCCESS(Iosb.Status)) {
3781
3782 //
3783 // Now, we may have added some access bits above to indicate the access
3784 // this caller would conflict with (as opposed to what they get) in order
3785 // to perform the overwrite/supersede. We need to make a call to that will
3786 // recalculate the bits in the fileobject to reflect the real access they
3787 // will get.
3788 //
3789
3790 if (AddedAccess) {
3791
3793
3794 ClearFlag( *DesiredAccess, AddedAccess );
3795
3796#ifdef _MSC_VER
3797#pragma prefast( suppress:28931, "it needs to be there for debug assert" );
3798#endif
3801 FileObject,
3802 &Fcb->ShareAccess,
3803 TRUE );
3804
3805 //
3806 // It must be the case that we are really asking for less access, so
3807 // any conflict must have been detected before this point.
3808 //
3809
3811
3812 } else {
3813
3815 }
3816
3817 UnwindShareAccess = TRUE;
3818
3819 //
3820 // In case this was set, clear it now.
3821 //
3822
3824
3825 Fcb->UncleanCount += 1;
3826 Fcb->OpenCount += 1;
3829 }
3830 Vcb->OpenFileCount += 1;
3831 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
3832
3833 {
3834 PCCB Ccb;
3835
3836 Ccb = (PCCB)FileObject->FsContext2;
3837
3838 //
3839 // Mark the DeleteOnClose bit if the operation was successful.
3840 //
3841
3842 if ( DeleteOnClose ) {
3843
3845 }
3846
3847 //
3848 // Mark the OpenedByShortName bit if the operation was successful.
3849 //
3850
3851 if ( FileNameOpenedDos ) {
3852
3854 }
3855
3856 //
3857 // Mark the ManageVolumeAccess bit if the privilege is held.
3858 //
3859
3860 if (FatCheckManageVolumeAccess( IrpContext,
3861 IrpSp->Parameters.Create.SecurityContext->AccessState,
3863 UserMode :
3864 IrpContext->OriginatingIrp->RequestorMode ))) {
3865
3867 }
3868 }
3869
3870
3871 }
3872
3873 } _SEH2_FINALLY {
3874
3875 DebugUnwind( FatOpenExistingFcb );
3876
3877 //
3878 // Unpin the Dirent Bcb if pinned.
3879 //
3880
3881 FatUnpinBcb( IrpContext, DirentBcb );
3882
3883 //
3884 // If this is an abnormal termination then undo our work
3885 //
3886
3888
3889 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
3890 if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); }
3891 }
3892
3893 if (DecrementFcbOpenCount) {
3894
3895 Fcb->OpenCount -= 1;
3896
3897 if (Fcb->OpenCount == 0) {
3899 FileObject->SectionObjectPointer = NULL;
3900 }
3901 FatDeleteFcb( IrpContext, &Fcb );
3902 FcbAcquired = FALSE;
3903 }
3904 }
3905
3906 if (FcbAcquired) {
3907
3908 FatReleaseFcb( IrpContext, Fcb );
3909 }
3910
3911 DebugTrace(-1, Dbg, "FatOpenExistingFcb -> Iosb.Status = %08lx\n", Iosb.Status);
3912 } _SEH2_END;
3913
3914 return Iosb;
3915}
3916
3917//
3918// Internal support routine
3919//
3920
3921_Requires_lock_held_(_Global_critical_region_)
3923FatOpenTargetDirectory (
3924 _In_ PIRP_CONTEXT IrpContext,
3929 _In_ BOOLEAN DoesNameExist,
3931 )
3932
3933/*++
3934
3935Routine Description:
3936
3937 This routine opens the target directory and replaces the name in the
3938 file object with the remaining name.
3939
3940Arguments:
3941
3942 FileObject - Supplies the File object
3943
3944 Dcb - Supplies an already existing dcb that we are going to open
3945
3946 DesiredAccess - Supplies the desired access of the caller
3947
3948 ShareAccess - Supplies the share access of the caller
3949
3950 DoesNameExist - Indicates if the file name already exists in the
3951 target directory.
3952
3953
3954Return Value:
3955
3956 IO_STATUS_BLOCK - Returns the completion status for the operation
3957
3958--*/
3959
3960{
3961 IO_STATUS_BLOCK Iosb = {0};
3962
3963 //
3964 // The following variables are for abnormal termination
3965 //
3966
3967 BOOLEAN UnwindShareAccess = FALSE;
3969 BOOLEAN DcbAcquired = FALSE;
3970
3971 PAGED_CODE();
3972
3973 DebugTrace(+1, Dbg, "FatOpenTargetDirectory...\n", 0);
3974
3975 //
3976 // Get the Dcb exlcusive. This is important as cleanup does not
3977 // acquire the Vcb.
3978 //
3979
3980 (VOID)FatAcquireExclusiveFcb( IrpContext, Dcb );
3981 DcbAcquired = TRUE;
3982
3983 _SEH2_TRY {
3984
3985 ULONG i;
3986
3987 //
3988 // If the Dcb is already opened by someone then we need
3989 // to check the share access
3990 //
3991
3992 if (Dcb->OpenCount > 0) {
3993
3996 FileObject,
3997 &Dcb->ShareAccess,
3998 TRUE ))) {
3999
4000 try_return( Iosb );
4001 }
4002
4003 } else {
4004
4007 FileObject,
4008 &Dcb->ShareAccess );
4009 }
4010
4011 UnwindShareAccess = TRUE;
4012
4013 //
4014 // Setup the context and section object pointers, and update
4015 // our reference counts
4016 //
4017
4020 Dcb,
4021 UnwindCcb = FatCreateCcb( IrpContext ));
4022
4023 Dcb->UncleanCount += 1;
4024 Dcb->OpenCount += 1;
4025 Dcb->Vcb->OpenFileCount += 1;
4026 if (IsFileObjectReadOnly(FileObject)) { Dcb->Vcb->ReadOnlyCount += 1; }
4027
4028 //
4029 // Update the name in the file object, by definition the remaining
4030 // part must be shorter than the original file name so we'll just
4031 // overwrite the file name.
4032 //
4033
4034 i = FileObject->FileName.Length/sizeof(WCHAR) - 1;
4035
4036 //
4037 // Get rid of a trailing backslash
4038 //
4039
4040 if (FileObject->FileName.Buffer[i] == L'\\') {
4041
4042 NT_ASSERT(i != 0);
4043
4044 FileObject->FileName.Length -= sizeof(WCHAR);
4045 i -= 1;
4046 }
4047
4048 //
4049 // Find the first non-backslash character. i will be its index.
4050 //
4051
4052 while (TRUE) {
4053
4054 if (FileObject->FileName.Buffer[i] == L'\\') {
4055
4056 i += 1;
4057 break;
4058 }
4059
4060 if (i == 0) {
4061 break;
4062 }
4063
4064 i--;
4065 }
4066
4067 if (i) {
4068
4069 FileObject->FileName.Length -= (USHORT)(i * sizeof(WCHAR));
4070
4071 RtlMoveMemory( &FileObject->FileName.Buffer[0],
4072 &FileObject->FileName.Buffer[i],
4073 FileObject->FileName.Length );
4074 }
4075
4076 //
4077 // And set our status to success
4078 //
4079
4080 Iosb.Status = STATUS_SUCCESS;
4081 Iosb.Information = (DoesNameExist ? FILE_EXISTS : FILE_DOES_NOT_EXIST);
4082
4083 if ( ( NT_SUCCESS(Iosb.Status) ) && ( DoesNameExist ) ) {
4084 PCCB Ccb;
4085
4086 Ccb = (PCCB)FileObject->FsContext2;
4087
4088 //
4089 // Mark the OpenedByShortName bit if the operation was successful.
4090 //
4091
4092 if ( FileNameOpenedDos ) {
4093
4095 }
4096 }
4097
4098 try_exit: NOTHING;
4099 } _SEH2_FINALLY {
4100
4101 DebugUnwind( FatOpenTargetDirectory );
4102
4103 //
4104 // If this is an abnormal termination then undo our work
4105 //
4106
4108
4109 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
4110 if (UnwindShareAccess) { IoRemoveShareAccess( FileObject, &Dcb->ShareAccess ); }
4111 }
4112
4113 if (DcbAcquired) {
4114
4115 FatReleaseFcb( IrpContext, Dcb );
4116 }
4117
4118 DebugTrace(-1, Dbg, "FatOpenTargetDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
4119 } _SEH2_END;
4120
4121 return Iosb;
4122}
4123
4124
4125
4126//
4127// Internal support routine
4128//
4130_Requires_lock_held_(_Global_critical_region_)
4132#ifdef _MSC_VER
4133#pragma warning(suppress:6101) // bug in PREFast means the _Success_ annotation is not correctly applied
4134#endif
4135FatOpenExistingDirectory (
4136 _In_ PIRP_CONTEXT IrpContext,
4153 )
4154
4155/*++
4156
4157Routine Description:
4158
4159 This routine opens the specified directory. The directory has not
4160 previously been opened.
4161
4162Arguments:
4163
4164 FileObject - Supplies the File object
4165
4166 Vcb - Supplies the Vcb denoting the volume containing the dcb
4167
4168 Dcb - Returns the newly-created DCB for the file.
4169
4170 ParentDcb - Supplies the parent directory containing the subdirectory
4171 to be opened
4172
4173 DirectoryName - Supplies the file name of the directory being opened.
4174
4175 Dirent - Supplies the dirent for the directory being opened
4176
4177 LfnByteOffset - Tells where the Lfn begins. If there is no Lfn
4178 this field is the same as DirentByteOffset.
4179
4180 DirentByteOffset - Supplies the Vbo of the dirent within its parent
4181 directory
4182
4183 Lfn - May supply a long name for the file.
4184
4185 DesiredAccess - Supplies the desired access of the caller
4186
4187 ShareAccess - Supplies the share access of the caller
4188
4189 CreateDisposition - Supplies the create disposition for this operation
4190
4191 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
4192 open if the file has NeedEa's.
4193
4194 DeleteOnClose - The caller wants the file gone when the handle is closed
4195
4196 OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
4197
4198Return Value:
4199
4200 IO_STATUS_BLOCK - Returns the completion status for the operation
4201
4202--*/
4203
4204{
4205 IO_STATUS_BLOCK Iosb = {0};
4206
4207 //
4208 // The following variables are for abnormal termination
4209 //
4210
4213
4215
4217#if (NTDDI_VERSION <= NTDDI_WIN7)
4219#endif
4221
4223
4224 DebugTrace(+1, Dbg, "FatOpenExistingDirectory...\n", 0);
4225
4227
4228 //
4229 // If the caller has no Ea knowledge, we immediately check for
4230 // Need Ea's on the file.
4231 //
4232
4233 if (NoEaKnowledge && !FatIsFat32(Vcb)) {
4234
4236
4237 FatGetNeedEaCount( IrpContext,
4238 Vcb,
4239 Dirent,
4240 &NeedEaCount );
4241
4242 if (NeedEaCount != 0) {
4243
4244 Iosb.Status = STATUS_ACCESS_DENIED;
4245 try_return( Iosb );
4246 }
4247 }
4248
4249 //
4250 // Check the create disposition and desired access
4251 //
4252
4253 if ((CreateDisposition != FILE_OPEN) &&
4255
4257 try_return( Iosb );
4258 }
4259
4260 if (!FatCheckFileAccess( IrpContext,
4261 Dirent->Attributes,
4262 DesiredAccess)) {
4263
4264 Iosb.Status = STATUS_ACCESS_DENIED;
4265 try_return( Iosb );
4266 }
4267
4268 //
4269 // Create a new dcb for the directory
4270 //
4271
4272 *Dcb = UnwindDcb = FatCreateDcb( IrpContext,
4273 Vcb,
4274 ParentDcb,
4277 Dirent,
4278 Lfn );
4279
4280#if (NTDDI_VERSION >= NTDDI_WIN8)
4281
4282 //
4283 // Let's make sure that if the caller provided an oplock key that it
4284 // gets stored in the file object.
4285 //
4286
4287 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(*Dcb),
4288 IrpContext->OriginatingIrp,
4290 NULL,
4291 NULL,
4292 NULL );
4293
4294 //
4295 // If the caller wants atomic create-with-oplock semantics, tell
4296 // the oplock package. We haven't incremented the Fcb's UncleanCount
4297 // for this create yet, so add that in on the call.
4298 //
4299
4301 (Iosb.Status == STATUS_SUCCESS)) {
4302
4304 IrpContext->OriginatingIrp,
4305 ((*Dcb)->UncleanCount + 1) );
4306 }
4307
4308 //
4309 // Get out if either of the above calls failed. Raise to trigger
4310 // cleanup of the new Dcb.
4311 //
4312
4313 if (Iosb.Status != STATUS_SUCCESS) {
4314
4315 NT_ASSERT( Iosb.Status != STATUS_PENDING );
4316
4317 FatRaiseStatus( IrpContext, Iosb.Status );
4318 }
4319#endif
4320
4321 //
4322 // Setup our share access
4323 //
4324
4327 FileObject,
4328 &(*Dcb)->ShareAccess );
4329
4330 //
4331 // Setup the context and section object pointers, and update
4332 // our reference counts
4333 //
4334
4337 (*Dcb),
4338 UnwindCcb = FatCreateCcb( IrpContext ));
4339
4340 (*Dcb)->UncleanCount += 1;
4341 (*Dcb)->OpenCount += 1;
4342 Vcb->OpenFileCount += 1;
4343 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
4344
4346
4347
4348 //
4349 // And set our status to success
4350 //
4351
4352 Iosb.Status = STATUS_SUCCESS;
4353 Iosb.Information = FILE_OPENED;
4354
4355 if ( NT_SUCCESS(Iosb.Status) ) {
4356 PCCB Ccb;
4357
4358 Ccb = (PCCB)FileObject->FsContext2;
4359
4360 //
4361 // Mark the OpenedByShortName bit if the operation was successful.
4362 //
4363
4364 if ( FileNameOpenedDos ) {
4365
4367 }
4368 }
4369
4370 try_exit: NOTHING;
4372
4373 DebugUnwind( FatOpenExistingDirectory );
4374
4375 //
4376 // If this is an abnormal termination then undo our work
4377 //
4378
4380
4381 if (CountsIncremented) {
4382
4383 (*Dcb)->UncleanCount -= 1;
4384 (*Dcb)->OpenCount -= 1;
4385 Vcb->OpenFileCount -= 1;
4386 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
4387 }
4388
4389 if (UnwindDcb != NULL) {
4391 FileObject->SectionObjectPointer = NULL;
4392 }
4393 FatDeleteFcb( IrpContext, &UnwindDcb );
4394 *Dcb = NULL;
4395 }
4396 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
4397 }
4398
4399 DebugTrace(-1, Dbg, "FatOpenExistingDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
4401
4402 return Iosb;
4403}
4404
4405
4406//
4407// Internal support routine
4408//
4409
4410_Requires_lock_held_(_Global_critical_region_)
4412FatOpenExistingFile (
4413 _In_ PIRP_CONTEXT IrpContext,
4422 _In_ PUNICODE_STRING OrigLfn,
4430 _In_ BOOLEAN IsPagingFile,
4435 )
4436
4437/*++
4438
4439Routine Description:
4440
4441 This routine opens the specified file. The file has not previously
4442 been opened.
4443
4444Arguments:
4445
4446 FileObject - Supplies the File object
4447
4448 Vcb - Supplies the Vcb denoting the volume containing the file
4449
4450 Fcb - Returns the newly-created FCB for the file.
4451
4452 ParentDcb - Supplies the parent directory containing the file to be
4453 opened
4454
4455 Dirent - Supplies the dirent for the file being opened
4456
4457 LfnByteOffset - Tells where the Lfn begins. If there is no Lfn
4458 this field is the same as DirentByteOffset.
4459
4460 DirentByteOffset - Supplies the Vbo of the dirent within its parent
4461 directory
4462
4463 Lfn - May supply a long name for the file.
4464
4465 DesiredAccess - Supplies the desired access of the caller
4466
4467 ShareAccess - Supplies the share access of the caller
4468
4469 AllocationSize - Supplies the initial allocation if the file is being
4470 superseded, overwritten, or created.
4471
4472 EaBuffer - Supplies the Ea set if the file is being superseded,
4473 overwritten, or created.
4474
4475 EaLength - Supplies the size, in byte, of the EaBuffer
4476
4477 FileAttributes - Supplies file attributes to use if the file is being
4478 superseded, overwritten, or created
4479
4480 CreateDisposition - Supplies the create disposition for this operation
4481
4482 IsPagingFile - Indicates if this is the paging file being opened.
4483
4484 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
4485 open if the file has NeedEa's.
4486
4487 DeleteOnClose - The caller wants the file gone when the handle is closed
4488
4489 OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
4490
4491 FileNameOpenedDos - The caller opened this file by hitting the 8.3 side
4492 of the Lfn/8.3 pair
4493
4494Return Value:
4495
4496 IO_STATUS_BLOCK - Returns the completion status for the operation
4497
4498--*/
4499
4500{
4501 IO_STATUS_BLOCK Iosb = {0};
4502
4503 ACCESS_MASK AddedAccess = 0;
4504
4505 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
4506
4507 //
4508 // The following variables are for abnormal termination
4509 //
4510
4511 PFCB UnwindFcb = NULL;
4514
4515
4516#if (NTDDI_VERSION < NTDDI_WIN7)
4518#endif
4519
4520 PAGED_CODE();
4521
4522 DebugTrace(+1, Dbg, "FatOpenExistingFile...\n", 0);
4523
4524 _SEH2_TRY {
4525
4526 //
4527 // Check if the user wanted to create the file or if access is
4528 // denied
4529 //
4530
4533 try_return( Iosb );
4534
4535 } else if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
4536
4537 SetFlag( AddedAccess,
4538 DELETE & ~(*DesiredAccess) );
4539
4541
4542 } else if (((CreateDisposition == FILE_OVERWRITE) ||
4543 (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
4544
4545 SetFlag( AddedAccess,
4547
4549 }
4550
4551 if (!FatCheckFileAccess( IrpContext,
4552 Dirent->Attributes,
4553 DesiredAccess)) {
4554
4555 Iosb.Status = STATUS_ACCESS_DENIED;
4556 try_return( Iosb );
4557 }
4558
4559
4560 //
4561 // Check for trying to delete a read only file.
4562 //
4563
4564 if (DeleteOnClose &&
4565 FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_READ_ONLY )) {
4566
4567 Iosb.Status = STATUS_CANNOT_DELETE;
4568 try_return( Iosb );
4569 }
4570
4571 //
4572 // IF we are asked to do an overwrite or supersede operation then
4573 // deny access for files where the file attributes for system and
4574 // hidden do not match
4575 //
4576
4580
4583
4586
4587 if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
4589
4590 DebugTrace(0, Dbg, "The hidden and/or system bits do not match\n", 0);
4591
4592 if ( !IsPagingFile ) {
4593
4594 Iosb.Status = STATUS_ACCESS_DENIED;
4595 try_return( Iosb );
4596 }
4597 }
4598
4599 //
4600 // If this media is write protected, don't even try the create.
4601 //
4602
4603 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
4604
4605 //
4606 // Set the real device for the pop-up info, and set the verify
4607 // bit in the device object, so that we will force a verify
4608 // in case the user put the correct media back in.
4609 //
4610
4611
4612 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
4613 Vcb->Vpb->RealDevice );
4614
4615 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
4616
4618 }
4619 }
4620
4621 //
4622 // Create a new Fcb for the file, and set the file size in
4623 // the fcb.
4624 //
4625
4626 *Fcb = UnwindFcb = FatCreateFcb( IrpContext,
4627 Vcb,
4628 ParentDcb,
4631 Dirent,
4632 Lfn,
4633 OrigLfn,
4634 IsPagingFile,
4635 FALSE );
4636
4637
4638 (*Fcb)->Header.ValidDataLength.LowPart = (*Fcb)->Header.FileSize.LowPart;
4639
4640 //
4641 // If this is a paging file, lookup the allocation size so that
4642 // the Mcb is always valid
4643 //
4644
4645 if (IsPagingFile) {
4646
4647 FatLookupFileAllocationSize( IrpContext, *Fcb );
4648 }
4649
4650#if (NTDDI_VERSION >= NTDDI_WIN7)
4651
4652 //
4653 // Let's make sure that if the caller provided an oplock key that it
4654 // gets stored in the file object.
4655 //
4656
4657 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(*Fcb),
4658 IrpContext->OriginatingIrp,
4660 NULL,
4661 NULL,
4662 NULL );
4663
4664 //
4665 // If the caller wants atomic create-with-oplock semantics, tell
4666 // the oplock package. We haven't incremented the Fcb's UncleanCount
4667 // for this create yet, so add that in on the call.
4668 //
4669
4670 if (OpenRequiringOplock &&
4671 (Iosb.Status == STATUS_SUCCESS)) {
4672
4674 IrpContext->OriginatingIrp,
4675 ((*Fcb)->UncleanCount + 1) );
4676 }
4677
4678 //
4679 // Get out if either of the above calls failed. Raise to trigger
4680 // cleanup of the new Fcb.
4681 //
4682
4683 if (Iosb.Status != STATUS_SUCCESS) {
4684
4685 NT_ASSERT( Iosb.Status != STATUS_PENDING );
4686
4687 FatRaiseStatus( IrpContext, Iosb.Status );
4688 }
4689#endif
4690
4691 //
4692 // Now case on whether we are to simply open, supersede, or
4693 // overwrite the file.
4694 //
4695
4696 switch (CreateDisposition) {
4697
4698 case FILE_OPEN:
4699 case FILE_OPEN_IF:
4700
4701 DebugTrace(0, Dbg, "Doing only an open operation\n", 0);
4702
4703 //
4704 // If the caller has no Ea knowledge, we immediately check for
4705 // Need Ea's on the file.
4706 //
4707
4708 if (NoEaKnowledge && !FatIsFat32(Vcb)) {
4709
4711
4712 FatGetNeedEaCount( IrpContext,
4713 Vcb,
4714 Dirent,
4715 &NeedEaCount );
4716
4717 if (NeedEaCount != 0) {
4718
4719 FatRaiseStatus( IrpContext, STATUS_ACCESS_DENIED );
4720 }
4721 }
4722
4723 //
4724 // Setup the context and section object pointers.
4725 //
4726
4729 *Fcb,
4730 UnwindCcb = FatCreateCcb( IrpContext ));
4731
4732 FileObject->SectionObjectPointer = &(*Fcb)->NonPaged->SectionObjectPointers;
4733
4734 Iosb.Status = STATUS_SUCCESS;
4735 Iosb.Information = FILE_OPENED;
4736 break;
4737
4738 case FILE_SUPERSEDE:
4739 case FILE_OVERWRITE:
4740 case FILE_OVERWRITE_IF:
4741
4742 DebugTrace(0, Dbg, "Doing supersede/overwrite operation\n", 0);
4743
4744 //
4745 // Determine the granted access for this operation now.
4746 //
4747
4748 if (!NT_SUCCESS( Iosb.Status = FatCheckSystemSecurityAccess( IrpContext ))) {
4749
4750 try_return( Iosb );
4751 }
4752
4753 Iosb = FatSupersedeOrOverwriteFile( IrpContext,
4754 FileObject,
4755 *Fcb,
4757 EaBuffer,
4758 EaLength,
4761 NoEaKnowledge );
4762 break;
4763
4764 default:
4765
4766 DebugTrace(0, Dbg, "Illegal Create Disposition\n", 0);
4767
4768#ifdef _MSC_VER
4769#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
4770#endif
4772 break;
4773 }
4774
4775 try_exit: NOTHING;
4776
4777 //
4778 // Setup our share access and counts if things were successful.
4779 //
4780
4781 if ((Iosb.Status != STATUS_PENDING) && NT_SUCCESS( Iosb.Status )) {
4782
4783 //
4784 // Remove any virtual access the caller needed to check against, but will
4785 // not really receive. Overwrite/supersede is a bit of a special case.
4786 //
4787
4788 ClearFlag( *DesiredAccess, AddedAccess );
4789
4792 FileObject,
4793 &(*Fcb)->ShareAccess );
4794
4795 (*Fcb)->UncleanCount += 1;
4796 (*Fcb)->OpenCount += 1;
4798 (*Fcb)->NonCachedUncleanCount += 1;
4799 }
4800 Vcb->OpenFileCount += 1;
4801 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
4802
4804 }
4805
4806 {
4807 PCCB Ccb;
4808
4809 Ccb = (PCCB)FileObject->FsContext2;
4810
4811 if ( NT_SUCCESS(Iosb.Status) ) {
4812
4813 //
4814 // Mark the DeleteOnClose bit if the operation was successful.
4815 //
4816
4817 if ( DeleteOnClose ) {
4818
4820 }
4821
4822 //
4823 // Mark the OpenedByShortName bit if the operation was successful.
4824 //
4825
4826 if ( FileNameOpenedDos ) {
4827
4829 }
4830
4831 //
4832 // Mark the ManageVolumeAccess bit if the privilege is held.
4833 //
4834
4835 if (FatCheckManageVolumeAccess( IrpContext,
4836 IrpSp->Parameters.Create.SecurityContext->AccessState,
4838 UserMode :
4839 IrpContext->OriginatingIrp->RequestorMode ))) {
4840
4842 }
4843
4844 }
4845 }
4846
4847
4848 } _SEH2_FINALLY {
4849
4850 DebugUnwind( FatOpenExistingFile );
4851
4852 //
4853 // If this is an abnormal termination then undo our work
4854 //
4855
4857
4858 if (CountsIncremented) {
4859 (*Fcb)->UncleanCount -= 1;
4860 (*Fcb)->OpenCount -= 1;
4862 (*Fcb)->NonCachedUncleanCount -= 1;
4863 }
4864 Vcb->OpenFileCount -= 1;
4865 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
4866 }
4867
4868 if (UnwindFcb != NULL) {
4870 FileObject->SectionObjectPointer = NULL;
4871 }
4872 FatDeleteFcb( IrpContext, &UnwindFcb );
4873 *Fcb = NULL;
4874 }
4875
4876 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
4877 }
4878
4879 DebugTrace(-1, Dbg, "FatOpenExistingFile -> Iosb.Status = %08lx\n", Iosb.Status);
4880 } _SEH2_END;
4881
4882 return Iosb;
4883}
4884
4885
4886//
4887// Internal support routine
4888//
4889
4890_Requires_lock_held_(_Global_critical_region_)
4892FatCreateNewDirectory (
4893 _In_ PIRP_CONTEXT IrpContext,
4908 )
4909
4910/*++
4911
4912Routine Description:
4913
4914 This routine creates a new directory. The directory has already been
4915 verified not to exist yet.
4916
4917Arguments:
4918
4919 FileObject - Supplies the file object for the newly created directory
4920
4921 Vcb - Supplies the Vcb denote the volume to contain the new directory
4922
4923 ParentDcb - Supplies the parent directory containg the newly created
4924 directory
4925
4926 OemName - Supplies the Oem name for the newly created directory. It may
4927 or maynot be 8.3 complient, but will be upcased.
4928
4929 UnicodeName - Supplies the Unicode name for the newly created directory.
4930 It may or maynot be 8.3 complient. This name contains the original
4931 case information.
4932
4933 DesiredAccess - Supplies the desired access of the caller
4934
4935 ShareAccess - Supplies the shared access of the caller
4936
4937 EaBuffer - Supplies the Ea set for the newly created directory
4938
4939 EaLength - Supplies the length, in bytes, of EaBuffer
4940
4941 FileAttributes - Supplies the file attributes for the newly created
4942 directory.
4943
4944 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
4945 open if the file has NeedEa's.
4946
4947 DeleteOnClose - The caller wants the file gone when the handle is closed
4948
4949 OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
4950
4951Return Value:
4952
4953 IO_STATUS_BLOCK - Returns the completion status for the operation
4954
4955--*/
4956
4957{
4959
4960 PDCB Dcb = NULL;
4961 PCCB Ccb = NULL;
4962
4964 PBCB DirentBcb = NULL;
4967
4968 PDIRENT ShortDirent;
4969 ULONG ShortDirentByteOffset;
4970
4972
4976
4977 ULONG BytesInFirstPage = 0;
4978 ULONG DirentsInFirstPage = 0;
4979 PDIRENT FirstPageDirent = 0;
4980
4981 PBCB SecondPageBcb = NULL;
4982 ULONG SecondPageOffset;
4983 PDIRENT SecondPageDirent = NULL;
4984
4985 BOOLEAN DirentFromPool = FALSE;
4986
4987
4989 UCHAR ShortNameBuffer[12];
4990
4991#if (NTDDI_VERSION <= NTDDI_WIN7)
4993#endif
4994
4996
4997 PAGED_CODE();
4998
4999 DebugTrace(+1, Dbg, "FatCreateNewDirectory...\n", 0);
5000
5001 ShortName.Length = 0;
5002 ShortName.MaximumLength = 12;
5003 ShortName.Buffer = (PCHAR)&ShortNameBuffer[0];
5004
5005 EaHandle = 0;
5006
5007 //
5008 // We fail this operation if the caller doesn't understand Ea's.
5009 //
5010
5011 if (NoEaKnowledge
5012 && EaLength > 0) {
5013
5014 Iosb.Status = STATUS_ACCESS_DENIED;
5015
5016 DebugTrace(-1, Dbg, "FatCreateNewDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
5017 return Iosb;
5018 }
5019
5020 //
5021 // DeleteOnClose and ReadOnly are not compatible.
5022 //
5023
5025
5026 Iosb.Status = STATUS_CANNOT_DELETE;
5027 return Iosb;
5028 }
5029
5030 // Now get the names that we will be using.
5031 //
5032
5033 FatSelectNames( IrpContext,
5034 ParentDcb,
5035 OemName,
5037 &ShortName,
5038 NULL,
5041 &CreateLfn );
5042
5043 //
5044 // If we are not in Chicago mode, ignore the magic bits.
5045 //
5046
5047 if (!FatData.ChicagoMode) {
5048
5051 CreateLfn = FALSE;
5052 }
5053
5054 //
5055 // Create/allocate a new dirent
5056 //
5057
5059
5060 DirentByteOffset = FatCreateNewDirent( IrpContext,
5061 ParentDcb,
5063 FALSE );
5064 _SEH2_TRY {
5065
5066 FatPrepareWriteDirectoryFile( IrpContext,
5067 ParentDcb,
5069 sizeof(DIRENT),
5070 &DirentBcb,
5071#ifndef __REACTOS__
5072 &Dirent,
5073#else
5074 (PVOID *)&Dirent,
5075#endif
5076 FALSE,
5077 TRUE,
5078 &Iosb.Status );
5079
5080 NT_ASSERT( NT_SUCCESS( Iosb.Status ) && DirentBcb && Dirent );
5081
5082 //
5083 // Deal with the special case of an LFN + Dirent structure crossing
5084 // a page boundry.
5085 //
5086
5087 if ((DirentByteOffset / PAGE_SIZE) !=
5088 ((DirentByteOffset + (DirentsNeeded - 1) * sizeof(DIRENT)) / PAGE_SIZE)) {
5089
5090 SecondPageBcb;
5091 SecondPageOffset;
5092 SecondPageDirent;
5093
5094 SecondPageOffset = (DirentByteOffset & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
5095
5096 BytesInFirstPage = SecondPageOffset - DirentByteOffset;
5097
5098 DirentsInFirstPage = BytesInFirstPage / sizeof(DIRENT);
5099
5100 FatPrepareWriteDirectoryFile( IrpContext,
5101 ParentDcb,
5102 SecondPageOffset,
5103 sizeof(DIRENT),
5104 &SecondPageBcb,
5105#ifndef __REACTOS__
5106 &SecondPageDirent,
5107#else
5108 (PVOID *)&SecondPageDirent,
5109#endif
5110 FALSE,
5111 TRUE,
5112 &Iosb.Status );
5113
5114 NT_ASSERT( NT_SUCCESS( Iosb.Status ) && SecondPageBcb && SecondPageDirent );
5115
5116 FirstPageDirent = Dirent;
5117
5119 DirentsNeeded * sizeof(DIRENT),
5120 TAG_DIRENT );
5121
5122 DirentFromPool = TRUE;
5123 }
5124
5125 //
5126 // Bump up Dirent and DirentByteOffset
5127 //
5128
5129 ShortDirent = Dirent + DirentsNeeded - 1;
5130 ShortDirentByteOffset = DirentByteOffset +
5131 (DirentsNeeded - 1) * sizeof(DIRENT);
5132
5133 NT_ASSERT( NT_SUCCESS( Iosb.Status ));
5134
5135
5136 //
5137 // Fill in the fields of the dirent.
5138 //
5139
5140 FatConstructDirent( IrpContext,
5141 ShortDirent,
5142 &ShortName,
5147 TRUE,
5148 NULL );
5149
5150 //
5151 // If the dirent crossed pages, we have to do some real gross stuff.
5152 //
5153
5154 if (DirentFromPool) {
5155
5156 RtlCopyMemory( FirstPageDirent, Dirent, BytesInFirstPage );
5157
5158 RtlCopyMemory( SecondPageDirent,
5159 Dirent + DirentsInFirstPage,
5160 DirentsNeeded*sizeof(DIRENT) - BytesInFirstPage );
5161
5162 ShortDirent = SecondPageDirent + (DirentsNeeded - DirentsInFirstPage) - 1;
5163 }
5164
5165 //
5166 // Create a new dcb for the directory.
5167 //
5168
5169 Dcb = FatCreateDcb( IrpContext,
5170 Vcb,
5171 ParentDcb,
5173 ShortDirentByteOffset,
5174 ShortDirent,
5176
5177#if (NTDDI_VERSION >= NTDDI_WIN8)
5178 //
5179 // The next three FsRtl calls are for oplock work. We deliberately
5180 // do these here so that if either call fails we will be able to
5181 // clean up without adding a bunch of code to unwind counts, fix
5182 // the file object, etc.
5183 //
5184
5185 //
5186 // Let's make sure that if the caller provided an oplock key that it
5187 // gets stored in the file object.
5188 //
5189
5190 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Dcb),
5191 IrpContext->OriginatingIrp,
5193 NULL,
5194 NULL,
5195 NULL );
5196
5197 //
5198 // If the caller wants atomic create-with-oplock semantics, tell
5199 // the oplock package. We haven't incremented the Dcb's UncleanCount
5200 // for this create yet, so add that in on the call.
5201 //
5202
5203 if (OpenRequiringOplock &&
5204 (Iosb.Status == STATUS_SUCCESS)) {
5205
5207 IrpContext->OriginatingIrp,
5208 (Dcb->UncleanCount + 1) );
5209 }
5210
5211 //
5212 // Break parent directory oplock. Directory oplock breaks are always
5213 // advisory, so we will never block/get STATUS_PENDING here. On the
5214 // off chance this fails with INSUFFICIENT_RESOURCES we do it here
5215 // where we can still tolerate a failure.
5216 //
5217
5218 if (Iosb.Status == STATUS_SUCCESS) {
5219
5220 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb),
5221 IrpContext->OriginatingIrp,
5222 OPLOCK_FLAG_PARENT_OBJECT,
5223 NULL,
5224 NULL,
5225 NULL );
5226 }
5227
5228 //
5229 // Get out if any of the oplock calls failed.
5230 //
5231
5232 if (Iosb.Status != STATUS_SUCCESS) {
5233
5234 FatRaiseStatus( IrpContext, Iosb.Status );
5235 }
5236#endif
5237
5238 //
5239 // Tentatively add the new Ea's,
5240 //
5241
5242 if (EaLength > 0) {
5243
5244 //
5245 // This returns false if we are trying to create a file
5246 // with Need Ea's and don't understand EA's.
5247 //
5248
5249 FatCreateEa( IrpContext,
5250 Dcb->Vcb,
5251 (PUCHAR) EaBuffer,
5252 EaLength,
5253 &Dcb->ShortName.Name.Oem,
5254 &EaHandle );
5255 }
5256
5257 if (!FatIsFat32(Dcb->Vcb)) {
5258
5259 ShortDirent->ExtendedAttributes = EaHandle;
5260 }
5261
5262 //
5263 // After this point we cannot just simply mark the dirent deleted,
5264 // we have to deal with the directory file object.
5265 //
5266
5267 //
5268 // Make the dirent into a directory. Note that even if this call
5269 // raises because of disk space, the diectory file object has been
5270 // created.
5271 //
5272
5273 FatInitializeDirectoryDirent( IrpContext, Dcb, ShortDirent );
5274
5275 //
5276 // Setup the context and section object pointers, and update
5277 // our reference counts. Note that this call cannot fail.
5278 //
5279
5282 Dcb,
5283 Ccb = FatCreateCcb( IrpContext ) );
5284
5285 //
5286 // Initialize the LongFileName if it has not already been set, so that
5287 // FatNotify below won't have to. If there are filesystem filters
5288 // attached to FAT, the LongFileName could have gotten set if the
5289 // filter queried for name information on this file object while
5290 // watching the IO needed in FatInitializeDirectoryDirent.
5291 //
5292
5293 if (Dcb->FullFileName.Buffer == NULL) {
5294
5295 FatSetFullNameInFcb( IrpContext, Dcb, UnicodeName );
5296 }
5297
5298 //
5299 // We call the notify package to report that the
5300 // we added a file.
5301 //
5302
5303 FatNotifyReportChange( IrpContext,
5304 Vcb,
5305 Dcb,
5308
5309 //
5310 // Setup our share access
5311 //
5312
5315 FileObject,
5316 &Dcb->ShareAccess );
5317
5318
5319 //
5320 // From this point on, nothing can raise.
5321 //
5322
5323 Dcb->UncleanCount += 1;
5324 Dcb->OpenCount += 1;
5325 Vcb->OpenFileCount += 1;
5326 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
5327
5328 if (DeleteOnClose) {
5329
5331 }
5332
5333 //
5334 // And set our return status
5335 //
5336
5337 Iosb.Status = STATUS_SUCCESS;
5338 Iosb.Information = FILE_CREATED;
5339
5341
5342 //
5343 // We'll catch all exceptions and handle them below.
5344 //
5345
5346 Iosb.Status = IrpContext->ExceptionStatus;
5347 } _SEH2_END;
5348
5349 //
5350 // If we failed then undo our work.
5351 //
5352
5353 if (!NT_SUCCESS( Iosb.Status )) {
5354
5355 //
5356 // We always have to delete the Ccb if we created one.
5357 //
5358
5359 if ( Ccb != NULL ) {
5360
5361 FatDeleteCcb( IrpContext, &Ccb );
5362 }
5363
5364#ifdef _MSC_VER
5365#pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but DCB can be NULL depending on where we raise" )
5366#endif
5367 if ( Dcb == NULL) {
5368
5369 NT_ASSERT( (ParentDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
5370 RtlAreBitsSet( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
5371 DirentByteOffset / sizeof(DIRENT),
5372 DirentsNeeded ) );
5373
5374 RtlClearBits( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
5375 DirentByteOffset / sizeof(DIRENT),
5376 DirentsNeeded );
5377
5378 //
5379 // Mark the dirents deleted. The codes is complex because of
5380 // dealing with an LFN than crosses a page boundry.
5381 //
5382
5383 if (Dirent != NULL) {
5384
5385 ULONG i;
5386
5387 //
5388 // We failed before creating a directory file object.
5389 // We can just mark the dirent deleted and exit.
5390 //
5391
5392 for (i = 0; i < DirentsNeeded; i++) {
5393
5394 if (DirentFromPool == FALSE) {
5395
5396 //
5397 // Simple case.
5398 //
5399
5401
5402 } else {
5403
5404 //
5405 // If the second CcPreparePinWrite failed, we have
5406 // to stop early.
5407 //
5408
5409 if ((SecondPageBcb == NULL) &&
5410 (i == DirentsInFirstPage)) {
5411
5412 break;
5413 }
5414
5415 //
5416 // Now conditionally update either page.
5417 //
5418
5419 if (i < DirentsInFirstPage) {
5420
5421 FirstPageDirent[i].FileName[0] = FAT_DIRENT_DELETED;
5422
5423 } else {
5424
5425 SecondPageDirent[i - DirentsInFirstPage].FileName[0] = FAT_DIRENT_DELETED;
5426 }
5427 }
5428 }
5429 }
5430 }
5431 }
5432
5433 //
5434 // Just drop the Bcbs we have in the parent right now so if we
5435 // failed to create the directory and we take the path to rip apart
5436 // the partially created child, when we sync-uninit we won't cause
5437 // a lazy writer processing the parent to block on us. This would
5438 // consume one of the lazy writers, one of which must be running free
5439 // in order for us to come back from the sync-uninit.
5440 //
5441 // Neat, huh?
5442 //
5443 // Granted, the delete dirent below will be marginally less efficient
5444 // since the Bcb may be reclaimed by the time it executes. Life is
5445 // tough.
5446 //
5447
5448 FatUnpinBcb( IrpContext, DirentBcb );
5449 FatUnpinBcb( IrpContext, SecondPageBcb );
5450
5451 if (DirentFromPool) {
5452
5453 ExFreePool( Dirent );
5454 }
5455
5456 if (!NT_SUCCESS( Iosb.Status )) {
5457
5458#ifdef _MSC_VER
5459#pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but DCB can be NULL depending on where we raise" )
5460#endif
5461 if (Dcb != NULL) {
5462
5463 //
5464 // We have created the Dcb. If an error occurred while
5465 // creating the Ea's, there will be no directory file
5466 // object.
5467 //
5468
5469 PFILE_OBJECT DirectoryFileObject;
5470
5471 DirectoryFileObject = Dcb->Specific.Dcb.DirectoryFile;
5472
5473 //
5474 // Knock down all of the repinned data so we can begin to destroy
5475 // this failed child. We don't care about any raising here - we're
5476 // already got a fire going.
5477 //
5478 // Note that if we failed to do this, the repinned initial pieces
5479 // of the child would cause the sync-uninit to block forever.
5480 //
5481 // A previous spin on this fix had us not make the ./.. creation
5482 // "reversible" (bad term) and thus avoid having the Bcb still
5483 // outstanding. This wound up causing very bad things to happen
5484 // on DMF floppies when we tried to do a similar yank-down in the
5485 // create path - we want the purge it does to make sure we never
5486 // try to write the bytes out ... it is just a lot cleaner to
5487 // unpinrepin. I'll leave the reversible logic in place if it ever
5488 // proves useful.
5489 //
5490
5491 //
5492 // There is a possibility that this may be a generally good idea
5493 // for "live" finally clauses - set in ExceptionFilter, clear in
5494 // ProcessException. Think about this.
5495 //
5496
5497 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE );
5498 FatUnpinRepinnedBcbs( IrpContext );
5499 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE );
5500
5501 if (Dcb->FirstClusterOfFile != 0) {
5502
5503 _SEH2_TRY {
5504
5505 Dcb->Header.FileSize.LowPart = 0;
5506
5507 CcSetFileSizes( Dcb->Specific.Dcb.DirectoryFile,
5508 (PCC_FILE_SIZES)&Dcb->Header.AllocationSize );
5509
5510 //
5511 // Now zap the allocation backing it.
5512 //
5513
5514 FatTruncateFileAllocation( IrpContext, Dcb, 0 );
5515
5517
5518 //
5519 // We catch all exceptions that Fat catches, but don't do
5520 // anything with them.
5521 //
5522 } _SEH2_END;
5523 }
5524
5525 if (DirectoryFileObject != NULL) {
5526
5527 FatSyncUninitializeCacheMap( IrpContext,
5528 DirectoryFileObject );
5529 }
5530
5531
5532 _SEH2_TRY {
5533
5534 //
5535 // Remove the directory entry we made in the parent Dcb.
5536 //
5537
5538 FatDeleteDirent( IrpContext, Dcb, NULL, TRUE );
5539
5540 //
5541 // FatDeleteDirent can pin and dirty BCBs, so lets unrepin again.
5542 //
5543
5544 FatUnpinRepinnedBcbs( IrpContext );
5545
5547
5548 //
5549 // We catch all exceptions that Fat catches, but don't do
5550 // anything with them.
5551 //
5552 } _SEH2_END;
5553
5554 //
5555 // Finaly, dereference the directory file object. This will
5556 // cause a close Irp to be processed, blowing away the Fcb.
5557 //
5558
5559 if (DirectoryFileObject != NULL) {
5560
5561 //
5562 // Dereference the file object for this DCB. The DCB will
5563 // go away when this file object is closed.
5564 //
5565
5566 Dcb->Specific.Dcb.DirectoryFile = NULL;
5567 ObDereferenceObject( DirectoryFileObject );
5568
5569 } else {
5570
5571 //
5572 // This was also a PDK fix. If the stream file exists, this would
5573 // be done during the dereference file object operation. Otherwise
5574 // we have to remove the Dcb and check if we should remove the parent.
5575 // For now we will just leave the parent lying around.
5576 //
5577
5578#ifdef _MSC_VER
5579#pragma prefast( suppress: 28924, "prefast thinks this test is redundant, but FileObject can be NULL depending on where we raise" )
5580#endif
5582 FileObject->SectionObjectPointer = NULL;
5583 }
5584 FatDeleteFcb( IrpContext, &Dcb );
5585 }
5586 }
5587
5588 DebugTrace(-1, Dbg, "FatCreateNewDirectory -> Iosb.Status = %08lx\n", Iosb.Status);
5589
5590 FatRaiseStatus( IrpContext, Iosb.Status );
5591 }
5592
5595
5596 return Iosb;
5597}
5598
5599
5600//
5601// Internal support routine
5602//
5603
5604_Requires_lock_held_(_Global_critical_region_)
5606FatCreateNewFile (
5607 _In_ PIRP_CONTEXT IrpContext,
5620 _In_ PUNICODE_STRING LfnBuffer,
5621 _In_ BOOLEAN IsPagingFile,
5625 _In_ BOOLEAN TemporaryFile
5626 )
5627
5628/*++
5629
5630Routine Description:
5631
5632 This routine creates a new file. The file has already been verified
5633 not to exist yet.
5634
5635Arguments:
5636
5637 FileObject - Supplies the file object for the newly created file
5638
5639 Vcb - Supplies the Vcb denote the volume to contain the new file
5640
5641 ParentDcb - Supplies the parent directory containg the newly created
5642 File
5643
5644 OemName - Supplies the Oem name for the newly created file. It may
5645 or maynot be 8.3 complient, but will be upcased.
5646
5647 UnicodeName - Supplies the Unicode name for the newly created file.
5648 It may or maynot be 8.3 complient. This name contains the original
5649 case information.
5650
5651 DesiredAccess - Supplies the desired access of the caller
5652
5653 ShareAccess - Supplies the shared access of the caller
5654
5655 AllocationSize - Supplies the initial allocation size for the file
5656
5657 EaBuffer - Supplies the Ea set for the newly created file
5658
5659 EaLength - Supplies the length, in bytes, of EaBuffer
5660
5661 FileAttributes - Supplies the file attributes for the newly created
5662 file
5663
5664 LfnBuffer - A MAX_LFN sized buffer for directory searching
5665
5666 IsPagingFile - Indicates if this is the paging file being created
5667
5668 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
5669 open if the file has NeedEa's.
5670
5671 DeleteOnClose - The caller wants the file gone when the handle is closed
5672
5673 OpenRequiringOplock - The caller provided the FILE_OPEN_REQUIRING_OPLOCK option.
5674
5675 TemporaryFile - Signals the lazywriter to not write dirty data unless
5676 absolutely has to.
5677
5678
5679Return Value:
5680
5681 IO_STATUS_BLOCK - Returns the completion status for the operation
5682
5683--*/
5684
5685{
5686 IO_STATUS_BLOCK Iosb = {0};
5687
5688 PFCB Fcb = NULL;
5689
5691 PBCB DirentBcb = NULL;
5694
5695 PDIRENT ShortDirent;
5696 ULONG ShortDirentByteOffset;
5697
5699
5703
5704 ULONG BytesInFirstPage = 0;
5705 ULONG DirentsInFirstPage = 0;
5706 PDIRENT FirstPageDirent = NULL;
5707
5708 PBCB SecondPageBcb = NULL;
5709 ULONG SecondPageOffset;
5710 PDIRENT SecondPageDirent = NULL;
5711
5712 BOOLEAN DirentFromPool = FALSE;
5713
5715 UCHAR ShortNameBuffer[12];
5716
5717 UNICODE_STRING UniTunneledShortName;
5718 WCHAR UniTunneledShortNameBuffer[12];
5719 UNICODE_STRING UniTunneledLongName;
5720 WCHAR UniTunneledLongNameBuffer[26];
5721 LARGE_INTEGER TunneledCreationTime;
5722 ULONG TunneledDataSize;
5723 BOOLEAN HaveTunneledInformation;
5724 BOOLEAN UsingTunneledLfn = FALSE;
5725
5726 PUNICODE_STRING RealUnicodeName;
5727
5728
5729 //
5730 // The following variables are for abnormal termination
5731 //
5732
5733 PDIRENT UnwindDirent = NULL;
5734 PFCB UnwindFcb = NULL;
5735 BOOLEAN UnwindAllocation = FALSE;
5738
5739 ULONG LocalAbnormalTermination = FALSE;
5740
5741#if (NTDDI_VERSION < NTDDI_WIN7)
5743#endif
5744
5745 PAGED_CODE();
5746
5747 DebugTrace(+1, Dbg, "FatCreateNewFile...\n", 0);
5748
5749 ShortName.Length = 0;
5750 ShortName.MaximumLength = sizeof(ShortNameBuffer);
5751 ShortName.Buffer = (PCHAR)&ShortNameBuffer[0];
5752
5753 UniTunneledShortName.Length = 0;
5754 UniTunneledShortName.MaximumLength = sizeof(UniTunneledShortNameBuffer);
5755 UniTunneledShortName.Buffer = &UniTunneledShortNameBuffer[0];
5756
5757 UniTunneledLongName.Length = 0;
5758 UniTunneledLongName.MaximumLength = sizeof(UniTunneledLongNameBuffer);
5759 UniTunneledLongName.Buffer = &UniTunneledLongNameBuffer[0];
5760
5761 EaHandle = 0;
5762
5763 //
5764 // We fail this operation if the caller doesn't understand Ea's.
5765 //
5766
5767 if (NoEaKnowledge
5768 && EaLength > 0) {
5769
5770 Iosb.Status = STATUS_ACCESS_DENIED;
5771
5772 DebugTrace(-1, Dbg, "FatCreateNewFile -> Iosb.Status = %08lx\n", Iosb.Status);
5773 return Iosb;
5774 }
5775
5776 //
5777 // DeleteOnClose and ReadOnly are not compatible.
5778 //
5779
5781
5782 Iosb.Status = STATUS_CANNOT_DELETE;
5783 return Iosb;
5784 }
5785
5786 //
5787 // Look in the tunnel cache for names and timestamps to restore
5788 //
5789
5790 TunneledDataSize = sizeof(LARGE_INTEGER);
5791 HaveTunneledInformation = FsRtlFindInTunnelCache( &Vcb->Tunnel,
5794 &UniTunneledShortName,
5795 &UniTunneledLongName,
5796 &TunneledDataSize,
5797 &TunneledCreationTime );
5798 NT_ASSERT(TunneledDataSize == sizeof(LARGE_INTEGER));
5799
5800 //
5801 // Now get the names that we will be using.
5802 //
5803
5804 FatSelectNames( IrpContext,
5805 ParentDcb,
5806 OemName,
5808 &ShortName,
5809 (HaveTunneledInformation? &UniTunneledShortName : NULL),
5812 &CreateLfn );
5813
5814 //
5815 // If we are not in Chicago mode, ignore the magic bits.
5816 //
5817
5818 RealUnicodeName = UnicodeName;
5819
5820 if (!FatData.ChicagoMode) {
5821
5824 CreateLfn = FALSE;
5825
5826 } else {
5827
5828 //
5829 // If the Unicode name was legal for a short name and we got
5830 // a tunneling hit which had a long name associated which is
5831 // avaliable for use, use it.
5832 //
5833
5834 if (!CreateLfn &&
5835 UniTunneledLongName.Length &&
5836 !FatLfnDirentExists(IrpContext, ParentDcb, &UniTunneledLongName, LfnBuffer)) {
5837
5838 UsingTunneledLfn = TRUE;
5839 CreateLfn = TRUE;
5840
5841 RealUnicodeName = &UniTunneledLongName;
5842
5843 //
5844 // Short names are always upcase if an LFN exists
5845 //
5846
5849 }
5850 }
5851
5852
5853 //
5854 // Create/allocate a new dirent
5855 //
5856
5857 DirentsNeeded = CreateLfn ? FAT_LFN_DIRENTS_NEEDED(RealUnicodeName) + 1 : 1;
5858
5859 DirentByteOffset = FatCreateNewDirent( IrpContext,
5860 ParentDcb,
5862 FALSE );
5863
5864 _SEH2_TRY {
5865
5866 FatPrepareWriteDirectoryFile( IrpContext,
5867 ParentDcb,
5869 sizeof(DIRENT),
5870 &DirentBcb,
5871#ifndef __REACTOS__
5872 &Dirent,
5873#else
5874 (PVOID *)&Dirent,
5875#endif
5876 FALSE,
5877 TRUE,
5878 &Iosb.Status );
5879
5880 NT_ASSERT( NT_SUCCESS( Iosb.Status ) );
5881
5882 UnwindDirent = Dirent;
5883
5884 //
5885 // Deal with the special case of an LFN + Dirent structure crossing
5886 // a page boundry.
5887 //
5888
5889 if ((DirentByteOffset / PAGE_SIZE) !=
5890 ((DirentByteOffset + (DirentsNeeded - 1) * sizeof(DIRENT)) / PAGE_SIZE)) {
5891
5892 SecondPageBcb;
5893 SecondPageOffset;
5894 SecondPageDirent;
5895
5896 SecondPageOffset = (DirentByteOffset & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
5897
5898 BytesInFirstPage = SecondPageOffset - DirentByteOffset;
5899
5900 DirentsInFirstPage = BytesInFirstPage / sizeof(DIRENT);
5901
5902 FatPrepareWriteDirectoryFile( IrpContext,
5903 ParentDcb,
5904 SecondPageOffset,
5905 sizeof(DIRENT),
5906 &SecondPageBcb,
5907#ifndef __REACTOS__
5908 &SecondPageDirent,
5909#else
5910 (PVOID *)&SecondPageDirent,
5911#endif
5912 FALSE,
5913 TRUE,
5914 &Iosb.Status );
5915
5916 NT_ASSERT( NT_SUCCESS( Iosb.Status ) );
5917
5918 FirstPageDirent = Dirent;
5919
5921 DirentsNeeded * sizeof(DIRENT),
5922 TAG_DIRENT );
5923
5924 DirentFromPool = TRUE;
5925 }
5926
5927 //
5928 // Bump up Dirent and DirentByteOffset
5929 //
5930
5931 ShortDirent = Dirent + DirentsNeeded - 1;
5932 ShortDirentByteOffset = DirentByteOffset +
5933 (DirentsNeeded - 1) * sizeof(DIRENT);
5934
5935 NT_ASSERT( NT_SUCCESS( Iosb.Status ));
5936
5937
5938 //
5939 // Fill in the fields of the dirent.
5940 //
5941
5942 FatConstructDirent( IrpContext,
5943 ShortDirent,
5944 &ShortName,
5947 CreateLfn ? RealUnicodeName : NULL,
5949 TRUE,
5950 (HaveTunneledInformation ? &TunneledCreationTime : NULL) );
5951
5952 //
5953 // If the dirent crossed pages, we have to do some real gross stuff.
5954 //
5955
5956 if (DirentFromPool) {
5957
5958 RtlCopyMemory( FirstPageDirent, Dirent, BytesInFirstPage );
5959
5960 RtlCopyMemory( SecondPageDirent,
5961 Dirent + DirentsInFirstPage,
5962 DirentsNeeded*sizeof(DIRENT) - BytesInFirstPage );
5963
5964 ShortDirent = SecondPageDirent + (DirentsNeeded - DirentsInFirstPage) - 1;
5965 }
5966
5967 //
5968 // Create a new Fcb for the file. Once the Fcb is created we
5969 // will not need to unwind dirent because delete dirent will
5970 // now do the work.
5971 //
5972
5973 Fcb = UnwindFcb = FatCreateFcb( IrpContext,
5974 Vcb,
5975 ParentDcb,
5977 ShortDirentByteOffset,
5978 ShortDirent,
5979 CreateLfn ? RealUnicodeName : NULL,
5980 CreateLfn ? RealUnicodeName : NULL,
5981 IsPagingFile,
5982 FALSE );
5983 UnwindDirent = NULL;
5984
5985#if (NTDDI_VERSION >= NTDDI_WIN7)
5986 //
5987 // The next three FsRtl calls are for oplock work. We deliberately
5988 // do these here so that if either call fails we will be able to
5989 // clean up without adding a bunch of code to unwind counts, fix
5990 // the file object, etc.
5991 //
5992
5993 //
5994 // Let's make sure that if the caller provided an oplock key that it
5995 // gets stored in the file object.
5996 //
5997
5998 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
5999 IrpContext->OriginatingIrp,
6001 NULL,
6002 NULL,
6003 NULL );
6004
6005 //
6006 // If the caller wants atomic create-with-oplock semantics, tell
6007 // the oplock package. We haven't incremented the Fcb's UncleanCount
6008 // for this create yet, so add that in on the call.
6009 //
6010
6011 if (OpenRequiringOplock &&
6012 (Iosb.Status == STATUS_SUCCESS)) {
6013
6015 IrpContext->OriginatingIrp,
6016 (Fcb->UncleanCount + 1) );
6017 }
6018#endif
6019
6020#if (NTDDI_VERSION >= NTDDI_WIN8)
6021 //
6022 // Break parent directory oplock. Directory oplock breaks are always
6023 // advisory, so we will never block/get STATUS_PENDING here. On the
6024 // off chance this fails with INSUFFICIENT_RESOURCES we do it here
6025 // where we can still tolerate a failure.
6026 //
6027
6028 if (Iosb.Status == STATUS_SUCCESS) {
6029
6030 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(ParentDcb),
6031 IrpContext->OriginatingIrp,
6032 OPLOCK_FLAG_PARENT_OBJECT,
6033 NULL,
6034 NULL,
6035 NULL );
6036 }
6037
6038 //
6039 // Get out if any of the oplock calls failed. We raise to provoke
6040 // abnormal termination and ensure that the newly-created Fcb gets
6041 // deleted.
6042 //
6043
6044 if (Iosb.Status != STATUS_SUCCESS) {
6045
6046 FatRaiseStatus( IrpContext, Iosb.Status );
6047 }
6048#endif
6049
6050 //
6051 // If this is a temporary file, note it in the FcbState
6052 //
6053
6054 if (TemporaryFile) {
6055
6057 }
6058
6059
6060 //
6061 // Add some initial file allocation
6062 //
6063
6064
6065 FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize );
6066
6067
6068 UnwindAllocation = TRUE;
6069
6071
6072 //
6073 // Tentatively add the new Ea's
6074 //
6075
6076 if ( EaLength > 0 ) {
6077
6078 FatCreateEa( IrpContext,
6079 Fcb->Vcb,
6080 (PUCHAR) EaBuffer,
6081 EaLength,
6083 &EaHandle );
6084 }
6085
6086 if (!FatIsFat32(Fcb->Vcb)) {
6087
6088 ShortDirent->ExtendedAttributes = EaHandle;
6089 }
6090
6091
6092
6093 //
6094 // Initialize the LongFileName right now so that FatNotify
6095 // below won't have to.
6096 //
6097
6098 if (Fcb->FullFileName.Buffer == NULL) {
6099 FatSetFullNameInFcb( IrpContext, Fcb, RealUnicodeName );
6100 }
6101
6102 //
6103 // Setup the context and section object pointers, and update
6104 // our reference counts
6105 //
6106
6109 Fcb,
6110 UnwindCcb = FatCreateCcb( IrpContext ));
6111
6112 FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
6113
6114 //
6115 // We call the notify package to report that the
6116 // we added a file.
6117 //
6118
6119 FatNotifyReportChange( IrpContext,
6120 Vcb,
6121 Fcb,
6124
6125 //
6126 // Setup our share access
6127 //
6128
6131 FileObject,
6132 &Fcb->ShareAccess );
6133
6134 Fcb->UncleanCount += 1;
6135 Fcb->OpenCount += 1;
6138 }
6139 Vcb->OpenFileCount += 1;
6140 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount += 1; }
6142
6143
6144 //
6145 // And set our return status
6146 //
6147
6148 Iosb.Status = STATUS_SUCCESS;
6149 Iosb.Information = FILE_CREATED;
6150
6151 if ( NT_SUCCESS(Iosb.Status) ) {
6152
6153 //
6154 // Mark the DeleteOnClose bit if the operation was successful.
6155 //
6156
6157 if ( DeleteOnClose ) {
6158
6160 }
6161
6162 //
6163 // Mark the OpenedByShortName bit if the operation was successful.
6164 // If we created an Lfn, we have some sort of generated short name
6165 // and thus don't consider ourselves to have opened it - though we
6166 // may have had a case mix Lfn "Foo.bar" and generated "FOO.BAR"
6167 //
6168 // Unless, of course, we wanted to create a short name and hit an
6169 // associated Lfn in the tunnel cache
6170 //
6171
6172 if ( !CreateLfn && !UsingTunneledLfn ) {
6173
6175 }
6176
6177 //
6178 // Mark the ManageVolumeAccess bit if the privilege is held.
6179 //
6180
6181 if (FatCheckManageVolumeAccess( IrpContext,
6182 IrpSp->Parameters.Create.SecurityContext->AccessState,
6184 UserMode :
6185 IrpContext->OriginatingIrp->RequestorMode ))) {
6186
6188 }
6189
6190 }
6191
6192
6193 } _SEH2_FINALLY {
6194
6195 DebugUnwind( FatCreateNewFile );
6196
6197 if (UniTunneledLongName.Buffer != UniTunneledLongNameBuffer) {
6198
6199 //
6200 // Tunneling package grew the buffer from pool
6201 //
6202
6203 ExFreePool( UniTunneledLongName.Buffer );
6204 }
6205
6206
6207 //
6208 // If this is an abnormal termination then undo our work.
6209 //
6210 // The extra exception handling here is complex. We've got
6211 // two places here where an exception can be thrown again.
6212 //
6213
6214 LocalAbnormalTermination = _SEH2_AbnormalTermination();
6215
6216 if (LocalAbnormalTermination) {
6217
6218 if (CountsIncremented) {
6219 Fcb->UncleanCount -= 1;
6220 Fcb->OpenCount -= 1;
6223 }
6224 Vcb->OpenFileCount -= 1;
6225 if (IsFileObjectReadOnly(FileObject)) { Vcb->ReadOnlyCount -= 1; }
6226 }
6227
6228 if (UnwindFcb == NULL) {
6229
6230 NT_ASSERT( (ParentDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
6231 RtlAreBitsSet( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
6232 DirentByteOffset / sizeof(DIRENT),
6233 DirentsNeeded ) );
6234
6235 RtlClearBits( &ParentDcb->Specific.Dcb.FreeDirentBitmap,
6236 DirentByteOffset / sizeof(DIRENT),
6237 DirentsNeeded );
6238 }
6239
6240 //
6241 // Mark the dirents deleted. The code is complex because of
6242 // dealing with an LFN that crosses a page boundary.
6243 //
6244
6245 if (UnwindDirent != NULL) {
6246
6247 ULONG i;
6248
6249 for (i = 0; i < DirentsNeeded; i++) {
6250
6251 if (DirentFromPool == FALSE) {
6252
6253 //
6254 // Simple case.
6255 //
6256
6258
6259 } else {
6260
6261 //
6262 // If the second CcPreparePinWrite failed, we have
6263 // to stop early.
6264 //
6265
6266 if ((SecondPageBcb == NULL) &&
6267 (i == DirentsInFirstPage)) {
6268
6269 break;
6270 }
6271
6272 //
6273 // Now conditionally update either page.
6274 //
6275
6276 if (i < DirentsInFirstPage) {
6277
6278 FirstPageDirent[i].FileName[0] = FAT_DIRENT_DELETED;
6279
6280 } else {
6281
6282 SecondPageDirent[i - DirentsInFirstPage].FileName[0] = FAT_DIRENT_DELETED;
6283 }
6284 }
6285 }
6286 }
6287 }
6288
6289 //
6290 // We must handle exceptions in the following fragments and plow on with the
6291 // unwind of this create operation. This is basically inverted from the
6292 // previous state of the code. Since AbnormalTermination() changes when we
6293 // enter a new enclosure, we cached the original state ...
6294 //
6295
6296 _SEH2_TRY {
6297
6298 if (LocalAbnormalTermination) {
6299 if (UnwindAllocation) {
6300 FatTruncateFileAllocation( IrpContext, Fcb, 0 );
6301 }
6302 }
6303
6304 } _SEH2_FINALLY {
6305
6306 _SEH2_TRY {
6307
6308 if (LocalAbnormalTermination) {
6309 if (UnwindFcb != NULL) {
6310 FatDeleteDirent( IrpContext, UnwindFcb, NULL, TRUE );
6311 }
6312 }
6313
6314 } _SEH2_FINALLY {
6315
6316 if (LocalAbnormalTermination) {
6317 if (UnwindFcb != NULL) {
6319 FileObject->SectionObjectPointer = NULL;
6320 }
6321 FatDeleteFcb( IrpContext, &UnwindFcb );
6322 }
6323 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
6324 }
6325
6326 //
6327 // This is the normal cleanup code.
6328 //
6329
6330 FatUnpinBcb( IrpContext, DirentBcb );
6331 FatUnpinBcb( IrpContext, SecondPageBcb );
6332
6333 if (DirentFromPool) {
6334
6335 ExFreePool( Dirent );
6336 }
6337
6338 } _SEH2_END;
6339 } _SEH2_END;
6340
6341 DebugTrace(-1, Dbg, "FatCreateNewFile -> Iosb.Status = %08lx\n", Iosb.Status);
6342 } _SEH2_END;
6343
6344 return Iosb;
6345}
6346
6347
6348//
6349// Internal support routine
6350//
6351
6352_Requires_lock_held_(_Global_critical_region_)
6354FatSupersedeOrOverwriteFile (
6355 _In_ PIRP_CONTEXT IrpContext,
6364 )
6365
6366/*++
6367
6368Routine Description:
6369
6370 This routine performs a file supersede or overwrite operation.
6371
6372Arguments:
6373
6374 FileObject - Supplies a pointer to the file object
6375
6376 Fcb - Supplies a pointer to the Fcb
6377
6378 AllocationSize - Supplies an initial allocation size
6379
6380 EaBuffer - Supplies the Ea set for the superseded/overwritten file
6381
6382 EaLength - Supplies the length, in bytes, of EaBuffer
6383
6384 FileAttributes - Supplies the supersede/overwrite file attributes
6385
6386 CreateDisposition - Supplies the create disposition for the file
6387 It must be either supersede, overwrite, or overwrite if.
6388
6389 NoEaKnowledge - This opener doesn't understand Ea's and we fail this
6390 open if the file has NeedEa's.
6391
6392Return Value:
6393
6394 IO_STATUS_BLOCK - Returns the completion status for the operation
6395
6396--*/
6397
6398{
6399 IO_STATUS_BLOCK Iosb = {0};
6400
6402 PBCB DirentBcb;
6403
6404 USHORT EaHandle = 0;
6405 BOOLEAN EaChange = FALSE;
6406 BOOLEAN ReleasePaging = FALSE;
6407
6408 PCCB Ccb;
6409
6411 ULONG HeaderSize = 0;
6412 LARGE_INTEGER AllocSize = {0};
6413
6414 //
6415 // The following variables are for abnormal termination
6416 //
6417
6419 USHORT UnwindEa = 0;
6420
6421 PAGED_CODE();
6422
6423 DebugTrace(+1, Dbg, "FatSupersedeOrOverwriteFile...\n", 0);
6424
6425 DirentBcb = NULL;
6426
6427 //
6428 // We fail this operation if the caller doesn't understand Ea's.
6429 //
6430
6431 if (NoEaKnowledge
6432 && EaLength > 0) {
6433
6434 Iosb.Status = STATUS_ACCESS_DENIED;
6435
6436 DebugTrace(-1, Dbg, "FatSupersedeOrOverwriteFile -> Iosb.Status = %08lx\n", Iosb.Status);
6437 return Iosb;
6438 }
6439
6440 _SEH2_TRY {
6441
6442 //
6443 // Before we actually truncate, check to see if the purge
6444 // is going to fail.
6445 //
6446
6448 &FatLargeZero )) {
6449
6451 }
6452
6453 //
6454 // Setup the context and section object pointers, and update
6455 // our reference counts
6456 //
6457
6460 Fcb,
6461 Ccb = UnwindCcb = FatCreateCcb( IrpContext ));
6462
6463 FileObject->SectionObjectPointer = &Fcb->NonPaged->SectionObjectPointers;
6464
6465 //
6466 // Since this is an supersede/overwrite, purge the section so
6467 // that mappers will see zeros. We set the CREATE_IN_PROGRESS flag
6468 // to prevent the Fcb from going away out from underneath us.
6469 //
6470
6472
6474
6475 //
6476 // Tentatively add the new Ea's
6477 //
6478
6479 if (EaLength > 0) {
6480
6481 FatCreateEa( IrpContext,
6482 Fcb->Vcb,
6483 (PUCHAR) EaBuffer,
6484 EaLength,
6486 &EaHandle );
6487
6488 UnwindEa = EaHandle;
6489 EaChange = TRUE;
6490 }
6491
6492#if (NTDDI_VERSION >= NTDDI_WIN8)
6493 //
6494 // Break parent directory oplock. Directory oplock breaks are always
6495 // advisory, so we will never block/get STATUS_PENDING here. On the
6496 // off chance this fails with INSUFFICIENT_RESOURCES we do it here
6497 // where we can still tolerate a failure.
6498 //
6499
6500 Iosb.Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
6501 IrpContext->OriginatingIrp,
6502 OPLOCK_FLAG_PARENT_OBJECT,
6503 NULL,
6504 NULL,
6505 NULL );
6506
6507 if (Iosb.Status != STATUS_SUCCESS) {
6508
6509 FatRaiseStatus( IrpContext, Iosb.Status );
6510 }
6511#endif
6512
6513 //
6514 // Now set the new allocation size, we do that by first
6515 // zeroing out the current file size. Then we truncate and
6516 // allocate up to the new allocation size
6517 //
6518
6519 (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE );
6520 ReleasePaging = TRUE;
6521
6522 Fcb->Header.FileSize.LowPart = 0;
6523 Fcb->Header.ValidDataLength.LowPart = 0;
6524 Fcb->ValidDataToDisk = 0;
6525
6526
6527 //
6528 // Validate that the allocation size will work.
6529 //
6530
6531 AllocSize.QuadPart = AllocationSize;
6532 if (!FatIsIoRangeValid( Fcb->Vcb, AllocSize, 0 )) {
6533
6534 DebugTrace(-1, Dbg, "Illegal allocation size\n", 0);
6535
6536 FatRaiseStatus( IrpContext, STATUS_DISK_FULL );
6537 }
6538
6539
6540 //
6541 // Tell the cache manager the size went to zero
6542 // This call is unconditional, because MM always wants to know.
6543 //
6544
6546 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
6547
6548 FatTruncateFileAllocation( IrpContext, Fcb, AllocationSize+HeaderSize );
6549
6550 ExReleaseResourceLite( Fcb->Header.PagingIoResource );
6551 ReleasePaging = FALSE;
6552
6553 FatAddFileAllocation( IrpContext, Fcb, FileObject, AllocationSize+HeaderSize );
6554
6556
6557 //
6558 // Modify the attributes and time of the file, by first reading
6559 // in the dirent for the file and then updating its attributes
6560 // and time fields. Note that for supersede we replace the file
6561 // attributes as opposed to adding to them.
6562 //
6563
6564 FatGetDirentFromFcbOrDcb( IrpContext,
6565 Fcb,
6566 FALSE,
6567 &Dirent,
6568 &DirentBcb );
6569 //
6570 // We should get the dirent since this Fcb is in good condition, verified as
6571 // we crawled down the prefix tree.
6572 //
6573 // Update the appropriate dirent fields, and the fcb fields
6574 //
6575
6576 Dirent->FileSize = 0;
6577
6578
6580
6582
6583 Dirent->Attributes = (UCHAR)FileAttributes;
6584
6585 } else {
6586
6587 Dirent->Attributes |= (UCHAR)FileAttributes;
6588 }
6589
6590 Fcb->DirentFatFlags = Dirent->Attributes;
6591
6593
6594 (VOID)FatNtTimeToFatTime( IrpContext,
6596 TRUE,
6597 &Dirent->LastWriteTime,
6598 NULL );
6599
6600 if (FatData.ChicagoMode) {
6601
6602 Dirent->LastAccessDate = Dirent->LastWriteTime.Date;
6603 }
6604
6608
6609 //
6610 // And now delete the previous Ea set if there was one.
6611 //
6612
6613 if (!FatIsFat32(Fcb->Vcb) && Dirent->ExtendedAttributes != 0) {
6614
6615 //
6616 // **** SDK fix, we won't fail this if there is
6617 // an error in the Ea's, we'll just leave
6618 // the orphaned Ea's in the file.
6619 //
6620
6621 EaChange = TRUE;
6622
6623 _SEH2_TRY {
6624
6625 FatDeleteEa( IrpContext,
6626 Fcb->Vcb,
6627 Dirent->ExtendedAttributes,
6628 &Fcb->ShortName.Name.Oem );
6629
6631
6632 FatResetExceptionState( IrpContext );
6633 } _SEH2_END;
6634 }
6635
6636 //
6637 // Update the extended attributes handle in the dirent.
6638 //
6639
6640 if (EaChange) {
6641
6643
6644 Dirent->ExtendedAttributes = EaHandle;
6645
6647 }
6648
6649 //
6650 // Now update the dirent to the new ea handle and set the bcb dirty
6651 // Once we do this we can no longer back out the Ea
6652 //
6653
6654 FatSetDirtyBcb( IrpContext, DirentBcb, Fcb->Vcb, TRUE );
6655 UnwindEa = 0;
6656
6657 //
6658 // Indicate that the Eas for this file have changed.
6659 //
6660
6662
6663 //
6664 // Check to see if we need to notify outstanding Irps for full
6665 // changes only (i.e., we haven't added, deleted, or renamed the file).
6666 //
6667
6668 FatNotifyReportChange( IrpContext,
6669 Fcb->Vcb,
6670 Fcb,
6673
6674 //
6675 // And set our status to success
6676 //
6677
6678 Iosb.Status = STATUS_SUCCESS;
6679
6681
6682 Iosb.Information = FILE_SUPERSEDED;
6683
6684 } else {
6685
6686 Iosb.Information = FILE_OVERWRITTEN;
6687 }
6688
6689 try_exit: NOTHING;
6690 } _SEH2_FINALLY {
6691
6692 DebugUnwind( FatSupersedeOfOverwriteFile );
6693
6694 if (ReleasePaging) { ExReleaseResourceLite( Fcb->Header.PagingIoResource ); }
6695
6696 //
6697 // If this is an abnormal termination then undo our work.
6698 //
6699
6701
6702 if (UnwindEa != 0) { FatDeleteEa( IrpContext, Fcb->Vcb, UnwindEa, &Fcb->ShortName.Name.Oem ); }
6703 if (UnwindCcb != NULL) { FatDeleteCcb( IrpContext, &UnwindCcb ); }
6704 }
6705
6706 FatUnpinBcb( IrpContext, DirentBcb );
6707
6709
6710 DebugTrace(-1, Dbg, "FatSupersedeOrOverwriteFile -> Iosb.Status = %08lx\n", Iosb.Status);
6711 } _SEH2_END;
6712
6713 return Iosb;
6714}
6715
6716
6717VOID
6719 _In_ PIRP_CONTEXT IrpContext,
6721 _In_ PUNICODE_STRING FinalName
6722 )
6723
6724/*++
6725
6726Routine Description:
6727
6728 This routine attempts a quick form of the full FatSetFullFileNameInFcb
6729 operation.
6730
6731 NOTE: this routine is probably not worth the code duplication involved,
6732 and is not equipped to handle the cases where the parent doesn't have
6733 the full name set up.
6734
6735Arguments:
6736
6737 Fcb - Supplies a pointer to the Fcb
6738
6739 FinalName - Supplies the last component of the path to this Fcb's dirent
6740
6741Return Value:
6742
6743 None. May silently fail.
6744
6745--*/
6746
6747{
6748 PAGED_CODE();
6749
6750 UNREFERENCED_PARAMETER( IrpContext );
6751
6753
6754 //
6755 // Prefer the ExactCaseLongName of the file for this operation, if set. In
6756 // this way we avoid building the fullname with a short filename. Several
6757 // operations assume this - the FinalNameLength in particular is the Lfn
6758 // (if existant) length, and we use this to crack the fullname in paths
6759 // such as the FsRtlNotify caller.
6760 //
6761 // If the caller specified a particular name and it is short, it is the
6762 // case that the long name was set up.
6763 //
6764
6766
6768 FinalName = &Fcb->ExactCaseLongName;
6769 }
6770
6771 //
6772 // Special case the root.
6773 //
6774
6776
6778 Fcb->FullFileName.MaximumLength = sizeof(WCHAR) + FinalName->Length;
6779
6783
6784 Fcb->FullFileName.Buffer[0] = L'\\';
6785
6787 &FinalName->Buffer[0],
6788 FinalName->Length );
6789
6790 } else {
6791
6793
6794 Prefix = &Fcb->ParentDcb->FullFileName;
6795
6796 //
6797 // It is possible our parent's full filename is not set. Simply fail
6798 // this attempt.
6799 //
6800
6801 if (Prefix->Buffer == NULL) {
6802
6803 return;
6804 }
6805
6807 Fcb->FullFileName.MaximumLength = Prefix->Length + sizeof(WCHAR) + FinalName->Length;
6808
6812
6814 &Prefix->Buffer[0],
6815 Prefix->Length );
6816
6817 Fcb->FullFileName.Buffer[Prefix->Length / sizeof(WCHAR)] = L'\\';
6818
6819 RtlCopyMemory( &Fcb->FullFileName.Buffer[(Prefix->Length / sizeof(WCHAR)) + 1],
6820 &FinalName->Buffer[0],
6821 FinalName->Length );
6822
6823 }
6824}
6825
6826
6829 _In_ PIRP_CONTEXT IrpContext
6830 )
6831{
6833 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
6834
6835 PAGED_CODE();
6836
6837 //
6838 // We check if the caller wants ACCESS_SYSTEM_SECURITY access on this
6839 // object and fail the request if he does.
6840 //
6841
6842 NT_ASSERT( IrpSp->Parameters.Create.SecurityContext != NULL );
6843 AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
6844
6845 //
6846 // Check if the remaining privilege includes ACCESS_SYSTEM_SECURITY.
6847 //
6848
6849 if (FlagOn( AccessState->RemainingDesiredAccess, ACCESS_SYSTEM_SECURITY )) {
6850
6852 UserMode )) {
6853
6854 return STATUS_ACCESS_DENIED;
6855 }
6856
6857 //
6858 // Move this privilege from the Remaining access to Granted access.
6859 //
6860
6861 ClearFlag( AccessState->RemainingDesiredAccess, ACCESS_SYSTEM_SECURITY );
6862 SetFlag( AccessState->PreviouslyGrantedAccess, ACCESS_SYSTEM_SECURITY );
6863 }
6864
6865 return STATUS_SUCCESS;
6866}
6867
6868
6871 _In_ PIRP_CONTEXT IrpContext,
6876 )
6877
6878/*++
6879
6880Routine Description:
6881
6882 This routine checks conditions that may result in a sharing violation.
6883
6884Arguments:
6885
6886 FileObject - Pointer to the file object of the current open request.
6887
6888 FcbOrDcb - Supplies a pointer to the Fcb/Dcb.
6889
6890 DesiredAccess - Desired access of current open request.
6891
6892 ShareAccess - Shared access requested by current open request.
6893
6894Return Value:
6895
6896 If the accessor has access to the file, STATUS_SUCCESS is returned.
6897 Otherwise, STATUS_SHARING_VIOLATION is returned.
6898
6899--*/
6900
6901{
6902 PAGED_CODE();
6903
6904#if (NTDDI_VERSION >= NTDDI_VISTA)
6905 //
6906 // Do an extra test for writeable user sections if the user did not allow
6907 // write sharing - this is neccessary since a section may exist with no handles
6908 // open to the file its based against.
6909 //
6910
6911 if ((NodeType( FcbOrDcb ) == FAT_NTC_FCB) &&
6915
6917 }
6918#endif
6919
6920 //
6921 // Check if the Fcb has the proper share access.
6922 //
6923
6926 FileObject,
6928 FALSE );
6929
6930 UNREFERENCED_PARAMETER( IrpContext );
6931}
6932
6933//
6934// Lifted from NTFS.
6935//
6936
6940 __in PIRP Irp,
6941 __in PVOID Contxt
6942 )
6943
6944{
6945 //
6946 // Set the event so that our call will wake up.
6947 //
6948
6949 KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
6950
6953
6954 //
6955 // If we change this return value then FatIoCallSelf needs to reference the
6956 // file object.
6957 //
6958
6960}
ULONG NTAPI MmDoesFileHaveUserWritableReferences(IN PSECTION_OBJECT_POINTERS SectionPointer)
Definition: section.c:3352
#define PAGED_CODE()
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
BOOLEAN FatCheckFileAccess(PIRP_CONTEXT IrpContext, IN UCHAR DirentAttributes, IN PACCESS_MASK DesiredAccess)
Definition: acchksup.c:39
NTSTATUS FatExplicitDeviceAccessGranted(IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT DeviceObject, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE ProcessorMode)
Definition: acchksup.c:225
BOOLEAN FatCheckManageVolumeAccess(_In_ PIRP_CONTEXT IrpContext, _In_ PACCESS_STATE AccessState, _In_ KPROCESSOR_MODE ProcessorMode)
Definition: acchksup.c:176
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONGLONG PartitionSectorCount)
Definition: fat.c:138
#define except(x)
Definition: btrfs_drv.h:136
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
CCB * PCCB
Definition: cdstruc.h:1101
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:769
@ FcbGood
Definition: cdstruc.h:779
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define __in
Definition: dbghelp.h:35
#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
#define FILE_SHARE_READ
Definition: compat.h:136
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:878
#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 DirentByteOffset
Definition: create.c:4144
LUID FatSecurityPrivilege
Definition: create.c:50
_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 _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT Dirent
Definition: create.c:4142
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT _In_ ULONG _In_ BOOLEAN _In_ BOOLEAN _In_ BOOLEAN _In_ BOOLEAN OpenRequiringOplock
Definition: create.c:4204
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
NTSTATUS FatCheckSystemSecurityAccess(_In_ PIRP_CONTEXT IrpContext)
Definition: create.c:6828
PCCB UnwindCcb
Definition: create.c:4212
NTSTATUS FatCallSelfCompletionRoutine(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Contxt)
Definition: create.c:6938
VOID FatSetFullNameInFcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ PUNICODE_STRING FinalName)
Definition: create.c:6718
FatSetFileObject(FileObject, UserDirectoryOpen,(*Dcb), UnwindCcb=FatCreateCcb(IrpContext))
#define CollectCreateStatistics(VCB, STATUS)
Definition: create.c:41
#define CollectCreateHitStatistics(VCB)
Definition: create.c:36
#define Dbg
Definition: create.c:29
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB ParentDcb
Definition: create.c:4141
PDCB UnwindDcb
Definition: create.c:4211
NTSTATUS FatCheckShareAccess(_In_ PIRP_CONTEXT IrpContext, _In_ PFILE_OBJECT FileObject, _In_ PFCB FcbOrDcb, _In_ PACCESS_MASK DesiredAccess, _In_ ULONG ShareAccess)
Definition: create.c:6870
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT _In_ ULONG _In_ BOOLEAN _In_ BOOLEAN DeleteOnClose
Definition: create.c:4150
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG LfnByteOffset
Definition: create.c:4143
BOOLEAN CountsIncremented
Definition: create.c:4214
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT _In_ ULONG _In_ BOOLEAN NoEaKnowledge
Definition: create.c:4149
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT _In_ ULONG _In_ BOOLEAN _In_ BOOLEAN _In_ BOOLEAN FileNameOpenedDos
Definition: create.c:4151
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4147
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_ATTR_READ_ONLY
Definition: fat.h:368
VBO * PVBO
Definition: fat.h:39
#define FAT_DIRENT_DELETED
Definition: fat.h:337
#define FAT_DIRENT_ATTR_SYSTEM
Definition: fat.h:370
#define FAT_DIRENT_ATTR_DIRECTORY
Definition: fat.h:372
#define FAT_DIRENT_ATTR_HIDDEN
Definition: fat.h:369
PACKED_LFN_DIRENT LFN_DIRENT
Definition: lfn.h:43
#define FAT_LFN_DIRENTS_NEEDED(NAME)
Definition: lfn.h:53
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define TAG_DIRENT
Definition: nodetype.h:158
#define TAG_FILENAME_BUFFER
Definition: nodetype.h:167
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#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 BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
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
VOID FatConstructDirent(IN PIRP_CONTEXT IrpContext, IN OUT PDIRENT Dirent, IN POEM_STRING FileName, IN BOOLEAN ComponentReallyLowercase, IN BOOLEAN ExtensionReallyLowercase, IN PUNICODE_STRING Lfn OPTIONAL, IN USHORT Attributes, IN BOOLEAN ZeroAndSetTimeFields, IN PLARGE_INTEGER SetCreationTime OPTIONAL)
Definition: dirsup.c:2171
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
FAT_DATA FatData
Definition: fatdata.c:56
PMDL FatReserveMdl
Definition: fatdata.c:119
#define TimerStart(LEVEL)
Definition: fatdata.h:318
#define FAT_RESERVE_MDL_SIZE
Definition: fatdata.h:70
#define TimerStop(LEVEL, s)
Definition: fatdata.h:319
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define DebugUnwind(X)
Definition: fatdata.h:315
#define DIRENT
Definition: fatfs.h:187
@ VolumeClean
Definition: fatprocs.h:1954
VOID FatDeleteFcb(IN PIRP_CONTEXT IrpContext, IN PFCB *Fcb)
Definition: strucsup.c:1952
VOID FatDeleteCcb(IN PIRP_CONTEXT IrpContext, IN PCCB *Ccb)
Definition: strucsup.c:2254
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
static INLINE BOOLEAN FatIsNameLongUnicodeValid(PIRP_CONTEXT IrpContext, PUNICODE_STRING Name, BOOLEAN CanContainWildcards, BOOLEAN PathNameOk, BOOLEAN LeadingBackslashOk)
Definition: fatprocs.h:1215
VOID FatStringTo8dot3(_In_ PIRP_CONTEXT IrpContext, _In_ OEM_STRING InputString, _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3)
Definition: namesup.c:79
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN IN OUT BOOLEAN IN OUT BOOLEAN * CreateLfn
Definition: fatprocs.h:1311
#define IsFileObjectReadOnly(FO)
Definition: fatprocs.h:2866
#define FAT_CREATE_INITIAL_NAME_BUF_SIZE
Definition: fatprocs.h:111
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN * AllLowerComponent
Definition: fatprocs.h:1308
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2168
@ DirectoryFile
Definition: fatprocs.h:1046
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
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 NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
PFCB FatFindFcb(IN PIRP_CONTEXT IrpContext, IN OUT PRTL_SPLAY_LINKS *RootNode, IN PSTRING Name, OUT PBOOLEAN FileNameDos OPTIONAL)
Definition: splaysup.c:306
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3095
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2983
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
VOID FatEnsureStringBufferEnough(_Inout_ PVOID String, _In_ USHORT DesiredBufferSize)
Definition: strucsup.c:3739
IN PFCB FcbOrDcb
Definition: fatprocs.h:306
IN PDCB IN ULONG DirentsNeeded
Definition: fatprocs.h:699
IN PDCB IN POEM_STRING IN PUNICODE_STRING UnicodeName
Definition: fatprocs.h:1305
BOOLEAN FatIsHandleCountZero(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: strucsup.c:3614
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1306
PCCB FatCreateCcb(IN PIRP_CONTEXT IrpContext)
Definition: strucsup.c:2155
#define FatIsFastIoPossible(FCB)
Definition: fatprocs.h:2813
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING IN PUNICODE_STRING SuggestedShortName IN OUT BOOLEAN IN OUT BOOLEAN * AllLowerExtension
Definition: fatprocs.h:1309
#define FatIsNameShortOemValid(IRPCONTEXT, NAME, CAN_CONTAIN_WILD_CARDS, PATH_NAME_OK, LEADING_BACKSLASH_OK)
Definition: fatprocs.h:1198
IN PVCB IN PUCHAR IN ULONG IN POEM_STRING OUT PUSHORT EaHandle
Definition: fatprocs.h:898
VOID FatVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:270
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2977
IN PVCB IN PDIRENT OUT PULONG EaLength
Definition: fatprocs.h:878
@ Flush
Definition: fatprocs.h:1054
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1656
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
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
VOID FatRemoveNames(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: splaysup.c:222
#define FatIsFileOplockable(F)
Definition: fatprocs.h:2851
VOID FatFreeStringBuffer(_Inout_ PVOID String)
Definition: strucsup.c:3784
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
IN PDCB IN POEM_STRING OemName
Definition: fatprocs.h:1304
#define FatDirectoryKey(FcbOrDcb)
Definition: fatprocs.h:850
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
IN PVCB IN PDIRENT OUT PULONG NeedEaCount
Definition: fatprocs.h:887
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
static INLINE BOOLEAN FatIsIoRangeValid(IN PVCB Vcb, IN LARGE_INTEGER Start, IN ULONG Length)
Definition: fatprocs.h:218
#define VCB_STATE_FLAG_VOLUME_DIRTY
Definition: fatstruc.h:561
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:559
#define CCB_FLAG_MANAGE_VOLUME_ACCESS
Definition: fatstruc.h:1338
#define IRP_CONTEXT_FLAG_SWAPPED_STACK
Definition: fatstruc.h:1579
#define VCB_STATE_FLAG_REMOVABLE_MEDIA
Definition: fatstruc.h:560
#define IRP_CONTEXT_FLAG_DISABLE_RAISE
Definition: fatstruc.h:1573
#define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE
Definition: fatstruc.h:567
#define CCB_FLAG_OPENED_BY_SHORTNAME
Definition: fatstruc.h:1296
#define CCB_FLAG_SKIP_SHORT_NAME_COMPARE
Definition: fatstruc.h:1253
#define VCB_STATE_FLAG_CREATE_IN_PROGRESS
Definition: fatstruc.h:566
#define VCB_STATE_FLAG_MOUNTED_DIRTY
Definition: fatstruc.h:562
#define FCB_STATE_TEMPORARY
Definition: fatstruc.h:1198
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:570
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1193
#define FCB_STATE_SYSTEM_FILE
Definition: fatstruc.h:1199
#define FCB_STATE_TRUNCATE_ON_CLOSE
Definition: fatstruc.h:1194
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
@ VcbGood
Definition: fatstruc.h:223
#define IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH
Definition: fatstruc.h:1565
#define CCB_FLAG_DELETE_ON_CLOSE
Definition: fatstruc.h:1289
#define FCB_STATE_DELAY_CLOSE
Definition: fatstruc.h:1203
struct _FileName FileName
Definition: fatprocs.h:896
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
Definition: fltkernel.h:1236
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OVERWRITE_IF
Definition: from_kernel.h:58
#define FILE_NO_EA_KNOWLEDGE
Definition: from_kernel.h:36
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SUPERSEDE
Definition: from_kernel.h:53
#define FsRtlEnterFileSystem
_Out_ PANSI_STRING _Out_ PANSI_STRING RemainingPart
Definition: fsrtlfuncs.h:379
#define FsRtlExitFileSystem
#define OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY
Definition: fsrtltypes.h:267
#define OPLOCK_FLAG_BACK_OUT_ATOMIC_OPLOCK
Definition: fsrtltypes.h:268
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
GLuint in
Definition: glext.h:9616
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
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define FILE_OPEN_REQUIRING_OPLOCK
Definition: winternl.h:186
NTSYSAPI NTSTATUS WINAPI RtlDowncaseUnicodeString(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN)
NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeStringToCountedOemString(STRING *, const UNICODE_STRING *, BOOLEAN)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
NTSYSAPI BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP, ULONG, ULONG)
#define NOTHING
Definition: input_list.c:10
HRESULT Create([out]ITransactionReceiver **ppReceiver)
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
if(dx< 0)
Definition: linetemp.h:194
BOOLEAN NTAPI CcIsThereDirtyData(IN PVPB Vpb)
Definition: logsup.c:55
#define PCHAR
Definition: match.c:90
#define SE_SECURITY_PRIVILEGE
Definition: security.c:662
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Success_(expr)
Definition: ms_sal.h:259
#define _Inout_
Definition: ms_sal.h:378
#define _Outptr_result_maybenull_
Definition: ms_sal.h:428
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
@ Hidden
Definition: scrrun.idl:71
@ System
Definition: scrrun.idl:72
#define UserMode
Definition: asm.h:35
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_DOES_NOT_EXIST
Definition: nt_native.h:773
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define ACCESS_SYSTEM_SECURITY
Definition: nt_native.h:77
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
ACCESS_MASK * PACCESS_MASK
Definition: nt_native.h:41
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_CREATED
Definition: nt_native.h:770
#define FILE_OVERWRITTEN
Definition: nt_native.h:771
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_EXECUTE
Definition: nt_native.h:642
#define FILE_SUPERSEDED
Definition: nt_native.h:768
#define FILE_EXISTS
Definition: nt_native.h:772
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define DELETE
Definition: nt_native.h:57
#define FILE_OPENED
Definition: nt_native.h:769
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define ARGUMENT_PRESENT(ArgumentPointer)
#define FILE_ATTRIBUTE_ENCRYPTED
Definition: ntifs_ex.h:385
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
VOID NTAPI FsRtlDissectName(IN UNICODE_STRING Name, OUT PUNICODE_STRING FirstPart, OUT PUNICODE_STRING RemainingPart)
Definition: name.c:398
VOID NTAPI IoSetShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3517
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
Definition: file.c:3390
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
VOID NTAPI IoUpdateShareAccess(IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3351
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_USER_MAPPED_FILE
Definition: ntstatus.h:711
#define STATUS_FILE_INVALID
Definition: ntstatus.h:388
#define STATUS_EAS_NOT_SUPPORTED
Definition: ntstatus.h:315
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_OPLOCK_BREAK_IN_PROGRESS
Definition: ntstatus.h:87
#define STATUS_CANNOT_BREAK_OPLOCK
Definition: ntstatus.h:1166
#define STATUS_UNMAPPABLE_CHARACTER
Definition: ntstatus.h:590
#define L(x)
Definition: ntvdm.h:50
BOOLEAN NTAPI FsRtlCurrentBatchOplock(IN POPLOCK Oplock)
Definition: oplock.c:1364
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1430
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1170
#define BOOLEAN
Definition: pedump.c:73
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
@ OpenDirectory
Definition: arc.h:73
#define KERNEL_STACK_SIZE
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4255
BOOLEAN NTAPI MmFlushImageSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN MMFLUSH_TYPE FlushType)
Definition: section.c:4356
#define AbnormalTermination()
Definition: seh.h:28
#define GetExceptionInformation()
Definition: seh.h:26
#define GetExceptionCode()
Definition: seh.h:27
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
UNICODE_STRING UnicodeQueryTemplate
Definition: fatstruc.h:1430
union _CCB::@723::@725::@727 OemQueryTemplate
FAT8DOT3 Constant
Definition: fatstruc.h:1426
ULONG Flags
Definition: cdstruc.h:1080
BOOLEAN ContainsWildCards
Definition: fatstruc.h:1379
PCHAR FileName
Definition: cdstruc.h:1648
struct _FAT_CALLOUT_PARAMETERS::@730::@732 Create
BOOLEAN ChicagoMode
Definition: fatstruc.h:87
LIST_ENTRY AsyncCloseList
Definition: fatstruc.h:132
LIST_ENTRY DelayedCloseList
Definition: fatstruc.h:139
Definition: cdstruc.h:902
struct _FCB * ParentDcb
Definition: fatstruc.h:836
union _FCB::@719 Specific
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
UNICODE_STRING ExactCaseLongName
Definition: fatstruc.h:1139
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1009
UNICODE_STRING FullFileName
Definition: fatstruc.h:1122
ULONG EaModificationCount
Definition: fatstruc.h:1107
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
LARGE_INTEGER LastWriteTime
Definition: fatstruc.h:922
CLONG OpenCount
Definition: fatstruc.h:881
CLONG UncleanCount
Definition: fatstruc.h:873
ULONG ValidDataToDisk
Definition: fatstruc.h:928
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
struct _FCB::@719::@721 Dcb
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
UCHAR DirentFatFlags
Definition: fatstruc.h:1133
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:811
CLONG NonCachedUncleanCount
Definition: fatstruc.h:888
union _FILE_NAME_NODE::@718 Name
OEM_STRING Oem
Definition: fatstruc.h:693
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PUNICODE_STRING FileName
Definition: iotypes.h:3149
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
USHORT ShareAccess
Definition: iotypes.h:3120
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:729
unsigned short Length
Definition: sprintf.c:451
void * Buffer
Definition: sprintf.c:453
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
CLONG ReadOnlyCount
Definition: fatstruc.h:313
CLONG OpenFileCount
Definition: fatstruc.h:312
ULONG VcbState
Definition: cdstruc.h:540
Definition: ps.c:97
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
BOOLEAN NTAPI FsRtlFindInTunnelCache(IN PTUNNEL Cache, IN ULONGLONG DirectoryKey, IN PUNICODE_STRING Name, OUT PUNICODE_STRING ShortName, OUT PUNICODE_STRING LongName, IN OUT PULONG DataLength, OUT PVOID Data)
Definition: tunnel.c:766
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
union _LARGE_INTEGER LARGE_INTEGER
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
STRING OEM_STRING
Definition: umtypes.h:203
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG _Out_opt_ PULONG CreateDisposition
Definition: wdfregistry.h:120
#define CreateDirectory
Definition: winbase.h:3681
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG _In_ ULONG _In_ ULONG _In_opt_ PVOID EaBuffer
Definition: iofuncs.h:845
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define FILE_OPBATCH_BREAK_UNDERWAY
#define SL_OPEN_PAGING_FILE
Definition: iotypes.h:1817
#define FILE_NOTIFY_CHANGE_SIZE
#define FILE_ACTION_MODIFIED
#define SL_FORCE_ACCESS_CHECK
Definition: iotypes.h:1816
#define FO_FILE_FAST_IO_READ
Definition: iotypes.h:1795
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_NOTIFY_CHANGE_FILE_NAME
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1778
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_NOTIFY_CHANGE_EA
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1818
#define FILE_ACTION_ADDED
#define FILE_NOTIFY_CHANGE_DIR_NAME
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define NT_ASSERT
Definition: rtlfuncs.h:3310
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1630
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID _Out_ PIO_STATUS_BLOCK _In_ ULONG NotifyFilter
Definition: zwfuncs.h:504