ReactOS  0.4.13-dev-249-gcba1a2f
create.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  Create.c
8 
9 Abstract:
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_))
34 CdNormalizeFileNames (
35  _Inout_ PIRP_CONTEXT IrpContext,
36  _In_ PVCB Vcb,
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)
49 CdOpenByFileId (
50  _In_ PIRP_CONTEXT IrpContext,
52  _In_ PVCB Vcb,
54  );
55 
56 _Requires_lock_held_(_Global_critical_region_)
58 CdOpenExistingFcb (
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)
70 CdOpenDirectoryFromPathEntry (
71  _In_ PIRP_CONTEXT IrpContext,
73  _In_ PVCB Vcb,
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_)
85 CdOpenFileFromFileContext (
86  _In_ PIRP_CONTEXT IrpContext,
88  _In_ PVCB Vcb,
92  _In_ BOOLEAN ShortNameMatch,
94  _In_opt_ PCCB RelatedCcb
95  );
96 
97 _Requires_lock_held_(_Global_critical_region_)
99 CdCompleteFcbOpen (
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_)
121 NTSTATUS
122 #ifdef _MSC_VER
123 #pragma prefast(suppress:26165, "Esp:1153")
124 #endif
125 CdCommonCreate (
126  _Inout_ PIRP_CONTEXT IrpContext,
128  )
129 
130 /*++
131 
132 Routine 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 
157 Arguments:
158 
159  Irp - Supplies the Irp to process
160 
161 Return 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;
208  PFCB CurrentFcb = NULL;
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 
274  return STATUS_ACCESS_DENIED;
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 
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,
348  OpenByFileId,
349  IgnoreCase,
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 
468  if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
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,
546  UserFileOpen,
547  IgnoreCase,
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,
579  IgnoreCase,
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,
634  CurrentFcb,
635  &FinalName,
636  IgnoreCase,
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,
664  CurrentFcb,
665  &FinalName,
666  IgnoreCase,
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,
686  CurrentFcb,
687  &FileContext.InitialDirent->Dirent.CdCaseFileName,
688  IgnoreCase,
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,
797  IgnoreCase,
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,
813  IgnoreCase,
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,
845  CurrentFcb,
846  &FinalName,
847  IgnoreCase,
848  &FileContext,
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,
925  IgnoreCase,
927  &FileContext,
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 
973  CurrentFcb = NULL;
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_))
1029 NTSTATUS
1030 CdNormalizeFileNames (
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 
1044 Routine 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 
1052 Arguments:
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 
1074 Return 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 
1175  return STATUS_INVALID_PARAMETER;
1176 
1177  //
1178  // The remaining name cannot begin with a backslash.
1179  //
1180 
1181  } else if (FileName->Buffer[0] == L'\\' ) {
1182 
1183  return STATUS_INVALID_PARAMETER;
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 
1228  return STATUS_INVALID_PARAMETER;
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 
1252  return STATUS_INVALID_PARAMETER;
1253  }
1254 
1255  //
1256  // Now see if we need to allocate a new buffer.
1257  //
1258 
1259  if (FileName->MaximumLength < BufferLength) {
1260 
1262  BufferLength,
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,
1346  RemainingName,
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 
1378  return STATUS_INVALID_PARAMETER;
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,
1457  RemainingName,
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)
1479 NTSTATUS
1480 CdOpenByFileId (
1481  _In_ PIRP_CONTEXT IrpContext,
1483  _In_ PVCB Vcb,
1485  )
1486 
1487 /*++
1488 
1489 Routine 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 
1511 Arguments:
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 
1521 Return 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,
1649  &CompoundPathEntry );
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 
1715  if (TypeOfOpen == UserDirectoryOpen) {
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 
1802  Found = CdLookupNextInitialFileDirent( IrpContext,
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 
1833  if (FlagOn( IrpSp->Parameters.Create.Options, FILE_DIRECTORY_FILE )) {
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 
1859  CdInitializeFcbFromFileContext( IrpContext,
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 
1873  if (FlagOn( NextFcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
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_)
1982 NTSTATUS
1983 CdOpenExistingFcb (
1984  _In_ PIRP_CONTEXT IrpContext,
1989  _In_opt_ PCCB RelatedCcb
1990  )
1991 
1992 /*++
1993 
1994 Routine 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 
2000 Arguments:
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 
2016 Return 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)
2085 NTSTATUS
2086 CdOpenDirectoryFromPathEntry (
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 
2101 Routine 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 
2122 Arguments:
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 
2143 Return 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;
2157  PFCB ParentFcb = NULL;
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 ) &&
2186  FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) {
2187 
2188  CcbFlags = CCB_FLAG_OPEN_RELATIVE_BY_ID;
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 
2258  ParentFcb = *CurrentFcb;
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_)
2367 NTSTATUS
2368 CdOpenFileFromFileContext (
2369  _In_ PIRP_CONTEXT IrpContext,
2371  _In_ PVCB Vcb,
2375  _In_ BOOLEAN ShortNameMatch,
2377  _In_opt_ PCCB RelatedCcb
2378  )
2379 
2380 /*++
2381 
2382 Routine 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 
2402 Arguments:
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 
2421 Return 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;
2435  PFCB ParentFcb = NULL;
2436 
2438 
2439  PAGED_CODE();
2440 
2441  //
2442  // Check for illegal access to this file.
2443  //
2444 
2445  if (CdIllegalFcbAccess( IrpContext,
2446  UserFileOpen,
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 
2464  SetFlag( CcbFlags, CCB_FLAG_OPEN_WITH_VERSION );
2465  }
2466 
2467  //
2468  // Check the related Ccb to see if this was an OpenByFileId.
2469  //
2470 
2471  if (ARGUMENT_PRESENT( RelatedCcb ) &&
2472  FlagOn( RelatedCcb->Flags, CCB_FLAG_OPEN_BY_ID | CCB_FLAG_OPEN_RELATIVE_BY_ID )) {
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 
2510  CdInitializeFcbFromFileContext( IrpContext,
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 
2547  ParentFcb = *CurrentFcb;
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,
2623  UserFileOpen,
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_)
2657 NTSTATUS
2658 CdCompleteFcbOpen (
2659  _In_ PIRP_CONTEXT IrpContext,
2661  _In_ PVCB Vcb,
2664  _In_ ULONG UserCcbFlags,
2666  )
2667 
2668 /*++
2669 
2670 Routine 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 
2677 Arguments:
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 
2692 Return 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 {
2701  NTSTATUS Status;
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 
2716  if (MAXIMUM_ALLOWED == DesiredAccess) {
2717 
2720  FILE_WRITE_DATA |
2721  FILE_WRITE_EA |
2722  FILE_ADD_FILE |
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 
2744  return STATUS_SHARING_VIOLATION;
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 
2778  return STATUS_SHARING_VIOLATION;
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,
2831  IrpSp->FileObject,
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,
2866  IrpSp->FileObject,
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,
2891  IrpSp->FileObject,
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 
UNICODE_STRING VersionString
Definition: cdstruc.h:256
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
VOID CdCleanupFileContext(_In_ PIRP_CONTEXT IrpContext, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1636
#define FILE_OPEN_REQUIRING_OPLOCK
Definition: winternl.h:186
#define FILE_WRITE_EA
Definition: nt_native.h:640
#define VCB_STATE_AUDIO_DISK
Definition: cdstruc.h:718
PFCB CdCreateFcb(_In_ PIRP_CONTEXT IrpContext, _In_ FILE_ID FileId, _In_ NODE_TYPE_CODE NodeTypeCode, _Out_opt_ PBOOLEAN FcbExisted)
Definition: strucsup.c:986
#define _Analysis_suppress_lock_checking_(lock)
Definition: no_sal2.h:685
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1776
_Inout_ PFCB * CurrentFcb
Definition: cdprocs.h:806
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:987
#define Add2Ptr(PTR, INC)
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define CdQueryFidPathTableOffset(I)
Definition: cdstruc.h:1838
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
USHORT MaximumLength
Definition: env_spec_w32.h:370
Iosb Status
Definition: create.c:4311
#define SL_OPEN_PAGING_FILE
Definition: iotypes.h:1773
_In_ PIRP Irp
Definition: csq.h:116
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
Definition: cdstruc.h:1073
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
ULONG FileAttributes
Definition: cdstruc.h:983
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_CREATE
Definition: from_kernel.h:55
ULONG CdShortNameDirentOffset(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING Name)
Definition: namesup.c:955
#define CdReleaseFcb(IC, F)
Definition: cdprocs.h:1017
#define FILE_OPENED
Definition: nt_native.h:769
#define CdInitializeCompoundPathEntry(IC, CP)
Definition: cdprocs.h:768
#define TAG_FILE_NAME
Definition: cdprocs.h:85
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 STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
Definition: cdstruc.h:504
#define FILE_OVERWRITE
Definition: from_kernel.h:57
VOID NTAPI IoSetShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3516
_Acquires_exclusive_lock_(Vcb->Resource)) FINISHED FatAcquireExclusiveVcb_Real(IN PIRP_CONTEXT IrpContext
uint16_t * PWCHAR
Definition: typedefs.h:54
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1734
#define FILE_APPEND_DATA
Definition: nt_native.h:634
#define CdFidSetDirectory(I)
Definition: cdstruc.h:1842
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT _Out_ PCD_NAME * MatchingName
Definition: cdprocs.h:444
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
#define CCB_FLAG_OPEN_RELATIVE_BY_ID
Definition: cdstruc.h:1110
#define CdAcquireFcbExclusive(IC, F, I)
Definition: cdprocs.h:1011
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define CDFS_NTC_FCB_INDEX
Definition: nodetype.h:30
#define FILE_SHARE_READ
Definition: compat.h:125
#define _In_opt_
Definition: no_sal2.h:213
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
VOID CdFspClose(_In_opt_ PVCB Vcb)
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1065
_SEH2_TRY
Definition: create.c:4250
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _In_ ULONG ShortNameDirentOffset
Definition: cdprocs.h:464
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB Vcb
Definition: create.c:4157
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define _Acquires_lock_(lock)
Definition: no_sal2.h:677
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define CdGetFcbOplock(F)
Definition: cdprocs.h:1086
#define FILE_DELETE_CHILD
Definition: nt_native.h:645
#define _Analysis_assume_lock_held_(lock)
Definition: no_sal2.h:682
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
VOID CdInitializeFcbFromPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_opt_ PFCB ParentFcb, _In_ PPATH_ENTRY PathEntry)
Definition: strucsup.c:1136
_In_ ULONG BufferLength
Definition: usbdlib.h:225
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define CDFS_NTC_FCB_DATA
Definition: nodetype.h:31
CdLookupInitialFileDirent(IrpContext, Fcb, FileContext, Fcb->StreamOffset)
#define IRP_CONTEXT_FLAG_TRAIL_BACKSLASH
Definition: cdstruc.h:1236
#define CD_ATTRIBUTE_DIRECTORY
Definition: cd.h:354
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT FileObject
Definition: create.c:4157
#define FILE_OPBATCH_BREAK_UNDERWAY
__volatile LONG FcbReference
Definition: cdstruc.h:970
#define CCB_FLAG_IGNORE_CASE
Definition: cdstruc.h:1111
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define _At_(target, annos)
Definition: no_sal2.h:11
ULONG Flags
Definition: cdstruc.h:1086
PFCB CdLookupFcbTable(_In_ PIRP_CONTEXT IrpContext, _In_ PVCB Vcb, _In_ FILE_ID FileId)
Definition: strucsup.c:2107
#define CdQueryFidDirentOffset(I)
Definition: cdstruc.h:1837
#define VCB_STATE_LOCKED
Definition: cdstruc.h:715
#define CCB_FLAG_OPEN_WITH_VERSION
Definition: cdstruc.h:1112
_Requires_lock_held_(_Global_critical_region_)
Definition: create.c:1477
return Found
Definition: dirsup.c:1270
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: cdprocs.h:444
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define CdFidIsDirectory(I)
Definition: cdstruc.h:1841
VOID CdLookupLastFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1426
PAGED_CODE()
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:984
PCCB CdCreateCcb(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG Flags)
Definition: strucsup.c:1405
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1015
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
CdVerifyOrCreateDirStreamFile(IrpContext, Fcb)
#define try_return(S)
Definition: cdprocs.h:2189
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1033
#define ARGUMENT_PRESENT(ArgumentPointer)
#define _Analysis_assume_same_lock_(lock1, lock2)
Definition: no_sal2.h:684
#define WRITE_DAC
Definition: nt_native.h:59
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
BOOLEAN CdLookupNextInitialFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _Inout_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1275
#define CdPagedPool
Definition: cdprocs.h:1385
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define _Inout_
Definition: no_sal2.h:244
BOOLEAN NTAPI FsRtlCurrentBatchOplock(IN POPLOCK Oplock)
Definition: oplock.c:1366
* PFILE_OBJECT
Definition: iotypes.h:1954
_In_ PFCB ParentFcb
Definition: cdprocs.h:741
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1737
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1028
ULONG Flags
Definition: ntfs.h:520
#define CCB_FLAG_OPEN_BY_ID
Definition: cdstruc.h:1109
static const WCHAR L[]
Definition: oid.c:1250
#define CdIsFastIoPossible(F)
Definition: cdprocs.h:2025
BOOLEAN CdLookupNextPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENUM_CONTEXT PathContext, _Inout_ PPATH_ENTRY PathEntry)
Definition: pathsup.c:207
PUNICODE_STRING FileName
Definition: iotypes.h:2792
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define CdCleanupCompoundPathEntry(IC, CP)
Definition: cdprocs.h:771
Status
Definition: gdiplustypes.h:24
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1049
#define FILE_OPEN
Definition: from_kernel.h:54
#define MAXULONG
Definition: typedefs.h:250
VOID CdDissectName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PUNICODE_STRING RemainingName, _Out_ PUNICODE_STRING FinalName)
Definition: namesup.c:301
#define _In_
Definition: no_sal2.h:204
NTSTATUS NTAPI IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, IN ULONG DesiredShareAccess, IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess, IN BOOLEAN Update)
Definition: file.c:3389
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
Definition: cdstruc.h:1466
struct _FileName FileName
Definition: fatprocs.h:884
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_SEH2_END
Definition: create.c:4424
#define OpenByFileId
#define SL_OPEN_TARGET_DIRECTORY
Definition: iotypes.h:1774
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define CdFreePool(x)
Definition: cdprocs.h:2200
Definition: cdstruc.h:1531
#define IgnoreCase
Definition: cdprocs.h:464
#define CdSetFidPathTableOffset(I, P)
Definition: cdstruc.h:1840
#define IRP_CONTEXT_FLAG_FULL_NAME
Definition: cdstruc.h:1235
unsigned short USHORT
Definition: pedump.c:61
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
ERESOURCE FcbResource
Definition: cdstruc.h:885
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
_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 DesiredAccess
Definition: create.c:4157
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
_SEH2_FINALLY
Definition: create.c:4395
#define MAXUSHORT
Definition: typedefs.h:81
PFCB Fcb
Definition: cdstruc.h:1092
#define CdIncrementCleanupCounts(IC, F)
Definition: cdprocs.h:1310
VOID CdLookupPathEntry(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG PathEntryOffset, _In_ ULONG Ordinal, _In_ BOOLEAN VerifyBounds, _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry)
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
SECTION_OBJECT_POINTERS SegmentObject
Definition: cdstruc.h:879
unsigned int ULONG
Definition: retypes.h:1
#define CdIncrementReferenceCounts(IC, F, C, UC)
Definition: cdprocs.h:1322
#define CdIllegalFcbAccess(IC, T, DA)
Definition: cdprocs.h:127
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:741
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:1172
USHORT NODE_TYPE_CODE
Definition: nodetype.h:22
VOID CdInitializeFcbFromFileContext(_In_ PIRP_CONTEXT IrpContext, _Inout_ PFCB Fcb, _In_ PFCB ParentFcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: strucsup.c:1225
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2745
PFCB_NONPAGED FcbNonpaged
Definition: cdstruc.h:1009
#define CdSetFidDirentOffset(I, D)
Definition: cdstruc.h:1839
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1111
UNICODE_STRING FileName
Definition: cdstruc.h:250
_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 CreateDisposition
Definition: create.c:4157
HRESULT Create([out]ITransactionReceiver **ppReceiver)
VOID NTAPI IoUpdateShareAccess(IN PFILE_OBJECT FileObject, OUT PSHARE_ACCESS ShareAccess)
Definition: file.c:3350
ULONG ACCESS_MASK
Definition: nt_native.h:40
_When_(RelatedTypeOfOpen !=UnopenedFileObject, _At_(RelatedCcb, _In_))
Definition: create.c:29
#define CdInitializeFileContext(IC, FC)
Definition: cdprocs.h:532
Iosb Information
Definition: create.c:4377
#define DELETE
Definition: nt_native.h:57
LONGLONG QuadPart
Definition: typedefs.h:112
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
Definition: cdprocs.h:741
ULONG FcbCleanup
Definition: cdstruc.h:969
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:806