changeset 17574:a6f392cc9587 v8.1.1784

patch 8.1.1784: MS-Windows: resolve() does not work if serial nr duplicated commit https://github.com/vim/vim/commit/3f9bdeb2a521a408c04fd9584a752845b3accbbd Author: Bram Moolenaar <Bram@vim.org> Date: Thu Aug 1 13:55:37 2019 +0200 patch 8.1.1784: MS-Windows: resolve() does not work if serial nr duplicated Problem: MS-Windows: resolve() does not work if serial nr duplicated. Solution: Use another method to get the full path. (Ken Takata, closes https://github.com/vim/vim/issues/4661)
author Bram Moolenaar <Bram@vim.org>
date Thu, 01 Aug 2019 14:00:08 +0200
parents c9e79e8ef303
children b2a246caeb25
files src/os_mswin.c src/version.c
diffstat 2 files changed, 30 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -1703,55 +1703,12 @@ mch_print_set_fg(long_u fgcol)
 #  include <shlobj.h>
 # endif
 
-typedef enum _FILE_INFO_BY_HANDLE_CLASS_ {
-  FileBasicInfo_,
-  FileStandardInfo_,
-  FileNameInfo_,
-  FileRenameInfo_,
-  FileDispositionInfo_,
-  FileAllocationInfo_,
-  FileEndOfFileInfo_,
-  FileStreamInfo_,
-  FileCompressionInfo_,
-  FileAttributeTagInfo_,
-  FileIdBothDirectoryInfo_,
-  FileIdBothDirectoryRestartInfo_,
-  FileIoPriorityHintInfo_,
-  FileRemoteProtocolInfo_,
-  FileFullDirectoryInfo_,
-  FileFullDirectoryRestartInfo_,
-  FileStorageInfo_,
-  FileAlignmentInfo_,
-  FileIdInfo_,
-  FileIdExtdDirectoryInfo_,
-  FileIdExtdDirectoryRestartInfo_,
-  FileDispositionInfoEx_,
-  FileRenameInfoEx_,
-  MaximumFileInfoByHandleClass_
-} FILE_INFO_BY_HANDLE_CLASS_;
-
-typedef struct _FILE_NAME_INFO_ {
-  DWORD FileNameLength;
-  WCHAR FileName[1];
-} FILE_NAME_INFO_;
-
-typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)(
-	HANDLE				hFile,
-	FILE_INFO_BY_HANDLE_CLASS_	FileInformationClass,
-	LPVOID				lpFileInformation,
-	DWORD				dwBufferSize);
-static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL;
-
-typedef BOOL (WINAPI *pfnGetVolumeInformationByHandleW)(
+typedef BOOL (WINAPI *pfnGetFinalPathNameByHandleW)(
 	HANDLE	hFile,
-	LPWSTR	lpVolumeNameBuffer,
-	DWORD	nVolumeNameSize,
-	LPDWORD	lpVolumeSerialNumber,
-	LPDWORD	lpMaximumComponentLength,
-	LPDWORD	lpFileSystemFlags,
-	LPWSTR	lpFileSystemNameBuffer,
-	DWORD	nFileSystemNameSize);
-static pfnGetVolumeInformationByHandleW pGetVolumeInformationByHandleW = NULL;
+	LPWSTR	lpszFilePath,
+	DWORD	cchFilePath,
+	DWORD	dwFlags);
+static pfnGetFinalPathNameByHandleW pGetFinalPathNameByHandleW = NULL;
 
 # define is_path_sep(c)	    ((c) == L'\\' || (c) == L'/')
 
