ReactOS 0.4.15-dev-8119-g4fb2fdb
namesup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1991-2000 Microsoft Corporation
4
5Module Name:
6
7 NameSup.c
8
9Abstract:
10
11 This module implements the Cdfs Name support routines
12
13
14--*/
15
16#include "cdprocs.h"
17
18//
19// The Bug check file id for this module
20//
21
22#define BugCheckFileId (CDFS_BUG_CHECK_NAMESUP)
23
24#ifdef ALLOC_PRAGMA
25#pragma alloc_text(PAGE, CdConvertBigToLittleEndian)
26#pragma alloc_text(PAGE, CdConvertNameToCdName)
27#pragma alloc_text(PAGE, CdDissectName)
28#pragma alloc_text(PAGE, CdGenerate8dot3Name)
29#pragma alloc_text(PAGE, CdFullCompareNames)
30#pragma alloc_text(PAGE, CdIsLegalName)
31#pragma alloc_text(PAGE, CdIs8dot3Name)
32#pragma alloc_text(PAGE, CdIsNameInExpression)
33#pragma alloc_text(PAGE, CdShortNameDirentOffset)
34#pragma alloc_text(PAGE, CdUpcaseName)
35#endif
36
37
40VOID
41CdConvertNameToCdName (
42 _In_ PIRP_CONTEXT IrpContext,
44 )
45
46/*++
47
48Routine Description:
49
50 This routine is called to convert a string of bytes into a CdName.
51
52 The full name is already in the CdName structure in the FileName field.
53 We split this into the filename and version strings.
54
55Arguments:
56
57 CdName - Pointer to CdName structure to update.
58
59Return Value:
60
61 None.
62
63--*/
64
65{
66 ULONG NameLength = 0;
68
70
72
73 //
74 // Look for a separator character.
75 //
76
77 while ((NameLength < CdName->FileName.Length) &&
78 (*CurrentCharacter != L';')) {
79
81 NameLength += 2;
82 }
83
84 //
85 // If there is at least one more character after a possible separator then it
86 // and all following characters are part of the version string.
87 //
88
90 if (NameLength + sizeof( WCHAR ) < CdName->FileName.Length) {
91
93 CdName->VersionString.Length = (USHORT) (CdName->FileName.Length - NameLength - sizeof( WCHAR ));
95 NameLength + sizeof( WCHAR ),
96 PWCHAR );
97 }
98
99 //
100 // Now update the filename portion of the name.
101 //
102
103 CdName->FileName.Length = (USHORT) NameLength;
104
105 return;
106}
107
108
109VOID
111 _In_ PIRP_CONTEXT IrpContext,
115 )
116
117/*++
118
119Routine Description:
120
121 This routine is called to convert a unicode string in big endian to
122 little endian. We start by copying all of the source bytes except
123 the first. This will put the low order bytes in the correct position.
124 We then copy each high order byte in its correct position.
125
126Arguments:
127
128 BigEndian - Pointer to the string of big endian characters.
129
130 ByteCount - Number of unicode characters in this string.
131
132 LittleEndian - Pointer to array to store the little endian characters.
133
134Return Value:
135
136 None.
137
138--*/
139
140{
141 ULONG RemainingByteCount = ByteCount;
142
143 PCHAR Source = BigEndian;
144 PCHAR Destination = LittleEndian;
145
146 PAGED_CODE();
147
148 //
149 // If the byte count isn't an even number then the disk is corrupt.
150 //
151
152 if (FlagOn( ByteCount, 1 )) {
153
155 }
156
157 //
158 // Start by copy the low-order bytes into the correct position. Do
159 // this by skipping the first byte in the BigEndian string.
160 //
161
163 Source + 1,
164 RemainingByteCount - 1 );
165
166 //
167 // Now move the high-order bytes into position.
168 //
169
170 Destination += 1;
171
172 while (RemainingByteCount != 0) {
173
174#ifdef _MSC_VER
175#pragma prefast(push)
176#pragma prefast(suppress:26014, "RemainingByteCount is even")
177#endif
179#ifdef _MSC_VER
180#pragma prefast(pop)
181#endif
182
183 Source += 2;
184 Destination += 2;
185
186 RemainingByteCount -= 2;
187 }
188
189 return;
190}
191
192
193VOID
195 _In_ PIRP_CONTEXT IrpContext,
197 _Inout_ PCD_NAME UpcaseName
198 )
199
200/*++
201
202Routine Description:
203
204 This routine is called to upcase a CdName structure. We will do both
205 the filename and version strings.
206
207Arguments:
208
209 Name - This is the mixed case version of the name.
210
211 UpcaseName - This is the destination for the upcase operation.
212
213Return Value:
214
215 None. This routine will raise all errors.
216
217--*/
218
219{
221
222 PAGED_CODE();
223
224 UNREFERENCED_PARAMETER( IrpContext );
225
226 //
227 // If the name structures are different then initialize the different components.
228 //
229
230 if (Name != UpcaseName) {
231
232 //
233 // Initialize the version string portion of the name.
234 //
235
236 UpcaseName->VersionString.Length = 0;
237
238 if (Name->VersionString.Length != 0) {
239
240 UpcaseName->VersionString.MaximumLength =
241 UpcaseName->VersionString.Length = Name->VersionString.Length;
242
243 //
244 // Initially set the buffer to point to where we need to insert
245 // the separator.
246 //
247
248 UpcaseName->VersionString.Buffer = Add2Ptr( UpcaseName->FileName.Buffer,
249 Name->FileName.Length,
250 PWCHAR );
251
252 //
253 // We are currently pointing to the location to store the separator.
254 // Store the ';' and then move to the next character to
255 // copy the data.
256 //
257
258#ifdef _MSC_VER
259#pragma prefast( suppress:26015, "CD_NAME structures have two UNICODE_STRING structures pointing to the same allocation. there is no way to tell prefast this is the case and that the allocation is always big enough.");
260#endif
261 *(UpcaseName->VersionString.Buffer) = L';';
262
263 UpcaseName->VersionString.Buffer += 1;
264 }
265 }
266
267 //
268 // Upcase the string using the correct upcase routine.
269 //
270
271 Status = RtlUpcaseUnicodeString( &UpcaseName->FileName,
272 &Name->FileName,
273 FALSE );
274
275 //
276 // This should never fail.
277 //
278
281
282 if (Name->VersionString.Length != 0) {
283
284 Status = RtlUpcaseUnicodeString( &UpcaseName->VersionString,
285 &Name->VersionString,
286 FALSE );
287
288 //
289 // This should never fail.
290 //
291
294 }
295
296 return;
297}
298
299
300VOID
302 _In_ PIRP_CONTEXT IrpContext,
304 _Out_ PUNICODE_STRING FinalName
305 )
306
307/*++
308
309Routine Description:
310
311 This routine is called to strip off leading components of the name strings. We search
312 for either the end of the string or separating characters. The input remaining
313 name strings should have neither a trailing or leading backslash.
314
315Arguments:
316
317 RemainingName - Remaining name.
318
319 FinalName - Location to store next component of name.
320
321Return Value:
322
323 None.
324
325--*/
326
327{
328 ULONG NameLength;
329 PWCHAR NextWchar;
330
331 PAGED_CODE();
332
333 UNREFERENCED_PARAMETER( IrpContext );
334
335 //
336 // Find the offset of the next component separators.
337 //
338
339 for (NameLength = 0, NextWchar = RemainingName->Buffer;
340 (NameLength < RemainingName->Length) && (*NextWchar != L'\\');
341 NameLength += sizeof( WCHAR) , NextWchar += 1);
342
343 //
344 // Adjust all the strings by this amount.
345 //
346
347 FinalName->Buffer = RemainingName->Buffer;
348
349 FinalName->MaximumLength = FinalName->Length = (USHORT) NameLength;
350
351 //
352 // If this is the last component then set the RemainingName lengths to zero.
353 //
354
355 if (NameLength == RemainingName->Length) {
356
357 RemainingName->Length = 0;
358
359 //
360 // Otherwise we adjust the string by this amount plus the separating character.
361 //
362
363 } else {
364
365 RemainingName->MaximumLength -= (USHORT) (NameLength + sizeof( WCHAR ));
366 RemainingName->Length -= (USHORT) (NameLength + sizeof( WCHAR ));
367 RemainingName->Buffer = Add2Ptr( RemainingName->Buffer,
368 NameLength + sizeof( WCHAR ),
369 PWCHAR );
370 }
371
372 return;
373}
374
375
378 _In_ PIRP_CONTEXT IrpContext,
380 )
381
382/*++
383
384Routine Description:
385
386 This routine checks if the name is a legal ISO 9660 name.
387
388Arguments:
389
390 FileName - String of bytes containing the name.
391
392Return Value:
393
394 BOOLEAN - TRUE if this name is a legal, FALSE otherwise.
395
396--*/
397
398{
399 PWCHAR Wchar;
400
401 PAGED_CODE();
402
403 UNREFERENCED_PARAMETER( IrpContext );
404
405 //
406 // Check if name corresponds to a legal file name.
407 //
408
409 for (Wchar = FileName->Buffer;
410 Wchar < Add2Ptr( FileName->Buffer, FileName->Length, PWCHAR );
411 Wchar++) {
412
413 if ((*Wchar < 0xff) &&
415 (*Wchar != L'"') &&
416 (*Wchar != L'<') &&
417 (*Wchar != L'>') &&
418 (*Wchar != L'|')) {
419
420 return FALSE;
421 }
422 }
423
424 return TRUE;
425}
426
427
430 _In_ PIRP_CONTEXT IrpContext,
432 )
433
434/*++
435
436Routine Description:
437
438 This routine checks if the name follows the 8.3 name conventions. We check for
439 the name length and whether the characters are valid.
440
441Arguments:
442
443 FileName - String of bytes containing the name.
444
445Return Value:
446
447 BOOLEAN - TRUE if this name is a legal 8.3 name, FALSE otherwise.
448
449--*/
450
451{
452 CHAR DbcsNameBuffer[ BYTE_COUNT_8_DOT_3 ];
453 STRING DbcsName = {0};
454
455 PWCHAR NextWchar;
456 ULONG Count;
457
458 ULONG DotCount = 0;
459 BOOLEAN LastCharDot = FALSE;
460
461 PAGED_CODE();
462
463 UNREFERENCED_PARAMETER( IrpContext );
464
465 //
466 // The length must be less than 24 bytes.
467 //
468
469 NT_ASSERT( FileName.Length != 0 );
470 if (FileName.Length > BYTE_COUNT_8_DOT_3) {
471
472 return FALSE;
473 }
474
475 //
476 // Walk though and check for a space character.
477 //
478
479 NextWchar = FileName.Buffer;
480 Count = 0;
481
482 do {
483
484 //
485 // No spaces allowed.
486 //
487
488 if (*NextWchar == L' ') { return FALSE; }
489
490 if (*NextWchar == L'.') {
491
492 //
493 // Not an 8.3 name if more than 1 dot or more than 8 characters
494 // remaining. (It is legal for the dot to be in the ninth
495 // position)
496 //
497
498 if ((DotCount > 0) ||
499 (Count > 8 * sizeof( WCHAR ))) {
500
501 return FALSE;
502 }
503
504 DotCount += 1;
505 LastCharDot = TRUE;
506
507 } else {
508
509 LastCharDot = FALSE;
510 }
511
512 Count += 2;
513 NextWchar += 1;
514
515 } while (Count < FileName.Length);
516
517 //
518 // Go ahead and truncate the dot if at the end.
519 //
520
521 if (LastCharDot) {
522
523 FileName.Length -= sizeof( WCHAR );
524 }
525
526 //
527 // Create an Oem name to use to check for a valid short name.
528 //
529
530 DbcsName.MaximumLength = BYTE_COUNT_8_DOT_3;
531 DbcsName.Buffer = DbcsNameBuffer;
532
533 if (!NT_SUCCESS( RtlUnicodeStringToCountedOemString( &DbcsName,
534 &FileName,
535 FALSE ))) {
536
537 return FALSE;
538 }
539
540 //
541 // We have now initialized the Oem string. Call the FsRtl package to check for a
542 // valid FAT name.
543 //
544
545 return FsRtlIsFatDbcsLegal( DbcsName, FALSE, FALSE, FALSE );
546}
547
548
549VOID
551 _In_ PIRP_CONTEXT IrpContext,
554 _Out_writes_bytes_to_(BYTE_COUNT_8_DOT_3, *ShortByteCount) PWCHAR ShortFileName,
555 _Out_ PUSHORT ShortByteCount
556 )
557
558/*++
559
560Routine Description:
561
562 This routine is called to generate a short name from the given long name. We will
563 generate a short name from the given long name.
564
565 We go through the following steps to make this conversion.
566
567 1 - Generate the generic short name. This will also be in unicode format.
568
569 2 - Build the string representation of the dirent offset.
570
571 3 - Build the biased short name string by combining the generic short name with
572 the dirent offset string.
573
574 4 - Copy the final unicode string back to our caller's buffer.
575
576Arguments:
577
578 FileName - String of bytes containing the name.
579
580 DirentOffset - Offset in the directory for this filename. We incorporate the offset into
581 the short name by dividing this by 32 and prepending a tilde character to the
582 digit character. We then append this to the base of the generated short name.
583
584 ShortFileName - Pointer to the buffer to store the short name into.
585
586 ShortByteCount - Address to store the number of bytes in the short name.
587
588Return Value:
589
590 None.
591
592--*/
593
594{
596
598 UNICODE_STRING BiasedShortName;
599 WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / sizeof( WCHAR ) ] = {0};
600 WCHAR BiasedShortNameBuffer[ BYTE_COUNT_8_DOT_3 / sizeof( WCHAR ) ];
601
602 GENERATE_NAME_CONTEXT NameContext;
603
604 ULONG BiasedDirentOffset;
605
606 ULONG MaximumBaseBytes;
607 ULONG BaseNameOffset;
608
609 PWCHAR NextWchar;
610 WCHAR ThisWchar;
612
613 BOOLEAN FoundTilde = FALSE;
614
615 OEM_STRING OemName = {0};
616 USHORT OemNameOffset = 0;
617 BOOLEAN OverflowBuffer = FALSE;
618
619 PAGED_CODE();
620
621 //
622 // Initialize the short string to use the input buffer.
623 //
624
625 ShortName.Buffer = ShortNameBuffer;
626 ShortName.MaximumLength = BYTE_COUNT_8_DOT_3;
627
628 //
629 // Initialize the name context.
630 //
631
632 RtlZeroMemory( &NameContext, sizeof( GENERATE_NAME_CONTEXT ));
633
634 //
635 // We now have the unicode name for the input string. Go ahead and generate
636 // the short name.
637 //
638
639 RtlGenerate8dot3Name( FileName, TRUE, &NameContext, &ShortName );
640
641 //
642 // We now have the generic short name. We want incorporate the dirent offset
643 // into the name in order to reduce the chance of name conflicts. We will use
644 // a tilde character followed by a character representation of the dirent offset.
645 // This will be the hexadecimal representation of the dirent offset in the directory.
646 // It is actuall this offset divided by 32 since we don't need the full
647 // granularity.
648 //
649
650 BiasedDirentOffset = DirentOffset >> SHORT_NAME_SHIFT;
651
652 //
653 // Point to a local buffer to store the offset string. We start
654 // at the end of the buffer and work backwards.
655 //
656
657 NextWchar = Add2Ptr( BiasedShortNameBuffer,
659 PWCHAR );
660
661 BiasedShortName.MaximumLength = BYTE_COUNT_8_DOT_3;
662
663 //
664 // Generate an OEM version of the string so that we can check for double
665 // byte characters.
666 //
667
669
670 //
671 // If this failed, bail out. Don't expect any problems other than no mem.
672 //
673
674 if (!NT_SUCCESS( Status)) {
675
677 CdRaiseStatus( IrpContext, Status);
678 }
679
680 Length = 0;
681
682 //
683 // Now add the characters for the dirent offset. We need to start
684 // from the least significant digit and work backwards.
685 //
686
687 do {
688
689 NextWchar -= 1;
690
691 ThisWchar = (WCHAR) (BiasedDirentOffset & 0x0000000f);
692
693 //
694 // Store in the next character. Bias against either '0' or 'A'
695 //
696
697 if (ThisWchar <= 9) {
698
699 *NextWchar = ThisWchar + L'0';
700
701 } else {
702
703 *NextWchar = ThisWchar + L'A' - 0xA;
704 }
705
706 Length += sizeof( WCHAR );
707
708 //
709 // Shift out the low 4 bits of the offset.
710 //
711
712 BiasedDirentOffset >>= 4;
713
714 } while (BiasedDirentOffset != 0);
715
716 //
717 // Now store in the tilde character.
718 //
719
720 NextWchar -= 1;
721 *NextWchar = L'~';
722 Length += sizeof( WCHAR );
723
724 //
725 // Set the length of this string.
726 //
727
728 BiasedShortName.Length = Length;
729 BiasedShortName.Buffer = NextWchar;
730
731 //
732 // Figure out the maximum number of characters we can copy of the base
733 // name. We subract the number of characters in the dirent string from 8.
734 // We will copy this many characters or stop when we reach a '.' character
735 // or a '~' character in the name.
736 //
737
738 MaximumBaseBytes = 16 - Length;
739
740 BaseNameOffset = 0;
741
742 //
743 // Keep copying from the base name until we hit a '.', '~' or the end of
744 // the short name.
745 //
746
747 NextWchar = ShortFileName;
748 Length = 0;
749
750 while ((BaseNameOffset < ShortName.Length) &&
751 (ShortName.Buffer[BaseNameOffset / 2] != L'.')) {
752
753 //
754 // Remember if we found a tilde character in the short name,
755 // so we don't copy it or anything following it.
756 //
757
758 if (ShortName.Buffer[BaseNameOffset / 2] == L'~') {
759
760 FoundTilde = TRUE;
761 }
762
763 //
764 // We need to consider the DBCS code page, because Unicode characters
765 // may use 2 bytes as DBCS characters.
766 //
767
768#ifdef _MSC_VER
769#pragma prefast(push)
770#pragma prefast(suppress:26014, "OemNameOffset <= BaseNameOffset throughout this loop; OemName buffer previously allocated based on ShortName's length.")
771#endif
772 if (FsRtlIsLeadDbcsCharacter(OemName.Buffer[OemNameOffset])) {
773#ifdef _MSC_VER
774#pragma prefast(pop)
775#endif
776
777 OemNameOffset += 2;
778
779 if ((OemNameOffset + (BiasedShortName.Length / sizeof(WCHAR))) > 8) {
780
781 OverflowBuffer = TRUE;
782 }
783 }
784 else {
785
786 OemNameOffset++;
787 }
788
789 //
790 // Only copy the bytes if we still have space for the dirent string.
791 //
792
793 if (!FoundTilde && !OverflowBuffer && (BaseNameOffset < MaximumBaseBytes)) {
794
795 *NextWchar = ShortName.Buffer[BaseNameOffset / 2];
796 Length += sizeof( WCHAR );
797 NextWchar += 1;
798 }
799
800 BaseNameOffset += 2;
801 }
802
804
805 //
806 // Now copy the dirent string into the biased name buffer.
807 //
808
809#ifdef _MSC_VER
810#pragma prefast(push)
811#endif
812 RtlCopyMemory( NextWchar,
813 BiasedShortName.Buffer,
814 BiasedShortName.Length );
815#ifdef _MSC_VER
816#pragma prefast(pop)
817#endif
818
819 Length += BiasedShortName.Length;
820 NextWchar += (BiasedShortName.Length / sizeof( WCHAR ));
821
822 //
823 // Now copy any remaining bytes over to the biased short name.
824 //
825
826 if (BaseNameOffset != ShortName.Length) {
827
828 RtlCopyMemory( NextWchar,
829 &ShortName.Buffer[BaseNameOffset / 2],
830 ShortName.Length - BaseNameOffset );
831
832 Length += (ShortName.Length - (USHORT) BaseNameOffset);
833 }
834
835 //
836 // The final short name is stored in the user's buffer.
837 //
838
839 *ShortByteCount = Length;
840}
841
842
845 _In_ PIRP_CONTEXT IrpContext,
846 _In_ PCD_NAME CurrentName,
847 _In_ PCD_NAME SearchExpression,
848 _In_ ULONG WildcardFlags,
849 _In_ BOOLEAN CheckVersion
850 )
851
852/*++
853
854Routine Description:
855
856 This routine will compare two CdName strings. We assume that if this
857 is to be a case-insensitive search then they are already upcased.
858
859 We compare the filename portions of the name and if they match we
860 compare the version strings if requested.
861
862Arguments:
863
864 CurrentName - Filename from the disk.
865
866 SearchExpression - Filename expression to use for match.
867
868 WildcardFlags - Flags field which indicates which parts of the
869 search expression might have wildcards. These flags are the
870 same as in the Ccb flags field.
871
872 CheckVersion - Indicates whether we should check both the name and the
873 version strings or just the name.
874
875Return Value:
876
877 BOOLEAN - TRUE if the expressions match, FALSE otherwise.
878
879--*/
880
881{
882 BOOLEAN Match = TRUE;
883 PAGED_CODE();
884
885 UNREFERENCED_PARAMETER( IrpContext );
886
887 //
888 // If there are wildcards in the expression then we call the
889 // appropriate FsRtlRoutine.
890 //
891
892 if (FlagOn( WildcardFlags, CCB_FLAG_ENUM_NAME_EXP_HAS_WILD )) {
893
894 Match = FsRtlIsNameInExpression( &SearchExpression->FileName,
895 &CurrentName->FileName,
896 FALSE,
897 NULL );
898
899 //
900 // Otherwise do a direct memory comparison for the name string.
901 //
902
903 } else {
904
905 if ((CurrentName->FileName.Length != SearchExpression->FileName.Length) ||
906 (!RtlEqualMemory( CurrentName->FileName.Buffer,
907 SearchExpression->FileName.Buffer,
908 CurrentName->FileName.Length ))) {
909
910 Match = FALSE;
911 }
912 }
913
914 //
915 // Check the version numbers if requested by the user and we have a
916 // match on the name and the version number is present.
917 //
918
919 if (Match && CheckVersion && SearchExpression->VersionString.Length &&
920 !FlagOn( WildcardFlags, CCB_FLAG_ENUM_VERSION_MATCH_ALL )) {
921
922 //
923 // If there are wildcards in the expression then call the
924 // appropriate search expression.
925 //
926
927 if (FlagOn( WildcardFlags, CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD )) {
928
929 Match = FsRtlIsNameInExpression( &SearchExpression->VersionString,
930 &CurrentName->VersionString,
931 FALSE,
932 NULL );
933
934 //
935 // Otherwise do a direct memory comparison for the name string.
936 //
937
938 } else {
939
940 if ((CurrentName->VersionString.Length != SearchExpression->VersionString.Length) ||
941 (!RtlEqualMemory( CurrentName->VersionString.Buffer,
942 SearchExpression->VersionString.Buffer,
943 CurrentName->VersionString.Length ))) {
944
945 Match = FALSE;
946 }
947 }
948 }
949
950 return Match;
951}
952
953
954ULONG
956 _In_ PIRP_CONTEXT IrpContext,
958 )
959
960/*++
961
962Routine Description:
963
964 This routine is called to examine a name to see if the dirent offset string is contained.
965 This consists of a tilde character followed by the offset represented as a hexadecimal
966 characters. We don't do any other checks to see if this is a short name. We
967 catch that later outside this routine.
968
969Arguments:
970
971 Name - This is the CdName to examine.
972
973Return Value:
974
975 ULONG - MAXULONG if there is no valid dirent offset string embedded, otherwise the
976 convert the value to numeric form.
977
978--*/
979
980{
981 ULONG ResultOffset = MAXULONG;
982 ULONG RemainingByteCount = Name->Length;
983
984 BOOLEAN FoundTilde = FALSE;
985
986 PWCHAR NextWchar;
987
988 PAGED_CODE();
989
990 UNREFERENCED_PARAMETER( IrpContext );
991
992 //
993 // Walk through the name until we either reach the end of the name
994 // or find a tilde character.
995 //
996
997 for (NextWchar = Name->Buffer;
998 RemainingByteCount != 0;
999 NextWchar += 1, RemainingByteCount -= sizeof( WCHAR )) {
1000
1001 //
1002 // Check if this is a dot. Stop constructing any string if
1003 // we found a dot.
1004 //
1005
1006 if (*NextWchar == L'.') {
1007
1008 break;
1009 }
1010
1011 //
1012 // If we already found a tilde then check this character as a
1013 // valid character. It must be a digit or A to F.
1014 //
1015
1016 if (FoundTilde) {
1017
1018 if ((*NextWchar < L'0') ||
1019 (*NextWchar > L'F') ||
1020 ((*NextWchar > L'9') && (*NextWchar < 'A'))) {
1021
1022 ResultOffset = MAXULONG;
1023 break;
1024 }
1025
1026 //
1027 // Shift the result by 4 bits and add in this new character.
1028 //
1029
1030 ResultOffset <<= 4;
1031
1032 if (*NextWchar < L'A') {
1033
1034 ResultOffset += *NextWchar - L'0';
1035
1036 } else {
1037
1038 ResultOffset += (*NextWchar - L'A') + 10;
1039 }
1040
1041 continue;
1042 }
1043
1044 //
1045 // If this is a tilde then start building the dirent string.
1046 //
1047
1048 if (*NextWchar == L'~') {
1049
1050 FoundTilde = TRUE;
1051 ResultOffset = 0;
1052 }
1053 }
1054
1055 return ResultOffset;
1056}
1057
1058
1059//
1060// Local support routine
1061//
1062
1065 _In_ PIRP_CONTEXT IrpContext,
1066 _In_ PUNICODE_STRING NameA,
1067 _In_ PUNICODE_STRING NameB
1068 )
1069
1070/*++
1071
1072Routine Description:
1073
1074 This function compares two names as fast as possible. Note that since
1075 this comparison is case sensitive we can do a direct memory comparison.
1076
1077Arguments:
1078
1079 NameA & NameB - The names to compare.
1080
1081Return Value:
1082
1083 COMPARISON - returns
1084
1085 LessThan if NameA < NameB lexicalgraphically,
1086 GreaterThan if NameA > NameB lexicalgraphically,
1087 EqualTo if NameA is equal to NameB
1088
1089--*/
1090
1091{
1092 SIZE_T i;
1093 ULONG MinLength = NameA->Length;
1095
1096 PAGED_CODE();
1097
1098 UNREFERENCED_PARAMETER( IrpContext );
1099
1100 //
1101 // Figure out the minimum of the two lengths
1102 //
1103
1104 if (NameA->Length > NameB->Length) {
1105
1106 MinLength = NameB->Length;
1108
1109 } else if (NameA->Length == NameB->Length) {
1110
1111 Result = EqualTo;
1112 }
1113
1114 //
1115 // Loop through looking at all of the characters in both strings
1116 // testing for equalilty, less than, and greater than
1117 //
1118
1119 i = RtlCompareMemory( NameA->Buffer, NameB->Buffer, MinLength );
1120
1121 if (i < MinLength) {
1122
1123 //
1124 // We know the offset of the first character which is different.
1125 //
1126
1127 return ((NameA->Buffer[ i / 2 ] < NameB->Buffer[ i / 2 ]) ?
1128 LessThan :
1129 GreaterThan);
1130 }
1131
1132 //
1133 // The names match up to the length of the shorter string.
1134 // The shorter string lexically appears first.
1135 //
1136
1137 return Result;
1138}
1139
1140
1141
unsigned char BOOLEAN
NTSYSAPI VOID NTAPI RtlGenerate8dot3Name(_In_ PCUNICODE_STRING Name, _In_ BOOLEAN AllowExtendedCharacters, _Inout_ PGENERATE_NAME_CONTEXT Context, _Inout_ PUNICODE_STRING Name8dot3)
LONG NTSTATUS
Definition: precomp.h:26
#define SHORT_NAME_SHIFT
Definition: cd.h:364
#define BYTE_COUNT_8_DOT_3
Definition: cd.h:362
Dirent DirentOffset
Definition: dirsup.c:444
FSRTL_COMPARISON_RESULT CdFullCompareNames(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING NameA, _In_ PUNICODE_STRING NameB)
Definition: namesup.c:1064
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
CdName VersionString Length
Definition: namesup.c:89
VOID CdDissectName(_In_ PIRP_CONTEXT IrpContext, _Inout_ PUNICODE_STRING RemainingName, _Out_ PUNICODE_STRING FinalName)
Definition: namesup.c:301
VOID CdUpcaseName(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME Name, _Inout_ PCD_NAME UpcaseName)
Definition: namesup.c:194
PAGED_CODE()
_Inout_ PCD_NAME CdName
Definition: namesup.c:65
BOOLEAN CdIsNameInExpression(_In_ PIRP_CONTEXT IrpContext, _In_ PCD_NAME CurrentName, _In_ PCD_NAME SearchExpression, _In_ ULONG WildcardFlags, _In_ BOOLEAN CheckVersion)
Definition: namesup.c:844
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
BOOLEAN CdIsLegalName(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING FileName)
Definition: namesup.c:377
PWCHAR CurrentCharacter
Definition: namesup.c:67
ULONG CdShortNameDirentOffset(_In_ PIRP_CONTEXT IrpContext, _In_ PUNICODE_STRING Name)
Definition: namesup.c:955
BOOLEAN CdIs8dot3Name(_In_ PIRP_CONTEXT IrpContext, _In_ UNICODE_STRING FileName)
Definition: namesup.c:429
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define CCB_FLAG_ENUM_NAME_EXP_HAS_WILD
Definition: cdstruc.h:1114
#define CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD
Definition: cdstruc.h:1115
#define CCB_FLAG_ENUM_VERSION_MATCH_ALL
Definition: cdstruc.h:1117
BOOLEAN NTAPI FsRtlIsFatDbcsLegal(IN ANSI_STRING DbcsName, IN BOOLEAN WildCardsPermissible, IN BOOLEAN PathNamePermissible, IN BOOLEAN LeadingBackslashPermissible)
Definition: dbcsname.c:466
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define FsRtlIsLeadDbcsCharacter(DBCS_CHAR)
Definition: init.c:428
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1306
IN PDCB IN POEM_STRING OemName
Definition: fatprocs.h:1304
std::wstring STRING
Definition: fontsub.cpp:33
#define FsRtlIsAnsiCharacterLegalHpfs(C, WILD)
Definition: fsrtlfuncs.h:1614
@ LessThan
Definition: fsrtltypes.h:77
@ GreaterThan
Definition: fsrtltypes.h:79
@ EqualTo
Definition: fsrtltypes.h:78
enum _FSRTL_COMPARISON_RESULT FSRTL_COMPARISON_RESULT
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID NTAPI RtlFreeOemString(POEM_STRING OemString)
#define Add2Ptr(PTR, INC)
#define RtlEqualMemory(a, b, c)
Definition: kdvm.h:18
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define _Inout_
Definition: ms_sal.h:378
#define _Out_writes_bytes_(size)
Definition: ms_sal.h:350
#define _Out_writes_bytes_to_(size, count)
Definition: ms_sal.h:360
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _Post_satisfies_(cond)
Definition: ms_sal.h:588
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
int Count
Definition: noreturn.cpp:7
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
BOOLEAN NTAPI FsRtlIsNameInExpression(IN PUNICODE_STRING Expression, IN PUNICODE_STRING Name, IN BOOLEAN IgnoreCase, IN PWCHAR UpcaseTable OPTIONAL)
Definition: name.c:514
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_SUCCESS
Definition: shellext.h:65
#define __analysis_assert(e)
Definition: specstrings.h:259
UNICODE_STRING VersionString
Definition: cdstruc.h:250
UNICODE_STRING FileName
Definition: cdstruc.h:244
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define MAXULONG
Definition: typedefs.h:251
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
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
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
STRING OEM_STRING
Definition: umtypes.h:203
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define NT_ASSERT
Definition: rtlfuncs.h:3310
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175