diff dynload/dynload_windows.c @ 308:7c6f19d42b31

dynload UTF-8 support for library paths: - added missing support to windows - added test code for all platforms to dynload_plain - doc update
author Tassilo Philipp
date Thu, 24 Oct 2019 23:19:20 +0200
parents f5577f6bf97a
children 2e8be88dad11
line wrap: on
line diff
--- a/dynload/dynload_windows.c	Mon Apr 29 11:51:30 2019 +0200
+++ b/dynload/dynload_windows.c	Thu Oct 24 23:19:20 2019 +0200
@@ -35,13 +35,37 @@
 
 
 #include "dynload.h"
+#include "dynload_alloc.h"
 
 #include <windows.h>
 
 
 DLLib* dlLoadLibrary(const char* libPath)
 {
-  return (DLLib*)(libPath != NULL ? LoadLibraryA(libPath) : GetModuleHandle(NULL));
+  if(libPath == NULL)
+    return (DLLib*)GetModuleHandle(NULL);
+  else {
+    /* convert from UTF-8 to wide chars, so count required size... */
+    DLLib* pLib;
+    wchar_t* ws;
+    int r = MultiByteToWideChar(CP_UTF8, 0, libPath, -1, NULL, 0);
+    if(!r) {
+      return NULL;
+    }
+
+    /* ... reserve temp space, ... */
+    ws = (wchar_t*)dlAllocMem(r * sizeof(wchar_t));
+    if(!ws)
+      return NULL;
+
+    /* ... convert (and use r as success flag), ... */
+    r = (MultiByteToWideChar(CP_UTF8, 0, libPath, -1, ws, r) == r);
+    pLib = (DLLib*)(r ? LoadLibraryW(ws) : NULL);/*@@@ testcode of unicode path*/
+
+    /* ... free temp space and return handle */
+    dlFreeMem(ws);
+    return pLib;
+  }
 }
 
 
@@ -59,6 +83,48 @@
 
 int dlGetLibraryPath(DLLib* pLib, char* sOut, int bufSize)
 {
-  return GetModuleFileNameA((HMODULE)pLib, sOut, bufSize)+1; /* strlen + '\0' */
+  /* get the path name as wide chars, then convert to UTF-8; we need   */
+  /* some trial and error to figure out needed wide char string length */
+
+  wchar_t* ws;
+  int r;
+
+  /* num chars to alloc temp space for, and upper limit, must be both power */
+  /* of 2s for loop to be precise and to test allow testing up to 32768 chars */
+  /* (including \0), which is the extended path ("\\?\...") maximum */
+  static const int MAX_EXT_PATH = 1<<15; /* max extended path length (32768) */
+  int nc = 1<<6;                         /* guess start buffer size, */
+
+  while(nc <= MAX_EXT_PATH)/*@@@ testcode*/
+  {
+    ws = (wchar_t*)dlAllocMem(nc * sizeof(wchar_t));
+    if(!ws)
+      break;
+
+    r = GetModuleFileNameW((HMODULE)pLib, ws, nc);
+
+    /* r == nc if string was truncated, double temp buffer size */
+    if(r == nc) {
+      nc <<= 1;/*@@@ testcode*/
+      dlFreeMem(ws);
+      continue;
+    }
+    /* error if r is 0 */
+    else if(!r) {
+      dlFreeMem(ws);
+      break;
+    }
+
+    /* check if output buffer is big enough */
+    r = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
+    if(r <= bufSize)
+      r = WideCharToMultiByte(CP_UTF8, 0, ws, -1, sOut, bufSize, NULL, NULL);
+
+    /* cleanup and return either size of copied bytes or needed buffer size */
+    dlFreeMem(ws);
+    return r;
+  }
+
+  return 0;
 }