Index: lib/rtl/path.c =================================================================== --- lib/rtl/path.c (révision 62612) +++ lib/rtl/path.c (copie de travail) @@ -10,7 +10,7 @@ * Pierre Schweitzer (pierre@reactos.org) */ -/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/ #include @@ -289,78 +289,97 @@ /****************************************************************** * 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; + * 2) Gets rid of duplicate backslashes; + * 3) 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++) + /**/ULONG PathLength = wcslen(Path); + /**/PWSTR end = Path + PathLength ; // Path + PathBufferSize / sizeof(WCHAR); /**/ + /**/PWSTR end2;/**/ + + /* Convert every '/' into a '\' */ + 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; + /**/end2 = 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; - continue; + /**/end2 = p;/**/ + continue; // Makes the while() loop breaking. case L'\\': /* .\ component */ next = p + 2; + if (end2 - next != wcslen(next)) DPRINT1("************* (1) (end2 - next = %d) != (wcslen(next) = %d) *************\n", end2 - next, wcslen(next)); RtlMoveMemory( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + /**/end2 -= (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--; } + if (end2 - next != wcslen(next)) DPRINT1("************* (1) (end2 - next = %d) != (wcslen(next) = %d) *************\n", end2 - next, wcslen(next)); RtlMoveMemory( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); + /**/end2 -= (next - p);/**/ continue; } else if (!p[2]) /* 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; + /**/end2 = 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'.') + /* Remove last dot in previous dir name */ + if (p > Path + mark && p[-1] == L'.') + { + if (end2 - p != wcslen(p)) DPRINT1("************* (end2 - p = %d) != (wcslen(p) = %d) *************\n", end2 - p, wcslen(p)); RtlMoveMemory( p-1, p, (wcslen(p) + 1) * sizeof(WCHAR) ); + /**/end2 -= 1;/**/ + } else p++; } @@ -369,22 +388,38 @@ /* 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 zone (which starts at p included) */ + if (end < p) DPRINT1("******************** end (0x%p) < p (0x%p), should not happen!! ********************\n", end, p); + // ASSERT(end >= p); + + // PathLength == ((ULONG_PTR)p-(ULONG_PTR)Path)/sizeof(WCHAR) == wcslen(Path); + + RtlZeroMemory(p, (end - p + 1) * sizeof(WCHAR)); + + /* Null-terminate the string */ // Done just above + // *p = UNICODE_NULL; +/* + if (PathLength != wcslen(Path)) + DPRINT1("******************** (v2) (Path = 0x%p ; p = 0x%p) ; PathLength (%d) != wcslen(Path) (%d), should not happen!! ; Path = '%S' ********************\n", + Path, p, PathLength, wcslen(Path), Path); + */ + + return (wcslen(Path) * 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) @@ -619,7 +654,7 @@ * 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 @@ /* * 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,16 +758,11 @@ } /* - * Finally, put the path in canonical form, - * i.e. simplify redundant . and .., etc... + * Finally, put the path in canonical form (remove + * redundant . and .., 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); + reqsize = RtlpCollapsePath(Buffer, /* Size, reqsize, */ PrefixCut, SkipTrailingPathSeparators); - /* 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 */ if (ShortName) { @@ -761,7 +788,8 @@ Quit: /* Release PEB lock */ RtlReleasePebLock(); - return (ULONG)reqsize; + + return reqsize; } NTSTATUS