test: curdir.c File Reference

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

# curdir.c File Reference

`#include "nt.h"`
`#include "ntrtl.h"`
`#include "nturtl.h"`
`#include "string.h"`
`#include "ctype.h"`

Go to the source code of this file.

## Defines

#define | IS_PATH_SEPARATOR_U(ch) ((ch == L'\\') || (ch == L'/'))
#define | IS_DOT_U(s) ( s[0] == L'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) )
#define | IS_DOT_DOT_U(s) ( s[0] == L'.' && s[1] == L'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) )
#define | CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
#define | RtlpLongestPrefix RtlpDosDevicesUncPrefix.Length

## Functions

VOID | RtlpCheckRelativeDrive (WCHAR NewDrive)
ULONG | RtlIsDosDeviceName_Ustr (IN PUNICODE_STRING DosFileName)
ULONG | RtlGetFullPathName_Ustr (PUNICODE_STRING FileName, ULONG nBufferLength, PWSTR lpBuffer, PWSTR *lpFilePart OPTIONAL, PBOOLEAN NameInvalid, RTL_PATH_TYPE *InputPathType)
ULONG | RtlpComputeBackupIndex (IN PCURDIR CurDir)
ULONG | RtlGetLongestNtPathLength (VOID)
VOID | RtlpResetDriveEnvironment (IN WCHAR DriveLetter)
ULONG | RtlGetCurrentDirectory_U (ULONG nBufferLength, PWSTR lpBuffer)
NTSTATUS | RtlSetCurrentDirectory_U (PUNICODE_STRING PathName)
RTL_PATH_TYPE | RtlDetermineDosPathNameType_U (IN PCWSTR DosFileName)
ULONG | RtlIsDosDeviceName_U (IN PWSTR DosFileName)
BOOLEAN | RtlpCheckDeviceName (PUNICODE_STRING DevName, ULONG DeviceNameOffset)
VOID | RtlpValidateCurrentDirectory (PCURDIR CurDir)
ULONG | RtlGetFullPathName_U (PCWSTR lpFileName, ULONG nBufferLength, PWSTR lpBuffer, PWSTR *lpFilePart OPTIONAL)
BOOLEAN | RtlpWin32NTNameToNtPathName_U (IN PUNICODE_STRING DosFileName, OUT PUNICODE_STRING NtFileName, OUT PWSTR *FilePart OPTIONAL, OUT PRTL_RELATIVE_NAME RelativeName OPTIONAL)
BOOLEAN | RtlDosPathNameToNtPathName_U (IN PCWSTR DosFileName, OUT PUNICODE_STRING NtFileName, OUT PWSTR *FilePart OPTIONAL, OUT PRTL_RELATIVE_NAME RelativeName OPTIONAL)
BOOLEAN | RtlDoesFileExists_UEx (IN PCWSTR FileName, IN BOOLEAN TreatDeniedOrSharingAsHit)
BOOLEAN | RtlDoesFileExists_U (IN PCWSTR FileName)
ULONG | RtlDosSearchPath_U (IN PWSTR lpPath, IN PWSTR lpFileName, IN PWSTR lpExtension OPTIONAL, IN ULONG nBufferLength, OUT PWSTR lpBuffer, OUT PWSTR *lpFilePart)

## Variables

const UNICODE_STRING | RtlpDosLPTDevice = CONSTANT_UNICODE_STRING( L"LPT" )
const UNICODE_STRING | RtlpDosCOMDevice = CONSTANT_UNICODE_STRING( L"COM" )
const UNICODE_STRING | RtlpDosPRNDevice = CONSTANT_UNICODE_STRING( L"PRN" )
const UNICODE_STRING | RtlpDosAUXDevice = CONSTANT_UNICODE_STRING( L"AUX" )
const UNICODE_STRING | RtlpDosNULDevice = CONSTANT_UNICODE_STRING( L"NUL" )
const UNICODE_STRING | RtlpDosCONDevice = CONSTANT_UNICODE_STRING( L"CON" )
const UNICODE_STRING | RtlpDosSlashCONDevice = CONSTANT_UNICODE_STRING( L"\\\\.\\CON" )
const UNICODE_STRING | RtlpSlashSlashDot = CONSTANT_UNICODE_STRING( L"\\\\.\\" )
const UNICODE_STRING | RtlpDosDevicesPrefix = CONSTANT_UNICODE_STRING( L"\\??\\" )
const UNICODE_STRING | RtlpDosDevicesUncPrefix = CONSTANT_UNICODE_STRING( L"\\??\\UNC\\" )

## Define Documentation

#define CONSTANT_UNICODE_STRING | ( | s |  | ) | { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }

| Definition at line 51 of file curdir.c.

#define IS_DOT_DOT_U | ( | s |  | ) | ( s[0] == L'.' && s[1] == L'.' && ( IS_PATH_SEPARATOR_U(s[2]) || s[2] == UNICODE_NULL) )

| Definition at line 29 of file curdir.c. Referenced by RtlGetFullPathName_Ustr().

#define IS_DOT_U | ( | s |  | ) | ( s[0] == L'.' && ( IS_PATH_SEPARATOR_U(s[1]) || s[1] == UNICODE_NULL) )

| Definition at line 28 of file curdir.c. Referenced by RtlGetFullPathName_Ustr().

#define IS_PATH_SEPARATOR_U | ( | ch |  | ) | ((ch == L'\\') || (ch == L'/'))

