comparison src/os_mswin.c @ 15774:c4efa095f323 v8.1.0894

patch 8.1.0894: MS-Windows: resolve() does not return a reparse point commit https://github.com/vim/vim/commit/dce1e89be4675bcdbc9785584d3da25295481e63 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 10 23:18:53 2019 +0100 patch 8.1.0894: MS-Windows: resolve() does not return a reparse point Problem: MS-Windows: resolve() does not return a reparse point. Solution: Improve resolve(). (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3896)
author Bram Moolenaar <Bram@vim.org>
date Sun, 10 Feb 2019 23:30:08 +0100
parents 639b8318472c
children 028c9fdb8469
comparison
equal deleted inserted replaced
15773:e3c2762bc354 15774:c4efa095f323
1821 #if defined(FEAT_SHORTCUT) || defined(PROTO) 1821 #if defined(FEAT_SHORTCUT) || defined(PROTO)
1822 # ifndef PROTO 1822 # ifndef PROTO
1823 # include <shlobj.h> 1823 # include <shlobj.h>
1824 # endif 1824 # endif
1825 1825
1826 typedef enum _FILE_INFO_BY_HANDLE_CLASS_ {
1827 FileBasicInfo_,
1828 FileStandardInfo_,
1829 FileNameInfo_,
1830 FileRenameInfo_,
1831 FileDispositionInfo_,
1832 FileAllocationInfo_,
1833 FileEndOfFileInfo_,
1834 FileStreamInfo_,
1835 FileCompressionInfo_,
1836 FileAttributeTagInfo_,
1837 FileIdBothDirectoryInfo_,
1838 FileIdBothDirectoryRestartInfo_,
1839 FileIoPriorityHintInfo_,
1840 FileRemoteProtocolInfo_,
1841 FileFullDirectoryInfo_,
1842 FileFullDirectoryRestartInfo_,
1843 FileStorageInfo_,
1844 FileAlignmentInfo_,
1845 FileIdInfo_,
1846 FileIdExtdDirectoryInfo_,
1847 FileIdExtdDirectoryRestartInfo_,
1848 FileDispositionInfoEx_,
1849 FileRenameInfoEx_,
1850 MaximumFileInfoByHandleClass_
1851 } FILE_INFO_BY_HANDLE_CLASS_;
1852
1853 typedef struct _FILE_NAME_INFO_ {
1854 DWORD FileNameLength;
1855 WCHAR FileName[1];
1856 } FILE_NAME_INFO_;
1857
1858 typedef BOOL (WINAPI *pfnGetFileInformationByHandleEx)(
1859 HANDLE hFile,
1860 FILE_INFO_BY_HANDLE_CLASS_ FileInformationClass,
1861 LPVOID lpFileInformation,
1862 DWORD dwBufferSize);
1863 static pfnGetFileInformationByHandleEx pGetFileInformationByHandleEx = NULL;
1864
1865 typedef BOOL (WINAPI *pfnGetVolumeInformationByHandleW)(
1866 HANDLE hFile,
1867 LPWSTR lpVolumeNameBuffer,
1868 DWORD nVolumeNameSize,
1869 LPDWORD lpVolumeSerialNumber,
1870 LPDWORD lpMaximumComponentLength,
1871 LPDWORD lpFileSystemFlags,
1872 LPWSTR lpFileSystemNameBuffer,
1873 DWORD nFileSystemNameSize);
1874 static pfnGetVolumeInformationByHandleW pGetVolumeInformationByHandleW = NULL;
1875
1876 char_u *
1877 resolve_reparse_point(char_u *fname)
1878 {
1879 HANDLE h = INVALID_HANDLE_VALUE;
1880 DWORD size;
1881 char_u *rfname = NULL;
1882 FILE_NAME_INFO_ *nameinfo = NULL;
1883 WCHAR buff[MAX_PATH], *volnames = NULL;
1884 HANDLE hv;
1885 DWORD snfile, snfind;
1886 static BOOL loaded = FALSE;
1887
1888 if (pGetFileInformationByHandleEx == NULL ||
1889 pGetVolumeInformationByHandleW == NULL)
1890 {
1891 HMODULE hmod = GetModuleHandle("kernel32.dll");
1892
1893 if (loaded == TRUE)
1894 return NULL;
1895 pGetFileInformationByHandleEx = (pfnGetFileInformationByHandleEx)
1896 GetProcAddress(hmod, "GetFileInformationByHandleEx");
1897 pGetVolumeInformationByHandleW = (pfnGetVolumeInformationByHandleW)
1898 GetProcAddress(hmod, "GetVolumeInformationByHandleW");
1899 loaded = TRUE;
1900 if (pGetFileInformationByHandleEx == NULL ||
1901 pGetVolumeInformationByHandleW == NULL)
1902 return NULL;
1903 }
1904
1905 if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
1906 {
1907 WCHAR *p;
1908
1909 p = enc_to_utf16(fname, NULL);
1910 if (p == NULL)
1911 goto fail;
1912
1913 if ((GetFileAttributesW(p) & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1914 {
1915 vim_free(p);
1916 goto fail;
1917 }
1918
1919 h = CreateFileW(p, 0, 0, NULL, OPEN_EXISTING,
1920 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1921 vim_free(p);
1922 }
1923 else
1924 {
1925 if ((GetFileAttributes((char*) fname) &
1926 FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1927 goto fail;
1928
1929 h = CreateFile((char*) fname, 0, 0, NULL, OPEN_EXISTING,
1930 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1931 }
1932
1933 if (h == INVALID_HANDLE_VALUE)
1934 goto fail;
1935
1936 size = sizeof(FILE_NAME_INFO_) + sizeof(WCHAR) * (MAX_PATH - 1);
1937 nameinfo = (FILE_NAME_INFO_*)alloc(size + sizeof(WCHAR));
1938 if (nameinfo == NULL)
1939 goto fail;
1940
1941 if (!pGetFileInformationByHandleEx(h, FileNameInfo_, nameinfo, size))
1942 goto fail;
1943
1944 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = 0;
1945
1946 if (!pGetVolumeInformationByHandleW(
1947 h, NULL, 0, &snfile, NULL, NULL, NULL, 0))
1948 goto fail;
1949
1950 hv = FindFirstVolumeW(buff, MAX_PATH);
1951 if (hv == INVALID_HANDLE_VALUE)
1952 goto fail;
1953
1954 do {
1955 GetVolumeInformationW(
1956 buff, NULL, 0, &snfind, NULL, NULL, NULL, 0);
1957 if (snfind == snfile)
1958 break;
1959 } while (FindNextVolumeW(hv, buff, MAX_PATH));
1960
1961 FindVolumeClose(hv);
1962
1963 if (snfind != snfile)
1964 goto fail;
1965
1966 size = 0;
1967 if (!GetVolumePathNamesForVolumeNameW(buff, NULL, 0, &size) &&
1968 GetLastError() != ERROR_MORE_DATA)
1969 goto fail;
1970
1971 volnames = (WCHAR*)alloc(size * sizeof(WCHAR));
1972 if (!GetVolumePathNamesForVolumeNameW(buff, volnames, size,
1973 &size))
1974 goto fail;
1975
1976 wcscpy(buff, volnames);
1977 if (nameinfo->FileName[0] == '\\')
1978 wcscat(buff, nameinfo->FileName + 1);
1979 else
1980 wcscat(buff, nameinfo->FileName);
1981 rfname = utf16_to_enc(buff, NULL);
1982
1983 fail:
1984 if (h != INVALID_HANDLE_VALUE)
1985 CloseHandle(h);
1986 if (nameinfo != NULL)
1987 vim_free(nameinfo);
1988 if (volnames != NULL)
1989 vim_free(volnames);
1990
1991 return rfname;
1992 }
1993
1826 /* 1994 /*
1827 * When "fname" is the name of a shortcut (*.lnk) resolve the file it points 1995 * When "fname" is the name of a shortcut (*.lnk) resolve the file it points
1828 * to and return that name in allocated memory. 1996 * to and return that name in allocated memory.
1829 * Otherwise NULL is returned. 1997 * Otherwise NULL is returned.
1830 */ 1998 */
1831 char_u * 1999 static char_u *
1832 mch_resolve_shortcut(char_u *fname) 2000 resolve_shortcut(char_u *fname)
1833 { 2001 {
1834 HRESULT hr; 2002 HRESULT hr;
1835 IShellLink *psl = NULL; 2003 IShellLink *psl = NULL;
1836 IPersistFile *ppf = NULL; 2004 IPersistFile *ppf = NULL;
1837 OLECHAR wsz[MAX_PATH]; 2005 OLECHAR wsz[MAX_PATH];
1934 if (pslw != NULL) 2102 if (pslw != NULL)
1935 pslw->lpVtbl->Release(pslw); 2103 pslw->lpVtbl->Release(pslw);
1936 2104
1937 CoUninitialize(); 2105 CoUninitialize();
1938 return rfname; 2106 return rfname;
2107 }
2108
2109 char_u *
2110 mch_resolve_path(char_u *fname, int reparse_point)
2111 {
2112 char_u *path = resolve_shortcut(fname);
2113
2114 if (path == NULL && reparse_point)
2115 path = resolve_reparse_point(fname);
2116 return path;
1939 } 2117 }
1940 #endif 2118 #endif
1941 2119
1942 #if (defined(FEAT_EVAL) && !defined(FEAT_GUI)) || defined(PROTO) 2120 #if (defined(FEAT_EVAL) && !defined(FEAT_GUI)) || defined(PROTO)
1943 /* 2121 /*