ReactOS  0.4.14-dev-52-g6116262
pathsup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  PathSup.c
8 
9 Abstract:
10 
11  This module implements the Path Table support routines for Cdfs.
12 
13  The path table on a CDROM is a condensed summary of the entire
14  directory structure. It is stored on a number of contiguous sectors
15  on the disk. Each directory on the disk has an entry in the path
16  table. The entries are aligned on USHORT boundaries and MAY span
17  sector boundaries. The entries are stored as a breadth-first search.
18 
19  The first entry in the table contains the entry for the root. The
20  next entries will consist of the contents of the root directory. The
21  next entries will consist of the all the directories at the next level
22  of the tree. The children of a given directory will be grouped together.
23 
24  The directories are assigned ordinal numbers based on their position in
25  the path table. The root dirctory is assigned ordinal value 1.
26 
27  Path table sectors:
28 
29  Ordinal 1 2 3 4 5 6
30  +-----------+
31  | Spanning |
32  | Sectors |
33  +----------------------------+ +------------------------+
34  | | | | | | | | |
35  DirName | \ | a | b |c| | c | d | e |
36  | | | | | | | | |
37  Parent #| 1 | 1 | 1 | | | 2 | 2 | 3 |
38  +----------------------------+ +------------------------+
39 
40  Directory Tree:
41 
42  \ (root)
43 
44  / \
45  / \
46  a b
47 
48  / \ \
49  / \ \
50  c d e
51 
52  Path Table Entries:
53 
54  - Position scan at known offset in the path table. Path Entry at
55  this offset must exist and is known to be valid. Used when
56  scanning for the children of a given directory.
57 
58  - Position scan at known offset in the path table. Path Entry is
59  known to start at this location but the bounds must be checked
60  for validity.
61 
62  - Move to next path entry in the table.
63 
64  - Update a common path entry structure with the details of the
65  on-disk structure. This is used to smooth out the differences
66  in the on-disk structures.
67 
68  - Update the filename in the in-memory path entry with the bytes
69  off the disk. For Joliet disks we will have
70  to convert to little endian. We assume that directories
71  don't have version numbers.
72 
73 
74 --*/
75 
76 #include "cdprocs.h"
77 
78 //
79 // The Bug check file id for this module
80 //
81 
82 #define BugCheckFileId (CDFS_BUG_CHECK_PATHSUP)
83 
84 //
85 // Local macros
86 //
87 
88 //
89 // PRAW_PATH_ENTRY
90 // CdRawPathEntry (
91 // _In_ PIRP_CONTEXT IrpContext,
92 // _In_ PPATH_ENUM_CONTEXT PathContext
93 // );
94 //
95 
96 #define CdRawPathEntry(IC, PC) \
97  Add2Ptr( (PC)->Data, (PC)->DataOffset, PRAW_PATH_ENTRY )
98 
99 //
100 // Local support routines
101 //
102 
103 VOID
105  _In_ PIRP_CONTEXT IrpContext,
106  _In_ PFCB Fcb,
107  _In_ LONGLONG BaseOffset,
108  _Inout_ PPATH_ENUM_CONTEXT PathContext
109  );
110 
111 _Success_(return != FALSE)
112 BOOLEAN
113 CdUpdatePathEntryFromRawPathEntry (
114  _In_ PIRP_CONTEXT IrpContext,
115  _In_ ULONG Ordinal,
116  _In_ BOOLEAN VerifyBounds,
117  _In_ PPATH_ENUM_CONTEXT PathContext,
118  _Out_ PPATH_ENTRY PathEntry
119  );
120 
121 #ifdef ALLOC_PRAGMA
122 #pragma alloc_text(PAGE, CdFindPathEntry)
123 #pragma alloc_text(PAGE, CdLookupPathEntry)
124 #pragma alloc_text(PAGE, CdLookupNextPathEntry)
125 #pragma alloc_text(PAGE, CdMapPathTableBlock)
126 #pragma alloc_text(PAGE, CdUpdatePathEntryFromRawPathEntry)
127 #pragma alloc_text(PAGE, CdUpdatePathEntryName)
128 #endif
129 
130 
131 VOID
133  _In_ PIRP_CONTEXT IrpContext,
134  _In_ ULONG PathEntryOffset,
135  _In_ ULONG Ordinal,
136  _In_ BOOLEAN VerifyBounds,
138  )
139 
140 /*++
141 
142 Routine Description:
143 
144  This routine is called to initiate a walk through a path table. We are
145  looking for a path table entry at location PathEntryOffset.
146 
147 Arguments:
148 
149  PathEntryOffset - This is our target point in the Path Table. We know that
150  a path entry must begin at this point although we may have to verify
151  the bounds.
152 
153  Ordinal - Ordinal number for the directory at the PathEntryOffset above.
154 
155  VerifyBounds - Indicates whether we need to check the validity of
156  this entry.
157 
158  CompoundPathEntry - PathEnumeration context and in-memory path entry. This
159  has been initialized outside of this call.
160 
161 Return Value:
162 
163  None.
164 
165 --*/
166 
167 {
168  PPATH_ENUM_CONTEXT PathContext = &CompoundPathEntry->PathContext;
169  LONGLONG CurrentBaseOffset;
170 
171  PAGED_CODE();
172 
173  //
174  // Compute the starting base and starting path table offset.
175  //
176 
177  CurrentBaseOffset = SectorTruncate( PathEntryOffset );
178 
179  //
180  // Map the next block in the Path Table.
181  //
182 
183  CdMapPathTableBlock( IrpContext,
184  IrpContext->Vcb->PathTableFcb,
185  CurrentBaseOffset,
186  PathContext );
187 
188  //
189  // Set up our current offset into the Path Context.
190  //
191 
192  PathContext->DataOffset = PathEntryOffset - PathContext->BaseOffset;
193 
194  //
195  // Update the in-memory structure for this path entry.
196  //
197 
198  (VOID) CdUpdatePathEntryFromRawPathEntry( IrpContext,
199  Ordinal,
200  VerifyBounds,
201  &CompoundPathEntry->PathContext,
202  &CompoundPathEntry->PathEntry );
203 }
204 
205 
206 BOOLEAN
208  _In_ PIRP_CONTEXT IrpContext,
209  _Inout_ PPATH_ENUM_CONTEXT PathContext,
210  _Inout_ PPATH_ENTRY PathEntry
211  )
212 
213 /*++
214 
215 Routine Description:
216 
217  This routine is called to move to the next path table entry. We know
218  the offset and the length of the current entry. We start by computing
219  the offset of the next entry and determine if it is contained in the
220  table. Then we check to see if we need to move to the next sector in
221  the path table. We always map two sectors at a time so we don't
222  have to deal with any path entries which span sectors. We move to
223  the next sector if we are in the second sector of the current mapped
224  data block.
225 
226  We look up the next entry and update the path entry structure with
227  the values out of the raw sector but don't update the CdName structure.
228 
229 Arguments:
230 
231  PathContext - Enumeration context for this scan of the path table.
232 
233  PathEntry - In-memory representation of the on-disk path table entry.
234 
235 Return Value:
236 
237  BOOLEAN - TRUE if another entry is found, FALSE otherwise.
238  This routine may raise on error.
239 
240 --*/
241 
242 {
243  LONGLONG CurrentBaseOffset;
244 
245  PAGED_CODE();
246 
247  //
248  // Get the offset of the next path entry within the current
249  // data block.
250  //
251 
252  PathContext->DataOffset += PathEntry->PathEntryLength;
253 
254  //
255  // If we are in the last data block then check if we are beyond the
256  // end of the file.
257  //
258 
259  if (PathContext->LastDataBlock) {
260 
261  if (PathContext->DataOffset >= PathContext->DataLength) {
262 
263  return FALSE;
264  }
265 
266  //
267  // If we are not in the last data block of the path table and
268  // this offset is in the second sector then move to the next
269  // data block.
270  //
271 
272  } else if (PathContext->DataOffset >= SECTOR_SIZE) {
273 
274  CurrentBaseOffset = PathContext->BaseOffset + SECTOR_SIZE;
275 
276  CdMapPathTableBlock( IrpContext,
277  IrpContext->Vcb->PathTableFcb,
278  CurrentBaseOffset,
279  PathContext );
280 
281  //
282  // Set up our current offset into the Path Context.
283  //
284 
285  PathContext->DataOffset -= SECTOR_SIZE;
286  }
287 
288  //
289  // Now update the path entry with the values from the on-disk
290  // structure.
291  //
292 
293  return CdUpdatePathEntryFromRawPathEntry( IrpContext,
294  PathEntry->Ordinal + 1,
295  TRUE,
296  PathContext,
297  PathEntry );
298 }
299 
300 _Success_(return != FALSE)
301 BOOLEAN
302 CdFindPathEntry (
303  _In_ PIRP_CONTEXT IrpContext,
308  )
309 
310 /*++
311 
312 Routine Description:
313 
314  This routine will walk through the path table looking for a matching entry for DirName
315  among the child directories of the ParentFcb.
316 
317 Arguments:
318 
319  ParentFcb - This is the directory we are examining. We know the ordinal and path table
320  offset for this directory in the path table. If this is the first scan for this
321  Fcb we will update the first child offset for this directory in the path table.
322 
323  DirName - This is the name we are searching for. This name will not contain wildcard
324  characters. The name will also not have a version string.
325 
326  IgnoreCase - Indicates if this search is exact or ignore case.
327 
328  CompoundPathEntry - Complete path table enumeration structure. We will have initialized
329  it for the search on entry. This will be positioned at the matching name if found.
330 
331 Return Value:
332 
333  BOOLEAN - TRUE if matching entry found, FALSE otherwise.
334 
335 --*/
336 
337 {
338  BOOLEAN Found = FALSE;
339  BOOLEAN UpdateChildOffset = TRUE;
340 
342  ULONG StartingOrdinal;
343 
344  PAGED_CODE();
345 
346  //
347  // Position ourselves at either the first child or at the directory itself.
348  // Lock the Fcb to get this value and remember whether to update with the first
349  // child.
350  //
351 
353  StartingOrdinal = ParentFcb->Ordinal;
354 
355  //
356  // ISO 9660 9.4.4 restricts the backpointer from child to parent in a
357  // pathtable entry to 16bits. Although we internally store ordinals
358  // as 32bit values, it is impossible to search for the children of a
359  // directory whose ordinal value is greater than MAXUSHORT. Media that
360  // could induce such a search is illegal.
361  //
362  // Note that it is not illegal to have more than MAXUSHORT directories.
363  //
364 
365  if (ParentFcb->Ordinal > MAXUSHORT) {
366 
368  }
369 
370  CdLockFcb( IrpContext, ParentFcb );
371 
372  if (ParentFcb->ChildPathTableOffset != 0) {
373 
374  StartingOffset = ParentFcb->ChildPathTableOffset;
375  StartingOrdinal = ParentFcb->ChildOrdinal;
376  UpdateChildOffset = FALSE;
377 
378  } else if (ParentFcb == ParentFcb->Vcb->RootIndexFcb) {
379 
380  UpdateChildOffset = FALSE;
381  }
382 
383  CdUnlockFcb( IrpContext, ParentFcb );
384 
385  CdLookupPathEntry( IrpContext, StartingOffset, StartingOrdinal, FALSE, CompoundPathEntry );
386 
387  //
388  // Loop until we find a match or are beyond the children for this directory.
389  //
390 
391  do {
392 
393  //
394  // If we are beyond this directory then return FALSE.
395  //
396 
397  if (CompoundPathEntry->PathEntry.ParentOrdinal > ParentFcb->Ordinal) {
398 
399  //
400  // Update the Fcb with the offsets for the children in the path table.
401  //
402 
403  if (UpdateChildOffset) {
404 
405  CdLockFcb( IrpContext, ParentFcb );
406 
407  ParentFcb->ChildPathTableOffset = StartingOffset;
408  ParentFcb->ChildOrdinal = StartingOrdinal;
409 
410  CdUnlockFcb( IrpContext, ParentFcb );
411  }
412 
413  break;
414  }
415 
416  //
417  // If we are within the children of this directory then check for a match.
418  //
419 
420  if (CompoundPathEntry->PathEntry.ParentOrdinal == ParentFcb->Ordinal) {
421 
422  //
423  // Update the child offset if not yet done.
424  //
425 
426  if (UpdateChildOffset) {
427 
428  CdLockFcb( IrpContext, ParentFcb );
429 
430  ParentFcb->ChildPathTableOffset = CompoundPathEntry->PathEntry.PathTableOffset;
431  ParentFcb->ChildOrdinal = CompoundPathEntry->PathEntry.Ordinal;
432 
433  CdUnlockFcb( IrpContext, ParentFcb );
434 
435  UpdateChildOffset = FALSE;
436  }
437 
438  //
439  // Update the name in the path entry.
440  //
441 
442  CdUpdatePathEntryName( IrpContext, &CompoundPathEntry->PathEntry, IgnoreCase );
443 
444  //
445  // Now compare the names for an exact match.
446  //
447 
448  if (CdIsNameInExpression( IrpContext,
449  &CompoundPathEntry->PathEntry.CdCaseDirName,
450  DirName,
451  0,
452  FALSE )) {
453 
454  //
455  // Let our caller know we have a match.
456  //
457 
458  Found = TRUE;
459  break;
460  }
461  }
462 
463  //
464  // Go to the next entry in the path table. Remember the current position
465  // in the event we update the Fcb.
466  //
467 
468  StartingOffset = CompoundPathEntry->PathEntry.PathTableOffset;
469  StartingOrdinal = CompoundPathEntry->PathEntry.Ordinal;
470 
471  } while (CdLookupNextPathEntry( IrpContext,
472  &CompoundPathEntry->PathContext,
473  &CompoundPathEntry->PathEntry ));
474 
475  return Found;
476 }
477 
478 
479 //
480 // Local support routine
481 //
482 
483 VOID
485  _In_ PIRP_CONTEXT IrpContext,
486  _In_ PFCB Fcb,
487  _In_ LONGLONG BaseOffset,
488  _Inout_ PPATH_ENUM_CONTEXT PathContext
489  )
490 
491 /*++
492 
493 Routine Description:
494 
495  This routine is called to map (or allocate and copy) the next
496  data block in the path table. We check if the next block will
497  span a view boundary and allocate an auxilary buffer in that case.
498 
499 Arguments:
500 
501  Fcb - This is the Fcb for the Path Table.
502 
503  BaseOffset - Offset of the first sector to map. This will be on a
504  sector boundary.
505 
506  PathContext - Enumeration context to update in this routine.
507 
508 Return Value:
509 
510  None.
511 
512 --*/
513 
514 {
515  ULONG CurrentLength;
517  ULONG DataOffset;
518  ULONG PassCount;
519  PVOID Sector;
520 
521  PAGED_CODE();
522 
523  UNREFERENCED_PARAMETER( IrpContext );
524 
525  //
526  // Map the new block and set the enumeration context to this
527  // point. Allocate an auxilary buffer if necessary.
528  //
529 
530  CurrentLength = 2 * SECTOR_SIZE;
531 
532  if (CurrentLength >= (ULONG) (Fcb->FileSize.QuadPart - BaseOffset)) {
533 
534  CurrentLength = (ULONG) (Fcb->FileSize.QuadPart - BaseOffset);
535 
536  //
537  // We know this is the last data block for this
538  // path table.
539  //
540 
541  PathContext->LastDataBlock = TRUE;
542  }
543 
544  //
545  // Set context values.
546  //
547 
548  PathContext->BaseOffset = (ULONG) BaseOffset;
549  PathContext->DataLength = CurrentLength;
550 
551  //
552  // Drop the previous sector's mapping
553  //
554 
555  CdUnpinData( IrpContext, &PathContext->Bcb );
556 
557  //
558  // Check if spanning a view section. The following must
559  // be true before we take this step.
560  //
561  // Data length is more than one sector.
562  // Starting offset must be one sector before the
563  // cache manager VACB boundary.
564  //
565 
566  if ((CurrentLength > SECTOR_SIZE) &&
567  (FlagOn( ((ULONG) BaseOffset), VACB_MAPPING_MASK ) == LAST_VACB_SECTOR_OFFSET )) {
568 
569  //
570  // Map each sector individually and store into an auxilary
571  // buffer.
572  //
573 
575  DataOffset = 0;
576  PassCount = 2;
577 
578  PathContext->Data = FsRtlAllocatePoolWithTag( CdPagedPool,
579  CurrentLength,
581  PathContext->AllocatedData = TRUE;
582 
583  while (PassCount--) {
584 
586  (PLARGE_INTEGER) &BaseOffset,
587  SectorSize,
588  TRUE,
589  &PathContext->Bcb,
590  &Sector );
591 
592  RtlCopyMemory( Add2Ptr( PathContext->Data, DataOffset, PVOID ),
593  Sector,
594  SectorSize );
595 
596  CdUnpinData( IrpContext, &PathContext->Bcb );
597 
598  BaseOffset += SECTOR_SIZE;
599  SectorSize = CurrentLength - SECTOR_SIZE;
600  DataOffset = SECTOR_SIZE;
601  }
602 
603  //
604  // Otherwise we can just map the data into the cache.
605  //
606 
607  } else {
608 
609  //
610  // There is a slight chance that we have allocated an
611  // auxilary buffer on the previous sector.
612  //
613 
614  if (PathContext->AllocatedData) {
615 
616  CdFreePool( &PathContext->Data );
617  PathContext->AllocatedData = FALSE;
618  }
619 
621  (PLARGE_INTEGER) &BaseOffset,
622  CurrentLength,
623  TRUE,
624  &PathContext->Bcb,
625  &PathContext->Data );
626  }
627 
628  return;
629 }
630 
631 
632 //
633 // Local support routine
634 //
635 _Success_(return != FALSE)
636 BOOLEAN
637 CdUpdatePathEntryFromRawPathEntry (
638  _In_ PIRP_CONTEXT IrpContext,
639  _In_ ULONG Ordinal,
640  _In_ BOOLEAN VerifyBounds,
641  _In_ PPATH_ENUM_CONTEXT PathContext,
642  _Out_ PPATH_ENTRY PathEntry
643  )
644 
645 /*++
646 
647 Routine Description:
648 
649  This routine is called to update the in-memory Path Entry from the on-disk
650  path entry. We also do a careful check of the bounds if requested and we
651  are in the last data block of the path table.
652 
653 Arguments:
654 
655  Ordinal - Ordinal number for this directory.
656 
657  VerifyBounds - Check that the current raw Path Entry actually fits
658  within the data block.
659 
660  PathContext - Current path table enumeration context.
661 
662  PathEntry - Pointer to the in-memory path entry structure.
663 
664 Return Value:
665 
666  TRUE if updated ok,
667  FALSE if we've hit the end of the pathtable - zero name length && PT size is a multiple
668  of blocksize. This is a workaround for some Video CDs. Win 9x works around this.
669 
670  This routine may raise.
671 
672 --*/
673 
674 {
675  PRAW_PATH_ENTRY RawPathEntry = CdRawPathEntry( IrpContext, PathContext );
676  ULONG RemainingDataLength;
677 
678  PAGED_CODE();
679 
680  //
681  // Check for a name length of zero. This is the first byte of the record,
682  // and there must be at least one byte remaining in the buffer else we
683  // wouldn't be here (caller would have spotted buffer end).
684  //
685 
686  PathEntry->DirNameLen = CdRawPathIdLen( IrpContext, RawPathEntry );
687 
688  if (0 == PathEntry->DirNameLen) {
689 
690  //
691  // If we are in the last block, and the path table size (ie last block) is a
692  // multiple of block size, then we will consider this the end of the path table
693  // rather than raising an error. Workaround for NTI Cd Maker video CDs which
694  // round path table length to blocksize multiple. In all other cases we consider
695  // a zero length name to be corruption.
696  //
697 
698  if ( PathContext->LastDataBlock &&
699  (0 == BlockOffset( IrpContext->Vcb, PathContext->DataLength))) {
700 
701  return FALSE;
702  }
703 
705  }
706 
707  //
708  // Check if we should verify the path entry. If we are not in the last
709  // data block then there is nothing to check.
710  //
711 
712  if (PathContext->LastDataBlock && VerifyBounds) {
713 
714  //
715  // Quick check to see if the maximum size is still available. This
716  // will handle most cases and we don't need to access any of the
717  // fields.
718  //
719 
720  RemainingDataLength = PathContext->DataLength - PathContext->DataOffset;
721 
722  if (RemainingDataLength < sizeof( RAW_PATH_ENTRY )) {
723 
724  //
725  // Make sure the remaining bytes hold the path table entries.
726  // Do the following checks.
727  //
728  // - A minimal path table entry will fit (and then check)
729  // - This path table entry (with dir name) will fit.
730  //
731 
732  if ((RemainingDataLength < MIN_RAW_PATH_ENTRY_LEN) ||
733  (RemainingDataLength < (ULONG) (CdRawPathIdLen( IrpContext, RawPathEntry ) + MIN_RAW_PATH_ENTRY_LEN - 1))) {
734 
736  }
737  }
738  }
739 
740  //
741  // The ordinal number of this directory is passed in.
742  // Compute the path table offset of this entry.
743  //
744 
745  PathEntry->Ordinal = Ordinal;
746  PathEntry->PathTableOffset = PathContext->BaseOffset + PathContext->DataOffset;
747 
748  //
749  // We know we can safely access all of the fields of the raw path table at
750  // this point.
751 
752  //
753  // Bias the disk offset by the number of logical blocks
754  //
755 
756  CopyUchar4( &PathEntry->DiskOffset, CdRawPathLoc( IrpContext, RawPathEntry ));
757 
758  PathEntry->DiskOffset += CdRawPathXar( IrpContext, RawPathEntry );
759 
760  CopyUchar2( &PathEntry->ParentOrdinal, &RawPathEntry->ParentNum );
761 
762  PathEntry->PathEntryLength = PathEntry->DirNameLen + MIN_RAW_PATH_ENTRY_LEN - 1;
763 
764  //
765  // Align the path entry length on a ushort boundary.
766  //
767 
768  PathEntry->PathEntryLength = WordAlign( PathEntry->PathEntryLength );
769 
770  PathEntry->DirName = (PCHAR)RawPathEntry->DirId;
771 
772  return TRUE;
773 }
774 
775 
776 //
777 // Local support routine
778 //
779 
780 VOID
782  _In_ PIRP_CONTEXT IrpContext,
783  _Inout_ PPATH_ENTRY PathEntry,
785  )
786 
787 /*++
788 
789 Routine Description:
790 
791  This routine will store the directory name into the CdName in the
792  path entry. If this is a Joliet name then we will make sure we have
793  an allocated buffer and need to convert from big endian to little
794  endian. We also correctly update the case name. If this operation is ignore
795  case then we need an auxilary buffer for the name.
796 
797  For an Ansi disk we can use the name from the disk for the exact case. We only
798  need to allocate a buffer for the ignore case name. The on-disk representation of
799  a Unicode name is useless for us. In this case we will need a name buffer for
800  both names. We store a buffer in the PathEntry which can hold two 8.3 unicode
801  names. This means we will almost never need to allocate a buffer in the Ansi case
802  (we only need one buffer and already have 48 characters).
803 
804 Arguments:
805 
806  PathEntry - Pointer to a path entry structure. We have already updated
807  this path entry with the values from the raw path entry.
808 
809 Return Value:
810 
811  None.
812 
813 --*/
814 
815 {
816  ULONG Length;
818 
819  PAGED_CODE();
820 
821  //
822  // Check if this is a self entry. We use a fixed string for this.
823  //
824  // Self-Entry - Length is 1, value is 0.
825  //
826 
827  if ((*PathEntry->DirName == 0) &&
828  (PathEntry->DirNameLen == 1)) {
829 
830  //
831  // There should be no allocated buffers.
832  //
833 
834  NT_ASSERT( !FlagOn( PathEntry->Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER ));
835 
836  //
837  // Now use one of the hard coded directory names.
838  //
839 
840  PathEntry->CdDirName.FileName = CdUnicodeDirectoryNames[0];
841 
842  //
843  // Show that there is no version number.
844  //
845 
846  PathEntry->CdDirName.VersionString.Length = 0;
847 
848  //
849  // The case name is identical.
850  //
851 
852  PathEntry->CdCaseDirName = PathEntry->CdDirName;
853 
854  //
855  // Return now.
856  //
857 
858  return;
859  }
860 
861  //
862  // Compute how large a buffer we will need. If this is an ignore
863  // case operation then we will want a double size buffer. If the disk is not
864  // a Joliet disk then we might need two bytes for each byte in the name.
865  //
866 
867  Length = PathEntry->DirNameLen;
868 
869  if (IgnoreCase) {
870 
871  Length *= 2;
872  }
873 
874  if (!FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
875 
876  Length *= sizeof( WCHAR );
877  }
878 
879  //
880  // Now decide if we need to allocate a new buffer. We will if
881  // this name won't fit in the embedded name buffer and it is
882  // larger than the current allocated buffer. We always use the
883  // allocated buffer if present.
884  //
885  // If we haven't allocated a buffer then use the embedded buffer if the data
886  // will fit. This is the typical case.
887  //
888 
889  if (!FlagOn( PathEntry->Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER ) &&
890  (Length <= sizeof( PathEntry->NameBuffer ))) {
891 
892  PathEntry->CdDirName.FileName.MaximumLength = sizeof( PathEntry->NameBuffer );
893  PathEntry->CdDirName.FileName.Buffer = PathEntry->NameBuffer;
894 
895  } else {
896 
897  //
898  // We need to use an allocated buffer. Check if the current buffer
899  // is large enough.
900  //
901 
902  if (Length > PathEntry->CdDirName.FileName.MaximumLength) {
903 
904  //
905  // Free any allocated buffer.
906  //
907 
908  if (FlagOn( PathEntry->Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER )) {
909 
910  CdFreePool( &PathEntry->CdDirName.FileName.Buffer );
911  ClearFlag( PathEntry->Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER );
912  }
913 
914  PathEntry->CdDirName.FileName.Buffer = FsRtlAllocatePoolWithTag( CdPagedPool,
915  Length,
917 
918  SetFlag( PathEntry->Flags, PATH_ENTRY_FLAG_ALLOC_BUFFER );
919 
920  PathEntry->CdDirName.FileName.MaximumLength = (USHORT) Length;
921  }
922  }
923 
924  //
925  // We now have a buffer for the name. We need to either convert the on-disk bigendian
926  // to little endian or covert the name to Unicode.
927  //
928 
929  if (!FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
930 
931  Status = RtlOemToUnicodeN( PathEntry->CdDirName.FileName.Buffer,
932  PathEntry->CdDirName.FileName.MaximumLength,
933  &Length,
934  PathEntry->DirName,
935  PathEntry->DirNameLen );
936 
938  __analysis_assert( Status == STATUS_SUCCESS );
939  PathEntry->CdDirName.FileName.Length = (USHORT) Length;
940 
941  } else {
942 
943  //
944  // Convert this string to little endian.
945  //
946 
947  CdConvertBigToLittleEndian( IrpContext,
948  PathEntry->DirName,
949  PathEntry->DirNameLen,
950  (PCHAR) PathEntry->CdDirName.FileName.Buffer );
951 
952  PathEntry->CdDirName.FileName.Length = (USHORT) PathEntry->DirNameLen;
953  }
954 
955  //
956  // There is no version string.
957  //
958 
959  PathEntry->CdDirName.VersionString.Length =
960  PathEntry->CdCaseDirName.VersionString.Length = 0;
961 
962  //
963  // If the name string ends with a period then knock off the last
964  // character.
965  //
966 
967  if (PathEntry->CdDirName.FileName.Buffer[(PathEntry->CdDirName.FileName.Length - sizeof( WCHAR )) / 2] == L'.') {
968 
969  //
970  // Shrink the filename length.
971  //
972 
973  PathEntry->CdDirName.FileName.Length -= sizeof( WCHAR );
974  }
975 
976  //
977  // Update the case name buffer if necessary. If this is an exact case
978  // operation then just copy the exact case string.
979  //
980 
981  if (IgnoreCase) {
982 
983  PathEntry->CdCaseDirName.FileName.Buffer = Add2Ptr( PathEntry->CdDirName.FileName.Buffer,
984  PathEntry->CdDirName.FileName.MaximumLength / 2,
985  PWCHAR);
986 
987  PathEntry->CdCaseDirName.FileName.MaximumLength = PathEntry->CdDirName.FileName.MaximumLength / 2;
988 
989  CdUpcaseName( IrpContext,
990  &PathEntry->CdDirName,
991  &PathEntry->CdCaseDirName );
992 
993  } else {
994 
995  PathEntry->CdCaseDirName = PathEntry->CdDirName;
996  }
997 
998  return;
999 }
1000 
1001 
signed char * PCHAR
Definition: retypes.h:7
#define VCB_STATE_JOLIET
Definition: cdstruc.h:714
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
BOOLEAN CdIsNameInExpression(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME CurrentName, _In_ PCD_NAME SearchExpression, _In_ ULONG WildcardFlags, _In_ BOOLEAN CheckVersion)
Definition: namesup.c:844
#define Add2Ptr(PTR, INC)
#define CdQueryFidPathTableOffset(I)
Definition: cdstruc.h:1838
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
PFILE_OBJECT FileObject
Definition: ntfs.h:516
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
LONG NTSTATUS
Definition: precomp.h:26
VOID CdMapPathTableBlock(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ LONGLONG BaseOffset, _Inout_ PPATH_ENUM_CONTEXT PathContext)
Definition: pathsup.c:484
#define CopyUchar2(Dst, Src)
Definition: cdprocs.h:1703
struct _FCB * RootIndexFcb
Definition: cdstruc.h:566
NTSYSAPI NTSTATUS WINAPI RtlOemToUnicodeN(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD)
#define LAST_VACB_SECTOR_OFFSET
Definition: cdstruc.h:1459
#define WordAlign(Ptr)
Definition: cdprocs.h:1564
uint16_t * PWCHAR
Definition: typedefs.h:54
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 PAGED_CODE()
Definition: video.h:57
#define TAG_SPANNING_PATH_TABLE
Definition: cdprocs.h:95
#define CdRawPathIdLen(IC, RP)
Definition: cd.h:455
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1065
#define MIN_RAW_PATH_ENTRY_LEN
Definition: cd.h:443
#define BlockOffset(V, L)
Definition: cdprocs.h:1660
USHORT ParentNum
Definition: cd.h:424
#define CdRawPathEntry(IC, PC)
Definition: pathsup.c:96
unsigned char BOOLEAN
#define _Out_
Definition: no_sal2.h:323
#define VACB_MAPPING_MASK
Definition: cdstruc.h:1458
return Found
Definition: dirsup.c:1270
#define PCHAR
Definition: match.c:90
int64_t LONGLONG
Definition: typedefs.h:66
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
#define CopyUchar4(Dst, Src)
Definition: cdprocs.h:1711
#define CdRawPathLoc(IC, RP)
Definition: cd.h:467
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define TAG_PATH_ENTRY_NAME
Definition: cdprocs.h:92
#define CdPagedPool
Definition: cdprocs.h:1385
#define _Inout_
Definition: no_sal2.h:244
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
_In_ PFCB ParentFcb
Definition: cdprocs.h:741
#define SectorTruncate(L)
Definition: cdprocs.h:1598
#define PATH_ENTRY_FLAG_ALLOC_BUFFER
Definition: cdstruc.h:1523
static const WCHAR L[]
Definition: oid.c:1250
VOID CdUpdatePathEntryName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENTRY PathEntry, _In_ BOOLEAN IgnoreCase)
Definition: pathsup.c:781
#define VOID
Definition: acefi.h:82
UNICODE_STRING CdUnicodeDirectoryNames[]
Definition: cddata.c:52
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1049
#define _In_
Definition: no_sal2.h:204
Definition: cdstruc.h:1466
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_Success_(return !=FALSE)
Definition: pathsup.c:111
#define CdFreePool(x)
Definition: cdprocs.h:2200
Definition: cdstruc.h:1531
#define IgnoreCase
Definition: cdprocs.h:464
unsigned short USHORT
Definition: pedump.c:61
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
FILE_ID FileId
Definition: cdstruc.h:958
#define MAXUSHORT
Definition: typedefs.h:81
#define CdRawPathXar(IC, RP)
Definition: cd.h:461
BOOLEAN CdLookupNextPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENUM_CONTEXT PathContext, _Inout_ PPATH_ENTRY PathEntry)
Definition: pathsup.c:207
VOID CdLookupPathEntry(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG PathEntryOffset, _In_ ULONG Ordinal, _In_ BOOLEAN VerifyBounds, _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry)
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
unsigned int ULONG
Definition: retypes.h:1
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:741
PVCB Vcb
Definition: cdstruc.h:939
#define SECTOR_SIZE
Definition: fs.h:22
_In_ ULONG SectorSize
Definition: halfuncs.h:291
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define CdUnpinData(IC, B)
Definition: cdprocs.h:261
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
Definition: cdprocs.h:741
UCHAR DirId[MAX_FILE_ID_LENGTH]
Definition: cd.h:425
#define NT_ASSERT
Definition: rtlfuncs.h:3312