ReactOS  0.4.12-dev-916-gffc4e30
path.c File Reference
#include <rtl.h>
#include <debug.h>
Include dependency graph for path.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MAX_PFX_SIZE   16
 
#define IS_PATH_SEPARATOR(x)   (((x)==L'\\')||((x)==L'/'))
 
#define RTL_CURDIR_IS_REMOVABLE   0x1
 
#define RTL_CURDIR_DROP_OLD_HANDLE   0x2
 
#define RTL_CURDIR_ALL_FLAGS   (RTL_CURDIR_DROP_OLD_HANDLE | RTL_CURDIR_IS_REMOVABLE)
 

Functions

 C_ASSERT (RTL_CURDIR_ALL_FLAGS==OBJ_HANDLE_TAGBITS)
 
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr (IN PCUNICODE_STRING PathString)
 
ULONG NTAPI RtlIsDosDeviceName_Ustr (IN PCUNICODE_STRING PathString)
 
NTSTATUS NTAPI RtlpCheckDeviceName (IN PUNICODE_STRING FileName, IN ULONG Length, OUT PBOOLEAN NameInvalid)
 
static ULONG RtlpCollapsePath (PWSTR Path, ULONG mark, BOOLEAN SkipTrailingPathSeparators)
 
static SIZE_T RtlpSkipUNCPrefix (PCWSTR FileNameBuffer)
 
NTSTATUS NTAPI RtlpApplyLengthFunction (IN ULONG Flags, IN ULONG Type, IN PVOID UnicodeStringOrUnicodeStringBuffer, IN PVOID LengthFunction)
 
NTSTATUS NTAPI RtlGetLengthWithoutLastFullDosOrNtPathElement (IN ULONG Flags, IN PWCHAR Path, OUT PULONG LengthOut)
 
NTSTATUS NTAPI RtlComputePrivatizedDllName_U (_In_ PUNICODE_STRING DllName, _Inout_ PUNICODE_STRING RealName, _Inout_ PUNICODE_STRING LocalName)
 
ULONG NTAPI RtlGetFullPathName_Ustr (_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
 
NTSTATUS NTAPI RtlpWin32NTNameToNtPathName_U (IN PUNICODE_STRING DosPath, OUT PUNICODE_STRING NtPath, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_Ustr (IN BOOLEAN HaveRelative, IN PCUNICODE_STRING DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U (IN BOOLEAN HaveRelative, IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_Ustr (IN PCUNICODE_STRING DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
BOOLEAN NTAPI RtlDoesFileExists_UstrEx (IN PCUNICODE_STRING FileName, IN BOOLEAN SucceedIfBusy)
 
BOOLEAN NTAPI RtlDoesFileExists_UStr (IN PUNICODE_STRING FileName)
 
BOOLEAN NTAPI RtlDoesFileExists_UEx (IN PCWSTR FileName, IN BOOLEAN SucceedIfBusy)
 
VOID NTAPI RtlReleaseRelativeName (IN PRTL_RELATIVE_NAME_U RelativeName)
 
ULONG NTAPI RtlGetLongestNtPathLength (VOID)
 
NTSTATUS NTAPI RtlGetLengthWithoutTrailingPathSeparators (IN ULONG Flags, IN PCUNICODE_STRING PathString, OUT PULONG Length)
 
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U (IN PCWSTR Path)
 
ULONG NTAPI RtlIsDosDeviceName_U (IN PCWSTR Path)
 
ULONG NTAPI RtlGetCurrentDirectory_U (_In_ ULONG MaximumLength, _Out_bytecap_(MaximumLength) PWSTR Buffer)
 
NTSTATUS NTAPI RtlSetCurrentDirectory_U (IN PUNICODE_STRING Path)
 
ULONG NTAPI RtlGetFullPathName_UEx (_In_ PWSTR FileName, _In_ ULONG BufferLength, _Out_writes_bytes_(BufferLength) PWSTR Buffer, _Out_opt_ PWSTR *FilePart, _Out_opt_ RTL_PATH_TYPE *InputPathType)
 
ULONG NTAPI RtlGetFullPathName_U (_In_ PCWSTR FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PWSTR *ShortName)
 
BOOLEAN NTAPI RtlDosPathNameToNtPathName_U (IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
NTSTATUS NTAPI RtlDosPathNameToNtPathName_U_WithStatus (IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U (IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
NTSTATUS NTAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus (IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
 
NTSTATUS NTAPI RtlNtPathNameToDosPathName (IN ULONG Flags, IN OUT PRTL_UNICODE_STRING_BUFFER Path, OUT PULONG PathType, PULONG Unknown)
 
ULONG NTAPI RtlDosSearchPath_U (IN PCWSTR Path, IN PCWSTR FileName, IN PCWSTR Extension, IN ULONG Size, IN PWSTR Buffer, OUT PWSTR *PartName)
 
NTSTATUS NTAPI RtlGetFullPathName_UstrEx (IN PUNICODE_STRING FileName, IN PUNICODE_STRING StaticString, IN PUNICODE_STRING DynamicString, IN PUNICODE_STRING *StringUsed, IN PSIZE_T FilePartSize, OUT PBOOLEAN NameInvalid, OUT RTL_PATH_TYPE *PathType, OUT PSIZE_T LengthNeeded)
 
NTSTATUS NTAPI RtlDosSearchPath_Ustr (IN ULONG Flags, IN PUNICODE_STRING PathString, IN PUNICODE_STRING FileNameString, IN PUNICODE_STRING ExtensionString, IN PUNICODE_STRING CallerBuffer, IN OUT PUNICODE_STRING DynamicString OPTIONAL, OUT PUNICODE_STRING *FullNameOut OPTIONAL, OUT PSIZE_T FilePartSize OPTIONAL, OUT PSIZE_T LengthNeeded OPTIONAL)
 
BOOLEAN NTAPI RtlDoesFileExists_U (IN PCWSTR FileName)
 

Variables

const UNICODE_STRING DeviceRootString = RTL_CONSTANT_STRING(L"\\\\.\\")
 
const UNICODE_STRING RtlpDosDevicesUncPrefix = RTL_CONSTANT_STRING(L"\\??\\UNC\\")
 
const UNICODE_STRING RtlpWin32NtRootSlash = RTL_CONSTANT_STRING(L"\\\\?\\")
 
const UNICODE_STRING RtlpDosSlashCONDevice = RTL_CONSTANT_STRING(L"\\\\.\\CON")
 
const UNICODE_STRING RtlpDosDevicesPrefix = RTL_CONSTANT_STRING(L"\\??\\")
 
const UNICODE_STRING RtlpDosLPTDevice = RTL_CONSTANT_STRING(L"LPT")
 
const UNICODE_STRING RtlpDosCOMDevice = RTL_CONSTANT_STRING(L"COM")
 
const UNICODE_STRING RtlpDosPRNDevice = RTL_CONSTANT_STRING(L"PRN")
 
const UNICODE_STRING RtlpDosAUXDevice = RTL_CONSTANT_STRING(L"AUX")
 
const UNICODE_STRING RtlpDosCONDevice = RTL_CONSTANT_STRING(L"CON")
 
const UNICODE_STRING RtlpDosNULDevice = RTL_CONSTANT_STRING(L"NUL")
 
const UNICODE_STRING RtlpDoubleSlashPrefix = RTL_CONSTANT_STRING(L"\\\\")
 
static const UNICODE_STRING RtlpDefaultExtension = RTL_CONSTANT_STRING(L".DLL")
 
static const UNICODE_STRING RtlpDotLocal = RTL_CONSTANT_STRING(L".Local\\")
 
static const UNICODE_STRING RtlpPathDividers = RTL_CONSTANT_STRING(L"\\/")
 
PRTLP_CURDIR_REF RtlpCurDirRef
 

Macro Definition Documentation

◆ IS_PATH_SEPARATOR

#define IS_PATH_SEPARATOR (   x)    (((x)==L'\\')||((x)==L'/'))

Definition at line 24 of file path.c.

◆ MAX_PFX_SIZE

#define MAX_PFX_SIZE   16

Definition at line 22 of file path.c.

◆ NDEBUG

#define NDEBUG

Definition at line 17 of file path.c.

◆ RTL_CURDIR_ALL_FLAGS

Definition at line 28 of file path.c.

◆ RTL_CURDIR_DROP_OLD_HANDLE

#define RTL_CURDIR_DROP_OLD_HANDLE   0x2

Definition at line 27 of file path.c.

◆ RTL_CURDIR_IS_REMOVABLE

#define RTL_CURDIR_IS_REMOVABLE   0x1

Definition at line 26 of file path.c.

Function Documentation

◆ C_ASSERT()

◆ RtlComputePrivatizedDllName_U()

NTSTATUS NTAPI RtlComputePrivatizedDllName_U ( _In_ PUNICODE_STRING  DllName,
_Inout_ PUNICODE_STRING  RealName,
_Inout_ PUNICODE_STRING  LocalName 
)

Definition at line 467 of file path.c.

471 {
472  static const UNICODE_STRING ExtensionChar = RTL_CONSTANT_STRING(L".");
473 
475  UNICODE_STRING ImagePathName, DllNameOnly, CopyRealName, CopyLocalName;
476  BOOLEAN HasExtension;
479  C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR));
480 
481  CopyRealName = *RealName;
482  CopyLocalName = *LocalName;
483 
484 
485  /* Get the image path */
487 
488  /* Check if it's not normalized */
489  if (!(RtlGetCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_NORMALIZED))
490  {
491  /* Normalize it */
492  ImagePathName.Buffer = (PWSTR)((ULONG_PTR)ImagePathName.Buffer + (ULONG_PTR)RtlGetCurrentPeb()->ProcessParameters);
493  }
494 
495 
496  if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
497  DllName, &RtlpPathDividers, &Position)))
498  {
499  DllNameOnly = *DllName;
500  }
501  else
502  {
503  /* Just keep the dll name, ignore path components */
504  Position += sizeof(WCHAR);
505  DllNameOnly.Buffer = DllName->Buffer + Position / sizeof(WCHAR);
506  DllNameOnly.Length = DllName->Length - Position;
507  DllNameOnly.MaximumLength = DllName->MaximumLength - Position;
508  }
509 
510  if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
511  &DllNameOnly, &ExtensionChar, &Position)))
512  {
513  Position = 0;
514  }
515 
516  HasExtension = Position > 1;
517 
518  /* First we create the c:\path\processname.exe.Local\something.dll path */
519  RequiredSize = ImagePathName.Length + RtlpDotLocal.Length + DllNameOnly.Length +
520  (HasExtension ? 0 : RtlpDefaultExtension.Length) + sizeof(UNICODE_NULL);
521 
522  /* This is not going to work out */
524  return STATUS_NAME_TOO_LONG;
525 
526  /* We need something extra */
527  if (RequiredSize > CopyLocalName.MaximumLength)
528  {
530  if (CopyLocalName.Buffer == NULL)
531  return STATUS_NO_MEMORY;
532  CopyLocalName.MaximumLength = RequiredSize;
533  }
534  /* Now build the entire path */
535  CopyLocalName.Length = 0;
536  Status = RtlAppendUnicodeStringToString(&CopyLocalName, &ImagePathName);
538  if (NT_SUCCESS(Status))
539  {
542  }
543  if (NT_SUCCESS(Status))
544  {
545  Status = RtlAppendUnicodeStringToString(&CopyLocalName, &DllNameOnly);
547  }
548  /* Do we need to append an extension? */
549  if (NT_SUCCESS(Status) && !HasExtension)
550  {
553  }
554 
555  if (NT_SUCCESS(Status))
556  {
557  /* then we create the c:\path\something.dll path */
558  if (NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
559  &ImagePathName, &RtlpPathDividers, &Position)))
560  {
561  ImagePathName.Length = Position + sizeof(WCHAR);
562  }
563 
564  RequiredSize = ImagePathName.Length + DllNameOnly.Length +
565  (HasExtension ? 0 : RtlpDefaultExtension.Length) + sizeof(UNICODE_NULL);
566 
568  {
570  }
571  else
572  {
573  if (RequiredSize > CopyRealName.MaximumLength)
574  {
576  if (CopyRealName.Buffer == NULL)
578  CopyRealName.MaximumLength = RequiredSize;
579  }
580  CopyRealName.Length = 0;
581  if (NT_SUCCESS(Status))
582  {
583  Status = RtlAppendUnicodeStringToString(&CopyRealName, &ImagePathName);
585  }
586  if (NT_SUCCESS(Status))
587  {
588  Status = RtlAppendUnicodeStringToString(&CopyRealName, &DllNameOnly);
590  }
591  if (NT_SUCCESS(Status) && !HasExtension)
592  {
595  }
596  }
597  }
598 
599  if (!NT_SUCCESS(Status))
600  {
601  if (CopyRealName.Buffer && CopyRealName.Buffer != RealName->Buffer)
602  RtlpFreeStringMemory(CopyRealName.Buffer, TAG_USTR);
603  if (CopyLocalName.Buffer && CopyLocalName.Buffer != LocalName->Buffer)
604  RtlpFreeStringMemory(CopyLocalName.Buffer, TAG_USTR);
605  return Status;
606  }
607 
608  *RealName = CopyRealName;
609  *LocalName = CopyLocalName;
610  return STATUS_SUCCESS;
611 }
static const UNICODE_STRING RtlpDotLocal
Definition: path.c:51
USHORT MaximumLength
Definition: env_spec_w32.h:370
C_ASSERT(RTL_CURDIR_ALL_FLAGS==OBJ_HANDLE_TAGBITS)
uint16_t * PWSTR
Definition: typedefs.h:54
static COORD Position
Definition: mouse.c:34
LONG NTSTATUS
Definition: precomp.h:26
#define RtlpAllocateStringMemory
Definition: rtlp.h:140
#define UNICODE_STRING_MAX_BYTES
static const UNICODE_STRING RtlpDefaultExtension
Definition: path.c:50
uint32_t ULONG_PTR
Definition: typedefs.h:63
static ULONG_PTR
Definition: path.c:79
#define UNICODE_NULL
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_Inout_ PRTL_BUFFER _In_ SIZE_T RequiredSize
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const UNICODE_STRING RtlpPathDividers
Definition: path.c:52
PPEB NTAPI RtlGetCurrentPeb(VOID)
Definition: libsupp.c:63
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define RtlpFreeStringMemory
Definition: rtlp.h:141
UNICODE_STRING ImagePathName
Definition: btrfs_drv.h:1826
static const WCHAR L[]
Definition: oid.c:1250
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1838
#define TAG_USTR
Definition: libsupp.c:111
Status
Definition: gdiplustypes.h:24
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI NTSTATUS NTAPI RtlFindCharInUnicodeString(_In_ ULONG Flags, _In_ PCUNICODE_STRING SearchString, _In_ PCUNICODE_STRING MatchString, _Out_ PUSHORT Position)
unsigned int ULONG
Definition: retypes.h:1
#define RTL_USER_PROCESS_PARAMETERS_NORMALIZED
Definition: rtltypes.h:41
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by RtlDosApplyFileIsolationRedirection_Ustr(), test_allocations(), and test_dllnames().

◆ RtlDetermineDosPathNameType_U()

RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U ( IN PCWSTR  Path)

Definition at line 1494 of file path.c.

1495 {
1496  DPRINT("RtlDetermineDosPathNameType_U %S\n", Path);
1497 
1498  /* Unlike the newer RtlDetermineDosPathNameType_U we assume 4 characters */
1499  if (IS_PATH_SEPARATOR(Path[0]))
1500  {
1501  if (!IS_PATH_SEPARATOR(Path[1])) return RtlPathTypeRooted; /* \x */
1502  if ((Path[2] != L'.') && (Path[2] != L'?')) return RtlPathTypeUncAbsolute;/* \\x */
1503  if (IS_PATH_SEPARATOR(Path[3])) return RtlPathTypeLocalDevice; /* \\.\x or \\?\x */
1504  if (Path[3]) return RtlPathTypeUncAbsolute; /* \\.x or \\?x */
1505  return RtlPathTypeRootLocalDevice; /* \\. or \\? */
1506  }
1507  else
1508  {
1509  if (!(Path[0]) || (Path[1] != L':')) return RtlPathTypeRelative; /* x */
1510  if (IS_PATH_SEPARATOR(Path[2])) return RtlPathTypeDriveAbsolute; /* x:\ */
1511  return RtlPathTypeDriveRelative; /* x: */
1512  }
1513 }
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
void DPRINT(...)
Definition: polytest.cpp:61
static const WCHAR L[]
Definition: oid.c:1250
PRTL_UNICODE_STRING_BUFFER Path