| Definition at line 27 of file curdir.c. Referenced by RtlDetermineDosPathNameType_U(), RtlGetFullPathName_Ustr(), and RtlpComputeBackupIndex().

#define RtlpLongestPrefix RtlpDosDevicesUncPrefix.Length

| Definition at line 65 of file curdir.c. Referenced by RtlDosPathNameToNtPathName_U(), and RtlGetLongestNtPathLength().

## Function Documentation

RTL_PATH_TYPE RtlDetermineDosPathNameType_U | ( | IN PCWSTR | DosFileName | ) |

Definition at line 493 of file curdir.c.

References IS_PATH_SEPARATOR_U, and L.

Referenced by RtlDosPathNameToNtPathName_U(), RtlDosSearchPath_U(), RtlGetFullPathName_Ustr(), RtlIsDosDeviceName_Ustr(), and RtlpComputeBackupIndex().

    00499                    :
    00500
    00501     This function examines the Dos format file name and determines the
    00502     type of file name (i.e.  UNC, DriveAbsolute, Current Directory
    00503     rooted, or Relative.
    00504
    00505 Arguments:
    00506
    00507     DosFileName - Supplies the Dos format file name whose type is to be
    00508         determined.
    00509
    00510 Return Value:
    00511
    00512     RtlPathTypeUnknown - The path type can not be determined
    00513
    00514     RtlPathTypeUncAbsolute - The path specifies a Unc absolute path
    00515         in the format \\server-name\sharename\rest-of-path
    00516
    00517     RtlPathTypeLocalDevice - The path specifies a local device in the format
    00518         \\.\rest-of-path this can be used for any device where the nt and
    00519         Win32 names are the same. For example mailslots.
    00520
    00521     RtlPathTypeRootLocalDevice - The path specifies the root of the local
    00522         devices in the format \\.
    00523
    00524     RtlPathTypeDriveAbsolute - The path specifies a drive letter absolute
    00525         path in the form drive:\rest-of-path
    00526
    00527     RtlPathTypeDriveRelative - The path specifies a drive letter relative
    00528         path in the form drive:rest-of-path
    00529
    00530     RtlPathTypeRooted - The path is rooted relative to the current disk
    00531         designator (either Unc disk, or drive). The form is \rest-of-path.
    00532
    00533     RtlPathTypeRelative - The path is relative (i.e. not absolute or rooted).
    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 }

BOOLEAN RtlDoesFileExists_U | ( | IN PCWSTR | FileName | ) |

Definition at line 2128 of file curdir.c.

References FileName, RtlDoesFileExists_UEx(), and TRUE.

Referenced by RtlpCheckDeviceName().

    02134                    :
    02135
    02136     This function checks to see if the specified unicode filename exists.
    02137
    02138 Arguments:
    02139
    02140     FileName - Supplies the file name of the file to find.
    02141
    02142 Return Value:
    02143
    02144     TRUE - The file was found.
    02145
    02146     FALSE - The file was not found.
    02147
    02148 --*/
    02149
    02150 {
    02151
    02152     return RtlDoesFileExists_UEx(FileName,TRUE);
    02153 }

BOOLEAN RtlDoesFileExists_UEx | ( | IN PCWSTR | FileName,
|  | IN BOOLEAN | TreatDeniedOrSharingAsHit
| ) |

Definition at line 2033 of file curdir.c.

References FALSE, FileName, NT_SUCCESS, NtQueryAttributesFile(), NTSTATUS(), NULL, RelativeName, RtlDosPathNameToNtPathName_U(), RtlFreeHeap, Status, and TRUE.

Referenced by RtlDoesFileExists_U(), and RtlDosSearchPath_U().

    02040                    :
    02041
    02042     This function checks to see if the specified unicode filename exists.
    02043
    02044 Arguments:
    02045
    02046     FileName - Supplies the file name of the file to find.
    02047
    02048 Return Value:
    02049
    02050     TRUE - The file was found.
    02051
    02052     FALSE - The file was not found.
    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     // Query the file's attributes.  Note that the file cannot simply be opened
    02095     // to determine whether or not it exists, as the NT LanMan redirector lies
    02096     // on NtOpenFile to a Lan Manager server because it does not actually open
    02097     // the file until an operation is performed on it.
    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 }

BOOLEAN RtlDosPathNameToNtPathName_U | ( | IN PCWSTR | DosFileName,
|  | OUT PUNICODE_STRING | NtFileName,
|  | OUT PWSTR *FilePart | OPTIONAL,
|  | OUT PRTL_RELATIVE_NAME RelativeName | OPTIONAL
| ) |

Definition at line 1717 of file curdir.c.

References ASSERT, FALSE, L, NULL, RelativeName, RtlAcquirePebLock(), RtlAllocateHeap, RtlDetermineDosPathNameType_U(), RtlEqualUnicodeString(), RtlFreeHeap, RtlGetFullPathName_Ustr(), RtlInitUnicodeString(), RtlpDosDevicesPrefix, RtlpDosDevicesUncPrefix, RtlpLongestPrefix, RtlpWin32NTNameToNtPathName_U(), RtlReleasePebLock(), TRUE, and USHORT.

