Another fix for handling of file names on Windows 9X.
authorEli Zaretskii <eliz@gnu.org>
Thu, 6 Feb 2014 15:27:46 +0000 (17:27 +0200)
committerEli Zaretskii <eliz@gnu.org>
Thu, 6 Feb 2014 15:27:46 +0000 (17:27 +0200)
 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.

src/ChangeLog
src/w32.c
src/w32.h
src/w32fns.c

index 8a7dfae..e19b6d8 100644 (file)
@@ -1,3 +1,22 @@
+2014-02-06  Eli Zaretskii  <eliz@gnu.org>
+
+       * 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  <jan.h.d@swipnet.se>
 
        * nsterm.m (toggleFullScreen:): Hide menubar on secondary monitor
index ebd1dff..11fb2a7 100644 (file)
--- 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");
+    }
 }
 
 /*
index 0ca30c6..33fd270 100644 (file)
--- 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);
index 7aca7fd..66f532c 100644 (file)
@@ -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))
        {