00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "nt.h"
00022
#include "ntrtl.h"
00023
#include "nturtl.h"
00024
#include "string.h"
00025
#include "ctype.h"
00026
00027 #define IS_PATH_SEPARATOR_U(ch) ((ch == L'\\') || (ch == L'/'))
00028 #define IS_DOT_U(s) ( s[0] == L'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) )
00029 #define IS_DOT_DOT_U(s) ( s[0] == L'.' && s[1] == L'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) )
00030
00031
VOID
00032
RtlpCheckRelativeDrive(
00033 WCHAR NewDrive
00034 );
00035
00036 ULONG
00037
RtlIsDosDeviceName_Ustr(
00038 IN PUNICODE_STRING DosFileName
00039 );
00040
00041 ULONG
00042
RtlGetFullPathName_Ustr(
00043 PUNICODE_STRING FileName,
00044 ULONG nBufferLength,
00045 PWSTR lpBuffer,
00046 PWSTR *lpFilePart OPTIONAL,
00047 PBOOLEAN NameInvalid,
00048 RTL_PATH_TYPE *InputPathType
00049 );
00050
00051 #define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
00052
00053 const UNICODE_STRING
RtlpDosLPTDevice =
CONSTANT_UNICODE_STRING( L
"LPT" );
00054 const UNICODE_STRING
RtlpDosCOMDevice =
CONSTANT_UNICODE_STRING( L
"COM" );
00055 const UNICODE_STRING
RtlpDosPRNDevice =
CONSTANT_UNICODE_STRING( L
"PRN" );
00056 const UNICODE_STRING
RtlpDosAUXDevice =
CONSTANT_UNICODE_STRING( L
"AUX" );
00057 const UNICODE_STRING
RtlpDosNULDevice =
CONSTANT_UNICODE_STRING( L
"NUL" );
00058 const UNICODE_STRING
RtlpDosCONDevice =
CONSTANT_UNICODE_STRING( L
"CON" );
00059
00060 const UNICODE_STRING
RtlpDosSlashCONDevice =
CONSTANT_UNICODE_STRING( L
"\\\\.\\CON" );
00061 const UNICODE_STRING
RtlpSlashSlashDot =
CONSTANT_UNICODE_STRING( L
"\\\\.\\" );
00062 const UNICODE_STRING
RtlpDosDevicesPrefix =
CONSTANT_UNICODE_STRING( L
"\\??\\" );
00063 const UNICODE_STRING
RtlpDosDevicesUncPrefix =
CONSTANT_UNICODE_STRING( L
"\\??\\UNC\\" );
00064
00065 #define RtlpLongestPrefix RtlpDosDevicesUncPrefix.Length
00066
00067 ULONG
00068 RtlpComputeBackupIndex(
00069 IN PCURDIR CurDir
00070 )
00071 {
00072 ULONG BackupIndex;
00073 PWSTR UncPathPointer;
00074 ULONG NumberOfPathSeparators;
00075 RTL_PATH_TYPE CurDirPathType;
00076
00077
00078
00079
00080
00081
00082 CurDirPathType =
RtlDetermineDosPathNameType_U(CurDir->DosPath.Buffer);
00083 BackupIndex = 3;
00084
if ( CurDirPathType == RtlPathTypeUncAbsolute ) {
00085
00086
00087
00088
00089
00090
00091 UncPathPointer = CurDir->DosPath.Buffer + 2;
00092 NumberOfPathSeparators = 0;
00093
while (*UncPathPointer) {
00094
if (
IS_PATH_SEPARATOR_U(*UncPathPointer)) {
00095
00096 NumberOfPathSeparators++;
00097
00098
if (NumberOfPathSeparators == 2) {
00099
break;
00100 }
00101 }
00102
00103 UncPathPointer++;
00104
00105 }
00106
00107 BackupIndex = (ULONG)(UncPathPointer - CurDir->DosPath.Buffer);
00108 }
00109
return BackupIndex;
00110 }
00111
00112
00113 ULONG
00114 RtlGetLongestNtPathLength( VOID )
00115 {
00116
return RtlpLongestPrefix + DOS_MAX_PATH_LENGTH + 1;
00117 }
00118
00119
VOID
00120 RtlpResetDriveEnvironment(
00121 IN WCHAR DriveLetter
00122 )
00123 {
00124 WCHAR EnvVarNameBuffer[4];
00125 WCHAR EnvVarNameValue[4];
00126 UNICODE_STRING s1,s2;
00127
00128 EnvVarNameBuffer[0] =
L'=';
00129 EnvVarNameBuffer[1] = DriveLetter;
00130 EnvVarNameBuffer[2] =
L':';
00131 EnvVarNameBuffer[3] =
L'\0';
00132
RtlInitUnicodeString(&s1,EnvVarNameBuffer);
00133
00134 EnvVarNameValue[0] = DriveLetter;
00135 EnvVarNameValue[1] =
L':';
00136 EnvVarNameValue[2] =
L'\\';
00137 EnvVarNameValue[3] =
L'\0';
00138
RtlInitUnicodeString(&s2,EnvVarNameValue);
00139
00140
RtlSetEnvironmentVariable(
NULL,&s1,&s2);
00141 }
00142
00143
00144 ULONG
00145 RtlGetCurrentDirectory_U(
00146 ULONG nBufferLength,
00147 PWSTR lpBuffer
00148 )
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 {
00177 PCURDIR CurDir;
00178 ULONG Length;
00179 PWSTR CurDirName;
00180
00181 CurDir = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
00182
00183
RtlAcquirePebLock();
00184 CurDirName = CurDir->DosPath.Buffer;
00185
00186
00187
00188
00189
00190
00191 Length = CurDir->DosPath.Length>>1;
00192
if (CurDirName[Length-2] !=
L':') {
00193
if ( nBufferLength < (Length)<<1 ) {
00194
RtlReleasePebLock();
00195
return (Length)<<1;
00196 }
00197 }
00198
else {
00199
if ( nBufferLength <= (Length<<1) ) {
00200
RtlReleasePebLock();
00201
return ((Length+1)<<1);
00202 }
00203 }
00204
00205
try {
00206 RtlMoveMemory(lpBuffer,CurDirName,Length<<1);
00207
ASSERT(lpBuffer[Length-1] ==
L'\\');
00208
if (lpBuffer[Length-2] ==
L':') {
00209 lpBuffer[Length] = UNICODE_NULL;
00210 }
00211
else {
00212 lpBuffer[Length-1] = UNICODE_NULL;
00213 Length--;
00214 }
00215 }
00216 except (
EXCEPTION_EXECUTE_HANDLER) {
00217
RtlReleasePebLock();
00218
return 0
L;
00219 }
00220
RtlReleasePebLock();
00221
return Length<<1;
00222 }
00223
00224
NTSTATUS
00225 RtlSetCurrentDirectory_U(
00226 PUNICODE_STRING PathName
00227 )
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 {
00272 PCURDIR CurDir;
00273
NTSTATUS Status;
00274 BOOLEAN TranslationStatus;
00275 PVOID FreeBuffer;
00276 ULONG DosDirLength;
00277 ULONG IsDevice;
00278 ULONG DosDirCharCount;
00279 UNICODE_STRING DosDir;
00280 UNICODE_STRING NtFileName;
00281 HANDLE NewDirectoryHandle;
00282 OBJECT_ATTRIBUTES Obja;
00283 IO_STATUS_BLOCK IoStatusBlock;
00284 FILE_FS_DEVICE_INFORMATION DeviceInfo;
00285 RTL_PATH_TYPE InputPathType;
00286
00287 CurDir = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
00288
00289
00290 DosDir.Buffer =
NULL;
00291 FreeBuffer =
NULL;
00292 NewDirectoryHandle =
NULL;
00293
00294
RtlAcquirePebLock();
00295
00296 NtCurrentPeb()->EnvironmentUpdateCount += 1;
00297
00298
00299
00300
00301
00302
00303
00304
if ( ((ULONG_PTR)CurDir->Handle & OBJ_HANDLE_TAGBITS) == RTL_USER_PROC_CURDIR_CLOSE ) {
00305
NtClose(CurDir->Handle);
00306 CurDir->Handle =
NULL;
00307 }
00308
00309
try {
00310
try {
00311
00312
00313
00314
00315
00316
00317 DosDirLength = CurDir->DosPath.MaximumLength;
00318 DosDir.Buffer =
RtlAllocateHeap(RtlProcessHeap(), 0,DosDirLength);
00319
if ( !DosDir.Buffer ) {
00320
return STATUS_NO_MEMORY;
00321 }
00322 DosDir.Length = 0;
00323 DosDir.MaximumLength = (
USHORT)DosDirLength;
00324
00325
00326
00327
00328
00329
00330 IsDevice =
RtlIsDosDeviceName_Ustr(PathName);
00331
if ( IsDevice ) {
00332
return STATUS_NOT_A_DIRECTORY;
00333 }
00334
00335 DosDirLength =
RtlGetFullPathName_Ustr(
00336 PathName,
00337 DosDirLength,
00338 DosDir.Buffer,
00339
NULL,
00340
NULL,
00341 &InputPathType
00342 );
00343
00344
if ( !DosDirLength ) {
00345
return STATUS_OBJECT_NAME_INVALID;
00346 }
00347
00348 DosDirCharCount = DosDirLength >> 1;
00349
00350
00351
00352
00353
00354 TranslationStatus =
RtlDosPathNameToNtPathName_U(
00355 DosDir.Buffer,
00356 &NtFileName,
00357
NULL,
00358
NULL
00359 );
00360
00361
if ( !TranslationStatus ) {
00362
return STATUS_OBJECT_NAME_INVALID;
00363 }
00364 FreeBuffer = NtFileName.Buffer;
00365
00366 InitializeObjectAttributes(
00367 &Obja,
00368 &NtFileName,
00369 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
00370
NULL,
00371
NULL
00372 );
00373
00374
00375
00376
00377
00378
00379
if ( ((ULONG_PTR)CurDir->Handle & OBJ_HANDLE_TAGBITS) == RTL_USER_PROC_CURDIR_INHERIT ) {
00380 NewDirectoryHandle = (HANDLE)((ULONG_PTR)CurDir->Handle & ~OBJ_HANDLE_TAGBITS);
00381 CurDir->Handle =
NULL;
00382
00383
00384
00385
00386
00387
00388
00389
Status =
NtQueryVolumeInformationFile(
00390 NewDirectoryHandle,
00391 &IoStatusBlock,
00392 &DeviceInfo,
00393
sizeof(DeviceInfo),
00394 FileFsDeviceInformation
00395 );
00396
if ( !
NT_SUCCESS(
Status) ) {
00397
return RtlSetCurrentDirectory_U(PathName);
00398 }
00399
else {
00400
if ( DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA ) {
00401 NewDirectoryHandle =(HANDLE)( (ULONG_PTR)NewDirectoryHandle | 1);
00402 }
00403 }
00404
00405 }
00406
else {
00407
00408
00409
00410
00411
00412
Status =
NtOpenFile(
00413 &NewDirectoryHandle,
00414 FILE_TRAVERSE | SYNCHRONIZE,
00415 &Obja,
00416 &IoStatusBlock,
00417 FILE_SHARE_READ | FILE_SHARE_WRITE,
00418 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
00419 );
00420
00421
if ( !
NT_SUCCESS(
Status) ) {
00422
return Status;
00423 }
00424
00425
00426
00427
00428
00429
Status =
NtQueryVolumeInformationFile(
00430 NewDirectoryHandle,
00431 &IoStatusBlock,
00432 &DeviceInfo,
00433
sizeof(DeviceInfo),
00434 FileFsDeviceInformation
00435 );
00436
if ( !
NT_SUCCESS(
Status) ) {
00437
return Status;
00438 }
00439
else {
00440
if ( DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA ) {
00441 NewDirectoryHandle =(HANDLE)( (ULONG_PTR)NewDirectoryHandle | 1);
00442 }
00443 }
00444 }
00445
00446
00447
00448
00449
00450
if ( DosDir.Buffer[DosDirCharCount] !=
L'\\' &&
00451 DosDir.Buffer[DosDirCharCount-1] !=
L'\\') {
00452 DosDir.Buffer[DosDirCharCount] =
L'\\';
00453 DosDir.Buffer[DosDirCharCount+1] = UNICODE_NULL;
00454 DosDir.Length = (
USHORT)(DosDirLength +
sizeof(UNICODE_NULL));
00455 }
00456
else {
00457 DosDir.Length = (
USHORT)DosDirLength;
00458 }
00459
00460
00461
00462
00463
00464 RtlMoveMemory( CurDir->DosPath.Buffer, DosDir.Buffer, DosDir.Length+
sizeof(UNICODE_NULL) );
00465 CurDir->DosPath.Length = DosDir.Length;
00466
00467
if ( CurDir->Handle ) {
00468
NtClose(CurDir->Handle);
00469 }
00470 CurDir->Handle = NewDirectoryHandle;
00471 NewDirectoryHandle =
NULL;
00472 }
00473 finally {
00474
if ( DosDir.Buffer ) {
00475
RtlFreeHeap(RtlProcessHeap(), 0, DosDir.Buffer);
00476 }
00477
if ( FreeBuffer ) {
00478
RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
00479 }
00480
if ( NewDirectoryHandle ) {
00481
NtClose(NewDirectoryHandle);
00482 }
00483
RtlReleasePebLock();
00484 }
00485 }
00486 except (
EXCEPTION_EXECUTE_HANDLER) {
00487
return STATUS_ACCESS_VIOLATION;
00488 }
00489
return STATUS_SUCCESS;
00490 }
00491
00492 RTL_PATH_TYPE
00493 RtlDetermineDosPathNameType_U(
00494 IN PCWSTR DosFileName
00495 )
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 {
00538
00539 RTL_PATH_TYPE ReturnValue;
00540
00541
if (
IS_PATH_SEPARATOR_U(*DosFileName) ) {
00542
if (
IS_PATH_SEPARATOR_U(*(DosFileName+1)) ) {
00543
if ( DosFileName[2] ==
'.' ) {
00544
if (
IS_PATH_SEPARATOR_U(*(DosFileName+3)) ){
00545 ReturnValue = RtlPathTypeLocalDevice;
00546 }
00547
else if ( (*(DosFileName+3)) == UNICODE_NULL ){
00548 ReturnValue = RtlPathTypeRootLocalDevice;
00549 }
00550
else {
00551 ReturnValue = RtlPathTypeUncAbsolute;
00552 }
00553 }
00554
else {
00555 ReturnValue = RtlPathTypeUncAbsolute;
00556 }
00557 }
00558
else {
00559 ReturnValue = RtlPathTypeRooted;
00560 }
00561 }
00562
else if (*DosFileName && *(DosFileName+1)==
L':') {
00563
if (
IS_PATH_SEPARATOR_U(*(DosFileName+2))) {
00564 ReturnValue = RtlPathTypeDriveAbsolute;
00565 }
00566
else {
00567 ReturnValue = RtlPathTypeDriveRelative;
00568 }
00569 }
00570
else {
00571 ReturnValue = RtlPathTypeRelative;
00572 }
00573
return ReturnValue;
00574 }
00575
00576 ULONG
00577 RtlIsDosDeviceName_Ustr(
00578 IN PUNICODE_STRING DosFileName
00579 )
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 {
00615 UNICODE_STRING UnicodeString;
00616
USHORT NumberOfCharacters;
00617 ULONG ReturnLength;
00618 ULONG ReturnOffset;
00619 LPWSTR p;
00620
USHORT ColonBias;
00621 RTL_PATH_TYPE PathType;
00622 WCHAR wch;
00623
00624 ColonBias = 0;
00625
00626 PathType =
RtlDetermineDosPathNameType_U(DosFileName->Buffer);
00627
switch ( PathType ) {
00628
00629
case RtlPathTypeLocalDevice:
00630
00631
00632
00633
00634
00635
if (
RtlEqualUnicodeString(DosFileName,&
RtlpDosSlashCONDevice,
TRUE) ) {
00636
return 0x00080006;
00637 }
00638
00639
00640
00641
00642
00643
case RtlPathTypeUncAbsolute:
00644
case RtlPathTypeUnknown:
00645
return 0;
00646 }
00647
00648 UnicodeString = *DosFileName;
00649 NumberOfCharacters = DosFileName->Length >> 1;
00650
00651
if (NumberOfCharacters && DosFileName->Buffer[NumberOfCharacters-1] ==
L':') {
00652 UnicodeString.Length -=
sizeof(WCHAR);
00653 NumberOfCharacters--;
00654 ColonBias = 1;
00655 }
00656
00657
00658
00659
00660
00661
00662
if ( NumberOfCharacters == 0 ) {
00663
return 0;
00664 }
00665
00666 wch = UnicodeString.Buffer[NumberOfCharacters-1];
00667
while ( NumberOfCharacters && (wch ==
L'.' || wch ==
L' ') ) {
00668 UnicodeString.Length -=
sizeof(WCHAR);
00669 NumberOfCharacters--;
00670 ColonBias++;
00671 wch = UnicodeString.Buffer[NumberOfCharacters-1];
00672 }
00673
00674 ReturnLength = NumberOfCharacters << 1;
00675
00676
00677
00678
00679
00680
00681
00682 ReturnOffset = 0;
00683
if ( NumberOfCharacters ) {
00684 p = UnicodeString.Buffer + NumberOfCharacters-1;
00685
while ( p >= UnicodeString.Buffer ) {
00686
if ( *p ==
L'\\' || *p ==
L'/'
00687 || (*p ==
L':' && p == UnicodeString.Buffer + 1)) {
00688 p++;
00689
00690
00691
00692
00693
00694
00695
00696 wch = (*p) | 0x20;
00697
00698
00699
00700
00701
00702
00703
if ( !(wch ==
L'l' || wch ==
L'c' || wch ==
L'p' || wch ==
L'a'
00704 || wch ==
L'n')
00705 ) {
00706
return 0;
00707 }
00708 ReturnOffset = (ULONG)((PSZ)p - (PSZ)UnicodeString.Buffer);
00709
RtlInitUnicodeString(&UnicodeString,p);
00710 NumberOfCharacters = UnicodeString.Length >> 1;
00711 NumberOfCharacters -= ColonBias;
00712 ReturnLength = NumberOfCharacters << 1;
00713 UnicodeString.Length -= ColonBias*
sizeof(WCHAR);
00714
break;
00715 }
00716 p--;
00717 }
00718
00719 wch = UnicodeString.Buffer[0] | 0x20;
00720
00721
00722
00723
00724
00725
00726
if ( !( wch ==
L'l' || wch ==
L'c' || wch ==
L'p' || wch ==
L'a'
00727 || wch ==
L'n' ) ) {
00728
return 0;
00729 }
00730 }
00731
00732
00733
00734
00735
00736
00737
00738 p = UnicodeString.Buffer;
00739
while (p < UnicodeString.Buffer + NumberOfCharacters && *p !=
L'.' && *p !=
L':') {
00740 p++;
00741 }
00742
00743
00744
00745
00746
00747
00748
while (p > UnicodeString.Buffer && p[-1] ==
L' ') {
00749 p--;
00750 }
00751
00752
00753
00754
00755
00756
00757 NumberOfCharacters = (
USHORT)(p - UnicodeString.Buffer);
00758 UnicodeString.Length = NumberOfCharacters *
sizeof( WCHAR );
00759
00760
if ( NumberOfCharacters == 4 && iswdigit(UnicodeString.Buffer[3] ) ) {
00761
if ( (WCHAR)UnicodeString.Buffer[3] ==
L'0') {
00762
return 0;
00763 }
else {
00764 UnicodeString.Length -=
sizeof(WCHAR);
00765
if (
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosLPTDevice,
TRUE) ||
00766
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosCOMDevice,
TRUE) ) {
00767 ReturnLength = NumberOfCharacters << 1;
00768 }
else {
00769
return 0;
00770 }
00771 }
00772 }
else if ( NumberOfCharacters != 3 ) {
00773
return 0;
00774 }
else if (
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosPRNDevice,
TRUE) ) {
00775 ReturnLength = NumberOfCharacters << 1;
00776 }
else if (
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosAUXDevice,
TRUE) ) {
00777 ReturnLength = NumberOfCharacters << 1;
00778 }
else if (
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosNULDevice,
TRUE) ) {
00779 ReturnLength = NumberOfCharacters << 1;
00780 }
else if (
RtlEqualUnicodeString(&UnicodeString,&
RtlpDosCONDevice,
TRUE) ) {
00781 ReturnLength = NumberOfCharacters << 1;
00782 }
else {
00783
return 0;
00784 }
00785
00786
return ReturnLength | (ReturnOffset << 16);
00787 }
00788
00789 ULONG
00790 RtlIsDosDeviceName_U(
00791 IN PWSTR DosFileName
00792 )
00793 {
00794 UNICODE_STRING UnicodeString;
00795
00796
RtlInitUnicodeString(&UnicodeString,DosFileName);
00797
00798
return RtlIsDosDeviceName_Ustr(&UnicodeString);
00799 }
00800
00801 BOOLEAN
00802 RtlpCheckDeviceName(
00803 PUNICODE_STRING DevName,
00804 ULONG DeviceNameOffset
00805 )
00806 {
00807
00808 BOOLEAN NameInvalid;
00809 PWSTR DevPath;
00810
00811 DevPath =
RtlAllocateHeap(RtlProcessHeap(), 0,DevName->Length);
00812
if (!DevPath) {
00813
return FALSE;
00814 }
00815
00816 NameInvalid =
TRUE;
00817
try {
00818
00819 RtlCopyMemory(DevPath,DevName->Buffer,DevName->Length);
00820 DevPath[DeviceNameOffset>>1]=
L'.';
00821 DevPath[(DeviceNameOffset>>1)+1]=UNICODE_NULL;
00822
00823
if (
RtlDoesFileExists_U(DevPath) ) {
00824 NameInvalid =
FALSE;
00825 }
00826
else {
00827 NameInvalid =
TRUE;
00828 }
00829
00830 }
00831 finally {
00832
RtlFreeHeap(RtlProcessHeap(), 0, DevPath);
00833 }
00834
return NameInvalid;
00835 }
00836
00837
00838
VOID
00839 RtlpValidateCurrentDirectory(
00840 PCURDIR CurDir
00841 )
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 {
00863
NTSTATUS FsCtlStatus;
00864 IO_STATUS_BLOCK IoStatusBlock;
00865 WCHAR TrimmedPath[4];
00866 UNICODE_STRING str;
00867
00868
00869
00870
00871
00872
00873
00874
00875 FsCtlStatus =
NtFsControlFile(
00876 CurDir->Handle,
00877
NULL,
00878
NULL,
00879
NULL,
00880 &IoStatusBlock,
00881 FSCTL_IS_VOLUME_MOUNTED,
00882
NULL,
00883 0,
00884
NULL,
00885 0
00886 );
00887
00888
if ( FsCtlStatus == STATUS_WRONG_VOLUME || FsCtlStatus == STATUS_VOLUME_DISMOUNTED) {
00889
00890
00891
00892
00893
00894
00895
NtClose( CurDir->Handle );
00896 CurDir->Handle =
NULL;
00897
00898 FsCtlStatus =
RtlSetCurrentDirectory_U(&CurDir->DosPath);
00899
if ( !
NT_SUCCESS(FsCtlStatus) ) {
00900
00901 TrimmedPath[0] = CurDir->DosPath.Buffer[0];
00902 TrimmedPath[1] = CurDir->DosPath.Buffer[1];
00903 TrimmedPath[2] = CurDir->DosPath.Buffer[2];
00904 TrimmedPath[3] = UNICODE_NULL;
00905
RtlpResetDriveEnvironment( TrimmedPath[0] );
00906
RtlInitUnicodeString( &str, TrimmedPath );
00907
00908
00909
00910
00911
00912
00913 (
VOID)
RtlSetCurrentDirectory_U( &str );
00914 }
00915 }
00916 }
00917
00918
00919 ULONG
00920 RtlGetFullPathName_Ustr(
00921 PUNICODE_STRING FileName,
00922 ULONG nBufferLength,
00923 PWSTR lpBuffer,
00924 PWSTR *lpFilePart OPTIONAL,
00925 PBOOLEAN NameInvalid,
00926 RTL_PATH_TYPE *InputPathType
00927 )
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 {
00964 ULONG DeviceNameLength;
00965 ULONG DeviceNameOffset;
00966 ULONG PrefixSourceLength;
00967 LONG PathNameLength;
00968 UCHAR CurDrive, NewDrive;
00969 WCHAR EnvVarNameBuffer[4];
00970 UNICODE_STRING EnvVarName;
00971 PWSTR Source,Dest;
00972 UNICODE_STRING Prefix;
00973 PCURDIR CurDir;
00974 ULONG MaximumLength;
00975 UNICODE_STRING FullPath;
00976 ULONG BackupIndex;
00977 RTL_PATH_TYPE PathType;
00978
NTSTATUS Status;
00979 BOOLEAN StripTrailingSlash;
00980 UNICODE_STRING UnicodeString;
00981 ULONG NumberOfCharacters;
00982 PWSTR lpFileName;
00983 WCHAR wch;
00984 ULONG i,j;
00985
00986
if ( ARGUMENT_PRESENT(NameInvalid) ) {
00987 *NameInvalid =
FALSE;
00988 }
00989
00990
if ( nBufferLength > MAXUSHORT ) {
00991 nBufferLength = MAXUSHORT-2;
00992 }
00993
00994 *InputPathType = RtlPathTypeUnknown;
00995
00996 UnicodeString = *
FileName;
00997 lpFileName = UnicodeString.Buffer;
00998
00999 NumberOfCharacters = UnicodeString.Length >> 1;
01000 PathNameLength = UnicodeString.Length;
01001
01002
if ( PathNameLength == 0 || UnicodeString.Buffer[0] == UNICODE_NULL ) {
01003
return 0;
01004 }
01005
else {
01006
01007
01008
01009
01010 DeviceNameLength = PathNameLength;
01011 wch = UnicodeString.Buffer[(DeviceNameLength>>1) - 1];
01012
while ( DeviceNameLength && wch ==
L' ' ) {
01013 DeviceNameLength -=
sizeof(WCHAR);
01014
if ( DeviceNameLength ) {
01015 wch = UnicodeString.Buffer[(DeviceNameLength>>1) - 1];
01016 }
01017 }
01018
if ( !DeviceNameLength ) {
01019
return 0;
01020 }
01021 }
01022
01023
if ( lpFileName[NumberOfCharacters-1] ==
L'\\' || lpFileName[NumberOfCharacters-1] ==
L'/' ) {
01024 StripTrailingSlash =
FALSE;
01025 }
01026
else {
01027 StripTrailingSlash =
TRUE;
01028 }
01029
01030
01031
01032
01033
01034
01035 DeviceNameLength =
RtlIsDosDeviceName_Ustr(&UnicodeString);
01036
if ( DeviceNameLength ) {
01037
01038
if ( ARGUMENT_PRESENT( lpFilePart ) ) {
01039 *lpFilePart =
NULL;
01040 }
01041
01042 DeviceNameOffset = DeviceNameLength >> 16;
01043 DeviceNameLength &= 0x0000ffff;
01044
01045
if ( ARGUMENT_PRESENT(NameInvalid) && DeviceNameOffset ) {
01046
if (
RtlpCheckDeviceName(&UnicodeString,DeviceNameOffset) ) {
01047 *NameInvalid =
TRUE;
01048
return 0;
01049 }
01050 }
01051
01052 PathNameLength = DeviceNameLength +
RtlpSlashSlashDot.Length;
01053
if ( PathNameLength < (LONG)nBufferLength ) {
01054 RtlMoveMemory(
01055 lpBuffer,
01056
RtlpSlashSlashDot.Buffer,
01057
RtlpSlashSlashDot.Length
01058 );
01059 RtlMoveMemory(
01060 (PVOID)((PUCHAR)lpBuffer+
RtlpSlashSlashDot.Length),
01061 (PSZ)lpFileName+DeviceNameOffset,
01062 DeviceNameLength
01063 );
01064
01065 RtlZeroMemory(
01066 (PVOID)((PUCHAR)lpBuffer+
RtlpSlashSlashDot.Length+DeviceNameLength),
01067
sizeof(UNICODE_NULL)
01068 );
01069
01070
return PathNameLength;
01071 }
01072
else {
01073
return PathNameLength+
sizeof(UNICODE_NULL);
01074 }
01075 }
01076
01077
01078
01079
01080
01081 FullPath.MaximumLength = (
USHORT)nBufferLength;
01082 FullPath.Length = 0;
01083 FullPath.Buffer = lpBuffer;
01084 RtlZeroMemory(lpBuffer,nBufferLength);
01085
01086
01087
01088
01089 CurDir = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
01090
01091
01092
01093
01094
01095
01096 *InputPathType = PathType =
RtlDetermineDosPathNameType_U(lpFileName);
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
RtlAcquirePebLock();
01113
try {
01114
01115
01116
01117
01118
01119 Source = lpFileName;
01120 PrefixSourceLength = 0;
01121 Prefix.Length = 0;
01122 Prefix.MaximumLength = 0;
01123 Prefix.Buffer =
NULL;
01124
01125
switch (PathType) {
01126
case RtlPathTypeUncAbsolute :
01127 {
01128 PWSTR UncPathPointer;
01129 ULONG NumberOfPathSeparators;
01130
01131
01132
01133
01134
01135
01136 UncPathPointer = lpFileName + 2;
01137 NumberOfPathSeparators = 0;
01138
while (*UncPathPointer) {
01139
if (
IS_PATH_SEPARATOR_U(*UncPathPointer)) {
01140
01141 NumberOfPathSeparators++;
01142
01143
if (NumberOfPathSeparators == 2) {
01144
break;
01145 }
01146 }
01147
01148 UncPathPointer++;
01149
01150 }
01151
01152 BackupIndex = (ULONG)(UncPathPointer - lpFileName);
01153
01154
01155
01156
01157
01158 PrefixSourceLength = BackupIndex << 1;
01159
01160 Source += BackupIndex;
01161
01162
01163
01164
01165
01166
01167 }
01168
break;
01169
01170
case RtlPathTypeLocalDevice :
01171
01172
01173
01174
01175
01176 PrefixSourceLength =
RtlpSlashSlashDot.Length;
01177 BackupIndex = 4;
01178 Source += BackupIndex;
01179 PathNameLength -= BackupIndex *
sizeof( WCHAR );
01180
01181
01182
01183
01184
01185
01186
break;
01187
01188
case RtlPathTypeRootLocalDevice :
01189
01190
01191
01192
01193
01194 Prefix =
RtlpSlashSlashDot;
01195 Prefix.Length = (
USHORT)(Prefix.Length - (
USHORT)(2*
sizeof(UNICODE_NULL)));
01196 PrefixSourceLength = Prefix.Length +
sizeof(UNICODE_NULL);
01197 BackupIndex = 3;
01198 Source += BackupIndex;
01199 PathNameLength -= BackupIndex *
sizeof( WCHAR );
01200
break;
01201
01202
case RtlPathTypeDriveAbsolute :
01203
01204 CurDrive = (UCHAR)
RtlUpcaseUnicodeChar( CurDir->DosPath.Buffer[0] );
01205 NewDrive = (UCHAR)
RtlUpcaseUnicodeChar( lpFileName[0] );
01206
if ( CurDrive == NewDrive ) {
01207
01208
RtlpValidateCurrentDirectory( CurDir );
01209
01210 }
01211
01212
01213
01214
01215
01216 BackupIndex = 3;
01217
break;
01218
01219
case RtlPathTypeDriveRelative :
01220
01221
01222
01223
01224
01225 CurDrive = (UCHAR)
RtlUpcaseUnicodeChar( CurDir->DosPath.Buffer[0] );
01226 NewDrive = (UCHAR)
RtlUpcaseUnicodeChar( lpFileName[0] );
01227
if ( CurDrive == NewDrive ) {
01228
01229
RtlpValidateCurrentDirectory( CurDir );
01230
01231 Prefix = *(PUNICODE_STRING)&CurDir->DosPath;
01232
01233 }
01234
01235
else {
01236
RtlpCheckRelativeDrive((WCHAR)NewDrive);
01237
01238 EnvVarNameBuffer[0] =
L'=';
01239 EnvVarNameBuffer[1] = (WCHAR)NewDrive;
01240 EnvVarNameBuffer[2] =
L':';
01241 EnvVarNameBuffer[3] = UNICODE_NULL;
01242
RtlInitUnicodeString(&EnvVarName,EnvVarNameBuffer);
01243
01244 Prefix = FullPath;
01245
Status =
RtlQueryEnvironmentVariable_U(
NULL,
01246 &EnvVarName,
01247 &Prefix
01248 );
01249
if ( !
NT_SUCCESS(
Status ) ) {
01250
if (
Status == STATUS_BUFFER_TOO_SMALL) {
01251
return (ULONG)(Prefix.Length) + PathNameLength + 2;
01252 }
01253
else {
01254
01255
01256
01257
01258 EnvVarNameBuffer[0] = (WCHAR)NewDrive;
01259 EnvVarNameBuffer[1] =
L':';
01260 EnvVarNameBuffer[2] =
L'\\';
01261 EnvVarNameBuffer[3] = UNICODE_NULL;
01262
RtlInitUnicodeString(&Prefix,EnvVarNameBuffer);
01263 }
01264 }
01265
else {
01266
01267 {
01268 ULONG LastChar;
01269
01270
01271
01272
01273
01274
01275 LastChar = Prefix.Length >> 1;
01276
01277
if (LastChar > 3) {
01278 Prefix.Buffer[ LastChar ] =
L'\\';
01279 Prefix.Length +=
sizeof(UNICODE_NULL);
01280 }
01281 }
01282
01283 }
01284 }
01285
01286 BackupIndex = 3;
01287 Source += 2;
01288 PathNameLength -= 2 *
sizeof( WCHAR );
01289
break;
01290
01291
case RtlPathTypeRooted :
01292 BackupIndex =
RtlpComputeBackupIndex(CurDir);
01293
if ( BackupIndex != 3 ) {
01294 Prefix = CurDir->DosPath;
01295 Prefix.Length = (
USHORT)(BackupIndex << 1);
01296 }
01297
else {
01298
01299
01300
01301
01302
01303 Prefix = CurDir->DosPath;
01304 Prefix.Length = 2*
sizeof(UNICODE_NULL);
01305 }
01306
break;
01307
01308
case RtlPathTypeRelative :
01309
01310
RtlpValidateCurrentDirectory( CurDir );
01311
01312
01313
01314
01315
01316 Prefix = CurDir->DosPath;
01317 BackupIndex =
RtlpComputeBackupIndex(CurDir);
01318
break;
01319
01320
default:
01321
return 0;
01322 }
01323
01324
01325
01326
01327
01328
01329
01330 MaximumLength = PathNameLength + Prefix.Length;
01331
01332
if ( MaximumLength >= nBufferLength ) {
01333
if ( (NumberOfCharacters > 1) ||
01334 (*lpFileName !=
L'.') ) {
01335
if ( PathType == RtlPathTypeRelative && NumberOfCharacters == 1 ) {
01336
return (ULONG)Prefix.Length -
sizeof(UNICODE_NULL);
01337 }
01338
return MaximumLength+
sizeof(UNICODE_NULL);
01339 }
01340
else {
01341
01342
01343
01344
01345
01346
if ( NumberOfCharacters == 1 && *lpFileName ==
L'.' ) {
01347
01348
01349
01350
01351
01352
if ( Prefix.Length == 6 ) {
01353
if ( nBufferLength <= Prefix.Length ) {
01354
return (ULONG)(Prefix.Length+(
USHORT)
sizeof(UNICODE_NULL));
01355 }
01356 }
01357
else {
01358
if ( nBufferLength < Prefix.Length ) {
01359
return (ULONG)Prefix.Length;
01360 }
01361
else {
01362
for(i=0,j=0;i<Prefix.Length;i+=
sizeof(WCHAR),j++){
01363
if ( Prefix.Buffer[j] ==
L'\\' ||
01364 Prefix.Buffer[j] ==
L'/' ) {
01365
01366 FullPath.Buffer[j] =
L'\\';
01367 }
01368
else {
01369 FullPath.Buffer[j] = Prefix.Buffer[j];
01370 }
01371 }
01372 FullPath.Length = Prefix.Length-(
USHORT)
sizeof(
L'\\');
01373
goto skipit;
01374 }
01375 }
01376 }
01377
else {
01378
return MaximumLength;
01379 }
01380 }
01381 }
01382
01383
if (PrefixSourceLength || Prefix.Buffer != FullPath.Buffer) {
01384
01385
01386
01387
01388
01389
01390
for(i=0,j=0;i<PrefixSourceLength;i+=
sizeof(WCHAR),j++){
01391
if ( lpFileName[j] ==
L'\\' ||
01392 lpFileName[j] ==
L'/' ) {
01393
01394 FullPath.Buffer[j] =
L'\\';
01395 }
01396
else {
01397 FullPath.Buffer[j] = lpFileName[j];
01398 }
01399 }
01400
01401 FullPath.Length = (
USHORT)PrefixSourceLength;
01402
01403
01404
01405
01406
01407
for(i=0,j=0;i<Prefix.Length;i+=
sizeof(WCHAR),j++){
01408
if ( Prefix.Buffer[j] ==
L'\\' ||
01409 Prefix.Buffer[j] ==
L'/' ) {
01410
01411 FullPath.Buffer[j+(FullPath.Length>>1)] =
L'\\';
01412 }
01413
else {
01414 FullPath.Buffer[j+(FullPath.Length>>1)] = Prefix.Buffer[j];
01415 }
01416 }
01417 FullPath.Length += Prefix.Length;
01418
01419 }
01420
else {
01421 FullPath.Length = Prefix.Length;
01422 }
01423 skipit:
01424 Dest = (PWSTR)((PUCHAR)FullPath.Buffer + FullPath.Length);
01425 *Dest = UNICODE_NULL;
01426
01427
while ( *Source ) {
01428
switch ( *Source ) {
01429
01430
case L'\\' :
01431
case L'/' :
01432
01433
01434
01435
01436
01437
if ( *(Dest-1) !=
L'\\' ) {
01438 *Dest++ =
L'\\';
01439 }
01440
01441 Source++;
01442
break;
01443
01444
case '.' :
01445
01446
01447
01448
01449
01450
01451
01452
if (
IS_DOT_U(Source) ) {
01453 Source++;
01454
if (
IS_PATH_SEPARATOR_U(*Source)) {
01455 Source++;
01456 }
01457
break;
01458 }
01459
else if (
IS_DOT_DOT_U(Source) ) {
01460
01461
01462
01463
01464
while (*Dest !=
L'\\') {
01465 *Dest = UNICODE_NULL;
01466 Dest--;
01467 }
01468
01469
01470
01471
01472
01473
01474
do {
01475
01476
01477
01478
01479
01480
01481
if ( Dest == FullPath.Buffer + (BackupIndex-1) ) {
01482
break;
01483 }
01484
01485 *Dest = UNICODE_NULL;
01486 Dest--;
01487
01488 }
while (*Dest !=
L'\\');
01489
if ( Dest == FullPath.Buffer + (BackupIndex-1) ) {
01490 Dest++;
01491 }
01492
01493
01494
01495
01496
01497 Source += 2;
01498
01499
break;
01500 }
01501
01502
01503
01504
01505
01506
default:
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
while ( *Source && !
IS_PATH_SEPARATOR_U(*Source) ) {
01521
if ( *Source ==
L'.' ) {
01522
01523
01524
01525
01526
01527
if (
IS_PATH_SEPARATOR_U(*(Source+1)) ) {
01528 Source++;
01529 }
01530
else {
01531 *Dest++ = *Source++;
01532 }
01533 }
01534
else {
01535 *Dest++ = *Source++;
01536 }
01537 }
01538 }
01539 }
01540
01541 *Dest = UNICODE_NULL;
01542
01543
if ( StripTrailingSlash ) {
01544
if ( Dest > (FullPath.Buffer + BackupIndex ) && *(Dest-1) ==
L'\\' ) {
01545 Dest--;
01546 *Dest = UNICODE_NULL;
01547 }
01548 }
01549 FullPath.Length = (
USHORT)(PtrToUlong(Dest) - PtrToUlong(FullPath.Buffer));
01550
01551
01552
01553
01554
01555 Source = Dest-1;
01556
while(Source > FullPath.Buffer ) {
01557
if ( *Source ==
L' ' || *Source ==
L'.' ) {
01558 *Source = UNICODE_NULL;
01559 Dest--;
01560 Source--;
01561 FullPath.Length -= 2;
01562 }
01563
else {
01564
break;
01565 }
01566 }
01567
01568
if ( ARGUMENT_PRESENT( lpFilePart ) ) {
01569
01570
01571
01572
01573
01574 Source = Dest-1;
01575 Dest =
NULL;
01576
01577
while(Source > FullPath.Buffer ) {
01578
if ( *Source ==
L'\\' ) {
01579 Dest = Source + 1;
01580
break;
01581 }
01582 Source--;
01583 }
01584
01585
if ( Dest && *Dest ) {
01586
01587
01588
01589
01590
if ( PathType == RtlPathTypeUncAbsolute ) {
01591
if ( Dest < (FullPath.Buffer + BackupIndex ) ) {
01592 *lpFilePart =
NULL;
01593 leave;
01594 }
01595 }
01596 *lpFilePart = Dest;
01597 }
01598
else {
01599 *lpFilePart =
NULL;
01600 }
01601 }
01602 }
01603 finally {
01604
RtlReleasePebLock();
01605 }
01606
01607
return (ULONG)FullPath.Length;
01608 }
01609
01610 ULONG
01611 RtlGetFullPathName_U(
01612 PCWSTR lpFileName,
01613 ULONG nBufferLength,
01614 PWSTR lpBuffer,
01615 PWSTR *lpFilePart OPTIONAL
01616 )
01617
01618 {
01619 UNICODE_STRING UnicodeString;
01620 RTL_PATH_TYPE PathType;
01621
01622
RtlInitUnicodeString(&UnicodeString,lpFileName);
01623
01624
return RtlGetFullPathName_Ustr(&UnicodeString,nBufferLength,lpBuffer,lpFilePart,
NULL,&PathType);
01625 }
01626
01627 BOOLEAN
01628 RtlpWin32NTNameToNtPathName_U(
01629 IN PUNICODE_STRING DosFileName,
01630 OUT PUNICODE_STRING NtFileName,
01631 OUT PWSTR *FilePart OPTIONAL,
01632 OUT PRTL_RELATIVE_NAME RelativeName OPTIONAL
01633 )
01634 {
01635
01636 PWSTR FullNtPathName =
NULL;
01637 PWSTR Source,Dest;
01638
01639 FullNtPathName =
RtlAllocateHeap(
01640 RtlProcessHeap(),
01641 0,
01642 DosFileName->Length-8+
sizeof(UNICODE_NULL)+
RtlpDosDevicesPrefix.Length
01643 );
01644
if ( !FullNtPathName ) {
01645
return FALSE;
01646 }
01647
01648
01649
01650
01651
01652
01653 RtlMoveMemory(FullNtPathName,
RtlpDosDevicesPrefix.Buffer,
RtlpDosDevicesPrefix.Length);
01654 RtlMoveMemory((PUCHAR)FullNtPathName+
RtlpDosDevicesPrefix.Length,
01655 DosFileName->Buffer + 4,
01656 DosFileName->Length - 8);
01657
01658
01659
01660
01661
01662
01663 NtFileName->Buffer = FullNtPathName;
01664 NtFileName->Length = (
USHORT)(DosFileName->Length-8+
RtlpDosDevicesPrefix.Length);
01665 NtFileName->MaximumLength = NtFileName->Length +
sizeof(UNICODE_NULL);
01666 FullNtPathName[ NtFileName->Length >> 1 ] = UNICODE_NULL;
01667
01668
01669
01670
01671
01672
01673
if ( ARGUMENT_PRESENT(
RelativeName) ) {
01674
01675
01676
01677
01678
01679
01680
01681
01682
RelativeName->RelativeName.Length = 0;
01683
RelativeName->RelativeName.MaximumLength = 0;
01684
RelativeName->RelativeName.Buffer = 0;
01685
RelativeName->ContainingDirectory =
NULL;
01686 }
01687
01688
if ( ARGUMENT_PRESENT( FilePart ) ) {
01689
01690
01691
01692
01693
01694 Source = &FullNtPathName[ (NtFileName->Length-1) >> 1 ];
01695 Dest =
NULL;
01696
01697
while(Source > FullNtPathName ) {
01698
if ( *Source ==
L'\\' ) {
01699 Dest = Source + 1;
01700
break;
01701 }
01702 Source--;
01703 }
01704
01705
if ( Dest && *Dest ) {
01706 *FilePart = Dest;
01707 }
01708
else {
01709 *FilePart =
NULL;
01710 }
01711 }
01712
01713
return TRUE;
01714 }
01715
01716 BOOLEAN
01717 RtlDosPathNameToNtPathName_U(
01718 IN PCWSTR DosFileName,
01719 OUT PUNICODE_STRING NtFileName,
01720 OUT PWSTR *FilePart OPTIONAL,
01721 OUT PRTL_RELATIVE_NAME RelativeName OPTIONAL
01722 )
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769 {
01770
01771 ULONG BufferLength;
01772 ULONG DosPathLength;
01773 PWSTR FullNtPathName =
NULL;
01774 PWSTR FullDosPathName =
NULL;
01775 UNICODE_STRING Prefix;
01776 UNICODE_STRING UnicodeFilePart;
01777 UNICODE_STRING FullDosPathString;
01778 PCURDIR CurDir;
01779 RTL_PATH_TYPE DosPathType;
01780 RTL_PATH_TYPE InputDosPathType;
01781 ULONG DosPathNameOffset;
01782 ULONG FullDosPathNameLength;
01783 ULONG LastCharacter;
01784 UNICODE_STRING UnicodeString;
01785 BOOLEAN NameInvalid;
01786 WCHAR StaticDosBuffer[DOS_MAX_PATH_LENGTH + 1];
01787 BOOLEAN UseWin32Name;
01788
01789
01790
01791
01792
01793
01794 BufferLength = (DOS_MAX_PATH_LENGTH << 1 ) +
sizeof(UNICODE_NULL);
01795 DosPathLength = (DOS_MAX_PATH_LENGTH << 1 );
01796
01797
if ( !BufferLength ) {
01798
return FALSE;
01799 }
01800
01801
01802
RtlInitUnicodeString(&UnicodeString,DosFileName);
01803
01804
01805
01806
01807
01808
if ( UnicodeString.Length > 8 && UnicodeString.Buffer[0] ==
'\\' &&
01809 UnicodeString.Buffer[1] ==
'\\' && UnicodeString.Buffer[2] ==
'?' &&
01810 UnicodeString.Buffer[3] ==
'\\' ) {
01811
01812 UseWin32Name =
TRUE;
01813 }
01814
else {
01815 UseWin32Name =
FALSE;
01816
01817
01818
01819
01820
01821 FullDosPathName = &StaticDosBuffer[0];
01822
01823 BufferLength +=
RtlpLongestPrefix;
01824
01825
01826
01827
01828
01829 FullNtPathName =
RtlAllocateHeap(RtlProcessHeap(), 0, BufferLength);
01830
01831
if ( !FullNtPathName ) {
01832
return FALSE;
01833 }
01834 }
01835
01836
RtlAcquirePebLock();
01837
try {
01838
01839
01840
if ( UseWin32Name ) {
01841
01842
if (
RtlpWin32NTNameToNtPathName_U(&UnicodeString,NtFileName,FilePart,
RelativeName)) {
01843
goto finally_exit;
01844 }
01845
else {
01846
return FALSE;
01847 }
01848
01849 }
01850
01851
01852 FullDosPathNameLength =
RtlGetFullPathName_Ustr(
01853 &UnicodeString,
01854 DosPathLength,
01855 FullDosPathName,
01856 FilePart,
01857 &NameInvalid,
01858 &InputDosPathType
01859 );
01860
01861
if ( NameInvalid || !FullDosPathNameLength ||
01862 FullDosPathNameLength > DosPathLength ) {
01863
return FALSE;
01864 }
01865
01866
01867
01868
01869
01870
01871
01872 Prefix =
RtlpDosDevicesPrefix;
01873
01874 DosPathType =
RtlDetermineDosPathNameType_U(FullDosPathName);
01875
01876
switch (DosPathType) {
01877
case RtlPathTypeUncAbsolute :
01878
01879
01880
01881
01882
01883
01884 Prefix =
RtlpDosDevicesUncPrefix;
01885 DosPathNameOffset = 2;
01886
break;
01887
01888
case RtlPathTypeLocalDevice :
01889
01890
01891
01892
01893
01894
01895 DosPathNameOffset = 4;
01896
break;
01897
01898
case RtlPathTypeRootLocalDevice :
01899
01900
ASSERT(
FALSE );
01901
break;
01902
01903
case RtlPathTypeDriveAbsolute :
01904
case RtlPathTypeDriveRelative :
01905
case RtlPathTypeRooted :
01906
case RtlPathTypeRelative :
01907
01908
01909
01910
01911
01912
01913 DosPathNameOffset = 0;
01914
break;
01915
01916
default:
01917
ASSERT(
FALSE );
01918 }
01919
01920
01921
01922
01923
01924
01925
01926 RtlMoveMemory(FullNtPathName,Prefix.Buffer,Prefix.Length);
01927 RtlMoveMemory((PUCHAR)FullNtPathName+Prefix.Length,
01928 FullDosPathName + DosPathNameOffset,
01929 FullDosPathNameLength - (DosPathNameOffset<<1));
01930
01931
01932
01933
01934
01935
01936 NtFileName->Buffer = FullNtPathName;
01937 NtFileName->Length = (
USHORT)(FullDosPathNameLength-(DosPathNameOffset<<1))+Prefix.Length;
01938 NtFileName->MaximumLength = (
USHORT)BufferLength;
01939 LastCharacter = NtFileName->Length >> 1;
01940 FullNtPathName[ LastCharacter ] = UNICODE_NULL;
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
if ( ARGUMENT_PRESENT(FilePart) ) {
01951
if (*FilePart) {
01952
RtlInitUnicodeString(&UnicodeFilePart,*FilePart);
01953 *FilePart = &FullNtPathName[ LastCharacter ] - (UnicodeFilePart.Length >> 1);
01954 }
01955 }
01956
01957
if ( ARGUMENT_PRESENT(
RelativeName) ) {
01958
01959
01960
01961
01962
01963
01964
01965
01966
RelativeName->RelativeName.Length = 0;
01967
RelativeName->RelativeName.MaximumLength = 0;
01968
RelativeName->RelativeName.Buffer = 0;
01969
RelativeName->ContainingDirectory =
NULL;
01970
01971
if ( InputDosPathType == RtlPathTypeRelative ) {
01972
01973 CurDir = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
01974
01975
if ( CurDir->Handle ) {
01976
01977
01978
01979
01980
01981
01982
01983
RtlInitUnicodeString(&FullDosPathString,FullDosPathName);
01984
if ( CurDir->DosPath.Length <= FullDosPathString.Length ) {
01985 FullDosPathString.Length = CurDir->DosPath.Length;
01986
if (
RtlEqualUnicodeString(
01987 (PUNICODE_STRING)&CurDir->DosPath,
01988 &FullDosPathString,
01989
TRUE
01990 ) ) {
01991
01992
01993
01994
01995
01996
01997
01998
RelativeName->RelativeName.Buffer = ((PUCHAR)FullNtPathName + Prefix.Length - (DosPathNameOffset<<1) + (CurDir->DosPath.Length));
01999
RelativeName->RelativeName.Length = (
USHORT)FullDosPathNameLength - (CurDir->DosPath.Length);
02000
if ( *(PWSTR)(
RelativeName->RelativeName.Buffer) ==
L'\\' ) {
02001 (PWSTR)(
RelativeName->RelativeName.Buffer)++;
02002
RelativeName->RelativeName.Length -= 2;
02003 }
02004
RelativeName->RelativeName.MaximumLength =
RelativeName->RelativeName.Length;
02005
RelativeName->ContainingDirectory = CurDir->Handle;
02006 }
02007 }
02008 }
02009 }
02010 }
02011 finally_exit:;
02012 }
02013 finally {
02014
02015
if ( AbnormalTermination() ) {
02016
if ( FullNtPathName ) {
02017
RtlFreeHeap(RtlProcessHeap(), 0, FullNtPathName);
02018 }
02019
02020
RtlReleasePebLock();
02021
02022
return FALSE;
02023 }
02024
02025
RtlReleasePebLock();
02026 }
02027
02028
return TRUE;
02029 }
02030
02031
02032 BOOLEAN
02033 RtlDoesFileExists_UEx(
02034 IN PCWSTR FileName,
02035 IN BOOLEAN TreatDeniedOrSharingAsHit
02036 )
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056 {
02057
NTSTATUS Status;
02058 OBJECT_ATTRIBUTES Obja;
02059 UNICODE_STRING NtFileName;
02060 BOOLEAN ReturnValue;
02061 RTL_RELATIVE_NAME
RelativeName;
02062 PVOID FreeBuffer;
02063 FILE_BASIC_INFORMATION BasicInfo;
02064
02065 ReturnValue =
RtlDosPathNameToNtPathName_U(
02066
FileName,
02067 &NtFileName,
02068
NULL,
02069 &
RelativeName
02070 );
02071
02072
if ( !ReturnValue ) {
02073
return FALSE;
02074 }
02075
02076 FreeBuffer = NtFileName.Buffer;
02077
02078
if (
RelativeName.RelativeName.Length ) {
02079 NtFileName = *(PUNICODE_STRING)&
RelativeName.RelativeName;
02080 }
02081
else {
02082
RelativeName.ContainingDirectory =
NULL;
02083 }
02084
02085 InitializeObjectAttributes(
02086 &Obja,
02087 &NtFileName,
02088 OBJ_CASE_INSENSITIVE,
02089
RelativeName.ContainingDirectory,
02090
NULL
02091 );
02092
02093
02094
02095
02096
02097
02098
02099
02100
Status =
NtQueryAttributesFile(
02101 &Obja,
02102 &BasicInfo
02103 );
02104
RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
02105
02106
if ( !
NT_SUCCESS(
Status) ) {
02107
if (
Status == STATUS_SHARING_VIOLATION ||
02108
Status == STATUS_ACCESS_DENIED ) {
02109
if ( TreatDeniedOrSharingAsHit ) {
02110 ReturnValue =
TRUE;
02111 }
02112
else {
02113 ReturnValue =
FALSE;
02114 }
02115 }
02116
else {
02117 ReturnValue =
FALSE;
02118 }
02119 }
02120
else {
02121 ReturnValue =
TRUE;
02122 }
02123
return ReturnValue;
02124 }
02125
02126
02127 BOOLEAN
02128 RtlDoesFileExists_U(
02129 IN PCWSTR FileName
02130 )
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150 {
02151
02152
return RtlDoesFileExists_UEx(
FileName,
TRUE);
02153 }
02154
02155 ULONG
02156 RtlDosSearchPath_U(
02157 IN PWSTR lpPath,
02158 IN PWSTR lpFileName,
02159 IN PWSTR lpExtension OPTIONAL,
02160 IN ULONG nBufferLength,
02161 OUT PWSTR lpBuffer,
02162 OUT PWSTR *lpFilePart
02163 )
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209 {
02210
02211 PWSTR ComputedFileName;
02212 ULONG ExtensionLength;
02213 ULONG PathLength;
02214 ULONG FileLength;
02215 PWSTR p;
02216 UNICODE_STRING Scratch;
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
if (
RtlDetermineDosPathNameType_U(lpFileName) != RtlPathTypeRelative ) {
02233
if (
RtlDoesFileExists_UEx(lpFileName,
TRUE) ) {
02234 PathLength =
RtlGetFullPathName_U(
02235 lpFileName,
02236 nBufferLength,
02237 lpBuffer,
02238 lpFilePart
02239 );
02240
return PathLength;
02241 }
02242
else {
02243
return 0;
02244 }
02245 }
02246
02247
02248
02249
02250
02251 ExtensionLength = 1;
02252 p = lpFileName;
02253
while (*p) {
02254
if ( *p ==
L'.' ) {
02255 ExtensionLength = 0;
02256
break;
02257 }
02258 p++;
02259 }
02260
02261
02262
02263
02264
02265
02266
if ( ExtensionLength ) {
02267
if ( ARGUMENT_PRESENT(lpExtension) ) {
02268
RtlInitUnicodeString(&Scratch,lpExtension);
02269 ExtensionLength = Scratch.Length;
02270 }
02271
else {
02272 ExtensionLength = 0;
02273 }
02274 }
02275
02276
02277
02278
02279
02280
RtlInitUnicodeString(&Scratch,lpPath);
02281 PathLength = Scratch.Length;
02282
RtlInitUnicodeString(&Scratch,lpFileName);
02283 FileLength = Scratch.Length;
02284
02285 ComputedFileName =
RtlAllocateHeap(
02286 RtlProcessHeap(), 0,
02287 PathLength + FileLength + ExtensionLength + 3*
sizeof(UNICODE_NULL)
02288 );
02289
02290
if ( !ComputedFileName ) {
02291
return 0;
02292 }
02293
02294
02295
02296
02297
02298
do {
02299 p = ComputedFileName;
02300
while (*lpPath) {
02301
if (*lpPath ==
L';') {
02302 lpPath++;
02303
break;
02304 }
02305 *p++ = *lpPath++;
02306 }
02307
02308
if (p != ComputedFileName &&
02309 p [ -1 ] !=
L'\\' ) {
02310 *p++ =
L'\\';
02311 }
02312
if (*lpPath == UNICODE_NULL) {
02313 lpPath =
NULL;
02314 }
02315 RtlMoveMemory(p,lpFileName,FileLength);
02316
if ( ExtensionLength ) {
02317 RtlMoveMemory((PUCHAR)p+FileLength,lpExtension,ExtensionLength+
sizeof(UNICODE_NULL));
02318 }
02319
else {
02320 *(PWSTR)((PUCHAR)p+FileLength) = UNICODE_NULL;
02321 }
02322
02323
if (
RtlDoesFileExists_UEx(ComputedFileName,
FALSE) ) {
02324 PathLength =
RtlGetFullPathName_U(
02325 ComputedFileName,
02326 nBufferLength,
02327 lpBuffer,
02328 lpFilePart
02329 );
02330
RtlFreeHeap(RtlProcessHeap(), 0, ComputedFileName);
02331
return PathLength;
02332 }
02333 }
02334
while ( lpPath );
02335
02336
RtlFreeHeap(RtlProcessHeap(), 0, ComputedFileName);
02337
return 0;
02338 }
02339
02340
VOID
02341 RtlpCheckRelativeDrive(
02342 WCHAR NewDrive
02343 )
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365 {
02366
02367 WCHAR EnvVarValueBuffer[DOS_MAX_PATH_LENGTH+12];
02368 WCHAR EnvVarNameBuffer[4];
02369 UNICODE_STRING EnvVarName;
02370 UNICODE_STRING EnvValue;
02371
NTSTATUS Status;
02372 OBJECT_ATTRIBUTES Obja;
02373 IO_STATUS_BLOCK IoStatusBlock;
02374 HANDLE DirHandle;
02375 ULONG HardErrorValue;
02376 PTEB Teb;
02377
02378 EnvVarNameBuffer[0] =
L'=';
02379 EnvVarNameBuffer[1] = (WCHAR)NewDrive;
02380 EnvVarNameBuffer[2] =
L':';
02381 EnvVarNameBuffer[3] = UNICODE_NULL;
02382
RtlInitUnicodeString(&EnvVarName,EnvVarNameBuffer);
02383
02384
02385
02386
02387
02388
02389
02390 EnvValue.Length = 0;
02391 EnvValue.MaximumLength = DOS_MAX_PATH_LENGTH<<1;
02392 EnvValue.Buffer = &EnvVarValueBuffer[
RtlpDosDevicesPrefix.Length>>1];
02393
02394
Status =
RtlQueryEnvironmentVariable_U(
NULL,
02395 &EnvVarName,
02396 &EnvValue
02397 );
02398
if ( !
NT_SUCCESS(
Status ) ) {
02399
02400
02401
02402
02403
02404 EnvValue.Buffer[0] = (WCHAR)NewDrive;
02405 EnvValue.Buffer[1] =
L':';
02406 EnvValue.Buffer[2] =
L'\\';
02407 EnvValue.Buffer[3] = UNICODE_NULL;
02408 EnvValue.Length = 6;
02409 }
02410
02411
02412
02413
02414
02415 EnvValue.Length = EnvValue.Length +
RtlpDosDevicesPrefix.Length;
02416 EnvValue.MaximumLength =
sizeof(EnvValue);
02417 EnvValue.Buffer = EnvVarValueBuffer;
02418 RtlCopyMemory(EnvVarValueBuffer,
RtlpDosDevicesPrefix.Buffer,
RtlpDosDevicesPrefix.Length);
02419
02420 InitializeObjectAttributes(
02421 &Obja,
02422 &EnvValue,
02423 OBJ_CASE_INSENSITIVE,
02424
NULL,
02425
NULL
02426 );
02427
02428
02429 Teb = NtCurrentTeb();
02430 HardErrorValue = Teb->HardErrorsAreDisabled;
02431 Teb->HardErrorsAreDisabled = 1;
02432
02433
Status =
NtOpenFile(
02434 &DirHandle,
02435 SYNCHRONIZE,
02436 &Obja,
02437 &IoStatusBlock,
02438 FILE_SHARE_READ | FILE_SHARE_WRITE,
02439 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
02440 );
02441
02442 Teb->HardErrorsAreDisabled = HardErrorValue;
02443
02444
02445
02446
02447
02448
02449
if (
NT_SUCCESS(
Status) ) {
02450
NtClose(DirHandle);
02451
return;
02452 }
02453
02454
RtlpResetDriveEnvironment(NewDrive);
02455 }