mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
254 lines
8.8 KiB
Diff
254 lines
8.8 KiB
Diff
From 2bde361904bbd2463c8de66941e725add7a239e3 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
|
Date: Tue, 12 Aug 2014 20:24:14 +0200
|
|
Subject: kernel32: Implement GetFinalPathNameByHandle.
|
|
|
|
---
|
|
.../api-ms-win-core-file-l1-2-0.spec | 4 +-
|
|
dlls/kernel32/file.c | 182 +++++++++++++++++++++
|
|
dlls/kernel32/kernel32.spec | 2 +
|
|
include/fileapi.h | 8 +
|
|
4 files changed, 194 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/dlls/api-ms-win-core-file-l1-2-0/api-ms-win-core-file-l1-2-0.spec b/dlls/api-ms-win-core-file-l1-2-0/api-ms-win-core-file-l1-2-0.spec
|
|
index ebfd52e..cddf112 100644
|
|
--- a/dlls/api-ms-win-core-file-l1-2-0/api-ms-win-core-file-l1-2-0.spec
|
|
+++ b/dlls/api-ms-win-core-file-l1-2-0/api-ms-win-core-file-l1-2-0.spec
|
|
@@ -39,8 +39,8 @@
|
|
@ stdcall GetFileSizeEx(long ptr) kernel32.GetFileSizeEx
|
|
@ stdcall GetFileTime(long ptr ptr ptr) kernel32.GetFileTime
|
|
@ stdcall GetFileType(long) kernel32.GetFileType
|
|
-@ stub GetFinalPathNameByHandleA
|
|
-@ stub GetFinalPathNameByHandleW
|
|
+@ stdcall GetFinalPathNameByHandleA(long ptr long long) kernel32.GetFinalPathNameByHandleA
|
|
+@ stdcall GetFinalPathNameByHandleW(long ptr long long) kernel32.GetFinalPathNameByHandleW
|
|
@ stdcall GetFullPathNameA(str long ptr ptr) kernel32.GetFullPathNameA
|
|
@ stdcall GetFullPathNameW(wstr long ptr ptr) kernel32.GetFullPathNameW
|
|
@ stdcall GetLogicalDriveStringsW(long ptr) kernel32.GetLogicalDriveStringsW
|
|
diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c
|
|
index 006db1c..b3cc8c3 100644
|
|
--- a/dlls/kernel32/file.c
|
|
+++ b/dlls/kernel32/file.c
|
|
@@ -2829,3 +2829,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_NT */
|
|
+ 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] != '\\' ||
|
|
+ strncmpiW( info->Name.Buffer, drive_part, drive_part_len ))
|
|
+ {
|
|
+ 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 c072780..d6955d3 100644
|
|
--- a/dlls/kernel32/kernel32.spec
|
|
+++ b/dlls/kernel32/kernel32.spec
|
|
@@ -539,6 +539,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
|
|
--
|
|
2.1.3
|
|
|