test: gen8dot3.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# gen8dot3.c File Reference

`#include "ntrtlp.h"`
`#include <stdio.h>`

Go to the source code of this file.

## Defines

#define | IsDbcsCharacter(WC)

## Functions

WCHAR | GetNextWchar (IN PUNICODE_STRING Name, IN PULONG CurrentIndex, IN BOOLEAN SkipDots, IN BOOLEAN AllowExtendedCharacters)
USHORT | RtlComputeLfnChecksum (PUNICODE_STRING Name)
VOID | RtlGenerate8dot3Name (IN PUNICODE_STRING Name, IN BOOLEAN AllowExtendedCharacters, IN OUT PGENERATE_NAME_CONTEXT Context, OUT PUNICODE_STRING Name8dot3)
BOOLEAN | RtlIsValidOemCharacter (IN PWCHAR Char)
BOOLEAN | RtlIsNameLegalDOS8Dot3 (IN PUNICODE_STRING Name, IN OUT POEM_STRING OemName OPTIONAL, OUT PBOOLEAN NameContainsSpaces OPTIONAL)

## Variables

PUSHORT | NlsUnicodeToMbOemData
PUSHORT | NlsOemToUnicodeData
PCH | NlsUnicodeToOemData
PUSHORT | NlsMbOemCodePageTables
BOOLEAN | NlsMbOemCodePageTag
PUSHORT | NlsOemLeadByteInfo
USHORT | OemDefaultChar
const ULONG | RtlFatIllegalTable []

## Define Documentation

#define IsDbcsCharacter | ( | WC |  | ) |

Value:

    (             \
        ((WC) > 127) &&                       \
        (HIBYTE(NlsUnicodeToMbOemData[(WC)])) \
    )

Definition at line 66 of file gen8dot3.c.

Referenced by RtlGenerate8dot3Name().

## Function Documentation

WCHAR GetNextWchar | ( | IN PUNICODE_STRING | Name,
|  | IN PULONG | CurrentIndex,
|  | IN BOOLEAN | SkipDots,
|  | IN BOOLEAN | AllowExtendedCharacters
| ) |

Definition at line 555 of file gen8dot3.c.

References L, Name, RtlFatIllegalTable, and RtlIsValidOemCharacter().

Referenced by RtlGenerate8dot3Name().

    00564                    :
    00565
    00566     This routine scans the input name starting at the current index and
    00567     returns the next valid character for the long name to 8.3 generation
    00568     algorithm.  It also updates the current index to point to the
    00569     next character to examine.
    00570
    00571     The user can specify if dots are skipped over or passed back.  The
    00572     filtering done by the procedure is:
    00573
    00574     1. Skip characters less then blanks, and larger than 127 if
    00575        AllowExtendedCharacters is FALSE
    00576     2. Optionally skip over dots
    00577     3. translate the special 7 characters : + , ; = [ ] into underscores
    00578
    00579 Arguments:
    00580
    00581     Name - Supplies the name being examined
    00582
    00583     CurrentIndex - Supplies the index to start our examination and also
    00584         receives the index of one beyond the character we return.
    00585
    00586     SkipDots - Indicates whether this routine will also skip over periods
    00587
    00588     AllowExtendedCharacters - Tell whether charaacters >= 127 are valid.
    00589
    00590 Return Value:
    00591
    00592     WCHAR - returns the next wchar in the name string
    00593
    00594 --*/
    00595
    00596 {
    00597     WCHAR wc;
    00598
    00599     //
    00600     //  Until we find out otherwise the character we are going to return
    00601     //  is 0
    00602     //
    00603
    00604     wc = 0;
    00605
    00606     //
    00607     //  Now loop through updating the current index until we either have a character to
    00608     //  return or until we exhaust the name buffer
    00609     //
    00610
    00611     while (*CurrentIndex < (ULONG)(Name->Length/2)) {
    00612
    00613         //
    00614         //  Get the next character in the buffer
    00615         //
    00616
    00617         wc = Name->Buffer[*CurrentIndex];
    00618         *CurrentIndex += 1;
    00619
    00620         //
    00621         //  If the character is to be skipped over then reset wc to 0
    00622         //
    00623
    00624         if ((wc <= L' ') ||
    00625             ((wc >= 127) && (!AllowExtendedCharacters || !RtlIsValidOemCharacter(&wc))) ||
    00626             ((wc == L'.') && SkipDots)) {
    00627
    00628             wc = 0;
    00629
    00630         } else {
    00631
    00632             //
    00633             //  We have a character to return, but first translate the character is necessary
    00634             //
    00635
    00636             if ((wc < 0x80) && (RtlFatIllegalTable[wc/32] & (1 << (wc%32)))) {
    00637
    00638                 wc = L'_';
    00639             }
    00640
    00641             //
    00642             //  Do an a-z upcase.
    00643             //
    00644
    00645             if ((wc >= L'a') && (wc <= L'z')) {
    00646
    00647                 wc -= L'a' - L'A';
    00648             }
    00649
    00650             //
    00651             //  And break out of the loop to return to our caller
    00652             //
    00653
    00654             break;
    00655         }
    00656     }
    00657
    00658     //DebugTrace( 0, Dbg, "GetNextWchar -> %08x\n", wc);
    00659
    00660     return wc;
    00661 }

