mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +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
1 changed files with 76 additions and 47 deletions
|
@ -10,7 +10,7 @@
|
|||
* Pierre Schweitzer (pierre@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include <rtl.h>
|
||||
|
||||
|
@ -289,102 +289,137 @@ RtlpCheckDeviceName(IN PUNICODE_STRING FileName,
|
|||
/******************************************************************
|
||||
* RtlpCollapsePath (from WINE)
|
||||
*
|
||||
* Helper for RtlGetFullPathName_U.
|
||||
* 1) Convert slashes into backslashes
|
||||
* 2) Get rid of duplicate backslashes
|
||||
* 3) Get rid of . and .. components in the path.
|
||||
* Helper for RtlGetFullPathName_U
|
||||
*
|
||||
* 1) Converts slashes into backslashes and gets rid of duplicated ones;
|
||||
* 2) Gets rid of . and .. components in the path.
|
||||
*
|
||||
* Returns the full path length without its terminating NULL character.
|
||||
*/
|
||||
static VOID
|
||||
RtlpCollapsePath(PWSTR path, ULONG mark, BOOLEAN SkipTrailingPathSeparators)
|
||||
static ULONG
|
||||
RtlpCollapsePath(PWSTR Path, /* ULONG PathBufferSize, ULONG PathLength, */ ULONG mark, BOOLEAN SkipTrailingPathSeparators)
|
||||
{
|
||||
PWSTR p, next;
|
||||
|
||||
/* convert every / into a \ */
|
||||
for (p = path; *p; p++)
|
||||
// FIXME: Do not suppose NULL-terminated strings!!
|
||||
|
||||
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'\\';
|
||||
}
|
||||
|
||||
/* collapse duplicate backslashes */
|
||||
next = path + max( 1, mark );
|
||||
/* Collapse duplicate backslashes */
|
||||
next = Path + max( 1, mark );
|
||||
for (p = next; *p; p++)
|
||||
{
|
||||
if (*p != L'\\' || next[-1] != L'\\') *next++ = *p;
|
||||
}
|
||||
*next = UNICODE_NULL;
|
||||
EndPath = next;
|
||||
|
||||
p = path + mark;
|
||||
p = Path + mark;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == L'.')
|
||||
{
|
||||
switch(p[1])
|
||||
switch (p[1])
|
||||
{
|
||||
case UNICODE_NULL: /* final . */
|
||||
if (p > path + mark) p--;
|
||||
if (p > Path + mark) p--;
|
||||
*p = UNICODE_NULL;
|
||||
EndPath = p;
|
||||
continue;
|
||||
|
||||
case L'\\': /* .\ component */
|
||||
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;
|
||||
|
||||
case L'.':
|
||||
if (p[2] == L'\\') /* ..\ component */
|
||||
{
|
||||
next = p + 3;
|
||||
if (p > path + mark)
|
||||
if (p > Path + mark)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (!p[2]) /* final .. */
|
||||
else if (p[2] == UNICODE_NULL) /* final .. */
|
||||
{
|
||||
if (p > path + mark)
|
||||
if (p > Path + mark)
|
||||
{
|
||||
p--;
|
||||
while (p > path + mark && p[-1] != L'\\') p--;
|
||||
if (p > path + mark) p--;
|
||||
while (p > Path + mark && p[-1] != L'\\') p--;
|
||||
if (p > Path + mark) p--;
|
||||
}
|
||||
*p = UNICODE_NULL;
|
||||
EndPath = p;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* skip to the next component */
|
||||
|
||||
/* Skip to the next component */
|
||||
while (*p && *p != L'\\') p++;
|
||||
if (*p == L'\\')
|
||||
{
|
||||
/* remove last dot in previous dir name */
|
||||
if (p > path + mark && p[-1] == L'.')
|
||||
RtlMoveMemory( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) );
|
||||
/* Remove last dot in previous dir name */
|
||||
if (p > Path + mark && p[-1] == L'.')
|
||||
{
|
||||
// ASSERT(EndPath - p == wcslen(p));
|
||||
RtlMoveMemory(p - 1, p, (EndPath - p + 1) * sizeof(WCHAR));
|
||||
EndPath--;
|
||||
}
|
||||
else
|
||||
{
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove trailing backslashes if needed (after the UNC part if it exists) */
|
||||
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) */
|
||||
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)
|
||||
*
|
||||
* 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
|
||||
RtlpSkipUNCPrefix(PCWSTR FileNameBuffer)
|
||||
|
@ -542,7 +577,7 @@ RtlGetFullPathName_Ustr(
|
|||
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);
|
||||
|
||||
/* Get the path type */
|
||||
|
@ -551,7 +586,7 @@ RtlGetFullPathName_Ustr(
|
|||
|
||||
|
||||
/**********************************************
|
||||
** CODE REWRITTEN IS HAPPENING THERE **
|
||||
** CODE REWRITING IS HAPPENING THERE **
|
||||
**********************************************/
|
||||
Source = FileNameBuffer;
|
||||
SourceLength = FileNameLength;
|
||||
|
@ -619,7 +654,7 @@ RtlGetFullPathName_Ustr(
|
|||
* FIXME: Win2k seems to check that the environment
|
||||
* variable actually points to an existing directory.
|
||||
* 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).
|
||||
*/
|
||||
EnvVarValue.Buffer[EnvVarValue.Length / sizeof(WCHAR)] = L'\\';
|
||||
|
@ -709,13 +744,10 @@ RtlGetFullPathName_Ustr(
|
|||
/*
|
||||
* Build the full path
|
||||
*/
|
||||
// if (ShortName) DPRINT1("buffer(1) = %S\n", Buffer);
|
||||
/* Copy the path's prefix */
|
||||
if (PrefixLength) RtlMoveMemory(Buffer, Prefix, PrefixLength);
|
||||
// if (ShortName) DPRINT1("buffer(2) = %S\n", Buffer);
|
||||
/* Copy the remaining part of the path */
|
||||
RtlMoveMemory(Buffer + PrefixLength / sizeof(WCHAR), Source, SourceLength + sizeof(WCHAR));
|
||||
// if (ShortName) DPRINT1("buffer(3) = %S\n", Buffer);
|
||||
|
||||
/* Some cleanup */
|
||||
Prefix = NULL;
|
||||
|
@ -726,15 +758,11 @@ RtlGetFullPathName_Ustr(
|
|||
}
|
||||
|
||||
/*
|
||||
* Finally, put the path in canonical form,
|
||||
* i.e. simplify redundant . and .., etc...
|
||||
* Finally, put the path in canonical form (remove redundant . and ..,
|
||||
* (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);
|
||||
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);
|
||||
reqsize = RtlpCollapsePath(Buffer, /* Size, reqsize, */ PrefixCut, SkipTrailingPathSeparators);
|
||||
|
||||
/* Find the file part, which is present after the last path separator */
|
||||
if (ShortName)
|
||||
|
@ -761,7 +789,8 @@ RtlGetFullPathName_Ustr(
|
|||
Quit:
|
||||
/* Release PEB lock */
|
||||
RtlReleasePebLock();
|
||||
return (ULONG)reqsize;
|
||||
|
||||
return reqsize;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
|
Loading…
Reference in a new issue