Mercurial > vim
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 /* |