Referenced by RtlDosSearchPath_U(), RtlGetFullPathName_Ustr(), RtlpDosPathNameToRelativeNtPathName_Ustr(), and SkipPathTypeIndicator_U().

◆ RtlDetermineDosPathNameType_Ustr()

RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr ( IN PCUNICODE_STRING  PathString)

Definition at line 61 of file path.c.

62 {
63  PWCHAR Path;
64  ULONG Chars;
65 
66  Path = PathString->Buffer;
67  Chars = PathString->Length / sizeof(WCHAR);
68 
69  /* Return if there are no characters */
70  if (!Chars) return RtlPathTypeRelative;
71 
72  /*
73  * The algorithm is similar to RtlDetermineDosPathNameType_U but here we
74  * actually check for the path length before touching the characters
75  */
76  if (IS_PATH_SEPARATOR(Path[0]))
77  {
78  if ((Chars < 2) || !(IS_PATH_SEPARATOR(Path[1]))) return RtlPathTypeRooted; /* \x */
79  if ((Chars < 3) || ((Path[2] != L'.') && (Path[2] != L'?'))) return RtlPathTypeUncAbsolute;/* \\x */
80  if ((Chars >= 4) && (IS_PATH_SEPARATOR(Path[3]))) return RtlPathTypeLocalDevice; /* \\.\x or \\?\x */
81  if (Chars != 3) return RtlPathTypeUncAbsolute; /* \\.x or \\?x */
82  return RtlPathTypeRootLocalDevice; /* \\. or \\? */
83  }
84  else
85  {
86  if ((Chars < 2) || (Path[1] != L':')) return RtlPathTypeRelative; /* x */
87  if ((Chars < 3) || !(IS_PATH_SEPARATOR(Path[2]))) return RtlPathTypeDriveRelative; /* x: */
88  return RtlPathTypeDriveAbsolute; /* x:\ */
89  }
90 }
uint16_t * PWCHAR
Definition: typedefs.h:54
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
__wchar_t WCHAR
Definition: xmlstorage.h:180
static const WCHAR L[]
Definition: oid.c:1250
PRTL_UNICODE_STRING_BUFFER Path
unsigned int ULONG
Definition: retypes.h:1

Referenced by RtlDosSearchPath_Ustr(), RtlIsDosDeviceName_Ustr(), RtlNtPathNameToDosPathName(), and START_TEST().

◆ RtlDoesFileExists_U()

BOOLEAN NTAPI RtlDoesFileExists_U ( IN PCWSTR  FileName)

Definition at line 2910 of file path.c.

2911 {
2912  /* Call the new function */
2914 }
#define TRUE
Definition: types.h:120
BOOLEAN NTAPI RtlDoesFileExists_UEx(IN PCWSTR FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1392

Referenced by RtlpCheckDeviceName().

◆ RtlDoesFileExists_UEx()

BOOLEAN NTAPI RtlDoesFileExists_UEx ( IN PCWSTR  FileName,
IN BOOLEAN  SucceedIfBusy 
)

Definition at line 1392 of file path.c.

1394 {
1395  UNICODE_STRING NameString;
1396 
1397  /* Create the unicode name*/
1398  if (NT_SUCCESS(RtlInitUnicodeStringEx(&NameString, FileName)))
1399  {
1400  /* Call the unicode function */
1401  return RtlDoesFileExists_UstrEx(&NameString, SucceedIfBusy);
1402  }
1403 
1404  /* Fail */
1405  return FALSE;
1406 }
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static IN BOOLEAN SucceedIfBusy
BOOLEAN NTAPI RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1311
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)

Referenced by RtlDoesFileExists_U(), RtlDosSearchPath_U(), RtlDosSearchPath_Ustr(), and START_TEST().

◆ RtlDoesFileExists_UStr()

BOOLEAN NTAPI RtlDoesFileExists_UStr ( IN PUNICODE_STRING  FileName)

Definition at line 1384 of file path.c.

1385 {
1386  /* Call the updated API */
1388 }
#define TRUE
Definition: types.h:120
BOOLEAN NTAPI RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1311

Referenced by LdrpInitializeDotLocalSupport(), RtlDosApplyFileIsolationRedirection_Ustr(), and START_TEST().

◆ RtlDoesFileExists_UstrEx()

BOOLEAN NTAPI RtlDoesFileExists_UstrEx ( IN PCUNICODE_STRING  FileName,
IN BOOLEAN  SucceedIfBusy 
)

Definition at line 1311 of file path.c.

1313 {
1314  BOOLEAN Result;
1315  RTL_RELATIVE_NAME_U RelativeName;
1316  UNICODE_STRING NtPathName;
1317  PVOID Buffer;
1319  NTSTATUS Status;
1320  FILE_BASIC_INFORMATION BasicInformation;
1321 
1322  /* Get the NT Path */
1324  &NtPathName,
1325  NULL,
1326  &RelativeName);
1327  if (!Result) return FALSE;
1328 
1329  /* Save the buffer */
1330  Buffer = NtPathName.Buffer;
1331 
1332  /* Check if we have a relative name */
1333  if (RelativeName.RelativeName.Length)
1334  {
1335  /* Use it */
1336  NtPathName = RelativeName.RelativeName;
1337  }
1338  else
1339  {
1340  /* Otherwise ignore it */
1341  RelativeName.ContainingDirectory = NULL;
1342  }
1343 
1344  /* Initialize the object attributes */
1346  &NtPathName,
1348  RelativeName.ContainingDirectory,
1349  NULL);
1350 
1351  /* Query the attributes and free the buffer now */
1352  Status = ZwQueryAttributesFile(&ObjectAttributes, &BasicInformation);
1353  RtlReleaseRelativeName(&RelativeName);
1354  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1355 
1356  /* Check if we failed */
1357  if (!NT_SUCCESS(Status))
1358  {
1359  /* Check if we failed because the file is in use */
1360  if ((Status == STATUS_SHARING_VIOLATION) ||
1362  {
1363  /* Check if the caller wants this to be considered OK */
1365  }
1366  else
1367  {
1368  /* A failure because the file didn't exist */
1369  Result = FALSE;
1370  }
1371  }
1372  else
1373  {
1374  /* The file exists */
1375  Result = TRUE;
1376  }
1377 
1378  /* Return the result */
1379  return Result;
1380 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define TRUE
Definition: types.h:120
VOID NTAPI RtlReleaseRelativeName(IN PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1415
HANDLE ContainingDirectory
Definition: rtltypes.h:1375
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
Definition: bufpool.h:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_Ustr(IN PCUNICODE_STRING DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1295
static IN BOOLEAN SucceedIfBusy
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI ZwQueryAttributesFile(_In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PFILE_BASIC_INFORMATION FileInformation)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
UNICODE_STRING RelativeName
Definition: rtltypes.h:1374
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34

Referenced by LdrpSearchPath(), RtlDoesFileExists_UEx(), RtlDoesFileExists_UStr(), RtlDosSearchPath_Ustr(), and START_TEST().

◆ RtlDosPathNameToNtPathName_U()

BOOLEAN NTAPI RtlDosPathNameToNtPathName_U ( IN PCWSTR  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1889 of file path.c.

1893 {
1894  /* Call the internal function */
1896  DosName,
1897  NtName,
1898  PartName,
1899  RelativeName));
1900 }
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative, IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1268
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270

Referenced by RtlSetCurrentDirectory_U().

◆ RtlDosPathNameToNtPathName_U_WithStatus()

NTSTATUS NTAPI RtlDosPathNameToNtPathName_U_WithStatus ( IN PCWSTR  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1907 of file path.c.

1911 {
1912  /* Call the internal function */
1914  DosName,
1915  NtName,
1916  PartName,
1917  RelativeName);
1918 }
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative, IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1268
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270

◆ RtlDosPathNameToRelativeNtPathName_U()

BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U ( IN PCWSTR  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1925 of file path.c.

1929 {
1930  /* Call the internal function */
1931  ASSERT(RelativeName);
1933  DosName,
1934  NtName,
1935  PartName,
1936  RelativeName));
1937 }
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative, IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1268
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270

◆ RtlDosPathNameToRelativeNtPathName_U_WithStatus()

NTSTATUS NTAPI RtlDosPathNameToRelativeNtPathName_U_WithStatus ( IN PCWSTR  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1944 of file path.c.

1948 {
1949  /* Call the internal function */
1950  ASSERT(RelativeName);
1952  DosName,
1953  NtName,
1954  PartName,
1955  RelativeName);
1956 }
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative, IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1268
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270

◆ RtlDosPathNameToRelativeNtPathName_Ustr()

BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_Ustr ( IN PCUNICODE_STRING  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1295 of file path.c.

1299 {
1300  /* Call the internal function */
1301  ASSERT(RelativeName);
1303  DosName,
1304  NtName,
1305  PartName,
1306  RelativeName));
1307 }
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative, IN PCUNICODE_STRING DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1036
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270

Referenced by RtlDoesFileExists_UstrEx().

◆ RtlDosSearchPath_U()

ULONG NTAPI RtlDosSearchPath_U ( IN PCWSTR  Path,
IN PCWSTR  FileName,
IN PCWSTR  Extension,
IN ULONG  Size,
IN PWSTR  Buffer,
OUT PWSTR PartName 
)

Definition at line 2049 of file path.c.

