diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-01-12 21:44:49 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-01-12 21:44:49 +0100 |
commit | 972c3b8f1b50e2f887a397c324af99eb354aad0b (patch) | |
tree | d830bec1d8553a493f1c24b09a84c99a45bf0c78 /src/os_win32.c | |
parent | b8f7bd68f6fdff51ca4db5b145dcde42ee7b804b (diff) | |
download | vim-git-972c3b8f1b50e2f887a397c324af99eb354aad0b.tar.gz |
patch 8.0.0175: setting language on MS-Windows does not always workv8.0.0175
Problem: Setting language in gvim on MS-Windows does not work when
libintl.dll is dynamically linked with msvcrt.dll.
Solution: Use putenv() from libintl as well. (Ken Takata, closes #1082)
Diffstat (limited to 'src/os_win32.c')
-rw-r--r-- | src/os_win32.c | 130 |
1 files changed, 113 insertions, 17 deletions
diff --git a/src/os_win32.c b/src/os_win32.c index e08adcbb1..9b86478d3 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -425,6 +425,84 @@ vimLoadLib(char *name) return dll; } +#if defined(DYNAMIC_ICONV) || defined(DYNAMIC_GETTEXT) || defined(PROTO) +/* + * Get related information about 'funcname' which is imported by 'hInst'. + * If 'info' is 0, return the function address. + * If 'info' is 1, return the module name which the function is imported from. + */ + static void * +get_imported_func_info(HINSTANCE hInst, const char *funcname, int info) +{ + PBYTE pImage = (PBYTE)hInst; + PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER)hInst; + PIMAGE_NT_HEADERS pPE; + PIMAGE_IMPORT_DESCRIPTOR pImpDesc; + PIMAGE_THUNK_DATA pIAT; /* Import Address Table */ + PIMAGE_THUNK_DATA pINT; /* Import Name Table */ + PIMAGE_IMPORT_BY_NAME pImpName; + + if (pDOS->e_magic != IMAGE_DOS_SIGNATURE) + return NULL; + pPE = (PIMAGE_NT_HEADERS)(pImage + pDOS->e_lfanew); + if (pPE->Signature != IMAGE_NT_SIGNATURE) + return NULL; + pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pImage + + pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + for (; pImpDesc->FirstThunk; ++pImpDesc) + { + if (!pImpDesc->OriginalFirstThunk) + continue; + pIAT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->FirstThunk); + pINT = (PIMAGE_THUNK_DATA)(pImage + pImpDesc->OriginalFirstThunk); + for (; pIAT->u1.Function; ++pIAT, ++pINT) + { + if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal)) + continue; + pImpName = (PIMAGE_IMPORT_BY_NAME)(pImage + + (UINT_PTR)(pINT->u1.AddressOfData)); + if (strcmp((char *)pImpName->Name, funcname) == 0) + { + switch (info) + { + case 0: + return (void *)pIAT->u1.Function; + case 1: + return (void *)(pImage + pImpDesc->Name); + default: + return NULL; + } + } + } + } + return NULL; +} + +/* + * Get the module handle which 'funcname' in 'hInst' is imported from. + */ + HINSTANCE +find_imported_module_by_funcname(HINSTANCE hInst, const char *funcname) +{ + char *modulename; + + modulename = (char *)get_imported_func_info(hInst, funcname, 1); + if (modulename != NULL) + return GetModuleHandleA(modulename); + return NULL; +} + +/* + * Get the address of 'funcname' which is imported by 'hInst' DLL. + */ + void * +get_dll_import_func(HINSTANCE hInst, const char *funcname) +{ + return get_imported_func_info(hInst, funcname, 0); +} +#endif + #if defined(DYNAMIC_GETTEXT) || defined(PROTO) # ifndef GETTEXT_DLL # define GETTEXT_DLL "libintl.dll" @@ -436,6 +514,7 @@ static char *null_libintl_ngettext(const char *, const char *, unsigned long n); static char *null_libintl_textdomain(const char *); static char *null_libintl_bindtextdomain(const char *, const char *); static char *null_libintl_bind_textdomain_codeset(const char *, const char *); +static int null_libintl_putenv(const char *); static HINSTANCE hLibintlDLL = NULL; char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext; @@ -446,6 +525,7 @@ char *(*dyn_libintl_bindtextdomain)(const char *, const char *) = null_libintl_bindtextdomain; char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *) = null_libintl_bind_textdomain_codeset; +int (*dyn_libintl_putenv)(const char *) = null_libintl_putenv; int dyn_libintl_init(void) @@ -463,6 +543,7 @@ dyn_libintl_init(void) {"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain}, {NULL, NULL} }; + HINSTANCE hmsvcrt; /* No need to initialize twice. */ if (hLibintlDLL) @@ -507,6 +588,13 @@ dyn_libintl_init(void) dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset; + /* _putenv() function for the libintl.dll is optional. */ + hmsvcrt = find_imported_module_by_funcname(hLibintlDLL, "getenv"); + if (hmsvcrt != NULL) + dyn_libintl_putenv = (void *)GetProcAddress(hmsvcrt, "_putenv"); + if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == putenv) + dyn_libintl_putenv = null_libintl_putenv; + return 1; } @@ -521,6 +609,7 @@ dyn_libintl_end(void) dyn_libintl_textdomain = null_libintl_textdomain; dyn_libintl_bindtextdomain = null_libintl_bindtextdomain; dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset; + dyn_libintl_putenv = null_libintl_putenv; } /*ARGSUSED*/ @@ -562,6 +651,13 @@ null_libintl_textdomain(const char *domainname) return NULL; } +/*ARGSUSED*/ + int +null_libintl_putenv(const char *envstring) +{ + return 0; +} + #endif /* DYNAMIC_GETTEXT */ /* This symbol is not defined in older versions of the SDK or Visual C++ */ @@ -4781,32 +4877,32 @@ mch_call_shell( #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) static HANDLE job_io_file_open( - char_u *fname, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes) + char_u *fname, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes) { HANDLE h; # ifdef FEAT_MBYTE WCHAR *wn = NULL; if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { - wn = enc_to_utf16(fname, NULL); - if (wn != NULL) - { - h = CreateFileW(wn, dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, - dwFlagsAndAttributes, NULL); - vim_free(wn); - } + wn = enc_to_utf16(fname, NULL); + if (wn != NULL) + { + h = CreateFileW(wn, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, NULL); + vim_free(wn); + } } if (wn == NULL) # endif - h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, - dwFlagsAndAttributes, NULL); + h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode, + lpSecurityAttributes, dwCreationDisposition, + dwFlagsAndAttributes, NULL); return h; } |