ReactOS 0.4.15-dev-7942-gd23573b
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 Cdfs called by the
12 Fsd/Fsp dispatch routines.
13
14
15--*/
16
17#include "cdprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (CDFS_BUG_CHECK_CREATE)
24
25//
26// Local support routines
27//
28
29_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_))
30_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_))
31_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_))
32_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_))
34CdNormalizeFileNames (
35 _Inout_ PIRP_CONTEXT IrpContext,
39 _In_ TYPE_OF_OPEN RelatedTypeOfOpen,
40 PCCB RelatedCcb,
41 PUNICODE_STRING RelatedFileName,
44 );
45
46_Requires_lock_held_(_Global_critical_region_)
47_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource)
49CdOpenByFileId (
50 _In_ PIRP_CONTEXT IrpContext,
54 );
55
56_Requires_lock_held_(_Global_critical_region_)
58CdOpenExistingFcb (
59 _In_ PIRP_CONTEXT IrpContext,
64 _In_opt_ PCCB RelatedCcb
65 );
66
67_Requires_lock_held_(_Global_critical_region_)
68_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource)
70CdOpenDirectoryFromPathEntry (
71 _In_ PIRP_CONTEXT IrpContext,
77 _In_ BOOLEAN ShortNameMatch,
78 _In_ PPATH_ENTRY PathEntry,
79 _In_ BOOLEAN PerformUserOpen,
80 _In_opt_ PCCB RelatedCcb
81 );
82
83_Requires_lock_held_(_Global_critical_region_)
85CdOpenFileFromFileContext (
86 _In_ PIRP_CONTEXT IrpContext,
92 _In_ BOOLEAN ShortNameMatch,
94 _In_opt_ PCCB RelatedCcb
95 );
96
97_Requires_lock_held_(_Global_critical_region_)
99CdCompleteFcbOpen (
100 _In_ PIRP_CONTEXT IrpContext,
102 _In_ PVCB Vcb,
105 _In_ ULONG UserCcbFlags,
107 );
108
109#ifdef ALLOC_PRAGMA
110#pragma alloc_text(PAGE, CdCommonCreate)
111#pragma alloc_text(PAGE, CdCompleteFcbOpen)
112#pragma alloc_text(PAGE, CdNormalizeFileNames)
113#pragma alloc_text(PAGE, CdOpenByFileId)
114#pragma alloc_text(PAGE, CdOpenDirectoryFromPathEntry)
115#pragma alloc_text(PAGE, CdOpenExistingFcb)
116#pragma alloc_text(PAGE, CdOpenFileFromFileContext)
117#endif
118
119
120_Requires_lock_held_(_Global_critical_region_)
122#ifdef _MSC_VER
123#pragma prefast(suppress:26165, "Esp:1153")
124#endif
125CdCommonCreate (
126 _Inout_ PIRP_CONTEXT IrpContext,
128 )
129
130/*++
131
132Routine Description:
133
134 This is the common routine for opening a file called by both the
135 Fsp and Fsd threads.
136
137 The file can be opened either by name or by file Id either with or without
138 a relative name. The file name field in the file object passed to this routine
139 contains either a unicode string or a 64 bit value which is the file Id.
140 If this is not a Joliet disk then we will convert the unicode name to
141 an Oem string in this routine. If there is a related file object with
142 a name then we will already have converted that name to Oem.
143
144 We will store the full name for the file in the file object on a successful
145 open. We will allocate a larger buffer if necessary and combine the
146 related and file object names. The only exception is the relative open
147 when the related file object is for an OpenByFileId file. If we need to
148 allocate a buffer for a case insensitive name then we allocate it at
149 the tail of the buffer we will store into the file object. The upcased
150 portion will begin immediately after the name defined by the FileName
151 in the file object.
152
153 Once we have the full name in the file object we don't want to split the
154 name in the event of a retry. We use a flag in the IrpContext to indicate
155 that the name has been split.
156
157Arguments:
158
159 Irp - Supplies the Irp to process
160
161Return Value:
162
163 NTSTATUS - This is the status from this open operation.
164
165--*/
166
167{
170
172
173 COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
174 BOOLEAN CleanupCompoundPathEntry = FALSE;
175
177 BOOLEAN CleanupFileContext = FALSE;
178 BOOLEAN FoundEntry;
179
180 PVCB Vcb;
181
185
186 BOOLEAN ShortNameMatch;
188
189 BOOLEAN VolumeOpen = FALSE;
190
191 //
192 // We will be acquiring and releasing file Fcb's as we move down the
193 // directory tree during opens. At any time we need to know the deepest
194 // point we have traversed down in the tree in case we need to cleanup
195 // any structures created here.
196 //
197 // CurrentFcb - represents this point. If non-null it means we have
198 // acquired it and need to release it in finally clause.
199 //
200 // NextFcb - represents the NextFcb to walk to but haven't acquired yet.
201 //
202
203 TYPE_OF_OPEN RelatedTypeOfOpen = UnopenedFileObject;
204 PFILE_OBJECT RelatedFileObject;
205 PCCB RelatedCcb = NULL;
206
207 PFCB NextFcb;
209
210 //
211 // During the open we need to combine the related file object name
212 // with the remaining name. We also may need to upcase the file name
213 // in order to do a case-insensitive name comparison. We also need
214 // to restore the name in the file object in the event that we retry
215 // the request. We use the following string variables to manage the
216 // name. We will can put these strings into either Unicode or Ansi
217 // form.
218 //
219 // FileName - Pointer to name as currently stored in the file
220 // object. We store the full name into the file object early in
221 // the open operation.
222 //
223 // RelatedFileName - Pointer to the name in the related file object.
224 //
225 // RemainingName - String containing remaining name to parse.
226 //
227 // MatchingName - Address of name structure in FileContext which matched.
228 // We need this to know whether we matched the long or short name.
229 //
230
232 PUNICODE_STRING RelatedFileName = NULL;
233
234 CD_NAME RemainingName = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
235 CD_NAME FinalName;
237
238 PAGED_CODE();
239
240 //
241 // If we were called with our file system device object instead of a
242 // volume device object, just complete this request with STATUS_SUCCESS.
243 //
244
245 if (IrpContext->Vcb == NULL) {
246
247 CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
248 return STATUS_SUCCESS;
249 }
250
251 //
252 // Get create parameters from the Irp.
253 //
254
257 CreateDisposition = (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
258
259 //
260 // Do some preliminary checks to make sure the operation is supported.
261 // We fail in the following cases immediately.
262 //
263 // - Open a paging file.
264 // - Open a target directory.
265 // - Open a file with Eas.
266 // - Create a file.
267 //
268
270 (IrpSp->Parameters.Create.EaLength != 0) ||
272
275 }
276
277#if (NTDDI_VERSION >= NTDDI_WIN7)
278 //
279 // CDFS does not support FILE_OPEN_REQUIRING_OPLOCK
280 //
281
283
286 }
287#endif
288
289 //
290 // Copy the Vcb to a local. Assume the starting directory is the root.
291 //
292
293 Vcb = IrpContext->Vcb;
294 NextFcb = Vcb->RootIndexFcb;
295
296 //
297 // Reference our input parameters to make things easier
298 //
299
301 RelatedFileObject = NULL;
302
303 FileName = &FileObject->FileName;
304
305 //
306 // Set up the file object's Vpb pointer in case anything happens.
307 // This will allow us to get a reasonable pop-up.
308 //
309
310 if ((FileObject->RelatedFileObject != NULL) && !OpenByFileId) {
311
312 RelatedFileObject = FileObject->RelatedFileObject;
313 FileObject->Vpb = RelatedFileObject->Vpb;
314
315 RelatedTypeOfOpen = CdDecodeFileObject( IrpContext, RelatedFileObject, &NextFcb, &RelatedCcb );
316
317 //
318 // Fail the request if this is not a user file object.
319 //
320
321 if (RelatedTypeOfOpen < UserVolumeOpen) {
322
325 }
326
327 //
328 // Remember the name in the related file object.
329 //
330
331 RelatedFileName = &RelatedFileObject->FileName;
332 }
333
334 //
335 // If we haven't initialized the names then make sure the strings are valid.
336 // If this an OpenByFileId then verify the file id buffer.
337 //
338 // After this routine returns we know that the full name is in the
339 // FileName buffer and the buffer will hold the upcased portion
340 // of the name yet to parse immediately after the full name in the
341 // buffer. Any trailing backslash has been removed and the flag
342 // in the IrpContext will indicate whether we removed the
343 // backslash.
344 //
345
346 Status = CdNormalizeFileNames( IrpContext,
347 Vcb,
350 RelatedTypeOfOpen,
351 RelatedCcb,
352 RelatedFileName,
353 FileName,
354 &RemainingName );
355
356 //
357 // Return the error code if not successful.
358 //
359
360 if (!NT_SUCCESS( Status )) {
361
362 CdCompleteRequest( IrpContext, Irp, Status );
363 return Status;
364 }
365
366 //
367 // We want to acquire the Vcb. Exclusively for a volume open, shared otherwise.
368 // The file name is empty for a volume open.
369 //
370
371 if ((FileName->Length == 0) &&
372 (RelatedTypeOfOpen <= UserVolumeOpen) &&
373 !OpenByFileId) {
374
375 VolumeOpen = TRUE;
376 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
377
378 } else {
379
380 CdAcquireVcbShared( IrpContext, Vcb, FALSE );
381 }
382
383 //
384 // Use a try-finally to facilitate cleanup.
385 //
386
387 _SEH2_TRY {
388
389 //
390 // Verify that the Vcb is not in an unusable condition. This routine
391 // will raise if not usable.
392 //
393
394 CdVerifyVcb( IrpContext, Vcb );
395
396 //
397 // If the Vcb is locked then we cannot open another file
398 //
399
400 if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
401
403 }
404
405 //
406 // If we are opening this file by FileId then process this immediately
407 // and exit.
408 //
409
410 if (OpenByFileId) {
411
412 //
413 // We only allow Dasd opens of audio disks. Fail this request at
414 // this point.
415 //
416
417 if (FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) {
418
420 }
421
422 //
423 // The only create disposition we allow is OPEN.
424 //
425
426 if ((CreateDisposition != FILE_OPEN) &&
428
430 }
431
432 //
433 // Make sure we can wait for this request.
434 //
435
436 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
437
438 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
439 }
440
441 try_return( Status = CdOpenByFileId( IrpContext,
442 IrpSp,
443 Vcb,
444 &CurrentFcb ));
445 }
446
447 //
448 // If we are opening this volume Dasd then process this immediately
449 // and exit.
450 //
451
452 if (VolumeOpen) {
453
454 //
455 // The only create disposition we allow is OPEN.
456 //
457
458 if ((CreateDisposition != FILE_OPEN) &&
460
462 }
463
464 //
465 // If they wanted to open a directory, surprise.
466 //
467
469
471 }
472
473 //
474 // Acquire the Fcb first.
475 //
476
477 CurrentFcb = Vcb->VolumeDasdFcb;
478 CdAcquireFcbExclusive( IrpContext, CurrentFcb, FALSE );
479
480 try_return( Status = CdOpenExistingFcb( IrpContext,
481 IrpSp,
482 &CurrentFcb,
484 FALSE,
485 NULL ));
486 }
487
488 //
489 // At this point CurrentFcb points to the deepest Fcb for this open
490 // in the tree. Let's acquire this Fcb to keep it from being deleted
491 // beneath us.
492 //
493
494 CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
495 CurrentFcb = NextFcb;
496
497 //
498 // Do a prefix search if there is more of the name to parse.
499 //
500
501 if (RemainingName.FileName.Length != 0) {
502
503 //
504 // Do the prefix search to find the longest matching name.
505 //
506
507 CdFindPrefix( IrpContext,
508 &CurrentFcb,
509 &RemainingName.FileName,
510 IgnoreCase );
511 }
512
513 //
514 // If the remaining name length is zero then we have found our
515 // target.
516 //
517
518 if (RemainingName.FileName.Length == 0) {
519
520 //
521 // If this is a file so verify the user didn't want to open
522 // a directory.
523 //
524
526
527 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
529
531 }
532
533 //
534 // The only create disposition we allow is OPEN.
535 //
536
537 if ((CreateDisposition != FILE_OPEN) &&
539
541 }
542
543 try_return( Status = CdOpenExistingFcb( IrpContext,
544 IrpSp,
545 &CurrentFcb,
548 RelatedCcb ));
549
550 //
551 // This is a directory. Verify the user didn't want to open
552 // as a file.
553 //
554
555 } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_NON_DIRECTORY_FILE )) {
556
558
559 //
560 // Open the file as a directory.
561 //
562
563 } else {
564
565 //
566 // The only create disposition we allow is OPEN.
567 //
568
569 if ((CreateDisposition != FILE_OPEN) &&
571
573 }
574
575 try_return( Status = CdOpenExistingFcb( IrpContext,
576 IrpSp,
577 &CurrentFcb,
580 RelatedCcb ));
581 }
582 }
583
584 //
585 // We have more work to do. We have a starting Fcb which we own shared.
586 // We also have the remaining name to parse. Walk through the name
587 // component by component looking for the full name.
588 //
589
590 //
591 // Our starting Fcb better be a directory.
592 //
593
595
597 }
598
599 //
600 // If we can't wait then post this request.
601 //
602
603 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
604
605 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
606 }
607
608 //
609 // Make sure the final name has no version string.
610 //
611
612 FinalName.VersionString.Length = 0;
613
614 while (TRUE) {
615
616 ShortNameMatch = FALSE;
617
618 //
619 // Split off the next component from the name.
620 //
621
622 CdDissectName( IrpContext,
623 &RemainingName.FileName,
624 &FinalName.FileName );
625
626 //
627 // Go ahead and look this entry up in the path table.
628 //
629
631 CleanupCompoundPathEntry = TRUE;
632
633 FoundEntry = CdFindPathEntry( IrpContext,
635 &FinalName,
638
639 //
640 // If we didn't find the entry then check if the current name
641 // is a possible short name.
642 //
643
644 if (!FoundEntry) {
645
646 ShortNameDirentOffset = CdShortNameDirentOffset( IrpContext, &FinalName.FileName );
647
648 //
649 // If there is an embedded short name offset then look for the
650 // matching long name in the directory.
651 //
652
654
655 if (CleanupFileContext) {
656
657 CdCleanupFileContext( IrpContext, &FileContext );
658 }
659
660 CdInitializeFileContext( IrpContext, &FileContext );
661 CleanupFileContext = TRUE;
662
663 FoundEntry = CdFindFileByShortName( IrpContext,
665 &FinalName,
668 &FileContext );
669
670 //
671 // If we found an entry and it is a directory then look
672 // this up in the path table.
673 //
674
675 if (FoundEntry) {
676
677 ShortNameMatch = TRUE;
678
679 if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags,
681
684
685 FoundEntry = CdFindPathEntry( IrpContext,
687 &FileContext.InitialDirent->Dirent.CdCaseFileName,
690
691 //
692 // We better find this entry.
693 //
694
695 if (!FoundEntry) {
696
698 }
699
700 //
701 // Upcase the name with the short name if case
702 // insensitive.
703 //
704
705 if (IgnoreCase) {
706
707 CdUpcaseName( IrpContext, &FinalName, &FinalName );
708 }
709
710 //
711 // We found a matching file. If we are at the last
712 // entry then break out of the loop and open the
713 // file below. Otherwise we return an error.
714 //
715
716 } else if (RemainingName.FileName.Length == 0) {
717
718 //
719 // Break out of the loop. We will process the dirent
720 // below.
721 //
722
724 break;
725
726 } else {
727
729 }
730 }
731 }
732
733 //
734 // We didn't find the name in either the path table or as
735 // a short name in a directory. If the remaining name
736 // length is zero then break out of the loop to search
737 // the directory.
738 //
739
740 if (!FoundEntry) {
741
742 if (RemainingName.FileName.Length == 0) {
743
744 break;
745
746 //
747 // Otherwise this path could not be cracked.
748 //
749
750 } else {
751
753 }
754 }
755 }
756
757 //
758 // If this is an ignore case open then copy the exact case
759 // in the file object name. If it was a short name match then
760 // the name must be upcase already.
761 //
762
763 if (IgnoreCase && !ShortNameMatch) {
764
765 RtlCopyMemory( FinalName.FileName.Buffer,
766 CompoundPathEntry.PathEntry.CdDirName.FileName.Buffer,
767 CompoundPathEntry.PathEntry.CdDirName.FileName.Length );
768 }
769
770 //
771 // If we have found the last component then open this as a directory
772 // and return to our caller.
773 //
774
775 if (RemainingName.FileName.Length == 0) {
776
778
780 }
781
782 //
783 // The only create disposition we allow is OPEN.
784 //
785
786 if ((CreateDisposition != FILE_OPEN) &&
788
790 }
791
792 try_return( Status = CdOpenDirectoryFromPathEntry( IrpContext,
793 IrpSp,
794 Vcb,
795 &CurrentFcb,
796 &FinalName,
798 ShortNameMatch,
799 &CompoundPathEntry.PathEntry,
800 TRUE,
801 RelatedCcb ));
802 }
803
804 //
805 // Otherwise open an Fcb for this intermediate index Fcb.
806 //
807
808 CdOpenDirectoryFromPathEntry( IrpContext,
809 IrpSp,
810 Vcb,
811 &CurrentFcb,
812 &FinalName,
814 ShortNameMatch,
815 &CompoundPathEntry.PathEntry,
816 FALSE,
817 NULL );
818
820 CleanupCompoundPathEntry = FALSE;
821 }
822
823 //
824 // We need to scan the current directory for a matching file name
825 // if we don't already have one.
826 //
827
828 if (!FoundEntry) {
829
830 if (CleanupFileContext) {
831
832 CdCleanupFileContext( IrpContext, &FileContext );
833 }
834
835 CdInitializeFileContext( IrpContext, &FileContext );
836 CleanupFileContext = TRUE;
837
838 //
839 // Split our search name into separate components.
840 //
841
842 CdConvertNameToCdName( IrpContext, &FinalName );
843
844 FoundEntry = CdFindFile( IrpContext,
846 &FinalName,
849 &MatchingName );
850 }
851
852 //
853 // If we didn't find a match then check if the name is invalid to
854 // determine which error code to return.
855 //
856
857 if (!FoundEntry) {
858
859 if ((CreateDisposition == FILE_OPEN) ||
861
863 }
864
865 //
866 // Any other operation return STATUS_ACCESS_DENIED.
867 //
868
870 }
871
872 //
873 // If this is a directory then the disk is corrupt because it wasn't
874 // in the Path Table.
875 //
876
877 if (FlagOn( FileContext.InitialDirent->Dirent.Flags, CD_ATTRIBUTE_DIRECTORY )) {
878
880 }
881
882 //
883 // Make sure our opener didn't want a directory.
884 //
885
886 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH ) ||
888
890 }
891
892 //
893 // The only create disposition we allow is OPEN.
894 //
895
896 if ((CreateDisposition != FILE_OPEN) &&
898
900 }
901
902 //
903 // If this is an ignore case open then copy the exact case
904 // in the file object name. Any version portion should
905 // already be upcased.
906 //
907
908 if (IgnoreCase) {
909
910 RtlCopyMemory( FinalName.FileName.Buffer,
911 MatchingName->FileName.Buffer,
912 MatchingName->FileName.Length );
913 }
914
915 //
916 // Open the file using the file context. We already have the
917 // first and last dirents.
918 //
919
920 try_return( Status = CdOpenFileFromFileContext( IrpContext,
921 IrpSp,
922 Vcb,
923 &CurrentFcb,
924 &FinalName,
928 RelatedCcb ));
929
930 try_exit: NOTHING;
931 } _SEH2_FINALLY {
932
933 //
934 // Cleanup the PathEntry if initialized.
935 //
936
937 if (CleanupCompoundPathEntry) {
938
940 }
941
942 //
943 // Cleanup the FileContext if initialized.
944 //
945
946 if (CleanupFileContext) {
947
948 CdCleanupFileContext( IrpContext, &FileContext );
949 }
950
951 //
952 // The result of this open could be success, pending or some error
953 // condition.
954 //
955
957
958
959 //
960 // In the error path we start by calling our teardown routine if we
961 // have a CurrentFcb and its not the volume Dasd Fcb.
962 //
963
964 if ((CurrentFcb != NULL) &&
965 (CurrentFcb != Vcb->VolumeDasdFcb)) {
966
967 BOOLEAN RemovedFcb;
968
969 CdTeardownStructures( IrpContext, CurrentFcb, &RemovedFcb );
970
971 if (RemovedFcb) {
972
974 }
975 }
976
977 //
978 // No need to complete the request.
979 //
980
981 IrpContext = NULL;
982 Irp = NULL;
983
984 //
985 // If we posted this request through the oplock package we need
986 // to show that there is no reason to complete the request.
987 //
988
989 } else if (Status == STATUS_PENDING) {
990
991 IrpContext = NULL;
992 Irp = NULL;
993 }
994
995 //
996 // Release the Current Fcb if still acquired.
997 //
998
999 if (CurrentFcb != NULL) {
1001 CdReleaseFcb( IrpContext, CurrentFcb );
1002 }
1003
1004 //
1005 // Release the Vcb.
1006 //
1007
1008 CdReleaseVcb( IrpContext, Vcb );
1009
1010 //
1011 // Call our completion routine. It will handle the case where either
1012 // the Irp and/or IrpContext are gone.
1013 //
1014
1015 CdCompleteRequest( IrpContext, Irp, Status );
1016 } _SEH2_END;
1017
1018 return Status;
1019}
1020
1021
1022//
1023// Local support routine
1024//
1025_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedCcb, _In_))
1026_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedCcb, _In_opt_))
1027_When_(RelatedTypeOfOpen != UnopenedFileObject, _At_(RelatedFileName, _In_))
1028_When_(RelatedTypeOfOpen == UnopenedFileObject, _At_(RelatedFileName, _In_opt_))
1030CdNormalizeFileNames (
1031 _Inout_ PIRP_CONTEXT IrpContext,
1032 _In_ PVCB Vcb,
1035 _In_ TYPE_OF_OPEN RelatedTypeOfOpen,
1036 PCCB RelatedCcb,
1037 PUNICODE_STRING RelatedFileName,
1040 )
1041
1042/*++
1043
1044Routine Description:
1045
1046 This routine is called to store the full name and upcased name into the
1047 filename buffer. We only upcase the portion yet to parse. We also
1048 check for a trailing backslash and lead-in double backslashes. This
1049 routine also verifies the mode of the related open against the name
1050 currently in the filename.
1051
1052Arguments:
1053
1054 Vcb - Vcb for this volume.
1055
1056 OpenByFileId - Indicates if the filename should be a 64 bit FileId.
1057
1058 IgnoreCase - Indicates if this open is a case-insensitive operation.
1059
1060 RelatedTypeOfOpen - Indicates the type of the related file object.
1061
1062 RelatedCcb - Ccb for the related open. Ignored if no relative open.
1063
1064 RelatedFileName - FileName buffer for related open. Ignored if no
1065 relative open.
1066
1067 FileName - FileName to update in this routine. The name should
1068 either be a 64-bit FileId or a Unicode string.
1069
1070 RemainingName - Name with the remaining portion of the name. This
1071 will begin after the related name and any separator. For a
1072 non-relative open we also step over the initial separator.
1073
1074Return Value:
1075
1076 NTSTATUS - STATUS_SUCCESS if the names are OK, appropriate error code
1077 otherwise.
1078
1079--*/
1080
1081{
1082 ULONG RemainingNameLength = 0;
1083 ULONG RelatedNameLength = 0;
1084 ULONG SeparatorLength = 0;
1085
1087
1088 UNICODE_STRING NewFileName;
1089
1090 PAGED_CODE();
1091
1092 //
1093 // If this is the first pass then we need to build the full name and
1094 // check for name compatibility.
1095 //
1096
1097 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME )) {
1098
1099 //
1100 // Deal with the regular file name case first.
1101 //
1102
1103 if (!OpenByFileId) {
1104
1105 //
1106 // This is here because the Win32 layer can't avoid sending me double
1107 // beginning backslashes.
1108 //
1109
1110 if ((FileName->Length > sizeof( WCHAR )) &&
1111 (FileName->Buffer[1] == L'\\') &&
1112 (FileName->Buffer[0] == L'\\')) {
1113
1114 //
1115 // If there are still two beginning backslashes, the name is bogus.
1116 //
1117
1118 if ((FileName->Length > 2 * sizeof( WCHAR )) &&
1119 (FileName->Buffer[2] == L'\\')) {
1120
1122 }
1123
1124 //
1125 // Slide the name down in the buffer.
1126 //
1127
1128 FileName->Length -= sizeof( WCHAR );
1129
1130 RtlMoveMemory( FileName->Buffer,
1131 FileName->Buffer + 1,
1132 FileName->Length );
1133 }
1134
1135 //
1136 // Check for a trailing backslash. Don't strip off if only character
1137 // in the full name or for relative opens where this is illegal.
1138 //
1139
1140 if (((FileName->Length > sizeof( WCHAR)) ||
1141 ((FileName->Length == sizeof( WCHAR )) && (RelatedTypeOfOpen == UserDirectoryOpen))) &&
1142 (FileName->Buffer[ (FileName->Length/2) - 1 ] == L'\\')) {
1143
1144 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TRAIL_BACKSLASH );
1145 FileName->Length -= sizeof( WCHAR );
1146 }
1147
1148 //
1149 // Remember the length we need for this portion of the name.
1150 //
1151
1152 RemainingNameLength = FileName->Length;
1153
1154 //
1155 // If this is a related file object then we verify the compatibility
1156 // of the name in the file object with the relative file object.
1157 //
1158
1159 if (RelatedTypeOfOpen != UnopenedFileObject) {
1160
1161 //
1162 // If the filename length was zero then it must be legal.
1163 // If there are characters then check with the related
1164 // type of open.
1165 //
1166
1167 if (FileName->Length != 0) {
1168
1169 //
1170 // The name length must always be zero for a volume open.
1171 //
1172
1173 if (RelatedTypeOfOpen <= UserVolumeOpen) {
1174
1176
1177 //
1178 // The remaining name cannot begin with a backslash.
1179 //
1180
1181 } else if (FileName->Buffer[0] == L'\\' ) {
1182
1184
1185 //
1186 // If the related file is a user file then there
1187 // is no file with this path.
1188 //
1189
1190 } else if (RelatedTypeOfOpen == UserFileOpen) {
1191
1193 }
1194 }
1195
1196 //
1197 // Remember the length of the related name when building
1198 // the full name. We leave the RelatedNameLength and
1199 // SeparatorLength at zero if the relative file is opened
1200 // by Id.
1201 //
1202
1203 if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) {
1204
1205 //
1206 // Add a separator if the name length is non-zero
1207 // unless the relative Fcb is at the root.
1208 //
1209
1210 if ((FileName->Length != 0) &&
1211 (RelatedCcb->Fcb != Vcb->RootIndexFcb)) {
1212
1213 SeparatorLength = sizeof( WCHAR );
1214 }
1215
1216 RelatedNameLength = RelatedFileName->Length;
1217 }
1218
1219 //
1220 // The full name is already in the filename. It must either
1221 // be length 0 or begin with a backslash.
1222 //
1223
1224 } else if (FileName->Length != 0) {
1225
1226 if (FileName->Buffer[0] != L'\\') {
1227
1229 }
1230
1231 //
1232 // We will want to trim the leading backslash from the
1233 // remaining name we return.
1234 //
1235
1236 RemainingNameLength -= sizeof( WCHAR );
1237 SeparatorLength = sizeof( WCHAR );
1238 }
1239
1240 //
1241 // Now see if the buffer is large enough to hold the full name.
1242 //
1243
1244 BufferLength = RelatedNameLength + SeparatorLength + RemainingNameLength;
1245
1246 //
1247 // Check for an overflow of the maximum filename size.
1248 //
1249
1250 if (BufferLength > MAXUSHORT) {
1251
1253 }
1254
1255 //
1256 // Now see if we need to allocate a new buffer.
1257 //
1258
1259 if (FileName->MaximumLength < BufferLength) {
1260
1263 TAG_FILE_NAME );
1264
1265 NewFileName.MaximumLength = (USHORT) BufferLength;
1266
1267 } else {
1268
1269 NewFileName.Buffer = FileName->Buffer;
1270 NewFileName.MaximumLength = FileName->MaximumLength;
1271 }
1272
1273 //
1274 // If there is a related name then we need to slide the remaining bytes up and
1275 // insert the related name. Otherwise the name is in the correct position
1276 // already.
1277 //
1278
1279 if (RelatedNameLength != 0) {
1280
1281 //
1282 // Store the remaining name in its correct position.
1283 //
1284
1285 if (RemainingNameLength != 0) {
1286
1287 RtlMoveMemory( Add2Ptr( NewFileName.Buffer, RelatedNameLength + SeparatorLength, PVOID ),
1288 FileName->Buffer,
1289 RemainingNameLength );
1290 }
1291
1292 RtlCopyMemory( NewFileName.Buffer,
1293 RelatedFileName->Buffer,
1294 RelatedNameLength );
1295
1296 //
1297 // Add the separator if needed.
1298 //
1299
1300 if (SeparatorLength != 0) {
1301
1302 *(Add2Ptr( NewFileName.Buffer, RelatedNameLength, PWCHAR )) = L'\\';
1303 }
1304
1305 //
1306 // Update the filename value we got from the user.
1307 //
1308
1309 if (NewFileName.Buffer != FileName->Buffer) {
1310
1311 if (FileName->Buffer != NULL) {
1312
1313 CdFreePool( &FileName->Buffer );
1314 }
1315
1316 FileName->Buffer = NewFileName.Buffer;
1317 FileName->MaximumLength = NewFileName.MaximumLength;
1318 }
1319
1320 //
1321 // Copy the name length to the user's filename.
1322 //
1323
1324 FileName->Length = (USHORT) (RelatedNameLength + SeparatorLength + RemainingNameLength);
1325 }
1326
1327 //
1328 // Now update the remaining name to parse.
1329 //
1330
1331 RemainingName->FileName.MaximumLength =
1332 RemainingName->FileName.Length = (USHORT) RemainingNameLength;
1333 RemainingName->VersionString.Length = 0;
1334
1335 RemainingName->FileName.Buffer = Add2Ptr( FileName->Buffer,
1336 RelatedNameLength + SeparatorLength,
1337 PWCHAR );
1338
1339 //
1340 // Upcase the name if necessary.
1341 //
1342
1343 if (IgnoreCase && (RemainingNameLength != 0)) {
1344
1345 CdUpcaseName( IrpContext,
1347 RemainingName );
1348 }
1349
1350 //
1351 // Do a quick check to make sure there are no wildcards.
1352 //
1353#ifdef _MSC_VER
1354#pragma prefast(push)
1355#pragma prefast(suppress:26000, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).")
1356#endif
1357 if (FsRtlDoesNameContainWildCards( &RemainingName->FileName )) {
1358#ifdef _MSC_VER
1359#pragma prefast(pop)
1360#endif
1361
1363 }
1364
1365 //
1366 // For the open by file Id case we verify the name really contains
1367 // a 64 bit value.
1368 //
1369
1370 } else {
1371
1372 //
1373 // Check for validity of the buffer.
1374 //
1375
1376 if (FileName->Length != sizeof( FILE_ID )) {
1377
1379 }
1380 }
1381
1382 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FULL_NAME );
1383
1384 //
1385 // If we are in the retry path then the full name is already in the
1386 // file object name. If this is a case-sensitive operation then
1387 // we need to upcase the name from the end of any related file name already stored
1388 // there.
1389 //
1390
1391 } else {
1392
1393 //
1394 // Assume there is no relative name.
1395 //
1396
1397 RemainingName->FileName = *FileName;
1398 RemainingName->VersionString.Length = 0;
1399
1400 //
1401 // Nothing to do if the name length is zero.
1402 //
1403
1404 if (RemainingName->FileName.Length != 0) {
1405
1406 //
1407 // If there is a relative name then we need to walk past it.
1408 //
1409
1410 if (RelatedTypeOfOpen != UnopenedFileObject) {
1411
1412 //
1413 // Nothing to walk past if the RelatedCcb is opened by FileId.
1414 //
1415
1416
1417 if (!FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID )) {
1418
1419 //
1420 // Related file name is a proper prefix of the full name.
1421 // We step over the related name and if we are then
1422 // pointing at a separator character we step over that.
1423 //
1424
1425 RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer,
1426 RelatedFileName->Length,
1427 PWCHAR );
1428
1429 RemainingName->FileName.Length -= RelatedFileName->Length;
1430 }
1431 }
1432
1433 //
1434 // If we are pointing at a separator character then step past that.
1435 //
1436
1437 if (RemainingName->FileName.Length != 0) {
1438
1439 if (*(RemainingName->FileName.Buffer) == L'\\') {
1440
1441 RemainingName->FileName.Buffer = Add2Ptr( RemainingName->FileName.Buffer,
1442 sizeof( WCHAR ),
1443 PWCHAR );
1444
1445 RemainingName->FileName.Length -= sizeof( WCHAR );
1446 }
1447 }
1448 }
1449
1450 //
1451 // Upcase the name if necessary.
1452 //
1453
1454 if (IgnoreCase && (RemainingName->FileName.Length != 0)) {
1455
1456 CdUpcaseName( IrpContext,
1458 RemainingName );
1459 }
1460 }
1461
1462#ifdef _MSC_VER
1463#pragma prefast(push)
1464#pragma prefast(suppress:26030, "RemainingName->FileName.Buffer = FileName.Buffer + (RelatedNameLength + SeparatorLength); FileName.MaximumLength < (RelatedNameLength + SeparatorLength + RemainingNameLength).")
1465#endif
1466 return STATUS_SUCCESS;
1467#ifdef _MSC_VER
1468#pragma prefast(pop)
1469#endif
1470}
1471
1472
1473//
1474// Local support routine
1475//
1476
1477_Requires_lock_held_(_Global_critical_region_)
1478_Acquires_exclusive_lock_((*CurrentFcb)->FcbNonpaged->FcbResource)
1480CdOpenByFileId (
1481 _In_ PIRP_CONTEXT IrpContext,
1483 _In_ PVCB Vcb,
1485 )
1486
1487/*++
1488
1489Routine Description:
1490
1491 This routine is called to open a file by the FileId. The file Id is in
1492 the FileObject name buffer and has been verified to be 64 bits.
1493
1494 We extract the Id number and then check to see whether we are opening a
1495 file or directory and compare that with the create options. If this
1496 generates no error then optimistically look up the Fcb in the Fcb Table.
1497
1498 If we don't find the Fcb then we need to carefully verify there is a file
1499 at this offset. First check whether the Parent Fcb is in the table. If
1500 not then lookup the parent at the path table offset given by file ID.
1501
1502 If found then build the Fcb from this entry and store the new Fcb in the
1503 tree.
1504
1505 We know have the parent Fcb. Do a directory scan to find the dirent at
1506 the given offset in this stream. This must point to the first entry
1507 of a valid file.
1508
1509 Finally we call our worker routine to complete the open on this Fcb.
1510
1511Arguments:
1512
1513 IrpSp - Stack location within the create Irp.
1514
1515 Vcb - Vcb for this volume.
1516
1517 CurrentFcb - Address to store the Fcb for this open. We only store the
1518 CurrentFcb here when we have acquired it so our caller knows to
1519 free or deallocate it.
1520
1521Return Value:
1522
1523 NTSTATUS - Status indicating the result of the operation.
1524
1525--*/
1526
1527{
1529
1530 BOOLEAN UnlockVcb = FALSE;
1531 BOOLEAN Found;
1532
1533 ULONG StreamOffset;
1534
1535 NODE_TYPE_CODE NodeTypeCode;
1537
1539 BOOLEAN CleanupFileContext = FALSE;
1540
1541 COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
1542 BOOLEAN CleanupCompoundPathEntry = FALSE;
1543
1544 FILE_ID FileId;
1545 FILE_ID ParentFileId;
1546
1547 PFCB NextFcb;
1548
1549 PAGED_CODE();
1550
1551 //
1552 // Extract the FileId from the FileObject.
1553 //
1554
1555 RtlCopyMemory( &FileId, IrpSp->FileObject->FileName.Buffer, sizeof( FILE_ID ));
1556
1557 //
1558 // Use a try-finally to facilitate cleanup.
1559 //
1560
1561 _SEH2_TRY {
1562
1563 //
1564 // Go ahead and figure out the TypeOfOpen and NodeType. We can
1565 // get these from the input FileId.
1566 //
1567
1568 if (CdFidIsDirectory( FileId )) {
1569
1571 NodeTypeCode = CDFS_NTC_FCB_INDEX;
1572
1573 //
1574 // If the offset isn't zero then the file Id is bad.
1575 //
1576
1577 if (CdQueryFidDirentOffset( FileId ) != 0) {
1578
1580 }
1581
1582 } else {
1583
1585 NodeTypeCode = CDFS_NTC_FCB_DATA;
1586 }
1587
1588 //
1589 // Acquire the Vcb and check if there is already an Fcb.
1590 // If not we will need to carefully verify the Fcb.
1591 // We will post the request if we don't find the Fcb and this
1592 // request can't wait.
1593 //
1594
1595 CdLockVcb( IrpContext, Vcb );
1596 UnlockVcb = TRUE;
1597
1598 NextFcb = CdLookupFcbTable( IrpContext, Vcb, FileId );
1599
1600 if (NextFcb == NULL) {
1601
1602 //
1603 // Get the path table offset from the file id.
1604 //
1605
1606 StreamOffset = CdQueryFidPathTableOffset( FileId );
1607
1608 //
1609 // Build the parent FileId for this and try looking it
1610 // up in the PathTable.
1611 //
1612
1613 CdSetFidDirentOffset( ParentFileId, 0 );
1614 CdSetFidPathTableOffset( ParentFileId, StreamOffset );
1615 CdFidSetDirectory( ParentFileId );
1616
1617 NextFcb = CdLookupFcbTable( IrpContext, Vcb, ParentFileId );
1618
1619 //
1620 // If not present then walk through the PathTable to this point.
1621 //
1622
1623 if (NextFcb == NULL) {
1624
1625 CdUnlockVcb( IrpContext, Vcb );
1626 UnlockVcb = FALSE;
1627
1628 //
1629 // Check that the path table offset lies within the path
1630 // table.
1631 //
1632
1633 if (StreamOffset > Vcb->PathTableFcb->FileSize.LowPart) {
1634
1636 }
1637
1639 CleanupCompoundPathEntry = TRUE;
1640
1641 //
1642 // Start at the first entry in the PathTable.
1643 //
1644
1645 CdLookupPathEntry( IrpContext,
1646 Vcb->PathTableFcb->StreamOffset,
1647 1,
1648 TRUE,
1650
1651 //
1652 // Continue looking until we have passed our target offset.
1653 //
1654
1655 while (TRUE) {
1656
1657 //
1658 // Move to the next entry.
1659 //
1660
1661 Found = CdLookupNextPathEntry( IrpContext,
1662 &CompoundPathEntry.PathContext,
1663 &CompoundPathEntry.PathEntry );
1664
1665 //
1666 // If we didn't find the entry or are beyond it then the
1667 // input Id is invalid.
1668 //
1669
1670 if (!Found ||
1671 (CompoundPathEntry.PathEntry.PathTableOffset > StreamOffset)) {
1672
1674 }
1675 }
1676
1677 //
1678 // If the FileId specified a directory then we have found
1679 // the entry. Make sure our caller wanted to open a directory.
1680 //
1681
1682 if ((TypeOfOpen == UserDirectoryOpen) &&
1684
1686 }
1687
1688 //
1689 // Lock the Vcb and create the Fcb if necessary.
1690 //
1691
1692 CdLockVcb( IrpContext, Vcb );
1693 UnlockVcb = TRUE;
1694
1695 NextFcb = CdCreateFcb( IrpContext, ParentFileId, NodeTypeCode, &Found );
1696
1697 //
1698 // It's possible that someone got in here ahead of us.
1699 //
1700
1701 if (!Found) {
1702
1703 CdInitializeFcbFromPathEntry( IrpContext,
1704 NextFcb,
1705 NULL,
1706 &CompoundPathEntry.PathEntry );
1707 }
1708
1709 //
1710 // If the user wanted to open a directory then we have found
1711 // it. Store this Fcb into the CurrentFcb and skip the
1712 // directory scan.
1713 //
1714
1716
1717 *CurrentFcb = NextFcb;
1718 NextFcb = NULL;
1719 }
1720 }
1721
1722 //
1723 // Perform the directory scan if we don't already have our target.
1724 //
1725
1726 if (NextFcb != NULL) {
1727
1728 //
1729 // Acquire the parent. We currently own the Vcb lock so
1730 // do this without waiting first.
1731 //
1732
1733 if (!CdAcquireFcbExclusive( IrpContext,
1734 NextFcb,
1735 TRUE )) {
1736
1737 NextFcb->FcbReference += 1;
1738 CdUnlockVcb( IrpContext, Vcb );
1739
1740 CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
1741
1742 CdLockVcb( IrpContext, Vcb );
1743 NextFcb->FcbReference -= 1;
1744 CdUnlockVcb( IrpContext, Vcb );
1745
1746 } else {
1747
1748 CdUnlockVcb( IrpContext, Vcb );
1749 }
1750
1751 UnlockVcb = FALSE;
1752
1753 //
1754 // Set up the CurrentFcb pointers. We know there was
1755 // no previous parent in this case.
1756 //
1757
1758 *CurrentFcb = NextFcb;
1759
1760 //
1761 // Calculate the offset in the stream.
1762 //
1763
1764 StreamOffset = CdQueryFidDirentOffset( FileId );
1765
1766 //
1767 // Create the stream file if it doesn't exist. This will update
1768 // the Fcb with the size from the self entry.
1769 //
1770
1771 CdVerifyOrCreateDirStreamFile( IrpContext, NextFcb);
1772
1773 //
1774 // If our offset is beyond the end of the directory then the
1775 // FileId is invalid.
1776 //
1777
1778 if (StreamOffset > NextFcb->FileSize.LowPart) {
1779
1781 }
1782
1783 //
1784 // Otherwise position ourselves at the self entry and walk
1785 // through dirent by dirent until this location is found.
1786 //
1787
1788 CdInitializeFileContext( IrpContext, &FileContext );
1789 CdLookupInitialFileDirent( IrpContext,
1790 NextFcb,
1791 &FileContext,
1792 NextFcb->StreamOffset );
1793
1794 CleanupFileContext = TRUE;
1795
1796 while (TRUE) {
1797
1798 //
1799 // Move to the first entry of the next file.
1800 //
1801
1803 NextFcb,
1804 &FileContext );
1805
1806 //
1807 // If we didn't find the entry or are beyond it then the
1808 // input Id is invalid.
1809 //
1810
1811 if (!Found ||
1812 (FileContext.InitialDirent->Dirent.DirentOffset > StreamOffset)) {
1813
1815 }
1816 }
1817
1818 //
1819 // This better not be a directory. Directory FileIds must
1820 // refer to the self entry for directories.
1821 //
1822
1823 if (FlagOn( FileContext.InitialDirent->Dirent.DirentFlags,
1825
1827 }
1828
1829 //
1830 // Check that our caller wanted to open a file.
1831 //
1832
1834
1836 }
1837
1838 //
1839 // Otherwise we want to collect all of the dirents for this file
1840 // and create an Fcb with this.
1841 //
1842
1843 CdLookupLastFileDirent( IrpContext, NextFcb, &FileContext );
1844
1845 CdLockVcb( IrpContext, Vcb );
1846 UnlockVcb = TRUE;
1847
1848 NextFcb = CdCreateFcb( IrpContext, FileId, NodeTypeCode, &Found );
1849
1850 //
1851 // It's possible that someone has since created this Fcb since we
1852 // first checked. If so then can simply use this. Otherwise
1853 // we need to initialize a new Fcb and attach it to our parent
1854 // and insert it into the Fcb Table.
1855 //
1856
1857 if (!Found) {
1858
1860 NextFcb,
1861 *CurrentFcb,
1862 &FileContext );
1863 }
1864 }
1865
1866 //
1867 // We have the Fcb. Check that the type of the file is compatible with
1868 // the desired type of file to open.
1869 //
1870
1871 } else {
1872
1874
1876
1878 }
1879
1880 } else if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
1881
1883 }
1884 }
1885
1886 //
1887 // If we have a the previous Fcb and have inserted the next Fcb into
1888 // the Fcb Table. It is safe to release the current Fcb if present
1889 // since it is referenced through the child Fcb.
1890 //
1891
1892 if (*CurrentFcb != NULL) {
1893
1894 CdReleaseFcb( IrpContext, *CurrentFcb );
1895 }
1896
1897 //
1898 // We now know the Fcb and currently hold the Vcb lock.
1899 // Try to acquire this Fcb without waiting. Otherwise we
1900 // need to reference it, drop the Vcb, acquire the Fcb and
1901 // then dereference the Fcb.
1902 //
1903
1904 if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) {
1905
1906 NextFcb->FcbReference += 1;
1907
1908 CdUnlockVcb( IrpContext, Vcb );
1909
1910 CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
1911
1912 CdLockVcb( IrpContext, Vcb );
1913 NextFcb->FcbReference -= 1;
1914 CdUnlockVcb( IrpContext, Vcb );
1915
1916 } else {
1917
1918 CdUnlockVcb( IrpContext, Vcb );
1919 }
1920
1921 UnlockVcb = FALSE;
1922
1923 //
1924 // Move to this Fcb.
1925 //
1926
1927 *CurrentFcb = NextFcb;
1928
1929 // Lock object is acquired using internal state
1931
1932 //
1933 // Check the requested access on this Fcb.
1934 //
1935
1936 if (!CdIllegalFcbAccess( IrpContext,
1937 TypeOfOpen,
1938 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
1939
1940 //
1941 // Call our worker routine to complete the open.
1942 //
1943
1944 Status = CdCompleteFcbOpen( IrpContext,
1945 IrpSp,
1946 Vcb,
1947 CurrentFcb,
1948 TypeOfOpen,
1950 IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
1951
1952 }
1953
1954 try_exit: NOTHING;
1955 } _SEH2_FINALLY {
1956
1957 if (UnlockVcb) {
1958
1959 CdUnlockVcb( IrpContext, Vcb );
1960 }
1961
1962 if (CleanupFileContext) {
1963
1964 CdCleanupFileContext( IrpContext, &FileContext );
1965 }
1966
1967 if (CleanupCompoundPathEntry) {
1968
1970 }
1971 } _SEH2_END;
1972
1973 return Status;
1974}
1975
1976
1977//
1978// Local support routine
1979//
1980
1981_Requires_lock_held_(_Global_critical_region_)
1983CdOpenExistingFcb (
1984 _In_ PIRP_CONTEXT IrpContext,
1989 _In_opt_ PCCB RelatedCcb
1990 )
1991
1992/*++
1993
1994Routine Description:
1995
1996 This routine is called to open an Fcb which is already in the Fcb table.
1997 We will verify the access to the file and then call our worker routine
1998 to perform the final operations.
1999
2000Arguments:
2001
2002 IrpSp - Pointer to the stack location for this open.
2003
2004 CurrentFcb - Address of Fcb to open. We will clear this if the Fcb
2005 is released here.
2006
2007 TypeOfOpen - Indicates whether we are opening a file, directory or volume.
2008
2009 IgnoreCase - Indicates if this open is case-insensitive.
2010
2011 RelatedCcb - Ccb for related file object if relative open. We use
2012 this when setting the Ccb flags for this open. It will tell
2013 us whether the name currently in the file object is relative or
2014 absolute.
2015
2016Return Value:
2017
2018 NTSTATUS - Status indicating the result of the operation.
2019
2020--*/
2021
2022{
2023 ULONG CcbFlags = 0;
2024
2026
2027 PAGED_CODE();
2028
2029 //
2030 // Check that the desired access is legal.
2031 //
2032
2033 if (!CdIllegalFcbAccess( IrpContext,
2034 TypeOfOpen,
2035 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
2036
2037 //
2038 // Set the Ignore case.
2039 //
2040
2041 if (IgnoreCase) {
2042
2043 SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE );
2044 }
2045
2046 //
2047 // Check the related Ccb to see if this was an OpenByFileId and
2048 // whether there was a version.
2049 //
2050
2051 if (ARGUMENT_PRESENT( RelatedCcb )) {
2052
2053 SetFlag( CcbFlags, FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_WITH_VERSION ));
2054
2055
2056 if (FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) {
2057
2059 }
2060 }
2061
2062 //
2063 // Call our worker routine to complete the open.
2064 //
2065
2066 Status = CdCompleteFcbOpen( IrpContext,
2067 IrpSp,
2068 (*CurrentFcb)->Vcb,
2069 CurrentFcb,
2070 TypeOfOpen,
2071 CcbFlags,
2072 IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
2073 }
2074
2075 return Status;
2076}
2077
2078
2079//
2080// Local support routine
2081//
2082
2083_Requires_lock_held_(_Global_critical_region_)
2084_Acquires_lock_((*CurrentFcb)->FcbNonpaged->FcbResource)
2086CdOpenDirectoryFromPathEntry (
2087 _In_ PIRP_CONTEXT IrpContext,
2089 _In_ PVCB Vcb,
2093 _In_ BOOLEAN ShortNameMatch,
2094 _In_ PPATH_ENTRY PathEntry,
2095 _In_ BOOLEAN PerformUserOpen,
2096 _In_opt_ PCCB RelatedCcb
2097 )
2098
2099/*++
2100
2101Routine Description:
2102
2103 This routine is called to open a directory where the directory was found
2104 in the path table. This routine is called in the case where this is the
2105 file to open for the user and where this is an intermediate node in the
2106 full path to open.
2107
2108 We first check that the desired access is legal for a directory. Then we
2109 construct the FileId for this and do a check to see if it is the Fcb
2110 Table. It is always possible that either it was created since or simply
2111 wasn't in the prefix table at the time of the prefix table search.
2112 Initialize the Fcb and store into the FcbTable if not present.
2113
2114 Next we will add this to the prefix table of our parent if needed.
2115
2116 Once we know that the new Fcb has been initialized then we move our pointer
2117 in the tree down to this position.
2118
2119 This routine does not own the Vcb lock on entry. We must be sure to release
2120 it on exit.
2121
2122Arguments:
2123
2124 IrpSp - Stack location for this request.
2125
2126 Vcb - Vcb for this volume.
2127
2128 CurrentFcb - On input this is the parent of the Fcb to open. On output we
2129 store the Fcb for the file being opened.
2130
2131 DirName - This is always the exact name used to reach this file.
2132
2133 IgnoreCase - Indicates the type of case match for the open.
2134
2135 ShortNameMatch - Indicates if we are opening via the short name.
2136
2137 PathEntry - Path entry for the entry found.
2138
2139 PerformUserOpen - TRUE if we are to open this for a user, FALSE otherwise.
2140
2141 RelatedCcb - RelatedCcb for relative file object used to make this open.
2142
2143Return Value:
2144
2145 NTSTATUS - Status indicating the result of the operation.
2146
2147--*/
2148
2149{
2150 ULONG CcbFlags = 0;
2151 FILE_ID FileId;
2152
2153 BOOLEAN UnlockVcb = FALSE;
2154 BOOLEAN FcbExisted;
2155
2156 PFCB NextFcb;
2158
2160
2161 PAGED_CODE();
2162
2163 //
2164 // Check for illegal access to this file.
2165 //
2166
2167 if (PerformUserOpen &&
2168 CdIllegalFcbAccess( IrpContext,
2170 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
2171
2172 return STATUS_ACCESS_DENIED;
2173 }
2174
2175 //
2176 // Use a try-finally to facilitate cleanup.
2177 //
2178
2179 _SEH2_TRY {
2180
2181 //
2182 // Check the related Ccb to see if this was an OpenByFileId.
2183 //
2184
2185 if (ARGUMENT_PRESENT( RelatedCcb ) &&
2187
2189 }
2190
2191 if (IgnoreCase) {
2192
2193 SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE );
2194 }
2195
2196 //
2197 // Build the file Id for this file.
2198 //
2199
2200 FileId.QuadPart = 0;
2201 CdSetFidPathTableOffset( FileId, PathEntry->PathTableOffset );
2202 CdFidSetDirectory( FileId );
2203
2204 //
2205 // Lock the Vcb so we can examine the Fcb Table.
2206 //
2207
2208 CdLockVcb( IrpContext, Vcb );
2209 UnlockVcb = TRUE;
2210
2211 //
2212 // Get the Fcb for this directory.
2213 //
2214
2215 NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_INDEX, &FcbExisted );
2216
2217 //
2218 // If the Fcb was created here then initialize from the values in the
2219 // path table entry.
2220 //
2221
2222 if (!FcbExisted) {
2223
2224 CdInitializeFcbFromPathEntry( IrpContext, NextFcb, *CurrentFcb, PathEntry );
2225 }
2226
2227 //
2228 // Now try to acquire the new Fcb without waiting. We will reference
2229 // the Fcb and retry with wait if unsuccessful.
2230 //
2231
2232 if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) {
2233
2234 NextFcb->FcbReference += 1;
2235
2236 CdUnlockVcb( IrpContext, Vcb );
2237
2238 CdReleaseFcb( IrpContext, *CurrentFcb );
2239 CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
2240 CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE );
2241
2242 CdLockVcb( IrpContext, Vcb );
2243 NextFcb->FcbReference -= 1;
2244 CdUnlockVcb( IrpContext, Vcb );
2245
2246 } else {
2247
2248 //
2249 // Unlock the Vcb and move down to this new Fcb. Remember that we still
2250 // own the parent however.
2251 //
2252
2253 CdUnlockVcb( IrpContext, Vcb );
2254 }
2255
2256 UnlockVcb = FALSE;
2257
2259 *CurrentFcb = NextFcb;
2260
2261 // Lock object is acquired using internal state
2263
2264 //
2265 // Store this name into the prefix table for the parent.
2266 //
2267
2268 if (ShortNameMatch) {
2269
2270 //
2271 // Make sure the exact case is always in the tree.
2272 //
2273
2274 CdInsertPrefix( IrpContext,
2275 NextFcb,
2276 DirName,
2277 FALSE,
2278 TRUE,
2279 ParentFcb );
2280
2281 if (IgnoreCase) {
2282
2283 CdInsertPrefix( IrpContext,
2284 NextFcb,
2285 DirName,
2286 TRUE,
2287 TRUE,
2288 ParentFcb );
2289 }
2290
2291 } else {
2292
2293 //
2294 // Make sure the exact case is always in the tree.
2295 //
2296
2297 CdInsertPrefix( IrpContext,
2298 NextFcb,
2299 &PathEntry->CdDirName,
2300 FALSE,
2301 FALSE,
2302 ParentFcb );
2303
2304 if (IgnoreCase) {
2305
2306 CdInsertPrefix( IrpContext,
2307 NextFcb,
2308 &PathEntry->CdCaseDirName,
2309 TRUE,
2310 FALSE,
2311 ParentFcb );
2312 }
2313 }
2314
2315 //
2316 // Release the parent Fcb at this point.
2317 //
2318
2319 CdReleaseFcb( IrpContext, ParentFcb );
2320 ParentFcb = NULL;
2321
2322 //
2323 // Call our worker routine to complete the open.
2324 //
2325
2326 if (PerformUserOpen) {
2327
2328 Status = CdCompleteFcbOpen( IrpContext,
2329 IrpSp,
2330 Vcb,
2331 CurrentFcb,
2333 CcbFlags,
2334 IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
2335 }
2336
2337 } _SEH2_FINALLY {
2338
2339 //
2340 // Unlock the Vcb if held.
2341 //
2342
2343 if (UnlockVcb) {
2344
2345 CdUnlockVcb( IrpContext, Vcb );
2346 }
2347
2348 //
2349 // Release the parent if held.
2350 //
2351
2352 if (ParentFcb != NULL) {
2353
2354 CdReleaseFcb( IrpContext, ParentFcb );
2355 }
2356 } _SEH2_END;
2357
2358 return Status;
2359}
2360
2361
2362//
2363// Local support routine
2364//
2365
2366_Requires_lock_held_(_Global_critical_region_)
2368CdOpenFileFromFileContext (
2369 _In_ PIRP_CONTEXT IrpContext,
2371 _In_ PVCB Vcb,
2375 _In_ BOOLEAN ShortNameMatch,
2377 _In_opt_ PCCB RelatedCcb
2378 )
2379
2380/*++
2381
2382Routine Description:
2383
2384 This routine is called to open a file where the file was found in a directory scan.
2385 This should only be for a file in the case since we will find the directories in the
2386 path table.
2387
2388 We first check that the desired access is legal for this file. Then we
2389 construct the FileId for this and do a check to see if it is the Fcb
2390 Table. It is always possible that either it was created since or simply
2391 wasn't in the prefix table at the time of the prefix table search.
2392 Initialize the Fcb and store into the FcbTable if not present.
2393
2394 Next we will add this to the prefix table of our parent if needed.
2395
2396 Once we know that the new Fcb has been initialized then we move our pointer
2397 in the tree down to this position.
2398
2399 This routine does not own the Vcb lock on entry. We must be sure to release
2400 it on exit.
2401
2402Arguments:
2403
2404 IrpSp - Stack location for this request.
2405
2406 Vcb - Vcb for the current volume.
2407
2408 CurrentFcb - On input this is the parent of the Fcb to open. On output we
2409 store the Fcb for the file being opened.
2410
2411 FileName - This is always the exact name used to reach this file.
2412
2413 IgnoreCase - Indicates the type of case of CaseName above.
2414
2415 ShortNameMatch - Indicates if we are opening via the short name.
2416
2417 FileContext - This is the context used to find the file.
2418
2419 RelatedCcb - RelatedCcb for relative file object used to make this open.
2420
2421Return Value:
2422
2423 NTSTATUS - Status indicating the result of the operation.
2424
2425--*/
2426
2427{
2428 ULONG CcbFlags = 0;
2429 FILE_ID FileId;
2430
2431 BOOLEAN UnlockVcb = FALSE;
2432 BOOLEAN FcbExisted;
2433
2434 PFCB NextFcb;
2436
2438
2439 PAGED_CODE();
2440
2441 //
2442 // Check for illegal access to this file.
2443 //
2444
2445 if (CdIllegalFcbAccess( IrpContext,
2447 IrpSp->Parameters.Create.SecurityContext->DesiredAccess )) {
2448
2449 return STATUS_ACCESS_DENIED;
2450 }
2451
2452 //
2453 // Use a try-finally to facilitate cleanup.
2454 //
2455
2456 _SEH2_TRY {
2457
2458 //
2459 // Check if a version number was used to open this file.
2460 //
2461
2462 if (FileName->VersionString.Length != 0) {
2463
2465 }
2466
2467 //
2468 // Check the related Ccb to see if this was an OpenByFileId.
2469 //
2470
2471 if (ARGUMENT_PRESENT( RelatedCcb ) &&
2473
2475 }
2476
2477 if (IgnoreCase) {
2478
2479 SetFlag( CcbFlags, CCB_FLAG_IGNORE_CASE );
2480 }
2481
2482 //
2483 // Build the file Id for this file. We can use the path table offset from the
2484 // parent and the directory offset from the dirent.
2485 //
2486
2487 CdSetFidPathTableOffset( FileId, CdQueryFidPathTableOffset( (*CurrentFcb)->FileId ));
2488 CdSetFidDirentOffset( FileId, FileContext->InitialDirent->Dirent.DirentOffset );
2489
2490 //
2491 // Lock the Vcb so we can examine the Fcb Table.
2492 //
2493
2494 CdLockVcb( IrpContext, Vcb );
2495 UnlockVcb = TRUE;
2496
2497 //
2498 // Get the Fcb for this file.
2499 //
2500
2501 NextFcb = CdCreateFcb( IrpContext, FileId, CDFS_NTC_FCB_DATA, &FcbExisted );
2502
2503 //
2504 // If the Fcb was created here then initialize from the values in the
2505 // dirent.
2506 //
2507
2508 if (!FcbExisted) {
2509
2511 NextFcb,
2512 *CurrentFcb,
2513 FileContext );
2514 }
2515
2516 //
2517 // Now try to acquire the new Fcb without waiting. We will reference
2518 // the Fcb and retry with wait if unsuccessful.
2519 //
2520
2521 if (!CdAcquireFcbExclusive( IrpContext, NextFcb, TRUE )) {
2522
2523 NextFcb->FcbReference += 1;
2524
2525 CdUnlockVcb( IrpContext, Vcb );
2526
2527 CdReleaseFcb( IrpContext, *CurrentFcb );
2528 CdAcquireFcbExclusive( IrpContext, NextFcb, FALSE );
2529 CdAcquireFcbExclusive( IrpContext, *CurrentFcb, FALSE );
2530
2531 CdLockVcb( IrpContext, Vcb );
2532 NextFcb->FcbReference -= 1;
2533 CdUnlockVcb( IrpContext, Vcb );
2534
2535 } else {
2536
2537 //
2538 // Unlock the Vcb and move down to this new Fcb. Remember that we still
2539 // own the parent however.
2540 //
2541
2542 CdUnlockVcb( IrpContext, Vcb );
2543 }
2544
2545 UnlockVcb = FALSE;
2546
2548 *CurrentFcb = NextFcb;
2549
2550 //
2551 // Store this name into the prefix table for the parent.
2552 //
2553
2554
2555 if (ShortNameMatch) {
2556
2557 //
2558 // Make sure the exact case is always in the tree.
2559 //
2560
2561 CdInsertPrefix( IrpContext,
2562 NextFcb,
2563 FileName,
2564 FALSE,
2565 TRUE,
2566 ParentFcb );
2567
2568 if (IgnoreCase) {
2569
2570 CdInsertPrefix( IrpContext,
2571 NextFcb,
2572 FileName,
2573 TRUE,
2574 TRUE,
2575 ParentFcb );
2576 }
2577
2578 //
2579 // Insert this into the prefix table if we found this without
2580 // using a version string.
2581 //
2582
2583 } else if (FileName->VersionString.Length == 0) {
2584
2585 //
2586 // Make sure the exact case is always in the tree.
2587 //
2588
2589 CdInsertPrefix( IrpContext,
2590 NextFcb,
2591 &FileContext->InitialDirent->Dirent.CdFileName,
2592 FALSE,
2593 FALSE,
2594 ParentFcb );
2595
2596 if (IgnoreCase) {
2597
2598 CdInsertPrefix( IrpContext,
2599 NextFcb,
2600 &FileContext->InitialDirent->Dirent.CdCaseFileName,
2601 TRUE,
2602 FALSE,
2603 ParentFcb );
2604 }
2605 }
2606
2607 //
2608 // Release the parent Fcb at this point.
2609 //
2610
2612 CdReleaseFcb( IrpContext, ParentFcb );
2613 ParentFcb = NULL;
2614
2615 //
2616 // Call our worker routine to complete the open.
2617 //
2618
2619 Status = CdCompleteFcbOpen( IrpContext,
2620 IrpSp,
2621 Vcb,
2622 CurrentFcb,
2624 CcbFlags,
2625 IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
2626
2627 } _SEH2_FINALLY {
2628
2629 //
2630 // Unlock the Vcb if held.
2631 //
2632
2633 if (UnlockVcb) {
2634
2635 CdUnlockVcb( IrpContext, Vcb );
2636 }
2637
2638 //
2639 // Release the parent if held.
2640 //
2641
2642 if (ParentFcb != NULL) {
2643
2644 CdReleaseFcb( IrpContext, ParentFcb );
2645 }
2646 } _SEH2_END;
2647
2648 return Status;
2649}
2650
2651
2652//
2653// Local support routine
2654//
2655
2656_Requires_lock_held_(_Global_critical_region_)
2658CdCompleteFcbOpen (
2659 _In_ PIRP_CONTEXT IrpContext,
2661 _In_ PVCB Vcb,
2664 _In_ ULONG UserCcbFlags,
2666 )
2667
2668/*++
2669
2670Routine Description:
2671
2672 This is the worker routine which takes an existing Fcb and completes
2673 the open. We will do any necessary oplock checks and sharing checks.
2674 Finally we will create the Ccb and update the file object and any
2675 file object flags.
2676
2677Arguments:
2678
2679 IrpSp - Stack location for the current request.
2680
2681 Vcb - Vcb for the current volume.
2682
2683 CurrentFcb - Address of pointer to Fcb to open. We clear this field if
2684 we release the resource for this file.
2685
2686 TypeOfOpen - Type of open for this request.
2687
2688 UserCcbFlags - Flags to OR into the Ccb flags.
2689
2690 DesiredAccess - Desired access for this open.
2691
2692Return Value:
2693
2694 NTSTATUS - STATUS_SUCCESS if we complete this request, STATUS_PENDING if
2695 the oplock package takes the Irp or SHARING_VIOLATION if there is a
2696 sharing check conflict.
2697
2698--*/
2699
2700{
2702 NTSTATUS OplockStatus = STATUS_SUCCESS;
2704
2705 BOOLEAN LockVolume = FALSE;
2706
2707 PFCB Fcb = *CurrentFcb;
2708 PCCB Ccb;
2709
2710 PAGED_CODE();
2711
2712 //
2713 // Expand maximum allowed to something sensible for share access checking
2714 //
2715
2717
2724 FILE_APPEND_DATA) : 0) |
2726 DELETE |
2727 WRITE_DAC );
2728 }
2729
2730 //
2731 // If this a volume open and the user wants to lock the volume then
2732 // purge and lock the volume.
2733 //
2734
2735 if ((TypeOfOpen <= UserVolumeOpen) &&
2736 !FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ )) {
2737
2738 //
2739 // If there are open handles then fail this immediately.
2740 //
2741
2742 if (Vcb->VcbCleanup != 0) {
2743
2745 }
2746
2747 //
2748 // If we can't wait then force this to be posted.
2749 //
2750
2751 if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
2752
2753 CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
2754 }
2755
2756 LockVolume = TRUE;
2757
2758 //
2759 // Purge the volume and make sure all of the user references
2760 // are gone.
2761 //
2762
2763 Status = CdPurgeVolume( IrpContext, Vcb, FALSE );
2764
2765 if (Status != STATUS_SUCCESS) {
2766
2767 return Status;
2768 }
2769
2770 //
2771 // Now force all of the delayed close operations to go away.
2772 //
2773
2774 CdFspClose( Vcb );
2775
2776 if (Vcb->VcbUserReference > CDFS_RESIDUAL_USER_REFERENCE) {
2777
2779 }
2780 }
2781
2782 //
2783 // If the Fcb already existed then we need to check the oplocks and
2784 // the share access.
2785 //
2786
2787 if (Fcb->FcbCleanup != 0) {
2788
2789 //
2790 // If this is a user file open then check whether there are any
2791 // batch oplock.
2792 //
2793
2794 if (TypeOfOpen == UserFileOpen) {
2795
2796 //
2797 // Store the address of the Fcb for a possible teardown into
2798 // the IrpContext. We will release this in the call to
2799 // prepost the Irp.
2800 //
2801
2802 IrpContext->TeardownFcb = CurrentFcb;
2803
2805
2806 //
2807 // We remember if a batch oplock break is underway for the
2808 // case where the sharing check fails.
2809 //
2810
2812
2813 OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb),
2814 IrpContext->Irp,
2815 IrpContext,
2816 (PVOID)CdOplockComplete, /* ReactOS Change: GCC "assignment from incompatible pointer type" */
2817 (PVOID)CdPrePostIrp ); /* ReactOS Change: GCC "assignment from incompatible pointer type" */
2818
2819 if (OplockStatus == STATUS_PENDING) {
2820
2821 return STATUS_PENDING;
2822 }
2823 }
2824
2825 //
2826 // Check the share access before breaking any exclusive oplocks.
2827 //
2828
2830 IrpSp->Parameters.Create.ShareAccess,
2832 &Fcb->ShareAccess,
2833 FALSE );
2834
2835 if (!NT_SUCCESS( Status )) {
2836
2837 return Status;
2838 }
2839
2840 //
2841 // Now check that we can continue based on the oplock state of the
2842 // file.
2843 //
2844
2845 OplockStatus = FsRtlCheckOplock( CdGetFcbOplock(Fcb),
2846 IrpContext->Irp,
2847 IrpContext,
2848 (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
2849 (PVOID)CdPrePostIrp );/* ReactOS Change: GCC "assignment from incompatible pointer type" */
2850
2851 if (OplockStatus == STATUS_PENDING) {
2852
2853 return STATUS_PENDING;
2854 }
2855
2856 IrpContext->TeardownFcb = NULL;
2857
2858 //
2859 // Otherwise just do the sharing check.
2860 //
2861
2862 } else {
2863
2865 IrpSp->Parameters.Create.ShareAccess,
2867 &Fcb->ShareAccess,
2868 FALSE );
2869
2870 if (!NT_SUCCESS( Status )) {
2871
2872 return Status;
2873 }
2874 }
2875 }
2876
2877 //
2878 // Create the Ccb now.
2879 //
2880
2881 Ccb = CdCreateCcb( IrpContext, Fcb, UserCcbFlags );
2882
2883 //
2884 // Update the share access.
2885 //
2886
2887 if (Fcb->FcbCleanup == 0) {
2888
2890 IrpSp->Parameters.Create.ShareAccess,
2892 &Fcb->ShareAccess );
2893
2894 } else {
2895
2897 }
2898
2899 //
2900 // Set the file object type.
2901 //
2902
2903 CdSetFileObject( IrpContext, IrpSp->FileObject, TypeOfOpen, Fcb, Ccb );
2904
2905 //
2906 // Set the appropriate cache flags for a user file object.
2907 //
2908
2909 if (TypeOfOpen == UserFileOpen) {
2910
2912
2914
2915 } else {
2916
2918 }
2919 }
2920 else if (TypeOfOpen == UserVolumeOpen) {
2921
2923 }
2924
2925 //
2926 // Update the open and cleanup counts. Check the fast io state here.
2927 //
2928
2929 CdLockVcb( IrpContext, Vcb );
2930
2931 CdIncrementCleanupCounts( IrpContext, Fcb );
2932 CdIncrementReferenceCounts( IrpContext, Fcb, 1, 1 );
2933
2934 if (LockVolume) {
2935
2936 Vcb->VolumeLockFileObject = IrpSp->FileObject;
2937 SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
2938 }
2939
2940 CdUnlockVcb( IrpContext, Vcb );
2941
2942 CdLockFcb( IrpContext, Fcb );
2943
2944 if (TypeOfOpen == UserFileOpen) {
2945
2946 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
2947
2948 } else {
2949
2950 Fcb->IsFastIoPossible = FastIoIsNotPossible;
2951 }
2952
2953 CdUnlockFcb( IrpContext, Fcb );
2954
2955 //
2956 // Show that we opened the file.
2957 //
2958
2959 IrpContext->Irp->IoStatus.Information = Information;
2960
2961 //
2962 // Point to the section object pointer in the non-paged Fcb.
2963 //
2964
2965 IrpSp->FileObject->SectionObjectPointer = &Fcb->FcbNonpaged->SegmentObject;
2966 return OplockStatus;
2967}
2968
2969
2970
2971
2972
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define CD_ATTRIBUTE_DIRECTORY
Definition: cd.h:354
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
return Found
Definition: dirsup.c:1270
#define CdIllegalFcbAccess(IC, T, DA)
Definition: cdprocs.h:135
static INLINE VOID CdVerifyOrCreateDirStreamFile(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: cdprocs.h:242
VOID CdInitializeFcbFromFileContext(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ PFCB ParentFcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: strucsup.c:1225
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1044
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
BOOLEAN CdLookupNextPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENUM_CONTEXT PathContext, _Inout_ PPATH_ENTRY PathEntry)
Definition: pathsup.c:207
PCCB CdCreateCcb(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG Flags)
Definition: strucsup.c:1405
#define TAG_FILE_NAME
Definition: cdprocs.h:93
#define CdInitializeCompoundPathEntry(IC, CP)
Definition: cdprocs.h:763
VOID CdFspClose(_In_opt_ PVCB Vcb)
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
Definition: cdprocs.h:740
VOID CdDissectName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PUNICODE_STRING RemainingName, _Out_ PUNICODE_STRING FinalName)
Definition: namesup.c:301
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:985
#define CdReleaseFcb(IC, F)
Definition: cdprocs.h:1012
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT _Out_ PCD_NAME * MatchingName
Definition: cdprocs.h:444
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411
VOID CdLookupLastFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1426
@ UnopenedFileObject
Definition: cdprocs.h:573
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1023
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
PFCB CdLookupFcbTable(_In_ PIRP_CONTEXT IrpContext, _In_ PVCB Vcb, _In_ FILE_ID FileId)
Definition: strucsup.c:2107
#define CdGetFcbOplock(F)
Definition: cdprocs.h:1081
#define CdInitializeFileContext(IC, FC)
Definition: cdprocs.h:527
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: cdprocs.h:442
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:982
VOID CdInitializeFcbFromPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_opt_ PFCB ParentFcb, _In_ PPATH_ENTRY PathEntry)
Definition: strucsup.c:1136
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1028
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define CdLookupInitialFileDirent(IC, F, FC, DO)
Definition: cdprocs.h:551
BOOLEAN CdLookupNextInitialFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _Inout_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1275
#define CdCleanupCompoundPathEntry(IC, CP)
Definition: cdprocs.h:766
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:979
#define CdAcquireFcbExclusive(IC, F, I)
Definition: cdprocs.h:1006
PFCB CdCreateFcb(_In_ PIRP_CONTEXT IrpContext, _In_ FILE_ID FileId, _In_ NODE_TYPE_CODE NodeTypeCode, _Out_opt_ PBOOLEAN FcbExisted)
Definition: strucsup.c:986
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFCB * CurrentFcb
Definition: cdprocs.h:801
ULONG CdShortNameDirentOffset(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING Name)
Definition: namesup.c:955
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _In_ ULONG ShortNameDirentOffset
Definition: cdprocs.h:462
#define CdIncrementCleanupCounts(IC, F)
Definition: cdprocs.h:1305
#define CdFreePool(x)
Definition: cdprocs.h:2190
#define try_return(S)
Definition: cdprocs.h:2179
VOID CdInsertPrefix(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ PCD_NAME Name, _In_ BOOLEAN IgnoreCase, _In_ BOOLEAN ShortNameMatch, _Inout_ PFCB ParentFcb)
Definition: prefxsup.c:52
#define CdPagedPool
Definition: cdprocs.h:1380
VOID CdLookupPathEntry(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG PathEntryOffset, _In_ ULONG Ordinal, _In_ BOOLEAN VerifyBounds, _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry)
#define CdIsFastIoPossible(F)
Definition: cdprocs.h:2015
VOID CdCleanupFileContext(_In_ PIRP_CONTEXT IrpContext, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1636
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1060
#define CdIncrementReferenceCounts(IC, F, C, UC)
Definition: cdprocs.h:1317
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define CCB_FLAG_IGNORE_CASE
Definition: cdstruc.h:1105
#define IRP_CONTEXT_FLAG_FULL_NAME
Definition: cdstruc.h:1229
#define CdFidIsDirectory(I)
Definition: cdstruc.h:1835
#define CCB_FLAG_OPEN_RELATIVE_BY_ID
Definition: cdstruc.h:1104
#define CCB_FLAG_OPEN_WITH_VERSION
Definition: cdstruc.h:1106
#define CdQueryFidDirentOffset(I)
Definition: cdstruc.h:1831
#define CCB_FLAG_OPEN_BY_ID
Definition: cdstruc.h:1103
#define CdSetFidDirentOffset(I, D)
Definition: cdstruc.h:1833
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
#define VCB_STATE_AUDIO_DISK
Definition: cdstruc.h:712
#define VCB_STATE_LOCKED
Definition: cdstruc.h:709
#define CdFidSetDirectory(I)
Definition: cdstruc.h:1836
#define IRP_CONTEXT_FLAG_TRAIL_BACKSLASH
Definition: cdstruc.h:1230
#define CdQueryFidPathTableOffset(I)
Definition: cdstruc.h:1832
#define CdSetFidPathTableOffset(I, P)
Definition: cdstruc.h:1834
#define _Acquires_lock_(lock)
#define _Requires_lock_held_(lock)
#define _Acquires_exclusive_lock_(lock)
#define _Analysis_assume_lock_held_(lock)
#define _Analysis_assume_same_lock_(lock1, lock2)
#define _Analysis_suppress_lock_checking_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define IgnoreCase
Definition: cdprocs.h:461
#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
USHORT NODE_TYPE_CODE
Definition: nodetype.h:22
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
#define CDFS_NTC_FCB_INDEX
Definition: nodetype.h:30
#define CDFS_NTC_FCB_DATA
Definition: nodetype.h:31
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define OpenByFileId
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
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
#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_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
@ FastIoIsNotPossible
Definition: fsrtltypes.h:240
Status
Definition: gdiplustypes.h:25
#define FILE_OPEN_REQUIRING_OPLOCK
Definition: winternl.h:186
#define NOTHING
Definition: input_list.c:10
#define Add2Ptr(PTR, INC)
#define _Inout_
Definition: ms_sal.h:378
#define _At_(target, annos)
Definition: ms_sal.h:244
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define WRITE_DAC
Definition: nt_native.h:59
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define FILE_DELETE_CHILD
Definition: nt_native.h:645
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define FILE_OPENED
Definition: nt_native.h:769
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define ARGUMENT_PRESENT(ArgumentPointer)
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
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 IoUpdateShareAccess(IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3351
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
BOOLEAN NTAPI FsRtlCurrentBatchOplock(IN POPLOCK Oplock)
Definition: oplock.c:1364
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
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:1067
PFCB Fcb
Definition: cdstruc.h:1086
ULONG Flags
Definition: cdstruc.h:1080
UNICODE_STRING VersionString
Definition: cdstruc.h:250
UNICODE_STRING FileName
Definition: cdstruc.h:244
Definition: cdstruc.h:1525
ERESOURCE FcbResource
Definition: cdstruc.h:879
SECTION_OBJECT_POINTERS SegmentObject
Definition: cdstruc.h:873
Definition: cdstruc.h:902
ULONG Flags
Definition: ntfs.h:536
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1009
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
ULONG FcbCleanup
Definition: cdstruc.h:963
ULONG FileAttributes
Definition: cdstruc.h:977
__volatile LONG FcbReference
Definition: cdstruc.h:964
PFCB_NONPAGED FcbNonpaged
Definition: cdstruc.h:1003
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3979 Create
Definition: cdstruc.h:1460
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
#define MAXULONG
Definition: typedefs.h:251
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#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_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_opt_ WDFKEY _In_ PCUNICODE_STRING _In_ ACCESS_MASK _In_ ULONG _Out_opt_ PULONG CreateDisposition
Definition: wdfregistry.h:120
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
#define FILE_OPBATCH_BREAK_UNDERWAY
#define SL_OPEN_PAGING_FILE
Definition: iotypes.h:1817
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1778
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1818
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1820
__wchar_t WCHAR
Definition: xmlstorage.h:180