USHORT RtlComputeLfnChecksum | ( | PUNICODE_STRING | Name | ) |

Definition at line 669 of file gen8dot3.c.

References Name, RTL_PAGED_CODE, and USHORT.

Referenced by RtlGenerate8dot3Name().

    00675                    :
    00676
    00677     This routine computes the Chicago long file name checksum.
    00678
    00679 Arguments:
    00680
    00681     Name - Supplies the name to compute the checksum on.  Note that one
    00682         character names don't have interesting checksums.
    00683
    00684 Return Value:
    00685
    00686     The checksum.
    00687
    00688 --*/
    00689
    00690 {
    00691     ULONG i;
    00692     USHORT Checksum;
    00693
    00694     RTL_PAGED_CODE();
    00695
    00696     if (Name->Length == sizeof(WCHAR)) {
    00697
    00698         return Name->Buffer[0];
    00699     }
    00700
    00701     Checksum = ((Name->Buffer[0] << 8) + Name->Buffer[1]) & 0xffff;
    00702
    00703     //
    00704     //  This checksum is kinda strange because we want to still have
    00705     //  a good range even if all the characters are < 0x00ff.
    00706     //
    00707
    00708     for (i=2; i < Name->Length / sizeof(WCHAR); i+=2) {
    00709
    00710         Checksum = (Checksum & 1 ? 0x8000 : 0) +
    00711                    (Checksum >> 1) +
    00712                    (Name->Buffer[i] << 8);
    00713
    00714         //
    00715         //  Be carefull to not walk off the end of the string.
    00716         //
    00717
    00718         if (i+1 < Name->Length / sizeof(WCHAR)) {
    00719
    00720             Checksum += Name->Buffer[i+1] & 0xffff;
    00721         }
    00722     }
    00723
    00724     return Checksum;
    00725 }

VOID RtlGenerate8dot3Name | ( | IN PUNICODE_STRING | Name,
|  | IN BOOLEAN | AllowExtendedCharacters,
|  | IN OUT PGENERATE_NAME_CONTEXT | Context,
|  | OUT PUNICODE_STRING | Name8dot3
| ) |

Definition at line 81 of file gen8dot3.c.