@@ -1791,28 +1748,21 @@ resolve_reparse_point(char_u *fname)
 {
     HANDLE	    h = INVALID_HANDLE_VALUE;
     DWORD	    size;
-    WCHAR	    *p;
+    WCHAR	    *p, *wp;
     char_u	    *rfname = NULL;
-    FILE_NAME_INFO_ *nameinfo = NULL;
-    WCHAR	    buff[MAX_PATH], *volnames = NULL;
-    HANDLE	    hv;
-    DWORD	    snfile, snfind;
+    WCHAR	    *buff = NULL;
     static BOOL	    loaded = FALSE;
 
-    if (pGetFileInformationByHandleEx == NULL ||
-	    pGetVolumeInformationByHandleW == NULL)
+    if (pGetFinalPathNameByHandleW == NULL)
     {
 	HMODULE hmod = GetModuleHandle("kernel32.dll");
 
 	if (loaded == TRUE)
 	    return NULL;
-	pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx)
-		GetProcAddress(hmod, "GetFileInformationByHandleEx");
-	pGetVolumeInformationByHandleW = (pfnGetVolumeInformationByHandleW)
-		GetProcAddress(hmod, "GetVolumeInformationByHandleW");
+	pGetFinalPathNameByHandleW = (pfnGetFinalPathNameByHandleW)
+		GetProcAddress(hmod, "GetFinalPathNameByHandleW");
 	loaded = TRUE;
-	if (pGetFileInformationByHandleEx == NULL ||
-		pGetVolumeInformationByHandleW == NULL)
+	if (pGetFinalPathNameByHandleW == NULL)
 	    return NULL;
     }
 
@@ -1833,60 +1783,32 @@ resolve_reparse_point(char_u *fname)
     if (h == INVALID_HANDLE_VALUE)
 	goto fail;
 
-    size = sizeof(FILE_NAME_INFO_) + sizeof(WCHAR) * (MAX_PATH - 1);
-    nameinfo = alloc(size + sizeof(WCHAR));
-    if (nameinfo == NULL)
-	goto fail;
-
-    if (!pGetFileInformationByHandleEx(h, FileNameInfo_, nameinfo, size))
+    size = pGetFinalPathNameByHandleW(h, NULL, 0, 0);
+    if (size == 0)
 	goto fail;
-
-    nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = 0;
-
-    if (!pGetVolumeInformationByHandleW(
-	    h, NULL, 0, &snfile, NULL, NULL, NULL, 0))
+    buff = ALLOC_MULT(WCHAR, size);
+    if (buff == NULL)
 	goto fail;
-
-    hv = FindFirstVolumeW(buff, MAX_PATH);
-    if (hv == INVALID_HANDLE_VALUE)
+    if (pGetFinalPathNameByHandleW(h, buff, size, 0) == 0)
 	goto fail;
 
-    do {
-	GetVolumeInformationW(
-		buff, NULL, 0, &snfind, NULL, NULL, NULL, 0);
-	if (snfind == snfile)
-	    break;
-    } while (FindNextVolumeW(hv, buff, MAX_PATH));
-
-    FindVolumeClose(hv);
-
-    if (snfind != snfile)
-	goto fail;
-
-    size = 0;
-    if (!GetVolumePathNamesForVolumeNameW(buff, NULL, 0, &size) &&
-	    GetLastError() != ERROR_MORE_DATA)
-	goto fail;
-
-    volnames = ALLOC_MULT(WCHAR, size);
-    if (!GetVolumePathNamesForVolumeNameW(buff, volnames, size,
-		&size))
-	goto fail;
-
-    wcscpy(buff, volnames);
-    if (nameinfo->FileName[0] == '\\')
-	wcscat(buff, nameinfo->FileName + 1);
+    if (wcsncmp(buff, L"\\\\?\\UNC\\", 8) == 0)
+    {
+	buff[6] = L'\\';
+	wp = buff + 6;
+    }
+    else if (wcsncmp(buff, L"\\\\?\\", 4) == 0)
+	wp = buff + 4;
     else
-	wcscat(buff, nameinfo->FileName);
-    rfname = utf16_to_enc(buff, NULL);
+	wp = buff;
+
+    rfname = utf16_to_enc(wp, NULL);
 
 fail:
     if (h != INVALID_HANDLE_VALUE)
 	CloseHandle(h);
-    if (nameinfo != NULL)
-	vim_free(nameinfo);
-    if (volnames != NULL)
-	vim_free(volnames);
+    if (buff != NULL)
+	vim_free(buff);
 
     return rfname;
 }
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1784,
+/**/
     1783,
 /**/
     1782,