diff --git a/README.md b/README.md index 6b414aac..9a2712bb 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Wine-Compholio contains fixes for the following Wine bugs: * Need for Speed 3 installer requires devices in HKEY_DYN_DATA ([Wine Bug #7115](http://bugs.winehq.org/show_bug.cgi?id=7115 "Need for Speed III installer fails in Win9X mode, reporting \"Could not get 'HardWareKey' value\" (active PnP device keys in 'HKEY_DYN_DATA\\\\Config Manager\\\\Enum' missing)")) * Return correct IMediaSeeking stream positions in quartz ([Wine Bug #23174](http://bugs.winehq.org/show_bug.cgi?id=23174 "Fallout 3: Diologue and Video/sound issues")) * Set ldr.EntryPoint for main executable ([Wine Bug #33034](http://bugs.winehq.org/show_bug.cgi?id=33034 "Many GFWL (Games For Windows Live) 1.x/2.x/3.x games crash or exit silently on startup (DiRT 2/3, GTA IV Steam)")) +* Some applications neeed kernel32.GetFinalPathNameByHandle ([Wine Bug #36073](http://bugs.winehq.org/show_bug.cgi?id=36073 "OneDrive crashes on unimplemented function KERNEL32.dll.GetFinalPathNameByHandleW")) * Support for AllocateAndGetTcpExTableFromStack ([Wine Bug #34372](http://bugs.winehq.org/show_bug.cgi?id=34372 "Add missing function AllocateAndGetTcpExTableFromStack() to iphlpapi.dll")) * Support for DwmInvalidateIconicBitmaps ([Wine Bug #32977](http://bugs.winehq.org/show_bug.cgi?id=32977 "Solidworks 2012 needs unimplemented function dwmapi.dll.DwmInvalidateIconicBitmaps (Win7 mode)")) * Support for GetSystemTimes ([Wine Bug #19813](http://bugs.winehq.org/show_bug.cgi?id=19813 "Voddler needs GetSystemTimes to run")) diff --git a/patches/Makefile b/patches/Makefile index e64d8686..16f02420 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -16,6 +16,7 @@ PATCHLIST := \ dwmapi-Invalidate_Thumbnail.ok \ fonts-Missing_Fonts.ok \ iphlpapi-TCP_Table.ok \ + kernel32-GetFinalPathNameByHandle.ok \ kernel32-GetSystemTimes.ok \ kernel32-GetVolumePathName.ok \ kernel32-Named_Pipe.ok \ @@ -230,6 +231,25 @@ iphlpapi-TCP_Table.ok: echo '+ { "iphlpapi-TCP_Table", "Erich E. Hoover", "Implement AllocateAndGetTcpExTableFromStack." },'; \ ) > iphlpapi-TCP_Table.ok +# Patchset kernel32-GetFinalPathNameByHandle +# | +# | Included patches: +# | * Implement GetFinalPathNameByHandle in kernel32. [by Michael Müller] +# | +# | This patchset fixes the following Wine bugs: +# | * [#36073] OneDrive crashes on unimplemented function KERNEL32.dll.GetFinalPathNameByHandleW +# | +# | Modified files: +# | * dlls/kernel32/file.c, dlls/kernel32/kernel32.spec, dlls/kernel32/tests/file.c, include/fileapi.h +# | +.INTERMEDIATE: kernel32-GetFinalPathNameByHandle.ok +kernel32-GetFinalPathNameByHandle.ok: + $(call APPLY_FILE,kernel32-GetFinalPathNameByHandle/0001-kernel32-Implement-GetFinalPathNameByHandle.patch) + $(call APPLY_FILE,kernel32-GetFinalPathNameByHandle/0002-kernel32-tests-Add-tests-for-GetFinalPathNameByHandl.patch) + @( \ + echo '+ { "kernel32-GetFinalPathNameByHandle", "Michael Müller", "Implement GetFinalPathNameByHandle in kernel32." },'; \ + ) > kernel32-GetFinalPathNameByHandle.ok + # Patchset kernel32-GetSystemTimes # | # | Included patches: diff --git a/patches/kernel32-GetFinalPathNameByHandle/0001-kernel32-Implement-GetFinalPathNameByHandle.patch b/patches/kernel32-GetFinalPathNameByHandle/0001-kernel32-Implement-GetFinalPathNameByHandle.patch new file mode 100644 index 00000000..4fb7fa9c --- /dev/null +++ b/patches/kernel32-GetFinalPathNameByHandle/0001-kernel32-Implement-GetFinalPathNameByHandle.patch @@ -0,0 +1,237 @@ +From 5301ca38d5f079f106616c2f629464de101bd8aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 12 Aug 2014 20:24:14 +0200 +Subject: kernel32: Implement GetFinalPathNameByHandle. + +--- + dlls/kernel32/file.c | 182 ++++++++++++++++++++++++++++++++++++++++++++ + dlls/kernel32/kernel32.spec | 2 + + include/fileapi.h | 8 ++ + 3 files changed, 192 insertions(+) + +diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c +index 412659b..eb17abb 100644 +--- a/dlls/kernel32/file.c ++++ b/dlls/kernel32/file.c +@@ -2810,3 +2810,185 @@ DWORD WINAPI K32GetDeviceDriverFileNameW(void *image_base, LPWSTR file_name, DWO + + return 0; + } ++ ++/*********************************************************************** ++ * GetFinalPathNameByHandleW (KERNEL32.@) ++ */ ++DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags) ++{ ++ WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1]; ++ OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer; ++ WCHAR drive_part[MAX_PATH]; ++ DWORD drive_part_len; ++ NTSTATUS status; ++ DWORD result = 0; ++ ULONG dummy; ++ WCHAR *ptr; ++ ++ TRACE( "(%p,%p,%d,%x)\n", file, path, charcount, flags ); ++ ++ /* check for invalid arguments */ ++ if (!path) ++ { ++ SetLastError( ERROR_INVALID_PARAMETER ); ++ return 0; ++ } ++ else if (file == INVALID_HANDLE_VALUE) ++ { ++ SetLastError( ERROR_INVALID_HANDLE ); ++ return 0; ++ } ++ else if (flags & ~(FILE_NAME_OPENED | VOLUME_NAME_GUID | VOLUME_NAME_NONE | VOLUME_NAME_NT)) ++ { ++ WARN("Invalid or unsupported flags: %x\n", flags); ++ SetLastError( ERROR_INVALID_PARAMETER ); ++ return 0; ++ } ++ ++ /* get object name */ ++ status = NtQueryObject( file, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ); ++ if (status != STATUS_SUCCESS) ++ { ++ SetLastError( RtlNtStatusToDosError( status ) ); ++ return 0; ++ } ++ else if (info->Name.Length < 4 * sizeof(WCHAR) || info->Name.Buffer[0] != '\\' || ++ info->Name.Buffer[1] != '?' || info->Name.Buffer[2] != '?' || info->Name.Buffer[3] != '\\' ) ++ { ++ FIXME("Unexpected object name: %s\n", debugstr_wn(info->Name.Buffer, info->Name.Length / sizeof(WCHAR))); ++ SetLastError( ERROR_GEN_FAILURE ); ++ return 0; ++ } ++ ++ /* add terminating null character, remove "\\??\\" */ ++ info->Name.Buffer[info->Name.Length / sizeof(WCHAR)] = 0; ++ info->Name.Length -= 4 * sizeof(WCHAR); ++ info->Name.Buffer += 4; ++ ++ /* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */ ++ if (flags & FILE_NAME_OPENED) ++ { ++ FIXME("FILE_NAME_OPENED not supported\n"); ++ flags &= ~FILE_NAME_OPENED; ++ } ++ ++ /* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_DOS */ ++ if (flags == VOLUME_NAME_NONE || flags == VOLUME_NAME_GUID || flags == VOLUME_NAME_NT) ++ { ++ if (!GetVolumePathNameW( info->Name.Buffer, drive_part, MAX_PATH )) ++ return 0; ++ ++ drive_part_len = strlenW(drive_part); ++ if (!drive_part_len || drive_part_len > strlenW(info->Name.Buffer) || ++ drive_part[drive_part_len-1] != '\\' || ++ memcmp( info->Name.Buffer, drive_part, drive_part_len * sizeof(WCHAR) )) ++ { ++ FIXME("Path %s returned by GetVolumePathNameW does not match file path %s\n", ++ debugstr_w(drive_part), debugstr_w(info->Name.Buffer)); ++ SetLastError( ERROR_GEN_FAILURE ); ++ return 0; ++ } ++ } ++ ++ if (flags == VOLUME_NAME_NONE) ++ { ++ ptr = info->Name.Buffer + drive_part_len - 1; ++ result = strlenW(ptr); ++ if (result < charcount) ++ memcpy(path, ptr, (result + 1) * sizeof(WCHAR)); ++ else result++; ++ } ++ else if (flags == VOLUME_NAME_GUID) ++ { ++ WCHAR volume_prefix[51]; ++ ++ /* GetVolumeNameForVolumeMountPointW sets error code on failure */ ++ if (!GetVolumeNameForVolumeMountPointW( drive_part, volume_prefix, 50 )) ++ return 0; ++ ++ ptr = info->Name.Buffer + drive_part_len; ++ result = strlenW(volume_prefix) + strlenW(ptr); ++ if (result < charcount) ++ { ++ path[0] = 0; ++ strcatW(path, volume_prefix); ++ strcatW(path, ptr); ++ } ++ else result++; ++ } ++ else if (flags == VOLUME_NAME_NT) ++ { ++ WCHAR nt_prefix[MAX_PATH]; ++ ++ /* QueryDosDeviceW sets error code on failure */ ++ drive_part[drive_part_len - 1] = 0; ++ if (!QueryDosDeviceW( drive_part, nt_prefix, MAX_PATH )) ++ return 0; ++ ++ ptr = info->Name.Buffer + drive_part_len - 1; ++ result = strlenW(nt_prefix) + strlenW(ptr); ++ if (result < charcount) ++ { ++ path[0] = 0; ++ strcatW(path, nt_prefix); ++ strcatW(path, ptr); ++ } ++ else result++; ++ } ++ else if (flags == VOLUME_NAME_DOS) ++ { ++ static const WCHAR dos_prefix[] = {'\\','\\','?','\\', '\0'}; ++ ++ result = strlenW(dos_prefix) + strlenW(info->Name.Buffer); ++ if (result < charcount) ++ { ++ path[0] = 0; ++ strcatW(path, dos_prefix); ++ strcatW(path, info->Name.Buffer); ++ } ++ else result++; ++ } ++ else ++ { ++ /* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */ ++ WARN("Invalid combination of flags: %x\n", flags); ++ SetLastError( ERROR_INVALID_PARAMETER ); ++ } ++ ++ return result; ++} ++ ++/*********************************************************************** ++ * GetFinalPathNameByHandleA (KERNEL32.@) ++ */ ++DWORD WINAPI GetFinalPathNameByHandleA(HANDLE file, LPSTR path, DWORD charcount, DWORD flags) ++{ ++ WCHAR *str; ++ DWORD result; ++ ++ TRACE( "(%p,%p,%d,%x)\n", file, path, charcount, flags ); ++ ++ if (!path || !charcount) ++ return GetFinalPathNameByHandleW(file, (LPWSTR)path, charcount, flags); ++ ++ str = HeapAlloc( GetProcessHeap(), 0, charcount * sizeof(WCHAR) ); ++ if (!str) ++ { ++ SetLastError( ERROR_NOT_ENOUGH_MEMORY ); ++ return 0; ++ } ++ ++ result = GetFinalPathNameByHandleW(file, (LPWSTR)str, charcount, flags); ++ if (result) ++ { ++ if (result < charcount) ++ { ++ result = FILE_name_WtoA( str, result, path, charcount - 1 ); ++ path[result] = 0; ++ } ++ else result--; /* Why does Windows do this? */ ++ } ++ ++ HeapFree( GetProcessHeap(), 0, str ); ++ return result; ++} +\ No newline at end of file +diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec +index 2de2119..10a5ef3 100644 +--- a/dlls/kernel32/kernel32.spec ++++ b/dlls/kernel32/kernel32.spec +@@ -538,6 +538,8 @@ + @ stdcall GetFileAttributesW(wstr) + @ stdcall GetFileInformationByHandle(long ptr) + @ stdcall GetFileInformationByHandleEx(long long ptr long) ++@ stdcall GetFinalPathNameByHandleA(long ptr long long) ++@ stdcall GetFinalPathNameByHandleW(long ptr long long) + @ stdcall GetFileSize(long ptr) + @ stdcall GetFileSizeEx(long ptr) + @ stdcall GetFileTime(long ptr ptr ptr) +diff --git a/include/fileapi.h b/include/fileapi.h +index 02bbbd4..0ccf9e9 100644 +--- a/include/fileapi.h ++++ b/include/fileapi.h +@@ -34,6 +34,14 @@ typedef struct _CREATEFILE2_EXTENDED_PARAMETERS { + + WINBASEAPI HANDLE WINAPI CreateFile2(LPCWSTR,DWORD,DWORD,DWORD,LPCREATEFILE2_EXTENDED_PARAMETERS); + ++#define FILE_NAME_NORMALIZED 0x0 ++#define FILE_NAME_OPENED 0x8 ++ ++#define VOLUME_NAME_DOS 0x0 ++#define VOLUME_NAME_GUID 0x1 ++#define VOLUME_NAME_NT 0x2 ++#define VOLUME_NAME_NONE 0x4 ++ + #ifdef __cplusplus + } + #endif +-- +1.8.3.2 + diff --git a/patches/kernel32-GetFinalPathNameByHandle/0002-kernel32-tests-Add-tests-for-GetFinalPathNameByHandl.patch b/patches/kernel32-GetFinalPathNameByHandle/0002-kernel32-tests-Add-tests-for-GetFinalPathNameByHandl.patch new file mode 100644 index 00000000..5f2088fe --- /dev/null +++ b/patches/kernel32-GetFinalPathNameByHandle/0002-kernel32-tests-Add-tests-for-GetFinalPathNameByHandl.patch @@ -0,0 +1,253 @@ +From d5bb58d2350486ac12970aef61dcec95f23dfbfe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Tue, 12 Aug 2014 20:25:18 +0200 +Subject: kernel32/tests: Add tests for GetFinalPathNameByHandle + +--- + dlls/kernel32/tests/file.c | 204 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 204 insertions(+) + +diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c +index 492a34f..490f4bd 100644 +--- a/dlls/kernel32/tests/file.c ++++ b/dlls/kernel32/tests/file.c +@@ -34,6 +34,7 @@ + #include "winerror.h" + #include "winnls.h" + #include "fileapi.h" ++#include "ntsecapi.h" + + static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD); + static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID); +@@ -46,6 +47,8 @@ static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD + static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG); + static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*); + static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*); ++static DWORD (WINAPI* pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD); ++static DWORD (WINAPI* pGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD); + + /* keep filename and filenameW the same */ + static const char filename[] = "testfile.xxx"; +@@ -85,6 +88,8 @@ static void InitFunctionPointers(void) + pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData"); + pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2"); + pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2"); ++ pGetFinalPathNameByHandleA = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleA"); ++ pGetFinalPathNameByHandleW = (void *) GetProcAddress(hkernel32, "GetFinalPathNameByHandleW"); + } + + static void test__hread( void ) +@@ -4088,6 +4093,203 @@ todo_wine + } + } + ++ ++static void test_GetFinalPathNameByHandleA(void) ++{ ++ static char prefix[] = "GetFinalPathNameByHandleA"; ++ static char dos_prefix[] = "\\\\?\\"; ++ char temp_path[MAX_PATH], test_path[MAX_PATH]; ++ char long_path[MAX_PATH], result_path[MAX_PATH]; ++ char dos_path[sizeof(dos_prefix) + MAX_PATH]; ++ HANDLE hFile; ++ DWORD count; ++ UINT ret; ++ ++ if (!pGetFinalPathNameByHandleA) ++ { ++ win_skip("GetFinalPathNameByHandleA is missing\n"); ++ return; ++ } ++ ++ /* Test calling with INVALID_HANDLE_VALUE */ ++ SetLastError(0xdeadbeaf); ++ count = pGetFinalPathNameByHandleA(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == 0, "Expected length 0, got %d\n", count); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); ++ ++ count = GetTempPathA(MAX_PATH, temp_path); ++ ok(count, "Failed to get temp path, error %d\n", GetLastError()); ++ if (!count) return; ++ ++ ret = GetTempFileNameA(temp_path, prefix, 0, test_path); ++ ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); ++ if (!ret) return; ++ ++ ret = GetLongPathNameA(test_path, long_path, MAX_PATH); ++ ok(ret != 0, "GetLongPathNameA error %d\n", GetLastError()); ++ if (!ret) return; ++ ++ hFile = CreateFileA(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, ++ CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0); ++ ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError()); ++ if (hFile == INVALID_HANDLE_VALUE) return; ++ ++ dos_path[0] = 0; ++ strcat(dos_path, dos_prefix); ++ strcat(dos_path, long_path); ++ ++ /* Test VOLUME_NAME_DOS with sufficient buffer size */ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleA(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == strlen(dos_path), "Expected length %d, got %d\n", strlen(dos_path), count); ++ if (count && count <= MAX_PATH) ++ ok(lstrcmpiA(dos_path, result_path) == 0, "Expected %s, got %s\n", dos_path, result_path); ++ ++ /* Test VOLUME_NAME_DOS with insufficient buffer size */ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-2, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == strlen(dos_path), "Expected length %d, got %d\n", strlen(dos_path), count); ++ ok(result_path[0] == 0x11, "Result path was modified\n"); ++ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == strlen(dos_path), "Expected length %d, got %d\n", strlen(dos_path), count); ++ ok(result_path[0] == 0x11, "Result path was modified\n"); ++ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == strlen(dos_path), "Expected length %d, got %d\n", strlen(dos_path), count); ++ ok(result_path[0] == 0x11, "Result path was modified\n"); ++ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleA(hFile, result_path, strlen(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == strlen(dos_path), "Expected length %d, got %d\n", strlen(dos_path), count); ++ ok(result_path[0] != 0x11, "Result path was not modified\n"); ++ ok(result_path[strlen(dos_path)+1] == 0x11, "Buffer overflow\n"); ++ ++ CloseHandle(hFile); ++} ++ ++static void test_GetFinalPathNameByHandleW(void) ++{ ++ static WCHAR prefix[] = {'G','e','t','F','i','n','a','l','P','a','t','h','N','a','m','e','B','y','H','a','n','d','l','e','W','\0'}; ++ static WCHAR dos_prefix[] = {'\\','\\','?','\\','\0'}; ++ WCHAR temp_path[MAX_PATH], test_path[MAX_PATH]; ++ WCHAR long_path[MAX_PATH], result_path[MAX_PATH]; ++ WCHAR dos_path[MAX_PATH + sizeof(dos_prefix)]; ++ WCHAR drive_part[MAX_PATH]; ++ WCHAR *file_part; ++ WCHAR volume_path[MAX_PATH+50]; ++ WCHAR nt_path[2*MAX_PATH]; ++ HANDLE hFile; ++ DWORD count; ++ UINT ret; ++ ++ if (!pGetFinalPathNameByHandleW) ++ { ++ win_skip("GetFinalPathNameByHandleW is missing\n"); ++ return; ++ } ++ ++ /* Test calling with INVALID_HANDLE_VALUE */ ++ SetLastError(0xdeadbeaf); ++ count = pGetFinalPathNameByHandleW(INVALID_HANDLE_VALUE, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == 0, "Expected length 0, got %d\n", count); ++ ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); ++ ++ count = GetTempPathW(MAX_PATH, temp_path); ++ ok(count, "Failed to get temp path, error %d\n", GetLastError()); ++ if (!count) return; ++ ++ ret = GetTempFileNameW(temp_path, prefix, 0, test_path); ++ ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError()); ++ if (!ret) return; ++ ++ ret = GetLongPathNameW(test_path, long_path, MAX_PATH); ++ ok(ret != 0, "GetLongPathNameW error %d\n", GetLastError()); ++ if (!ret) return; ++ ++ hFile = CreateFileW(test_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, ++ CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0); ++ ok(hFile != INVALID_HANDLE_VALUE, "CreateFileW error %d\n", GetLastError()); ++ if (hFile == INVALID_HANDLE_VALUE) return; ++ ++ dos_path[0] = 0; ++ lstrcatW(dos_path, dos_prefix); ++ lstrcatW(dos_path, long_path); ++ ++ /* Test VOLUME_NAME_DOS with sufficient buffer size */ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count); ++ if (count && count <= MAX_PATH) ++ ok(lstrcmpiW(dos_path, result_path) == 0, "Expected %s, got %s\n", wine_dbgstr_w(dos_path), wine_dbgstr_w(result_path)); ++ ++ /* Test VOLUME_NAME_DOS with insufficient buffer size */ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count); ++ ok(result_path[0] == 0x1111, "Result path was modified\n"); ++ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path), FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == lstrlenW(dos_path) + 1, "Expected length %d, got %d\n", lstrlenW(dos_path) + 1, count); ++ ok(result_path[0] == 0x1111, "Result path was modified\n"); ++ ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, lstrlenW(dos_path)+1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); ++ ok(count == lstrlenW(dos_path), "Expected length %d, got %d\n", lstrlenW(dos_path), count); ++ ok(result_path[0] != 0x1111, "Result path was not modified\n"); ++ ok(result_path[lstrlenW(dos_path)+1] == 0x1111, "Buffer overflow\n"); ++ ++ if (!GetVolumePathNameW(long_path, drive_part, MAX_PATH)) ++ { ++ ok(0, "Failed to get drive part, error: %d\n", GetLastError()); ++ CloseHandle(hFile); ++ return; ++ } ++ ++ if (!GetVolumeNameForVolumeMountPointW(drive_part, volume_path, sizeof(volume_path) / sizeof(WCHAR))) ++ ok(0, "GetVolumeNameForVolumeMountPointW failed, error: %d\n", GetLastError()); ++ else ++ { ++ /* Test for VOLUME_NAME_GUID */ ++ lstrcatW(volume_path, long_path + lstrlenW(drive_part)); ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_GUID); ++ ok(count == lstrlenW(volume_path), "Expected length %d, got %d\n", lstrlenW(volume_path), count); ++ if (count && count <= MAX_PATH) ++ ok(lstrcmpiW(volume_path, result_path) == 0, "Expected %s, got %s\n", ++ wine_dbgstr_w(volume_path), wine_dbgstr_w(result_path)); ++ } ++ ++ /* Test for VOLUME_NAME_NONE */ ++ file_part = long_path + lstrlenW(drive_part) - 1; ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NONE); ++ ok(count == lstrlenW(file_part), "Expected length %d, got %d\n", lstrlenW(file_part), count); ++ if (count && count <= MAX_PATH) ++ ok(lstrcmpiW(file_part, result_path) == 0, "Expected %s, got %s\n", ++ wine_dbgstr_w(file_part), wine_dbgstr_w(result_path)); ++ ++ drive_part[lstrlenW(drive_part)-1] = 0; ++ if (!QueryDosDeviceW(drive_part, nt_path, sizeof(nt_path) / sizeof(WCHAR))) ++ ok(0, "QueryDosDeviceW failed, error: %d\n", GetLastError()); ++ else ++ { ++ /* Test for VOLUME_NAME_NT */ ++ lstrcatW(nt_path, file_part); ++ memset(result_path, 0x11, sizeof(result_path)); ++ count = pGetFinalPathNameByHandleW(hFile, result_path, MAX_PATH, FILE_NAME_NORMALIZED | VOLUME_NAME_NT); ++ ok(count == lstrlenW(nt_path), "Expected length %d, got %d\n", lstrlenW(nt_path), count); ++ if (count && count <= MAX_PATH) ++ ok(lstrcmpiW(nt_path, result_path) == 0, "Expected %s, got %s\n", ++ wine_dbgstr_w(nt_path), wine_dbgstr_w(result_path)); ++ } ++ ++ CloseHandle(hFile); ++} ++ + START_TEST(file) + { + InitFunctionPointers(); +@@ -4133,4 +4335,6 @@ START_TEST(file) + test_OpenFileById(); + test_SetFileValidData(); + test_file_access(); ++ test_GetFinalPathNameByHandleA(); ++ test_GetFinalPathNameByHandleW(); + } +-- +1.8.3.2 + diff --git a/patches/kernel32-GetFinalPathNameByHandle/definition b/patches/kernel32-GetFinalPathNameByHandle/definition new file mode 100644 index 00000000..77b4ba98 --- /dev/null +++ b/patches/kernel32-GetFinalPathNameByHandle/definition @@ -0,0 +1,4 @@ +Author: Michael Müller +Subject: Implement GetFinalPathNameByHandle in kernel32. +Revision: 1 +Fixes: [36073] Some applications neeed kernel32.GetFinalPathNameByHandle