Referenced by LdrLoadAlternateResourceModule(), LdrpCheckForLoadedDll(), LdrpMapDll(), main(), processargs(), RegReadMultiSzFile(), RtlDoesFileExists_UEx(), and RtlSetCurrentDirectory_U().

    01726                    :
    01727
    01728     A Dos pathname can be translated into an Nt style pathname
    01729     using this function.
    01730
    01731     This function is used only within the Base dll to translate Dos
    01732     pathnames to Nt pathnames. Upon successful translation, the
    01733     pointer (NtFileName->Buffer) points to memory from RtlProcessHeap()
    01734     that contains the Nt version of the input dos file name.
    01735
    01736 Arguments:
    01737
    01738     DosFileName - Supplies the unicode Dos style file name that is to be
    01739         translated into an equivalent unicode Nt file name.
    01740
    01741     NtFileName - Returns the address of memory in the RtlProcessHeap() that
    01742         contains an NT filename that refers to the specified Dos file
    01743         name.
    01744
    01745     FilePart - Optional parameter that if specified, returns the
    01746         trailing file portion of the file name.  A path of \foo\bar\x.x
    01747         returns the address of x.x as the file part.
    01748
    01749     RelativeName - An optional parameter, that if specified, returns
    01750         a pathname relative to the current directory of the file. The
    01751         length field of RelativeName->RelativeName is 0 if the relative
    01752         name can not be used.
    01753
    01754 Return Value:
    01755
    01756     TRUE - The path name translation was successful.  Once the caller is
    01757         done with the translated name, the memory pointed to by
    01758         NtFileName.Buffer should be returned to the RtlProcessHeap().
    01759
    01760     FALSE - The operation failed.
    01761
    01762 Note:
    01763     The buffers pointed to by RelativeName, FilePart, and NtFileName must ALL
    01764     point within the same memory address.  If they don't, code that calls
    01765     this routine will fail.
    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     // Calculate the size needed for the full pathname. Add in
    01791     // space for the longest Nt prefix
    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     // see if this is \\?\ form of name
    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         // The dos name starts just after the longest Nt prefix
    01819         //
    01820
    01821         FullDosPathName = &StaticDosBuffer[0];
    01822
    01823         BufferLength += RtlpLongestPrefix;
    01824
    01825         //
    01826         // Allocate space for the full Nt Name (including DOS name portion)
    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         // Determine how to format prefix of FullNtPathName base on the
    01868         // the type of Dos path name.  All Nt names begin in the \DosDevices
    01869         // directory.
    01870         //
    01871
    01872         Prefix = RtlpDosDevicesPrefix;
    01873
    01874         DosPathType = RtlDetermineDosPathNameType_U(FullDosPathName);
    01875
    01876         switch (DosPathType) {
    01877             case RtlPathTypeUncAbsolute :
    01878
    01879                 //
    01880                 // Unc name, use \DosDevices\UNC symbolic link to find
    01881                 // redirector.  Skip of \\ in source Dos path.
    01882                 //
    01883
    01884                 Prefix = RtlpDosDevicesUncPrefix;
    01885                 DosPathNameOffset = 2;
    01886                 break;
    01887
    01888             case RtlPathTypeLocalDevice :
    01889
    01890                 //
    01891                 // Local device name, so just use \DosDevices prefix and
    01892                 // skip \\.\ in source Dos path.
    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                 // All drive references just use \DosDevices prefix and
    01910                 // do not skip any of the characters in the source Dos path.
    01911                 //
    01912
    01913                 DosPathNameOffset = 0;
    01914                 break;
    01915
    01916             default:
    01917                 ASSERT( FALSE );
    01918             }
    01919
    01920         //
    01921         // Copy the full DOS path next to the name prefix, skipping over
    01922         // the "\\" at the front of the UNC path or the "\\.\" at the front
    01923         // of a device name.
    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         // Null terminate the path name to make strlen below happy.
    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         // Readjust the file part to point to the appropriate position within
    01945         // the FullNtPathName buffer instead of inside the FullDosPathName
    01946         // buffer
    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             // If the current directory is a sub-string of the
    01961             // Nt file name, and if a handle exists for the current
    01962             // directory, then return the directory handle and name
    01963             // relative to the directory.
    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                     // Now compare curdir to full dos path. If curdir length is
    01979                     // greater than full path. It is not a match. Otherwise,
    01980                     // trim full path length to cur dir length and compare.
    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                             // The full dos pathname is a substring of the
    01994                             // current directory.  Compute the start of the
    01995                             // relativename.
    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 }

ULONG RtlDosSearchPath_U | ( | IN PWSTR | lpPath,
|  | IN PWSTR | lpFileName,
|  | IN PWSTR lpExtension | OPTIONAL,
|  | IN ULONG | nBufferLength,
|  | OUT PWSTR | lpBuffer,
|  | OUT PWSTR * | lpFilePart
| ) |

Definition at line 2156 of file curdir.c.

References FALSE, L, NULL, RtlAllocateHeap, RtlDetermineDosPathNameType_U(), RtlDoesFileExists_UEx(), RtlFreeHeap, RtlGetFullPathName_U(), RtlInitUnicodeString(), and TRUE.

