mirror of
https://github.com/reactos/reactos.git
synced 2024-07-31 00:28:56 +00:00
[RTL]
Some fixes for RtlGetFullPathName_U(str): - Start to polish RtlpCollapsePath (Work in progress) - Correctly zero-out the path destination buffer They fix the following tests: * ntdll:RtlGetFullPathName_U (2 failures to full success) * ntdll:RtlGetFullPathName_UstrEx (2 failures to full success) svn path=/trunk/; revision=62623
This commit is contained in:
parent
9ad09cfd87
commit
e9cd63fb67
|
@ -10,7 +10,7 @@
|
||||||
* Pierre Schweitzer (pierre@reactos.org)
|
* Pierre Schweitzer (pierre@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include <rtl.h>
|
#include <rtl.h>
|
||||||
|
|
||||||
|
@ -289,102 +289,137 @@ RtlpCheckDeviceName(IN PUNICODE_STRING FileName,
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* RtlpCollapsePath (from WINE)
|
* RtlpCollapsePath (from WINE)
|
||||||
*
|
*
|
||||||
* Helper for RtlGetFullPathName_U.
|
* Helper for RtlGetFullPathName_U
|
||||||
* 1) Convert slashes into backslashes
|
*
|
||||||
* 2) Get rid of duplicate backslashes
|
* 1) Converts slashes into backslashes and gets rid of duplicated ones;
|
||||||
* 3) Get rid of . and .. components in the path.
|
* 2) Gets rid of . and .. components in the path.
|
||||||
|
*
|
||||||
|
* Returns the full path length without its terminating NULL character.
|
||||||
*/
|
*/
|
||||||
static VOID
|
static ULONG
|
||||||
RtlpCollapsePath(PWSTR path, ULONG mark, BOOLEAN SkipTrailingPathSeparators)
|
RtlpCollapsePath(PWSTR Path, /* ULONG PathBufferSize, ULONG PathLength, */ ULONG mark, BOOLEAN SkipTrailingPathSeparators)
|
||||||
{
|
{
|
||||||
PWSTR p, next;
|
PWSTR p, next;
|
||||||
|
|
||||||
/* convert every / into a \ */
|
// FIXME: Do not suppose NULL-terminated strings!!
|
||||||
for (p = path; *p; p++)
|
|
||||||
|
ULONG PathLength = wcslen(Path);
|
||||||
|
PWSTR EndBuffer = Path + PathLength; // Path + PathBufferSize / sizeof(WCHAR);
|
||||||
|
PWSTR EndPath;
|
||||||
|
|
||||||
|
/* Convert slashes into backslashes */
|
||||||
|
for (p = Path; *p; p++)
|
||||||
{
|
{
|
||||||
if (*p == L'/') *p = L'\\';
|
if (*p == L'/') *p = L'\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* collapse duplicate backslashes */
|
/* Collapse duplicate backslashes */
|
||||||
next = path + max( 1, mark );
|
next = Path + max( 1, mark );
|
||||||
for (p = next; *p; p++)
|
for (p = next; *p; p++)
|
||||||
{
|
{
|
||||||
if (*p != L'\\' || next[-1] != L'\\') *next++ = *p;
|
if (*p != L'\\' || next[-1] != L'\\') *next++ = *p;
|
||||||
}
|
}
|
||||||
*next = UNICODE_NULL;
|
*next = UNICODE_NULL;
|
||||||
|
EndPath = next;
|
||||||
|
|
||||||
p = path + mark;
|
p = Path + mark;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
if (*p == L'.')
|
if (*p == L'.')
|
||||||
{
|
{
|
||||||
switch(p[1])
|
switch (p[1])
|
||||||
{
|
{
|
||||||
case UNICODE_NULL: /* final . */
|
case UNICODE_NULL: /* final . */
|
||||||
if (p > path + mark) p--;
|
if (p > Path + mark) p--;
|
||||||
*p = UNICODE_NULL;
|
*p = UNICODE_NULL;
|
||||||
|
EndPath = p;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case L'\\': /* .\ component */
|
case L'\\': /* .\ component */
|
||||||
next = p + 2;
|
next = p + 2;
|
||||||
RtlMoveMemory( p, next, (wcslen(next) + 1) * sizeof(WCHAR) );
|
// ASSERT(EndPath - next == wcslen(next));
|
||||||
|
RtlMoveMemory(p, next, (EndPath - next + 1) * sizeof(WCHAR));
|
||||||
|
EndPath -= (next - p);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case L'.':
|
case L'.':
|
||||||
if (p[2] == L'\\') /* ..\ component */
|
if (p[2] == L'\\') /* ..\ component */
|
||||||
{
|
{
|
||||||
next = p + 3;
|
next = p + 3;
|
||||||
if (p > path + mark)
|
if (p > Path + mark)
|
||||||
{
|
{
|
||||||
p--;
|
p--;
|
||||||
while (p > path + mark && p[-1] != L'\\') p--;
|
while (p > Path + mark && p[-1] != L'\\') p--;
|
||||||
}
|
}
|
||||||
RtlMoveMemory( p, next, (wcslen(next) + 1) * sizeof(WCHAR) );
|
// ASSERT(EndPath - next == wcslen(next));
|
||||||
|
RtlMoveMemory(p, next, (EndPath - next + 1) * sizeof(WCHAR));
|
||||||
|
EndPath -= (next - p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!p[2]) /* final .. */
|
else if (p[2] == UNICODE_NULL) /* final .. */
|
||||||
{
|
{
|
||||||
if (p > path + mark)
|
if (p > Path + mark)
|
||||||
{
|
{
|
||||||
p--;
|
p--;
|
||||||
while (p > path + mark && p[-1] != L'\\') p--;
|
while (p > Path + mark && p[-1] != L'\\') p--;
|
||||||
if (p > path + mark) p--;
|
if (p > Path + mark) p--;
|
||||||
}
|
}
|
||||||
*p = UNICODE_NULL;
|
*p = UNICODE_NULL;
|
||||||
|
EndPath = p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* skip to the next component */
|
|
||||||
|
/* Skip to the next component */
|
||||||
while (*p && *p != L'\\') p++;
|
while (*p && *p != L'\\') p++;
|
||||||
if (*p == L'\\')
|
if (*p == L'\\')
|
||||||
{
|
{
|
||||||
/* remove last dot in previous dir name */
|
/* Remove last dot in previous dir name */
|
||||||
if (p > path + mark && p[-1] == L'.')
|
if (p > Path + mark && p[-1] == L'.')
|
||||||
RtlMoveMemory( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) );
|
{
|
||||||
|
// ASSERT(EndPath - p == wcslen(p));
|
||||||
|
RtlMoveMemory(p - 1, p, (EndPath - p + 1) * sizeof(WCHAR));
|
||||||
|
EndPath--;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
p++;
|
p++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove trailing backslashes if needed (after the UNC part if it exists) */
|
/* Remove trailing backslashes if needed (after the UNC part if it exists) */
|
||||||
if (SkipTrailingPathSeparators)
|
if (SkipTrailingPathSeparators)
|
||||||
{
|
{
|
||||||
while (p > path + mark && IS_PATH_SEPARATOR(p[-1])) *p-- = UNICODE_NULL;
|
while (p > Path + mark && IS_PATH_SEPARATOR(p[-1])) p--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove trailing spaces and dots (for all the path) */
|
/* Remove trailing spaces and dots (for all the path) */
|
||||||
while (p > path && (p[-1] == L' ' || p[-1] == L'.')) *p-- = UNICODE_NULL;
|
while (p > Path && (p[-1] == L' ' || p[-1] == L'.')) p--;
|
||||||
|
|
||||||
/* Null-terminate the string */
|
/*
|
||||||
*p = UNICODE_NULL;
|
* Zero-out the discarded buffer zone, starting just after
|
||||||
|
* the path string and going up to the end of the buffer.
|
||||||
|
* It also NULL-terminate the path string.
|
||||||
|
*/
|
||||||
|
ASSERT(EndBuffer >= p);
|
||||||
|
RtlZeroMemory(p, (EndBuffer - p + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* Return the real path length */
|
||||||
|
PathLength = (p - Path);
|
||||||
|
// ASSERT(PathLength == wcslen(Path));
|
||||||
|
return (PathLength * sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* RtlpSkipUNCPrefix (from WINE)
|
* RtlpSkipUNCPrefix (from WINE)
|
||||||
*
|
*
|
||||||
* Helper for RtlGetFullPathName_U
|
* Helper for RtlGetFullPathName_U
|
||||||
* Skip the \\share\dir part of a file name and return the new position
|
*
|
||||||
* (which can point on the last backslash of "dir\")
|
* Skips the \\share\dir part of a file name and returns the new position
|
||||||
|
* (which can point on the last backslash of "dir\").
|
||||||
*/
|
*/
|
||||||
static SIZE_T
|
static SIZE_T
|
||||||
RtlpSkipUNCPrefix(PCWSTR FileNameBuffer)
|
RtlpSkipUNCPrefix(PCWSTR FileNameBuffer)
|
||||||
|
@ -542,7 +577,7 @@ RtlGetFullPathName_Ustr(
|
||||||
return FullLength + sizeof(UNICODE_NULL);
|
return FullLength + sizeof(UNICODE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero out the destination buffer. FileName must be different from Buffer */
|
/* Zero-out the destination buffer. FileName must be different from Buffer */
|
||||||
RtlZeroMemory(Buffer, Size);
|
RtlZeroMemory(Buffer, Size);
|
||||||
|
|
||||||
/* Get the path type */
|
/* Get the path type */
|
||||||
|
@ -551,7 +586,7 @@ RtlGetFullPathName_Ustr(
|
||||||
|
|
||||||
|
|
||||||
/**********************************************
|
/**********************************************
|
||||||
** CODE REWRITTEN IS HAPPENING THERE **
|
** CODE REWRITING IS HAPPENING THERE **
|
||||||
**********************************************/
|
**********************************************/
|
||||||
Source = FileNameBuffer;
|
Source = FileNameBuffer;
|
||||||
SourceLength = FileNameLength;
|
SourceLength = FileNameLength;
|
||||||
|
@ -619,7 +654,7 @@ RtlGetFullPathName_Ustr(
|
||||||
* FIXME: Win2k seems to check that the environment
|
* FIXME: Win2k seems to check that the environment
|
||||||
* variable actually points to an existing directory.
|
* variable actually points to an existing directory.
|
||||||
* If not, root of the drive is used (this seems also
|
* If not, root of the drive is used (this seems also
|
||||||
* to be the only spot in RtlGetFullPathName that the
|
* to be the only place in RtlGetFullPathName that the
|
||||||
* existence of a part of a path is checked).
|
* existence of a part of a path is checked).
|
||||||
*/
|
*/
|
||||||
EnvVarValue.Buffer[EnvVarValue.Length / sizeof(WCHAR)] = L'\\';
|
EnvVarValue.Buffer[EnvVarValue.Length / sizeof(WCHAR)] = L'\\';
|
||||||
|
@ -709,13 +744,10 @@ RtlGetFullPathName_Ustr(
|
||||||
/*
|
/*
|
||||||
* Build the full path
|
* Build the full path
|
||||||
*/
|
*/
|
||||||
// if (ShortName) DPRINT1("buffer(1) = %S\n", Buffer);
|
|
||||||
/* Copy the path's prefix */
|
/* Copy the path's prefix */
|
||||||
if (PrefixLength) RtlMoveMemory(Buffer, Prefix, PrefixLength);
|
if (PrefixLength) RtlMoveMemory(Buffer, Prefix, PrefixLength);
|
||||||
// if (ShortName) DPRINT1("buffer(2) = %S\n", Buffer);
|
|
||||||
/* Copy the remaining part of the path */
|
/* Copy the remaining part of the path */
|
||||||
RtlMoveMemory(Buffer + PrefixLength / sizeof(WCHAR), Source, SourceLength + sizeof(WCHAR));
|
RtlMoveMemory(Buffer + PrefixLength / sizeof(WCHAR), Source, SourceLength + sizeof(WCHAR));
|
||||||
// if (ShortName) DPRINT1("buffer(3) = %S\n", Buffer);
|
|
||||||
|
|
||||||
/* Some cleanup */
|
/* Some cleanup */
|
||||||
Prefix = NULL;
|
Prefix = NULL;
|
||||||
|
@ -726,15 +758,11 @@ RtlGetFullPathName_Ustr(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, put the path in canonical form,
|
* Finally, put the path in canonical form (remove redundant . and ..,
|
||||||
* i.e. simplify redundant . and .., etc...
|
* (back)slashes...) and retrieve the length of the full path name
|
||||||
|
* (without its terminating null character) (in chars).
|
||||||
*/
|
*/
|
||||||
// if (*PathType == RtlPathTypeUncAbsolute) DPRINT1("RtlpCollapsePath('%S', %lu)\n", Buffer, PrefixCut);
|
reqsize = RtlpCollapsePath(Buffer, /* Size, reqsize, */ PrefixCut, SkipTrailingPathSeparators);
|
||||||
RtlpCollapsePath(Buffer, PrefixCut, SkipTrailingPathSeparators);
|
|
||||||
// if (ShortName) DPRINT1("buffer(4) = %S\n", Buffer);
|
|
||||||
|
|
||||||
/* Get the length of the full path name, without its terminating null character */
|
|
||||||
reqsize = wcslen(Buffer) * sizeof(WCHAR);
|
|
||||||
|
|
||||||
/* Find the file part, which is present after the last path separator */
|
/* Find the file part, which is present after the last path separator */
|
||||||
if (ShortName)
|
if (ShortName)
|
||||||
|
@ -761,7 +789,8 @@ RtlGetFullPathName_Ustr(
|
||||||
Quit:
|
Quit:
|
||||||
/* Release PEB lock */
|
/* Release PEB lock */
|
||||||
RtlReleasePebLock();
|
RtlReleasePebLock();
|
||||||
return (ULONG)reqsize;
|
|
||||||
|
return reqsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Reference in a new issue