[KERNEL32]

- Fix IN/OUT declaration of parameters for GetFullPathNameA/W
- Fix a bad usage of GetFullPathNameW in the GetTempPathW API, where the source and destination buffer for GetFullPathNameW was the same (Yet another Wineism :(( ). On Windows, using the same buffer fills it with a garbled string. Avoid this behaviour on ReactOS too, because internally GetFullPathNameW calls RtlGetFullPathName_U, the latter zeroing-out the destination buffer before usage.

[RTL:PATH]
See comments of revision r59183 (and in particular, fix some ntdll:RtlDos* path functions).

svn path=/trunk/; revision=59193
This commit is contained in:
Hermès Bélusca-Maïto 2013-06-08 14:48:33 +00:00
parent 2370b46e6f
commit 450943cf42
2 changed files with 66 additions and 57 deletions

View file

@ -986,8 +986,8 @@ DWORD
WINAPI WINAPI
GetFullPathNameA(IN LPCSTR lpFileName, GetFullPathNameA(IN LPCSTR lpFileName,
IN DWORD nBufferLength, IN DWORD nBufferLength,
IN LPSTR lpBuffer, OUT LPSTR lpBuffer,
IN LPSTR *lpFilePart) OUT LPSTR *lpFilePart)
{ {
NTSTATUS Status; NTSTATUS Status;
PWCHAR Buffer; PWCHAR Buffer;
@ -1099,11 +1099,11 @@ DWORD
WINAPI WINAPI
GetFullPathNameW(IN LPCWSTR lpFileName, GetFullPathNameW(IN LPCWSTR lpFileName,
IN DWORD nBufferLength, IN DWORD nBufferLength,
IN LPWSTR lpBuffer, OUT LPWSTR lpBuffer,
OUT LPWSTR *lpFilePart) OUT LPWSTR *lpFilePart)
{ {
/* Call Rtl to do the work */ /* Call Rtl to do the work */
return RtlGetFullPathName_U((LPWSTR)lpFileName, return RtlGetFullPathName_U(lpFileName,
nBufferLength * sizeof(WCHAR), nBufferLength * sizeof(WCHAR),
lpBuffer, lpBuffer,
lpFilePart) / sizeof(WCHAR); lpFilePart) / sizeof(WCHAR);
@ -2079,6 +2079,7 @@ GetTempPathW(IN DWORD count,
static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 }; static const WCHAR temp[] = { 'T', 'E', 'M', 'P', 0 };
static const WCHAR userprofile[] = { 'U','S','E','R','P','R','O','F','I','L','E',0 }; static const WCHAR userprofile[] = { 'U','S','E','R','P','R','O','F','I','L','E',0 };
WCHAR tmp_path[MAX_PATH]; WCHAR tmp_path[MAX_PATH];
WCHAR full_tmp_path[MAX_PATH];
UINT ret; UINT ret;
DPRINT("%u,%p\n", count, path); DPRINT("%u,%p\n", count, path);
@ -2087,42 +2088,44 @@ GetTempPathW(IN DWORD count,
!(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) && !(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) &&
!(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) && !(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) &&
!(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH ))) !(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH )))
{
return 0; return 0;
}
if (ret > MAX_PATH) if (ret > MAX_PATH)
{ {
SetLastError(ERROR_FILENAME_EXCED_RANGE); SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0; return 0;
} }
ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_path, NULL); ret = GetFullPathNameW(tmp_path, MAX_PATH, full_tmp_path, NULL);
if (!ret) return 0; if (!ret) return 0;
if (ret > MAX_PATH - 2) if (ret > MAX_PATH - 2)
{ {
SetLastError(ERROR_FILENAME_EXCED_RANGE); SetLastError(ERROR_FILENAME_EXCED_RANGE);
return 0; return 0;
} }
if (tmp_path[ret-1] != '\\') if (full_tmp_path[ret-1] != '\\')
{ {
tmp_path[ret++] = '\\'; full_tmp_path[ret++] = '\\';
tmp_path[ret] = '\0'; full_tmp_path[ret] = '\0';
} }
ret++; /* add space for terminating 0 */ ret++; /* add space for terminating 0 */
if (count) if (count)
{ {
lstrcpynW(path, tmp_path, count); lstrcpynW(path, full_tmp_path, count);
if (count >= ret) if (count >= ret)
ret--; /* return length without 0 */ ret--; /* return length without 0 */
else if (count < 4) else if (count < 4)
path[0] = 0; /* avoid returning ambiguous "X:" */ path[0] = 0; /* avoid returning ambiguous "X:" */
} }
DPRINT("GetTempPathW returning %u, %S\n", ret, path); DPRINT("GetTempPathW returning %u, %S\n", ret, path);
return ret; return ret;
} }
/* /*

View file

@ -160,7 +160,7 @@ RtlIsDosDeviceName_Ustr(IN PCUNICODE_STRING PathString)
{ {
/* Check if the character is a path or drive separator */ /* Check if the character is a path or drive separator */
c = *End; c = *End;
if ((c == '\\') || (c == '/') || ((c == ':') && (End == PathCopy.Buffer + 1))) if (IS_PATH_SEPARATOR(c) || ((c == ':') && (End == PathCopy.Buffer + 1)))
{ {
/* Get the next lower case character */ /* Get the next lower case character */
End++; End++;
@ -422,30 +422,33 @@ RtlpWin32NTNameToNtPathName_U(IN PUNICODE_STRING DosPath,
if (PartName) if (PartName)
{ {
/* Loop from the back until we find a path separator */ /* Loop from the back until we find a path separator */
p = &NewBuffer[(DosLength - 1) / sizeof (WCHAR)]; p = &NewBuffer[DosLength / sizeof(WCHAR)];
while (p > NewBuffer) if (*p-- == '\\') break; while (--p > NewBuffer)
/* Was one found? */
if (p > NewBuffer)
{ {
/* Move past it -- anything left? */ /* We found a path separator, move past it */
p++; if (*p == OBJ_NAME_PATH_SEPARATOR)
if (!*p)
{ {
/* The path ends with a path separator, no part name */ ++p;
*PartName = NULL; break;
}
else
{
/* What follows the path separator is the part name */
*PartName = p;
} }
} }
/* Check whether a separator was found and if something remains */
if ((p > NewBuffer) && *p)
{
/* What follows the path separator is the partial name */
*PartName = p;
}
else
{
/* The path ends with a path separator, no partial name */
*PartName = NULL;
}
} }
/* Build the final NT path string */ /* Build the final NT path string */
NtPath->Length = (USHORT)DosLength;
NtPath->Buffer = NewBuffer; NtPath->Buffer = NewBuffer;
NtPath->Length = (USHORT)DosLength;
NtPath->MaximumLength = (USHORT)DosLength + sizeof(UNICODE_NULL); NtPath->MaximumLength = (USHORT)DosLength + sizeof(UNICODE_NULL);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -574,7 +577,6 @@ RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative,
/* Nothing else is expected */ /* Nothing else is expected */
default: default:
ASSERT(FALSE); ASSERT(FALSE);
} }
/* Now copy the prefix and the buffer */ /* Now copy the prefix and the buffer */
@ -592,7 +594,7 @@ RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative,
NtName->Length = (USHORT)Length; NtName->Length = (USHORT)Length;
NtName->MaximumLength = (USHORT)MaxLength; NtName->MaximumLength = (USHORT)MaxLength;
NewBuffer[LengthChars] = UNICODE_NULL; NewBuffer[LengthChars] = UNICODE_NULL;
DPRINT("new buffer: %S\n", NewBuffer); DPRINT("New buffer: %S\n", NewBuffer);
DPRINT("NT Name: %wZ\n", NtName); DPRINT("NT Name: %wZ\n", NtName);
/* Check if a partial name was requested */ /* Check if a partial name was requested */
@ -651,7 +653,7 @@ RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative,
RelativeName->RelativeName.Buffer = (PWSTR)((ULONG_PTR)NewBuffer + PrefixLength + FullPath.Length - PrefixCut * sizeof(WCHAR)); RelativeName->RelativeName.Buffer = (PWSTR)((ULONG_PTR)NewBuffer + PrefixLength + FullPath.Length - PrefixCut * sizeof(WCHAR));
RelativeName->RelativeName.Length = (USHORT)(PathLength - FullPath.Length); RelativeName->RelativeName.Length = (USHORT)(PathLength - FullPath.Length);
/* If relative name starts with \, skip it */ /* If relative name starts with \, skip it */
if (RelativeName->RelativeName.Buffer[0] == L'\\') if (RelativeName->RelativeName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{ {
RelativeName->RelativeName.Buffer++; RelativeName->RelativeName.Buffer++;
RelativeName->RelativeName.Length -= sizeof(WCHAR); RelativeName->RelativeName.Length -= sizeof(WCHAR);
@ -1121,7 +1123,7 @@ RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path)
FullPath.Length = (USHORT)FullPathLength; FullPath.Length = (USHORT)FullPathLength;
/* If full path isn't \ terminated, do it */ /* If full path isn't \ terminated, do it */
if (FullPath.Buffer[CharLength - 1] != L'\\') if (FullPath.Buffer[CharLength - 1] != OBJ_NAME_PATH_SEPARATOR)
{ {
if ((CharLength + 1) * sizeof(WCHAR) > SavedLength) if ((CharLength + 1) * sizeof(WCHAR) > SavedLength)
{ {
@ -1129,7 +1131,7 @@ RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path)
goto Leave; goto Leave;
} }
FullPath.Buffer[CharLength] = L'\\'; FullPath.Buffer[CharLength] = OBJ_NAME_PATH_SEPARATOR;
FullPath.Buffer[CharLength + 1] = UNICODE_NULL; FullPath.Buffer[CharLength + 1] = UNICODE_NULL;
FullPath.Length += sizeof(WCHAR); FullPath.Length += sizeof(WCHAR);
} }
@ -1500,6 +1502,9 @@ ULONG NTAPI RtlGetFullPathName_U(
if (!name || !*name) return 0; if (!name || !*name) return 0;
/* Zero out the destination buffer (implies that "name" should be different from "buffer" to get this function well-behaving) */
RtlZeroMemory(buffer, size);
if (file_part) *file_part = NULL; if (file_part) *file_part = NULL;
/* check for DOS device name */ /* check for DOS device name */
@ -1733,9 +1738,9 @@ RtlDosSearchPath_U(IN PCWSTR Path,
} }
/* Add a terminating slash if needed */ /* Add a terminating slash if needed */
if ((BufferStart != NewBuffer) && (BufferStart[-1] != '\\')) if ((BufferStart != NewBuffer) && (BufferStart[-1] != OBJ_NAME_PATH_SEPARATOR))
{ {
*BufferStart++ = '\\'; *BufferStart++ = OBJ_NAME_PATH_SEPARATOR;
} }
/* Bail out if we reached the end */ /* Bail out if we reached the end */
@ -2051,6 +2056,7 @@ RtlDosSearchPath_Ustr(IN ULONG Flags,
/* Initialize optional arguments */ /* Initialize optional arguments */
if (FullNameOut) *FullNameOut = NULL; if (FullNameOut) *FullNameOut = NULL;
if (FilePartSize) *FilePartSize = 0; if (FilePartSize) *FilePartSize = 0;
if (LengthNeeded) *LengthNeeded = 0;
if (DynamicString) if (DynamicString)
{ {
DynamicString->Length = DynamicString->MaximumLength = 0; DynamicString->Length = DynamicString->MaximumLength = 0;
@ -2322,7 +2328,7 @@ RtlDosSearchPath_Ustr(IN ULONG Flags,
&StaticCandidateString, &StaticCandidateString,
Status); Status);
} }
DPRINT("STatus: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer); DPRINT("Status: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer);
goto Quickie; goto Quickie;
} }
else else