Referenced by LdrpCheckForLoadedDll(), LdrpResolveDllName(), and LoadLinkInfo().

    02167                    :
    02168
    02169     This function is used to search for a file specifying a search path
    02170     and a filename.  It returns with a fully qualified pathname of the
    02171     found file.
    02172
    02173     This function is used to locate a file using the specified path.  If
    02174     the file is found, its fully qualified pathname is returned.  In
    02175     addition to this, it calculates the address of the file name portion
    02176     of the fully qualified pathname.
    02177
    02178 Arguments:
    02179
    02180     lpPath - Supplies the search path to be used when locating the file.
    02181
    02182     lpFileName - Supplies the file name of the file to search for.
    02183
    02184     lpExtension - An optional parameter, that if specified, supplies an
    02185         extension to be added to the filename when doing the search.
    02186         The extension is only added if the specified filename does not
    02187         end with an extension.
    02188
    02189     nBufferLength - Supplies the length in bytes of the buffer that is
    02190         to receive the fully qualified path.
    02191
    02192     lpBuffer - Returns the fully qualified pathname corresponding to the
    02193         file that was found.
    02194
    02195     lpFilePart - Optional parameter that if specified, returns the
    02196         address of the last component of the fully qualified pathname.
    02197
    02198 Return Value:
    02199
    02200     The return value is the length of the string copied to lpBuffer, not
    02201     including the terminating null character.  If the return value is
    02202     greater than nBufferLength, the return value is the size of the buffer
    02203     required to hold the pathname.  The return value is zero if the
    02204     function failed.
    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     // if the file name is not a relative name, then
    02220     // return an if the file does not exist.
    02221     //
    02222     // If a fully qualified pathname is used in the search, then
    02223     // allow access_denied or sharing violations to terminate the
    02224     // search. This was the nt 3.1-4.0 behavior, and was changed for the
    02225     // loader to handle cases where when walking through a search, we didn't
    02226     // terminate the search early because of an inaccessible UNC path component
    02227     // be restoring the old behavior in this case, we give the correct (access_denied)
    02228     // error codes on fully qualified module lookups, but keep going when bumping
    02229     // through search path components
    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     // Determine if the file name contains an extension
    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     // If no extension was found, then determine the extension length
    02263     // that should be used to search for the file
    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     // Compute the file name length and the path length;
    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     // find ; 's in path and copy path component to computed file name
    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 }

ULONG RtlGetCurrentDirectory_U | ( | ULONG | nBufferLength,
|  | PWSTR | lpBuffer
| ) |

Definition at line 145 of file curdir.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, L, RtlAcquirePebLock(), and RtlReleasePebLock().

    00152                    :
    00153
    00154     The current directory for a process can be retreived using
    00155     GetCurrentDirectory.
    00156
    00157 Arguments:
    00158
    00159     nBufferLength - Supplies the length in bytes of the buffer that is to
    00160         receive the current directory string.
    00161
    00162     lpBuffer - Returns the current directory string for the current
    00163         process.  The string is a null terminated string and specifies
    00164         the absolute path to the current directory.
    00165
    00166 Return Value:
    00167
    00168     The return value is the length of the string copied to lpBuffer, not
    00169     including the terminating null character.  If the return value is
    00170     greater than nBufferLength, the return value is the size of the buffer
    00171     required to hold the pathname.  The return value is zero if the
    00172     function failed.
    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     // Make sure user's buffer is big enough to hold the null
    00188     // terminated current directory
    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 0L;
    00219         }
    00220     RtlReleasePebLock();
    00221     return Length<<1;
    00222 }

ULONG RtlGetFullPathName_U | ( | PCWSTR | lpFileName,
|  | ULONG | nBufferLength,
|  | PWSTR | lpBuffer,
|  | PWSTR *lpFilePart | OPTIONAL
| ) |

Definition at line 1611 of file curdir.c.

References NULL, RtlGetFullPathName_Ustr(), and RtlInitUnicodeString().

Referenced by RtlDosSearchPath_U().

    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 }

ULONG RtlGetFullPathName_Ustr | ( | PUNICODE_STRING | FileName,
|  | ULONG | nBufferLength,
|  | PWSTR | lpBuffer,
|  | PWSTR *lpFilePart | OPTIONAL,
|  | PBOOLEAN | NameInvalid,
|  | RTL_PATH_TYPE * | InputPathType
| ) |

Definition at line 920 of file curdir.c.

References FALSE, FileName, IS_DOT_DOT_U, IS_DOT_U, IS_PATH_SEPARATOR_U, L, NT_SUCCESS, NTSTATUS(), NULL, RtlAcquirePebLock(), RtlDetermineDosPathNameType_U(), RtlInitUnicodeString(), RtlIsDosDeviceName_Ustr(), RtlpCheckDeviceName(), RtlpCheckRelativeDrive(), RtlpComputeBackupIndex(), RtlpSlashSlashDot, RtlpValidateCurrentDirectory(), RtlQueryEnvironmentVariable_U(), RtlReleasePebLock(), RtlUpcaseUnicodeChar(), Status, TRUE, and USHORT.

