comparison src/os_mswin.c @ 5318:8e28c23e482c v7.4.012

updated for version 7.4.012 Problem: MS-Windows: resolving shortcut does not work properly with multi-byte characters. Solution: Use wide system functions. (Ken Takata)
author Bram Moolenaar <bram@vim.org>
date Fri, 30 Aug 2013 16:44:19 +0200
parents 1cf02fbe6281
children 07737d3aa817
comparison
equal deleted inserted replaced
5317:076f115ed30d 5318:8e28c23e482c
1759 HRESULT hr; 1759 HRESULT hr;
1760 IShellLink *psl = NULL; 1760 IShellLink *psl = NULL;
1761 IPersistFile *ppf = NULL; 1761 IPersistFile *ppf = NULL;
1762 OLECHAR wsz[MAX_PATH]; 1762 OLECHAR wsz[MAX_PATH];
1763 WIN32_FIND_DATA ffd; // we get those free of charge 1763 WIN32_FIND_DATA ffd; // we get those free of charge
1764 TCHAR buf[MAX_PATH]; // could have simply reused 'wsz'... 1764 CHAR buf[MAX_PATH]; // could have simply reused 'wsz'...
1765 char_u *rfname = NULL; 1765 char_u *rfname = NULL;
1766 int len; 1766 int len;
1767 # ifdef FEAT_MBYTE
1768 IShellLinkW *pslw = NULL;
1769 WIN32_FIND_DATAW ffdw; // we get those free of charge
1770 # endif
1767 1771
1768 /* Check if the file name ends in ".lnk". Avoid calling 1772 /* Check if the file name ends in ".lnk". Avoid calling
1769 * CoCreateInstance(), it's quite slow. */ 1773 * CoCreateInstance(), it's quite slow. */
1770 if (fname == NULL) 1774 if (fname == NULL)
1771 return rfname; 1775 return rfname;
1773 if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0) 1777 if (len <= 4 || STRNICMP(fname + len - 4, ".lnk", 4) != 0)
1774 return rfname; 1778 return rfname;
1775 1779
1776 CoInitialize(NULL); 1780 CoInitialize(NULL);
1777 1781
1782 # ifdef FEAT_MBYTE
1783 if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
1784 {
1785 // create a link manager object and request its interface
1786 hr = CoCreateInstance(
1787 &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1788 &IID_IShellLinkW, (void**)&pslw);
1789 if (hr == S_OK)
1790 {
1791 WCHAR *p = enc_to_utf16(fname, NULL);
1792
1793 if (p != NULL)
1794 {
1795 // Get a pointer to the IPersistFile interface.
1796 hr = pslw->lpVtbl->QueryInterface(
1797 pslw, &IID_IPersistFile, (void**)&ppf);
1798 if (hr != S_OK)
1799 goto shortcut_errorw;
1800
1801 // "load" the name and resolve the link
1802 hr = ppf->lpVtbl->Load(ppf, p, STGM_READ);
1803 if (hr != S_OK)
1804 goto shortcut_errorw;
1805 # if 0 // This makes Vim wait a long time if the target does not exist.
1806 hr = pslw->lpVtbl->Resolve(pslw, NULL, SLR_NO_UI);
1807 if (hr != S_OK)
1808 goto shortcut_errorw;
1809 # endif
1810
1811 // Get the path to the link target.
1812 ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR));
1813 hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0);
1814 if (hr == S_OK && wsz[0] != NUL)
1815 rfname = utf16_to_enc(wsz, NULL);
1816
1817 shortcut_errorw:
1818 vim_free(p);
1819 if (hr == S_OK)
1820 goto shortcut_end;
1821 }
1822 }
1823 /* Retry with non-wide function (for Windows 98). */
1824 }
1825 # endif
1778 // create a link manager object and request its interface 1826 // create a link manager object and request its interface
1779 hr = CoCreateInstance( 1827 hr = CoCreateInstance(
1780 &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 1828 &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1781 &IID_IShellLink, (void**)&psl); 1829 &IID_IShellLink, (void**)&psl);
1782 if (hr != S_OK) 1830 if (hr != S_OK)
1783 goto shortcut_error; 1831 goto shortcut_end;
1784 1832
1785 // Get a pointer to the IPersistFile interface. 1833 // Get a pointer to the IPersistFile interface.
1786 hr = psl->lpVtbl->QueryInterface( 1834 hr = psl->lpVtbl->QueryInterface(
1787 psl, &IID_IPersistFile, (void**)&ppf); 1835 psl, &IID_IPersistFile, (void**)&ppf);
1788 if (hr != S_OK) 1836 if (hr != S_OK)
1789 goto shortcut_error; 1837 goto shortcut_end;
1790 1838
1791 // full path string must be in Unicode. 1839 // full path string must be in Unicode.
1792 MultiByteToWideChar(CP_ACP, 0, fname, -1, wsz, MAX_PATH); 1840 MultiByteToWideChar(CP_ACP, 0, fname, -1, wsz, MAX_PATH);
1793 1841
1794 // "load" the name and resolve the link 1842 // "load" the name and resolve the link
1795 hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); 1843 hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
1796 if (hr != S_OK) 1844 if (hr != S_OK)
1797 goto shortcut_error; 1845 goto shortcut_end;
1798 #if 0 // This makes Vim wait a long time if the target doesn't exist. 1846 # if 0 // This makes Vim wait a long time if the target doesn't exist.
1799 hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); 1847 hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI);
1800 if (hr != S_OK) 1848 if (hr != S_OK)
1801 goto shortcut_error; 1849 goto shortcut_end;
1802 #endif 1850 # endif
1803 1851
1804 // Get the path to the link target. 1852 // Get the path to the link target.
1805 ZeroMemory(buf, MAX_PATH); 1853 ZeroMemory(buf, MAX_PATH);
1806 hr = psl->lpVtbl->GetPath(psl, buf, MAX_PATH, &ffd, 0); 1854 hr = psl->lpVtbl->GetPath(psl, buf, MAX_PATH, &ffd, 0);
1807 if (hr == S_OK && buf[0] != NUL) 1855 if (hr == S_OK && buf[0] != NUL)
1808 rfname = vim_strsave(buf); 1856 rfname = vim_strsave(buf);
1809 1857
1810 shortcut_error: 1858 shortcut_end:
1811 // Release all interface pointers (both belong to the same object) 1859 // Release all interface pointers (both belong to the same object)
1812 if (ppf != NULL) 1860 if (ppf != NULL)
1813 ppf->lpVtbl->Release(ppf); 1861 ppf->lpVtbl->Release(ppf);
1814 if (psl != NULL) 1862 if (psl != NULL)
1815 psl->lpVtbl->Release(psl); 1863 psl->lpVtbl->Release(psl);
1864 # ifdef FEAT_MBYTE
1865 if (pslw != NULL)
1866 pslw->lpVtbl->Release(pslw);
1867 # endif
1816 1868
1817 CoUninitialize(); 1869 CoUninitialize();
1818 return rfname; 1870 return rfname;
1819 } 1871 }
1820 #endif 1872 #endif