References FALSE, FsRtlSafeExtensions, GetNextWchar(), IsDbcsCharacter, L, Name, NlsMbOemCodePageTag, RtlComputeLfnChecksum(), TRUE, and USHORT.

    00090                    :
    00091
    00092     This routine is used to generate an 8.3 name from a long name.  It can
    00093     be called repeatedly to generate different 8.3 name variations for the
    00094     same long name.  This is necessary if the gernerated 8.3 name conflicts
    00095     with an existing 8.3 name.
    00096
    00097 Arguments:
    00098
    00099     Name - Supplies the original long name that is being translated from.
    00100
    00101     AllowExtendedCharacters - If TRUE, then extended characters, including
    00102         DBCS characters, are allowed in the basis of the short name if they
    00103         map to an upcased Oem character.
    00104
    00105     Context - Supplies a context for the translation.  This is a private structure
    00106         needed by this routine to help enumerate the different long name
    00107         possibilities.  The caller is responsible with providing a "zeroed out"
    00108         context structure on the first call for each given input name.
    00109
    00110     Name8dot3 - Receives the new 8.3 name.  Pool for the buffer must be allocated
    00111         by the caller and should be 12 characters wide (i.e., 24 bytes).
    00112
    00113 Return Value:
    00114
    00115     None.
    00116
    00117 --*/
    00118
    00119 {
    00120     BOOLEAN DbcsAware;
    00121     BOOLEAN IndexAll9s = TRUE;
    00122     ULONG OemLength;
    00123     ULONG IndexLength;
    00124     WCHAR IndexBuffer[8];
    00125     ULONG i;
    00126
    00127 #ifdef NTOS_KERNEL_RUNTIME
    00128     extern BOOLEAN FsRtlSafeExtensions;
    00129 #else
    00130     BOOLEAN FsRtlSafeExtensions = TRUE;
    00131 #endif
    00132
    00133     DbcsAware = AllowExtendedCharacters && NlsMbOemCodePageTag;
    00134
    00135     //
    00136     //  Check if this is the first time we are being called, and if so then
    00137     //  initialize the context fields.
    00138     //
    00139
    00140     if (Context->NameLength == 0) {
    00141
    00142         ULONG LastDotIndex;
    00143
    00144         ULONG CurrentIndex;
    00145         BOOLEAN SkipDots;
    00146         WCHAR wc;
    00147
    00148         //
    00149         //  Skip down the name remembering the index of the last dot we
    00150         //  will skip over the first dot provided the name starts with
    00151         //  a dot.
    00152         //
    00153
    00154         LastDotIndex = MAXULONG;
    00155
    00156         CurrentIndex = 0;
    00157         SkipDots = ((Name->Length > 0) && (Name->Buffer[0] == L'.'));
    00158
    00159         while ((wc = GetNextWchar( Name,
    00160                                    &CurrentIndex,
    00161                                    SkipDots,
    00162                                    AllowExtendedCharacters )) != 0) {
    00163
    00164             SkipDots = FALSE;
    00165             if (wc == L'.') { LastDotIndex = CurrentIndex; }
    00166         }
    00167
    00168         //
    00169         //  If the LastDotIndex is the last character in the name,
    00170         //  then there really isn't an extension, so reset LastDotIndex.
    00171         //
    00172
    00173         if (LastDotIndex == Name->Length/sizeof(WCHAR)) {
    00174
    00175             LastDotIndex = MAXULONG;
    00176         }
    00177
    00178         //
    00179         //  Build up the name part. This can be at most 6 characters
    00180         //  (because of the ~# appeneded on the end) and we skip over
    00181         //  dots, except the last dot, which terminates the loop.
    00182         //
    00183         //  We exit the loop if:
    00184         //
    00185         //  - The input Name has been exhausted
    00186         //  - We have consumed the input name up to the last dot
    00187         //  - We have filled 6 characters of short name basis
    00188         //
    00189
    00190         CurrentIndex = 0;
    00191         OemLength = 0;
    00192         Context->NameLength = 0;
    00193
    00194         while ((wc = GetNextWchar( Name, &CurrentIndex, TRUE, AllowExtendedCharacters)) &&
    00195                (CurrentIndex < LastDotIndex) &&
    00196                (Context->NameLength < 6)) {
    00197
    00198             //
    00199             //  If we are on a multi-byte code page we have to be careful
    00200             //  here because the short name (when converted to Oem) must
    00201             //  be 8.3 compliant.  Note that if AllowExtendedCharacters
    00202             //  is FALSE, then GetNextWchar will never return a DBCS
    00203             //  character, so we don't care what kind of code page we
    00204             //  are on.
    00205             //
    00206
    00207             if (DbcsAware) {
    00208
    00209                 OemLength += IsDbcsCharacter(wc) ? 2 : 1;
    00210
    00211                 if (OemLength > 6) { break; }
    00212             }
    00213
    00214             //
    00215             //  Copy the UNICODE character into the name buffer
    00216             //
    00217
    00218             Context->NameBuffer[Context->NameLength++] = wc;
    00219         }
    00220
    00221         //
    00222         //  Now if the name part of the basis is 2 or less bytes (when
    00223         //  represented in Oem) then append a four character checksum
    00224         //  to make the short name space less sparse.
    00225         //
    00226
    00227         if ((DbcsAware ? OemLength : Context->NameLength) <= 2) {
    00228
    00229             USHORT Checksum;
    00230             WCHAR Nibble;
    00231
    00232             Checksum =
    00233             Context->Checksum = RtlComputeLfnChecksum( Name );
    00234
    00235             for (i = 0; i < 4; i++, Checksum >>= 4) {
    00236
    00237                 Nibble = Checksum & 0xf;
    00238                 Nibble += Nibble <= 9 ? '0' : 'A' - 10;
    00239
    00240                 Context->NameBuffer[ Context->NameLength + i ] = Nibble;
    00241             }
    00242
    00243             Context->NameLength += 4;
    00244             Context->ChecksumInserted = TRUE;
    00245         }
    00246
    00247         //
    00248         //  Now process the last extension (if there is one).
    00249         //  If the last dot index is not MAXULONG then we
    00250         //  have located the last dot in the name
    00251         //
    00252
    00253         if (LastDotIndex != MAXULONG) {
    00254
    00255             //
    00256             //  Put in the "."
    00257             //
    00258
    00259             Context->ExtensionBuffer[0] = L'.';
    00260
    00261             //
    00262             //  Process the extension similar to how we processed the name
    00263             //
    00264             //  We exit the loop if:
    00265             //
    00266             //  - The input Name has been exhausted
    00267             //  - We have filled . + 3 characters of extension
    00268             //
    00269
    00270             OemLength = 1;
    00271             Context->ExtensionLength = 1;
    00272
    00273             while ((wc = GetNextWchar( Name, &LastDotIndex, TRUE, AllowExtendedCharacters)) &&
    00274                    (Context->ExtensionLength < 4)) {
    00275
    00276                 if (DbcsAware) {
    00277
    00278                     OemLength += IsDbcsCharacter(wc) ? 2 : 1;
    00279
    00280                     if (OemLength > 4) { break; }
    00281                 }
    00282
    00283                 Context->ExtensionBuffer[Context->ExtensionLength++] = wc;
    00284             }
    00285
    00286             //
    00287             //  If we had to truncate the extension (i.e. input name was not
    00288             //  exhausted), change the last char of the truncated extension
    00289             //  to a ~ is user has selected safe extensions.
    00290             //
    00291
    00292             if (wc && FsRtlSafeExtensions) {
    00293
    00294                 Context->ExtensionBuffer[Context->ExtensionLength - 1] = L'~';
    00295             }
    00296
    00297         } else {
    00298
    00299             Context->ExtensionLength = 0;
    00300         }
    00301     }
    00302
    00303     //
    00304     //  In all cases we add one to the index value and this is the value
    00305     //  of the index we are going to generate this time around
    00306     //
    00307
    00308     Context->LastIndexValue += 1;
    00309
    00310     //
    00311     //  Now if the new index value is greater than 4 then we've had too
    00312     //  many collisions and we should alter our basis if possible
    00313     //
    00314
    00315     if ((Context->LastIndexValue > 4) && !Context->ChecksumInserted) {
    00316
    00317         USHORT Checksum;
    00318         WCHAR Nibble;
    00319
    00320         //
    00321         // 'XX' is represented A DBCS character.
    00322         //
    00323         // LongName       -> ShortName  | DbcsBias  Oem  Unicode
    00324         // -----------------------------+------------------------
    00325         // XXXXThisisapen -> XX1234     |    1       6      5
    00326         // XXThisisapen   -> XX1234     |    1       6      5
    00327         // aXXThisisapen  -> a1234      |    1       5      5
    00328         // aaThisisapen   -> aa1234     |    0       6      6
    00329         //
    00330
    00331         ULONG DbcsBias;
    00332
    00333         if (DbcsAware) {
    00334
    00335               DbcsBias = ((IsDbcsCharacter(Context->NameBuffer[0]) ? 1 : 0) |
    00336                           (IsDbcsCharacter(Context->NameBuffer[1]) ? 1 : 0));
    00337
    00338         } else {
    00339
    00340               DbcsBias = 0;
    00341         }
    00342
    00343         Checksum =
    00344         Context->Checksum = RtlComputeLfnChecksum( Name );
    00345
    00346         for (i = (2-DbcsBias); i < (6-DbcsBias); i++, Checksum >>= 4) {
    00347
    00348             Nibble = Checksum & 0xf;
    00349             Nibble += Nibble <= 9 ? '0' : 'A' - 10;
    00350
    00351             Context->NameBuffer[ i ] = Nibble;
    00352         }
    00353
    00354         Context->NameLength = (UCHAR)(6-DbcsBias);
    00355         Context->LastIndexValue = 1;
    00356         Context->ChecksumInserted = TRUE;
    00357     }
    00358
    00359     //
    00360     //  Now build the index buffer from high index to low index because we
    00361     //  use a mod & div operation to build the string from the index value.
    00362     //
    00363     //  We also want to remember is we are about to rollover in base 10.
    00364     //
    00365
    00366     for (IndexLength = 1, i = Context->LastIndexValue;
    00367          (IndexLength <= 7) && (i > 0);
    00368          IndexLength += 1, i /= 10) {
    00369
    00370         if ((IndexBuffer[ 8 - IndexLength] = (WCHAR)(L'0' + (i % 10))) != L'9') {
    00371
    00372             IndexAll9s = FALSE;
    00373         }
    00374     }
    00375
    00376     //
    00377     //  And tack on the preceding dash
    00378     //
    00379
    00380     IndexBuffer[ 8 - IndexLength ] = L'~';
    00381
    00382     //
    00383     //  At this point everything is set up to copy to the output buffer.  First
    00384     //  copy over the name and then only copy the index and extension if they exist
    00385     //
    00386
    00387     if (Context->NameLength != 0) {
    00388
    00389         RtlCopyMemory( &Name8dot3->Buffer[0],
    00390                        &Context->NameBuffer[0],
    00391                        Context->NameLength * 2 );
    00392
    00393         Name8dot3->Length = (USHORT)(Context->NameLength * 2);
    00394
    00395     } else {
    00396
    00397         Name8dot3->Length = 0;
    00398     }
    00399
    00400     //
    00401     //  Now do the index.
    00402     //
    00403
    00404     RtlCopyMemory( &Name8dot3->Buffer[ Name8dot3->Length/2 ],
    00405                    &IndexBuffer[ 8 - IndexLength ],
    00406                    IndexLength * 2 );
    00407
    00408     Name8dot3->Length += (USHORT) (IndexLength * 2);
    00409
    00410     //
    00411     //  Now conditionally do the extension
    00412     //
    00413
    00414     if (Context->ExtensionLength != 0) {
    00415
    00416         RtlCopyMemory( &Name8dot3->Buffer[ Name8dot3->Length/2 ],
    00417                        &Context->ExtensionBuffer[0],
    00418                        Context->ExtensionLength * 2 );
    00419
    00420         Name8dot3->Length += (USHORT) (Context->ExtensionLength * 2);
    00421     }
    00422
    00423     //
    00424     //  If current index value is all 9s, then the next value will cause the
    00425     //  index string to grow from it's current size.  In this case recompute
    00426     //  Context->NameLength so that is will be correct for next time.
    00427     //
    00428
    00429     if (IndexAll9s) {
    00430
    00431         if (DbcsAware) {
    00432
    00433             for (i = 0, OemLength = 0; i < Context->NameLength; i++) {
    00434
    00435                 OemLength += IsDbcsCharacter(Context->NameBuffer[i]) ? 2 : 1;
    00436
    00437                 if (OemLength >= 8 - (IndexLength + 1)) {
    00438                     break;
    00439                 }
    00440             }
    00441
    00442             Context->NameLength = (UCHAR)i;
    00443
    00444         } else {
    00445
    00446             Context->NameLength -= 1;
    00447         }
    00448     }
    00449
    00450     //
    00451     //  And return to our caller
    00452     //
    00453
    00454     return;
    00455 }

BOOLEAN RtlIsNameLegalDOS8Dot3 | ( | IN PUNICODE_STRING | Name,
|  | IN OUT POEM_STRING OemName | OPTIONAL,
|  | OUT PBOOLEAN NameContainsSpaces | OPTIONAL
| ) |

Definition at line 729 of file gen8dot3.c.

References FALSE, Index, Name, NlsMbOemCodePageTag, NlsOemLeadByteInfo, NT_SUCCESS, RtlFatIllegalTable, RtlUpcaseUnicodeStringToCountedOemString(), and TRUE.

Referenced by LB_CreateLBLine().

    00736                    :
    00737
    00738     This routine takes an input string and gives a definitive answer
    00739     on whether this name can successfully be used to create a file
    00740     on the FAT file system.
    00741
    00742     This routine can therefore also be used to determine if a name is
    00743     appropriate to be passed back to a Win31 or DOS app, i.e. whether
    00744     the downlevel APP will understand the name.
    00745
    00746     Note: an important part of this test is the mapping from UNICODE
    00747     to Oem, which is why it is important that the input parameter be
    00748     received in UNICODE.
    00749
    00750 Arguments:
    00751
    00752     Name - The UNICODE name to test for conformance to 8.3 symantics.
    00753
    00754     OemName - If specified, will receive the Oem name corresponding
    00755         to the passed in Name.  Storage must be provided by the caller.
    00756         The name is undefined if the routine returns FALSE.
    00757
    00758     NameContainsSpaces - If the function returns TRUE, then this
    00759         parameter will indicate if the names contains spaces.  If
    00760         the function returns FALSE, this parameter is undefined. In
    00761         many instances, the alternate name is more appropriate to
    00762         use if spaces are present in the principle name, even if
    00763         it is 8.3 compliant.
    00764
    00765 Return Value:
    00766
    00767     BOOLEAN - TRUE if the passed in UNICODE name forms a valid 8.3
    00768         FAT name when upcased to the current Oem code page.
    00769
    00770 --*/
    00771
    00772 {
    00773     ULONG Index;
    00774     BOOLEAN ExtensionPresent = FALSE;
    00775     BOOLEAN SpacesPresent = FALSE;
    00776     OEM_STRING LocalOemName;
    00777     UCHAR Char;
    00778     UCHAR OemBuffer[12];
    00779
    00780     //
    00781     //  If the name is more than 12 chars, bail.
    00782     //
    00783
    00784     if (Name->Length > 12*sizeof(WCHAR)) {
    00785         return FALSE;
    00786     }
    00787
    00788     //
    00789     //  Now upcase this name to Oem.  If anything goes wrong,
    00790     //  return FALSE.
    00791     //
    00792
    00793     if (!ARGUMENT_PRESENT(OemName)) {
    00794
    00795         OemName = &LocalOemName;
    00796
    00797         OemName->Buffer = &OemBuffer[0];
    00798         OemName->Length = 0;
    00799         OemName->MaximumLength = 12;
    00800     }
    00801
    00802     if (!NT_SUCCESS(RtlUpcaseUnicodeStringToCountedOemString(OemName, Name, FALSE))) {
    00803         return FALSE;
    00804     }
    00805
    00806     //
    00807     //  Special case . and ..
    00808     //
    00809
    00810     if (((OemName->Length == 1) && (OemName->Buffer[0] == '.')) ||
    00811         ((OemName->Length == 2) && (OemName->Buffer[0] == '.') && (OemName->Buffer[1] == '.'))) {
    00812
    00813         if (ARGUMENT_PRESENT(NameContainsSpaces)) {
    00814             *NameContainsSpaces = FALSE;
    00815         }
    00816         return TRUE;
    00817     }
    00818
    00819     //
    00820     //  Now we are going to walk through the string looking for
    00821     //  illegal characters and/or incorrect syntax.
    00822     //
    00823
    00824     for ( Index = 0; Index < OemName->Length; Index += 1 ) {
    00825
    00826         Char = OemName->Buffer[ Index ];
    00827
    00828         //
    00829         //  Skip over and Dbcs chacters
    00830         //
    00831
    00832         if (NlsMbOemCodePageTag && NlsOemLeadByteInfo[Char]) {
    00833
    00834             //
    00835             //  1) if we're looking at base part ( !ExtensionPresent ) and the 8th byte
    00836             //     is in the dbcs leading byte range, it's error ( Index == 7 ). If the
    00837             //     length of base part is more than 8 ( Index > 7 ), it's definitely error.
    00838             //
    00839             //  2) if the last byte ( Index == DbcsName.Length - 1 ) is in the dbcs leading
    00840             //     byte range, it's error
    00841             //
    00842
    00843             if ((!ExtensionPresent && (Index >= 7)) ||
    00844                 (Index == (ULONG)(OemName->Length - 1))) {
    00845                 return FALSE;
    00846             }
    00847
    00848             Index += 1;
    00849
    00850             continue;
    00851         }
    00852
    00853         //
    00854         //  Make sure this character is legal.
    00855         //
    00856
    00857         if ((Char < 0x80) &&
    00858             (RtlFatIllegalTable[Char/32] & (1 << (Char%32)))) {
    00859             return FALSE;
    00860         }
    00861
    00862         //
    00863         //  Remember if there was a space.
    00864         //
    00865
    00866         if (Char == ' ') {
    00867             SpacesPresent = TRUE;
    00868         }
    00869
    00870         if (Char == '.') {
    00871
    00872             //
    00873             //  We stepped onto a period.  We require the following things:
    00874             //
    00875             //      - There can only be one
    00876             //      - It can't be the first character
    00877             //      - The previous character can't be a space.
    00878             //      - There can't be more than 3 bytes following
    00879             //
    00880
    00881             if (ExtensionPresent ||
    00882                 (Index == 0) ||
    00883                 (OemName->Buffer[Index - 1] == ' ') ||
    00884                 (OemName->Length - (Index + 1) > 3)) {
    00885
    00886                 return FALSE;
    00887             }
    00888
    00889             ExtensionPresent = TRUE;
    00890         }
    00891
    00892         //
    00893         //  The base part of the name can't be more than 8 characters long.
    00894         //
    00895
    00896         if ((Index >= 8) && !ExtensionPresent) { return FALSE; }
    00897     }
    00898
    00899     //
    00900     //  The name cannot end in a space or a period.
    00901     //
    00902
    00903     if ((Char == ' ') || (Char == '.')) { return FALSE; }
    00904
    00905     if (ARGUMENT_PRESENT(NameContainsSpaces)) {
    00906         *NameContainsSpaces = SpacesPresent;
    00907     }
    00908     return TRUE;
    00909 }

BOOLEAN RtlIsValidOemCharacter | ( | IN PWCHAR | Char | ) |

Definition at line 459 of file gen8dot3.c.

References FALSE, HIBYTE, LOBYTE, NLS_UPCASE, NlsMbOemCodePageTables, NlsMbOemCodePageTag, NlsOemLeadByteInfo, NlsOemToUnicodeData, NlsUnicodeToMbOemData, NlsUnicodeToOemData, OemDefaultChar, TRUE, and USHORT.

Referenced by GetNextWchar().

    00465                    :
    00466
    00467     This routine determines if the best-fitted and upcased version of the
    00468     input unicode char is a valid Oem character.
    00469
    00470 Arguments:
    00471
    00472     Char - Supplies the Unicode char and receives the best-fitted and
    00473         upcased version if it was indeed valid.
    00474
    00475 Return Value:
    00476
    00477     TRUE if the character was valid.
    00478
    00479 --*/
    00480
    00481 {
    00482     WCHAR UniTmp;
    00483     WCHAR OemChar;
    00484
    00485     //
    00486     //  First try to make a round trip from Unicode->Oem->Unicode.
    00487     //
    00488
    00489     if (!NlsMbOemCodePageTag) {
    00490
    00491         UniTmp = (WCHAR)NLS_UPCASE(NlsOemToUnicodeData[(UCHAR)NlsUnicodeToOemData[*Char]]);
    00492         OemChar = NlsUnicodeToOemData[UniTmp];
    00493
    00494     } else {
    00495
    00496         //
    00497         // Convert to OEM and back to Unicode before upper casing
    00498         // to ensure the visual best fits are converted and
    00499         // upper cased properly.
    00500         //
    00501
    00502         OemChar = NlsUnicodeToMbOemData[ *Char ];
    00503
    00504         if (NlsOemLeadByteInfo[HIBYTE(OemChar)]) {
    00505
    00506             USHORT Entry;
    00507
    00508             //
    00509             // Lead byte - translate the trail byte using the table
    00510             // that corresponds to this lead byte.
    00511             //
    00512
    00513             Entry = NlsOemLeadByteInfo[HIBYTE(OemChar)];
    00514             UniTmp = (WCHAR)NlsMbOemCodePageTables[ Entry + LOBYTE(OemChar) ];
    00515
    00516         } else {
    00517
    00518             //
    00519             // Single byte character.
    00520             //
    00521
    00522             UniTmp = NlsOemToUnicodeData[LOBYTE(OemChar)];
    00523         }
    00524
    00525         //
    00526         //  Now upcase this UNICODE character, and convert it to Oem.
    00527         //
    00528
    00529         UniTmp = (WCHAR)NLS_UPCASE(UniTmp);
    00530         OemChar = NlsUnicodeToMbOemData[UniTmp];
    00531     }
    00532
    00533     //
    00534     //  Now if the final OemChar is the default one, then there was no
    00535     //  mapping for this UNICODE character.
    00536     //
    00537
    00538     if (OemChar == OemDefaultChar) {
    00539
    00540         return FALSE;
    00541
    00542     } else {
    00543
    00544         *Char = UniTmp;
    00545         return TRUE;
    00546     }
    00547 }