Referenced by RtlDosPathNameToNtPathName_U(), RtlGetFullPathName_U(), and RtlSetCurrentDirectory_U().

    00931                    :
    00932
    00933     This function is used to return a fully qualified pathname
    00934     corresponding to the specified unicode filename.  It does this by
    00935     merging the current drive and directory together with the specified
    00936     file name.  In addition to this, it calculates the address of the
    00937     file name portion of the fully qualified pathname.
    00938
    00939 Arguments:
    00940
    00941     lpFileName - Supplies the unicode file name of the file whose fully
    00942         qualified pathname is to be returned.
    00943
    00944     nBufferLength - Supplies the length in bytes of the buffer that is
    00945         to receive the fully qualified path.
    00946
    00947     lpBuffer - Returns the fully qualified pathname corresponding to the
    00948         specified file.
    00949
    00950     lpFilePart - Optional parameter that if specified, returns the
    00951         address of the last component of the fully qualified pathname.
    00952
    00953 Return Value:
    00954
    00955     The return value is the length of the string copied to lpBuffer, not
    00956     including the terminating unicode null character.  If the return
    00957     value is greater than nBufferLength, the return value is the size of
    00958     the buffer required to hold the pathname.  The return value is zero
    00959     if the function failed.
    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         // trim trailing spaces to check for a null name
    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     // If pass Dos file name is a Dos device name, then turn it into
    01032     // \\.\devicename and return its length.
    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     // Setup output string that points to callers buffer.
    01079     //
    01080
    01081     FullPath.MaximumLength = (USHORT)nBufferLength;
    01082     FullPath.Length = 0;
    01083     FullPath.Buffer = lpBuffer;
    01084     RtlZeroMemory(lpBuffer,nBufferLength);
    01085     //
    01086     // Get a pointer to the current directory structure.
    01087     //
    01088
    01089     CurDir = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
    01090
    01091
    01092     //
    01093     // Determine the type of Dos Path Name specified.
    01094     //
    01095
    01096     *InputPathType = PathType = RtlDetermineDosPathNameType_U(lpFileName);
    01097
    01098     //
    01099     // Determine the prefix and backup index.
    01100     //
    01101     //  Input        Prefix                     Backup Index
    01102     //
    01103     //  \\        -> \\,                            end of \\server\share
    01104     //  \\.\      -> \\.\,                          4
    01105     //  \\.       -> \\.                            3 (\\.)
    01106     //  \         -> Drive: from CurDir.DosPath     3 (Drive:\)
    01107     //  d:        -> Drive:\curdir from environment 3 (Drive:\)
    01108     //  d:\       -> no prefix                      3 (Drive:\)
    01109     //  any       -> CurDir.DosPath                 3 (Drive:\)
    01110     //
    01111
    01112     RtlAcquirePebLock();
    01113     try {
    01114
    01115         //
    01116         // No prefixes yet.
    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                     // We want to scan the supplied path to determine where
    01133                     // the "share" ends, and set BackupIndex to that point.
    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                     // Unc name. prefix = \\server\share
    01156                     //
    01157
    01158                     PrefixSourceLength = BackupIndex << 1;
    01159
    01160                     Source += BackupIndex;
    01161
    01162                     //
    01163                     //  There is no prefix to place into the buffer.
    01164                     //  The entire path is in Source
    01165                     //
    01166
    01167                     }
    01168                 break;
    01169
    01170             case RtlPathTypeLocalDevice :
    01171
    01172                 //
    01173                 // Local device name. prefix = "\\.\"
    01174                 //
    01175
    01176                 PrefixSourceLength = RtlpSlashSlashDot.Length;
    01177                 BackupIndex = 4;
    01178                 Source += BackupIndex;
    01179                 PathNameLength -= BackupIndex * sizeof( WCHAR );
    01180
    01181                 //
    01182                 //  There is no prefix to place into the buffer.
    01183                 //  The entire path is in Source
    01184                 //
    01185
    01186                 break;
    01187
    01188             case RtlPathTypeRootLocalDevice :
    01189
    01190                 //
    01191                 // Local Device root. prefix = "\\.\"
    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                 // Dos drive absolute name
    01214                 //
    01215
    01216                 BackupIndex = 3;
    01217                 break;
    01218
    01219             case RtlPathTypeDriveRelative :
    01220
    01221                 //
    01222                 // Dos drive relative name
    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                             // Otherwise default to root directory of drive
    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                             // Determine
    01272                             // if a backslash needs to be added
    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                     // Rooted name. Prefix is drive portion of current directory
    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                 // Current drive:directory relative name
    01314                 //
    01315
    01316                 Prefix = CurDir->DosPath;
    01317                 BackupIndex = RtlpComputeBackupIndex(CurDir);
    01318                 break;
    01319
    01320             default:
    01321                 return 0;
    01322             }
    01323
    01324         //
    01325         // Maximum length required is the length of the prefix plus
    01326         // the length of the specified pathname. If the callers buffer
    01327         // is not at least this large, then return an error.
    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                 // If we are expanding curdir, then remember the trailing '\'
    01344                 //
    01345
    01346                 if ( NumberOfCharacters == 1 && *lpFileName == L'.' ) {
    01347
    01348                     //
    01349                     // We are expanding .
    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             // Copy the prefix from the source string.
    01386             //
    01387
    01388             //RtlMoveMemory(FullPath.Buffer,lpFileName,PrefixSourceLength);
    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             // Append any additional prefix
    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                 // collapse multiple "\" characters.
    01435                 //
    01436
    01437                 if  ( *(Dest-1) != L'\\' ) {
    01438                     *Dest++ = L'\\';
    01439                     }
    01440
    01441                 Source++;
    01442                 break;
    01443
    01444             case '.' :
    01445
    01446                 //
    01447                 // Ignore dot in a leading //./
    01448                 // Eat single dots as in /./
    01449                 // Double dots back up one level as in /../
    01450                 // Any other . is just a filename character
    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                     // backup destination string looking for a '\'
    01462                     //
    01463
    01464                     while (*Dest != L'\\') {
    01465                         *Dest = UNICODE_NULL;
    01466                         Dest--;
    01467                         }
    01468
    01469                     //
    01470                     // backup to previous component..
    01471                     // \a\b\c\.. to \a\b
    01472                     //
    01473
    01474                     do {
    01475
    01476                         //
    01477                         // If we bump into root prefix, then
    01478                         // stay at root
    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                     // Advance source past ..
    01495                     //
    01496
    01497                     Source += 2;
    01498
    01499                     break;
    01500                     }
    01501
    01502                 //
    01503                 // FALLTHRU
    01504                 //
    01505
    01506             default:
    01507
    01508                 //
    01509                 // Copy the filename. The copy will stop
    01510                 // on "non-portable" characters. Note that
    01511                 // null and /,\ will stop the copy. If any
    01512                 // charcter other than null or /,\ is encountered,
    01513                 // then the pathname is invalid.
    01514                 //
    01515
    01516                 //
    01517                 // strip trailing .'s within a component
    01518                 //
    01519
    01520                 while ( *Source && !IS_PATH_SEPARATOR_U(*Source) ) {
    01521                     if ( *Source == L'.' ) {
    01522
    01523                         //
    01524                         // nuke .'s that preceed pathname seperators
    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         // strip trailing spaces and dots
    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             // Locate the file part...
    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                 // If this is a UNC name, make sure filepart is past the backup index
    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 }

ULONG RtlGetLongestNtPathLength | ( | VOID |  | ) |

Definition at line 114 of file curdir.c.

References RtlpLongestPrefix.

    00115 {
    00116     return RtlpLongestPrefix + DOS_MAX_PATH_LENGTH + 1;
    00117 }

ULONG RtlIsDosDeviceName_U | ( | IN PWSTR | DosFileName | ) |

Definition at line 790 of file curdir.c.

References RtlInitUnicodeString(), and RtlIsDosDeviceName_Ustr().

    00793 {
    00794     UNICODE_STRING UnicodeString;
    00795
    00796     RtlInitUnicodeString(&UnicodeString,DosFileName);
    00797
    00798     return RtlIsDosDeviceName_Ustr(&UnicodeString);
    00799 }

ULONG RtlIsDosDeviceName_Ustr | ( | IN PUNICODE_STRING | DosFileName | ) |

Definition at line 577 of file curdir.c.

References L, RtlDetermineDosPathNameType_U(), RtlEqualUnicodeString(), RtlInitUnicodeString(), RtlpDosAUXDevice, RtlpDosCOMDevice, RtlpDosCONDevice, RtlpDosLPTDevice, RtlpDosNULDevice, RtlpDosPRNDevice, RtlpDosSlashCONDevice, TRUE, and USHORT.

Referenced by RtlGetFullPathName_Ustr(), RtlIsDosDeviceName_U(), and RtlSetCurrentDirectory_U().

    00583                    :
    00584
    00585     This function examines the Dos format file name and determines if it
    00586     is a Dos device name (e.g. LPT1, etc.).  Valid Dos device names are:
    00587
    00588         LPTn
    00589         COMn
    00590         PRN
    00591         AUX
    00592         NUL
    00593         CON
    00594
    00595     when n is a digit.  Trailing colon is ignored if present.
    00596
    00597 Arguments:
    00598
    00599     DosFileName - Supplies the Dos format file name that is to be examined.
    00600
    00601 Return Value:
    00602
    00603     0 - Specified Dos file name is not the name of a Dos device.
    00604
    00605     > 0 - Specified Dos file name is the name of a Dos device and the
    00606           return value is a ULONG where the high order 16 bits is the
    00607           offset in the input buffer where the dos device name beings
    00608           and the low order 16 bits is the length of the device name
    00609           the length of the name (excluding any optional
    00610           trailing colon).
    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         // For Unc Absolute, Check for \\.\CON
    00632         // since this really is not a device
    00633         //
    00634
    00635         if ( RtlEqualUnicodeString(DosFileName,&RtlpDosSlashCONDevice,TRUE) ) {
    00636             return 0x00080006;
    00637         }
    00638
    00639         //
    00640         // FALLTHRU
    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     // The above strip the trailing colon logic could have left us with 0
    00659     // for NumberOfCharacters, so that needs to be tested
    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     //  Walk backwards through the string finding the
    00678     //  first slash or the beginning of the string.  We also stop
    00679     //  at the drive: if it is present.
    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                 //  Get the first char of the file name and convert it to
    00692                 //  lower case.  This will be safe since we will be comparing
    00693                 //  it to only lower-case ASCII.
    00694                 //
    00695
    00696                 wch = (*p) | 0x20;
    00697
    00698                 //
    00699                 //  check to see if we possibly have a hit on
    00700                 //  lpt, prn, con, com, aux, or nul
    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         // check to see if we possibly have a hit on
    00723         // lpt, prn, con, com, aux, or nul
    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     //  Now we need to see if we are dealing with a device name that has
    00734     //  an extension or a stream name. If so, we need to limit the search to the
    00735     //  file portion only
    00736     //
    00737
    00738     p = UnicodeString.Buffer;
    00739     while (p < UnicodeString.Buffer + NumberOfCharacters && *p != L'.' && *p != L':') {
    00740         p++;
    00741     }
    00742
    00743     //
    00744     //  p either points past end of string or to a dot or :.  We back up over
    00745     //  trailing spaces
    00746     //
    00747
    00748     while (p > UnicodeString.Buffer && p[-1] == L' ') {
    00749         p--;
    00750     }
    00751
    00752     //
    00753     //  p either points to the beginning of the string or p[-1] is
    00754     //  the first non-space char found above.
    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 }

BOOLEAN RtlpCheckDeviceName | ( | PUNICODE_STRING | DevName,
|  | ULONG | DeviceNameOffset
| ) |

Definition at line 802 of file curdir.c.

References FALSE, L, RtlAllocateHeap, RtlDoesFileExists_U(), RtlFreeHeap, and TRUE.

Referenced by RtlGetFullPathName_Ustr().

    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 }

