ReactOS  0.4.14-dev-77-gd9e7c48
dirctrl.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  DirCtrl.c
8 
9 Abstract:
10 
11  This module implements the File Directory Control routines for Cdfs called
12  by the Fsd/Fsp dispatch drivers.
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_DIRCTRL)
24 
25 //
26 // Local support routines
27 //
28 
29 _Requires_lock_held_(_Global_critical_region_)
31 CdQueryDirectory (
32  _Inout_ PIRP_CONTEXT IrpContext,
35  _In_ PFCB Fcb,
36  _In_ PCCB Ccb
37  );
38 
39 _Requires_lock_held_(_Global_critical_region_)
41 CdNotifyChangeDirectory (
42  _Inout_ PIRP_CONTEXT IrpContext,
45  _In_ PCCB Ccb
46  );
47 
48 VOID
50  _In_ PIRP_CONTEXT IrpContext,
52  _In_ PFCB Fcb,
55  _Out_ PBOOLEAN ReturnNextEntry,
57  _Out_ PBOOLEAN InitialQuery
58  );
59 
60 BOOLEAN
62  _In_ PIRP_CONTEXT IrpContext,
63  _In_ PCCB Ccb,
65  _In_ BOOLEAN ReturnNextEntry
66  );
67 
68 #ifdef ALLOC_PRAGMA
69 #pragma alloc_text(PAGE, CdCommonDirControl)
70 #pragma alloc_text(PAGE, CdEnumerateIndex)
71 #pragma alloc_text(PAGE, CdInitializeEnumeration)
72 #pragma alloc_text(PAGE, CdNotifyChangeDirectory)
73 #pragma alloc_text(PAGE, CdQueryDirectory)
74 #endif
75 
76 
77 
78 _Requires_lock_held_(_Global_critical_region_)
80 CdCommonDirControl (
81  _Inout_ PIRP_CONTEXT IrpContext,
83  )
84 
85 /*++
86 
87 Routine Description:
88 
89  This routine is the entry point for the directory control operations. These
90  are directory enumerations and directory notify calls. We verify the
91  user's handle is for a directory and then call the appropriate routine.
92 
93 Arguments:
94 
95  Irp - Irp for this request.
96 
97 Return Value:
98 
99  NTSTATUS - Status returned from the lower level routines.
100 
101 --*/
102 
103 {
106 
107  PFCB Fcb;
108  PCCB Ccb;
109 
110  PAGED_CODE();
111 
112  //
113  // Decode the user file object and fail this request if it is not
114  // a user directory.
115  //
116 
117  if (CdDecodeFileObject( IrpContext,
118  IrpSp->FileObject,
119  &Fcb,
120  &Ccb ) != UserDirectoryOpen) {
121 
124  }
125 
126  //
127  // We know this is a directory control so we'll case on the
128  // minor function, and call a internal worker routine to complete
129  // the irp.
130  //
131 
132  switch (IrpSp->MinorFunction) {
133 
135 
136  Status = CdQueryDirectory( IrpContext, Irp, IrpSp, Fcb, Ccb );
137  break;
138 
140 
141  Status = CdNotifyChangeDirectory( IrpContext, Irp, IrpSp, Ccb );
142  break;
143 
144  default:
145 
148  break;
149  }
150 
151  return Status;
152 }
153 
154 
155 //
156 // Local support routines
157 //
158 
159 _Requires_lock_held_(_Global_critical_region_)
160 NTSTATUS
161 CdQueryDirectory (
162  _Inout_ PIRP_CONTEXT IrpContext,
163  _Inout_ PIRP Irp,
165  _In_ PFCB Fcb,
166  _In_ PCCB Ccb
167  )
168 
169 /*++
170 
171 Routine Description:
172 
173  This routine performs the query directory operation. It is responsible
174  for either completing of enqueuing the input Irp. We store the state of the
175  search in the Ccb.
176 
177 Arguments:
178 
179  Irp - Supplies the Irp to process
180 
181  IrpSp - Stack location for this Irp.
182 
183  Fcb - Fcb for this directory.
184 
185  Ccb - Ccb for this directory open.
186 
187 Return Value:
188 
189  NTSTATUS - The return status for the operation
190 
191 --*/
192 
193 {
195  ULONG Information = 0;
196 
197  ULONG LastEntry = 0;
198  ULONG NextEntry = 0;
199 
200  ULONG FileNameBytes;
201  ULONG SeparatorBytes;
202  ULONG VersionStringBytes;
203 
205  PDIRENT ThisDirent = NULL;
206  BOOLEAN InitialQuery;
207  BOOLEAN ReturnNextEntry = FALSE;
209  BOOLEAN Found;
210  BOOLEAN DoCcbUpdate = FALSE;
211 
212  PCHAR UserBuffer;
213  ULONG BytesRemainingInBuffer;
214 
215  ULONG BaseLength;
216 
218  PFILE_NAMES_INFORMATION NamesInfo;
219  PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo;
220  PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo;
221 
222  PAGED_CODE();
223 
224  //
225  // Check if we support this search mode. Also remember the size of the base part of
226  // each of these structures.
227  //
228 
229  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
230 
232 
234  FileName[0] );
235  break;
236 
238 
240  FileName[0] );
241  break;
242 
244 
246  FileName[0] );
247  break;
248 
250 
251  BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
252  FileName[0] );
253  break;
254 
256 
258  FileName[0] );
259  break;
260 
262 
264  FileName[0] );
265  break;
266 
267  default:
268 
271  }
272 
273  //
274  // Get the user buffer.
275  //
276 
277  CdMapUserBuffer( IrpContext, &UserBuffer);
278 
279  //
280  // Initialize our search context.
281  //
282 
283  CdInitializeFileContext( IrpContext, &FileContext );
284 
285  //
286  // Acquire the directory.
287  //
288 
289  CdAcquireFileShared( IrpContext, Fcb );
290 
291  //
292  // Use a try-finally to facilitate cleanup.
293  //
294 
295  _SEH2_TRY {
296 
297  //
298  // Verify the Fcb is still good.
299  //
300 
301  CdVerifyFcbOperation( IrpContext, Fcb );
302 
303  //
304  // Start by getting the initial state for the enumeration. This will set up the Ccb with
305  // the initial search parameters and let us know the starting offset in the directory
306  // to search.
307  //
308 
309  CdInitializeEnumeration( IrpContext,
310  IrpSp,
311  Fcb,
312  Ccb,
313  &FileContext,
314  &ReturnNextEntry,
316  &InitialQuery );
317 
318  //
319  // The current dirent is stored in the InitialDirent field. We capture
320  // this here so that we have a valid restart point even if we don't
321  // find a single entry.
322  //
323 
324  ThisDirent = &FileContext.InitialDirent->Dirent;
325 
326  //
327  // At this point we are about to enter our query loop. We have
328  // determined the index into the directory file to begin the
329  // search. LastEntry and NextEntry are used to index into the user
330  // buffer. LastEntry is the last entry we've added, NextEntry is
331  // current one we're working on. If NextEntry is non-zero, then
332  // at least one entry was added.
333  //
334 
335  while (TRUE) {
336 
337  //
338  // If the user had requested only a single match and we have
339  // returned that, then we stop at this point. We update the Ccb with
340  // the status based on the last entry returned.
341  //
342 
343  if ((NextEntry != 0) && ReturnSingleEntry) {
344 
345  DoCcbUpdate = TRUE;
346  try_leave( Status );
347  }
348 
349  //
350  // We try to locate the next matching dirent. Our search if based on a starting
351  // dirent offset, whether we should return the current or next entry, whether
352  // we should be doing a short name search and finally whether we should be
353  // checking for a version match.
354  //
355 
356  Found = CdEnumerateIndex( IrpContext, Ccb, &FileContext, ReturnNextEntry );
357 
358  //
359  // Initialize the value for the next search.
360  //
361 
362  ReturnNextEntry = TRUE;
363 
364  //
365  // If we didn't receive a dirent, then we are at the end of the
366  // directory. If we have returned any files, we exit with
367  // success, otherwise we return STATUS_NO_MORE_FILES.
368  //
369 
370  if (!Found) {
371 
372  if (NextEntry == 0) {
373 
375 
376  if (InitialQuery) {
377 
379  }
380  }
381 
382  DoCcbUpdate = TRUE;
383  try_leave( Status );
384  }
385 
386  //
387  // Remember the dirent for the file we just found.
388  //
389 
390  ThisDirent = &FileContext.InitialDirent->Dirent;
391 
392  //
393  // Here are the rules concerning filling up the buffer:
394  //
395  // 1. The Io system garentees that there will always be
396  // enough room for at least one base record.
397  //
398  // 2. If the full first record (including file name) cannot
399  // fit, as much of the name as possible is copied and
400  // STATUS_BUFFER_OVERFLOW is returned.
401  //
402  // 3. If a subsequent record cannot completely fit into the
403  // buffer, none of it (as in 0 bytes) is copied, and
404  // STATUS_SUCCESS is returned. A subsequent query will
405  // pick up with this record.
406  //
407 
408  //
409  // Let's compute the number of bytes we need to transfer the current entry.
410  //
411 
412  SeparatorBytes =
413  VersionStringBytes = 0;
414 
415  //
416  // We can look directly at the dirent that we found.
417  //
418 
419  FileNameBytes = ThisDirent->CdFileName.FileName.Length;
420 
421  //
422  // Compute the number of bytes for the version string if
423  // we will return this. Allow directories with illegal ";".
424  //
425 
426  if (((Ccb->SearchExpression.VersionString.Length != 0) ||
427  (FlagOn(ThisDirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY))) &&
428  (ThisDirent->CdFileName.VersionString.Length != 0)) {
429 
430  SeparatorBytes = 2;
431 
432  VersionStringBytes = ThisDirent->CdFileName.VersionString.Length;
433  }
434 
435  //
436  // If the slot for the next entry would be beyond the length of the
437  // user's buffer just exit (we know we've returned at least one entry
438  // already). This will happen when we align the pointer past the end.
439  //
440 
441  if (NextEntry > IrpSp->Parameters.QueryDirectory.Length) {
442 
443  ReturnNextEntry = FALSE;
444  DoCcbUpdate = TRUE;
446  }
447 
448  //
449  // Compute the number of bytes remaining in the buffer. Round this
450  // down to a WCHAR boundary so we can copy full characters.
451  //
452 
453  BytesRemainingInBuffer = IrpSp->Parameters.QueryDirectory.Length - NextEntry;
454  ClearFlag( BytesRemainingInBuffer, 1 );
455 
456  //
457  // If this won't fit and we have returned a previous entry then just
458  // return STATUS_SUCCESS.
459  //
460 
461  if ((BaseLength + FileNameBytes + SeparatorBytes + VersionStringBytes) > BytesRemainingInBuffer) {
462 
463  //
464  // If we already found an entry then just exit.
465  //
466 
467  if (NextEntry != 0) {
468 
469  ReturnNextEntry = FALSE;
470  DoCcbUpdate = TRUE;
472  }
473 
474  //
475  // Don't even try to return the version string if it doesn't all fit.
476  // Reduce the FileNameBytes to just fit in the buffer.
477  //
478 
479  if ((BaseLength + FileNameBytes) > BytesRemainingInBuffer) {
480 
481  FileNameBytes = BytesRemainingInBuffer - BaseLength;
482  }
483 
484  //
485  // Don't return any version string bytes.
486  //
487 
488  VersionStringBytes =
489  SeparatorBytes = 0;
490 
491  //
492  // Use a status code of STATUS_BUFFER_OVERFLOW. Also set
493  // ReturnSingleEntry so that we will exit the loop at the top.
494  //
495 
498  }
499 
500  //
501  // Protect access to the user buffer with an exception handler.
502  // Since (at our request) IO doesn't buffer these requests, we have
503  // to guard against a user messing with the page protection and other
504  // such trickery.
505  //
506 
507  _SEH2_TRY {
508 
509  //
510  // Zero and initialize the base part of the current entry.
511  //
512 
513  RtlZeroMemory( Add2Ptr( UserBuffer, NextEntry, PVOID ),
514  BaseLength );
515 
516  //
517  // Now we have an entry to return to our caller.
518  // We'll case on the type of information requested and fill up
519  // the user buffer if everything fits.
520  //
521 
522  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
523 
529 
530  DirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_BOTH_DIR_INFORMATION );
531 
532  //
533  // Use the create time for all the time stamps.
534  //
535 
536  CdConvertCdTimeToNtTime( IrpContext,
537  FileContext.InitialDirent->Dirent.CdTime,
538  &DirInfo->CreationTime );
539 
540  DirInfo->LastWriteTime = DirInfo->ChangeTime = DirInfo->CreationTime;
541 
542  //
543  // Set the attributes and sizes separately for directories and
544  // files.
545  //
546 
547  if (FlagOn( ThisDirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY )) {
548 
549  DirInfo->EndOfFile.QuadPart = DirInfo->AllocationSize.QuadPart = 0;
550 
552 
553  } else {
554 
555  DirInfo->EndOfFile.QuadPart = FileContext.FileSize;
556  DirInfo->AllocationSize.QuadPart = LlSectorAlign( FileContext.FileSize );
557 
559  }
560 
561  if (FlagOn( ThisDirent->DirentFlags,
563 
565  }
566 
567  DirInfo->FileIndex = ThisDirent->DirentOffset;
568 
569  DirInfo->FileNameLength = FileNameBytes + SeparatorBytes + VersionStringBytes;
570 
571  break;
572 
574 
575  NamesInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_NAMES_INFORMATION );
576 
577  NamesInfo->FileIndex = ThisDirent->DirentOffset;
578 
579  NamesInfo->FileNameLength = FileNameBytes + SeparatorBytes + VersionStringBytes;
580 
581  break;
582 
583  /* ReactOS Change: GCC "enumeration value not handled in switch" */
584  default: break;
585  }
586 
587  //
588  // Fill in the FileId
589  //
590 
591  switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
592 
594 
595  IdBothDirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_ID_BOTH_DIR_INFORMATION );
596  CdSetFidFromParentAndDirent( IdBothDirInfo->FileId, Fcb, ThisDirent );
597  break;
598 
600 
601  IdFullDirInfo = Add2Ptr( UserBuffer, NextEntry, PFILE_ID_FULL_DIR_INFORMATION );
602  CdSetFidFromParentAndDirent( IdFullDirInfo->FileId, Fcb, ThisDirent );
603  break;
604 
605  default:
606  break;
607  }
608 
609  //
610  // Now copy as much of the name as possible. We also may have a version
611  // string to copy.
612  //
613 
614  if (FileNameBytes != 0) {
615 
616  //
617  // This is a Unicode name, we can copy the bytes directly.
618  //
619 
620  RtlCopyMemory( Add2Ptr( UserBuffer, NextEntry + BaseLength, PVOID ),
621  ThisDirent->CdFileName.FileName.Buffer,
622  FileNameBytes );
623 
624  if (SeparatorBytes != 0) {
625 
626  *(Add2Ptr( UserBuffer,
627  NextEntry + BaseLength + FileNameBytes,
628  PWCHAR )) = L';';
629 
630  if (VersionStringBytes != 0) {
631 
632  RtlCopyMemory( Add2Ptr( UserBuffer,
633  NextEntry + BaseLength + FileNameBytes + sizeof( WCHAR ),
634  PVOID ),
635  ThisDirent->CdFileName.VersionString.Buffer,
636  VersionStringBytes );
637  }
638  }
639  }
640 
641  //
642  // Fill in the short name if we got STATUS_SUCCESS. The short name
643  // may already be in the file context. Otherwise we will check
644  // whether the long name is 8.3. Special case the self and parent
645  // directory names.
646  //
647 
648  if ((Status == STATUS_SUCCESS) &&
649  (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
650  IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation) &&
651  (Ccb->SearchExpression.VersionString.Length == 0) &&
652  !FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY )) {
653 
654  //
655  // If we already have the short name then copy into the user's buffer.
656  //
657 
658  if (FileContext.ShortName.FileName.Length != 0) {
659 
660  RtlCopyMemory( DirInfo->ShortName,
661  FileContext.ShortName.FileName.Buffer,
662  FileContext.ShortName.FileName.Length );
663 
664  DirInfo->ShortNameLength = (CCHAR) FileContext.ShortName.FileName.Length;
665 
666  //
667  // If the short name length is currently zero then check if
668  // the long name is not 8.3. We can copy the short name in
669  // unicode form directly into the caller's buffer.
670  //
671 
672  } else {
673 
674  if (!CdIs8dot3Name( IrpContext,
675  ThisDirent->CdFileName.FileName )) {
676 
677  CdGenerate8dot3Name( IrpContext,
678  &ThisDirent->CdCaseFileName.FileName,
679  ThisDirent->DirentOffset,
680  DirInfo->ShortName,
681  &FileContext.ShortName.FileName.Length );
682 
683  DirInfo->ShortNameLength = (CCHAR) FileContext.ShortName.FileName.Length;
684  }
685  }
686 
687  }
688 
689  //
690  // Sum the total number of bytes for the information field.
691  //
692 
693  FileNameBytes += SeparatorBytes + VersionStringBytes;
694 
695  //
696  // Update the information with the number of bytes stored in the
697  // buffer. We quad-align the existing buffer to add any necessary
698  // pad bytes.
699  //
700 
701  Information = NextEntry + BaseLength + FileNameBytes;
702 
703  //
704  // Go back to the previous entry and fill in the update to this entry.
705  //
706 
707  *(Add2Ptr( UserBuffer, LastEntry, PULONG )) = NextEntry - LastEntry;
708 
709  //
710  // Set up our variables for the next dirent.
711  //
712 
713  InitialQuery = FALSE;
714 
715  LastEntry = NextEntry;
716  NextEntry = QuadAlign( Information );
717 
718 #ifdef _MSC_VER
719 #pragma warning(suppress: 6320)
720 #endif
722 
723  //
724  // We had a problem filling in the user's buffer, so stop and
725  // fail this request. This is the only reason any exception
726  // would have occured at this level.
727  //
728 
729  Information = 0;
731  } _SEH2_END;
732  }
733 
734  DoCcbUpdate = TRUE;
735 
736  } _SEH2_FINALLY {
737 
738  //
739  // Cleanup our search context - *before* aquiring the FCB mutex exclusive,
740  // else can block on threads in cdcreateinternalstream/purge which
741  // hold the FCB but are waiting for all maps in this stream to be released.
742  //
743 
744  CdCleanupFileContext( IrpContext, &FileContext );
745 
746  //
747  // Now we can safely aqure the FCB mutex if we need to.
748  //
749 
750  if (DoCcbUpdate && !NT_ERROR( Status )) {
751 
752  //
753  // Update the Ccb to show the current state of the enumeration.
754  //
755 
756  CdLockFcb( IrpContext, Fcb );
757 
758  Ccb->CurrentDirentOffset = ThisDirent->DirentOffset;
759 
761 
762  if (ReturnNextEntry) {
763 
765  }
766 
767  CdUnlockFcb( IrpContext, Fcb );
768  }
769 
770  //
771  // Release the Fcb.
772  //
773 
774  CdReleaseFile( IrpContext, Fcb );
775  } _SEH2_END;
776 
777  //
778  // Complete the request here.
779  //
780 
781  Irp->IoStatus.Information = Information;
782 
783  CdCompleteRequest( IrpContext, Irp, Status );
784  return Status;
785 }
786 
787 
788 //
789 // Local support routines
790 //
791 
792 _Requires_lock_held_(_Global_critical_region_)
793 NTSTATUS
794 CdNotifyChangeDirectory (
795  _Inout_ PIRP_CONTEXT IrpContext,
796  _Inout_ PIRP Irp,
798  _In_ PCCB Ccb
799  )
800 
801 /*++
802 
803 Routine Description:
804 
805  This routine performs the notify change directory operation. It is
806  responsible for either completing of enqueuing the input Irp. Although there
807  will never be a notify signalled on a CDROM disk we still support this call.
808 
809  We have already checked that this is not an OpenById handle.
810 
811 Arguments:
812 
813  Irp - Supplies the Irp to process
814 
815  IrpSp - Io stack location for this request.
816 
817  Ccb - Handle to the directory being watched.
818 
819 Return Value:
820 
821  NTSTATUS - STATUS_PENDING, any other error will raise.
822 
823 --*/
824 
825 {
826  PAGED_CODE();
827 
828  //
829  // Always set the wait bit in the IrpContext so the initial wait can't fail.
830  //
831 
832  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
833 
834  //
835  // Acquire the Vcb shared.
836  //
837 
838  CdAcquireVcbShared( IrpContext, IrpContext->Vcb, FALSE );
839 
840  //
841  // Use a try-finally to facilitate cleanup.
842  //
843 
844  _SEH2_TRY {
845 
846  //
847  // Verify the Vcb.
848  //
849 
850  CdVerifyVcb( IrpContext, IrpContext->Vcb );
851 
852  //
853  // Call the Fsrtl package to process the request. We cast the
854  // unicode strings to ansi strings as the dir notify package
855  // only deals with memory matching.
856  //
857 
858  FsRtlNotifyFullChangeDirectory( IrpContext->Vcb->NotifySync,
859  &IrpContext->Vcb->DirNotifyList,
860  Ccb,
861  (PSTRING) &IrpSp->FileObject->FileName,
863  FALSE,
864  IrpSp->Parameters.NotifyDirectory.CompletionFilter,
865  Irp,
866  NULL,
867  NULL );
868 
869  } _SEH2_FINALLY {
870 
871  //
872  // Release the Vcb.
873  //
874 
875  CdReleaseVcb( IrpContext, IrpContext->Vcb );
876  } _SEH2_END;
877 
878  //
879  // Cleanup the IrpContext.
880  //
881 
882  CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
883 
884  return STATUS_PENDING;
885 }
886 
887 
888 //
889 // Local support routine
890 //
891 
892 VOID
894  _In_ PIRP_CONTEXT IrpContext,
896  _In_ PFCB Fcb,
897  _Inout_ PCCB Ccb,
899  _Out_ PBOOLEAN ReturnNextEntry,
901  _Out_ PBOOLEAN InitialQuery
902  )
903 
904 /*++
905 
906 Routine Description:
907 
908  This routine is called to initialize the enumeration variables and structures.
909  We look at the state of a previous enumeration from the Ccb as well as any
910  input values from the user. On exit we will position the FileContext at
911  a file in the directory and let the caller know whether this entry or the
912  next entry should be returned.
913 
914 Arguments:
915 
916  IrpSp - Irp stack location for this request.
917 
918  Fcb - Fcb for this directory.
919 
920  Ccb - Ccb for the directory handle.
921 
922  FileContext - FileContext to use for this enumeration.
923 
924  ReturnNextEntry - Address to store whether we should return the entry at
925  the FileContext position or the next entry.
926 
927  ReturnSingleEntry - Address to store whether we should only return
928  a single entry.
929 
930  InitialQuery - Address to store whether this is the first enumeration
931  query on this handle.
932 
933 Return Value:
934 
935  None.
936 
937 --*/
938 
939 {
941 
943  CD_NAME WildCardName;
944  CD_NAME SearchExpression;
945 
946  ULONG CcbFlags;
947 
949  ULONG LastDirentOffset;
950  BOOLEAN KnownOffset;
951 
952  BOOLEAN Found;
953 
954  PAGED_CODE();
955 
956  //
957  // If the user has specified that the scan be restarted, and has specicified
958  // a new query pattern, reinitialize the CCB.
959  //
960 
961  if (FlagOn( IrpSp->Flags, SL_RESTART_SCAN )) {
962 
963  CdLockFcb( IrpContext, Fcb );
964 
965  FileName = (PUNICODE_STRING) IrpSp->Parameters.QueryDirectory.FileName;
966  if (FileName && FileName->Length > 0) {
967 
969 
970  CdFreePool( &Ccb->SearchExpression.FileName.Buffer );
971  }
972 
976  }
977 
978  CdUnlockFcb( IrpContext, Fcb );
979  }
980 
981  //
982  // If this is the initial query then build a search expression from the input
983  // file name.
984  //
985 
987 
988  FileName = IrpSp->Parameters.QueryDirectory.FileName;
989 
990  CcbFlags = 0;
991 
992  //
993  // If the filename is not specified or is a single '*' then we will
994  // match all names.
995  //
996 
997  if ((FileName == NULL) ||
998  (FileName->Buffer == NULL) ||
999  (FileName->Length == 0) ||
1000  ((FileName->Length == sizeof( WCHAR )) &&
1001  (FileName->Buffer[0] == L'*'))) {
1002 
1003  SetFlag( CcbFlags, CCB_FLAG_ENUM_MATCH_ALL );
1004  RtlZeroMemory( &SearchExpression, sizeof( SearchExpression ));
1005 
1006  //
1007  // Otherwise build the CdName from the name in the stack location.
1008  // This involves building both the name and version portions and
1009  // checking for wild card characters. We also upcase the string if
1010  // this is a case-insensitive search.
1011  //
1012 
1013  } else {
1014 
1015  //
1016  // Create a CdName to check for wild cards.
1017  //
1018 
1019  WildCardName.FileName = *FileName;
1020 
1021  CdConvertNameToCdName( IrpContext, &WildCardName );
1022 
1023  //
1024  // The name better have at least one character.
1025  //
1026 
1027  if (WildCardName.FileName.Length == 0) {
1028 
1029  CdRaiseStatus( IrpContext, STATUS_INVALID_PARAMETER );
1030  }
1031 
1032  //
1033  // Check for wildcards in the separate components.
1034  //
1035 
1036  if (FsRtlDoesNameContainWildCards( &WildCardName.FileName)) {
1037 
1039  }
1040 
1041  if ((WildCardName.VersionString.Length != 0) &&
1042  (FsRtlDoesNameContainWildCards( &WildCardName.VersionString ))) {
1043 
1045 
1046  //
1047  // Check if this is a wild card only and match all version
1048  // strings.
1049  //
1050 
1051  if ((WildCardName.VersionString.Length == sizeof( WCHAR )) &&
1052  (WildCardName.VersionString.Buffer[0] == L'*')) {
1053 
1055  }
1056  }
1057 
1058  //
1059  // Now create the search expression to store in the Ccb.
1060  //
1061 
1063  FileName->Length,
1065 
1066  SearchExpression.FileName.MaximumLength = FileName->Length;
1067 
1068  //
1069  // Either copy the name directly or perform the upcase.
1070  //
1071 
1072  if (FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE )) {
1073 
1074  Status = RtlUpcaseUnicodeString( (PUNICODE_STRING) &SearchExpression.FileName,
1075  FileName,
1076  FALSE );
1077 
1078  //
1079  // This should never fail.
1080  //
1081  __analysis_assert( Status == STATUS_SUCCESS );
1083 
1084  } else {
1085 
1086  RtlCopyMemory( SearchExpression.FileName.Buffer,
1087  FileName->Buffer,
1088  FileName->Length );
1089  }
1090 
1091  //
1092  // Now split into the separate name and version components.
1093  //
1094 
1095  SearchExpression.FileName.Length = WildCardName.FileName.Length;
1096  SearchExpression.VersionString.Length = WildCardName.VersionString.Length;
1097  SearchExpression.VersionString.MaximumLength = WildCardName.VersionString.MaximumLength;
1098 
1099  SearchExpression.VersionString.Buffer = Add2Ptr( SearchExpression.FileName.Buffer,
1100  SearchExpression.FileName.Length + sizeof( WCHAR ),
1101  PWCHAR );
1102  }
1103 
1104  //
1105  // But we do not want to return the constant "." and ".." entries for
1106  // the root directory, for consistency with the rest of Microsoft's
1107  // filesystems.
1108  //
1109 
1110  if (Fcb == Fcb->Vcb->RootIndexFcb) {
1111 
1113  }
1114 
1115  //
1116  // Now lock the Fcb in order to update the Ccb with the inital
1117  // enumeration values.
1118  //
1119 
1120  CdLockFcb( IrpContext, Fcb );
1121 
1122  //
1123  // Check again that this is the initial search.
1124  //
1125 
1127 
1128  //
1129  // Update the values in the Ccb.
1130  //
1131 
1132  Ccb->CurrentDirentOffset = Fcb->StreamOffset;
1133  Ccb->SearchExpression = SearchExpression;
1134 
1135  //
1136  // Set the appropriate flags in the Ccb.
1137  //
1138 
1139  SetFlag( Ccb->Flags, CcbFlags | CCB_FLAG_ENUM_INITIALIZED );
1140 
1141  //
1142  // Otherwise cleanup any buffer allocated here.
1143  //
1144 
1145  } else {
1146 
1147  if (!FlagOn( CcbFlags, CCB_FLAG_ENUM_MATCH_ALL )) {
1148 
1149  CdFreePool( &SearchExpression.FileName.Buffer );
1150  }
1151  }
1152 
1153  //
1154  // Otherwise lock the Fcb so we can read the current enumeration values.
1155  //
1156 
1157  } else {
1158 
1159  CdLockFcb( IrpContext, Fcb );
1160  }
1161 
1162  //
1163  // Capture the current state of the enumeration.
1164  //
1165  // If the user specified an index then use his offset. We always
1166  // return the next entry in this case.
1167  //
1168 
1169  if (FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED )) {
1170 
1171  KnownOffset = FALSE;
1172  DirentOffset = IrpSp->Parameters.QueryDirectory.FileIndex;
1173  *ReturnNextEntry = TRUE;
1174 
1175  //
1176  // If we are restarting the scan then go from the self entry.
1177  //
1178 
1179  } else if (FlagOn( IrpSp->Flags, SL_RESTART_SCAN )) {
1180 
1181  KnownOffset = TRUE;
1182  DirentOffset = Fcb->StreamOffset;
1183  *ReturnNextEntry = FALSE;
1184 
1185  //
1186  // Otherwise use the values from the Ccb.
1187  //
1188 
1189  } else {
1190 
1191  KnownOffset = TRUE;
1192  DirentOffset = Ccb->CurrentDirentOffset;
1193  *ReturnNextEntry = BooleanFlagOn( Ccb->Flags, CCB_FLAG_ENUM_RETURN_NEXT );
1194  }
1195 
1196  //
1197  // Unlock the Fcb.
1198  //
1199 
1200  CdUnlockFcb( IrpContext, Fcb );
1201 
1202  //
1203  // We have the starting offset in the directory and whether to return
1204  // that entry or the next. If we are at the beginning of the directory
1205  // and are returning that entry, then tell our caller this is the
1206  // initial query.
1207  //
1208 
1209  *InitialQuery = FALSE;
1210 
1211  if ((DirentOffset == Fcb->StreamOffset) &&
1212  !(*ReturnNextEntry)) {
1213 
1214  *InitialQuery = TRUE;
1215  }
1216 
1217  //
1218  // If there is no file object then create it now.
1219  //
1220 
1221  CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);
1222 
1223  //
1224  // Determine the offset in the stream to position the FileContext and
1225  // whether this offset is known to be a file offset.
1226  //
1227  // If this offset is known to be safe then go ahead and position the
1228  // file context. This handles the cases where the offset is the beginning
1229  // of the stream, the offset is from a previous search or this is the
1230  // initial query.
1231  //
1232 
1233  if (KnownOffset) {
1234 
1236 
1237  //
1238  // Otherwise we walk through the directory from the beginning until
1239  // we reach the entry which contains this offset.
1240  //
1241 
1242  } else {
1243 
1244  LastDirentOffset = Fcb->StreamOffset;
1245  Found = TRUE;
1246 
1247  CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, LastDirentOffset );
1248 
1249  //
1250  // If the requested offset is prior to the beginning offset in the stream
1251  // then don't return the next entry.
1252  //
1253 
1254  if (DirentOffset < LastDirentOffset) {
1255 
1256  *ReturnNextEntry = FALSE;
1257 
1258  //
1259  // Else look for the last entry which ends past the desired index.
1260  //
1261 
1262  } else {
1263 
1264  //
1265  // Keep walking through the directory until we run out of
1266  // entries or we find an entry which ends beyond the input
1267  // index value.
1268  //
1269 
1270  do {
1271 
1272  //
1273  // If we have passed the index value then exit.
1274  //
1275 
1276  if (FileContext->InitialDirent->Dirent.DirentOffset > DirentOffset) {
1277 
1278  Found = FALSE;
1279  break;
1280  }
1281 
1282  //
1283  // Remember the current position in case we need to go back.
1284  //
1285 
1286  LastDirentOffset = FileContext->InitialDirent->Dirent.DirentOffset;
1287 
1288  //
1289  // Exit if the next entry is beyond the desired index value.
1290  //
1291 
1292  if (LastDirentOffset + FileContext->InitialDirent->Dirent.DirentLength > DirentOffset) {
1293 
1294  break;
1295  }
1296 
1298 
1299  } while (Found);
1300 
1301  //
1302  // If we didn't find the entry then go back to the last known entry.
1303  // This can happen if the index lies in the unused range at the
1304  // end of a sector.
1305  //
1306 
1307  if (!Found) {
1308 
1309  CdCleanupFileContext( IrpContext, FileContext );
1310  CdInitializeFileContext( IrpContext, FileContext );
1311 
1312  CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, LastDirentOffset );
1313  }
1314  }
1315  }
1316 
1317  //
1318  // Only update the dirent name if we will need it for some reason.
1319  // Don't update this name if we are returning the next entry and
1320  // the search string has a version component.
1321  //
1322 
1323  FileContext->ShortName.FileName.Length = 0;
1324 
1325  if (!(*ReturnNextEntry) ||
1326  (Ccb->SearchExpression.VersionString.Length == 0)) {
1327 
1328  //
1329  // Update the name in the dirent into filename and version components.
1330  //
1331 
1332  CdUpdateDirentName( IrpContext,
1333  &FileContext->InitialDirent->Dirent,
1335  }
1336 
1337  //
1338  // Look at the flag in the IrpSp indicating whether to return just
1339  // one entry.
1340  //
1341 
1343 
1345 
1347  }
1348 
1349  return;
1350 }
1351 
1352 
1353 //
1354 // Local support routine
1355 //
1356 
1357 BOOLEAN
1359  _In_ PIRP_CONTEXT IrpContext,
1360  _In_ PCCB Ccb,
1362  _In_ BOOLEAN ReturnNextEntry
1363  )
1364 
1365 /*++
1366 
1367 Routine Description:
1368 
1369  This routine is the worker routine for index enumeration. We are positioned
1370  at some dirent in the directory and will either return the first match
1371  at that point or look to the next entry. The Ccb contains details about
1372  the type of matching to do. If the user didn't specify a version in
1373  his search string then we only return the first version of a sequence
1374  of files with versions. We also don't return any associated files.
1375 
1376 Arguments:
1377 
1378  Ccb - Ccb for this directory handle.
1379 
1380  FileContext - File context already positioned at some entry in the directory.
1381 
1382  ReturnNextEntry - Indicates if we are returning this entry or should start
1383  with the next entry.
1384 
1385 Return Value:
1386 
1387  BOOLEAN - TRUE if next entry is found, FALSE otherwise.
1388 
1389 --*/
1390 
1391 {
1392  PDIRENT PreviousDirent = NULL;
1393  PDIRENT ThisDirent = &FileContext->InitialDirent->Dirent;
1394 
1395  BOOLEAN Found = FALSE;
1396 
1397  PAGED_CODE();
1398 
1399  //
1400  // Loop until we find a match or exaust the directory.
1401  //
1402 
1403  while (TRUE) {
1404 
1405  //
1406  // Move to the next entry unless we want to consider the current
1407  // entry.
1408  //
1409 
1410  if (ReturnNextEntry) {
1411 
1412  if (!CdLookupNextInitialFileDirent( IrpContext, Ccb->Fcb, FileContext )) {
1413 
1414  break;
1415  }
1416 
1417  PreviousDirent = ThisDirent;
1418  ThisDirent = &FileContext->InitialDirent->Dirent;
1419 
1420  CdUpdateDirentName( IrpContext, ThisDirent, FlagOn( Ccb->Flags, CCB_FLAG_IGNORE_CASE ));
1421 
1422  } else {
1423 
1424  ReturnNextEntry = TRUE;
1425  }
1426 
1427  //
1428  // Don't bother if we have a constant entry and are ignoring them.
1429  //
1430 
1431  if (FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
1433 
1434  continue;
1435  }
1436 
1437  //
1438  // Look at the current entry if it is not an associated file
1439  // and the name doesn't match the previous file if the version
1440  // name is not part of the search.
1441  //
1442 
1443  if (!FlagOn( ThisDirent->DirentFlags, CD_ATTRIBUTE_ASSOC )) {
1444 
1445  //
1446  // Check if this entry matches the previous entry except
1447  // for version number and whether we should return the
1448  // entry in that case. Go directly to the name comparison
1449  // if:
1450  //
1451  // There is no previous entry.
1452  // The search expression has a version component.
1453  // The name length doesn't match the length of the previous entry.
1454  // The base name strings don't match.
1455  //
1456 
1457  if ((PreviousDirent == NULL) ||
1458  (Ccb->SearchExpression.VersionString.Length != 0) ||
1459  (PreviousDirent->CdCaseFileName.FileName.Length != ThisDirent->CdCaseFileName.FileName.Length) ||
1460  FlagOn( PreviousDirent->DirentFlags, CD_ATTRIBUTE_ASSOC ) ||
1461  !RtlEqualMemory( PreviousDirent->CdCaseFileName.FileName.Buffer,
1462  ThisDirent->CdCaseFileName.FileName.Buffer,
1463  ThisDirent->CdCaseFileName.FileName.Length )) {
1464 
1465  //
1466  // If we match all names then return to our caller.
1467  //
1468 
1470 
1471  FileContext->ShortName.FileName.Length = 0;
1472  Found = TRUE;
1473  break;
1474  }
1475 
1476  //
1477  // Check if the long name matches the search expression.
1478  //
1479 
1480  if (CdIsNameInExpression( IrpContext,
1481  &ThisDirent->CdCaseFileName,
1482  &Ccb->SearchExpression,
1483  Ccb->Flags,
1484  TRUE )) {
1485 
1486  //
1487  // Let our caller know we found an entry.
1488  //
1489 
1490  Found = TRUE;
1491  FileContext->ShortName.FileName.Length = 0;
1492  break;
1493  }
1494 
1495  //
1496  // The long name didn't match so we need to check for a
1497  // possible short name match. There is no match if the
1498  // long name is 8dot3 or the search expression has a
1499  // version component. Special case the self and parent
1500  // entries.
1501  //
1502 
1503  if ((Ccb->SearchExpression.VersionString.Length == 0) &&
1504  !FlagOn( ThisDirent->Flags, DIRENT_FLAG_CONSTANT_ENTRY ) &&
1505  !CdIs8dot3Name( IrpContext,
1506  ThisDirent->CdFileName.FileName )) {
1507 
1508  CdGenerate8dot3Name( IrpContext,
1509  &ThisDirent->CdCaseFileName.FileName,
1510  ThisDirent->DirentOffset,
1511  FileContext->ShortName.FileName.Buffer,
1512  &FileContext->ShortName.FileName.Length );
1513 
1514  //
1515  // Check if this name matches.
1516  //
1517 
1518  if (CdIsNameInExpression( IrpContext,
1520  &Ccb->SearchExpression,
1521  Ccb->Flags,
1522  FALSE )) {
1523 
1524  //
1525  // Let our caller know we found an entry.
1526  //
1527 
1528  Found = TRUE;
1529  break;
1530  }
1531  }
1532  }
1533  }
1534  }
1535 
1536  //
1537  // If we found the entry then make sure we walk through all of the
1538  // file dirents.
1539  //
1540 
1541  if (Found) {
1542 
1543  CdLookupLastFileDirent( IrpContext, Ccb->Fcb, FileContext );
1544  }
1545 
1546  return Found;
1547 }
1548 
1549 
UNICODE_STRING VersionString
Definition: cdstruc.h:256
#define CCB_FLAG_ENUM_MATCH_ALL
Definition: cdstruc.h:1122
signed char * PCHAR
Definition: retypes.h:7
VOID CdCleanupFileContext(_In_ PIRP_CONTEXT IrpContext, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1636
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define CCB_FLAG_ENUM_RETURN_NEXT
Definition: cdstruc.h:1124
#define TAG_ENUM_EXPRESSION
Definition: cdprocs.h:80
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
#define CD_ATTRIBUTE_HIDDEN
Definition: cd.h:353
BOOLEAN CdIsNameInExpression(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME CurrentName, _In_ PCD_NAME SearchExpression, _In_ ULONG WildcardFlags, _In_ BOOLEAN CheckVersion)
Definition: namesup.c:844
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:987
#define Add2Ptr(PTR, INC)
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
#define SL_INDEX_SPECIFIED
Definition: iotypes.h:1794
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOID NTAPI FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
Definition: notify.c:1458
#define CdReleaseFile(IC, F)
Definition: cdprocs.h:1008
BOOLEAN CdIs8dot3Name(_In_ PIRP_CONTEXT IrpContext, _In_ UNICODE_STRING FileName)
Definition: namesup.c:429
_In_ PIRP Irp
Definition: csq.h:116
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
Definition: cdstruc.h:1073
Dirent DirentOffset
Definition: dirsup.c:444
#define CdMapUserBuffer(IC, UB)
Definition: cdprocs.h:376
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
CD_NAME CdCaseFileName
Definition: cdstruc.h:1663
VOID CdUpdateDirentName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PDIRENT Dirent, _In_ ULONG IgnoreCase)
Definition: dirsup.c:534
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define CdSetFidFromParentAndDirent(I, F, D)
Definition: cdstruc.h:1844
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
struct _FCB * RootIndexFcb
Definition: cdstruc.h:566
uint16_t * PWCHAR
Definition: typedefs.h:54
#define CdAcquireFileShared(IC, F)
Definition: cdprocs.h:1002
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
#define PAGED_CODE()
Definition: video.h:57
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1065
_SEH2_TRY
Definition: create.c:4250
#define CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD
Definition: cdstruc.h:1121
UCHAR Flags
Definition: cdstruc.h:1625
LARGE_INTEGER LastWriteTime
Definition: from_kernel.h:143
#define CCB_FLAG_ENUM_VERSION_MATCH_ALL
Definition: cdstruc.h:1123
#define CCB_FLAG_ENUM_INITIALIZED
Definition: cdstruc.h:1125
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
CdLookupInitialFileDirent(IrpContext, Fcb, FileContext, Fcb->StreamOffset)
#define CD_ATTRIBUTE_DIRECTORY
Definition: cd.h:354
LARGE_INTEGER AllocationSize
Definition: from_kernel.h:146
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define CCB_FLAG_IGNORE_CASE
Definition: cdstruc.h:1111
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
#define CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY
Definition: cdstruc.h:1126
return Found
Definition: dirsup.c:1270
UCHAR DirentFlags
Definition: cdstruc.h:1619
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: cdprocs.h:444
#define DIRENT_FLAG_CONSTANT_ENTRY
Definition: cdstruc.h:1677
VOID CdLookupLastFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1426
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define try_leave(S)
Definition: cdprocs.h:2190
VOID CdGenerate8dot3Name(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING FileName, _In_ ULONG DirentOffset, _Out_writes_bytes_to_(BYTE_COUNT_8_DOT_3, *ShortByteCount) PWCHAR ShortFileName, _Out_ PUSHORT ShortByteCount)
Definition: namesup.c:550
VOID CdInitializeEnumeration(_In_ PIRP_CONTEXT IrpContext, _In_ PIO_STACK_LOCATION IrpSp, _In_ PFCB Fcb, _Inout_ PCCB Ccb, _Inout_ PFILE_ENUM_CONTEXT FileContext, _Out_ PBOOLEAN ReturnNextEntry, _Out_ PBOOLEAN ReturnSingleEntry, _Out_ PBOOLEAN InitialQuery)
Definition: dirctrl.c:893
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
CdVerifyOrCreateDirStreamFile(IrpContext, Fcb)
char CCHAR
Definition: typedefs.h:50
#define CD_ATTRIBUTE_ASSOC
Definition: cd.h:355
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
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 _Inout_
Definition: no_sal2.h:244
#define NT_ERROR(Status)
Definition: umtypes.h:106
#define CCB_FLAG_ENUM_NAME_EXP_HAS_WILD
Definition: cdstruc.h:1120
ULONG Flags
Definition: ntfs.h:532
char * PBOOLEAN
Definition: retypes.h:11
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:226
static const WCHAR L[]
Definition: oid.c:1250
#define LlSectorAlign(L)
Definition: cdprocs.h:1594
#define SL_WATCH_TREE
Definition: iotypes.h:1796
#define CdConvertCdTimeToNtTime(IC, CD, NT)
Definition: cd.h:394
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1049
BOOLEAN CdEnumerateIndex(_In_ PIRP_CONTEXT IrpContext, _In_ PCCB Ccb, _Inout_ PFILE_ENUM_CONTEXT FileContext, _In_ BOOLEAN ReturnNextEntry)
Definition: dirctrl.c:1358
#define _In_
Definition: no_sal2.h:204
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
struct _FileName FileName
Definition: fatprocs.h:884
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
#define SL_RETURN_SINGLE_ENTRY
Definition: iotypes.h:1793
_SEH2_END
Definition: create.c:4424
#define CdFreePool(x)
Definition: cdprocs.h:2200
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
struct _FCB::@693::@696 Fcb
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
_SEH2_FINALLY
Definition: create.c:4395
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define SL_RESTART_SCAN
Definition: iotypes.h:1792
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
LARGE_INTEGER CreationTime
Definition: from_kernel.h:141
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PVCB Vcb
Definition: cdstruc.h:939
#define QuadAlign(Ptr)
Definition: cdprocs.h:1582
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
ULONG DirentOffset
Definition: cdstruc.h:1591
return STATUS_SUCCESS
Definition: btrfs.c:2966
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1114
UNICODE_STRING FileName
Definition: cdstruc.h:250
_Requires_lock_held_(_Global_critical_region_)
Definition: dirctrl.c:29
CD_NAME CdFileName
Definition: cdstruc.h:1662
#define CdInitializeFileContext(IC, FC)
Definition: cdprocs.h:532
Iosb Information
Definition: create.c:4377
LONGLONG QuadPart
Definition: typedefs.h:112
#define NT_ASSERT
Definition: rtlfuncs.h:3312