## Variable Documentation

PUSHORT NlsMbOemCodePageTables

| Definition at line 31 of file gen8dot3.c. Referenced by RtlIsValidOemCharacter(), RtlOemToUnicodeN(), RtlResetRtlTranslations(), and RtlUpcaseUnicodeToOemN().

BOOLEAN NlsMbOemCodePageTag

| Definition at line 32 of file gen8dot3.c. Referenced by FsRtlIsDbcsInExpression(), RtlGenerate8dot3Name(), RtlIsNameLegalDOS8Dot3(), RtlIsValidOemCharacter(), RtlOemToUnicodeN(), RtlpDidUnicodeToOemWork(), RtlResetRtlTranslations(), RtlUnicodeToOemN(), and RtlUpcaseUnicodeToOemN().

PUSHORT NlsOemLeadByteInfo

| Definition at line 33 of file gen8dot3.c. Referenced by RtlIsNameLegalDOS8Dot3(), RtlIsValidOemCharacter(), RtlOemToUnicodeN(), RtlpDidUnicodeToOemWork(), RtlResetRtlTranslations(), and RtlUpcaseUnicodeToOemN().

PUSHORT NlsOemToUnicodeData

| Definition at line 29 of file gen8dot3.c. Referenced by RtlIsValidOemCharacter(), RtlOemToUnicodeN(), RtlResetRtlTranslations(), and RtlUpcaseUnicodeToOemN().

PUSHORT NlsUnicodeToMbOemData

| Definition at line 28 of file gen8dot3.c. Referenced by RtlIsValidOemCharacter(), RtlResetRtlTranslations(), RtlUnicodeToOemN(), and RtlUpcaseUnicodeToOemN().

PCH NlsUnicodeToOemData

| Definition at line 30 of file gen8dot3.c. Referenced by RtlIsValidOemCharacter(), RtlResetRtlTranslations(), RtlUnicodeToOemN(), and RtlUpcaseUnicodeToOemN().

USHORT OemDefaultChar

| Definition at line 34 of file gen8dot3.c. Referenced by RtlIsValidOemCharacter(), RtlpDidUnicodeToOemWork(), and RtlResetRtlTranslations().

const ULONG RtlFatIllegalTable[]

Initial value:

     { 0xffffffff,
                                   0xfc009c04,
                                   0x38000000,
                                   0x10000000 }

Definition at line 41 of file gen8dot3.c.

Referenced by GetNextWchar(), and RtlIsNameLegalDOS8Dot3().