VOID RtlpCheckRelativeDrive | ( | WCHAR | NewDrive | ) |

Definition at line 2341 of file curdir.c.

References L, NT_SUCCESS, NtClose(), NtOpenFile(), NTSTATUS(), NULL, RtlInitUnicodeString(), RtlpDosDevicesPrefix, RtlpResetDriveEnvironment(), RtlQueryEnvironmentVariable_U(), and Status.

Referenced by RtlGetFullPathName_Ustr().

    02347                    :
    02348
    02349     This function is called whenever we are asked to expand a non
    02350     current directory drive relative name ( f:this\is\my\file ).  In
    02351     this case, we validate the environment variable string to make sure
    02352     the current directory at that drive is valid. If not, we trim back to
    02353     the root.
    02354
    02355 Arguments:
    02356
    02357     NewDrive - Supplies the drive to check
    02358
    02359 Return Value:
    02360
    02361     None.
    02362
    02363 --*/
    02364
    02365 {
    02366
    02367     WCHAR EnvVarValueBuffer[DOS_MAX_PATH_LENGTH+12]; // + sizeof (\DosDevices\)
    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     // capture the value in a buffer that has space at the front for the dos devices
    02387     // prefix
    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         // Otherwise default to root directory of drive
    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     // Form the NT name for this directory
    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     // If the open succeeds, then the directory is valid... No need to do anything
    02446     // further. If the open fails, then trim back the environment to the root.
    02447     //
    02448
    02449     if ( NT_SUCCESS(Status) ) {
    02450         NtClose(DirHandle);
    02451         return;
    02452         }
    02453
    02454     RtlpResetDriveEnvironment(NewDrive);
    02455 }
    }

