From 450943cf4268e99590c5a459bad936ed8c9bb4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 8 Jun 2013 14:48:33 +0000 Subject: [PATCH] [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 --- reactos/dll/win32/kernel32/client/path.c | 67 +++++++++++++----------- reactos/lib/rtl/path.c | 56 +++++++++++--------- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/reactos/dll/win32/kernel32/client/path.c b/reactos/dll/win32/kernel32/client/path.c index b7256b60e6d..a1cce704dbe 100644 --- a/reactos/dll/win32/kernel32/client/path.c +++ b/reactos/dll/win32/kernel32/client/path.c @@ -986,8 +986,8 @@ DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, - IN LPSTR lpBuffer, - IN LPSTR *lpFilePart) + OUT LPSTR lpBuffer, + OUT LPSTR *lpFilePart) { NTSTATUS Status; PWCHAR Buffer; @@ -1099,11 +1099,11 @@ DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, - IN LPWSTR lpBuffer, + OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart) { /* Call Rtl to do the work */ - return RtlGetFullPathName_U((LPWSTR)lpFileName, + return RtlGetFullPathName_U(lpFileName, nBufferLength * sizeof(WCHAR), lpBuffer, lpFilePart) / sizeof(WCHAR); @@ -2079,6 +2079,7 @@ GetTempPathW(IN DWORD count, 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 }; WCHAR tmp_path[MAX_PATH]; + WCHAR full_tmp_path[MAX_PATH]; UINT ret; DPRINT("%u,%p\n", count, path); @@ -2087,42 +2088,44 @@ GetTempPathW(IN DWORD count, !(ret = GetEnvironmentVariableW( temp, tmp_path, MAX_PATH )) && !(ret = GetEnvironmentVariableW( userprofile, tmp_path, MAX_PATH )) && !(ret = GetWindowsDirectoryW( tmp_path, MAX_PATH ))) + { return 0; + } - if (ret > MAX_PATH) - { - SetLastError(ERROR_FILENAME_EXCED_RANGE); - return 0; - } + if (ret > MAX_PATH) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } - ret = GetFullPathNameW(tmp_path, MAX_PATH, tmp_path, NULL); - if (!ret) return 0; + ret = GetFullPathNameW(tmp_path, MAX_PATH, full_tmp_path, NULL); + if (!ret) return 0; - if (ret > MAX_PATH - 2) - { - SetLastError(ERROR_FILENAME_EXCED_RANGE); - return 0; - } + if (ret > MAX_PATH - 2) + { + SetLastError(ERROR_FILENAME_EXCED_RANGE); + return 0; + } - if (tmp_path[ret-1] != '\\') - { - tmp_path[ret++] = '\\'; - tmp_path[ret] = '\0'; - } + if (full_tmp_path[ret-1] != '\\') + { + full_tmp_path[ret++] = '\\'; + full_tmp_path[ret] = '\0'; + } - ret++; /* add space for terminating 0 */ + ret++; /* add space for terminating 0 */ - if (count) - { - lstrcpynW(path, tmp_path, count); - if (count >= ret) - ret--; /* return length without 0 */ - else if (count < 4) - path[0] = 0; /* avoid returning ambiguous "X:" */ - } + if (count) + { + lstrcpynW(path, full_tmp_path, count); + if (count >= ret) + ret--; /* return length without 0 */ + else if (count < 4) + path[0] = 0; /* avoid returning ambiguous "X:" */ + } - DPRINT("GetTempPathW returning %u, %S\n", ret, path); - return ret; + DPRINT("GetTempPathW returning %u, %S\n", ret, path); + return ret; } /* diff --git a/reactos/lib/rtl/path.c b/reactos/lib/rtl/path.c index 8927e9caa5c..6b9bc32f47c 100644 --- a/reactos/lib/rtl/path.c +++ b/reactos/lib/rtl/path.c @@ -160,7 +160,7 @@ RtlIsDosDeviceName_Ustr(IN PCUNICODE_STRING PathString) { /* Check if the character is a path or drive separator */ 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 */ End++; @@ -422,30 +422,33 @@ RtlpWin32NTNameToNtPathName_U(IN PUNICODE_STRING DosPath, 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) + p = &NewBuffer[DosLength / sizeof(WCHAR)]; + while (--p > NewBuffer) { - /* Move past it -- anything left? */ - p++; - if (!*p) + /* We found a path separator, move past it */ + if (*p == OBJ_NAME_PATH_SEPARATOR) { - /* The path ends with a path separator, no part name */ - *PartName = NULL; - } - else - { - /* What follows the path separator is the part name */ - *PartName = p; + ++p; + break; } } + + /* 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 */ - NtPath->Length = (USHORT)DosLength; NtPath->Buffer = NewBuffer; + NtPath->Length = (USHORT)DosLength; NtPath->MaximumLength = (USHORT)DosLength + sizeof(UNICODE_NULL); return STATUS_SUCCESS; } @@ -574,7 +577,6 @@ RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative, /* Nothing else is expected */ default: ASSERT(FALSE); - } /* Now copy the prefix and the buffer */ @@ -592,7 +594,7 @@ RtlpDosPathNameToRelativeNtPathName_Ustr(IN BOOLEAN HaveRelative, NtName->Length = (USHORT)Length; NtName->MaximumLength = (USHORT)MaxLength; NewBuffer[LengthChars] = UNICODE_NULL; - DPRINT("new buffer: %S\n", NewBuffer); + DPRINT("New buffer: %S\n", NewBuffer); DPRINT("NT Name: %wZ\n", NtName); /* 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.Length = (USHORT)(PathLength - FullPath.Length); /* 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.Length -= sizeof(WCHAR); @@ -1121,7 +1123,7 @@ RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path) FullPath.Length = (USHORT)FullPathLength; /* 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) { @@ -1129,7 +1131,7 @@ RtlSetCurrentDirectory_U(IN PUNICODE_STRING Path) goto Leave; } - FullPath.Buffer[CharLength] = L'\\'; + FullPath.Buffer[CharLength] = OBJ_NAME_PATH_SEPARATOR; FullPath.Buffer[CharLength + 1] = UNICODE_NULL; FullPath.Length += sizeof(WCHAR); } @@ -1500,6 +1502,9 @@ ULONG NTAPI RtlGetFullPathName_U( 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; /* check for DOS device name */ @@ -1733,9 +1738,9 @@ RtlDosSearchPath_U(IN PCWSTR Path, } /* 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 */ @@ -2051,6 +2056,7 @@ RtlDosSearchPath_Ustr(IN ULONG Flags, /* Initialize optional arguments */ if (FullNameOut) *FullNameOut = NULL; if (FilePartSize) *FilePartSize = 0; + if (LengthNeeded) *LengthNeeded = 0; if (DynamicString) { DynamicString->Length = DynamicString->MaximumLength = 0; @@ -2322,7 +2328,7 @@ RtlDosSearchPath_Ustr(IN ULONG Flags, &StaticCandidateString, Status); } - DPRINT("STatus: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer); + DPRINT("Status: %lx BUFFER: %S\n", Status, CallerBuffer->Buffer); goto Quickie; } else