2055 {
2056  NTSTATUS Status;
2057  ULONG ExtensionLength, Length, FileNameLength, PathLength;
2058  UNICODE_STRING TempString;
2059  PWCHAR NewBuffer, BufferStart;
2060  PCWSTR p;
2061 
2062  /* Check if this is an absolute path */
2064  {
2065  /* Check if the file exists */
2067  {
2068  /* Get the full name, which does the DOS lookup */
2069  return RtlGetFullPathName_U(FileName, Size, Buffer, PartName);
2070  }
2071 
2072  /* Doesn't exist, so fail */
2073  return 0;
2074  }
2075 
2076  /* Scan the filename */
2077  p = FileName;
2078  while (*p)
2079  {
2080  /* Looking for an extension */
2081  if (*p == L'.')
2082  {
2083  /* No extension string needed -- it's part of the filename */
2084  Extension = NULL;
2085  break;
2086  }
2087 
2088  /* Next character */
2089  p++;
2090  }
2091 
2092  /* Do we have an extension? */
2093  if (!Extension)
2094  {
2095  /* Nope, don't worry about one */
2096  ExtensionLength = 0;
2097  }
2098  else
2099  {
2100  /* Build a temporary string to get the extension length */
2101  Status = RtlInitUnicodeStringEx(&TempString, Extension);
2102  if (!NT_SUCCESS(Status)) return 0;
2103  ExtensionLength = TempString.Length;
2104  }
2105 
2106  /* Build a temporary string to get the path length */
2107  Status = RtlInitUnicodeStringEx(&TempString, Path);
2108  if (!NT_SUCCESS(Status)) return 0;
2109  PathLength = TempString.Length;
2110 
2111  /* Build a temporary string to get the filename length */
2112  Status = RtlInitUnicodeStringEx(&TempString, FileName);
2113  if (!NT_SUCCESS(Status)) return 0;
2114  FileNameLength = TempString.Length;
2115 
2116  /* Allocate the buffer for the new string name */
2117  NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
2118  0,
2119  FileNameLength +
2120  ExtensionLength +
2121  PathLength +
2122  3 * sizeof(WCHAR));
2123  if (!NewBuffer)
2124  {
2125  /* Fail the call */
2126  DbgPrint("%s: Failing due to out of memory (RtlAllocateHeap failure)\n",
2127  __FUNCTION__);
2128  return 0;
2129  }
2130 
2131  /* Final loop to build the path */
2132  while (TRUE)
2133  {
2134  /* Check if we have a valid character */
2135  BufferStart = NewBuffer;
2136  if (*Path)
2137  {
2138  /* Loop as long as there's no semicolon */
2139  while (*Path != L';')
2140  {
2141  /* Copy the next character */
2142  *BufferStart++ = *Path++;
2143  if (!*Path) break;
2144  }
2145 
2146  /* We found a semi-colon, to stop path processing on this loop */
2147  if (*Path == L';') ++Path;
2148  }
2149 
2150  /* Add a terminating slash if needed */
2151  if ((BufferStart != NewBuffer) && (BufferStart[-1] != OBJ_NAME_PATH_SEPARATOR))
2152  {
2153  *BufferStart++ = OBJ_NAME_PATH_SEPARATOR;
2154  }
2155 
2156  /* Bail out if we reached the end */
2157  if (!*Path) Path = NULL;
2158 
2159  /* Copy the file name and check if an extension is needed */
2160  RtlCopyMemory(BufferStart, FileName, FileNameLength);
2161  if (ExtensionLength)
2162  {
2163  /* Copy the extension too */
2164  RtlCopyMemory((PCHAR)BufferStart + FileNameLength,
2165  Extension,
2166  ExtensionLength + sizeof(WCHAR));
2167  }
2168  else
2169  {
2170  /* Just NULL-terminate */
2171  *(PWCHAR)((PCHAR)BufferStart + FileNameLength) = UNICODE_NULL;
2172  }
2173 
2174  /* Now, does this file exist? */
2175  if (RtlDoesFileExists_UEx(NewBuffer, FALSE))
2176  {
2177  /* Call the full-path API to get the length */
2178  Length = RtlGetFullPathName_U(NewBuffer, Size, Buffer, PartName);
2179  break;
2180  }
2181 
2182  /* If we got here, path doesn't exist, so fail the call */
2183  Length = 0;
2184  if (!Path) break;
2185  }
2186 
2187  /* Free the allocation and return the length */
2188  RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
2189  return Length;
2190 }
signed char * PCHAR
Definition: retypes.h:7
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define DbgPrint
Definition: loader.c:25
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
uint16_t * PWCHAR
Definition: typedefs.h:54
static USHORT PathLength
ULONG NTAPI RtlGetFullPathName_U(_In_ PCWSTR FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PWSTR *ShortName)
Definition: path.c:1868
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const WCHAR L[]
Definition: oid.c:1250
BOOLEAN NTAPI RtlDoesFileExists_UEx(IN PCWSTR FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1392
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(IN PCWSTR Path)
Definition: path.c:1494
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
Status
Definition: gdiplustypes.h:24
struct _FileName FileName
Definition: fatprocs.h:884
PRTL_UNICODE_STRING_BUFFER Path
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
unsigned int ULONG
Definition: retypes.h:1
GLfloat GLfloat p
Definition: glext.h:8902
#define __FUNCTION__
Definition: types.h:112
_Inout_opt_ PUNICODE_STRING Extension
Definition: fltkernel.h:1092

◆ RtlDosSearchPath_Ustr()

NTSTATUS NTAPI RtlDosSearchPath_Ustr ( IN ULONG  Flags,
IN PUNICODE_STRING  PathString,
IN PUNICODE_STRING  FileNameString,
IN PUNICODE_STRING  ExtensionString,
IN PUNICODE_STRING  CallerBuffer,
IN OUT PUNICODE_STRING DynamicString  OPTIONAL,
OUT PUNICODE_STRING *FullNameOut  OPTIONAL,
OUT PSIZE_T FilePartSize  OPTIONAL,
OUT PSIZE_T LengthNeeded  OPTIONAL 
)

Definition at line 2440 of file path.c.

2449 {
2450  WCHAR StaticCandidateBuffer[MAX_PATH];
2451  UNICODE_STRING StaticCandidateString;
2452  NTSTATUS Status;
2454  PWCHAR p, End, CandidateEnd, SegmentEnd;
2455  SIZE_T SegmentSize, ByteCount, PathSize, MaxPathSize = 0;
2456  USHORT NamePlusExtLength, WorstCaseLength, ExtensionLength = 0;
2457  PUNICODE_STRING FullIsolatedPath;
2458  DPRINT("DOS Path Search: %lx %wZ %wZ %wZ %wZ %wZ\n",
2459  Flags, PathString, FileNameString, ExtensionString, CallerBuffer, DynamicString);
2460 
2461  /* Initialize the input string */
2462  RtlInitEmptyUnicodeString(&StaticCandidateString,
2463  StaticCandidateBuffer,
2464  sizeof(StaticCandidateBuffer));
2465 
2466  /* Initialize optional arguments */
2467  if (FullNameOut ) *FullNameOut = NULL;
2468  if (FilePartSize) *FilePartSize = 0;
2469  if (LengthNeeded) *LengthNeeded = 0;
2470  if (DynamicString)
2471  {
2474  }
2475 
2476  /* Check for invalid parameters */
2477  if ((Flags & ~7) ||
2478  !(PathString) ||
2479  !(FileNameString) ||
2480  ((CallerBuffer) && (DynamicString) && !(FullNameOut)))
2481  {
2482  /* Fail */
2483  DbgPrint("%s: Invalid parameters passed\n", __FUNCTION__);
2485  goto Quickie;
2486  }
2487 
2488  /* First check what kind of path this is */
2489  PathType = RtlDetermineDosPathNameType_Ustr(FileNameString);
2490 
2491  /* Check if the caller wants to prevent relative .\ and ..\ paths */
2492  if ((Flags & 2) &&
2494  (FileNameString->Length >= (2 * sizeof(WCHAR))) &&
2495  (FileNameString->Buffer[0] == L'.') &&
2496  ((IS_PATH_SEPARATOR(FileNameString->Buffer[1])) ||
2497  ((FileNameString->Buffer[1] == L'.') &&
2498  ((FileNameString->Length >= (3 * sizeof(WCHAR))) &&
2499  (IS_PATH_SEPARATOR(FileNameString->Buffer[2]))))))
2500  {
2501  /* Yes, and this path is like that, so make it seem unknown */
2503  }
2504 
2505  /* Now check relative vs non-relative paths */
2507  {
2508  /* Does the caller want SxS? */
2509  if (Flags & 1)
2510  {
2511  /* Apply the SxS magic */
2512  FullIsolatedPath = NULL;
2514  FileNameString,
2515  ExtensionString,
2516  CallerBuffer,
2517  DynamicString,
2518  &FullIsolatedPath,
2519  NULL,
2520  FilePartSize,
2521  LengthNeeded);
2522  if (NT_SUCCESS(Status))
2523  {
2524  /* We found the SxS path, return it */
2525  if (FullNameOut) *FullNameOut = FullIsolatedPath;
2526  goto Quickie;
2527  }
2528  else if (Status != STATUS_SXS_KEY_NOT_FOUND)
2529  {
2530  /* Critical SxS error, fail */
2531  DbgPrint("%s: Failing because call to "
2532  "RtlDosApplyIsolationRedirection_Ustr(%wZ) failed with "
2533  "status 0x%08lx\n",
2534  __FUNCTION__,
2535  FileNameString,
2536  Status);
2537  goto Quickie;
2538  }
2539  }
2540 
2541  /* No SxS key found, or not requested, check if there's an extension */
2542  if (ExtensionString)
2543  {
2544  /* Save the extension length, and check if there's a file name */
2545  ExtensionLength = ExtensionString->Length;
2546  if (FileNameString->Length)
2547  {
2548  /* Start parsing the file name */
2549  End = &FileNameString->Buffer[FileNameString->Length / sizeof(WCHAR)];
2550  while (End > FileNameString->Buffer)
2551  {
2552  /* If we find a path separator, there's no extension */
2553  if (IS_PATH_SEPARATOR(*--End)) break;
2554 
2555  /* Otherwise, did we find an extension dot? */
2556  if (*End == L'.')
2557  {
2558  /* Ignore what the caller sent it, use the filename's */
2559  ExtensionString = NULL;
2560  ExtensionLength = 0;
2561  break;
2562  }
2563  }
2564  }
2565  }
2566 
2567  /* Check if we got a path */
2568  if (PathString->Length)
2569  {
2570  /* Start parsing the path name, looking for path separators */
2571  End = &PathString->Buffer[PathString->Length / sizeof(WCHAR)];
2572  p = End;
2573  while ((p > PathString->Buffer) && (*--p == L';'))
2574  {
2575  /* This is the size of the path -- handle a trailing slash */
2576  PathSize = End - p - 1;
2577  if ((PathSize) && !(IS_PATH_SEPARATOR(*(End - 1)))) PathSize++;
2578 
2579  /* Check if we found a bigger path than before */
2580  if (PathSize > MaxPathSize) MaxPathSize = PathSize;
2581 
2582  /* Keep going with the path after this path separator */
2583  End = p;
2584  }
2585 
2586  /* This is the trailing path, run the same code as above */
2587  PathSize = End - p;
2588  if ((PathSize) && !(IS_PATH_SEPARATOR(*(End - 1)))) PathSize++;
2589  if (PathSize > MaxPathSize) MaxPathSize = PathSize;
2590 
2591  /* Finally, convert the largest path size into WCHAR */
2592  MaxPathSize *= sizeof(WCHAR);
2593  }
2594 
2595  /* Use the extension, the file name, and the largest path as the size */
2596  WorstCaseLength = ExtensionLength +
2597  FileNameString->Length +
2598  (USHORT)MaxPathSize +
2599  sizeof(UNICODE_NULL);
2600  if (WorstCaseLength > UNICODE_STRING_MAX_BYTES)
2601  {
2602  /* It has to fit in a registry string, if not, fail here */
2603  DbgPrint("%s returning STATUS_NAME_TOO_LONG because the computed "
2604  "worst case file name length is %Iu bytes\n",
2605  __FUNCTION__,
2606  WorstCaseLength);
2608  goto Quickie;
2609  }
2610 
2611  /* Scan the path now, to see if we can find the file */
2612  p = PathString->Buffer;
2613  End = &p[PathString->Length / sizeof(WCHAR)];
2614  while (p < End)
2615  {
2616  /* Find out where this path ends */
2617  for (SegmentEnd = p;
2618  ((SegmentEnd != End) && (*SegmentEnd != L';'));
2619  SegmentEnd++);
2620 
2621  /* Compute the size of this path */
2622  ByteCount = SegmentSize = (SegmentEnd - p) * sizeof(WCHAR);
2623 
2624  /* Handle trailing slash if there isn't one */
2625  if ((SegmentSize) && !(IS_PATH_SEPARATOR(*(SegmentEnd - 1))))
2626  {
2627  /* Add space for one */
2629  }
2630 
2631  /* Now check if our initial static buffer is too small */
2632  if (StaticCandidateString.MaximumLength <
2633  (SegmentSize + ExtensionLength + FileNameString->Length))
2634  {
2635  /* At this point we should've been using our static buffer */
2636  ASSERT(StaticCandidateString.Buffer == StaticCandidateBuffer);
2637  if (StaticCandidateString.Buffer != StaticCandidateBuffer)
2638  {
2639  /* Something is really messed up if this was the dynamic string */
2640  DbgPrint("%s: internal error #1; "
2641  "CandidateString.Buffer = %p; "
2642  "StaticCandidateBuffer = %p\n",
2643  __FUNCTION__,
2644  StaticCandidateString.Buffer,
2645  StaticCandidateBuffer);
2647  goto Quickie;
2648  }
2649 
2650  /* We checked before that the maximum possible size shoudl fit! */
2651  ASSERT((SegmentSize + FileNameString->Length + ExtensionLength) <
2653  if ((SegmentSize + ExtensionLength + FileNameString->Length) >
2654  (UNICODE_STRING_MAX_BYTES - sizeof(WCHAR)))
2655  {
2656  /* For some reason it's not fitting anymore. Something messed up */
2657  DbgPrint("%s: internal error #2; SegmentSize = %u, "
2658  "FileName->Length = %u, DefaultExtensionLength = %u\n",
2659  __FUNCTION__,
2660  SegmentSize,
2661  FileNameString->Length,
2662  ExtensionLength);
2664  goto Quickie;
2665  }
2666 
2667  /* Now allocate the dynamic string */
2668  StaticCandidateString.MaximumLength = FileNameString->Length +
2669  WorstCaseLength;
2670  StaticCandidateString.Buffer = RtlpAllocateStringMemory(WorstCaseLength,
2671  TAG_USTR);
2672  if (!StaticCandidateString.Buffer)
2673  {
2674  /* Out of memory, fail */
2675  DbgPrint("%s: Unable to allocate %u byte buffer for path candidate\n",
2676  __FUNCTION__,
2677  StaticCandidateString.MaximumLength);
2679  goto Quickie;
2680  }
2681  }
2682 
2683  /* Copy the path in the string */
2684  RtlCopyMemory(StaticCandidateString.Buffer, p, ByteCount);
2685 
2686  /* Get to the end of the string, and add the trailing slash if missing */
2687  CandidateEnd = &StaticCandidateString.Buffer[ByteCount / sizeof(WCHAR)];
2688  if ((SegmentSize) && (SegmentSize != ByteCount))
2689  {
2690  *CandidateEnd++ = OBJ_NAME_PATH_SEPARATOR;
2691  }
2692 
2693  /* Copy the filename now */
2694  RtlCopyMemory(CandidateEnd,
2695  FileNameString->Buffer,
2696  FileNameString->Length);
2697  CandidateEnd += (FileNameString->Length / sizeof(WCHAR));
2698 
2699  /* Check if there was an extension */
2700  if (ExtensionString)
2701  {
2702  /* Copy the extension too */
2703  RtlCopyMemory(CandidateEnd,
2704  ExtensionString->Buffer,
2705  ExtensionString->Length);
2706  CandidateEnd += (ExtensionString->Length / sizeof(WCHAR));
2707  }
2708 
2709  /* We are done, terminate it */
2710  *CandidateEnd = UNICODE_NULL;
2711 
2712  /* Now set the final length of the string so it becomes valid */
2713  StaticCandidateString.Length = (USHORT)(CandidateEnd -
2714  StaticCandidateString.Buffer) *
2715  sizeof(WCHAR);
2716 
2717  /* Check if this file exists */
2718  DPRINT("BUFFER: %S\n", StaticCandidateString.Buffer);
2719  if (RtlDoesFileExists_UEx(StaticCandidateString.Buffer, FALSE))
2720  {
2721  /* Awesome, it does, now get the full path */
2722  Status = RtlGetFullPathName_UstrEx(&StaticCandidateString,
2723  CallerBuffer,
2724  DynamicString,
2725  (PUNICODE_STRING*)FullNameOut,
2726  FilePartSize,
2727  NULL,
2728  &PathType,
2729  LengthNeeded);
2730  if (!(NT_SUCCESS(Status)) &&
2731  ((Status != STATUS_NO_SUCH_FILE) &&
2733  {
2734  DbgPrint("%s: Failing because we thought we found %wZ on "
2735  "the search path, but RtlGetfullPathNameUStrEx() "
2736  "returned %08lx\n",
2737  __FUNCTION__,
2738  &StaticCandidateString,
2739  Status);
2740  }
2741  DPRINT("Status: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer);
2742  goto Quickie;
2743  }
2744  else
2745  {
2746  /* Otherwise, move to the next path */
2747  if (SegmentEnd != End)
2748  {
2749  /* Handle the case of the path separator trailing */
2750  p = SegmentEnd + 1;
2751  }
2752  else
2753  {
2754  p = SegmentEnd;
2755  }
2756  }
2757  }
2758 
2759  /* Loop finished and we didn't break out -- fail */
2761  }
2762  else
2763  {
2764  /* We have a full path, so check if it does exist */
2765  DPRINT("%wZ\n", FileNameString);
2766  if (!RtlDoesFileExists_UstrEx(FileNameString, TRUE))
2767  {
2768  /* It doesn't exist, did we have an extension? */
2769  if (!(ExtensionString) || !(ExtensionString->Length))
2770  {
2771  /* No extension, so just fail */
2773  goto Quickie;
2774  }
2775 
2776  /* There was an extension, check if the filename already had one */
2777  if (!(Flags & 4) && (FileNameString->Length))
2778  {
2779  /* Parse the filename */
2780  p = FileNameString->Buffer;
2781  End = &p[FileNameString->Length / sizeof(WCHAR)];
2782  while (End > p)
2783  {
2784  /* If there's a path separator, there's no extension */
2785  if (IS_PATH_SEPARATOR(*--End)) break;
2786 
2787  /* Othwerwise, did we find an extension dot? */
2788  if (*End == L'.')
2789  {
2790  /* File already had an extension, so fail */
2792  goto Quickie;
2793  }
2794  }
2795  }
2796 
2797  /* So there is an extension, we'll try again by adding it */
2798  NamePlusExtLength = FileNameString->Length +
2799  ExtensionString->Length +
2800  sizeof(UNICODE_NULL);
2801  if (NamePlusExtLength > UNICODE_STRING_MAX_BYTES)
2802  {
2803  /* It won't fit in any kind of valid string, so fail */
2804  DbgPrint("%s: Failing because filename plus extension (%Iu bytes) is too big\n",
2805  __FUNCTION__,
2806  NamePlusExtLength);
2808  goto Quickie;
2809  }
2810 
2811  /* Fill it fit in our temporary string? */
2812  if (NamePlusExtLength > StaticCandidateString.MaximumLength)
2813  {
2814  /* It won't fit anymore, allocate a dynamic string for it */
2815  StaticCandidateString.MaximumLength = NamePlusExtLength;
2816  StaticCandidateString.Buffer = RtlpAllocateStringMemory(NamePlusExtLength,
2817  TAG_USTR);
2818  if (!StaticCandidateString.Buffer)
2819  {
2820  /* Ran out of memory, so fail */
2821  DbgPrint("%s: Failing because allocating the dynamic filename buffer failed\n",
2822  __FUNCTION__);
2824  goto Quickie;
2825  }
2826  }
2827 
2828  /* Copy the filename */
2829  RtlCopyUnicodeString(&StaticCandidateString, FileNameString);
2830 
2831  /* Copy the extension */
2832  RtlAppendUnicodeStringToString(&StaticCandidateString,
2833  ExtensionString);
2834 
2835  DPRINT("SB: %wZ\n", &StaticCandidateString);
2836 
2837  /* And check if this file now exists */
2838  if (!RtlDoesFileExists_UstrEx(&StaticCandidateString, TRUE))
2839  {
2840  /* Still no joy, fail out */
2842  goto Quickie;
2843  }
2844 
2845  /* File was found, get the final full path */
2846  Status = RtlGetFullPathName_UstrEx(&StaticCandidateString,
2847  CallerBuffer,
2848  DynamicString,
2849  (PUNICODE_STRING*)FullNameOut,
2850  FilePartSize,
2851  NULL,
2852  &PathType,
2853  LengthNeeded);
2854  if (!(NT_SUCCESS(Status)) && (Status != STATUS_NO_SUCH_FILE))
2855  {
2856  DbgPrint("%s: Failing on \"%wZ\" because RtlGetfullPathNameUStrEx() "
2857  "failed with status %08lx\n",
2858  __FUNCTION__,
2859  &StaticCandidateString,
2860  Status);
2861  }
2862  DPRINT("Status: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer);
2863  }
2864  else
2865  {
2866  /* File was found on the first try, get the final full path */
2867  Status = RtlGetFullPathName_UstrEx(FileNameString,
2868  CallerBuffer,
2869  DynamicString,
2870  (PUNICODE_STRING*)FullNameOut,
2871  FilePartSize,
2872  NULL,
2873  &PathType,
2874  LengthNeeded);
2875  if (!(NT_SUCCESS(Status)) &&
2876  ((Status != STATUS_NO_SUCH_FILE) &&
2878  {
2879  DbgPrint("%s: Failing because RtlGetfullPathNameUStrEx() on %wZ "
2880  "failed with status %08lx\n",
2881  __FUNCTION__,
2882  FileNameString,
2883  Status);
2884  }
2885  DPRINT("Status: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer);
2886  }
2887  }
2888 
2889 Quickie:
2890  /* Anything that was not an error, turn into STATUS_SUCCESS */
2892 
2893  /* Check if we had a dynamic string */
2894  if ((StaticCandidateString.Buffer) &&
2895  (StaticCandidateString.Buffer != StaticCandidateBuffer))
2896  {
2897  /* Free it */
2898  RtlFreeUnicodeString(&StaticCandidateString);
2899  }
2900 
2901  /* Return the status */
2902  return Status;
2903 }
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:61
enum _RTL_PATH_TYPE RTL_PATH_TYPE
NTSTATUS NTAPI RtlGetFullPathName_UstrEx(IN PUNICODE_STRING FileName, IN PUNICODE_STRING StaticString, IN PUNICODE_STRING DynamicString, IN PUNICODE_STRING *StringUsed, IN PSIZE_T FilePartSize, OUT PBOOLEAN NameInvalid, OUT RTL_PATH_TYPE *PathType, OUT PSIZE_T LengthNeeded)
Definition: path.c:2197
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define DbgPrint
Definition: loader.c:25
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
#define RtlpAllocateStringMemory
Definition: rtlp.h:140
#define STATUS_SXS_KEY_NOT_FOUND
Definition: ntstatus.h:1170
uint16_t * PWCHAR
Definition: typedefs.h:54
#define UNICODE_STRING_MAX_BYTES
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MAX_PATH
Definition: compat.h:26
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
BOOLEAN NTAPI RtlDoesFileExists_UEx(IN PCWSTR FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1392
NTSYSAPI NTSTATUS NTAPI RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags, IN PUNICODE_STRING OriginalName, IN PUNICODE_STRING Extension, IN OUT PUNICODE_STRING StaticString, IN OUT PUNICODE_STRING DynamicString, IN OUT PUNICODE_STRING *NewName, IN PULONG NewFlags, IN PSIZE_T FileNameSize, IN PSIZE_T RequiredLength)
Definition: libsupp.c:778
_Inout_ PVOID _In_ ULONG SegmentSize
Definition: exfuncs.h:893
#define TAG_USTR
Definition: libsupp.c:111
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
BOOLEAN NTAPI RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName, IN BOOLEAN SucceedIfBusy)
Definition: path.c:1311
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION _In_ ULONG _Out_opt_ PULONG LengthNeeded
Definition: fltkernel.h:1342
GLfloat GLfloat p
Definition: glext.h:8902
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define __FUNCTION__
Definition: types.h:112
IN PUNICODE_STRING IN PUNICODE_STRING DynamicString

Referenced by SearchPathW().

◆ RtlGetCurrentDirectory_U()

ULONG NTAPI RtlGetCurrentDirectory_U ( _In_ ULONG  MaximumLength,
_Out_bytecap_(MaximumLength) PWSTR  Buffer 
)

Definition at line 1542 of file path.c.

1545 {
1546  ULONG Length, Bytes;
1547  PCURDIR CurDir;
1548  PWSTR CurDirName;
1549  DPRINT("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer);
1550 
1551  /* Lock the PEB to get the current directory */
1553  CurDir = &NtCurrentPeb()->ProcessParameters->CurrentDirectory;
1554 
1555  /* Get the buffer and character length */
1556  CurDirName = CurDir->DosPath.Buffer;
1557  Length = CurDir->DosPath.Length / sizeof(WCHAR);
1558  ASSERT((CurDirName != NULL) && (Length > 0));
1559 
1560  /*
1561  * DosPath.Buffer should always have a trailing slash. There is an assert
1562  * below which checks for this.
1563  *
1564  * This function either returns x:\ for a root (keeping the original buffer)
1565  * or it returns x:\path\foo for a directory (replacing the trailing slash
1566  * with a NULL.
1567  */
1568  Bytes = Length * sizeof(WCHAR);
1569  if ((Length <= 1) || (CurDirName[Length - 2] == L':'))
1570  {
1571  /* Check if caller does not have enough space */
1572  if (MaximumLength <= Bytes)
1573  {
1574  /* Call has no space for it, fail, add the trailing slash */
1576  return Bytes + sizeof(OBJ_NAME_PATH_SEPARATOR);
1577  }
1578  }
1579  else
1580  {
1581  /* Check if caller does not have enough space */
1582  if (MaximumLength < Bytes)
1583  {
1584  /* Call has no space for it, fail */
1586  return Bytes;
1587  }
1588  }
1589 
1590  /* Copy the buffer since we seem to have space */
1591  RtlCopyMemory(Buffer, CurDirName, Bytes);
1592 
1593  /* The buffer should end with a path separator */
1595 
1596  /* Again check for our two cases (drive root vs path) */
1597  if ((Length <= 1) || (Buffer[Length - 2] != L':'))
1598  {
1599  /* Replace the trailing slash with a null */
1600  Buffer[Length - 1] = UNICODE_NULL;
1601  --Length;
1602  }
1603  else
1604  {
1605  /* Append the null char since there's no trailing slash */
1607  }
1608 
1609  /* Release PEB lock */
1611  DPRINT("CurrentDirectory %S\n", Buffer);
1612  return Length * sizeof(WCHAR);
1613 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint16_t * PWSTR
Definition: typedefs.h:54
_In_ UINT Bytes
Definition: mmcopy.h:9
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
#define NtCurrentPeb()
Definition: FLS.c:19
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
UNICODE_STRING DosPath
Definition: rtltypes.h:1362
unsigned int ULONG
Definition: retypes.h:1

Referenced by GetCurrentDirectoryA(), GetCurrentDirectoryW(), and GetDriveTypeW().

◆ RtlGetFullPathName_U()

ULONG NTAPI RtlGetFullPathName_U ( _In_ PCWSTR  FileName,
_In_ ULONG  Size,
_Out_z_bytecap_(Size) PWSTR  Buffer,
_Out_opt_ PWSTR ShortName 
)

Definition at line 1868 of file path.c.

1873 {
1875 
1876  /* Call the extended function */
1878  Size,
1879  Buffer,
1880  ShortName,
1881  &PathType);
1882 }
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1294
enum _RTL_PATH_TYPE RTL_PATH_TYPE
uint16_t * PWSTR
Definition: typedefs.h:54
ULONG NTAPI RtlGetFullPathName_UEx(_In_ PWSTR FileName, _In_ ULONG BufferLength, _Out_writes_bytes_(BufferLength) PWSTR Buffer, _Out_opt_ PWSTR *FilePart, _Out_opt_ RTL_PATH_TYPE *InputPathType)
Definition: path.c:1823
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
Definition: bufpool.h:45
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359

Referenced by GetFullPathNameA(), GetFullPathNameW(), lookup_assembly(), RtlDosSearchPath_U(), RunTestCases(), and START_TEST().

◆ RtlGetFullPathName_UEx()

ULONG NTAPI RtlGetFullPathName_UEx ( _In_ PWSTR  FileName,
_In_ ULONG  BufferLength,
_Out_writes_bytes_(BufferLength) PWSTR  Buffer,
_Out_opt_ PWSTR FilePart,
_Out_opt_ RTL_PATH_TYPE InputPathType 
)

Definition at line 1823 of file path.c.

1829 {
1830  UNICODE_STRING FileNameString;
1831  NTSTATUS status;
1832 
1833  if (InputPathType)
1834  *InputPathType = 0;
1835 
1836  /* Build the string */
1837  status = RtlInitUnicodeStringEx(&FileNameString, FileName);
1838  if (!NT_SUCCESS(status)) return 0;
1839 
1840  /* Call the extended function */
1841  return RtlGetFullPathName_Ustr(
1842  &FileNameString,
1843  BufferLength,
1844  Buffer,
1845  (PCWSTR*)FilePart,
1846  NULL,
1847  InputPathType);
1848 }
const uint16_t * PCWSTR
Definition: typedefs.h:55
LONG NTSTATUS
Definition: precomp.h:26
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:615
_In_ ULONG BufferLength
Definition: usbdlib.h:225
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by RtlGetFullPathName_U().

◆ RtlGetFullPathName_Ustr()

ULONG NTAPI RtlGetFullPathName_Ustr ( _In_ PUNICODE_STRING  FileName,
_In_ ULONG  Size,
_Out_z_bytecap_(Size) PWSTR  Buffer,
_Out_opt_ PCWSTR ShortName,
_Out_opt_ PBOOLEAN  InvalidName,
_Out_ RTL_PATH_TYPE PathType 
)

Definition at line 615 of file path.c.

622 {
625  ULONG FileNameLength, FileNameChars, DosLength, DosLengthOffset, FullLength;
626  BOOLEAN SkipTrailingPathSeparators;
627  WCHAR c;
628 
629 
630  ULONG reqsize = 0;
631  PCWSTR ptr;
632 
633  PCUNICODE_STRING CurDirName;
634  UNICODE_STRING EnvVarName, EnvVarValue;
635  WCHAR EnvVarNameBuffer[4];
636 
637  ULONG PrefixCut = 0; // Where the path really starts (after the skipped prefix)
638  PWCHAR Prefix = NULL; // pointer to the string to be inserted as the new path prefix
639  ULONG PrefixLength = 0;
640  PWCHAR Source;
641  ULONG SourceLength;
642 
643 
644  /* For now, assume the name is valid */
645  DPRINT("Filename: %wZ\n", FileName);
646  DPRINT("Size and buffer: %lx %p\n", Size, Buffer);
647  if (InvalidName) *InvalidName = FALSE;
648 
649  /* Handle initial path type and failure case */
651  if ((FileName->Length == 0) || (FileName->Buffer[0] == UNICODE_NULL)) return 0;
652 
653  /* Break filename into component parts */
654  FileNameBuffer = FileName->Buffer;
655  FileNameLength = FileName->Length;
656  FileNameChars = FileNameLength / sizeof(WCHAR);
657 
658  /* Kill trailing spaces */
659  c = FileNameBuffer[FileNameChars - 1];
660  while ((FileNameLength != 0) && (c == L' '))
661  {
662  /* Keep going, ignoring the spaces */
663  FileNameLength -= sizeof(WCHAR);
664  if (FileNameLength != 0) c = FileNameBuffer[FileNameLength / sizeof(WCHAR) - 1];
665  }
666 
667  /* Check if anything is left */
668  if (FileNameLength == 0) return 0;
669 
670  /*
671  * Check whether we'll need to skip trailing path separators in the
672  * computed full path name. If the original file name already contained
673  * trailing separators, then we keep them in the full path name. On the
674  * other hand, if the original name didn't contain any trailing separators
675  * then we'll skip it in the full path name.
676  */
677  SkipTrailingPathSeparators = !IS_PATH_SEPARATOR(FileNameBuffer[FileNameChars - 1]);
678 
679  /* Check if this is a DOS name */
680  DosLength = RtlIsDosDeviceName_Ustr(FileName);
681  DPRINT("DOS length for filename: %lx %wZ\n", DosLength, FileName);
682  if (DosLength != 0)
683  {
684  /* Zero out the short name */
685  if (ShortName) *ShortName = NULL;
686 
687  /* See comment for RtlIsDosDeviceName_Ustr if this is confusing... */
688  DosLengthOffset = HIWORD(DosLength);
689  DosLength = LOWORD(DosLength);
690 
691  /* Do we have a DOS length, and does the caller want validity? */
692  if (InvalidName && (DosLengthOffset != 0))
693  {
694  /* Do the check */
695  Status = RtlpCheckDeviceName(FileName, DosLengthOffset, InvalidName);
696 
697  /* If the check failed, or the name is invalid, fail here */
698  if (!NT_SUCCESS(Status)) return 0;
699  if (*InvalidName) return 0;
700  }
701 
702  /* Add the size of the device root and check if it fits in the size */
703  FullLength = DosLength + DeviceRootString.Length;
704  if (FullLength < Size)
705  {
706  /* Add the device string */
708 
709  /* Now add the DOS device name */
711  (PCHAR)FileNameBuffer + DosLengthOffset,
712  DosLength);
713 
714  /* Null terminate */
715  *(PWCHAR)((ULONG_PTR)Buffer + FullLength) = UNICODE_NULL;
716  return FullLength;
717  }
718 
719  /* Otherwise, there's no space, so return the buffer size needed */
720  if ((FullLength + sizeof(UNICODE_NULL)) > UNICODE_STRING_MAX_BYTES) return 0;
721  return FullLength + sizeof(UNICODE_NULL);
722  }
723 
724  /* Zero-out the destination buffer. FileName must be different from Buffer */
726 
727  /* Get the path type */
729 
730 
731 
732  /**********************************************
733  ** CODE REWRITING IS HAPPENING THERE **
734  **********************************************/
736  SourceLength = FileNameLength;
737  EnvVarValue.Buffer = NULL;
738 
739  /* Lock the PEB to get the current directory */
741  CurDirName = &NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath;
742 
743  switch (*PathType)
744  {
745  case RtlPathTypeUncAbsolute: /* \\foo */
746  {
747  PrefixCut = RtlpSkipUNCPrefix(FileNameBuffer);
748  break;
749  }
750 
751  case RtlPathTypeLocalDevice: /* \\.\foo */
752  {
753  PrefixCut = 4;
754  break;
755  }
756 
757  case RtlPathTypeDriveAbsolute: /* c:\foo */
758  {
759  ASSERT(FileNameBuffer[1] == L':');
761 
762  // FileNameBuffer[0] = RtlpUpcaseUnicodeChar(FileNameBuffer[0]);
764  PrefixLength = 3 * sizeof(WCHAR);
765  Source += 3;
766  SourceLength -= 3 * sizeof(WCHAR);
767 
768  PrefixCut = 3;
769  break;
770  }
771 
772  case RtlPathTypeDriveRelative: /* c:foo */
773  {
774  WCHAR CurDrive, NewDrive;
775 
776  Source += 2;
777  SourceLength -= 2 * sizeof(WCHAR);
778 
779  CurDrive = RtlpUpcaseUnicodeChar(CurDirName->Buffer[0]);
780  NewDrive = RtlpUpcaseUnicodeChar(FileNameBuffer[0]);
781 
782  if ((NewDrive != CurDrive) || CurDirName->Buffer[1] != L':')
783  {
784  EnvVarNameBuffer[0] = L'=';
785  EnvVarNameBuffer[1] = NewDrive;
786  EnvVarNameBuffer[2] = L':';
787  EnvVarNameBuffer[3] = UNICODE_NULL;
788 
789  EnvVarName.Length = 3 * sizeof(WCHAR);
790  EnvVarName.MaximumLength = EnvVarName.Length + sizeof(WCHAR);
791  EnvVarName.Buffer = EnvVarNameBuffer;
792 
793  // FIXME: Is it possible to use the user-given buffer ?
794  // RtlInitEmptyUnicodeString(&EnvVarValue, NULL, Size);
795  EnvVarValue.Length = 0;
796  EnvVarValue.MaximumLength = (USHORT)Size;
797  EnvVarValue.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
798  if (EnvVarValue.Buffer == NULL)
799  {
800  Prefix = NULL;
801  PrefixLength = 0;
802  goto Quit;
803  }
804 
805  Status = RtlQueryEnvironmentVariable_U(NULL, &EnvVarName, &EnvVarValue);
806  switch (Status)
807  {
808  case STATUS_SUCCESS:
809  /*
810  * (From Wine)
811  * FIXME: Win2k seems to check that the environment
812  * variable actually points to an existing directory.
813  * If not, root of the drive is used (this seems also
814  * to be the only place in RtlGetFullPathName that the
815  * existence of a part of a path is checked).
816  */
817  EnvVarValue.Buffer[EnvVarValue.Length / sizeof(WCHAR)] = L'\\';
818  Prefix = EnvVarValue.Buffer;
819  PrefixLength = EnvVarValue.Length + sizeof(WCHAR); /* Append trailing '\\' */
820  break;
821 
823  reqsize = EnvVarValue.Length + SourceLength + sizeof(UNICODE_NULL);
824  goto Quit;
825 
826  default:
827  DPRINT1("RtlQueryEnvironmentVariable_U(\"%wZ\") returned 0x%08lx\n", &EnvVarName, Status);
828 
829  EnvVarNameBuffer[0] = NewDrive;
830  EnvVarNameBuffer[1] = L':';
831  EnvVarNameBuffer[2] = L'\\';
832  EnvVarNameBuffer[3] = UNICODE_NULL;
833  Prefix = EnvVarNameBuffer;
834  PrefixLength = 3 * sizeof(WCHAR);
835 
836  RtlFreeHeap(RtlGetProcessHeap(), 0, EnvVarValue.Buffer);
837  EnvVarValue.Buffer = NULL;
838  break;
839  }
840  PrefixCut = 3;
841  break;
842  }
843  /* Fall through */
844  DPRINT("RtlPathTypeDriveRelative - Using fall-through to RtlPathTypeRelative\n");
845  }
846 
847  case RtlPathTypeRelative: /* foo */
848  {
849  Prefix = CurDirName->Buffer;
850  PrefixLength = CurDirName->Length;
851  if (CurDirName->Buffer[1] != L':')
852  {
853  PrefixCut = RtlpSkipUNCPrefix(CurDirName->Buffer);
854  }
855  else
856  {
857  PrefixCut = 3;
858  }
859  break;
860  }
861 
862  case RtlPathTypeRooted: /* \xxx */
863  {
864  if (CurDirName->Buffer[1] == L':')
865  {
866  // The path starts with "C:\"
867  ASSERT(CurDirName->Buffer[1] == L':');
868  ASSERT(IS_PATH_SEPARATOR(CurDirName->Buffer[2]));
869 
870  Prefix = CurDirName->Buffer;
871  PrefixLength = 3 * sizeof(WCHAR); // Skip "C:\"
872 
873  PrefixCut = 3; // Source index location incremented of + 3
874  }
875  else
876  {
877  PrefixCut = RtlpSkipUNCPrefix(CurDirName->Buffer);
878  PrefixLength = PrefixCut * sizeof(WCHAR);
879  Prefix = CurDirName->Buffer;
880  }
881  break;
882  }
883 
884  case RtlPathTypeRootLocalDevice: /* \\. */
885  {
887  PrefixLength = DeviceRootString.Length;
888  Source += 3;
889  SourceLength -= 3 * sizeof(WCHAR);
890 
891  PrefixCut = 4;
892  break;
893  }
894 
895  case RtlPathTypeUnknown:
896  goto Quit;
897  }
898 
899  /* Do we have enough space for storing the full path? */
900  reqsize = PrefixLength;
901  if (reqsize + SourceLength + sizeof(WCHAR) > Size)
902  {
903  /* Not enough space, return needed size (including terminating '\0') */
904  reqsize += SourceLength + sizeof(WCHAR);
905  goto Quit;
906  }
907 
908  /*
909  * Build the full path
910  */
911  /* Copy the path's prefix */
912  if (PrefixLength) RtlMoveMemory(Buffer, Prefix, PrefixLength);
913  /* Copy the remaining part of the path */
914  RtlMoveMemory(Buffer + PrefixLength / sizeof(WCHAR), Source, SourceLength + sizeof(WCHAR));
915 
916  /* Some cleanup */
917  Prefix = NULL;
918  if (EnvVarValue.Buffer)
919  {
920  RtlFreeHeap(RtlGetProcessHeap(), 0, EnvVarValue.Buffer);
921  EnvVarValue.Buffer = NULL;
922  }
923 
924  /*
925  * Finally, put the path in canonical form (remove redundant . and ..,
926  * (back)slashes...) and retrieve the length of the full path name
927  * (without its terminating null character) (in chars).
928  */
929  reqsize = RtlpCollapsePath(Buffer, /* Size, reqsize, */ PrefixCut, SkipTrailingPathSeparators);
930 
931  /* Find the file part, which is present after the last path separator */
932  if (ShortName)
933  {
934  ptr = wcsrchr(Buffer, L'\\');
935  if (ptr) ++ptr; // Skip it
936 
937  /*
938  * For UNC paths, the file part is after the \\share\dir part of the path.
939  */
940  PrefixCut = (*PathType == RtlPathTypeUncAbsolute ? PrefixCut : 3);
941 
942  if (ptr && *ptr && (ptr >= Buffer + PrefixCut))
943  {
944  *ShortName = ptr;
945  }
946  else
947  {
948  /* Zero-out the short name */
949  *ShortName = NULL;
950  }
951  }
952 
953 Quit:
954  /* Release PEB lock */
956 
957  return reqsize;
958 }
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1294
signed char * PCHAR
Definition: retypes.h:7
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN InvalidName
ULONG NTAPI RtlIsDosDeviceName_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:94
const uint16_t * PCWSTR
Definition: typedefs.h:55
_In_ __drv_aliasesMem PSTRING Prefix
Definition: rtlfuncs.h:1631
USHORT MaximumLength
Definition: env_spec_w32.h:370
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
uint16_t * PWCHAR
Definition: typedefs.h:54
#define UNICODE_STRING_MAX_BYTES
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
uint32_t ULONG_PTR
Definition: typedefs.h:63
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
static SIZE_T RtlpSkipUNCPrefix(PCWSTR FileNameBuffer)
Definition: path.c:431
#define UNICODE_NULL
static PVOID ptr
Definition: dispmode.c:27
unsigned char BOOLEAN
NTSYSAPI NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(_In_opt_ PWSTR Environment, _In_ PCUNICODE_STRING Name, _Out_ PUNICODE_STRING Value)
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static ULONG RtlpCollapsePath(PWSTR Path, ULONG mark, BOOLEAN SkipTrailingPathSeparators)
Definition: path.c:306
const GLubyte * c
Definition: glext.h:8905
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(IN PCWSTR Path)
Definition: path.c:1494
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
Status
Definition: gdiplustypes.h:24
#define NtCurrentPeb()
Definition: FLS.c:19
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI RtlpCheckDeviceName(IN PUNICODE_STRING FileName, IN ULONG Length, OUT PBOOLEAN NameInvalid)
Definition: path.c:255
WCHAR NTAPI RtlpUpcaseUnicodeChar(IN WCHAR Source)
Definition: nls.c:715
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
#define DPRINT1
Definition: precomp.h:8
WCHAR FileNameBuffer[_MAX_PATH]
Definition: framewnd.c:239
#define c
Definition: ke_i.h:80
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3149
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define LOWORD(l)
Definition: pedump.c:82
const UNICODE_STRING DeviceRootString
Definition: path.c:34

Referenced by LdrpResolveFullName(), RtlGetFullPathName_UEx(), RtlGetFullPathName_UstrEx(), RtlpDosPathNameToRelativeNtPathName_Ustr(), RtlSetCurrentDirectory_U(), RunTestCases(), and START_TEST().

◆ RtlGetFullPathName_UstrEx()

NTSTATUS NTAPI RtlGetFullPathName_UstrEx ( IN PUNICODE_STRING  FileName,
IN PUNICODE_STRING  StaticString,
IN PUNICODE_STRING  DynamicString,
IN PUNICODE_STRING StringUsed,
IN PSIZE_T  FilePartSize,
OUT PBOOLEAN  NameInvalid,
OUT RTL_PATH_TYPE PathType,
OUT PSIZE_T  LengthNeeded 
)

Definition at line 2197 of file path.c.

2205 {
2206  NTSTATUS Status;
2207  PWCHAR StaticBuffer;
2208  PCWCH ShortName;
2209  ULONG Length;
2210  USHORT StaticLength;
2211  UNICODE_STRING TempDynamicString;
2212 
2213  /* Initialize all our locals */
2214  ShortName = NULL;
2215  StaticBuffer = NULL;
2216  TempDynamicString.Buffer = NULL;
2217 
2218  /* Initialize the input parameters */
2219  if (StringUsed) *StringUsed = NULL;
2220  if (LengthNeeded) *LengthNeeded = 0;
2221  if (FilePartSize) *FilePartSize = 0;
2222 
2223  /* Check for invalid parameters */
2224  if ((DynamicString) && !(StringUsed) && (StaticString))
2225  {
2226  return STATUS_INVALID_PARAMETER;
2227  }
2228 
2229  /* Check if we did not get an input string */
2230  if (!StaticString)
2231  {
2232  /* Allocate one */
2233  StaticLength = MAX_PATH * sizeof(WCHAR);
2234  StaticBuffer = RtlpAllocateStringMemory(MAX_PATH * sizeof(WCHAR), TAG_USTR);
2235  if (!StaticBuffer) return STATUS_NO_MEMORY;
2236  }
2237  else
2238  {
2239  /* Use the one we received */
2240  StaticBuffer = StaticString->Buffer;
2241  StaticLength = StaticString->MaximumLength;
2242  }
2243 
2244  /* Call the lower-level function */
2246  StaticLength,
2247  StaticBuffer,
2248  &ShortName,
2249  NameInvalid,
2250  PathType);
2251  DPRINT("Length: %u StaticBuffer: %S\n", Length, StaticBuffer);
2252  if (!Length)
2253  {
2254  /* Fail if it failed */
2255  DbgPrint("%s(%d) - RtlGetFullPathName_Ustr() returned 0\n",
2256  __FUNCTION__,
2257  __LINE__);
2259  goto Quickie;
2260  }
2261 
2262  /* Check if it fits inside our static string */
2263  if ((StaticString) && (Length < StaticLength))
2264  {
2265  /* Set the final length */
2267 
2268  /* Set the file part size */
2269  if (FilePartSize) *FilePartSize = ShortName ? (ShortName - StaticString->Buffer) : 0;
2270 
2271  /* Return the static string if requested */
2273 
2274  /* We are done with success */
2276  goto Quickie;
2277  }
2278 
2279  /* Did we not have an input dynamic string ?*/
2280  if (!DynamicString)
2281  {
2282  /* Return the length we need */
2284 
2285  /* And fail such that the caller can try again */
2287  goto Quickie;
2288  }
2289 
2290  /* Check if it fits in our static buffer */
2291  if ((StaticBuffer) && (Length < StaticLength))
2292  {
2293  /* NULL-terminate it */
2294  StaticBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
2295 
2296  /* Set the settings for the dynamic string the caller sent */
2297  DynamicString->MaximumLength = StaticLength;
2299  DynamicString->Buffer = StaticBuffer;
2300 
2301  /* Set the part size */
2302  if (FilePartSize) *FilePartSize = ShortName ? (ShortName - StaticBuffer) : 0;
2303 
2304  /* Return the dynamic string if requested */
2306 
2307  /* Do not free the static buffer on exit, and return success */
2308  StaticBuffer = NULL;
2310  goto Quickie;
2311  }
2312 
2313  /* Now try again under the PEB lock */
2316  StaticLength,
2317  StaticBuffer,
2318  &ShortName,
2319  NameInvalid,
2320  PathType);
2321  if (!Length)
2322  {
2323  /* It failed */
2324  DbgPrint("%s line %d: RtlGetFullPathName_Ustr() returned 0\n",
2325  __FUNCTION__, __LINE__);
2327  goto Release;
2328  }
2329 
2330  /* Check if it fits inside our static string now */
2331  if ((StaticString) && (Length < StaticLength))
2332  {
2333  /* Set the final length */
2335 
2336  /* Set the file part size */
2337  if (FilePartSize) *FilePartSize = ShortName ? (ShortName - StaticString->Buffer) : 0;
2338 
2339  /* Return the static string if requested */
2341 
2342  /* We are done with success */
2344  goto Release;
2345  }
2346 
2347  /* Check if the path won't even fit in a real string */
2348  if ((Length + sizeof(WCHAR)) > UNICODE_STRING_MAX_BYTES)
2349  {
2350  /* Name is way too long, fail */
2352  goto Release;
2353  }
2354 
2355  /* Allocate the string to hold the path name now */
2356  TempDynamicString.Buffer = RtlpAllocateStringMemory(Length + sizeof(WCHAR),
2357  TAG_USTR);
2358  if (!TempDynamicString.Buffer)
2359  {
2360  /* Out of memory, fail */
2362  goto Release;
2363  }
2364 
2365  /* Add space for a NULL terminator, and now check the full path */
2366  TempDynamicString.MaximumLength = (USHORT)Length + sizeof(UNICODE_NULL);
2368  Length,
2369  TempDynamicString.Buffer,
2370  &ShortName,
2371  NameInvalid,
2372  PathType);
2373  if (!Length)
2374  {
2375  /* Some path error, so fail out */
2376  DbgPrint("%s line %d: RtlGetFullPathName_Ustr() returned 0\n",
2377  __FUNCTION__, __LINE__);
2379  goto Release;
2380  }
2381 
2382  /* It should fit in the string we just allocated */
2383  ASSERT(Length < (TempDynamicString.MaximumLength - sizeof(WCHAR)));
2384  if (Length > TempDynamicString.MaximumLength)
2385  {
2386  /* This is really weird and would mean some kind of race */
2388  goto Release;
2389  }
2390 
2391  /* Return the file part size */
2392  if (FilePartSize) *FilePartSize = ShortName ? (ShortName - TempDynamicString.Buffer) : 0;
2393 
2394  /* Terminate the whole string now */
2395  TempDynamicString.Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
2396 
2397  /* Finalize the string and return it to the user */
2398  DynamicString->Buffer = TempDynamicString.Buffer;
2400  DynamicString->MaximumLength = TempDynamicString.MaximumLength;
2402 
2403  /* Return success and make sure we don't free the buffer on exit */
2404  TempDynamicString.Buffer = NULL;
2406 
2407 Release:
2408  /* Release the PEB lock */
2410 
2411 Quickie:
2412  /* Free any buffers we should be freeing */
2413  DPRINT("Status: %lx %S %S\n", Status, StaticBuffer, TempDynamicString.Buffer);
2414  if ((StaticString) && (StaticBuffer) && (StaticBuffer != StaticString->Buffer))
2415  {
2416  RtlpFreeMemory(StaticBuffer, TAG_USTR);
2417  }
2418  if (TempDynamicString.Buffer)
2419  {
2420  RtlpFreeMemory(TempDynamicString.Buffer, TAG_USTR);
2421  }
2422 
2423  /* Print out any unusual errors */
2424  if ((NT_ERROR(Status)) &&
2426  {
2427  DbgPrint("RTL: %s - failing on filename %wZ with status %08lx\n",
2429  }
2430 
2431  /* Return, we're all done */
2432  return Status;
2433 }
IN PDCB IN POEM_STRING IN PUNICODE_STRING IN OUT POEM_STRING ShortName
Definition: fatprocs.h:1294
CONST WCHAR * PCWCH
Definition: ntbasedef.h:418
_In_ BOOLEAN Release
Definition: classpnp.h:929
#define DbgPrint
Definition: loader.c:25
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
#define RtlpAllocateStringMemory
Definition: rtlp.h:140
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:615
VOID NTAPI RtlpFreeMemory(_In_ PVOID Mem, _In_ ULONG Tag)
Definition: rtlcompat.c:45
uint16_t * PWCHAR
Definition: typedefs.h:54
#define UNICODE_STRING_MAX_BYTES
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:451
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
#define UNICODE_NULL
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
#define NT_ERROR(Status)
Definition: umtypes.h:106
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define TAG_USTR
Definition: libsupp.c:111
Status
Definition: gdiplustypes.h:24
IN PUNICODE_STRING IN PUNICODE_STRING IN PUNICODE_STRING IN PSIZE_T FilePartSize OUT PBOOLEAN NameInvalid
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define STATUS_NO_SUCH_FILE
Definition: udferr_usr.h:137
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION _In_ ULONG _Out_opt_ PULONG LengthNeeded
Definition: fltkernel.h:1342
IN PUNICODE_STRING IN PUNICODE_STRING IN PUNICODE_STRING * StringUsed
return STATUS_SUCCESS
Definition: btrfs.c:2725
#define __FUNCTION__
Definition: types.h:112
IN PUNICODE_STRING StaticString
IN PUNICODE_STRING IN PUNICODE_STRING DynamicString

Referenced by RtlDosSearchPath_Ustr().

◆ RtlGetLengthWithoutLastFullDosOrNtPathElement()

NTSTATUS NTAPI RtlGetLengthWithoutLastFullDosOrNtPathElement ( IN ULONG  Flags,
IN PWCHAR  Path,
OUT PULONG  LengthOut 
)

Definition at line 457 of file path.c.

460 {
462  return STATUS_NOT_IMPLEMENTED;
463 }
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlGetLengthWithoutTrailingPathSeparators()

NTSTATUS NTAPI RtlGetLengthWithoutTrailingPathSeparators ( IN ULONG  Flags,
IN PCUNICODE_STRING  PathString,
OUT PULONG  Length 
)

Definition at line 1454 of file path.c.

1457 {
1458  ULONG NumChars;
1459 
1460  /* Parameters validation */
1461  if (Length == NULL) return STATUS_INVALID_PARAMETER;
1462 
1463  *Length = 0;
1464 
1465  if (PathString == NULL) return STATUS_INVALID_PARAMETER;
1466 
1467  /* No flags are supported yet */
1468  if (Flags != 0) return STATUS_INVALID_PARAMETER;
1469 
1470  NumChars = PathString->Length / sizeof(WCHAR);
1471 
1472  /*
1473  * Notice that we skip the last character, therefore:
1474  * - if we have: "some/path/f" we test for: "some/path/"
1475  * - if we have: "some/path/" we test for: "some/path"
1476  * - if we have: "s" we test for: ""
1477  * - if we have: "" then NumChars was already zero and we aren't there
1478  */
1479 
1480  while (NumChars > 0 && IS_PATH_SEPARATOR(PathString->Buffer[NumChars - 1]))
1481  {
1482  --NumChars;
1483  }
1484 
1485  *Length = NumChars;
1486  return STATUS_SUCCESS;
1487 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
smooth NULL
Definition: ftsmooth.c:416
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
unsigned int ULONG
Definition: retypes.h:1
return STATUS_SUCCESS
Definition: btrfs.c:2725

◆ RtlGetLongestNtPathLength()

ULONG NTAPI RtlGetLongestNtPathLength ( VOID  )

Definition at line 1436 of file path.c.

1437 {
1438  /*
1439  * The longest NT path is a DOS path that actually sits on a UNC path (ie:
1440  * a mapped network drive), which is accessed through the DOS Global?? path.
1441  * This is, and has always been equal to, 269 characters, except in Wine
1442  * which claims this is 277. Go figure.
1443  */
1444  return MAX_PATH + RtlpDosDevicesUncPrefix.Length / sizeof(WCHAR) + sizeof(ANSI_NULL);
1445 }
#define ANSI_NULL
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
const UNICODE_STRING RtlpDosDevicesUncPrefix
Definition: path.c:36

Referenced by START_TEST().

◆ RtlIsDosDeviceName_U()

ULONG NTAPI RtlIsDosDeviceName_U ( IN PCWSTR  Path)

Definition at line 1520 of file path.c.

1521 {
1522  UNICODE_STRING PathString;
1523  NTSTATUS Status;
1524 
1525  /* Build the string */
1526  Status = RtlInitUnicodeStringEx(&PathString, Path);
1527  if (!NT_SUCCESS(Status)) return 0;
1528 
1529  /*
1530  * Returns 0 if name is not valid DOS device name, or DWORD with
1531  * offset in bytes to DOS device name from beginning of buffer in high word
1532  * and size in bytes of DOS device name in low word
1533  */
1534  return RtlIsDosDeviceName_Ustr(&PathString);
1535 }
ULONG NTAPI RtlIsDosDeviceName_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:94
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
PRTL_UNICODE_STRING_BUFFER Path
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)

◆ RtlIsDosDeviceName_Ustr()

ULONG NTAPI RtlIsDosDeviceName_Ustr ( IN PCUNICODE_STRING  PathString)

Definition at line 94 of file path.c.

95 {
96  UNICODE_STRING PathCopy;
97  PWCHAR Start, End;
98  USHORT PathChars, ColonCount = 0;
99  USHORT ReturnOffset = 0, ReturnLength, OriginalLength;
100  WCHAR c;
101 
102  /* Validate the input */
103  if (!PathString) return 0;
104 
105  /* Check what type of path this is */
106  switch (RtlDetermineDosPathNameType_Ustr(PathString))
107  {
108  /* Fail for UNC or unknown paths */
109  case RtlPathTypeUnknown:
111  return 0;
112 
113  /* Make special check for the CON device */
116  {
117  /* This should return 0x80006 */
119  }
120  return 0;
121 
122  default:
123  break;
124  }
125 
126  /* Make a copy of the string */
127  PathCopy = *PathString;
128  OriginalLength = PathString->Length;
129 
130  /* Return if there's no characters */
131  PathChars = PathCopy.Length / sizeof(WCHAR);
132  if (!PathChars) return 0;
133 
134  /* Check for drive path and truncate */
135  if (PathCopy.Buffer[PathChars - 1] == L':')
136  {
137  /* Fixup the lengths */
138  PathCopy.Length -= sizeof(WCHAR);
139  if (!--PathChars) return 0;
140 
141  /* Remember this for later */
142  ColonCount = 1;
143  }
144 
145  /* Check for extension or space, and truncate */
146  do
147  {
148  /* Stop if we hit something else than a space or period */
149  c = PathCopy.Buffer[PathChars - 1];
150  if ((c != L'.') && (c != L' ')) break;
151 
152  /* Fixup the lengths */
153  PathCopy.Length -= sizeof(WCHAR);
154 
155  /* Remember this for later */
156  ColonCount++;
157  } while (--PathChars);
158 
159  /* Anything still left? */
160  if (PathChars)
161  {
162  /* Loop from the end */
163  for (End = &PathCopy.Buffer[PathChars - 1];
164  End >= PathCopy.Buffer;
165  --End)
166  {
167  /* Check if the character is a path or drive separator */
168  c = *End;
169  if (IS_PATH_SEPARATOR(c) || ((c == L':') && (End == PathCopy.Buffer + 1)))
170  {
171  /* Get the next lower case character */
172  End++;
173  c = RtlpDowncaseUnicodeChar(*End);
174 
175  /* Check if it's a DOS device (LPT, COM, PRN, AUX, or NUL) */
176  if ((End < &PathCopy.Buffer[OriginalLength / sizeof(WCHAR)]) &&
177  ((c == L'l') || (c == L'c') || (c == L'p') || (c == L'a') || (c == L'n')))
178  {
179  /* Calculate the offset */
180  ReturnOffset = (USHORT)((PCHAR)End - (PCHAR)PathCopy.Buffer);
181 
182  /* Build the final string */
183  PathCopy.Length = OriginalLength - ReturnOffset - (ColonCount * sizeof(WCHAR));
184  PathCopy.Buffer = End;
185 
186  /* Save new amount of chars in the path */
187  PathChars = PathCopy.Length / sizeof(WCHAR);
188 
189  break;
190  }
191  else
192  {
193  return 0;
194  }
195  }
196  }
197 
198  /* Get the next lower case character and check if it's a DOS device */
199  c = RtlpDowncaseUnicodeChar(*PathCopy.Buffer);
200  if ((c != L'l') && (c != L'c') && (c != L'p') && (c != L'a') && (c != L'n'))
201  {
202  /* Not LPT, COM, PRN, AUX, or NUL */
203  return 0;
204  }
205  }
206 
207  /* Now skip past any extra extension or drive letter characters */
208  Start = PathCopy.Buffer;
209  End = &Start[PathChars];
210  while (Start < End)
211  {
212  c = *Start;
213  if ((c == L'.') || (c == L':')) break;
214  Start++;
215  }
216 
217  /* And then go backwards to get rid of spaces */
218  while ((Start > PathCopy.Buffer) && (Start[-1] == L' ')) --Start;
219 
220  /* Finally see how many characters are left, and that's our size */
221  PathChars = (USHORT)(Start - PathCopy.Buffer);
222  PathCopy.Length = PathChars * sizeof(WCHAR);
223 
224  /* Check if this is a COM or LPT port, which has a digit after it */
225  if ((PathChars == 4) &&
226  (iswdigit(PathCopy.Buffer[3]) && (PathCopy.Buffer[3] != L'0')))
227  {
228  /* Don't compare the number part, just check for LPT or COM */
229  PathCopy.Length -= sizeof(WCHAR);
230  if ((RtlEqualUnicodeString(&PathCopy, &RtlpDosLPTDevice, TRUE)) ||
232  {
233  /* Found it */
234  ReturnLength = sizeof(L"COM1") - sizeof(WCHAR);
235  return MAKELONG(ReturnLength, ReturnOffset);
236  }
237  }
238  else if ((PathChars == 3) &&
239  ((RtlEqualUnicodeString(&PathCopy, &RtlpDosPRNDevice, TRUE)) ||
240  (RtlEqualUnicodeString(&PathCopy, &RtlpDosAUXDevice, TRUE)) ||
241  (RtlEqualUnicodeString(&PathCopy, &RtlpDosNULDevice, TRUE)) ||
243  {
244  /* Otherwise this was something like AUX, NUL, PRN, or CON */
245  ReturnLength = sizeof(L"AUX") - sizeof(WCHAR);
246  return MAKELONG(ReturnLength, ReturnOffset);
247  }
248 
249  /* Otherwise, this is not a valid DOS device */
250  return 0;
251 }
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:61
signed char * PCHAR
Definition: retypes.h:7
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
#define TRUE
Definition: types.h:120
const UNICODE_STRING RtlpDosCONDevice
Definition: path.c:45
const UNICODE_STRING RtlpDosAUXDevice
Definition: path.c:44
#define iswdigit(_c)
Definition: ctype.h:667
const UNICODE_STRING RtlpDosSlashCONDevice
Definition: path.c:38
uint16_t * PWCHAR
Definition: typedefs.h:54
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
const UNICODE_STRING RtlpDosNULDevice
Definition: path.c:46
const UNICODE_STRING RtlpDosCOMDevice
Definition: path.c:42
const UNICODE_STRING RtlpDosLPTDevice
Definition: path.c:41
#define MAKELONG(a, b)
Definition: typedefs.h:248
#define PCHAR
Definition: match.c:90
__wchar_t WCHAR
Definition: xmlstorage.h:180
const GLubyte * c
Definition: glext.h:8905
Definition: partlist.h:33
static const WCHAR L[]
Definition: oid.c:1250
unsigned short USHORT
Definition: pedump.c:61
const UNICODE_STRING RtlpDosPRNDevice
Definition: path.c:43
#define c
Definition: ke_i.h:80
WCHAR NTAPI RtlpDowncaseUnicodeChar(IN WCHAR Source)
Definition: nls.c:89
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
const UNICODE_STRING DeviceRootString
Definition: path.c:34

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

◆ RtlNtPathNameToDosPathName()

NTSTATUS NTAPI RtlNtPathNameToDosPathName ( IN ULONG  Flags,
IN OUT PRTL_UNICODE_STRING_BUFFER  Path,
OUT PULONG  PathType,
PULONG  Unknown 
)

Definition at line 1961 of file path.c.

1965 {
1966  PCUNICODE_STRING UsePrefix = NULL, AlternatePrefix = NULL;
1967 
1968  if (PathType)
1969  *PathType = 0;
1970 
1971  if (!Path || Flags)
1972  return STATUS_INVALID_PARAMETER;
1973 
1974  /* The initial check is done on Path->String */
1976  {
1977  UsePrefix = &RtlpDosDevicesUncPrefix;
1978  AlternatePrefix = &RtlpDoubleSlashPrefix;
1979  if (PathType)
1981  }
1983  {
1984  UsePrefix = &RtlpDosDevicesPrefix;
1985  if (PathType)
1987  }
1988 
1989  if (UsePrefix)
1990  {
1991  NTSTATUS Status;
1992 
1993  USHORT Len = Path->String.Length - UsePrefix->Length;
1994  if (AlternatePrefix)
1995  Len += AlternatePrefix->Length;
1996 
1997  Status = RtlEnsureBufferSize(0, &Path->ByteBuffer, Len);
1998  if (!NT_SUCCESS(Status))
1999  return Status;
2000 
2001  if (Len + sizeof(UNICODE_NULL) <= Path->ByteBuffer.Size)
2002  {
2003  /* Then, the contents of Path->ByteBuffer are always used... */
2004  if (AlternatePrefix)
2005  {
2006  memcpy(Path->ByteBuffer.Buffer, AlternatePrefix->Buffer, AlternatePrefix->Length);
2007  memmove(Path->ByteBuffer.Buffer + AlternatePrefix->Length, Path->ByteBuffer.Buffer + UsePrefix->Length,
2008  Len - AlternatePrefix->Length);
2009  }
2010  else
2011  {
2013  }
2015  Path->String.Length = Len;
2017  Path->String.Buffer[Len / sizeof(WCHAR)] = UNICODE_NULL;
2018  }
2019  return STATUS_SUCCESS;
2020  }
2021 
2022  if (PathType)
2023  {
2025  {
2031  break;
2032  case RtlPathTypeUnknown:
2034  case RtlPathTypeRooted:
2035  case RtlPathTypeRelative:
2037  break;
2038  }
2039  }
2040 
2041  return STATUS_SUCCESS;
2042 }
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:61
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define TRUE
Definition: types.h:120
SIZE_T Size
Definition: rtltypes.h:1809
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:54
#define RTL_UNCHANGED_DOS_PATH
Definition: rtlfuncs.h:2846
LONG NTSTATUS
Definition: precomp.h:26
#define RTL_CONVERTED_UNC_PATH
Definition: rtlfuncs.h:2844
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define UNICODE_NULL
smooth NULL
Definition: ftsmooth.c:416
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define Len
Definition: deflate.h:82
#define RTL_CONVERTED_NT_PATH
Definition: rtlfuncs.h:2845
UNICODE_STRING String
Definition: rtltypes.h:1817
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
const UNICODE_STRING RtlpDosDevicesPrefix
Definition: path.c:39
Status
Definition: gdiplustypes.h:24
PRTL_UNICODE_STRING_BUFFER Path
unsigned short USHORT
Definition: pedump.c:61
#define RTL_UNCHANGED_UNK_PATH
Definition: rtlfuncs.h:2843
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
PUCHAR Buffer
Definition: rtltypes.h:1807
const UNICODE_STRING RtlpDosDevicesUncPrefix
Definition: path.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2725
const UNICODE_STRING RtlpDoubleSlashPrefix
Definition: path.c:48

◆ RtlpApplyLengthFunction()

NTSTATUS NTAPI RtlpApplyLengthFunction ( IN ULONG  Flags,
IN ULONG  Type,
IN PVOID  UnicodeStringOrUnicodeStringBuffer,
IN PVOID  LengthFunction 
)

Definition at line 446 of file path.c.

450 {
452  return STATUS_NOT_IMPLEMENTED;
453 }
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define UNIMPLEMENTED
Definition: debug.h:114

◆ RtlpCheckDeviceName()

NTSTATUS NTAPI RtlpCheckDeviceName ( IN PUNICODE_STRING  FileName,
IN ULONG  Length,
OUT PBOOLEAN  NameInvalid 
)

Definition at line 255 of file path.c.

258 {
259  PWCHAR Buffer;
261 
262  /* Allocate a large enough buffer */
263  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FileName->Length);
264  if (Buffer)
265  {
266  /* Assume failure */
267  *NameInvalid = TRUE;
268 
269  /* Copy the filename */
270  RtlCopyMemory(Buffer, FileName->Buffer, FileName->Length);
271 
272  /* And add a dot at the end */
273  Buffer[Length / sizeof(WCHAR)] = L'.';
274  Buffer[(Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
275 
276  /* Check if the file exists or not */
278 
279  /* Get rid of the buffer now */
280  Status = RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
281  }
282  else
283  {
284  /* Assume the name is ok, but fail the call */
285  *NameInvalid = FALSE;
287  }
288 
289  /* Return the status */
290  return Status;
291 }
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
uint16_t * PWCHAR
Definition: typedefs.h:54
#define UNICODE_NULL
Definition: bufpool.h:45
BOOLEAN NTAPI RtlDoesFileExists_U(IN PCWSTR FileName)
Definition: path.c:2910
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const WCHAR L[]
Definition: oid.c:1250
Status
Definition: gdiplustypes.h:24
IN PUNICODE_STRING IN PUNICODE_STRING IN PUNICODE_STRING IN PSIZE_T FilePartSize OUT PBOOLEAN NameInvalid
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34

Referenced by RtlGetFullPathName_Ustr().

◆ RtlpCollapsePath()

static ULONG RtlpCollapsePath ( PWSTR  Path,
ULONG  mark,
BOOLEAN  SkipTrailingPathSeparators 
)
static

Definition at line 306 of file path.c.

307 {
308  PWSTR p, next;
309 
310  // FIXME: Do not suppose NULL-terminated strings!!
311 
313  PWSTR EndBuffer = Path + PathLength; // Path + PathBufferSize / sizeof(WCHAR);
314  PWSTR EndPath;
315 
316  /* Convert slashes into backslashes */
317  for (p = Path; *p; p++)
318  {
319  if (*p == L'/') *p = L'\\';
320  }
321 
322  /* Collapse duplicate backslashes */
323  next = Path + max( 1, mark );
324  for (p = next; *p; p++)
325  {
326  if (*p != L'\\' || next[-1] != L'\\') *next++ = *p;
327  }
328  *next = UNICODE_NULL;
329  EndPath = next;
330 
331  p = Path + mark;
332  while (*p)
333  {
334  if (*p == L'.')
335  {
336  switch (p[1])
337  {
338  case UNICODE_NULL: /* final . */
339  if (p > Path + mark) p--;
340  *p = UNICODE_NULL;
341  EndPath = p;
342  continue;
343 
344  case L'\\': /* .\ component */
345  next = p + 2;
346  // ASSERT(EndPath - next == wcslen(next));
347  RtlMoveMemory(p, next, (EndPath - next + 1) * sizeof(WCHAR));
348  EndPath -= (next - p);
349  continue;
350 
351  case L'.':
352  if (p[2] == L'\\') /* ..\ component */
353  {
354  next = p + 3;
355  if (p > Path + mark)
356  {
357  p--;
358  while (p > Path + mark && p[-1] != L'\\') p--;
359  }
360  // ASSERT(EndPath - next == wcslen(next));
361  RtlMoveMemory(p, next, (EndPath - next + 1) * sizeof(WCHAR));
362  EndPath -= (next - p);
363  continue;
364  }
365  else if (p[2] == UNICODE_NULL) /* final .. */
366  {
367  if (p > Path + mark)
368  {
369  p--;
370  while (p > Path + mark && p[-1] != L'\\') p--;
371  if (p > Path + mark) p--;
372  }
373  *p = UNICODE_NULL;
374  EndPath = p;
375  continue;
376  }
377  break;
378  }
379  }
380 
381  /* Skip to the next component */
382  while (*p && *p != L'\\') p++;
383  if (*p == L'\\')
384  {
385  /* Remove last dot in previous dir name */
386  if (p > Path + mark && p[-1] == L'.')
387  {
388  // ASSERT(EndPath - p == wcslen(p));
389  RtlMoveMemory(p - 1, p, (EndPath - p + 1) * sizeof(WCHAR));
390  EndPath--;
391  }
392  else
393  {
394  p++;
395  }
396  }
397  }
398 
399  /* Remove trailing backslashes if needed (after the UNC part if it exists) */
400  if (SkipTrailingPathSeparators)
401  {
402  while (p > Path + mark && IS_PATH_SEPARATOR(p[-1])) p--;
403  }
404 
405  /* Remove trailing spaces and dots (for all the path) */
406  while (p > Path && (p[-1] == L' ' || p[-1] == L'.')) p--;
407 
408  /*
409  * Zero-out the discarded buffer zone, starting just after
410  * the path string and going up to the end of the buffer.
411  * It also NULL-terminate the path string.
412  */
413  ASSERT(EndBuffer >= p);
414  RtlZeroMemory(p, (EndBuffer - p + 1) * sizeof(WCHAR));
415 
416  /* Return the real path length */
417  PathLength = (p - Path);
418  // ASSERT(PathLength == wcslen(Path));
419  return (PathLength * sizeof(WCHAR));
420 }
#define max(a, b)
Definition: svc.c:63
uint16_t * PWSTR
Definition: typedefs.h:54
static USHORT PathLength
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define UNICODE_NULL
__wchar_t WCHAR
Definition: xmlstorage.h:180
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
BOOL WINAPI EndPath(HDC hdc)
Definition: path.c:56
PRTL_UNICODE_STRING_BUFFER Path
static unsigned __int64 next
Definition: rand_nt.c:6
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
GLfloat GLfloat p
Definition: glext.h:8902
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)

Referenced by RtlGetFullPathName_Ustr().

◆ RtlpDosPathNameToRelativeNtPathName_U()

NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_U ( IN BOOLEAN  HaveRelative,
IN PCWSTR  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1268 of file path.c.

1273 {
1274  NTSTATUS Status;
1275  UNICODE_STRING NameString;
1276 
1277  /* Create the unicode name */
1278  Status = RtlInitUnicodeStringEx(&NameString, DosName);
1279  if (NT_SUCCESS(Status))
1280  {
1281  /* Call the unicode function */
1283  &NameString,
1284  NtName,
1285  PartName,
1286  RelativeName);
1287  }
1288 
1289  /* Return status */
1290  return Status;
1291 }
NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative, IN PCUNICODE_STRING DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1036
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)

Referenced by RtlDosPathNameToNtPathName_U(), RtlDosPathNameToNtPathName_U_WithStatus(), RtlDosPathNameToRelativeNtPathName_U(), and RtlDosPathNameToRelativeNtPathName_U_WithStatus().

◆ RtlpDosPathNameToRelativeNtPathName_Ustr()

NTSTATUS NTAPI RtlpDosPathNameToRelativeNtPathName_Ustr ( IN BOOLEAN  HaveRelative,
IN PCUNICODE_STRING  DosName,
OUT PUNICODE_STRING  NtName,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 1036 of file path.c.

1041 {
1042  WCHAR BigBuffer[MAX_PATH + 1];
1043  PWCHAR PrefixBuffer, NewBuffer, Buffer;
1044  ULONG MaxLength, PathLength, PrefixLength, PrefixCut, LengthChars, Length;
1045  UNICODE_STRING CapturedDosName, PartNameString, FullPath;
1046  BOOLEAN QuickPath;
1047  RTL_PATH_TYPE InputPathType, BufferPathType;
1048  NTSTATUS Status;
1051 
1052  /* Assume MAX_PATH for now */
1053  DPRINT("Relative: %lx DosName: %wZ NtName: %p, PartName: %p, RelativeName: %p\n",
1054  HaveRelative, DosName, NtName, PartName, RelativeName);
1055  MaxLength = sizeof(BigBuffer);
1056 
1057  /* Validate the input */
1058  if (!DosName) return STATUS_OBJECT_NAME_INVALID;
1059 
1060  /* Capture input string */
1061  CapturedDosName = *DosName;
1062 
1063  /* Check for the presence or absence of the NT prefix "\\?\" form */
1064  // if (!RtlPrefixUnicodeString(&RtlpWin32NtRootSlash, &CapturedDosName, FALSE))
1065  if ((CapturedDosName.Length <= RtlpWin32NtRootSlash.Length) ||
1066  (CapturedDosName.Buffer[0] != RtlpWin32NtRootSlash.Buffer[0]) ||
1067  (CapturedDosName.Buffer[1] != RtlpWin32NtRootSlash.Buffer[1]) ||
1068  (CapturedDosName.Buffer[2] != RtlpWin32NtRootSlash.Buffer[2]) ||
1069  (CapturedDosName.Buffer[3] != RtlpWin32NtRootSlash.Buffer[3]))
1070  {
1071  /* NT prefix not present */
1072 
1073  /* Quick path won't be used */
1074  QuickPath = FALSE;
1075 
1076  /* Use the static buffer */
1077  Buffer = BigBuffer;
1078  MaxLength += RtlpDosDevicesUncPrefix.Length;
1079 
1080  /* Allocate a buffer to hold the path */
1081  NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MaxLength);
1082  DPRINT("MaxLength: %lx\n", MaxLength);
1083  if (!NewBuffer) return STATUS_NO_MEMORY;
1084  }
1085  else
1086  {
1087  /* NT prefix present */
1088 
1089  /* Use the optimized path after acquiring the lock */
1090  QuickPath = TRUE;
1091  NewBuffer = NULL;
1092  }
1093 
1094  /* Lock the PEB and check if the quick path can be used */
1096  if (QuickPath)
1097  {
1098  /* Some simple fixups will get us the correct path */
1099  DPRINT("Quick path\n");
1100  Status = RtlpWin32NTNameToNtPathName_U(&CapturedDosName,
1101  NtName,
1102  PartName,
1103  RelativeName);
1104 
1105  /* Release the lock, we're done here */
1107  return Status;
1108  }
1109 
1110  /* Call the main function to get the full path name and length */
1111  PathLength = RtlGetFullPathName_Ustr(&CapturedDosName,
1112  MAX_PATH * sizeof(WCHAR),
1113  Buffer,
1114  PartName,
1115  &NameInvalid,
1116  &InputPathType);
1117  if ((NameInvalid) || !(PathLength) || (PathLength > (MAX_PATH * sizeof(WCHAR))))
1118  {
1119  /* Invalid name, fail */
1120  DPRINT("Invalid name: %lx Path Length: %lx\n", NameInvalid, PathLength);
1121  RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
1124  }
1125 
1126  /* Start by assuming the path starts with \??\ (DOS Devices Path) */
1127  PrefixLength = RtlpDosDevicesPrefix.Length;
1128  PrefixBuffer = RtlpDosDevicesPrefix.Buffer;
1129  PrefixCut = 0;
1130 
1131  /* Check where it really is */
1132  BufferPathType = RtlDetermineDosPathNameType_U(Buffer);
1133  DPRINT("Buffer: %S Type: %lx\n", Buffer, BufferPathType);
1134  switch (BufferPathType)
1135  {
1136  /* It's actually a UNC path in \??\UNC\ */
1138  PrefixLength = RtlpDosDevicesUncPrefix.Length;
1139  PrefixBuffer = RtlpDosDevicesUncPrefix.Buffer;
1140  PrefixCut = 2;
1141  break;
1142 
1144  /* We made a good guess, go with it but skip the \??\ */
1145  PrefixCut = 4;
1146  break;
1147 
1150  case RtlPathTypeRooted:
1151  case RtlPathTypeRelative:
1152  /* Our guess was good, roll with it */
1153  break;
1154 
1155  /* Nothing else is expected */
1156  default:
1157  ASSERT(FALSE);
1158  }
1159 
1160  /* Now copy the prefix and the buffer */
1161  RtlCopyMemory(NewBuffer, PrefixBuffer, PrefixLength);
1162  RtlCopyMemory((PCHAR)NewBuffer + PrefixLength,
1163  Buffer + PrefixCut,
1164  PathLength - (PrefixCut * sizeof(WCHAR)));
1165 
1166  /* Compute the length */
1167  Length = PathLength + PrefixLength - PrefixCut * sizeof(WCHAR);
1168  LengthChars = Length / sizeof(WCHAR);
1169 
1170  /* Setup the actual NT path string and terminate it */
1171  NtName->Buffer = NewBuffer;
1172  NtName->Length = (USHORT)Length;
1173  NtName->MaximumLength = (USHORT)MaxLength;
1174  NewBuffer[LengthChars] = UNICODE_NULL;
1175  DPRINT("New buffer: %S\n", NewBuffer);
1176  DPRINT("NT Name: %wZ\n", NtName);
1177 
1178  /* Check if a partial name was requested */
1179  if ((PartName) && (*PartName))
1180  {
1181  /* Convert to Unicode */
1182  Status = RtlInitUnicodeStringEx(&PartNameString, *PartName);
1183  if (NT_SUCCESS(Status))
1184  {
1185  /* Set the partial name */
1186  *PartName = &NewBuffer[LengthChars - (PartNameString.Length / sizeof(WCHAR))];
1187  }
1188  else
1189  {
1190  /* Fail */
1191  RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
1193  return Status;
1194  }
1195  }
1196 
1197  /* Check if a relative name was asked for */
1198  if (RelativeName)
1199  {
1200  /* Setup the structure */
1201  RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0);
1202  RelativeName->ContainingDirectory = NULL;
1203  RelativeName->CurDirRef = NULL;
1204 
1205  /* Check if the input path itself was relative */
1206  if (InputPathType == RtlPathTypeRelative)
1207  {
1208  /* Get current directory */
1209  CurrentDirectory = &(NtCurrentPeb()->ProcessParameters->CurrentDirectory);
1210  if (CurrentDirectory->Handle)
1211  {
1212  Status = RtlInitUnicodeStringEx(&FullPath, Buffer);
1213  if (!NT_SUCCESS(Status))
1214  {
1215  RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
1217  return Status;
1218  }
1219 
1220  /* If current directory is bigger than full path, there's no way */
1221  if (CurrentDirectory->DosPath.Length > FullPath.Length)
1222  {
1224  return Status;
1225  }
1226 
1227  /* File is in current directory */
1228  if (RtlEqualUnicodeString(&FullPath, &CurrentDirectory->DosPath, TRUE))
1229  {
1230  /* Make relative name string */
1231  RelativeName->RelativeName.Buffer = (PWSTR)((ULONG_PTR)NewBuffer + PrefixLength + FullPath.Length - PrefixCut * sizeof(WCHAR));
1232  RelativeName->RelativeName.Length = (USHORT)(PathLength - FullPath.Length);
1233  /* If relative name starts with \, skip it */
1234  if (RelativeName->RelativeName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
1235  {
1236  RelativeName->RelativeName.Buffer++;
1237  RelativeName->RelativeName.Length -= sizeof(WCHAR);
1238  }
1239  RelativeName->RelativeName.MaximumLength = RelativeName->RelativeName.Length;
1240  DPRINT("RelativeName: %wZ\n", &(RelativeName->RelativeName));
1241 
1242  if (!HaveRelative)
1243  {
1244  RelativeName->ContainingDirectory = CurrentDirectory->Handle;
1245  return Status;
1246  }
1247 
1248  /* Give back current directory data & reference counter */
1249  RelativeName->CurDirRef = RtlpCurDirRef;
1250  if (RelativeName->CurDirRef)
1251  {
1253  }
1254 
1255  RelativeName->ContainingDirectory = CurrentDirectory->Handle;
1256  }
1257  }
1258  }
1259  }
1260 
1261  /* Done */
1263  return STATUS_SUCCESS;
1264 }
signed char * PCHAR
Definition: retypes.h:7
enum _RTL_PATH_TYPE RTL_PATH_TYPE
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
WCHAR CurrentDirectory[1024]
Definition: chkdsk.c:74
uint16_t * PWSTR
Definition: typedefs.h:54
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:615
uint16_t * PWCHAR
Definition: typedefs.h:54
static USHORT PathLength
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MAX_PATH
Definition: compat.h:26
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
const UNICODE_STRING RtlpDosDevicesPrefix
Definition: path.c:39
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(IN PCWSTR Path)
Definition: path.c:1494
Status
Definition: gdiplustypes.h:24
IN PUNICODE_STRING IN PUNICODE_STRING IN PUNICODE_STRING IN PSIZE_T FilePartSize OUT PBOOLEAN NameInvalid
#define InterlockedIncrement
Definition: armddk.h:53
#define NtCurrentPeb()
Definition: FLS.c:19
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
_Out_ PUNICODE_STRING DosName
Definition: rtlfuncs.h:1270
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING, PCWSTR)
const UNICODE_STRING RtlpWin32NtRootSlash
Definition: path.c:37
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
NTSTATUS NTAPI RtlpWin32NTNameToNtPathName_U(IN PUNICODE_STRING DosPath, OUT PUNICODE_STRING NtPath, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:962
unsigned int ULONG
Definition: retypes.h:1
PRTLP_CURDIR_REF RtlpCurDirRef
Definition: path.c:55
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
const UNICODE_STRING RtlpDosDevicesUncPrefix
Definition: path.c:36
return STATUS_SUCCESS
Definition: btrfs.c:2725
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)

Referenced by RtlDosPathNameToRelativeNtPathName_Ustr(), and RtlpDosPathNameToRelativeNtPathName_U().

◆ RtlpSkipUNCPrefix()

static SIZE_T RtlpSkipUNCPrefix ( PCWSTR  FileNameBuffer)
static

Definition at line 431 of file path.c.

432 {
433  PCWSTR UncPath = FileNameBuffer + 2;
434  DPRINT("RtlpSkipUNCPrefix(%S)\n", FileNameBuffer);
435 
436  while (*UncPath && !IS_PATH_SEPARATOR(*UncPath)) UncPath++; /* share name */
437  while (IS_PATH_SEPARATOR(*UncPath)) UncPath++;
438  while (*UncPath && !IS_PATH_SEPARATOR(*UncPath)) UncPath++; /* dir name */
439  /* while (IS_PATH_SEPARATOR(*UncPath)) UncPath++; */
440 
441  return (UncPath - FileNameBuffer);
442 }
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IS_PATH_SEPARATOR(x)
Definition: path.c:24
void DPRINT(...)
Definition: polytest.cpp:61
WCHAR FileNameBuffer[_MAX_PATH]
Definition: framewnd.c:239

Referenced by RtlGetFullPathName_Ustr().

◆ RtlpWin32NTNameToNtPathName_U()

NTSTATUS NTAPI RtlpWin32NTNameToNtPathName_U ( IN PUNICODE_STRING  DosPath,
OUT PUNICODE_STRING  NtPath,
OUT PCWSTR PartName,
OUT PRTL_RELATIVE_NAME_U  RelativeName 
)

Definition at line 962 of file path.c.

966 {
967  ULONG DosLength;
968  PWSTR NewBuffer, p;
969 
970  /* Validate the input */
971  if (!DosPath) return STATUS_OBJECT_NAME_INVALID;
972 
973  /* Validate the DOS length */
974  DosLength = DosPath->Length;
975  if (DosLength >= UNICODE_STRING_MAX_BYTES) return STATUS_NAME_TOO_LONG;
976 
977  /* Make space for the new path */
978  NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
979  0,
980  DosLength + sizeof(UNICODE_NULL));
981  if (!NewBuffer) return STATUS_NO_MEMORY;
982 
983  /* Copy the prefix, and then the rest of the DOS path, and NULL-terminate */
986  DosPath->Buffer + RtlpDosDevicesPrefix.Length / sizeof(WCHAR),
987  DosPath->Length - RtlpDosDevicesPrefix.Length);
988  NewBuffer[DosLength / sizeof(WCHAR)] = UNICODE_NULL;
989 
990  /* Did the caller send a relative name? */
991  if (RelativeName)
992  {
993  /* Zero initialize it */
994  RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0);
995  RelativeName->ContainingDirectory = NULL;
996  RelativeName->CurDirRef = 0;
997  }
998 
999  /* Did the caller request a partial name? */
1000  if (PartName)
1001  {
1002  /* Loop from the back until we find a path separator */
1003  p = &NewBuffer[DosLength / sizeof(WCHAR)];
1004  while (--p > NewBuffer)
1005  {
1006  /* We found a path separator, move past it */
1007  if (*p == OBJ_NAME_PATH_SEPARATOR)
1008  {
1009  ++p;
1010  break;
1011  }
1012  }
1013 
1014  /* Check whether a separator was found and if something remains */
1015  if ((p > NewBuffer) && *p)
1016  {
1017  /* What follows the path separator is the partial name */
1018  *PartName = p;
1019  }
1020  else
1021  {
1022  /* The path ends with a path separator, no partial name */
1023  *PartName = NULL;
1024  }
1025  }
1026 
1027  /* Build the final NT path string */
1028  NtPath->Buffer = NewBuffer;
1029  NtPath->Length = (USHORT)DosLength;
1030  NtPath->MaximumLength = (USHORT)DosLength + sizeof(UNICODE_NULL);
1031  return STATUS_SUCCESS;
1032 }
signed char * PCHAR
Definition: retypes.h:7
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
uint16_t * PWSTR
Definition: typedefs.h:54
#define UNICODE_STRING_MAX_BYTES
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
smooth NULL
Definition: ftsmooth.c:416
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
__wchar_t WCHAR
Definition: xmlstorage.h:180
const UNICODE_STRING RtlpDosDevicesPrefix
Definition: path.c:39
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
unsigned int ULONG
Definition: retypes.h:1
GLfloat GLfloat p
Definition: glext.h:8902
return STATUS_SUCCESS
Definition: btrfs.c:2725

Referenced by RtlpDosPathNameToRelativeNtPathName_Ustr().

◆ RtlReleaseRelativeName()

VOID NTAPI RtlReleaseRelativeName ( IN PRTL_RELATIVE_NAME_U  RelativeName)

Definition at line 1415 of file path.c.

1416 {
1417  /* Check if a directory reference was grabbed */
1418  if (RelativeName->CurDirRef)
1419  {
1420  /* Decrease reference count */
1421  if (!InterlockedDecrement(&RelativeName->CurDirRef->RefCount))
1422  {
1423  /* If no one uses it any longer, close handle & free */
1424  NtClose(RelativeName->CurDirRef->Handle);
1425  RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeName->CurDirRef);
1426  }
1427  RelativeName->CurDirRef = NULL;
1428  }
1429 }
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define InterlockedDecrement
Definition: armddk.h:52

Referenced by RtlDoesFileExists_UstrEx().

◆ RtlSetCurrentDirectory_U()

NTSTATUS NTAPI RtlSetCurrentDirectory_U ( IN PUNICODE_STRING  Path)

Definition at line 1620 of file path.c.

1621 {
1622  PCURDIR CurDir;
1623  NTSTATUS Status;
1626  UNICODE_STRING FullPath, NtName;
1627  PRTLP_CURDIR_REF OldCurDir = NULL;
1629  FILE_FS_DEVICE_INFORMATION FileFsDeviceInfo;
1630  ULONG SavedLength, CharLength, FullPathLength;
1631  HANDLE OldHandle = NULL, CurDirHandle = NULL, OldCurDirHandle = NULL;
1632 
1633  DPRINT("RtlSetCurrentDirectory_U %wZ\n", Path);
1634 
1635  /* Initialize for failure case */
1636  RtlInitEmptyUnicodeString(&NtName, NULL, 0);
1637 
1638  /* Can't set current directory on DOS device */
1640  {
1641  return STATUS_NOT_A_DIRECTORY;
1642  }
1643 
1644  /* Get current directory */
1646  CurDir = &NtCurrentPeb()->ProcessParameters->CurrentDirectory;
1647 
1648  /* Check if we have to drop current handle */
1650  {
1651  OldHandle = CurDir->Handle;
1652  CurDir->Handle = NULL;
1653  }
1654 
1655  /* Allocate a buffer for full path (using max possible length */
1656  FullPath.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, CurDir->DosPath.MaximumLength);
1657  if (!FullPath.Buffer)
1658  {
1660  goto Leave;
1661  }
1662 
1663  /* Init string */
1664  FullPath.Length = 0;
1665  FullPath.MaximumLength = CurDir->DosPath.MaximumLength;
1666 
1667  /* Get new directory full path */
1668  FullPathLength = RtlGetFullPathName_Ustr(Path, FullPath.MaximumLength, FullPath.Buffer, NULL, NULL, &PathType);
1669  if (!FullPathLength)
1670  {
1672  goto Leave;
1673  }
1674 
1675  SavedLength = FullPath.MaximumLength;
1676  CharLength = FullPathLength / sizeof(WCHAR);
1677 
1678  if (FullPathLength > FullPath.MaximumLength)
1679  {
1681  goto Leave;
1682  }
1683 
1684  /* Translate it to NT name */
1685  if (!RtlDosPathNameToNtPathName_U(FullPath.Buffer, &NtName, NULL, NULL))
1686  {
1688  goto Leave;
1689  }
1690 
1693  NULL, NULL);
1694 
1695  /* If previous current directory was removable, then check it for dropping */
1697  {
1698  /* Get back normal handle */
1699  CurDirHandle = (HANDLE)((ULONG_PTR)(CurDir->Handle) & ~RTL_CURDIR_ALL_FLAGS);
1700  CurDir->Handle = NULL;
1701 
1702  /* Get device information */
1703  Status = NtQueryVolumeInformationFile(CurDirHandle,
1704  &IoStatusBlock,
1705  &FileFsDeviceInfo,
1706  sizeof(FileFsDeviceInfo),
1708  /* Retry without taking care of removable device */
1709  if (!NT_SUCCESS(Status))
1710  {
1712  goto Leave;
1713  }
1714  }
1715  else
1716  {
1717  /* Open directory */
1718  Status = NtOpenFile(&CurDirHandle,
1721  &IoStatusBlock,
1724  if (!NT_SUCCESS(Status)) goto Leave;
1725 
1726  /* Get device information */
1727  Status = NtQueryVolumeInformationFile(CurDirHandle,
1728  &IoStatusBlock,
1729  &FileFsDeviceInfo,
1730  sizeof(FileFsDeviceInfo),
1732  if (!NT_SUCCESS(Status)) goto Leave;
1733  }
1734 
1735  /* If device is removable, mark handle */
1736  if (FileFsDeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)
1737  {
1738  CurDirHandle = (HANDLE)((ULONG_PTR)CurDirHandle | RTL_CURDIR_IS_REMOVABLE);
1739  }
1740 
1741  FullPath.Length = (USHORT)FullPathLength;
1742 
1743  /* If full path isn't \ terminated, do it */
1744  if (FullPath.Buffer[CharLength - 1] != OBJ_NAME_PATH_SEPARATOR)
1745  {
1746  if ((CharLength + 1) * sizeof(WCHAR) > SavedLength)
1747  {
1749  goto Leave;
1750  }
1751 
1752  FullPath.Buffer[CharLength] = OBJ_NAME_PATH_SEPARATOR;
1753  FullPath.Buffer[CharLength + 1] = UNICODE_NULL;
1754  FullPath.Length += sizeof(WCHAR);
1755  }
1756 
1757  /* If we have previous current directory with only us as reference, save it */
1758  if (RtlpCurDirRef != NULL && RtlpCurDirRef->RefCount == 1)
1759  {
1760  OldCurDirHandle = RtlpCurDirRef->Handle;
1761  }
1762  else
1763  {
1764  /* Allocate new current directory struct saving previous one */
1765  OldCurDir = RtlpCurDirRef;
1766  RtlpCurDirRef = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(RTLP_CURDIR_REF));
1767  if (!RtlpCurDirRef)
1768  {
1769  RtlpCurDirRef = OldCurDir;
1770  OldCurDir = NULL;
1772  goto Leave;
1773  }
1774 
1775  /* Set reference to 1 (us) */
1776  RtlpCurDirRef->RefCount = 1;
1777  }
1778 
1779  /* Save new data */
1780  CurDir->Handle = CurDirHandle;
1781  RtlpCurDirRef->Handle = CurDirHandle;
1782  CurDirHandle = NULL;
1783 
1784  /* Copy full path */
1785  RtlCopyMemory(CurDir->DosPath.Buffer, FullPath.Buffer, FullPath.Length + sizeof(WCHAR));
1786  CurDir->DosPath.Length = FullPath.Length;
1787 
1789 
1790 Leave:
1792 
1793  if (FullPath.Buffer)
1794  {
1795  RtlFreeHeap(RtlGetProcessHeap(), 0, FullPath.Buffer);
1796  }
1797 
1798  if (NtName.Buffer)
1799  {
1800  RtlFreeHeap(RtlGetProcessHeap(), 0, NtName.Buffer);
1801  }
1802 
1803  if (CurDirHandle) NtClose(CurDirHandle);
1804 
1805  if (OldHandle) NtClose(OldHandle);
1806 
1807  if (OldCurDirHandle) NtClose(OldCurDirHandle);
1808 
1809  if (OldCurDir && InterlockedDecrement(&OldCurDir->RefCount) == 0)
1810  {
1811  NtClose(OldCurDir->Handle);
1812  RtlFreeHeap(RtlGetProcessHeap(), 0, OldCurDir);
1813  }
1814 
1815  return Status;
1816 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
enum _RTL_PATH_TYPE RTL_PATH_TYPE
ULONG NTAPI RtlIsDosDeviceName_Ustr(IN PCUNICODE_STRING PathString)
Definition: path.c:94
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static ULONG_PTR *static HANDLE(WINAPI *pCreateActCtxW)(PCACTCTXW)
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
VOID NTAPI RtlReleasePebLock(VOID)
Definition: libsupp.c:82
ULONG NTAPI RtlGetFullPathName_Ustr(_In_ PUNICODE_STRING FileName, _In_ ULONG Size, _Out_z_bytecap_(Size) PWSTR Buffer, _Out_opt_ PCWSTR *ShortName, _Out_opt_ PBOOLEAN InvalidName, _Out_ RTL_PATH_TYPE *PathType)
Definition: path.c:615
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:125
uint32_t ULONG_PTR
Definition: typedefs.h:63
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define UNICODE_NULL
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI NtQueryVolumeInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
Definition: iofunc.c:3976
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:484
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
NTSTATUS NTAPI RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path)
Definition: path.c:1620
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define OBJ_INHERIT
Definition: winternl.h:225
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define InterlockedDecrement
Definition: armddk.h:52
#define SYNCHRONIZE
Definition: nt_native.h:61
#define RTL_CURDIR_ALL_FLAGS
Definition: path.c:28
Status
Definition: gdiplustypes.h:24
BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(IN PCWSTR DosName, OUT PUNICODE_STRING NtName, OUT PCWSTR *PartName, OUT PRTL_RELATIVE_NAME_U RelativeName)
Definition: path.c:1889
PRTL_UNICODE_STRING_BUFFER Path
#define NtCurrentPeb()
Definition: FLS.c:19
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define RTL_CURDIR_DROP_OLD_HANDLE
Definition: path.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
VOID NTAPI RtlAcquirePebLock(VOID)
Definition: libsupp.c:72
#define RTL_CURDIR_IS_REMOVABLE
Definition: path.c:26
UNICODE_STRING DosPath
Definition: rtltypes.h:1362
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
unsigned int ULONG
Definition: retypes.h:1
HANDLE Handle
Definition: rtltypes.h:1363
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
PRTLP_CURDIR_REF RtlpCurDirRef
Definition: path.c:55
return STATUS_SUCCESS
Definition: btrfs.c:2725

Referenced by SetCurrentDirectoryA(), and SetCurrentDirectoryW().

Variable Documentation

◆ DeviceRootString

const UNICODE_STRING DeviceRootString = RTL_CONSTANT_STRING(L"\\\\.\\")

Definition at line 34 of file path.c.

Referenced by RtlGetFullPathName_Ustr(), and RtlIsDosDeviceName_Ustr().

◆ RtlpCurDirRef

PRTLP_CURDIR_REF RtlpCurDirRef

Definition at line 55 of file path.c.

Referenced by RtlpDosPathNameToRelativeNtPathName_Ustr(), and RtlSetCurrentDirectory_U().

◆ RtlpDefaultExtension

const UNICODE_STRING RtlpDefaultExtension = RTL_CONSTANT_STRING(L".DLL")
static

Definition at line 50 of file path.c.

Referenced by RtlComputePrivatizedDllName_U().

◆ RtlpDosAUXDevice

const UNICODE_STRING RtlpDosAUXDevice = RTL_CONSTANT_STRING(L"AUX")

Definition at line 44 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosCOMDevice

const UNICODE_STRING RtlpDosCOMDevice = RTL_CONSTANT_STRING(L"COM")

Definition at line 42 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosCONDevice

const UNICODE_STRING RtlpDosCONDevice = RTL_CONSTANT_STRING(L"CON")

Definition at line 45 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosDevicesPrefix

◆ RtlpDosDevicesUncPrefix

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

◆ RtlpDosLPTDevice

const UNICODE_STRING RtlpDosLPTDevice = RTL_CONSTANT_STRING(L"LPT")

Definition at line 41 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosNULDevice

const UNICODE_STRING RtlpDosNULDevice = RTL_CONSTANT_STRING(L"NUL")

Definition at line 46 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosPRNDevice

const UNICODE_STRING RtlpDosPRNDevice = RTL_CONSTANT_STRING(L"PRN")

Definition at line 43 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDosSlashCONDevice

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

Definition at line 38 of file path.c.

Referenced by RtlIsDosDeviceName_Ustr().

◆ RtlpDotLocal

const UNICODE_STRING RtlpDotLocal = RTL_CONSTANT_STRING(L".Local\\")
static

Definition at line 51 of file path.c.

Referenced by RtlComputePrivatizedDllName_U().

◆ RtlpDoubleSlashPrefix

const UNICODE_STRING RtlpDoubleSlashPrefix = RTL_CONSTANT_STRING(L"\\\\")

Definition at line 48 of file path.c.

Referenced by RtlNtPathNameToDosPathName().

◆ RtlpPathDividers

const UNICODE_STRING RtlpPathDividers = RTL_CONSTANT_STRING(L"\\/")
static

Definition at line 52 of file path.c.

Referenced by RtlComputePrivatizedDllName_U().

◆ RtlpWin32NtRootSlash

const UNICODE_STRING RtlpWin32NtRootSlash = RTL_CONSTANT_STRING(L"\\\\?\\")

Definition at line 37 of file path.c.

Referenced by RtlpDosPathNameToRelativeNtPathName_Ustr().