ULONG RtlpComputeBackupIndex | ( | IN PCURDIR | CurDir | ) |

Definition at line 68 of file curdir.c.

References IS_PATH_SEPARATOR_U, and RtlDetermineDosPathNameType_U().

Referenced by RtlGetFullPathName_Ustr().

    00071 {
    00072     ULONG BackupIndex;
    00073     PWSTR UncPathPointer;
    00074     ULONG NumberOfPathSeparators;
    00075     RTL_PATH_TYPE CurDirPathType;
    00076
    00077
    00078     //
    00079     // Get pathType of curdir
    00080     //
    00081
    00082     CurDirPathType = RtlDetermineDosPathNameType_U(CurDir->DosPath.Buffer);
    00083     BackupIndex = 3;
    00084     if ( CurDirPathType == RtlPathTypeUncAbsolute ) {
    00085
    00086         //
    00087         // We want to scan the supplied path to determine where
    00088         // the "share" ends, and set BackupIndex to that point.
    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 }

VOID RtlpResetDriveEnvironment | ( | IN WCHAR | DriveLetter | ) |

Definition at line 120 of file curdir.c.

References L, NULL, RtlInitUnicodeString(), and RtlSetEnvironmentVariable().

Referenced by RtlpCheckRelativeDrive(), and RtlpValidateCurrentDirectory().

    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 }

VOID RtlpValidateCurrentDirectory | ( | PCURDIR | CurDir | ) |

Definition at line 839 of file curdir.c.

References NT_SUCCESS, NtClose(), NtFsControlFile(), NTSTATUS(), NULL, RtlInitUnicodeString(), RtlpResetDriveEnvironment(), RtlSetCurrentDirectory_U(), and VOID().

Referenced by RtlGetFullPathName_Ustr().

    00845                    :
    00846
    00847     This function is used to validate the current directory for the process.
    00848     The current directory can change in several ways, first, by replacing
    00849     the media with one that has a different directory structure.  Second
    00850     by performing a force-dismount.
    00851
    00852 Arguments:
    00853
    00854     CurDir - Current directory structure for process
    00855
    00856 Return Value:
    00857
    00858     None.
    00859
    00860 --*/
    00861
    00862 {
    00863     NTSTATUS FsCtlStatus;
    00864     IO_STATUS_BLOCK IoStatusBlock;
    00865     WCHAR TrimmedPath[4];
    00866     UNICODE_STRING str;
    00867
    00868     //
    00869     // Call Nt to see if the volume that
    00870     // contains the directory is still mounted.
    00871     // If it is, then continue. Otherwise, trim
    00872     // current directory to the root.
    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         // Try to get back to where we were, failing that reset current directory
    00892         // to the root of the current drive
    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             //  This can still fail if the volume was hard dismounted. We tried.
    00910             //  Ah well.
    00911             //
    00912
    00913             (VOID) RtlSetCurrentDirectory_U( &str );
    00914         }
    00915     }
    00916 }

BOOLEAN RtlpWin32NTNameToNtPathName_U | ( | IN PUNICODE_STRING | DosFileName,
|  | OUT PUNICODE_STRING | NtFileName,
|  | OUT PWSTR *FilePart | OPTIONAL,
|  | OUT PRTL_RELATIVE_NAME RelativeName | OPTIONAL
| ) |

Definition at line 1628 of file curdir.c.

