comparison src/os_mswin.c @ 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 efd36a9052cc
children 59bc3cd42cf5
comparison
equal deleted inserted replaced
17573:c9e79e8ef303 17574:a6f392cc9587
1701 #if defined(FEAT_SHORTCUT) || defined(PROTO) 1701 #if defined(FEAT_SHORTCUT) || defined(PROTO)
1702 # ifndef PROTO 1702 # ifndef PROTO
1703 # include <shlobj.h> 1703 # include <shlobj.h>
1704 # endif 1704 # endif
1705 1705
1706 typedef enum _FILE_INFO_BY_HANDLE_CLASS_ { 1706 typedef BOOL (WINAPI *pfnGetFinalPathNameByHandleW)(
1707 FileBasicInfo_,
1708 FileStandardInfo_,
1709 FileNameInfo_,
1710 FileRenameInfo_,
1711 FileDispositionInfo_,
1712 FileAllocationInfo_,
1713 FileEndOfFileInfo_,
1714 FileStreamInfo_,
1715 FileCompressionInfo_,
1716 FileAttributeTagInfo_,
1717 FileIdBothDirectoryInfo_,
1718 FileIdBothDirectoryRestartInfo_,
1719 FileIoPriorityHintInfo_,
1720 FileRemoteProtocolInfo_,
1721 FileFullDirectoryInfo_,
1722 FileFullDirectoryRestartInfo_,
1723 FileStorageInfo_,
1724 FileAlignmentInfo_,
1725 FileIdInfo_,
1726 FileIdExtdDirectoryInfo_,
1727 FileIdExtdDirectoryRestartInfo_,
1728 FileDispositionInfoEx_,
1729 FileRenameInfoEx_,
1730 MaximumFileInfoByHandleClass_
1731 } FILE_INFO_BY_HANDLE_CLASS_;
1732
1733 typedef struct _FILE_NAME_INFO_ {
1734 DWORD FileNameLength;
1735 WCHAR FileName[1];
1736 } FILE_NAME_INFO_;
1737
1738 typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)(
1739 HANDLE hFile,
1740 FILE_INFO_BY_HANDLE_CLASS_ FileInformationClass,
1741 LPVOID lpFileInformation,
1742 DWORD dwBufferSize);
1743 static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL;
1744
1745 typedef BOOL (WINAPI *pfnGetVolumeInformationByHandleW)(
1746 HANDLE hFile, 1707 HANDLE hFile,
1747 LPWSTR lpVolumeNameBuffer, 1708 LPWSTR lpszFilePath,
1748 DWORD nVolumeNameSize, 1709 DWORD cchFilePath,
1749 LPDWORD lpVolumeSerialNumber, 1710 DWORD dwFlags);
1750 LPDWORD lpMaximumComponentLength, 1711 static pfnGetFinalPathNameByHandleW pGetFinalPathNameByHandleW = NULL;
1751 LPDWORD lpFileSystemFlags,
1752 LPWSTR lpFileSystemNameBuffer,
1753 DWORD nFileSystemNameSize);
1754 static pfnGetVolumeInformationByHandleW pGetVolumeInformationByHandleW = NULL;
1755 1712
1756 # define is_path_sep(c) ((c) == L'\\' || (c) == L'/') 1713 # define is_path_sep(c) ((c) == L'\\' || (c) == L'/')
1757 1714
1758 static int 1715 static int
1759 is_reparse_point_included(LPCWSTR fname) 1716 is_reparse_point_included(LPCWSTR fname)
1789 static char_u * 1746 static char_u *
1790 resolve_reparse_point(char_u *fname) 1747 resolve_reparse_point(char_u *fname)
1791 { 1748 {
1792 HANDLE h = INVALID_HANDLE_VALUE; 1749 HANDLE h = INVALID_HANDLE_VALUE;
1793 DWORD size; 1750 DWORD size;
1794 WCHAR *p; 1751 WCHAR *p, *wp;
1795 char_u *rfname = NULL; 1752 char_u *rfname = NULL;
1796 FILE_NAME_INFO_ *nameinfo = NULL; 1753 WCHAR *buff = NULL;
1797 WCHAR buff[MAX_PATH], *volnames = NULL;
1798 HANDLE hv;
1799 DWORD snfile, snfind;
1800 static BOOL loaded = FALSE; 1754 static BOOL loaded = FALSE;
1801 1755
1802 if (pGetFileInformationByHandleEx == NULL || 1756 if (pGetFinalPathNameByHandleW == NULL)
1803 pGetVolumeInformationByHandleW == NULL)
1804 { 1757 {
1805 HMODULE hmod = GetModuleHandle("kernel32.dll"); 1758 HMODULE hmod = GetModuleHandle("kernel32.dll");
1806 1759
1807 if (loaded == TRUE) 1760 if (loaded == TRUE)
1808 return NULL; 1761 return NULL;
1809 pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx) 1762 pGetFinalPathNameByHandleW = (pfnGetFinalPathNameByHandleW)
1810 GetProcAddress(hmod, "GetFileInformationByHandleEx"); 1763 GetProcAddress(hmod, "GetFinalPathNameByHandleW");
1811 pGetVolumeInformationByHandleW = (pfnGetVolumeInformationByHandleW)
1812 GetProcAddress(hmod, "GetVolumeInformationByHandleW");
1813 loaded = TRUE; 1764 loaded = TRUE;
1814 if (pGetFileInformationByHandleEx == NULL || 1765 if (pGetFinalPathNameByHandleW == NULL)
1815 pGetVolumeInformationByHandleW == NULL)
1816 return NULL; 1766 return NULL;
1817 } 1767 }
1818 1768
1819 p = enc_to_utf16(fname, NULL); 1769 p = enc_to_utf16(fname, NULL);
1820 if (p == NULL) 1770 if (p == NULL)
1831 vim_free(p); 1781 vim_free(p);
1832 1782
1833 if (h == INVALID_HANDLE_VALUE) 1783 if (h == INVALID_HANDLE_VALUE)
1834 goto fail; 1784 goto fail;
1835 1785
1836 size = sizeof(FILE_NAME_INFO_) + sizeof(WCHAR) * (MAX_PATH - 1); 1786 size = pGetFinalPathNameByHandleW(h, NULL, 0, 0);
1837 nameinfo = alloc(size + sizeof(WCHAR)); 1787 if (size == 0)
1838 if (nameinfo == NULL)
1839 goto fail; 1788 goto fail;
1840 1789 buff = ALLOC_MULT(WCHAR, size);
1841 if (!pGetFileInformationByHandleEx(h, FileNameInfo_, nameinfo, size)) 1790 if (buff == NULL)
1842 goto fail; 1791 goto fail;
1843 1792 if (pGetFinalPathNameByHandleW(h, buff, size, 0) == 0)
1844 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = 0;
1845
1846 if (!pGetVolumeInformationByHandleW(
1847 h, NULL, 0, &snfile, NULL, NULL, NULL, 0))
1848 goto fail; 1793 goto fail;
1849 1794
1850 hv = FindFirstVolumeW(buff, MAX_PATH); 1795 if (wcsncmp(buff, L"\\\\?\\UNC\\", 8) == 0)
1851 if (hv == INVALID_HANDLE_VALUE) 1796 {
1852 goto fail; 1797 buff[6] = L'\\';
1853 1798 wp = buff + 6;
1854 do { 1799 }
1855 GetVolumeInformationW( 1800 else if (wcsncmp(buff, L"\\\\?\\", 4) == 0)
1856 buff, NULL, 0, &snfind, NULL, NULL, NULL, 0); 1801 wp = buff + 4;
1857 if (snfind == snfile)
1858 break;
1859 } while (FindNextVolumeW(hv, buff, MAX_PATH));
1860
1861 FindVolumeClose(hv);
1862
1863 if (snfind != snfile)
1864 goto fail;
1865
1866 size = 0;
1867 if (!GetVolumePathNamesForVolumeNameW(buff, NULL, 0, &size) &&
1868 GetLastError() != ERROR_MORE_DATA)
1869 goto fail;
1870
1871 volnames = ALLOC_MULT(WCHAR, size);
1872 if (!GetVolumePathNamesForVolumeNameW(buff, volnames, size,
1873 &size))
1874 goto fail;
1875
1876 wcscpy(buff, volnames);
1877 if (nameinfo->FileName[0] == '\\')
1878 wcscat(buff, nameinfo->FileName + 1);
1879 else 1802 else
1880 wcscat(buff, nameinfo->FileName); 1803 wp = buff;
1881 rfname = utf16_to_enc(buff, NULL); 1804
1805 rfname = utf16_to_enc(wp, NULL);
1882 1806
1883 fail: 1807 fail:
1884 if (h != INVALID_HANDLE_VALUE) 1808 if (h != INVALID_HANDLE_VALUE)
1885 CloseHandle(h); 1809 CloseHandle(h);
1886 if (nameinfo != NULL) 1810 if (buff != NULL)
1887 vim_free(nameinfo); 1811 vim_free(buff);
1888 if (volnames != NULL)
1889 vim_free(volnames);
1890 1812
1891 return rfname; 1813 return rfname;
1892 } 1814 }
1893 1815
1894 /* 1816 /*