summaryrefslogtreecommitdiff
path: root/src/os_mswin.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-08-01 13:55:37 +0200
committerBram Moolenaar <Bram@vim.org>2019-08-01 13:55:37 +0200
commit3f9bdeb2a521a408c04fd9584a752845b3accbbd (patch)
treecfdcb9d6adc8882fc2a4255abb63c2531bbfe9e2 /src/os_mswin.c
parentdff2adc8ddcb6c8f3390a82c321362f8d6756fb8 (diff)
downloadvim-git-3f9bdeb2a521a408c04fd9584a752845b3accbbd.tar.gz
patch 8.1.1784: MS-Windows: resolve() does not work if serial nr duplicatedv8.1.1784
Problem: MS-Windows: resolve() does not work if serial nr duplicated. Solution: Use another method to get the full path. (Ken Takata, closes #4661)
Diffstat (limited to 'src/os_mswin.c')
-rw-r--r--src/os_mswin.c134
1 files changed, 28 insertions, 106 deletions
diff --git a/src/os_mswin.c b/src/os_mswin.c
index ced065b0d..00b8caa96 100644
--- 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)
+ size = pGetFinalPathNameByHandleW(h, NULL, 0, 0);
+ if (size == 0)
goto fail;
-
- if (!pGetFileInformationByHandleEx(h, FileNameInfo_, nameinfo, size))
+ buff = ALLOC_MULT(WCHAR, size);
+ if (buff == NULL)
goto fail;
-
- nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = 0;
-
- if (!pGetVolumeInformationByHandleW(
- h, NULL, 0, &snfile, NULL, NULL, NULL, 0))
- 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;
}