References FALSE, L, NULL, RelativeName, RtlAllocateHeap, RtlpDosDevicesPrefix, TRUE, and USHORT.

Referenced by RtlDosPathNameToNtPathName_U().

    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     // Copy the full Win32/NT path next to the name prefix, skipping over
    01650     // the \\?\ at the front of the path.
    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     // Null terminate the path name to make strlen below happy.
    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     // Now we have the passed in path with \DosDevices\ prepended. Blow out the
    01670     // relative name structure (if provided), and possibly compute filepart
    01671     //
    01672
    01673     if ( ARGUMENT_PRESENT(RelativeName) ) {
    01674
    01675         //
    01676         // If the current directory is a sub-string of the
    01677         // Nt file name, and if a handle exists for the current
    01678         // directory, then return the directory handle and name
    01679         // relative to the directory.
    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         // Locate the file part...
    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 }

NTSTATUS RtlSetCurrentDirectory_U | ( | PUNICODE_STRING | PathName | ) |

Definition at line 225 of file curdir.c.

References EXCEPTION_EXECUTE_HANDLER, L, NT_SUCCESS, NtClose(), NtOpenFile(), NtQueryVolumeInformationFile(), NTSTATUS(), NULL, RtlAcquirePebLock(), RtlAllocateHeap, RtlDosPathNameToNtPathName_U(), RtlFreeHeap, RtlGetFullPathName_Ustr(), RtlIsDosDeviceName_Ustr(), RtlReleasePebLock(), Status, and USHORT.

Referenced by LdrpInitializeProcess(), and RtlpValidateCurrentDirectory().

    00231                    :
    00232
    00233     The current directory for a process is changed using
    00234     SetCurrentDirectory.
    00235
    00236     Each process has a single current directory.  A current directory is
    00237     made up of type parts.
    00238
    00239         - A disk designator either which is either a drive letter followed
    00240           by a colon, or a UNC servername/sharename "\\servername\sharename".
    00241
    00242         - A directory on the disk designator.
    00243
    00244     For APIs that manipulate files, the file names may be relative to
    00245     the current directory.  A filename is relative to the entire current
    00246     directory if it does not begin with a disk designator or a path name
    00247     SEPARATOR.  If the file name begins with a path name SEPARATOR, then
    00248     it is relative to the disk designator of the current directory.  If
    00249     a file name begins with a disk designator, than it is a fully
    00250     qualified absolute path name.
    00251
    00252     The value of lpPathName supplies the current directory.  The value
    00253     of lpPathName, may be a relative path name as described above, or a
    00254     fully qualified absolute path name.  In either case, the fully
    00255     qualified absolute path name of the specified directory is
    00256     calculated and is stored as the current directory.
    00257
    00258 Arguments:
    00259
    00260     lpPathName - Supplies the pathname of the directory that is to be
    00261         made the current directory.
    00262
    00263 Return Value:
    00264
    00265     NT_SUCCESS - The operation was successful
    00266
    00267     !NT_SUCCESS - The operation failed
    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     // Set current directory is called first by the loader.
    00300     // If current directory is not being inherited, then close
    00301     // it !
    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             // Compute the length of the Dos style fully qualified current
    00314             // directory
    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             // Now get the full pathname for the Dos style current
    00327             // directory
    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             // Get the Nt filename of the new current directory
    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             // If we are inheriting current directory, then
    00376             // avoid the open
    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                 // Test to see if this is removable media. If so
    00385                 // tag the handle this may fail if the process was
    00386                 // created with inherit handles set to false
    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                 // Open a handle to the current directory. Don't allow
    00409                 // deletes of the directory.
    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                 // Test to see if this is removable media. If so
    00427                 // tag the handle
    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             // If there is no trailing '\', than place one
    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             // Now we are set to change to the new directory.
    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 }

## Variable Documentation

const UNICODE_STRING RtlpDosAUXDevice = CONSTANT_UNICODE_STRING( L"AUX" )

| Definition at line 56 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosCOMDevice = CONSTANT_UNICODE_STRING( L"COM" )

| Definition at line 54 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosCONDevice = CONSTANT_UNICODE_STRING( L"CON" )

| Definition at line 58 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosDevicesPrefix = CONSTANT_UNICODE_STRING( L"\\??\\" )

| Definition at line 62 of file curdir.c. Referenced by RtlDosPathNameToNtPathName_U(), RtlpCheckRelativeDrive(), and RtlpWin32NTNameToNtPathName_U().

const UNICODE_STRING RtlpDosDevicesUncPrefix = CONSTANT_UNICODE_STRING( L"\\??\\UNC\\" )

| Definition at line 63 of file curdir.c. Referenced by RtlDosPathNameToNtPathName_U().

const UNICODE_STRING RtlpDosLPTDevice = CONSTANT_UNICODE_STRING( L"LPT" )

| Definition at line 53 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosNULDevice = CONSTANT_UNICODE_STRING( L"NUL" )

| Definition at line 57 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosPRNDevice = CONSTANT_UNICODE_STRING( L"PRN" )

| Definition at line 55 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpDosSlashCONDevice = CONSTANT_UNICODE_STRING( L"\\\\.\\CON" )

| Definition at line 60 of file curdir.c. Referenced by RtlIsDosDeviceName_Ustr().

const UNICODE_STRING RtlpSlashSlashDot = CONSTANT_UNICODE_STRING( L"\\\\.\\" )

| Definition at line 61 of file curdir.c. Referenced by RtlGetFullPathName_Ustr().