ReactOS 0.4.16-dev-306-g647d351
pathsup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 PathSup.c
8
9Abstract:
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
103VOID
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)
113CdUpdatePathEntryFromRawPathEntry (
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
131VOID
133 _In_ PIRP_CONTEXT IrpContext,
134 _In_ ULONG PathEntryOffset,
135 _In_ ULONG Ordinal,
136 _In_ BOOLEAN VerifyBounds,
138 )
139
140/*++
141
142Routine 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
147Arguments:
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
161Return 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
208 _In_ PIRP_CONTEXT IrpContext,
209 _Inout_ PPATH_ENUM_CONTEXT PathContext,
210 _Inout_ PPATH_ENTRY PathEntry
211 )
212
213/*++
214
215Routine 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
229Arguments:
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
235Return 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)
302CdFindPathEntry (
303 _In_ PIRP_CONTEXT IrpContext,
308 )
309
310/*++
311
312Routine 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
317Arguments:
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
331Return Value:
332
333 BOOLEAN - TRUE if matching entry found, FALSE otherwise.
334
335--*/
336
337{
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
483VOID
485 _In_ PIRP_CONTEXT IrpContext,
486 _In_ PFCB Fcb,
487 _In_ LONGLONG BaseOffset,
488 _Inout_ PPATH_ENUM_CONTEXT PathContext
489 )
490
491/*++
492
493Routine 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
499Arguments:
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
508Return 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,
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)
637CdUpdatePathEntryFromRawPathEntry (
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
647Routine 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
653Arguments:
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
664Return 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
780VOID
782 _In_ PIRP_CONTEXT IrpContext,
783 _Inout_ PPATH_ENTRY PathEntry,
785 )
786
787/*++
788
789Routine 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
804Arguments:
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
809Return Value:
810
811 None.
812
813--*/
814
815{
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
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
#define PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define SECTOR_SIZE
Definition: fs.h:22
#define MIN_RAW_PATH_ENTRY_LEN
Definition: cd.h:443
#define CdRawPathXar(IC, RP)
Definition: cd.h:461
#define CdRawPathLoc(IC, RP)
Definition: cd.h:467
#define CdRawPathIdLen(IC, RP)
Definition: cd.h:455
UNICODE_STRING CdUnicodeDirectoryNames[]
Definition: cddata.c:52
return Found
Definition: dirsup.c:1270
#define CdUnpinData(IC, B)
Definition: cdprocs.h:269
#define CdLockFcb(IC, F)
Definition: cdprocs.h:1044
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
#define BlockOffset(V, L)
Definition: cdprocs.h:1650
_In_ PFCB _In_ PCD_NAME _In_ BOOLEAN _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry
Definition: cdprocs.h:740
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 CopyUchar4(Dst, Src)
Definition: cdprocs.h:1701
_In_ PFCB _In_ PCD_NAME DirName
Definition: cdprocs.h:737
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
#define WordAlign(Ptr)
Definition: cdprocs.h:1554
BOOLEAN CdIsNameInExpression(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME CurrentName, _In_ PCD_NAME SearchExpression, _In_ ULONG WildcardFlags, _In_ BOOLEAN CheckVersion)
Definition: namesup.c:844
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define CopyUchar2(Dst, Src)
Definition: cdprocs.h:1693
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define TAG_PATH_ENTRY_NAME
Definition: cdprocs.h:100
#define SectorTruncate(L)
Definition: cdprocs.h:1588
#define CdFreePool(x)
Definition: cdprocs.h:2190
#define TAG_SPANNING_PATH_TABLE
Definition: cdprocs.h:103
#define CdPagedPool
Definition: cdprocs.h:1380
VOID CdLookupPathEntry(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG PathEntryOffset, _In_ ULONG Ordinal, _In_ BOOLEAN VerifyBounds, _Inout_ PCOMPOUND_PATH_ENTRY CompoundPathEntry)
#define CdUnlockFcb(IC, F)
Definition: cdprocs.h:1060
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define PATH_ENTRY_FLAG_ALLOC_BUFFER
Definition: cdstruc.h:1517
#define VCB_STATE_JOLIET
Definition: cdstruc.h:708
#define VACB_MAPPING_MASK
Definition: cdstruc.h:1452
#define CdQueryFidPathTableOffset(I)
Definition: cdstruc.h:1832
#define LAST_VACB_SECTOR_OFFSET
Definition: cdstruc.h:1453
#define IgnoreCase
Definition: cdprocs.h:461
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
Status
Definition: gdiplustypes.h:25
#define Add2Ptr(PTR, INC)
#define PCHAR
Definition: match.c:90
_Use_decl_annotations_ NTSTATUS NTAPI RtlOemToUnicodeN(_Out_ PWCHAR UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH OemString, _In_ ULONG OemSize)
Definition: nlsboot.c:282
#define _Inout_
Definition: no_sal2.h:162
#define _Success_(c)
Definition: no_sal2.h:84
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
#define L(x)
Definition: ntvdm.h:50
VOID CdUpdatePathEntryName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENTRY PathEntry, _In_ BOOLEAN IgnoreCase)
Definition: pathsup.c:781
BOOLEAN CdLookupNextPathEntry(_In_ PIRP_CONTEXT IrpContext, _Inout_ PPATH_ENUM_CONTEXT PathContext, _Inout_ PPATH_ENTRY PathEntry)
Definition: pathsup.c:207
VOID CdMapPathTableBlock(_In_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb, _In_ LONGLONG BaseOffset, _Inout_ PPATH_ENUM_CONTEXT PathContext)
Definition: pathsup.c:484
#define CdRawPathEntry(IC, PC)
Definition: pathsup.c:96
unsigned short USHORT
Definition: pedump.c:61
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 STATUS_SUCCESS
Definition: shellext.h:65
#define __analysis_assert(e)
Definition: specstrings.h:259
Definition: cdstruc.h:1525
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
FILE_ID FileId
Definition: cdstruc.h:952
PFILE_OBJECT FileObject
Definition: ntfs.h:520
Definition: cdstruc.h:1460
UCHAR DirId[MAX_FILE_ID_LENGTH]
Definition: cd.h:425
USHORT ParentNum
Definition: cd.h:424
struct _FCB * RootIndexFcb
Definition: cdstruc.h:560
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
_In_ ULONG SectorSize
Definition: halfuncs.h:291
#define NT_ASSERT
Definition: rtlfuncs.h:3327
__wchar_t WCHAR
Definition: xmlstorage.h:180