ReactOS  0.4.14-dev-115-g4576127
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 Fat called
12  by the dispatch driver.
13 
14 
15 --*/
16 
17 #include "fatprocs.h"
18 
19 //
20 // The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId (FAT_BUG_CHECK_DIRCTRL)
24 
25 //
26 // The local debug trace level
27 //
28 
29 #define Dbg (DEBUG_TRACE_DIRCTRL)
30 
32  L'.', DOS_QM, DOS_QM, DOS_QM};
33 
34 //
35 // Local procedure prototypes
36 //
37 
38 _Requires_lock_held_(_Global_critical_region_)
40 FatQueryDirectory (
41  IN PIRP_CONTEXT IrpContext,
42  IN PIRP Irp
43  );
44 
45 VOID
47  PIRP_CONTEXT IrpContext,
50  );
51 
52 _Requires_lock_held_(_Global_critical_region_)
54 FatNotifyChangeDirectory (
55  IN PIRP_CONTEXT IrpContext,
56  IN PIRP Irp
57  );
58 
59 #ifdef ALLOC_PRAGMA
60 #pragma alloc_text(PAGE, FatCommonDirectoryControl)
61 #pragma alloc_text(PAGE, FatFsdDirectoryControl)
62 #pragma alloc_text(PAGE, FatNotifyChangeDirectory)
63 #pragma alloc_text(PAGE, FatQueryDirectory)
64 #pragma alloc_text(PAGE, FatGetDirTimes)
65 
66 #endif
67 
68 
72 NTAPI
73 FatFsdDirectoryControl (
74  _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
76  )
77 
78 /*++
79 
80 Routine Description:
81 
82  This routine implements the FSD part of directory control
83 
84 Arguments:
85 
86  VolumeDeviceObject - Supplies the volume device object where the
87  file exists
88 
89  Irp - Supplies the Irp being processed
90 
91 Return Value:
92 
93  NTSTATUS - The FSD status for the IRP
94 
95 --*/
96 
97 {
99  PIRP_CONTEXT IrpContext = NULL;
100 
102 
103  PAGED_CODE();
104 
105  DebugTrace(+1, Dbg, "FatFsdDirectoryControl\n", 0);
106 
107  //
108  // Call the common directory Control routine, with blocking allowed if
109  // synchronous
110  //
111 
113 
115 
116  _SEH2_TRY {
117 
118  IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
119 
120  Status = FatCommonDirectoryControl( IrpContext, Irp );
121 
123 
124  //
125  // We had some trouble trying to perform the requested
126  // operation, so we'll abort the I/O request with
127  // the error status that we get back from the
128  // execption code
129  //
130 
131  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
132  } _SEH2_END;
133 
134  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
135 
137 
138  //
139  // And return to our caller
140  //
141 
142  DebugTrace(-1, Dbg, "FatFsdDirectoryControl -> %08lx\n", Status);
143 
144  UNREFERENCED_PARAMETER( VolumeDeviceObject );
145 
146  return Status;
147 }
148 
149 
150 _Requires_lock_held_(_Global_critical_region_)
151 NTSTATUS
152 FatCommonDirectoryControl (
153  IN PIRP_CONTEXT IrpContext,
154  IN PIRP Irp
155  )
156 
157 /*++
158 
159 Routine Description:
160 
161  This is the common routine for doing directory control operations called
162  by both the fsd and fsp threads
163 
164 Arguments:
165 
166  Irp - Supplies the Irp to process
167 
168 Return Value:
169 
170  NTSTATUS - The return status for the operation
171 
172 --*/
173 
174 {
177 
178  PAGED_CODE();
179 
180  //
181  // Get a pointer to the current Irp stack location
182  //
183 
185 
186  DebugTrace(+1, Dbg, "FatCommonDirectoryControl\n", 0);
187  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
188  DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction );
189 
190  //
191  // We know this is a directory control so we'll case on the
192  // minor function, and call a internal worker routine to complete
193  // the irp.
194  //
195 
196  switch ( IrpSp->MinorFunction ) {
197 
199 
200  Status = FatQueryDirectory( IrpContext, Irp );
201  break;
202 
204 
205  Status = FatNotifyChangeDirectory( IrpContext, Irp );
206  break;
207 
208  default:
209 
210  DebugTrace(0, Dbg, "Invalid Directory Control Minor Function %08lx\n", IrpSp->MinorFunction);
211 
214  break;
215  }
216 
217  DebugTrace(-1, Dbg, "FatCommonDirectoryControl -> %08lx\n", Status);
218 
219  return Status;
220 }
221 
222 
223 //
224 // Local Support Routine
225 //
226 
227 _Requires_lock_held_(_Global_critical_region_)
228 NTSTATUS
229 FatQueryDirectory (
230  IN PIRP_CONTEXT IrpContext,
231  IN PIRP Irp
232  )
233 
234 /*++
235 
236 Routine Description:
237 
238  This routine performs the query directory operation. It is responsible
239  for either completing of enqueuing the input Irp.
240 
241 Arguments:
242 
243  Irp - Supplies the Irp to process
244 
245 Return Value:
246 
247  NTSTATUS - The return status for the operation
248 
249 --*/
250 
251 {
254 
255  PVCB Vcb;
256  PDCB Dcb;
257  PCCB Ccb;
258  PBCB Bcb;
259 
260  ULONG i;
261  PUCHAR Buffer;
262  CLONG UserBufferLength;
263 
264  PUNICODE_STRING UniArgFileName;
265  WCHAR LongFileNameBuffer[ FAT_CREATE_INITIAL_NAME_BUF_SIZE];
266  UNICODE_STRING LongFileName;
267  UNICODE_STRING OrigFileName;
269  ULONG FileIndex;
270  ULONG MatchFlags = 0;
273  BOOLEAN IndexSpecified;
274 
275  BOOLEAN InitialQuery;
276  VBO CurrentVbo = 0;
277  BOOLEAN UpdateCcb;
278  PDIRENT Dirent;
279  UCHAR Fat8Dot3Buffer[12];
280  OEM_STRING Fat8Dot3String;
281  ULONG DiskAllocSize;
282 
283  ULONG NextEntry;
284  ULONG LastEntry;
285 
287  PFILE_FULL_DIR_INFORMATION FullDirInfo;
288  PFILE_BOTH_DIR_INFORMATION BothDirInfo;
289  PFILE_ID_FULL_DIR_INFORMATION IdFullDirInfo;
290  PFILE_ID_BOTH_DIR_INFORMATION IdBothDirInfo;
291  PFILE_NAMES_INFORMATION NamesInfo;
292 
293 
294  PAGED_CODE();
295 
296  //
297  // Get the current Stack location
298  //
299 
301 
302  //
303  // Display the input values.
304  //
305  DebugTrace(+1, Dbg, "FatQueryDirectory...\n", 0);
306  DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
307  DebugTrace( 0, Dbg, " Irp = %p\n", Irp);
308  DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryDirectory.Length);
309  DebugTrace( 0, Dbg, " ->FileName = %wZ\n", IrpSp->Parameters.QueryDirectory.FileName);
310  DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryDirectory.FileInformationClass);
311  DebugTrace( 0, Dbg, " ->FileIndex = %08lx\n", IrpSp->Parameters.QueryDirectory.FileIndex);
312  DebugTrace( 0, Dbg, " ->UserBuffer = %p\n", Irp->AssociatedIrp.SystemBuffer);
313  DebugTrace( 0, Dbg, " ->RestartScan = %08lx\n", FlagOn( IrpSp->Flags, SL_RESTART_SCAN ));
314  DebugTrace( 0, Dbg, " ->ReturnSingleEntry = %08lx\n", FlagOn( IrpSp->Flags, SL_RETURN_SINGLE_ENTRY ));
315  DebugTrace( 0, Dbg, " ->IndexSpecified = %08lx\n", FlagOn( IrpSp->Flags, SL_INDEX_SPECIFIED ));
316 
317  //
318  // Reference our input parameters to make things easier
319  //
320 
321  UserBufferLength = IrpSp->Parameters.QueryDirectory.Length;
322 
323  FileInformationClass = IrpSp->Parameters.QueryDirectory.FileInformationClass;
324  FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;
325 
326  UniArgFileName = IrpSp->Parameters.QueryDirectory.FileName;
327 
330  IndexSpecified = BooleanFlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);
331 
332  //
333  // Check on the type of open. We return invalid parameter for all
334  // but UserDirectoryOpens. Also check that the filename is a valid
335  // UNICODE string.
336  //
337 
339  &Vcb,
340  &Dcb,
341  &Ccb) != UserDirectoryOpen ||
342  (UniArgFileName &&
343  UniArgFileName->Length % sizeof(WCHAR))) {
344 
346  DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0);
347 
349  }
350 
351  //
352  // Initialize the local variables.
353  //
354 
355  Bcb = NULL;
356  UpdateCcb = TRUE;
357  Dirent = NULL;
358 
359  Fat8Dot3String.MaximumLength = 12;
360  Fat8Dot3String.Buffer = (PCHAR)Fat8Dot3Buffer;
361 
362  LongFileName.Length = 0;
363  LongFileName.MaximumLength = sizeof( LongFileNameBuffer);
364  LongFileName.Buffer = LongFileNameBuffer;
365 
366  InitialQuery = (BOOLEAN)((Ccb->UnicodeQueryTemplate.Buffer == NULL) &&
369  Irp->IoStatus.Information = 0;
370 
371  DiskAllocSize = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
372 
373  //
374  // If this is the initial query, then grab exclusive access in
375  // order to update the search string in the Ccb. We may
376  // discover that we are not the initial query once we grab the Fcb
377  // and downgrade our status.
378  //
379  // If restartscan is set, we may be replacing the query template,
380  // so take the FCB exclusive to protect against multiple people
381  // changing the CCB at once.
382  //
383 
384  if (InitialQuery || RestartScan) {
385 
386  if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) {
387 
388  DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
389  Status = FatFsdPostRequest( IrpContext, Irp );
390  DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);
391 
392  return Status;
393  }
394 
395  if (!RestartScan && (Ccb->UnicodeQueryTemplate.Buffer != NULL)) {
396 
397  InitialQuery = FALSE;
398 
399  FatConvertToSharedFcb( IrpContext, Dcb );
400  }
401 
402  } else {
403 
404  if (!FatAcquireSharedFcb( IrpContext, Dcb )) {
405 
406  DebugTrace(0, Dbg, "FatQueryDirectory -> Enqueue to Fsp\n", 0);
407  Status = FatFsdPostRequest( IrpContext, Irp );
408  DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);
409 
410  return Status;
411 
412  }
413  }
414 
415  _SEH2_TRY {
416 
417  ULONG BaseLength;
418  ULONG BytesConverted;
419 
420  //
421  // If we are in the Fsp now because we had to wait earlier,
422  // we must map the user buffer, otherwise we can use the
423  // user's buffer directly.
424  //
425 
426  Buffer = FatMapUserBuffer( IrpContext, Irp );
427 
428  //
429  // Make sure the Dcb is still good.
430  //
431 
432  FatVerifyFcb( IrpContext, Dcb );
433 
434  //
435  // Determine where to start the scan. Highest priority is given
436  // to the file index. Lower priority is the restart flag. If
437  // neither of these is specified, then the Vbo offset field in the
438  // Ccb is used.
439  //
440 
441  if (IndexSpecified) {
442 
443  CurrentVbo = FileIndex + sizeof( DIRENT );
444 
445  } else if (RestartScan) {
446 
447  CurrentVbo = 0;
448  Ccb->OffsetToStartSearchFrom = 0;
449 
450  } else {
451 
452  CurrentVbo = Ccb->OffsetToStartSearchFrom;
453  }
454 
455  //
456  // If this is the first try then allocate a buffer for the file
457  // name.
458  //
459 
460  if (InitialQuery ||
461  (RestartScan && UniArgFileName != NULL && UniArgFileName->Length != 0)) {
462 
463  //
464  // If we're restarting the scan, clear out the pattern in the Ccb and regenerate it,
465  //
466 
467  if (RestartScan) {
468 
469  if (Ccb->UnicodeQueryTemplate.Buffer) {
470 
472 
473  ExFreePoolWithTag(Ccb->UnicodeQueryTemplate.Buffer, TAG_FILENAME_BUFFER);
475  }
476 
477  Ccb->UnicodeQueryTemplate.Buffer = NULL;
478  Ccb->UnicodeQueryTemplate.Length = 0;
479  Ccb->UnicodeQueryTemplate.MaximumLength = 0;
480  }
481 
482  if (Ccb->OemQueryTemplate.Wild.Buffer) {
483 
485 
486  RtlFreeOemString( &Ccb->OemQueryTemplate.Wild );
488  }
489 
490  Ccb->OemQueryTemplate.Wild.Buffer = NULL;
491  Ccb->OemQueryTemplate.Wild.Length = 0;
492  Ccb->OemQueryTemplate.Wild.MaximumLength = 0;
493  }
494 
495  Ccb->ContainsWildCards = FALSE;
500 
501  }
502 
503  //
504  // If either:
505  //
506  // - No name was specified
507  // - An empty name was specified
508  // - We received a '*'
509  // - The user specified the DOS equivolent of ????????.???
510  //
511  // then match all names.
512  //
513 
514  if ((UniArgFileName == NULL) ||
515  (UniArgFileName->Length == 0) ||
516  (UniArgFileName->Buffer == NULL) ||
517  ((UniArgFileName->Length == sizeof(WCHAR)) &&
518  (UniArgFileName->Buffer[0] == L'*')) ||
519  ((UniArgFileName->Length == 12*sizeof(WCHAR)) &&
520  (RtlEqualMemory( UniArgFileName->Buffer,
521  Fat8QMdot3QM,
522  12*sizeof(WCHAR) )))) {
523 
524  Ccb->ContainsWildCards = TRUE;
525 
527 
528  } else {
529 
530  BOOLEAN ExtendedName = FALSE;
531  OEM_STRING LocalBestFit;
532 
533  //
534  // First and formost, see if the name has wild cards.
535  //
536 
537  Ccb->ContainsWildCards =
538  FsRtlDoesNameContainWildCards( UniArgFileName );
539 
540  //
541  // Now check to see if the name contains any extended
542  // characters
543  //
544 
545  for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {
546 
547  if (UniArgFileName->Buffer[i] >= 0x80) {
548 
549  ExtendedName = TRUE;
550  break;
551  }
552  }
553 
554  //
555  // OK, now do the conversions we need.
556  //
557 
558  if (ExtendedName) {
559 
560  Status = RtlUpcaseUnicodeString( &Ccb->UnicodeQueryTemplate,
561  UniArgFileName,
562  TRUE );
563 
564  if (!NT_SUCCESS(Status)) {
565 
566  try_return( Status );
567  }
568 
570 
571  //
572  // Upcase the name and convert it to the Oem code page.
573  //
574 
576  UniArgFileName,
577  TRUE );
578 
579  //
580  // If this conversion failed for any reason other than
581  // an unmappable character fail the request.
582  //
583 
584  if (!NT_SUCCESS(Status)) {
585 
587 
589 
590  } else {
591 
592  try_return( Status );
593  }
594 
595  } else {
596 
598  }
599 
600  } else {
601 
602  PVOID Buffers;
603 
604  //
605  // This case is optimized because I know I only have to
606  // worry about a-z.
607  //
608 
610  UniArgFileName->Length +
611  UniArgFileName->Length / sizeof(WCHAR),
613 
614  Ccb->UnicodeQueryTemplate.Buffer = Buffers;
615  Ccb->UnicodeQueryTemplate.Length = UniArgFileName->Length;
616  Ccb->UnicodeQueryTemplate.MaximumLength = UniArgFileName->Length;
617 
618  LocalBestFit.Buffer = (PCHAR)Buffers + UniArgFileName->Length;
619  LocalBestFit.Length = UniArgFileName->Length / sizeof(WCHAR);
620  LocalBestFit.MaximumLength = LocalBestFit.Length;
621 
623 
624  for (i=0; i < UniArgFileName->Length / sizeof(WCHAR); i++) {
625 
626  WCHAR c = UniArgFileName->Buffer[i];
627 
628  LocalBestFit.Buffer[i] = (UCHAR)
629  (Ccb->UnicodeQueryTemplate.Buffer[i] =
630  (c < 'a' ? c : c <= 'z' ? c - ('a' - 'A') : c));
631  }
632  }
633 
634  //
635  // At this point we now have the upcased unicode name,
636  // and the two Oem names if they could be represented in
637  // this code page.
638  //
639  // Now determine if the Oem names are legal for what we
640  // going to try and do. Mark them as not usable is they
641  // are not legal. Note that we can optimize extended names
642  // since they are actually both the same string.
643  //
644 
646  !FatIsNameShortOemValid( IrpContext,
647  LocalBestFit,
648  Ccb->ContainsWildCards,
649  FALSE,
650  FALSE )) {
651 
652  if (ExtendedName) {
653 
654  RtlFreeOemString( &LocalBestFit );
656  }
657 
659  }
660 
661  //
662  // OK, now both locals oem strings correctly reflect their
663  // usability. Now we want to load up the Ccb structure.
664  //
665  // Now we will branch on two paths of wheather the name
666  // is wild or not.
667  //
668 
670 
671  if (Ccb->ContainsWildCards) {
672 
673  Ccb->OemQueryTemplate.Wild = LocalBestFit;
674 
675  } else {
676 
677  FatStringTo8dot3( IrpContext,
678  LocalBestFit,
679  &Ccb->OemQueryTemplate.Constant );
680 
682 
683  RtlFreeOemString( &LocalBestFit );
685  }
686  }
687  }
688  }
689 
690  //
691  // We convert to shared access.
692  //
693 
694  FatConvertToSharedFcb( IrpContext, Dcb );
695  }
696 
697  LastEntry = 0;
698  NextEntry = 0;
699 
700  switch (FileInformationClass) {
701 
703 
705  FileName[0] );
706  break;
707 
709 
711  FileName[0] );
712  break;
713 
715 
717  FileName[0] );
718  break;
719 
721 
722  BaseLength = FIELD_OFFSET( FILE_NAMES_INFORMATION,
723  FileName[0] );
724  break;
725 
727 
729  FileName[0] );
730  break;
731 
733 
735  FileName[0] );
736  break;
737 
738  default:
739 
741  }
742 
743  //
744  // At this point we are about to enter our query loop. We have
745  // determined the index into the directory file to begin the
746  // search. LastEntry and NextEntry are used to index into the user
747  // buffer. LastEntry is the last entry we've added, NextEntry is
748  // current one we're working on. If NextEntry is non-zero, then
749  // at least one entry was added.
750  //
751 
752  while ( TRUE ) {
753 
754  VBO NextVbo;
756  ULONG BytesRemainingInBuffer;
757  BOOLEAN FileNameDos;
758 
759  DebugTrace(0, Dbg, "FatQueryDirectory -> Top of loop\n", 0);
760 
761  //
762  // If the user had requested only a single match and we have
763  // returned that, then we stop at this point.
764  //
765 
766  if (ReturnSingleEntry && NextEntry != 0) {
767 
768  try_return( Status );
769  }
770 
771 
772  //
773  // We call FatLocateDirent to lock down the next matching dirent.
774  //
775 
776  FatLocateDirent( IrpContext,
777  Dcb,
778  Ccb,
779  CurrentVbo,
780  &MatchFlags,
781  &Dirent,
782  &Bcb,
783  &NextVbo,
784  &FileNameDos,
785  &LongFileName,
786  &OrigFileName );
787 
788  //
789  // If we didn't receive a dirent, then we are at the end of the
790  // directory. If we have returned any files, we exit with
791  // success, otherwise we return STATUS_NO_MORE_FILES.
792  //
793 
794  if (!Dirent) {
795 
796  DebugTrace(0, Dbg, "FatQueryDirectory -> No dirent\n", 0);
797 
798  if (NextEntry == 0) {
799 
800  UpdateCcb = FALSE;
801 
802  if (InitialQuery) {
803 
805 
806  } else {
807 
809  }
810  }
811 
812  try_return( Status );
813  }
814 
815 
816  //
817  // Protect access to the user buffer with an exception handler.
818  // Since (at our request) IO doesn't buffer these requests, we have
819  // to guard against a user messing with the page protection and other
820  // such trickery.
821  //
822 
823  _SEH2_TRY {
824 
825  Fat8dot3ToString( IrpContext, Dirent, TRUE, &Fat8Dot3String );
826 
827 
828  if (LongFileName.Length == 0) {
829 
830  //
831  // Now we have an entry to return to our caller. We'll convert
832  // the name from the form in the dirent to a <name>.<ext> form.
833  // We'll case on the type of information requested and fill up
834  // the user buffer if everything fits.
835  //
836 
837  //
838  // Determine the UNICODE length of the file name.
839  //
840 
842 
843  //
844  // Here are the rules concerning filling up the buffer:
845  //
846  // 1. The Io system garentees that there will always be
847  // enough room for at least one base record.
848  //
849  // 2. If the full first record (including file name) cannot
850  // fit, as much of the name as possible is copied and
851  // STATUS_BUFFER_OVERFLOW is returned.
852  //
853  // 3. If a subsequent record cannot completely fit into the
854  // buffer, none of it (as in 0 bytes) is copied, and
855  // STATUS_SUCCESS is returned. A subsequent query will
856  // pick up with this record.
857  //
858 
859  BytesRemainingInBuffer = UserBufferLength - NextEntry;
860 
861  if ( (NextEntry != 0) &&
862  ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
863  (UserBufferLength < NextEntry) ) ) {
864 
865  DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
866 
868  }
869 
870  NT_ASSERT( BytesRemainingInBuffer >= BaseLength );
871 
872  //
873  // Zero the base part of the structure.
874  //
875 
876  RtlZeroMemory( &Buffer[NextEntry], BaseLength );
877 
878  switch ( FileInformationClass ) {
879 
880  //
881  // Now fill the base parts of the strucure that are applicable.
882  //
883 
888 
889  DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
890 
891  //
892  // Get the Ea file length.
893  //
894 
895  FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
896 
897  //
898  // If the EAs are corrupt, ignore the error. We don't want
899  // to abort the directory query.
900  //
901 
902  _SEH2_TRY {
903 
904  FatGetEaLength( IrpContext,
905  Vcb,
906  Dirent,
907  &FullDirInfo->EaSize );
908 
910 
911  FatResetExceptionState( IrpContext );
912  FullDirInfo->EaSize = 0;
913  } _SEH2_END;
914 
916 
917  DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
918 
919  FatGetDirTimes( IrpContext, Dirent, DirInfo );
920 
921  DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
922 
923  if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
924 
925 
926  DirInfo->AllocationSize.QuadPart =
927  (((Dirent->FileSize + DiskAllocSize - 1) / DiskAllocSize) *
928  DiskAllocSize );
929  }
930 
931  if (Dirent->Attributes != 0) {
932  DirInfo->FileAttributes = Dirent->Attributes;
933 
934 
935  } else {
936 
937  DirInfo->FileAttributes = 0;
938 
940  }
941 
942  DirInfo->FileIndex = NextVbo;
943 
944  DirInfo->FileNameLength = FileNameLength;
945 
946  DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
947 
948  break;
949 
951 
952  DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
953 
954  NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
955 
956  NamesInfo->FileIndex = NextVbo;
957 
958  NamesInfo->FileNameLength = FileNameLength;
959 
960  DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
961 
962  break;
963 
964  default:
965 
966 #ifdef _MSC_VER
967 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
968 #endif
970  }
971 
972  BytesConverted = 0;
973 
974  Status = RtlOemToUnicodeN( (PWCH)&Buffer[NextEntry + BaseLength],
975  BytesRemainingInBuffer - BaseLength,
976  &BytesConverted,
977  Fat8Dot3String.Buffer,
978  Fat8Dot3String.Length );
979 
980  //
981  // Check for the case that a single entry doesn't fit.
982  // This should only get this far on the first entry
983  //
984 
985  if (BytesConverted < FileNameLength) {
986 
987  NT_ASSERT( NextEntry == 0 );
989  }
990 
991  //
992  // Set up the previous next entry offset
993  //
994 
995  *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
996 
997  //
998  // And indicate how much of the user buffer we have currently
999  // used up. We must compute this value before we long align
1000  // ourselves for the next entry
1001  //
1002 
1003  Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
1004  BaseLength + BytesConverted;
1005 
1006  //
1007  // If something happened with the conversion, bail here.
1008  //
1009 
1010  if ( !NT_SUCCESS( Status ) ) {
1011 
1012  try_return( NOTHING );
1013  }
1014 
1015  } else {
1016 
1017  ULONG ShortNameLength;
1018 
1019  FileNameLength = LongFileName.Length;
1020 
1021  //
1022  // Here are the rules concerning filling up the buffer:
1023  //
1024  // 1. The Io system garentees that there will always be
1025  // enough room for at least one base record.
1026  //
1027  // 2. If the full first record (including file name) cannot
1028  // fit, as much of the name as possible is copied and
1029  // STATUS_BUFFER_OVERFLOW is returned.
1030  //
1031  // 3. If a subsequent record cannot completely fit into the
1032  // buffer, none of it (as in 0 bytes) is copied, and
1033  // STATUS_SUCCESS is returned. A subsequent query will
1034  // pick up with this record.
1035  //
1036 
1037  BytesRemainingInBuffer = UserBufferLength - NextEntry;
1038 
1039  if ( (NextEntry != 0) &&
1040  ( (BaseLength + FileNameLength > BytesRemainingInBuffer) ||
1041  (UserBufferLength < NextEntry) ) ) {
1042 
1043  DebugTrace(0, Dbg, "Next entry won't fit\n", 0);
1044 
1046  }
1047 
1048  NT_ASSERT( BytesRemainingInBuffer >= BaseLength );
1049 
1050  //
1051  // Zero the base part of the structure.
1052  //
1053 
1054  RtlZeroMemory( &Buffer[NextEntry], BaseLength );
1055 
1056  switch ( FileInformationClass ) {
1057 
1058  //
1059  // Now fill the base parts of the strucure that are applicable.
1060  //
1061 
1064 
1065  BothDirInfo = (PFILE_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
1066 
1067  //
1068  // Now we have an entry to return to our caller. We'll convert
1069  // the name from the form in the dirent to a <name>.<ext> form.
1070  // We'll case on the type of information requested and fill up
1071  // the user buffer if everything fits.
1072  //
1073 
1074  Fat8dot3ToString( IrpContext, Dirent, FALSE, &Fat8Dot3String );
1075 
1076  NT_ASSERT( Fat8Dot3String.Length <= 12 );
1077 
1078  Status = RtlOemToUnicodeN( &BothDirInfo->ShortName[0],
1079  12*sizeof(WCHAR),
1080  &ShortNameLength,
1081  Fat8Dot3String.Buffer,
1082  Fat8Dot3String.Length );
1083 
1085  NT_ASSERT( ShortNameLength <= 12*sizeof(WCHAR) );
1086 
1087  //
1088  // Copy the length into the dirinfo structure. Note
1089  // that the LHS below is a USHORT, so it can not
1090  // be specificed as the OUT parameter above.
1091  //
1092 
1093  BothDirInfo->ShortNameLength = (UCHAR)ShortNameLength;
1094 
1095  //
1096  // If something happened with the conversion, bail here.
1097  //
1098 
1099  if ( !NT_SUCCESS( Status ) ) {
1100 
1101  try_return( NOTHING );
1102  }
1103 
1106 
1107  DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file full directory information\n", 0);
1108 
1109  //
1110  // Get the Ea file length.
1111  //
1112 
1113  FullDirInfo = (PFILE_FULL_DIR_INFORMATION)&Buffer[NextEntry];
1114 
1115  //
1116  // If the EAs are corrupt, ignore the error. We don't want
1117  // to abort the directory query.
1118  //
1119 
1120  _SEH2_TRY {
1121 
1122  FatGetEaLength( IrpContext,
1123  Vcb,
1124  Dirent,
1125  &FullDirInfo->EaSize );
1126 
1128 
1129  FatResetExceptionState( IrpContext );
1130  FullDirInfo->EaSize = 0;
1131  } _SEH2_END;
1132 
1134 
1135  DirInfo = (PFILE_DIRECTORY_INFORMATION)&Buffer[NextEntry];
1136 
1137  FatGetDirTimes( IrpContext, Dirent, DirInfo );
1138 
1139  DirInfo->EndOfFile.QuadPart = Dirent->FileSize;
1140 
1141  if (!FlagOn( Dirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY )) {
1142 
1143 
1144  DirInfo->AllocationSize.QuadPart = (
1145  (( Dirent->FileSize
1146  + DiskAllocSize - 1 )
1147  / DiskAllocSize )
1148  * DiskAllocSize );
1149  }
1150 
1151  if (Dirent->Attributes != 0) {
1152  DirInfo->FileAttributes = Dirent->Attributes;
1153 
1154 
1155  } else {
1156 
1157  DirInfo->FileAttributes = 0;
1158 
1159 
1161  }
1162 
1163 
1164  DirInfo->FileIndex = NextVbo;
1165 
1166  DirInfo->FileNameLength = FileNameLength;
1167 
1168  DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String);
1169 
1170  break;
1171 
1172  case FileNamesInformation:
1173 
1174  DebugTrace(0, Dbg, "FatQueryDirectory -> Getting file names information\n", 0);
1175 
1176  NamesInfo = (PFILE_NAMES_INFORMATION)&Buffer[NextEntry];
1177 
1178  NamesInfo->FileIndex = NextVbo;
1179 
1180  NamesInfo->FileNameLength = FileNameLength;
1181 
1182  DebugTrace(0, Dbg, "FatQueryDirectory -> Name = \"%Z\"\n", &Fat8Dot3String );
1183 
1184  break;
1185 
1186  default:
1187 
1188 #ifdef _MSC_VER
1189 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1190 #endif
1192  }
1193 
1194  BytesConverted = BytesRemainingInBuffer - BaseLength >= FileNameLength ?
1195  FileNameLength :
1196  BytesRemainingInBuffer - BaseLength;
1197 
1198  RtlCopyMemory( &Buffer[NextEntry + BaseLength],
1199  &LongFileName.Buffer[0],
1200  BytesConverted );
1201 
1202  //
1203  // Set up the previous next entry offset
1204  //
1205 
1206  *((PULONG)(&Buffer[LastEntry])) = NextEntry - LastEntry;
1207 
1208  //
1209  // And indicate how much of the user buffer we have currently
1210  // used up. We must compute this value before we long align
1211  // ourselves for the next entry
1212  //
1213 
1214  Irp->IoStatus.Information = QuadAlign( Irp->IoStatus.Information ) +
1215  BaseLength + BytesConverted;
1216 
1217  //
1218  // Check for the case that a single entry doesn't fit.
1219  // This should only get this far on the first entry.
1220  //
1221 
1222  if (BytesConverted < FileNameLength) {
1223 
1224  NT_ASSERT( NextEntry == 0 );
1225 
1227  }
1228  }
1229 
1230  //
1231  // Finish up by filling in the FileId
1232  //
1233 
1234  switch ( FileInformationClass ) {
1235 
1237 
1238  IdBothDirInfo = (PFILE_ID_BOTH_DIR_INFORMATION)&Buffer[NextEntry];
1239  IdBothDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
1240  break;
1241 
1243 
1244  IdFullDirInfo = (PFILE_ID_FULL_DIR_INFORMATION)&Buffer[NextEntry];
1245  IdFullDirInfo->FileId.QuadPart = FatGenerateFileIdFromDirentAndOffset( Dcb, Dirent, NextVbo );
1246  break;
1247 
1248  default:
1249  break;
1250  }
1251 
1253 
1254  //
1255  // We had a problem filling in the user's buffer, so stop and
1256  // fail this request. This is the only reason any exception
1257  // would have occured at this level.
1258  //
1259 
1260  Irp->IoStatus.Information = 0;
1261  UpdateCcb = FALSE;
1263  } _SEH2_END;
1264 
1265  //
1266  // Set ourselves up for the next iteration
1267  //
1268 
1269  LastEntry = NextEntry;
1270  NextEntry += (ULONG)QuadAlign(BaseLength + BytesConverted);
1271 
1272  CurrentVbo = NextVbo + sizeof( DIRENT );
1273  }
1274 
1275  try_exit: NOTHING;
1276  } _SEH2_FINALLY {
1277 
1278  DebugUnwind( FatQueryDirectory );
1279 
1280  FatReleaseFcb( IrpContext, Dcb );
1281 
1282  //
1283  // Unpin data in cache if still held.
1284  //
1285 
1286  FatUnpinBcb( IrpContext, Bcb );
1287 
1288  //
1289  // Free any dynamically allocated string buffer
1290  //
1291 
1292  FatFreeStringBuffer( &LongFileName);
1293 
1294  //
1295  // Perform any cleanup. If this is the first query, then store
1296  // the filename in the Ccb if successful. Also update the
1297  // VBO index for the next search. This is done by transferring
1298  // from shared access to exclusive access and copying the
1299  // data from the local copies.
1300  //
1301 
1302  if (!_SEH2_AbnormalTermination()) {
1303 
1304  if (UpdateCcb) {
1305 
1306  //
1307  // Store the most recent VBO to use as a starting point for
1308  // the next search.
1309  //
1310 
1311  Ccb->OffsetToStartSearchFrom = CurrentVbo;
1312  }
1313 
1314  FatCompleteRequest( IrpContext, Irp, Status );
1315  }
1316 
1317  DebugTrace(-1, Dbg, "FatQueryDirectory -> %08lx\n", Status);
1318 
1319  } _SEH2_END;
1320 
1321  return Status;
1322 }
1323 
1324 
1325 //
1326 // Local Support Routine
1327 //
1328 
1329 VOID
1331  PIRP_CONTEXT IrpContext,
1332  PDIRENT Dirent,
1334  )
1335 
1336 /*++
1337 
1338 Routine Description:
1339 
1340  This routine pulls the date/time information from a dirent and fills
1341  in the DirInfo structure.
1342 
1343 Arguments:
1344 
1345  Dirent - Supplies the dirent
1346  DirInfo - Supplies the target structure
1347 
1348 Return Value:
1349 
1350  VOID
1351 
1352 --*/
1353 
1354 
1355 {
1356  PAGED_CODE();
1357 
1358  //
1359  // Start with the Last Write Time.
1360  //
1361 
1362  DirInfo->LastWriteTime =
1363  FatFatTimeToNtTime( IrpContext,
1365  0 );
1366 
1367  //
1368  // These fields are only non-zero when in Chicago mode.
1369  //
1370 
1371  if (FatData.ChicagoMode) {
1372 
1373  //
1374  // Do a quick check here for Creation and LastAccess
1375  // times that are the same as the LastWriteTime.
1376  //
1377 
1378  if (*((UNALIGNED LONG *)&Dirent->CreationTime) ==
1379  *((UNALIGNED LONG *)&Dirent->LastWriteTime)) {
1380 
1381  DirInfo->CreationTime.QuadPart =
1382 
1383  DirInfo->LastWriteTime.QuadPart +
1384  Dirent->CreationMSec * 10 * 1000 * 10;
1385 
1386  } else {
1387 
1388  //
1389  // Only do the really hard work if this field is non-zero.
1390  //
1391 
1392  if (((PUSHORT)Dirent)[8] != 0) {
1393 
1394  DirInfo->CreationTime =
1395  FatFatTimeToNtTime( IrpContext,
1397  Dirent->CreationMSec );
1398 
1399  } else {
1400 
1402  &DirInfo->CreationTime );
1403  }
1404  }
1405 
1406  //
1407  // Do a quick check for LastAccessDate.
1408  //
1409 
1410  if (*((PUSHORT)&Dirent->LastAccessDate) ==
1411  *((PUSHORT)&Dirent->LastWriteTime.Date)) {
1412 
1413  PFAT_TIME WriteTime;
1414 
1415  WriteTime = &Dirent->LastWriteTime.Time;
1416 
1417  DirInfo->LastAccessTime.QuadPart =
1418  DirInfo->LastWriteTime.QuadPart -
1419  UInt32x32To64(((WriteTime->DoubleSeconds * 2) +
1420  (WriteTime->Minute * 60) +
1421  (WriteTime->Hour * 60 * 60)),
1422  1000 * 1000 * 10);
1423 
1424  } else {
1425 
1426  //
1427  // Only do the really hard work if this field is non-zero.
1428  //
1429 
1430  if (((PUSHORT)Dirent)[9] != 0) {
1431 
1432  DirInfo->LastAccessTime =
1433  FatFatDateToNtTime( IrpContext,
1434  Dirent->LastAccessDate );
1435 
1436  } else {
1437 
1439  &DirInfo->LastAccessTime );
1440  }
1441  }
1442  }
1443 }
1444 
1445 
1446 //
1447 // Local Support Routine
1448 //
1449 
1450 _Requires_lock_held_(_Global_critical_region_)
1451 NTSTATUS
1452 FatNotifyChangeDirectory (
1453  IN PIRP_CONTEXT IrpContext,
1454  IN PIRP Irp
1455  )
1456 
1457 /*++
1458 
1459 Routine Description:
1460 
1461  This routine performs the notify change directory operation. It is
1462  responsible for either completing of enqueuing the input Irp.
1463 
1464 Arguments:
1465 
1466  Irp - Supplies the Irp to process
1467 
1468 Return Value:
1469 
1470  NTSTATUS - The return status for the operation
1471 
1472 --*/
1473 
1474 {
1477  PVCB Vcb;
1478  PDCB Dcb;
1479  PCCB Ccb;
1482 
1484 
1485  PAGED_CODE();
1486 
1487  //
1488  // Get the current Stack location
1489  //
1490 
1492 
1493  DebugTrace(+1, Dbg, "FatNotifyChangeDirectory...\n", 0);
1494  DebugTrace( 0, Dbg, " Wait = %08lx\n", FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
1495  DebugTrace( 0, Dbg, " Irp = %p\n", Irp);
1496  DebugTrace( 0, Dbg, " ->CompletionFilter = %08lx\n", IrpSp->Parameters.NotifyDirectory.CompletionFilter);
1497 
1498  //
1499  // Always set the wait flag in the Irp context for the original request.
1500  //
1501 
1502  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
1503 
1504  //
1505  // Assume we don't complete request.
1506  //
1507 
1509 
1510  //
1511  // Check on the type of open. We return invalid parameter for all
1512  // but UserDirectoryOpens.
1513  //
1514 
1516  &Vcb,
1517  &Dcb,
1518  &Ccb ) != UserDirectoryOpen) {
1519 
1521  DebugTrace(-1, Dbg, "FatQueryDirectory -> STATUS_INVALID_PARAMETER\n", 0);
1522 
1523  return STATUS_INVALID_PARAMETER;
1524 
1525  }
1526 
1527  //
1528  // Reference our input parameter to make things easier
1529  //
1530 
1531  CompletionFilter = IrpSp->Parameters.NotifyDirectory.CompletionFilter;
1533 
1534  //
1535  // Try to acquire exclusive access to the Dcb and enqueue the Irp to the
1536  // Fsp if we didn't get access
1537  //
1538 
1539  if (!FatAcquireExclusiveFcb( IrpContext, Dcb )) {
1540 
1541  DebugTrace(0, Dbg, "FatNotifyChangeDirectory -> Cannot Acquire Fcb\n", 0);
1542 
1543  Status = FatFsdPostRequest( IrpContext, Irp );
1544 
1545  DebugTrace(-1, Dbg, "FatNotifyChangeDirectory -> %08lx\n", Status);
1546  return Status;
1547  }
1548 
1549  _SEH2_TRY {
1550 
1551  //
1552  // Make sure the Fcb is still good
1553  //
1554 
1555  FatVerifyFcb( IrpContext, Dcb );
1556 
1557  //
1558  // We need the full name.
1559  //
1560 
1561  FatSetFullFileNameInFcb( IrpContext, Dcb );
1562 
1563  //
1564  // If the file is marked as DELETE_PENDING then complete this
1565  // request immediately.
1566  //
1567 
1568  if (FlagOn( Dcb->FcbState, FCB_STATE_DELETE_ON_CLOSE )) {
1569 
1570  FatRaiseStatus( IrpContext, STATUS_DELETE_PENDING );
1571  }
1572 
1573  //
1574  // Call the Fsrtl package to process the request.
1575  //
1576 
1577  FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
1578  &Vcb->DirNotifyList,
1579  Ccb,
1580  (PSTRING)&Dcb->FullFileName,
1581  WatchTree,
1582  FALSE,
1584  Irp,
1585  NULL,
1586  NULL );
1587 
1589 
1591 
1592  } _SEH2_FINALLY {
1593 
1594  DebugUnwind( FatNotifyChangeDirectory );
1595 
1596  FatReleaseFcb( IrpContext, Dcb );
1597 
1598  //
1599  // If the dir notify package is holding the Irp, we discard the
1600  // the IrpContext.
1601  //
1602 
1603  if (CompleteRequest) {
1604 
1605  FatCompleteRequest( IrpContext, FatNull, 0 );
1606  }
1607 
1608  DebugTrace(-1, Dbg, "FatNotifyChangeDirectory -> %08lx\n", Status);
1609  } _SEH2_END;
1610 
1611  return Status;
1612 }
1613 
LARGE_INTEGER LastAccessTime
Definition: winternl.h:517
LONGLONG CreationTime
Definition: cdstruc.h:1036
LARGE_INTEGER LastWriteTime
Definition: fatstruc.h:921
#define IN
Definition: typedefs.h:38
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
struct _FILE_BOTH_DIR_INFORMATION * PFILE_BOTH_DIR_INFORMATION
#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
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define FsRtlEnterFileSystem
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:402
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3369
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2298
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
LARGE_INTEGER FatFatDateToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_DATE FatDate)
Definition: timesup.c:171
#define FsRtlExitFileSystem
USHORT Hour
Definition: fat.h:269
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2621
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
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
VOID Fat8dot3ToString(_In_ PIRP_CONTEXT IrpContext, _In_ PDIRENT Dirent, _In_ BOOLEAN RestoreCase, _Out_ POEM_STRING OutputString)
Definition: namesup.c:179
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define CCB_FLAG_FREE_OEM_BEST_FIT
Definition: fatstruc.h:1258
Definition: cdstruc.h:1073
ULONG32 VBO
Definition: fat.h:38
unsigned char * PUCHAR
Definition: retypes.h:3
PVOID Buffers[0x100]
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
struct _FILE_ID_BOTH_DIR_INFORMATION * PFILE_ID_BOTH_DIR_INFORMATION
VOID NTAPI RtlFreeOemString(POEM_STRING OemString)
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN ReturnSingleEntry
Definition: fltkernel.h:2295
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
struct _FILE_DIRECTORY_INFORMATION * PFILE_DIRECTORY_INFORMATION
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
Definition: cdstruc.h:504
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN WatchTree
Definition: fltkernel.h:2239
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define FAT_DIRENT_ATTR_DIRECTORY
Definition: fat.h:372
Definition: fat.h:265
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
BOOLEAN ChicagoMode
Definition: fatstruc.h:86
STRING OEM_STRING
Definition: umtypes.h:203
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2965
struct _FILE_FULL_DIRECTORY_INFORMATION * PFILE_FULL_DIR_INFORMATION
#define FatNull
Definition: fatdata.h:321
WCHAR Fat8QMdot3QM[12]
Definition: dirctrl.c:31
BOOLEAN NTAPI FsRtlDoesNameContainWildCards(IN PUNICODE_STRING Name)
Definition: name.c:464
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2401
#define DOS_QM
Definition: env_spec_w32.h:913
ULONG CLONG
Definition: umtypes.h:126
#define FAT_CREATE_INITIAL_NAME_BUF_SIZE
Definition: fatprocs.h:102
#define CCB_FLAG_SKIP_SHORT_NAME_COMPARE
Definition: fatstruc.h:1252
#define Dbg
Definition: dirctrl.c:29
LARGE_INTEGER FatFatTimeToNtTime(_In_ PIRP_CONTEXT IrpContext, _In_ FAT_TIME_STAMP FatTime, _In_ UCHAR TenMilliSeconds)
Definition: timesup.c:233
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
LARGE_INTEGER FatJanOne1980
Definition: fatdata.c:73
LARGE_INTEGER EndOfFile
Definition: winternl.h:520
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:537
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define CCB_FLAG_QUERY_TEMPLATE_MIXED
Definition: fatstruc.h:1302
struct _FILE_NAMES_INFORMATION * PFILE_NAMES_INFORMATION
Definition: bufpool.h:45
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define CCB_FLAG_FREE_UNICODE
Definition: fatstruc.h:1259
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2300
USHORT DoubleSeconds
Definition: fat.h:267
#define PCHAR
Definition: match.c:90
#define FatGenerateFileIdFromDirentAndOffset(Dcb, Dirent, DirentOffset)
Definition: fatprocs.h:3065
#define UNALIGNED
Definition: crtdefs.h:132
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
#define FatIsNameShortOemValid(IRPCONTEXT, NAME, CAN_CONTAIN_WILD_CARDS, PATH_NAME_OK, LEADING_BACKSLASH_OK)
Definition: fatprocs.h:1189
#define DebugUnwind(X)
Definition: fatdata.h:315
#define CCB_FLAG_MATCH_ALL
Definition: fatstruc.h:1251
FAT_DATA FatData
Definition: fatdata.c:56
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1635
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2971
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1192
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MORE_FILES
Definition: udferr_usr.h:128
#define try_return(S)
Definition: cdprocs.h:2189
#define Vcb
Definition: cdprocs.h:1425
LARGE_INTEGER LastWriteTime
Definition: winternl.h:518
const GLubyte * c
Definition: glext.h:8905
#define _Inout_
Definition: no_sal2.h:244
#define TAG_FILENAME_BUFFER
Definition: nodetype.h:167
NTSTATUS NTAPI CompleteRequest(IN PIRP Irp, IN NTSTATUS Status, IN ULONG_PTR Information)
Definition: dispatch.c:19
#define CanFsdWait(I)
Definition: cdprocs.h:2011
ULONG Flags
Definition: ntfs.h:532
WCHAR * PWCH
Definition: ntbasedef.h:417
USHORT Minute
Definition: fat.h:268
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:226
static const WCHAR L[]
Definition: oid.c:1250
#define SL_WATCH_TREE
Definition: iotypes.h:1796
_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
DRIVER_DISPATCH(nfs41_FsdDispatch)
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#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 STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
#define STATUS_UNMAPPABLE_CHARACTER
Definition: ntstatus.h:576
#define ExLocalTimeToSystemTime(LocTime, SysTime)
Definition: env_spec_w32.h:738
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
LARGE_INTEGER CreationTime
Definition: winternl.h:516
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#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
unsigned int * PULONG
Definition: retypes.h:1
VOID FatGetDirTimes(PIRP_CONTEXT IrpContext, PDIRENT Dirent, PFILE_DIRECTORY_INFORMATION DirInfo)
Definition: dirctrl.c:1330
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG CompletionFilter
Definition: fltkernel.h:2239
#define SL_RESTART_SCAN
Definition: iotypes.h:1792
VOID FatFreeStringBuffer(_Inout_ PVOID String)
Definition: strucsup.c:3783
VOID FatStringTo8dot3(_In_ PIRP_CONTEXT IrpContext, _In_ OEM_STRING InputString, _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3)
Definition: namesup.c:79
#define BOOLEAN
Definition: pedump.c:73
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define FatConvertToSharedFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1600
#define DIRENT
Definition: fatfs.h:187
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:429
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define QuadAlign(Ptr)
Definition: cdprocs.h:1582
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
struct _FILE_ID_FULL_DIR_INFORMATION * PFILE_ID_FULL_DIR_INFORMATION
NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeStringToCountedOemString(STRING *, const UNICODE_STRING *, BOOLEAN)
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define UInt32x32To64(a, b)
Definition: intsafe.h:258
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB * Dcb
Definition: create.c:4157
_Requires_lock_held_(_Global_critical_region_)
Definition: dirctrl.c:29
unsigned short * PUSHORT
Definition: retypes.h:2
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
LARGE_INTEGER AllocationSize
Definition: winternl.h:521
#define RtlOemStringToCountedUnicodeSize(STRING)
#define _Function_class_(x)
Definition: no_sal2.h:202
LONGLONG QuadPart
Definition: typedefs.h:112
#define NT_ASSERT
Definition: rtlfuncs.h:3312