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  )     { sizeof( s ) - sizeof( WCHAR ), sizeof( s ), s }
 

Definition at line 51 of file curdir.c.

#define IS_DOT_DOT_U  )     ( 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[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().


Generated on Sat May 15 19:43:23 2004 for test by doxygen 1.3.7