ReactOS  0.4.12-dev-916-gffc4e30
dirsup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  DirSup.c
8 
9 Abstract:
10 
11  This module implements the dirent support routines for Cdfs.
12 
13  Directories on a CD consist of a number of contiguous sectors on
14  the disk. File descriptors consist of one or more directory entries
15  (dirents) within a directory. Files may contain version numbers. If
16  present all like-named files will be ordered contiguously in the
17  directory by decreasing version numbers. We will only return the
18  first of these on a directory query unless the user explicitly
19  asks for version numbers. Finally dirents will not span sector
20  boundaries. Unused bytes at the end of a sector will be zero
21  filled.
22 
23  Directory sector: Offset
24  2048
25  +---------------------------------------------------------------+
26  | | | | | | |
27  | foo;4 | foo;4 | foo;3 | hat | zebra | Zero|
28  | | | | | | Fill|
29  | | final | single | | | |
30  | | extent | extent | | | |
31  +---------------------------------------------------------------+
32 
33  Dirent operations:
34 
35  - Position scan at known offset in directory. Dirent at this
36  offset must exist and is valid. Used when scanning a directory
37  from the beginning when the self entry is known to be valid.
38  Used when positioning at the first dirent for an open
39  file to scan the allocation information. Used when resuming
40  a directory enumeration from a valid directory entry.
41 
42  - Position scan at known offset in directory. Dirent is known to
43  start at this position but must be checked for validity.
44  Used to read the self-directory entry.
45 
46  - Move to the next dirent within a directory.
47 
48  - Given a known starting dirent, collect all the dirents for
49  that file. Scan will finish positioned at the last dirent
50  for the file. We will accumulate the extent lengths to
51  find the size of the file.
52 
53  - Given a known starting dirent, position the scan for the first
54  dirent of the following file. Used when not interested in
55  all of the details for the current file and are looking for
56  the next file.
57 
58  - Update a common dirent structure with the details of the on-disk
59  structure. This is used to smooth out the differences
60 
61  - Build the filename (name and version strings) out of the stream
62  of bytes in the file name on disk. For Joliet disks we will have
63  to convert to little endian.
64 
65 
66 --*/
67 
68 #include "cdprocs.h"
69 
70 //
71 // The Bug check file id for this module
72 //
73 
74 #define BugCheckFileId (CDFS_BUG_CHECK_DIRSUP)
75 
76 //
77 // Local macros
78 //
79 
80 //
81 // PRAW_DIRENT
82 // CdRawDirent (
83 // _In_ PIRP_CONTEXT IrpContext,
84 // _In_ PDIR_ENUM_CONTEXT DirContext
85 // );
86 //
87 
88 #define CdRawDirent(IC,DC) \
89  Add2Ptr( (DC)->Sector, (DC)->SectorOffset, PRAW_DIRENT )
90 
91 //
92 // Local support routines
93 //
94 
95 ULONG
97  _In_ PIRP_CONTEXT IrpContext,
99  );
100 
103  _In_ PIRP_CONTEXT IrpContext,
104  _In_ PRAW_DIRENT RawDirent,
106  );
107 
108 #ifdef ALLOC_PRAGMA
109 #pragma alloc_text(PAGE, CdCheckForXAExtent)
110 #pragma alloc_text(PAGE, CdCheckRawDirentBounds)
111 #pragma alloc_text(PAGE, CdCleanupFileContext)
112 #pragma alloc_text(PAGE, CdFindFile)
113 #pragma alloc_text(PAGE, CdFindDirectory)
114 #pragma alloc_text(PAGE, CdFindFileByShortName)
115 #pragma alloc_text(PAGE, CdLookupDirent)
116 #pragma alloc_text(PAGE, CdLookupLastFileDirent)
117 #pragma alloc_text(PAGE, CdLookupNextDirent)
118 #pragma alloc_text(PAGE, CdLookupNextInitialFileDirent)
119 #pragma alloc_text(PAGE, CdUpdateDirentFromRawDirent)
120 #pragma alloc_text(PAGE, CdUpdateDirentName)
121 #endif
122 
123 
124 VOID
126  _In_ PIRP_CONTEXT IrpContext,
127  _In_ PFCB Fcb,
130  )
131 
132 /*++
133 
134 Routine Description:
135 
136  This routine is called to initiate a walk through a directory. We will
137  position ourselves in the directory at offset DirentOffset. We know that
138  a dirent begins at this boundary but may have to verify the dirent bounds.
139  We will call this routine when looking up the first entry of a known
140  file or verifying the self entry of a directory.
141 
142 Arguments:
143 
144  Fcb - Fcb for the directory being traversed.
145 
146  DirentOffset - This is our target point in the directory. We will map the
147  page containing this entry and possibly verify the dirent bounds at
148  this location.
149 
150  DirContext - This is the dirent context for this scan. We update it with
151  the location of the dirent we found. This structure has been initialized
152  outside of this call.
153 
154 Return Value:
155 
156  None.
157 
158 --*/
159 
160 {
161  LONGLONG BaseOffset;
162 
163  PAGED_CODE();
164 
165  //
166  // Initialize the offset of the first dirent we want to map.
167  //
168 
169  DirContext->BaseOffset = SectorTruncate( DirentOffset );
170  BaseOffset = DirContext->BaseOffset;
171 
172  DirContext->DataLength = SECTOR_SIZE;
173 
174  DirContext->SectorOffset = SectorOffset( DirentOffset );
175 
176  //
177  // Truncate the data length if we are at the end of the file.
178  //
179 
180  if (DirContext->DataLength > (Fcb->FileSize.QuadPart - BaseOffset)) {
181 
182  DirContext->DataLength = (ULONG) (Fcb->FileSize.QuadPart - BaseOffset);
183  }
184 
185  //
186  // Now map the data at this offset.
187  //
188 
190  (PLARGE_INTEGER) &BaseOffset,
191  DirContext->DataLength,
192  TRUE,
193  &DirContext->Bcb,
194  &DirContext->Sector );
195 
196  //
197  // Verify the dirent bounds.
198  //
199 
200  DirContext->NextDirentOffset = CdCheckRawDirentBounds( IrpContext,
201  DirContext );
202 
203  return;
204 }
205 
206 
207 BOOLEAN
209  _In_ PIRP_CONTEXT IrpContext,
210  _In_ PFCB Fcb,
211  _In_ PDIRENT_ENUM_CONTEXT CurrentDirContext,
212  _Inout_ PDIRENT_ENUM_CONTEXT NextDirContext
213  )
214 
215 /*++
216 
217 Routine Description:
218 
219  This routine is called to find the next dirent in the directory. The
220  current position is given and we look for the next. We leave the context
221  for the starting position untouched and update the context for the
222  dirent we found. The target context may already be initialized so we
223  may already have the sector in memory.
224 
225  This routine will position the enumeration context for the next dirent and
226  verify the dirent bounds.
227 
228  NOTE - This routine can be called with CurrentDirContext and NextDirContext
229  pointing to the same enumeration context.
230 
231 Arguments:
232 
233  Fcb - Fcb for the directory being traversed.
234 
235  CurrentDirContext - This is the dirent context for this scan. We update
236  it with the location of the dirent we found. This is currently
237  pointing to a dirent location. The dirent bounds at this location
238  have already been verified.
239 
240  NextDirContext - This is the dirent context to update with the dirent we
241  find. This may already point to a dirent so we need to check if
242  we are in the same sector and unmap any buffer as necessary.
243 
244  This dirent is left in an indeterminant state if we don't find a dirent.
245 
246 Return Value:
247 
248  BOOLEAN - TRUE if we find a location for the next dirent, FALSE otherwise.
249  This routine can cause a raise if the directory is corrupt.
250 
251 --*/
252 
253 {
254  LONGLONG CurrentBaseOffset = CurrentDirContext->BaseOffset;
255  ULONG TempUlong;
256 
257  BOOLEAN FoundDirent = FALSE;
258 
259  PAGED_CODE();
260 
261  //
262  // Check if a different sector is mapped. If so then move our target
263  // enumeration context to the same sector.
264  //
265 
266  if ((CurrentDirContext->BaseOffset != NextDirContext->BaseOffset) ||
267  (NextDirContext->Bcb == NULL)) {
268 
269  //
270  // Unpin the current target Bcb and map the next sector.
271  //
272 
273  CdUnpinData( IrpContext, &NextDirContext->Bcb );
274 
276  (PLARGE_INTEGER) &CurrentBaseOffset,
277  CurrentDirContext->DataLength,
278  TRUE,
279  &NextDirContext->Bcb,
280  &NextDirContext->Sector );
281 
282  //
283  // Copy the data length and sector offset.
284  //
285 
286  NextDirContext->DataLength = CurrentDirContext->DataLength;
287  NextDirContext->BaseOffset = CurrentDirContext->BaseOffset;
288  }
289 
290  //
291  // Now move to the same offset in the sector.
292  //
293 
294  NextDirContext->SectorOffset = CurrentDirContext->SectorOffset;
295 
296  //
297  // If the value is zero then unmap the current sector and set up
298  // the base offset to the beginning of the next sector.
299  //
300 
301  if (CurrentDirContext->NextDirentOffset == 0) {
302 
303  CurrentBaseOffset = NextDirContext->BaseOffset + NextDirContext->DataLength;
304 
305  //
306  // Unmap the current sector. We test the value of the Bcb in the
307  // loop below to see if we need to read in another sector.
308  //
309 
310  CdUnpinData( IrpContext, &NextDirContext->Bcb );
311 
312  //
313  // There is another possible dirent in the current sector. Update the
314  // enumeration context to reflect this.
315  //
316 
317  } else {
318 
319  NextDirContext->SectorOffset += CurrentDirContext->NextDirentOffset;
320  }
321 
322  //
323  // Now loop until we find the next possible dirent or walk off the directory.
324  //
325 
326  while (TRUE) {
327 
328  //
329  // If we don't currently have a sector mapped then map the
330  // directory at the current offset.
331  //
332 
333  if (NextDirContext->Bcb == NULL) {
334 
335  TempUlong = SECTOR_SIZE;
336 
337  if (TempUlong > (ULONG) (Fcb->FileSize.QuadPart - CurrentBaseOffset)) {
338 
339  TempUlong = (ULONG) (Fcb->FileSize.QuadPart - CurrentBaseOffset);
340 
341  //
342  // If the length is zero then there is no dirent.
343  //
344 
345  if (TempUlong == 0) {
346 
347  break;
348  }
349  }
350 
352  (PLARGE_INTEGER) &CurrentBaseOffset,
353  TempUlong,
354  TRUE,
355  &NextDirContext->Bcb,
356  &NextDirContext->Sector );
357 
358  NextDirContext->BaseOffset = (ULONG) CurrentBaseOffset;
359  NextDirContext->SectorOffset = 0;
360  NextDirContext->DataLength = TempUlong;
361  }
362 
363  //
364  // The CDFS spec allows for sectors in a directory to contain all zeroes.
365  // In this case we need to move to the next sector. So look at the
366  // current potential dirent for a zero length. Move to the next
367  // dirent if length is zero.
368  //
369 
370  if (*((PCHAR) CdRawDirent( IrpContext, NextDirContext )) != 0) {
371 
372  FoundDirent = TRUE;
373  break;
374  }
375 
376  CurrentBaseOffset = NextDirContext->BaseOffset + NextDirContext->DataLength;
377  CdUnpinData( IrpContext, &NextDirContext->Bcb );
378  }
379 
380  //
381  // Check the dirent bounds if we found a dirent.
382  //
383 
384  if (FoundDirent) {
385 
386  NextDirContext->NextDirentOffset = CdCheckRawDirentBounds( IrpContext,
387  NextDirContext );
388  }
389 
390  return FoundDirent;
391 }
392 
393 
394 _At_(Dirent->CdTime, _Post_notnull_)
395 VOID
396 CdUpdateDirentFromRawDirent (
397  _In_ PIRP_CONTEXT IrpContext,
401  )
402 
403 /*++
404 
405 Routine Description:
406 
407  This routine is called to safely copy the data from the dirent on disk
408  to the in-memory dirent. The fields on disk are unaligned so we
409  need to safely copy them to our structure.
410 
411 Arguments:
412 
413  Fcb - Fcb for the directory being scanned.
414 
415  DirContext - Enumeration context for the raw disk dirent.
416 
417  Dirent - In-memory dirent to update.
418 
419 Return Value:
420 
421  None.
422 
423 --*/
424 
425 {
426  PRAW_DIRENT RawDirent = CdRawDirent( IrpContext, DirContext );
427 
428  PAGED_CODE();
429 
431 
432  //
433  // Clear all of the current state flags except the flag indicating that
434  // we allocated a name string.
435  //
436 
438 
439  //
440  // The dirent offset is the sum of the start of the sector and the
441  // sector offset.
442  //
443 
444  Dirent->DirentOffset = DirContext->BaseOffset + DirContext->SectorOffset;
445 
446  //
447  // Copy the dirent length from the raw dirent.
448  //
449 
450  Dirent->DirentLength = RawDirent->DirLen;
451 
452  //
453  // The starting offset on disk is computed by finding the starting
454  // logical block and stepping over the Xar block.
455  //
456 
457  CopyUchar4( &Dirent->StartingOffset, RawDirent->FileLoc );
458 
459  Dirent->StartingOffset += RawDirent->XarLen;
460 
461  //
462  // Do a safe copy to get the data length.
463  //
464 
465  CopyUchar4( &Dirent->DataLength, RawDirent->DataLen );
466 
467  //
468  // Save a pointer to the time stamps.
469  //
470 
471  Dirent->CdTime = (PCHAR)RawDirent->RecordTime;
472 
473  //
474  // Copy the dirent flags.
475  //
476 
477  Dirent->DirentFlags = CdRawDirentFlags( IrpContext, RawDirent );
478 
479  //
480  // For both the file unit and interleave skip we want to take the
481  // logical block count.
482  //
483 
484  Dirent->FileUnitSize =
485  Dirent->InterleaveGapSize = 0;
486 
487  if (RawDirent->IntLeaveSize != 0) {
488 
489  Dirent->FileUnitSize = RawDirent->IntLeaveSize;
490  Dirent->InterleaveGapSize = RawDirent->IntLeaveSkip;
491  }
492 
493  //
494  // Get the name length and remember a pointer to the start of the
495  // name string. We don't do any processing on the name at this
496  // point.
497  //
498  // Check that the name length is non-zero.
499  //
500 
501  if (RawDirent->FileIdLen == 0) {
502 
504  }
505 
506  Dirent->FileNameLen = RawDirent->FileIdLen;
507  Dirent->FileName = (PCHAR)RawDirent->FileId;
508 
509  //
510  // If there are any remaining bytes at the end of the dirent then
511  // there may be a system use area. We protect ourselves from
512  // disks which don't pad the dirent entries correctly by using
513  // a fudge factor of one. All system use areas must have a length
514  // greater than one. Don't bother with the system use area
515  // if this is a directory.
516  //
517 
520  Dirent->ExtentType = Form1Data;
521  Dirent->SystemUseOffset = 0;
522 
523  if (!FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY ) &&
524  (Dirent->DirentLength > ((FIELD_OFFSET( RAW_DIRENT, FileId ) + Dirent->FileNameLen) + 1))) {
525 
526  Dirent->SystemUseOffset = WordAlign( FIELD_OFFSET( RAW_DIRENT, FileId ) + Dirent->FileNameLen );
527  }
528 
529  return;
530 }
531 
532 
533 VOID
535  _In_ PIRP_CONTEXT IrpContext,
538  )
539 
540 /*++
541 
542 Routine Description:
543 
544  This routine is called to update the name in the dirent with the name
545  from the disk. We will look for the special case of the self and
546  parent entries and also construct the Unicode name for the Joliet disk
547  in order to work around the BigEndian on-disk structure.
548 
549 Arguments:
550 
551  Dirent - Pointer to the in-memory dirent structure.
552 
553  IgnoreCase - TRUE if we should build the upcased version. Otherwise we
554  use the exact case name.
555 
556 Return Value:
557 
558  None.
559 
560 --*/
561 
562 {
563  UCHAR DirectoryValue;
564  ULONG Length;
565 
567 
568  PAGED_CODE();
569 
570  //
571  // Check if this is a self or parent entry. There is no version number
572  // in these cases. We use a fixed string for these.
573  //
574  // Self-Entry - Length is 1, value is 0.
575  // Parent-Entry - Length is 1, value is 1.
576  //
577 
578  if ((Dirent->FileNameLen == 1) &&
579  FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY )) {
580 
581  DirectoryValue = *((PCHAR) Dirent->FileName);
582 
583  if ((DirectoryValue == 0) || (DirectoryValue == 1)) {
584 
585  //
586  // We should not have allocated a name by the time we see these cases.
587  // If we have, this means that the image is in violation of ISO 9660 7.6.2,
588  // which states that the ./.. entries must be the first two in the directory.
589  //
590 
592 
594  }
595 
596  //
597  // Now use one of the hard coded directory names.
598  //
599 
600  Dirent->CdFileName.FileName = CdUnicodeDirectoryNames[DirectoryValue];
601 
602  //
603  // Show that there is no version number.
604  //
605 
606  Dirent->CdFileName.VersionString.Length = 0;
607 
608  //
609  // The case name is the same as the exact name.
610  //
611 
612  Dirent->CdCaseFileName = Dirent->CdFileName;
613 
614  //
615  // Mark this as a constant value entry.
616  //
617 
619 
620  //
621  // Return now.
622  //
623 
624  return;
625  }
626  }
627 
628  //
629  // Mark this as a non-constant value entry.
630  //
631 
633 
634  //
635  // Compute how large a buffer we will need. If this is an ignore
636  // case operation then we will want a double size buffer. If the disk is not
637  // a Joliet disk then we might need two bytes for each byte in the name.
638  //
639 
640  Length = Dirent->FileNameLen;
641 
642  if (IgnoreCase) {
643 
644  Length *= 2;
645  }
646 
647  if (!FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
648 
649  Length *= sizeof( WCHAR );
650  }
651 
652  //
653  // Now decide if we need to allocate a new buffer. We will if
654  // this name won't fit in the embedded name buffer and it is
655  // larger than the current allocated buffer. We always use the
656  // allocated buffer if present.
657  //
658  // If we haven't allocated a buffer then use the embedded buffer if the data
659  // will fit. This is the typical case.
660  //
661 
663  (Length <= sizeof( Dirent->NameBuffer ))) {
664 
665  Dirent->CdFileName.FileName.MaximumLength = sizeof( Dirent->NameBuffer );
666  Dirent->CdFileName.FileName.Buffer = Dirent->NameBuffer;
667 
668  } else {
669 
670  //
671  // We need to use an allocated buffer. Check if the current buffer
672  // is large enough.
673  //
674 
675  if (Length > Dirent->CdFileName.FileName.MaximumLength) {
676 
677  //
678  // Free any allocated buffer.
679  //
680 
682 
683  CdFreePool( &Dirent->CdFileName.FileName.Buffer );
685  }
686 
687  Dirent->CdFileName.FileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool,
688  Length,
689  TAG_DIRENT_NAME );
690 
692 
693  Dirent->CdFileName.FileName.MaximumLength = (USHORT) Length;
694  }
695  }
696 
697  //
698  // We now have a buffer for the name. We need to either convert the on-disk bigendian
699  // to little endian or covert the name to Unicode.
700  //
701 
702  if (!FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
703 
704  Status = RtlOemToUnicodeN( Dirent->CdFileName.FileName.Buffer,
705  Dirent->CdFileName.FileName.MaximumLength,
706  &Length,
707  Dirent->FileName,
708  Dirent->FileNameLen );
709 
710  __analysis_assert( Status == STATUS_SUCCESS );
712  Dirent->CdFileName.FileName.Length = (USHORT) Length;
713 
714  } else {
715 
716  //
717  // Convert this string to little endian.
718  //
719 
720  CdConvertBigToLittleEndian( IrpContext,
721  Dirent->FileName,
722  Dirent->FileNameLen,
723  (PCHAR) Dirent->CdFileName.FileName.Buffer );
724 
725  Dirent->CdFileName.FileName.Length = (USHORT) Dirent->FileNameLen;
726  }
727 
728  //
729  // Split the name into name and version strings.
730  //
731 
732  CdConvertNameToCdName( IrpContext,
733  &Dirent->CdFileName );
734 
735  //
736  // The name length better be non-zero.
737  //
738 
739  if (Dirent->CdFileName.FileName.Length == 0) {
740 
742  }
743 
744  //
745  // If the filename ends with a period then back up one character.
746  //
747 
748  if (Dirent->CdFileName.FileName.Buffer[(Dirent->CdFileName.FileName.Length - sizeof( WCHAR )) / 2] == L'.') {
749 
750  //
751  // Slide the version string down.
752  //
753 
754  if (Dirent->CdFileName.VersionString.Length != 0) {
755 
756  PWCHAR NewVersion;
757 
758  //
759  // Start from the position currently containing the separator.
760  //
761 
762  NewVersion = Add2Ptr( Dirent->CdFileName.FileName.Buffer,
763  Dirent->CdFileName.FileName.Length,
764  PWCHAR );
765 
766  //
767  // Now overwrite the period.
768  //
769 
770  RtlMoveMemory( NewVersion - 1,
771  NewVersion,
772  Dirent->CdFileName.VersionString.Length + sizeof( WCHAR ));
773 
774  //
775  // Now point to the new version string.
776  //
777 
778  Dirent->CdFileName.VersionString.Buffer = NewVersion;
779  }
780 
781  //
782  // Shrink the filename length.
783  //
784 
785  Dirent->CdFileName.FileName.Length -= sizeof( WCHAR );
786  }
787 
788  if (!CdIsLegalName( IrpContext, &Dirent->CdFileName.FileName )) {
789 
791  }
792 
793  //
794  // If this an exact case operation then use the filename exactly.
795  //
796 
797  if (!IgnoreCase) {
798 
799  Dirent->CdCaseFileName = Dirent->CdFileName;
800 
801  //
802  // Otherwise perform our upcase operation. We already have guaranteed the buffers are
803  // there.
804  //
805 
806  } else {
807 
808  Dirent->CdCaseFileName.FileName.Buffer = Add2Ptr( Dirent->CdFileName.FileName.Buffer,
809  Dirent->CdFileName.FileName.MaximumLength / 2,
810  PWCHAR);
811 
812  Dirent->CdCaseFileName.FileName.MaximumLength = Dirent->CdFileName.FileName.MaximumLength / 2;
813 
814  CdUpcaseName( IrpContext,
815  &Dirent->CdFileName,
816  &Dirent->CdCaseFileName );
817  }
818 
819  return;
820 }
821 
822 
824 CdFindFile (
825  _In_ PIRP_CONTEXT IrpContext,
826  _In_ PFCB Fcb,
831  )
832 
833 /*++
834 
835 Routine Description:
836 
837  This routine is called to search a dirctory for a file matching the input
838  name. This name has been upcased at this point if this a case-insensitive
839  search. The name has been separated into separate name and version strings.
840  We look for an exact match in the name and only consider the version if
841  there is a version specified in the search name.
842 
843 Arguments:
844 
845  Fcb - Fcb for the directory being scanned.
846 
847  Name - Name to search for.
848 
849  IgnoreCase - Indicates the case of the search.
850 
851  FileContext - File context to use for the search. This has already been
852  initialized.
853 
854  MatchingName - Pointer to buffer containing matching name. We need this
855  in case we don't match the name in the directory but match the
856  short name instead.
857 
858 Return Value:
859 
860  BOOLEAN - TRUE if matching entry is found, FALSE otherwise.
861 
862 --*/
863 
864 {
865  PDIRENT Dirent;
867 
868  BOOLEAN Found = FALSE;
869 
870  PAGED_CODE();
871 
872  //
873  // Make sure there is a stream file for this Fcb.
874  //
875 
876  CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);
877 
878  //
879  // Check to see whether we need to check for a possible short name.
880  //
881 
882  ShortNameDirentOffset = CdShortNameDirentOffset( IrpContext, &Name->FileName );
883 
884  //
885  // Position ourselves at the first entry.
886  //
887 
888  CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, Fcb->StreamOffset );
889 
890  //
891  // Loop while there are more entries in this directory.
892  //
893 
894  do {
895 
896  Dirent = &FileContext->InitialDirent->Dirent;
897 
898  //
899  // We only consider files which don't have the associated bit set.
900  // We also only look for files. All directories would already
901  // have been found.
902  //
903 
904  if (!FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_ASSOC | CD_ATTRIBUTE_DIRECTORY )) {
905 
906  //
907  // Update the name in the current dirent.
908  //
909 
910  CdUpdateDirentName( IrpContext, Dirent, IgnoreCase );
911 
912  //
913  // Don't bother with constant entries.
914  //
915 
917 
918  continue;
919  }
920 
921  //
922  // Now check whether we have a name match.
923  // We exit the loop if we have a match.
924  //
925 
926  if (CdIsNameInExpression( IrpContext,
927  &Dirent->CdCaseFileName,
928  Name,
929  0,
930  TRUE )) {
931 
932  *MatchingName = &Dirent->CdCaseFileName;
933  Found = TRUE;
934  break;
935  }
936 
937  //
938  // The names didn't match. If the input name is a possible short
939  // name and we are at the correct offset in the directory then
940  // check if the short names match.
941  //
942 
943  if (((Dirent->DirentOffset >> SHORT_NAME_SHIFT) == ShortNameDirentOffset) &&
944  (Name->VersionString.Length == 0) &&
945  !CdIs8dot3Name( IrpContext,
946  Dirent->CdFileName.FileName )) {
947 
948  //
949  // Create the short name and check for a match.
950  //
951 
952  CdGenerate8dot3Name( IrpContext,
953  &Dirent->CdCaseFileName.FileName,
954  Dirent->DirentOffset,
955  FileContext->ShortName.FileName.Buffer,
956  &FileContext->ShortName.FileName.Length );
957 
958  //
959  // Now check whether we have a name match.
960  // We exit the loop if we have a match.
961  //
962 
963  if (CdIsNameInExpression( IrpContext,
965  Name,
966  0,
967  FALSE )) {
968 
970  Found = TRUE;
971  break;
972  }
973  }
974  }
975 
976  //
977  // Go to the next initial dirent for a file.
978  //
979 
980  } while (CdLookupNextInitialFileDirent( IrpContext, Fcb, FileContext ));
981 
982  //
983  // If we find the file then collect all of the dirents.
984  //
985 
986  if (Found) {
987 
988  CdLookupLastFileDirent( IrpContext, Fcb, FileContext );
989 
990  }
991 
992  return Found;
993 }
994 
995 
996 BOOLEAN
998  _In_ PIRP_CONTEXT IrpContext,
999  _In_ PFCB Fcb,
1000  _In_ PCD_NAME Name,
1003  )
1004 
1005 /*++
1006 
1007 Routine Description:
1008 
1009  This routine is called to search a dirctory for a directory matching the input
1010  name. This name has been upcased at this point if this a case-insensitive
1011  search. We look for an exact match in the name and do not look for shortname
1012  equivalents.
1013 
1014 Arguments:
1015 
1016  Fcb - Fcb for the directory being scanned.
1017 
1018  Name - Name to search for.
1019 
1020  IgnoreCase - Indicates the case of the search.
1021 
1022  FileContext - File context to use for the search. This has already been
1023  initialized.
1024 
1025 Return Value:
1026 
1027  BOOLEAN - TRUE if matching entry is found, FALSE otherwise.
1028 
1029 --*/
1030 
1031 {
1032  PDIRENT Dirent;
1033 
1034  BOOLEAN Found = FALSE;
1035 
1036  PAGED_CODE();
1037 
1038  //
1039  // Make sure there is a stream file for this Fcb.
1040  //
1041 
1042  CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);
1043 
1044  //
1045  // Position ourselves at the first entry.
1046  //
1047 
1048  CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, Fcb->StreamOffset );
1049 
1050  //
1051  // Loop while there are more entries in this directory.
1052  //
1053 
1054  do {
1055 
1056  Dirent = &FileContext->InitialDirent->Dirent;
1057 
1058  //
1059  // We only look for directories. Directories cannot have the
1060  // associated bit set.
1061  //
1062 
1063  if (FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_DIRECTORY )) {
1064 
1065  //
1066  // Update the name in the current dirent.
1067  //
1068 
1069  CdUpdateDirentName( IrpContext, Dirent, IgnoreCase );
1070 
1071  //
1072  // Don't bother with constant entries.
1073  //
1074 
1076 
1077  continue;
1078  }
1079 
1080  //
1081  // Now check whether we have a name match.
1082  // We exit the loop if we have a match.
1083  //
1084 
1085  if (CdIsNameInExpression( IrpContext,
1086  &Dirent->CdCaseFileName,
1087  Name,
1088  0,
1089  TRUE )) {
1090 
1091  Found = TRUE;
1092  break;
1093  }
1094  }
1095 
1096  //
1097  // Go to the next initial dirent.
1098  //
1099 
1100  } while (CdLookupNextInitialFileDirent( IrpContext, Fcb, FileContext ));
1101 
1102  return Found;
1103 }
1104 
1105 
1106 _At_(FileContext->ShortName.FileName.MaximumLength, _In_range_(>=, BYTE_COUNT_8_DOT_3))
1107 BOOLEAN
1108 CdFindFileByShortName (
1109  _In_ PIRP_CONTEXT IrpContext,
1111  _In_ PCD_NAME Name,
1115  )
1116 
1117 /*++
1118 
1119 Routine Description:
1120 
1121  This routine is called to find the file name entry whose short name
1122  is defined by the input DirentOffset. The dirent offset here is
1123  multiplied by 32 and we look for the dirent begins in this 32 byte offset in
1124  directory. The minimum dirent length is 34 so we are guaranteed that only
1125  one dirent can begin in each 32 byte block in the directory.
1126 
1127 Arguments:
1128 
1129  Fcb - Fcb for the directory being scanned.
1130 
1131  Name - Name we are trying to match. We know this contains the tilde
1132  character followed by decimal characters.
1133 
1134  IgnoreCase - Indicates whether we need to upcase the long name and
1135  generated short name.
1136 
1137  ShortNameDirentOffset - This is the shifted value for the offset of the
1138  name in the directory.
1139 
1140  FileContext - This is the initialized file context to use for the search.
1141 
1142 Return Value:
1143 
1144  BOOLEAN - TRUE if a matching name was found, FALSE otherwise.
1145 
1146 --*/
1147 
1149  BOOLEAN Found = FALSE;
1150  PDIRENT Dirent;
1151 
1153 
1154  PAGED_CODE();
1155 
1156  //
1157  // Make sure there is a stream file for this Fcb.
1158  //
1159 
1160  CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);
1161 
1162  //
1163  // Position ourselves at the start of the directory and update
1164  //
1165  //
1166 
1167  CdLookupInitialFileDirent( IrpContext, Fcb, FileContext, Fcb->StreamOffset );
1168 
1169  //
1170  // Loop until we have found the entry or are beyond this dirent.
1171  //
1172 
1173  do {
1174 
1175  //
1176  // Compute the short name dirent offset for the current dirent.
1177  //
1178 
1179  Dirent = &FileContext->InitialDirent->Dirent;
1181 
1182  //
1183  // If beyond the target then exit.
1184  //
1185 
1187 
1188  break;
1189  }
1190 
1191  //
1192  // If equal to the target then check if we have a name match.
1193  // We will either match or fail here.
1194  //
1195 
1197 
1198  //
1199  // If this is an associated file then get out.
1200  //
1201 
1202  if (FlagOn( Dirent->DirentFlags, CD_ATTRIBUTE_ASSOC )) {
1203 
1204  break;
1205  }
1206 
1207  //
1208  // Update the name in the dirent and check if it is not
1209  // an 8.3 name.
1210  //
1211 
1212  CdUpdateDirentName( IrpContext, Dirent, IgnoreCase );
1213 
1214  if (CdIs8dot3Name( IrpContext,
1215  Dirent->CdFileName.FileName )) {
1216 
1217  break;
1218  }
1219 
1220  //
1221  // Generate the 8.3 name see if it matches our input name.
1222  //
1223 
1224  CdGenerate8dot3Name( IrpContext,
1225  &Dirent->CdCaseFileName.FileName,
1226  Dirent->DirentOffset,
1227  FileContext->ShortName.FileName.Buffer,
1228  &FileContext->ShortName.FileName.Length );
1229 
1230  //
1231  // Check if this name matches.
1232  //
1233 
1234  if (CdIsNameInExpression( IrpContext,
1235  Name,
1237  0,
1238  FALSE )) {
1239 
1240  //
1241  // Let our caller know we found an entry.
1242  //
1243 
1244  Found = TRUE;
1245  }
1246 
1247  //
1248  // Break out of the loop.
1249  //
1250 
1251  break;
1252  }
1253 
1254  //
1255  // Continue until there are no more entries.
1256  //
1257 
1258  } while (CdLookupNextInitialFileDirent( IrpContext, Fcb, FileContext ));
1259 
1260  //
1261  // If we find the file then collect all of the dirents.
1262  //
1263 
1264  if (Found) {
1265 
1266  CdLookupLastFileDirent( IrpContext, Fcb, FileContext );
1267 
1268  }
1269 
1270  return Found;
1271 }
1272 
1273 
1274 BOOLEAN
1276  _In_ PIRP_CONTEXT IrpContext,
1277  _In_ PFCB Fcb,
1279  )
1280 
1281 /*++
1282 
1283 Routine Description:
1284 
1285  This routine is called to walk through the directory until we find the
1286  first possible dirent for file. We are positioned at some point described
1287  by the FileContext. We will walk through any remaing dirents for the
1288  current file until we find the first dirent for some subsequent file.
1289 
1290  We can be called when we have found just one dirent for a file or all
1291  of them. We first check the CurrentDirContext. In the typical
1292  single-extent case this is unused. Then we look to the InitialDirContext
1293  which must be initialized.
1294 
1295  This routine will save the initial DirContext to the PriorDirContext and
1296  clean up any existing DirContext for the Prior or Current positions in
1297  the enumeration context.
1298 
1299 Arguments:
1300 
1301  Fcb - This is the directory to scan.
1302 
1303  FileContext - This is the file enumeration context. It is currently pointing
1304  at some file in the directory.
1305 
1306 Return Value:
1307 
1308 --*/
1309 
1310 {
1311  PRAW_DIRENT RawDirent;
1312 
1313  PDIRENT_ENUM_CONTEXT CurrentDirContext;
1314  PDIRENT_ENUM_CONTEXT TargetDirContext;
1315  PCOMPOUND_DIRENT TempDirent;
1316 
1317  BOOLEAN FoundDirent = FALSE;
1318  BOOLEAN FoundLastDirent;
1319 
1320  PAGED_CODE();
1321 
1322  //
1323  // Start by saving the initial dirent of the current file as the
1324  // previous file.
1325  //
1326 
1327  TempDirent = FileContext->PriorDirent;
1328  FileContext->PriorDirent = FileContext->InitialDirent;
1329  FileContext->InitialDirent = TempDirent;
1330 
1331  //
1332  // We will use the initial dirent of the prior file unless the
1333  // previous search returned multiple extents.
1334  //
1335 
1336  CurrentDirContext = &FileContext->PriorDirent->DirContext;
1337 
1339 
1340  CurrentDirContext = &FileContext->CurrentDirent->DirContext;
1341  }
1342 
1343  //
1344  // Clear all of the flags and file size for the next file.
1345  //
1346 
1347  FileContext->Flags = 0;
1348  FileContext->FileSize = 0;
1349 
1350  FileContext->ShortName.FileName.Length = 0;
1351 
1352  //
1353  // We always want to store the result into the updated initial dirent
1354  // context.
1355  //
1356 
1357  TargetDirContext = &FileContext->InitialDirent->DirContext;
1358 
1359  //
1360  // Loop until we find the first dirent after the last dirent of the
1361  // current file. We may not be at the last dirent for the current file yet
1362  // so we may walk forward looking for the last and then find the
1363  // initial dirent for the next file after that.
1364  //
1365 
1366  while (TRUE) {
1367 
1368  //
1369  // Remember if the last dirent we visited was the last dirent for
1370  // a file.
1371  //
1372 
1373  RawDirent = CdRawDirent( IrpContext, CurrentDirContext );
1374 
1375  FoundLastDirent = !FlagOn( CdRawDirentFlags( IrpContext, RawDirent ), CD_ATTRIBUTE_MULTI );
1376 
1377  //
1378  // Try to find another dirent.
1379  //
1380 
1381  FoundDirent = CdLookupNextDirent( IrpContext,
1382  Fcb,
1383  CurrentDirContext,
1384  TargetDirContext );
1385 
1386  //
1387  // Exit the loop if no entry found.
1388  //
1389 
1390  if (!FoundDirent) {
1391 
1392  break;
1393 
1394  }
1395 
1396  //
1397  // Update the in-memory dirent.
1398  //
1399 
1400  CdUpdateDirentFromRawDirent( IrpContext,
1401  Fcb,
1402  TargetDirContext,
1403  &FileContext->InitialDirent->Dirent );
1404 
1405  //
1406  // Exit the loop if we had the end for the previous file.
1407  //
1408 
1409  if (FoundLastDirent) {
1410 
1411  break;
1412  }
1413 
1414  //
1415  // Always use a single dirent from this point on.
1416  //
1417 
1418  CurrentDirContext = TargetDirContext;
1419  }
1420 
1421  return FoundDirent;
1422 }
1423 
1424 
1425 VOID
1427  _In_ PIRP_CONTEXT IrpContext,
1428  _In_ PFCB Fcb,
1430  )
1431 
1432 /*++
1433 
1434 Routine Description:
1435 
1436  This routine is called when we've found the matching initial dirent for
1437  a file. Now we want to find all of the dirents for a file as well as
1438  compute the running total for the file size.
1439 
1440  We also go out to the system use area and check whether this is an
1441  XA sector. In that case we will compute the real file size.
1442 
1443  The dirent in the initial compound dirent has been updated from the
1444  raw dirent when this routine is called.
1445 
1446 Arguments:
1447 
1448  Fcb - Directory containing the entries for the file.
1449 
1450  FileContext - Enumeration context for this search. It currently points
1451  to the first dirent of the file and the in-memory dirent has been
1452  updated.
1453 
1454 Return Value:
1455 
1456  None. This routine may raise STATUS_FILE_CORRUPT.
1457 
1458 --*/
1459 
1460 {
1462  PCOMPOUND_DIRENT CurrentCompoundDirent;
1463  PDIRENT CurrentDirent = NULL;
1464 
1465  BOOLEAN FirstPass = TRUE;
1466  BOOLEAN FoundDirent;
1467 
1468  PAGED_CODE();
1469 
1470  //
1471  // The current dirent to look at is the initial dirent for the file.
1472  //
1473 
1474  CurrentCompoundDirent = FileContext->InitialDirent;
1475 
1476  //
1477  // Loop until we reach the last dirent for the file.
1478  //
1479 
1480  while (TRUE) {
1481 
1482  CurrentDirent = &CurrentCompoundDirent->Dirent;
1483 
1484  //
1485  // Check if this extent has XA sectors.
1486  //
1487 
1488  if ((CurrentDirent->SystemUseOffset != 0) &&
1490  CdCheckForXAExtent( IrpContext,
1491  CdRawDirent( IrpContext, &CurrentCompoundDirent->DirContext ),
1492  CurrentDirent )) {
1493 
1494  //
1495  // Any previous dirent must describe XA sectors as well.
1496  //
1497 
1498  if (!FirstPass && (ExtentType != CurrentDirent->ExtentType)) {
1499 
1501  }
1502 
1503  //
1504  // If there are XA sectors then the data on the disk must
1505  // be correctly aligned on sectors and be an integral number of
1506  // sectors. Only an issue if the logical block size is not
1507  // 2048.
1508  //
1509 
1510  if (Fcb->Vcb->BlockSize != SECTOR_SIZE) {
1511 
1512  //
1513  // We will do the following checks.
1514  //
1515  // Data must start on a sector boundary.
1516  // Data length must be integral number of sectors.
1517  //
1518 
1519  if ((SectorBlockOffset( Fcb->Vcb, CurrentDirent->StartingOffset ) != 0) ||
1520  (SectorBlockOffset( Fcb->Vcb, CurrentDirent->DataLength ) != 0)) {
1521 
1523  }
1524 
1525  //
1526  // If interleaved then both the file unit and interleave
1527  // gap must be integral number of sectors.
1528  //
1529 
1530  if ((CurrentDirent->FileUnitSize != 0) &&
1531  ((SectorBlockOffset( Fcb->Vcb, CurrentDirent->FileUnitSize ) != 0) ||
1532  (SectorBlockOffset( Fcb->Vcb, CurrentDirent->InterleaveGapSize ) != 0))) {
1533 
1535  }
1536  }
1537 
1538  //
1539  // If this is the first dirent then add the bytes for the RIFF
1540  // header.
1541  //
1542 
1543  if (FirstPass) {
1544 
1545  FileContext->FileSize = sizeof( RIFF_HEADER );
1546  }
1547 
1548  //
1549  // Add the size of the mode2-form2 sector for each sector
1550  // we have here.
1551  //
1552 
1553  FileContext->FileSize += Int32x32To64( CurrentDirent->DataLength >> SECTOR_SHIFT,
1554  XA_SECTOR_SIZE);
1555 
1556  } else {
1557 
1558  //
1559  // This extent does not have XA sectors. Any previous dirent
1560  // better not have XA sectors.
1561  //
1562 
1563  if (!FirstPass && (ExtentType != CurrentDirent->ExtentType)) {
1564 
1566  }
1567 
1568  //
1569  // Add these bytes to the file size.
1570  //
1571 
1572  FileContext->FileSize += CurrentDirent->DataLength;
1573  }
1574 
1575  //
1576  // If we are at the last dirent then exit.
1577  //
1578 
1579  if (!FlagOn( CurrentDirent->DirentFlags, CD_ATTRIBUTE_MULTI )) {
1580 
1581  break;
1582  }
1583 
1584  //
1585  // Remember the extent type of the current extent.
1586  //
1587 
1588  ExtentType = CurrentDirent->ExtentType;
1589 
1590  //
1591  // Look for the next dirent of the file.
1592  //
1593 
1594  FoundDirent = CdLookupNextDirent( IrpContext,
1595  Fcb,
1596  &CurrentCompoundDirent->DirContext,
1597  &FileContext->CurrentDirent->DirContext );
1598 
1599  //
1600  // If we didn't find the entry then this is a corrupt directory.
1601  //
1602 
1603  if (!FoundDirent) {
1604 
1606  }
1607 
1608  //
1609  // Remember the dirent we just found.
1610  //
1611 
1612  CurrentCompoundDirent = FileContext->CurrentDirent;
1613  FirstPass = FALSE;
1614 
1615  //
1616  // Look up all of the dirent information for the given dirent.
1617  //
1618 
1619  CdUpdateDirentFromRawDirent( IrpContext,
1620  Fcb,
1621  &CurrentCompoundDirent->DirContext,
1622  &CurrentCompoundDirent->Dirent );
1623 
1624  //
1625  // Set flag to show there were multiple extents.
1626  //
1627 
1629  }
1630 
1631  return;
1632 }
1633 
1634 
1635 VOID
1637  _In_ PIRP_CONTEXT IrpContext,
1639  )
1640 
1641 /*++
1642 
1643 Routine Description:
1644 
1645  This routine is called to cleanup the enumeration context for a file
1646  search in a directory. We will unpin any remaining Bcbs and free
1647  any allocated buffers.
1648 
1649 Arguments:
1650 
1651  FileContext - Enumeration context for the file search.
1652 
1653 Return Value:
1654 
1655  None.
1656 
1657 --*/
1658 
1659 {
1660  PCOMPOUND_DIRENT CurrentCompoundDirent;
1661  ULONG Count = 2;
1662 
1663  PAGED_CODE();
1664 
1665  UNREFERENCED_PARAMETER( IrpContext );
1666 
1667  //
1668  // Cleanup the individual compound dirents.
1669  //
1670 
1671  do {
1672 
1673  CurrentCompoundDirent = &FileContext->Dirents[ Count ];
1674  CdCleanupDirContext( IrpContext, &CurrentCompoundDirent->DirContext );
1675  CdCleanupDirent( IrpContext, &CurrentCompoundDirent->Dirent );
1676 
1677  } while (Count--);
1678 
1679  return;
1680 }
1681 
1682 
1683 //
1684 // Local support routine
1685 //
1686 
1687 ULONG
1689  _In_ PIRP_CONTEXT IrpContext,
1691  )
1692 
1693 /*++
1694 
1695 Routine Description:
1696 
1697  This routine takes a Dirent enumeration context and computes the offset
1698  to the next dirent. A non-zero value indicates the offset within this
1699  sector. A zero value indicates to move to the next sector. If the
1700  current dirent does not fit within the sector then we will raise
1701  STATUS_CORRUPT.
1702 
1703 Arguments:
1704 
1705  DirContext - Enumeration context indicating the current position in
1706  the sector.
1707 
1708 Return Value:
1709 
1710  ULONG - Offset to the next dirent in this sector or zero if the
1711  next dirent is in the next sector.
1712 
1713  This routine will raise on a dirent which does not fit into the
1714  described data buffer.
1715 
1716 --*/
1717 
1718 {
1719  ULONG NextDirentOffset;
1720  PRAW_DIRENT RawDirent;
1721 
1722  PAGED_CODE();
1723 
1724  UNREFERENCED_PARAMETER( IrpContext );
1725 
1726  //
1727  // We should always have at least a byte still available in the
1728  // current buffer.
1729  //
1730 
1731  NT_ASSERT( (DirContext->DataLength - DirContext->SectorOffset) >= 1 );
1732 
1733  //
1734  // Get a pointer to the current dirent.
1735  //
1736 
1737  RawDirent = CdRawDirent( IrpContext, DirContext );
1738 
1739  //
1740  // If the dirent length is non-zero then look at the current dirent.
1741  //
1742 
1743  if (RawDirent->DirLen != 0) {
1744 
1745  //
1746  // Check the following bound for the dirent length.
1747  //
1748  // - Fits in the available bytes in the sector.
1749  // - Is at least the minimal dirent size.
1750  // - Is large enough to hold the file name.
1751  //
1752 
1753  if ((RawDirent->DirLen > (DirContext->DataLength - DirContext->SectorOffset)) ||
1754  (RawDirent->DirLen < MIN_RAW_DIRENT_LEN) ||
1755  (RawDirent->DirLen < (MIN_RAW_DIRENT_LEN - 1 + RawDirent->FileIdLen))) {
1756 
1758  }
1759 
1760  //
1761  // Copy the dirent length field.
1762  //
1763 
1764  NextDirentOffset = RawDirent->DirLen;
1765 
1766  //
1767  // If we are exactly at the next sector then tell our caller by
1768  // returning zero.
1769  //
1770 
1771  if (NextDirentOffset == (DirContext->DataLength - DirContext->SectorOffset)) {
1772 
1773  NextDirentOffset = 0;
1774  }
1775 
1776  } else {
1777 
1778  NextDirentOffset = 0;
1779  }
1780 
1781  return NextDirentOffset;
1782 }
1783 
1784 
1785 //
1786 // Local support routine
1787 //
1788 
1791  _In_ PIRP_CONTEXT IrpContext,
1792  _In_ PRAW_DIRENT RawDirent,
1794  )
1795 
1796 /*++
1797 
1798 Routine Description:
1799 
1800  This routine is called to scan through the system use area to test if
1801  the current dirent has the XA bit set. The bit in the in-memory
1802  dirent will be set as appropriate.
1803 
1804 Arguments:
1805 
1806  RawDirent - Pointer to the on-disk dirent.
1807 
1808  Dirent - Pointer to the in-memory dirent. We will update this with the
1809  appropriate XA flag.
1810 
1811 Return Value:
1812 
1813  XA_EXTENT_TYPE - Type of physical extent for this on disk dirent.
1814 
1815 --*/
1816 
1817 {
1819  PSYSTEM_USE_XA SystemUseArea;
1820 
1821  PAGED_CODE();
1822 
1823  UNREFERENCED_PARAMETER( IrpContext );
1824 
1825  //
1826  // Check if there is enough space for the XA system use area.
1827  //
1828 
1829  if (Dirent->DirentLength - Dirent->SystemUseOffset >= sizeof( SYSTEM_USE_XA )) {
1830 
1831  SystemUseArea = Add2Ptr( RawDirent, Dirent->SystemUseOffset, PSYSTEM_USE_XA );
1832 
1833  //
1834  // Check for a valid signature.
1835  //
1836 
1837  if (SystemUseArea->Signature == SYSTEM_XA_SIGNATURE) {
1838 
1839  //
1840  // Check for an audio track.
1841  //
1842 
1843  if (FlagOn( SystemUseArea->Attributes, SYSTEM_USE_XA_DA )) {
1844 
1845  ExtentType = CDAudio;
1846 
1847  } else if (FlagOn( SystemUseArea->Attributes, SYSTEM_USE_XA_FORM2 )) {
1848 
1849  //
1850  // Check for XA data. Note that a number of discs (video CDs)
1851  // have files marked as type XA Mode 2 Form 1 (2048 bytes of
1852  // user data), but actually record these sectors as Mode2 Form 2
1853  // (2352). We will fail to read these files, since for M2F1,
1854  // a normal read CD command is issued (as per SCSI specs).
1855  //
1856 
1858  }
1859 
1860  Dirent->XAAttributes = SystemUseArea->Attributes;
1861  Dirent->XAFileNumber = SystemUseArea->FileNumber;
1862  }
1863  }
1864 
1865  Dirent->ExtentType = ExtentType;
1866  return ExtentType;
1867 }
1868 
1869 
1870 
ULONG DataLength
Definition: cdstruc.h:1606
#define CdRawDirentFlags(IC, RD)
Definition: cd.h:370
signed char * PCHAR
Definition: retypes.h:7
#define VCB_STATE_JOLIET
Definition: cdstruc.h:714
#define SYSTEM_USE_XA_FORM2
Definition: cd.h:517
VOID CdUpdateDirentName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PDIRENT Dirent, _In_ ULONG IgnoreCase)
Definition: dirsup.c:534
#define CdRawDirent(IC, DC)
Definition: dirsup.c:88
#define TRUE
Definition: types.h:120
UCHAR DirLen
Definition: cd.h:332
BOOLEAN CdIsNameInExpression(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME CurrentName, _In_ PCD_NAME SearchExpression, _In_ ULONG WildcardFlags, _In_ BOOLEAN CheckVersion)
Definition: namesup.c:844
USHORT Attributes
Definition: cd.h:493
#define Add2Ptr(PTR, INC)
Dirent ExtentType
Definition: dirsup.c:520
#define SectorBlockOffset(V, LB)
Definition: cdprocs.h:1636
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
ULONG InterleaveGapSize
Definition: cdstruc.h:1633
PFILE_OBJECT FileObject
Definition: ntfs.h:504
BOOLEAN CdIs8dot3Name(_In_ PIRP_CONTEXT IrpContext, _In_ UNICODE_STRING FileName)
Definition: namesup.c:429
Definition: cd.h:524
VOID CdLookupLastFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1426
Definition: cdstruc.h:908
#define SECTOR_SHIFT
Definition: cd.h:32
Dirent DirentOffset
Definition: dirsup.c:444
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
LONG NTSTATUS
Definition: precomp.h:26
ULONG CdShortNameDirentOffset(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING Name)
Definition: namesup.c:955
ULONG CdCheckRawDirentBounds(_In_ PIRP_CONTEXT IrpContext, _In_ PDIRENT_ENUM_CONTEXT DirContext)
Definition: dirsup.c:1688
ULONG BlockSize
Definition: cdstruc.h:626
DIRENT_ENUM_CONTEXT DirContext
Definition: cdstruc.h:1689
#define CdCleanupDirContext(IC, DC)
Definition: cdprocs.h:553
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG FileUnitSize
Definition: cdstruc.h:1632
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define _Post_notnull_
Definition: no_sal2.h:460
#define SYSTEM_USE_XA_DA
Definition: cd.h:518
#define WordAlign(Ptr)
Definition: cdprocs.h:1564
uint16_t * PWCHAR
Definition: typedefs.h:54
ULONG VcbState
Definition: cdstruc.h:546
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PFILE_ENUM_CONTEXT _Out_ PCD_NAME * MatchingName
Definition: cdprocs.h:444
VOID CdConvertBigToLittleEndian(_In_ PIRP_CONTEXT IrpContext, _In_reads_bytes_(ByteCount) PCHAR BigEndian, _In_ ULONG ByteCount, _Out_writes_bytes_(ByteCount) PCHAR LittleEndian)
Definition: namesup.c:110
#define DIRENT_FLAG_ALLOC_BUFFER
Definition: cdstruc.h:1676
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define FILE_CONTEXT_MULTIPLE_DIRENTS
Definition: cdstruc.h:1745
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _In_ ULONG ShortNameDirentOffset
Definition: dirsup.c:1110
_At_(Dirent->CdTime, _Post_notnull_) VOID CdUpdateDirentFromRawDirent(_In_ PIRP_CONTEXT IrpContext
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
UCHAR FileIdLen
Definition: cd.h:345
#define SECTOR_SIZE
Definition: winldr.h:34
CdLookupInitialFileDirent(IrpContext, Fcb, FileContext, Fcb->StreamOffset)
#define CD_ATTRIBUTE_DIRECTORY
Definition: cd.h:354
USHORT Signature
Definition: cd.h:499
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
PAGED_CODE()
#define _Out_
Definition: no_sal2.h:323
UCHAR FileLoc[4]
Definition: cd.h:334
return Found
Definition: dirsup.c:1270
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN IgnoreCase
Definition: dirsup.c:1110
UCHAR DirentFlags
Definition: cdstruc.h:1619
#define DIRENT_FLAG_CONSTANT_ENTRY
Definition: cdstruc.h:1677
#define PCHAR
Definition: match.c:90
BOOLEAN CdIsLegalName(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING FileName)
Definition: namesup.c:377
UCHAR FileId[MAX_FILE_ID_LENGTH]
Definition: cd.h:346
int64_t LONGLONG
Definition: typedefs.h:66
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _In_ ULONG _Inout_ PFILE_ENUM_CONTEXT FileContext
Definition: dirsup.c:1148
BOOLEAN NTAPI CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *BcbResult, OUT PVOID *Buffer)
Definition: pinsup.c:694
_Success_(return !=FALSE)
Definition: dirsup.c:823
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
#define CopyUchar4(Dst, Src)
Definition: cdprocs.h:1711
__wchar_t WCHAR
Definition: xmlstorage.h:180
CdVerifyOrCreateDirStreamFile(IrpContext, Fcb)
#define CD_ATTRIBUTE_MULTI
Definition: cd.h:356
#define CD_ATTRIBUTE_ASSOC
Definition: cd.h:355
UCHAR XarLen
Definition: cd.h:333
#define CdPagedPool
Definition: cdprocs.h:1385
#define _Inout_
Definition: no_sal2.h:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
XA_EXTENT_TYPE ExtentType
Definition: cdstruc.h:1669
ULONG Flags
Definition: ntfs.h:520
#define SYSTEM_XA_SIGNATURE
Definition: cd.h:520
#define TAG_DIRENT_NAME
Definition: cdprocs.h:79
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SectorTruncate(L)
Definition: cdprocs.h:1598
_In_ PFCB Fcb
Definition: dirsup.c:398
static const WCHAR L[]
Definition: oid.c:1250
ULONG SystemUseOffset
Definition: cdstruc.h:1639
struct _RIFF_HEADER RIFF_HEADER
XA_EXTENT_TYPE CdCheckForXAExtent(_In_ PIRP_CONTEXT IrpContext, _In_ PRAW_DIRENT RawDirent, _Inout_ PDIRENT Dirent)
Definition: dirsup.c:1790
UCHAR IntLeaveSize
Definition: cd.h:341
UNICODE_STRING CdUnicodeDirectoryNames[]
Definition: cddata.c:52
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
if(RawDirent->IntLeaveSize !=0)
Definition: dirsup.c:487
UCHAR RecordTime[6]
Definition: cd.h:338
#define MIN_RAW_DIRENT_LEN
Definition: cd.h:360
#define VCB_STATE_CDXA
Definition: cdstruc.h:717
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
BOOLEAN CdLookupNextDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PDIRENT_ENUM_CONTEXT CurrentDirContext, _Inout_ PDIRENT_ENUM_CONTEXT NextDirContext)
Definition: dirsup.c:208
UCHAR XAFileNumber
Definition: cdstruc.h:995
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
UCHAR IntLeaveSkip
Definition: cd.h:342
#define DIRENT_FLAG_NOT_PERSISTENT
Definition: cdstruc.h:1679
#define XA_SECTOR_SIZE
Definition: cd.h:35
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define CdFreePool(x)
Definition: cdprocs.h:2200
unsigned short USHORT
Definition: pedump.c:61
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
BOOLEAN CdLookupNextInitialFileDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _Inout_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1275
VOID CdLookupDirent(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ ULONG DirentOffset, _Out_ PDIRENT_ENUM_CONTEXT DirContext)
Definition: dirsup.c:125
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: dirsup.c:425
#define BYTE_COUNT_8_DOT_3
Definition: cd.h:362
ULONG StartingOffset
Definition: cdstruc.h:1599
unsigned int ULONG
Definition: retypes.h:1
Definition: cd.h:526
PVCB Vcb
Definition: cdstruc.h:939
VOID CdCleanupFileContext(_In_ PIRP_CONTEXT IrpContext, _In_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:1636
UCHAR DataLen[4]
Definition: cd.h:336
#define _In_range_(lb, ub)
Definition: no_sal2.h:227
UNREFERENCED_PARAMETER(Fcb)
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT DirContext
Definition: dirsup.c:398
return STATUS_SUCCESS
Definition: btrfs.c:2725
enum _XA_EXTENT_TYPE XA_EXTENT_TYPE
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1111
#define CdUnpinData(IC, B)
Definition: cdprocs.h:261
UCHAR FileNumber
Definition: cd.h:505
#define Int32x32To64(a, b)
BOOLEAN CdFindDirectory(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ PCD_NAME Name, _In_ BOOLEAN IgnoreCase, _Inout_ PFILE_ENUM_CONTEXT FileContext)
Definition: dirsup.c:997
#define CdCleanupDirent(IC, D)
Definition: cdprocs.h:547
#define SHORT_NAME_SHIFT
Definition: cd.h:364
ULONG ThisShortNameDirentOffset
Definition: dirsup.c:1152
#define NT_ASSERT
Definition: rtlfuncs.h:3312
USHORT XAAttributes
Definition: cdstruc.h:989