From: Eli Zaretskii Date: Thu, 6 Feb 2014 15:27:46 +0000 (+0200) Subject: Another fix for handling of file names on Windows 9X. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~146 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=829f4f2256d11c0336618269b45b2eea299ed2ce;p=emacs.git Another fix for handling of file names on Windows 9X. src/w32.c (pMultiByteToWideChar, pWideCharToMultiByte): New variables: pointers through which to call the respective APIs. (filename_to_utf16, filename_from_utf16, filename_to_ansi) (filename_from_ansi, sys_link, check_windows_init_file): Call MultiByteToWideChar and WideCharToMultiByte through pointers. This is required on Windows 9X, where we dynamically load UNICOWS.DLL which has their non-stub implementations. (maybe_load_unicows_dll): Assign addresses to these 2 function pointers after loading UNICOWS.DLL. src/w32fns.c (Fx_file_dialog, Fw32_shell_execute) [!CYGWIN]: Call MultiByteToWideChar and WideCharToMultiByte through function pointers. src/w32.h (pMultiByteToWideChar, pWideCharToMultiByte): New declarations. --- diff --git a/src/ChangeLog b/src/ChangeLog index 8a7dfae4864..e19b6d8781d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2014-02-06 Eli Zaretskii + + * w32.c (pMultiByteToWideChar, pWideCharToMultiByte): New + variables: pointers through which to call the respective APIs. + (filename_to_utf16, filename_from_utf16, filename_to_ansi) + (filename_from_ansi, sys_link, check_windows_init_file): Call + MultiByteToWideChar and WideCharToMultiByte through pointers. + This is required on Windows 9X, where we dynamically load + UNICOWS.DLL which has their non-stub implementations. + (maybe_load_unicows_dll): Assign addresses to these 2 function + pointers after loading UNICOWS.DLL. + + * w32fns.c (Fx_file_dialog, Fw32_shell_execute) [!CYGWIN]: Call + MultiByteToWideChar and WideCharToMultiByte through function + pointers. + + * w32.h (pMultiByteToWideChar, pWideCharToMultiByte): New + declarations. + 2014-02-06 Jan Djärv * nsterm.m (toggleFullScreen:): Hide menubar on secondary monitor diff --git a/src/w32.c b/src/w32.c index ebd1dff0b4d..11fb2a72f69 100644 --- a/src/w32.c +++ b/src/w32.c @@ -478,6 +478,9 @@ typedef DWORD (WINAPI *GetAdaptersInfo_Proc) ( PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen); +int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); +int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); + /* ** A utility function ** */ static BOOL is_windows_9x (void) @@ -1543,8 +1546,8 @@ codepage_for_filenames (CPINFO *cp_info) int filename_to_utf16 (const char *fn_in, wchar_t *fn_out) { - int result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1, - fn_out, MAX_PATH); + int result = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1, + fn_out, MAX_PATH); if (!result) { @@ -1570,8 +1573,8 @@ filename_to_utf16 (const char *fn_in, wchar_t *fn_out) int filename_from_utf16 (const wchar_t *fn_in, char *fn_out) { - int result = WideCharToMultiByte (CP_UTF8, 0, fn_in, -1, - fn_out, MAX_UTF8_PATH, NULL, NULL); + int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1, + fn_out, MAX_UTF8_PATH, NULL, NULL); if (!result) { @@ -1604,8 +1607,8 @@ filename_to_ansi (const char *fn_in, char *fn_out) int result; int codepage = codepage_for_filenames (NULL); - result = WideCharToMultiByte (codepage, 0, fn_utf16, -1, - fn_out, MAX_PATH, NULL, NULL); + result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1, + fn_out, MAX_PATH, NULL, NULL); if (!result) { DWORD err = GetLastError (); @@ -1634,8 +1637,8 @@ filename_from_ansi (const char *fn_in, char *fn_out) { wchar_t fn_utf16[MAX_PATH]; int codepage = codepage_for_filenames (NULL); - int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, - fn_utf16, MAX_PATH); + int result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, + fn_utf16, MAX_PATH); if (!result) { @@ -4033,8 +4036,8 @@ sys_link (const char * old, const char * new) /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN indicates that flag is unsupported for CP_UTF8, and OTOH says it is the default anyway. */ - wlen = MultiByteToWideChar (CP_UTF8, 0, newname, -1, - data.wid.cStreamName, MAX_PATH); + wlen = pMultiByteToWideChar (CP_UTF8, 0, newname, -1, + data.wid.cStreamName, MAX_PATH); if (wlen > 0) { LPVOID context = NULL; @@ -8749,22 +8752,22 @@ check_windows_init_file (void) "not unpacked properly.\nSee the README.W32 file in the " "top-level Emacs directory for more information.", init_file_name, load_path); - needed = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, - -1, NULL, 0); + needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, + -1, NULL, 0); if (needed > 0) { wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t)); - MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1, - msg_w, needed); - needed = WideCharToMultiByte (CP_ACP, 0, msg_w, -1, - NULL, 0, NULL, NULL); + pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1, + msg_w, needed); + needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, + NULL, 0, NULL, NULL); if (needed > 0) { char *msg_a = alloca (needed + 1); - WideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed, - NULL, NULL); + pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed, + NULL, NULL); msg = msg_a; } } @@ -8932,7 +8935,17 @@ maybe_load_unicows_dll (void) { HANDLE ret = LoadLibrary ("Unicows.dll"); if (ret) - return ret; + { + /* These two functions are present on Windows 9X as stubs + that always fail. We need the real implementations from + UNICOWS.DLL, so we must call these functions through + pointers, and assign the correct addresses to these + pointers at program startup (see emacs.c, which calls + this function early on). */ + pMultiByteToWideChar = GetProcAddress (ret, "MultiByteToWideChar"); + pWideCharToMultiByte = GetProcAddress (ret, "WideCharToMultiByte"); + return ret; + } else { int button; @@ -8954,7 +8967,14 @@ maybe_load_unicows_dll (void) } } else - return LoadLibrary ("Gdi32.dll"); + { + /* On NT family of Windows, these two functions are always + linked in, so we just assign their addresses to the 2 + pointers; no need for the LoadLibrary dance. */ + pMultiByteToWideChar = MultiByteToWideChar; + pWideCharToMultiByte = WideCharToMultiByte; + return LoadLibrary ("Gdi32.dll"); + } } /* diff --git a/src/w32.h b/src/w32.h index 0ca30c60125..33fd2709a71 100644 --- a/src/w32.h +++ b/src/w32.h @@ -175,6 +175,9 @@ extern int _sys_wait_accept (int fd); extern Lisp_Object QCloaded_from; extern HMODULE w32_delayed_load (Lisp_Object); +extern int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); +extern int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); + extern void init_environment (char **); extern void check_windows_init_file (void); extern void syms_of_ntproc (void); diff --git a/src/w32fns.c b/src/w32fns.c index 7aca7fde3ad..66f532c3721 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -6538,13 +6538,13 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0) report_file_error ("filename too long", default_filename); } - len = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, - SSDATA (prompt), -1, NULL, 0); + len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + SSDATA (prompt), -1, NULL, 0); if (len > 32768) len = 32768; prompt_w = alloca (len * sizeof (wchar_t)); - MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, - SSDATA (prompt), -1, prompt_w, len); + pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + SSDATA (prompt), -1, prompt_w, len); } else { @@ -6556,18 +6556,18 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */) if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0) report_file_error ("filename too long", default_filename); } - len = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, - SSDATA (prompt), -1, NULL, 0); + len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + SSDATA (prompt), -1, NULL, 0); if (len > 32768) len = 32768; prompt_w = alloca (len * sizeof (wchar_t)); - MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, - SSDATA (prompt), -1, prompt_w, len); - len = WideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL); + pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, + SSDATA (prompt), -1, prompt_w, len); + len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL); if (len > 32768) len = 32768; prompt_a = alloca (len); - WideCharToMultiByte (CP_ACP, 0, prompt_w, -1, prompt_a, len, NULL, NULL); + pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, prompt_a, len, NULL, NULL); } #endif /* NTGUI_UNICODE */ @@ -6974,13 +6974,13 @@ a ShowWindow flag: int len; parameters = ENCODE_SYSTEM (parameters); - len = MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, - SSDATA (parameters), -1, NULL, 0); + len = pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, + SSDATA (parameters), -1, NULL, 0); if (len > 32768) len = 32768; params_w = alloca (len * sizeof (wchar_t)); - MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, - SSDATA (parameters), -1, params_w, len); + pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, + SSDATA (parameters), -1, params_w, len); } if (STRINGP (operation)) {