| To: vim_dev@googlegroups.com |
| Subject: Patch 7.4.012 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.4.012 |
| Problem: MS-Windows: resolving shortcut does not work properly with |
| multi-byte characters. |
| Solution: Use wide system functions. (Ken Takata) |
| Files: src/os_mswin.c |
| |
| |
| |
| |
| |
| *** 1761,1769 **** |
| IPersistFile *ppf = NULL; |
| OLECHAR wsz[MAX_PATH]; |
| WIN32_FIND_DATA ffd; // we get those free of charge |
| ! TCHAR buf[MAX_PATH]; // could have simply reused 'wsz'... |
| char_u *rfname = NULL; |
| int len; |
| |
| /* Check if the file name ends in ".lnk". Avoid calling |
| * CoCreateInstance(), it's quite slow. */ |
| --- 1761,1773 ---- |
| IPersistFile *ppf = NULL; |
| OLECHAR wsz[MAX_PATH]; |
| WIN32_FIND_DATA ffd; // we get those free of charge |
| ! CHAR buf[MAX_PATH]; // could have simply reused 'wsz'... |
| char_u *rfname = NULL; |
| int len; |
| + # ifdef FEAT_MBYTE |
| + IShellLinkW *pslw = NULL; |
| + WIN32_FIND_DATAW ffdw; // we get those free of charge |
| + # endif |
| |
| /* Check if the file name ends in ".lnk". Avoid calling |
| * CoCreateInstance(), it's quite slow. */ |
| |
| *** 1775,1792 **** |
| |
| CoInitialize(NULL); |
| |
| // create a link manager object and request its interface |
| hr = CoCreateInstance( |
| &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
| &IID_IShellLink, (void**)&psl); |
| if (hr != S_OK) |
| ! goto shortcut_error; |
| |
| // Get a pointer to the IPersistFile interface. |
| hr = psl->lpVtbl->QueryInterface( |
| psl, &IID_IPersistFile, (void**)&ppf); |
| if (hr != S_OK) |
| ! goto shortcut_error; |
| |
| // full path string must be in Unicode. |
| MultiByteToWideChar(CP_ACP, 0, fname, -1, wsz, MAX_PATH); |
| --- 1779,1840 ---- |
| |
| CoInitialize(NULL); |
| |
| + # ifdef FEAT_MBYTE |
| + if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) |
| + { |
| + // create a link manager object and request its interface |
| + hr = CoCreateInstance( |
| + &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
| + &IID_IShellLinkW, (void**)&pslw); |
| + if (hr == S_OK) |
| + { |
| + WCHAR *p = enc_to_utf16(fname, NULL); |
| + |
| + if (p != NULL) |
| + { |
| + // Get a pointer to the IPersistFile interface. |
| + hr = pslw->lpVtbl->QueryInterface( |
| + pslw, &IID_IPersistFile, (void**)&ppf); |
| + if (hr != S_OK) |
| + goto shortcut_errorw; |
| + |
| + // "load" the name and resolve the link |
| + hr = ppf->lpVtbl->Load(ppf, p, STGM_READ); |
| + if (hr != S_OK) |
| + goto shortcut_errorw; |
| + # if 0 // This makes Vim wait a long time if the target does not exist. |
| + hr = pslw->lpVtbl->Resolve(pslw, NULL, SLR_NO_UI); |
| + if (hr != S_OK) |
| + goto shortcut_errorw; |
| + # endif |
| + |
| + // Get the path to the link target. |
| + ZeroMemory(wsz, MAX_PATH * sizeof(WCHAR)); |
| + hr = pslw->lpVtbl->GetPath(pslw, wsz, MAX_PATH, &ffdw, 0); |
| + if (hr == S_OK && wsz[0] != NUL) |
| + rfname = utf16_to_enc(wsz, NULL); |
| + |
| + shortcut_errorw: |
| + vim_free(p); |
| + if (hr == S_OK) |
| + goto shortcut_end; |
| + } |
| + } |
| + /* Retry with non-wide function (for Windows 98). */ |
| + } |
| + # endif |
| // create a link manager object and request its interface |
| hr = CoCreateInstance( |
| &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, |
| &IID_IShellLink, (void**)&psl); |
| if (hr != S_OK) |
| ! goto shortcut_end; |
| |
| // Get a pointer to the IPersistFile interface. |
| hr = psl->lpVtbl->QueryInterface( |
| psl, &IID_IPersistFile, (void**)&ppf); |
| if (hr != S_OK) |
| ! goto shortcut_end; |
| |
| // full path string must be in Unicode. |
| MultiByteToWideChar(CP_ACP, 0, fname, -1, wsz, MAX_PATH); |
| |
| *** 1794,1805 **** |
| // "load" the name and resolve the link |
| hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); |
| if (hr != S_OK) |
| ! goto shortcut_error; |
| ! #if 0 // This makes Vim wait a long time if the target doesn't exist. |
| hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); |
| if (hr != S_OK) |
| ! goto shortcut_error; |
| ! #endif |
| |
| // Get the path to the link target. |
| ZeroMemory(buf, MAX_PATH); |
| --- 1842,1853 ---- |
| // "load" the name and resolve the link |
| hr = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); |
| if (hr != S_OK) |
| ! goto shortcut_end; |
| ! # if 0 // This makes Vim wait a long time if the target doesn't exist. |
| hr = psl->lpVtbl->Resolve(psl, NULL, SLR_NO_UI); |
| if (hr != S_OK) |
| ! goto shortcut_end; |
| ! # endif |
| |
| // Get the path to the link target. |
| ZeroMemory(buf, MAX_PATH); |
| |
| *** 1807,1818 **** |
| if (hr == S_OK && buf[0] != NUL) |
| rfname = vim_strsave(buf); |
| |
| ! shortcut_error: |
| // Release all interface pointers (both belong to the same object) |
| if (ppf != NULL) |
| ppf->lpVtbl->Release(ppf); |
| if (psl != NULL) |
| psl->lpVtbl->Release(psl); |
| |
| CoUninitialize(); |
| return rfname; |
| --- 1855,1870 ---- |
| if (hr == S_OK && buf[0] != NUL) |
| rfname = vim_strsave(buf); |
| |
| ! shortcut_end: |
| // Release all interface pointers (both belong to the same object) |
| if (ppf != NULL) |
| ppf->lpVtbl->Release(ppf); |
| if (psl != NULL) |
| psl->lpVtbl->Release(psl); |
| + # ifdef FEAT_MBYTE |
| + if (pslw != NULL) |
| + pslw->lpVtbl->Release(pslw); |
| + # endif |
| |
| CoUninitialize(); |
| return rfname; |
| |
| |
| |
| *** 740,741 **** |
| --- 740,743 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 12, |
| /**/ |
| |
| -- |
| hundred-and-one symptoms of being an internet addict: |
| 142. You dream about creating the world's greatest web site. |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ an exciting new programming language -- http://www.Zimbu.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |