00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
#include "ntrtlp.h"
00026
#include <stdio.h>
00027
00028 extern PUSHORT NlsUnicodeToMbOemData;
00029 extern PUSHORT NlsOemToUnicodeData;
00030 extern PCH
NlsUnicodeToOemData;
00031 extern PUSHORT NlsMbOemCodePageTables;
00032 extern BOOLEAN
NlsMbOemCodePageTag;
00033 extern PUSHORT NlsOemLeadByteInfo;
00034 extern USHORT OemDefaultChar;
00035
00036
00037
00038
00039
00040
const
00041 ULONG
RtlFatIllegalTable[] = { 0xffffffff,
00042 0xfc009c04,
00043 0x38000000,
00044 0x10000000 };
00045
00046 WCHAR
00047
GetNextWchar (
00048 IN PUNICODE_STRING Name,
00049 IN PULONG CurrentIndex,
00050 IN BOOLEAN SkipDots,
00051 IN BOOLEAN AllowExtendedCharacters
00052 );
00053
00054
USHORT
00055
RtlComputeLfnChecksum (
00056 PUNICODE_STRING Name
00057 );
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define IsDbcsCharacter(WC) ( \
00067
((WC) > 127) && \
00068
(HIBYTE(NlsUnicodeToMbOemData[(WC)])) \
00069
)
00070
00071
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
00072
#pragma alloc_text(PAGE,RtlGenerate8dot3Name)
00073
#pragma alloc_text(PAGE,GetNextWchar)
00074
#pragma alloc_text(PAGE,RtlComputeLfnChecksum)
00075
#pragma alloc_text(PAGE,RtlIsNameLegalDOS8Dot3)
00076
#pragma alloc_text(PAGE,RtlIsValidOemCharacter)
00077
#endif
00078
00079
00080
VOID
00081 RtlGenerate8dot3Name (
00082 IN PUNICODE_STRING Name,
00083 IN BOOLEAN AllowExtendedCharacters,
00084 IN OUT PGENERATE_NAME_CONTEXT Context,
00085 OUT PUNICODE_STRING Name8dot3
00086 )
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
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
00137
00138
00139
00140
if (Context->NameLength == 0) {
00141
00142 ULONG LastDotIndex;
00143
00144 ULONG CurrentIndex;
00145 BOOLEAN SkipDots;
00146 WCHAR wc;
00147
00148
00149
00150
00151
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
00170
00171
00172
00173
if (LastDotIndex ==
Name->Length/
sizeof(WCHAR)) {
00174
00175 LastDotIndex = MAXULONG;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
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
00200
00201
00202
00203
00204
00205
00206
00207
if (DbcsAware) {
00208
00209 OemLength +=
IsDbcsCharacter(wc) ? 2 : 1;
00210
00211
if (OemLength > 6) {
break; }
00212 }
00213
00214
00215
00216
00217
00218 Context->NameBuffer[Context->NameLength++] = wc;
00219 }
00220
00221
00222
00223
00224
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
00249
00250
00251
00252
00253
if (LastDotIndex != MAXULONG) {
00254
00255
00256
00257
00258
00259 Context->ExtensionBuffer[0] =
L'.';
00260
00261
00262
00263
00264
00265
00266
00267
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
00288
00289
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
00305
00306
00307
00308 Context->LastIndexValue += 1;
00309
00310
00311
00312
00313
00314
00315
if ((Context->LastIndexValue > 4) && !Context->ChecksumInserted) {
00316
00317
USHORT Checksum;
00318 WCHAR Nibble;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
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
00361
00362
00363
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
00378
00379
00380 IndexBuffer[ 8 - IndexLength ] =
L'~';
00381
00382
00383
00384
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
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
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
00425
00426
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
00452
00453
00454
return;
00455 }
00456
00457
00458 BOOLEAN
00459 RtlIsValidOemCharacter (
00460 IN PWCHAR Char
00461 )
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 {
00482 WCHAR UniTmp;
00483 WCHAR OemChar;
00484
00485
00486
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
00498
00499
00500
00501
00502 OemChar =
NlsUnicodeToMbOemData[ *Char ];
00503
00504
if (
NlsOemLeadByteInfo[
HIBYTE(OemChar)]) {
00505
00506
USHORT Entry;
00507
00508
00509
00510
00511
00512
00513 Entry =
NlsOemLeadByteInfo[
HIBYTE(OemChar)];
00514 UniTmp = (WCHAR)
NlsMbOemCodePageTables[ Entry +
LOBYTE(OemChar) ];
00515
00516 }
else {
00517
00518
00519
00520
00521
00522 UniTmp =
NlsOemToUnicodeData[
LOBYTE(OemChar)];
00523 }
00524
00525
00526
00527
00528
00529 UniTmp = (WCHAR)
NLS_UPCASE(UniTmp);
00530 OemChar =
NlsUnicodeToMbOemData[UniTmp];
00531 }
00532
00533
00534
00535
00536
00537
00538
if (OemChar ==
OemDefaultChar) {
00539
00540
return FALSE;
00541
00542 }
else {
00543
00544 *Char = UniTmp;
00545
return TRUE;
00546 }
00547 }
00548
00549
00550
00551
00552
00553
00554 WCHAR
00555 GetNextWchar (
00556 IN PUNICODE_STRING Name,
00557 IN PULONG CurrentIndex,
00558 IN BOOLEAN SkipDots,
00559 IN BOOLEAN AllowExtendedCharacters
00560 )
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 {
00597 WCHAR wc;
00598
00599
00600
00601
00602
00603
00604 wc = 0;
00605
00606
00607
00608
00609
00610
00611
while (*CurrentIndex < (ULONG)(
Name->Length/2)) {
00612
00613
00614
00615
00616
00617 wc =
Name->Buffer[*CurrentIndex];
00618 *CurrentIndex += 1;
00619
00620
00621
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
00634
00635
00636
if ((wc < 0x80) && (
RtlFatIllegalTable[wc/32] & (1 << (wc%32)))) {
00637
00638 wc =
L'_';
00639 }
00640
00641
00642
00643
00644
00645
if ((wc >=
L'a') && (wc <=
L'z')) {
00646
00647 wc -=
L'a' -
L'A';
00648 }
00649
00650
00651
00652
00653
00654
break;
00655 }
00656 }
00657
00658
00659
00660
return wc;
00661 }
00662
00663
00664
00665
00666
00667
00668
USHORT
00669 RtlComputeLfnChecksum (
00670 PUNICODE_STRING Name
00671 )
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
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
00705
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
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 }
00726
00727
00728 BOOLEAN
00729 RtlIsNameLegalDOS8Dot3 (
00730 IN PUNICODE_STRING Name,
00731 IN OUT POEM_STRING OemName OPTIONAL,
00732 OUT PBOOLEAN NameContainsSpaces OPTIONAL
00733 )
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
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
00782
00783
00784
if (
Name->Length > 12*
sizeof(WCHAR)) {
00785
return FALSE;
00786 }
00787
00788
00789
00790
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
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
00821
00822
00823
00824
for (
Index = 0;
Index < OemName->Length;
Index += 1 ) {
00825
00826 Char = OemName->Buffer[
Index ];
00827
00828
00829
00830
00831
00832
if (
NlsMbOemCodePageTag &&
NlsOemLeadByteInfo[Char]) {
00833
00834
00835
00836
00837
00838
00839
00840
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
00855
00856
00857
if ((Char < 0x80) &&
00858 (
RtlFatIllegalTable[Char/32] & (1 << (Char%32)))) {
00859
return FALSE;
00860 }
00861
00862
00863
00864
00865
00866
if (Char ==
' ') {
00867 SpacesPresent =
TRUE;
00868 }
00869
00870
if (Char ==
'.') {
00871
00872
00873
00874
00875
00876
00877
00878
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
00894
00895
00896
if ((
Index >= 8) && !ExtensionPresent) {
return FALSE; }
00897 }
00898
00899
00900
00901
00902
00903
if ((Char ==
' ') || (Char ==
'.')) {
return FALSE; }
00904
00905
if (ARGUMENT_PRESENT(NameContainsSpaces)) {
00906 *NameContainsSpaces = SpacesPresent;
00907 }
00908
return TRUE;
00909 }
00910