[RTL]: Implement RtlDosPathNameToRelativeNtPathName_U_WithStatus, RtlDosPathNameToRelativeNtPathName_U, RtlDosPathNameToNtPathName_U_WithStatus.

[RTL]: Reimplement RtlDosPathNameToNtPathName_U to use UNICODE_STRING semantics.
[RTL]: Fix RtlGetFullPathName_Ustr.
[RTL]: RtlGetFullPathName_U remains based on the legacy non-UNICODE_STRING mechanism, but it's too complex to attempt changing for now.

svn path=/trunk/; revision=52726
This commit is contained in:
Alex Ionescu 2011-07-18 13:22:09 +00:00
parent 78bd31b30d
commit b328750c1b

View file

@ -25,127 +25,22 @@
/* GLOBALS ********************************************************************/
static const WCHAR DeviceRootW[] = L"\\\\.\\";
static const UNICODE_STRING _condev = RTL_CONSTANT_STRING(L"\\\\.\\CON");
static const UNICODE_STRING _unc = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
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 RtlpDosSlashCONDevice = RTL_CONSTANT_STRING(L"\\\\.\\CON");
const UNICODE_STRING RtlpDosNULDevice = RTL_CONSTANT_STRING(L"NUL");
/* PRIVATE FUNCTIONS **********************************************************/
BOOLEAN
NTAPI
RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName,
IN BOOLEAN SucceedIfBusy)
{
BOOLEAN Result;
RTL_RELATIVE_NAME_U RelativeName;
UNICODE_STRING NtPathName;
PVOID Buffer;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
FILE_BASIC_INFORMATION BasicInformation;
#if 0
/* Get the NT Path */
Result = RtlDosPathNameToRelativeNtPathName_Ustr(FileName,
&NtPathName,
NULL,
&RelativeName);
#else
/* FIXME: Use the old API for now */
Result = RtlDosPathNameToNtPathName_U(FileName->Buffer,
&NtPathName,
NULL,
&RelativeName);
#endif
if (!Result) return FALSE;
/* Save the buffer */
Buffer = NtPathName.Buffer;
/* Check if we have a relative name */
if (RelativeName.RelativeName.Length)
{
/* Use it */
NtPathName = RelativeName.RelativeName;
}
else
{
/* Otherwise ignore it */
RelativeName.ContainingDirectory = NULL;
}
/* Initialize the object attributes */
InitializeObjectAttributes(&ObjectAttributes,
&NtPathName,
OBJ_CASE_INSENSITIVE,
RelativeName.ContainingDirectory,
NULL);
/* Query the attributes and free the buffer now */
Status = ZwQueryAttributesFile(&ObjectAttributes, &BasicInformation);
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Check if we failed because the file is in use */
if ((Status == STATUS_SHARING_VIOLATION) ||
(Status == STATUS_ACCESS_DENIED))
{
/* Check if the caller wants this to be considered OK */
Result = SucceedIfBusy ? TRUE : FALSE;
}
else
{
/* A failure because the file didn't exist */
Result = FALSE;
}
}
else
{
/* The file exists */
Result = TRUE;
}
/* Return the result */
return Result;
}
BOOLEAN
NTAPI
RtlDoesFileExists_UStr(IN PUNICODE_STRING FileName)
{
/* Call the updated API */
return RtlDoesFileExists_UstrEx(FileName, TRUE);
}
BOOLEAN
NTAPI
RtlDoesFileExists_UEx(IN PCWSTR FileName,
IN BOOLEAN SucceedIfBusy)
{
UNICODE_STRING NameString;
/* Create the unicode name*/
if (NT_SUCCESS(RtlInitUnicodeStringEx(&NameString, FileName)))
{
/* Call the unicode function */
return RtlDoesFileExists_UstrEx(&NameString, SucceedIfBusy);
}
/* Fail */
return FALSE;
}
ULONG
NTAPI
RtlIsDosDeviceName_Ustr(IN PUNICODE_STRING PathString)
@ -381,6 +276,8 @@ RtlGetFullPathName_Ustr(IN PUNICODE_STRING FileName,
NTSTATUS Status;
/* For now, assume the name is valid */
DPRINT("Filename: %wZ\n", FileName);
DPRINT("Size and buffer: %lx %S\n", Size, Buffer);
if (InvalidName) *InvalidName = FALSE;
/* Handle initial path type and failure case */
@ -394,7 +291,7 @@ RtlGetFullPathName_Ustr(IN PUNICODE_STRING FileName,
/* Kill trailing spaces */
c = FileNameBuffer[FileNameChars - 1];
while ((FileNameLength) && (c != L' '))
while ((FileNameLength) && (c == L' '))
{
/* Keep going, ignoring the spaces */
FileNameLength -= sizeof(WCHAR);
@ -402,10 +299,11 @@ RtlGetFullPathName_Ustr(IN PUNICODE_STRING FileName,
}
/* Check if anything is left */
if (!FileNameLength ) return 0;
if (!FileNameLength) return 0;
/* Check if this is a DOS name */
DosLength = RtlIsDosDeviceName_Ustr(FileName);
DPRINT("DOS length for filename: %lx %wZ\n", DosLength, FileName);
if (DosLength)
{
/* Zero out the short name */
@ -450,11 +348,402 @@ RtlGetFullPathName_Ustr(IN PUNICODE_STRING FileName,
/* This should work well enough for our current needs */
*PathType = RtlDetermineDosPathNameType_U(FileNameBuffer);
DPRINT("Path type: %lx\n", *PathType);
/* This is disgusting... but avoids re-writing everything */
DPRINT("Calling old API with %s and %lx and %S\n", FileNameBuffer, Size, Buffer);
return RtlGetFullPathName_U(FileNameBuffer, Size, Buffer, (PWSTR*)ShortName);
}
NTSTATUS
NTAPI
RtlpWin32NTNameToNtPathName_U(IN PUNICODE_STRING DosPath,
IN PUNICODE_STRING NtPath,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
ULONG DosLength;
PWSTR NewBuffer, p;
/* Validate the DOS length */
DosLength = DosPath->Length;
if (DosLength >= UNICODE_STRING_MAX_BYTES) return STATUS_NAME_TOO_LONG;
/* Make space for the new path */
NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
0,
DosLength + sizeof(UNICODE_NULL));
if (!NewBuffer) return STATUS_NO_MEMORY;
/* Copy the prefix, and then the rest of the DOS path, and NULL-terminate */
RtlCopyMemory(NewBuffer, RtlpDosDevicesPrefix.Buffer, RtlpDosDevicesPrefix.Length);
RtlCopyMemory((PCHAR)NewBuffer + RtlpDosDevicesPrefix.Length,
DosPath->Buffer + RtlpDosDevicesPrefix.Length / sizeof(WCHAR),
DosPath->Length - RtlpDosDevicesPrefix.Length);
NewBuffer[DosLength / sizeof(WCHAR)] = UNICODE_NULL;
/* Did the caller send a relative name? */
if (RelativeName)
{
/* Zero initialize it */
RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0);
RelativeName->ContainingDirectory = NULL;
RelativeName->CurDirRef = 0;
}
/* Did the caller request a partial name? */
if (PartName)
{
/* Loop from the back until we find a path separator */
p = &NewBuffer[(DosLength - 1) / sizeof (WCHAR)];
while (p > NewBuffer) if (*p-- == '\\') break;
/* Was one found? */
if (p > NewBuffer)
{
/* Move past it -- anything left? */
p++;
if (!*p)
{
/* The path ends with a path separator, no part name */
*PartName = NULL;
}
else
{
/* What follows the path separator is the part name */
*PartName = p;
}
}
}
/* Build the final NT path string */
NtPath->Length = DosLength;
NtPath->Buffer = NewBuffer;
NtPath->MaximumLength = DosLength + sizeof(UNICODE_NULL);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative,
IN PCUNICODE_STRING DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
WCHAR BigBuffer[MAX_PATH + 1];
PWCHAR PrefixBuffer, NewBuffer, Buffer;
ULONG MaxLength, PathLength, PrefixLength, PrefixCut, LengthChars, Length;
UNICODE_STRING CapturedDosName, PartNameString;
BOOLEAN QuickPath;
RTL_PATH_TYPE InputPathType, BufferPathType;
NTSTATUS Status;
BOOLEAN NameInvalid;
/* Assume MAX_PATH for now */
DPRINT("Relative: %lx DosName: %wZ NtName: %wZ, PartName: %p, RelativeName: %p\n",
HaveRelative, DosName, NtName, PartName, RelativeName);
MaxLength = sizeof(BigBuffer);
/* Capture input string */
CapturedDosName = *DosName;
/* Check for \\?\\ form */
if ((CapturedDosName.Length <= RtlpWin32NtRootSlash.Length) |
(CapturedDosName.Buffer[0] != RtlpWin32NtRootSlash.Buffer[0]) ||
(CapturedDosName.Buffer[1] != RtlpWin32NtRootSlash.Buffer[1]) ||
(CapturedDosName.Buffer[2] != RtlpWin32NtRootSlash.Buffer[2]) ||
(CapturedDosName.Buffer[3] != RtlpWin32NtRootSlash.Buffer[3]))
{
/* Quick path won't be used */
QuickPath = FALSE;
/* Use the static buffer */
Buffer = BigBuffer;
MaxLength += RtlpDosDevicesUncPrefix.Length;
/* Allocate a buffer to hold the path */
NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MaxLength);
DPRINT("Length: %lx\n", MaxLength);
if (!NewBuffer) return STATUS_NO_MEMORY;
}
else
{
/* Use the optimized path after acquiring the lock */
QuickPath = 1;
NewBuffer = NULL;
}
/* Lock the PEB and check if the quick path can be used */
RtlAcquirePebLock();
if (QuickPath)
{
/* Some simple fixups will get us the correct path */
DPRINT("Quick path\n");
Status = RtlpWin32NTNameToNtPathName_U(&CapturedDosName,
NtName,
PartName,
RelativeName);
/* Release the lock, we're done here */
RtlReleasePebLock();
return Status;
}
/* Call the main function to get the full path name and length */
PathLength = RtlGetFullPathName_Ustr(&CapturedDosName,
MAX_PATH * sizeof(WCHAR),
Buffer,
PartName,
&NameInvalid,
&InputPathType);
if ((NameInvalid) || !(PathLength) || (PathLength > (MAX_PATH * sizeof(WCHAR))))
{
/* Invalid name, fail */
DPRINT("Invalid name: %lx Path Length: %lx\n", NameInvalid, PathLength);
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
RtlReleasePebLock();
return STATUS_OBJECT_NAME_INVALID;
}
/* Start by assuming the path starts with \??\ (DOS Devices Path) */
PrefixLength = RtlpDosDevicesPrefix.Length;
PrefixBuffer = RtlpDosDevicesPrefix.Buffer;
PrefixCut = 0;
/* Check where it really is */
BufferPathType = RtlDetermineDosPathNameType_U(Buffer);
DPRINT("Buffer: %S Type: %lx\n", Buffer, BufferPathType);
switch (BufferPathType)
{
/* It's actually a UNC path in \??\UNC\ */
case RtlPathTypeUncAbsolute:
PrefixLength = RtlpDosDevicesUncPrefix.Length;
PrefixBuffer = RtlpDosDevicesUncPrefix.Buffer;
PrefixCut = 2;
break;
case RtlPathTypeLocalDevice:
/* We made a good guess, go with it but skip the \??\ */
PrefixCut = 4;
break;
case RtlPathTypeDriveAbsolute:
case RtlPathTypeDriveRelative:
case RtlPathTypeRooted:
case RtlPathTypeRelative:
/* Our guess was good, roll with it */
break;
/* Nothing else is expected */
default:
ASSERT(FALSE);
}
/* Now copy the prefix and the buffer */
RtlCopyMemory(NewBuffer, PrefixBuffer, PrefixLength);
RtlCopyMemory((PCHAR)NewBuffer + PrefixLength,
&Buffer[PrefixCut],
PathLength - (PrefixCut * sizeof(WCHAR)));
/* Compute the length */
Length = PathLength - PrefixCut * sizeof(WCHAR) + PrefixLength;
LengthChars = Length / sizeof(WCHAR);
/* Setup the actual NT path string and terminate it */
NtName->Buffer = NewBuffer;
NtName->Length = Length;
NtName->MaximumLength = MaxLength;
NewBuffer[LengthChars] = UNICODE_NULL;
DPRINT("new buffer: %S\n", NewBuffer);
DPRINT("NT Name: %wZ\n", NtName);
/* Check if a partial name was requested */
if ((PartName) && (*PartName))
{
/* Convert to Unicode */
Status = RtlInitUnicodeStringEx(&PartNameString, *PartName);
if (NT_SUCCESS(Status))
{
/* Set the partial name */
*PartName = &NewBuffer[LengthChars - PartNameString.Length];
}
else
{
/* Fail */
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
RtlReleasePebLock();
return Status;
}
}
/* Check if a relative name was asked for */
if (RelativeName)
{
/* Setup the structure */
RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0);
RelativeName->ContainingDirectory = NULL;
RelativeName->CurDirRef = 0;
/* Check if the input path itself was relative */
if (InputPathType == RtlPathTypeRelative)
{
/* Don't handle this yet */
DPRINT1("UNIMPLEMENTED CORNER CASE\n");
RtlFreeHeap(RtlGetProcessHeap(), 0, NewBuffer);
RtlReleasePebLock();
return STATUS_NOT_IMPLEMENTED;
}
}
/* Done */
RtlReleasePebLock();
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
RtlpDosPathNameToRelativeNtPathName_U(IN BOOLEAN HaveRelative,
IN PCWSTR DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
NTSTATUS Status;
UNICODE_STRING NameString;
/* Create the unicode name */
Status = RtlInitUnicodeStringEx(&NameString, DosName);
if (NT_SUCCESS(Status))
{
/* Call the unicode function */
Status = RtlpDosPathNameToRelativeNtPathName_Ustr(HaveRelative,
&NameString,
NtName,
PartName,
RelativeName);
}
/* Return status */
return Status;
}
BOOLEAN
NTAPI
RtlDosPathNameToRelativeNtPathName_Ustr(IN PCUNICODE_STRING DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
/* Call the internal function */
ASSERT(RelativeName);
return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_Ustr(TRUE,
DosName,
NtName,
PartName,
RelativeName));
}
BOOLEAN
NTAPI
RtlDoesFileExists_UstrEx(IN PCUNICODE_STRING FileName,
IN BOOLEAN SucceedIfBusy)
{
BOOLEAN Result;
RTL_RELATIVE_NAME_U RelativeName;
UNICODE_STRING NtPathName;
PVOID Buffer;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
FILE_BASIC_INFORMATION BasicInformation;
/* Get the NT Path */
Result = RtlDosPathNameToRelativeNtPathName_Ustr(FileName,
&NtPathName,
NULL,
&RelativeName);
if (!Result) return FALSE;
/* Save the buffer */
Buffer = NtPathName.Buffer;
/* Check if we have a relative name */
if (RelativeName.RelativeName.Length)
{
/* Use it */
NtPathName = RelativeName.RelativeName;
}
else
{
/* Otherwise ignore it */
RelativeName.ContainingDirectory = NULL;
}
/* Initialize the object attributes */
InitializeObjectAttributes(&ObjectAttributes,
&NtPathName,
OBJ_CASE_INSENSITIVE,
RelativeName.ContainingDirectory,
NULL);
/* Query the attributes and free the buffer now */
Status = ZwQueryAttributesFile(&ObjectAttributes, &BasicInformation);
RtlReleaseRelativeName(&RelativeName);
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
/* Check if we failed */
if (!NT_SUCCESS(Status))
{
/* Check if we failed because the file is in use */
if ((Status == STATUS_SHARING_VIOLATION) ||
(Status == STATUS_ACCESS_DENIED))
{
/* Check if the caller wants this to be considered OK */
Result = SucceedIfBusy ? TRUE : FALSE;
}
else
{
/* A failure because the file didn't exist */
Result = FALSE;
}
}
else
{
/* The file exists */
Result = TRUE;
}
/* Return the result */
return Result;
}
BOOLEAN
NTAPI
RtlDoesFileExists_UStr(IN PUNICODE_STRING FileName)
{
/* Call the updated API */
return RtlDoesFileExists_UstrEx(FileName, TRUE);
}
BOOLEAN
NTAPI
RtlDoesFileExists_UEx(IN PCWSTR FileName,
IN BOOLEAN SucceedIfBusy)
{
UNICODE_STRING NameString;
/* Create the unicode name*/
if (NT_SUCCESS(RtlInitUnicodeStringEx(&NameString, FileName)))
{
/* Call the unicode function */
return RtlDoesFileExists_UstrEx(&NameString, SucceedIfBusy);
}
/* Fail */
return FALSE;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
@ -486,7 +775,7 @@ RtlGetLongestNtPathLength(VOID)
* This is, and has always been equal to, 269 characters, except in Wine
* which claims this is 277. Go figure.
*/
return (MAX_PATH + _unc.Length + sizeof(ANSI_NULL));
return (MAX_PATH + RtlpDosDevicesUncPrefix.Length + sizeof(ANSI_NULL));
}
/*
@ -1043,177 +1332,75 @@ ULONG NTAPI RtlGetFullPathName_U(
/*
* @implemented
*/
BOOLEAN NTAPI
RtlDosPathNameToNtPathName_U(IN PCWSTR DosPathName,
OUT PUNICODE_STRING NtPathName,
OUT PCWSTR *NtFileNamePart,
OUT PRTL_RELATIVE_NAME_U DirectoryInfo)
BOOLEAN
NTAPI
RtlDosPathNameToNtPathName_U(IN PCWSTR DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
UNICODE_STRING us;
PCURDIR cd;
ULONG Type;
ULONG Size;
ULONG Length;
ULONG tmpLength;
ULONG Offset;
WCHAR fullname[MAX_PATH + 1];
PWSTR Buffer = NULL;
RtlInitUnicodeString (&us, DosPathName);
if (us.Length > 8)
{
Buffer = us.Buffer;
/* check for "\\?\" - allows to use very long filenames ( up to 32k ) */
if (Buffer[0] == L'\\' && Buffer[1] == L'\\' &&
Buffer[2] == L'?' && Buffer[3] == L'\\')
{
/* allocate the new string and simply copy it */
NtPathName->Length = us.Length;
NtPathName->MaximumLength = us.Length + sizeof(WCHAR);
NtPathName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
0,
NtPathName->MaximumLength);
if (NtPathName->Buffer == NULL)
{
return FALSE;
}
/* copy the string */
RtlCopyMemory(NtPathName->Buffer,
us.Buffer,
NtPathName->Length);
NtPathName->Buffer[us.Length / sizeof(WCHAR)] = L'\0';
/* change the \\?\ prefix to \??\ */
NtPathName->Buffer[1] = L'?';
if (NtFileNamePart != NULL)
{
PWSTR FilePart = NULL;
PWSTR s;
/* try to find the last separator */
s = NtPathName->Buffer + (NtPathName->Length / sizeof(WCHAR));
while (s != NtPathName->Buffer)
{
if (*s == L'\\')
{
FilePart = s + 1;
break;
}
s--;
}
*NtFileNamePart = FilePart;
}
if (DirectoryInfo != NULL)
{
DirectoryInfo->RelativeName.Length = 0;
DirectoryInfo->RelativeName.MaximumLength = 0;
DirectoryInfo->RelativeName.Buffer = NULL;
DirectoryInfo->ContainingDirectory = NULL;
}
return TRUE;
}
}
Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
0,
sizeof( fullname ) + MAX_PFX_SIZE);
if (Buffer == NULL)
{
return FALSE;
}
RtlAcquirePebLock ();
Size = RtlGetFullPathName_U (DosPathName,
sizeof(fullname),
fullname,
(PWSTR*)NtFileNamePart);
if (Size == 0 || Size > MAX_PATH * sizeof(WCHAR))
{
RtlFreeHeap (RtlGetProcessHeap (),
0,
Buffer);
RtlReleasePebLock ();
return FALSE;
}
/* Set NT prefix */
Offset = 0;
memcpy (Buffer, L"\\??\\", 4 * sizeof(WCHAR));
tmpLength = 4;
Type = RtlDetermineDosPathNameType_U (fullname);
switch (Type)
{
case 1:
memcpy (Buffer + tmpLength, L"UNC\\", 4 * sizeof(WCHAR));
tmpLength += 4;
Offset = 2;
break; /* \\xxx */
case 6:
Offset = 4;
break; /* \\.\xxx */
}
Length = wcslen(fullname + Offset);
memcpy (Buffer + tmpLength, fullname + Offset, (Length + 1) * sizeof(WCHAR));
Length += tmpLength;
if (Type == RtlPathTypeDriveAbsolute ||
Type == RtlPathTypeDriveRelative)
{
/* make the drive letter to uppercase */
Buffer[tmpLength] = towupper(Buffer[tmpLength]);
}
/* set NT filename */
NtPathName->Length = Length * sizeof(WCHAR);
NtPathName->MaximumLength = sizeof(fullname) + MAX_PFX_SIZE;
NtPathName->Buffer = Buffer;
/* set pointer to file part if possible */
if (NtFileNamePart && *NtFileNamePart)
*NtFileNamePart = Buffer + Length - wcslen (*NtFileNamePart);
/* Set name and handle structure if possible */
if (DirectoryInfo)
{
memset (DirectoryInfo, 0, sizeof(RTL_RELATIVE_NAME_U));
cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath);
if (Type == 5 && cd->Handle)
{
RtlInitUnicodeString(&us, fullname);
if (RtlEqualUnicodeString(&us, &cd->DosPath, TRUE))
{
Length = ((cd->DosPath.Length / sizeof(WCHAR)) - Offset) + ((Type == 1) ? 8 : 4);
DirectoryInfo->RelativeName.Buffer = Buffer + Length;
DirectoryInfo->RelativeName.Length = NtPathName->Length - (Length * sizeof(WCHAR));
DirectoryInfo->RelativeName.MaximumLength = DirectoryInfo->RelativeName.Length;
DirectoryInfo->ContainingDirectory = cd->Handle;
}
}
}
RtlReleasePebLock();
return TRUE;
/* Call the internal function */
return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_U(FALSE,
DosName,
NtName,
PartName,
RelativeName));
}
/*
* @unimplemented
* @implemented
*/
BOOLEAN NTAPI
RtlDosPathNameToRelativeNtPathName_U(PVOID Unknown1,
PVOID Unknown2,
PVOID Unknown3,
PVOID Unknown4)
NTSTATUS
NTAPI
RtlDosPathNameToNtPathName_U_WithStatus(IN PCWSTR DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
DPRINT1("RtlDosPathNameToRelativeNtPathName_U(0x%p, 0x%p, 0x%p, 0x%p) UNIMPLEMENTED!\n",
Unknown1, Unknown2, Unknown3, Unknown4);
return FALSE;
/* Call the internal function */
return RtlpDosPathNameToRelativeNtPathName_U(FALSE,
DosName,
NtName,
PartName,
RelativeName);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
RtlDosPathNameToRelativeNtPathName_U(IN PWSTR DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
/* Call the internal function */
ASSERT(RelativeName);
return NT_SUCCESS(RtlpDosPathNameToRelativeNtPathName_U(TRUE,
DosName,
NtName,
PartName,
RelativeName));
}
/*
* @implemented
*/
NTSTATUS
NTAPI
RtlDosPathNameToRelativeNtPathName_U_WithStatus(IN PWSTR DosName,
OUT PUNICODE_STRING NtName,
OUT PCWSTR *PartName,
OUT PRTL_RELATIVE_NAME_U RelativeName)
{
/* Call the internal function */
ASSERT(RelativeName);
return RtlpDosPathNameToRelativeNtPathName_U(TRUE,
DosName,
NtName,
PartName,
RelativeName);
}
/*
@ -1269,7 +1456,7 @@ RtlDosSearchPath_U(IN PCWSTR Path,
Extension = NULL;
break;
}
/* Next character */
p++;
}