]> mj.ucw.cz Git - pciutils.git/commitdiff
libpci: windows: Fix locating path to pci.ids file for DLL builds
authorPali Rohár <pali@kernel.org>
Fri, 18 Nov 2022 20:54:53 +0000 (21:54 +0100)
committerPali Rohár <pali@kernel.org>
Fri, 18 Nov 2022 20:54:53 +0000 (21:54 +0100)
When using shared libpci DLL library, it is expected that pci.ids file is
stored in directory where is also libpci DLL library and not in directory
where is application executable.

Based on the build mode and compile options, choose the appropriate
function for retrieving path to the libpci DLL library or application
executable. Also pass correct module argument to GetModuleFileName() call.

lib/init.c

index 9cb64f378a8c0ae644d41399293151c3a33cd454..590dfb4227bc3140075f45630ac2ff0def46cad7 100644 (file)
 #include "internal.h"
 
 #ifdef PCI_OS_WINDOWS
+
 #include <windows.h>
+
+/* Force usage of ANSI (char*) variant of GetModuleFileName() function */
+#ifdef _WIN32
+#ifdef GetModuleFileName
+#undef GetModuleFileName
+#endif
+#define GetModuleFileName GetModuleFileNameA
+#endif
+
+/* Define __ImageBase for all linkers */
+#ifdef _WIN32
+/* GNU LD provides __ImageBase symbol since 2.19, in previous versions it is
+ * under name _image_base__, so add weak alias for compatibility. */
+#ifdef __GNUC__
+asm(".weak\t" PCI_STRINGIFY(__MINGW_USYMBOL(__ImageBase)) "\n\t"
+    ".set\t"  PCI_STRINGIFY(__MINGW_USYMBOL(__ImageBase)) "," PCI_STRINGIFY(__MINGW_USYMBOL(_image_base__)));
+#endif
+/*
+ * MSVC link.exe provides __ImageBase symbol since 12.00 (MSVC 6.0), for
+ * previous versions resolve it at runtime via GetModuleHandleA() which
+ * returns base for main executable or via VirtualQuery() for DLL builds.
+ */
+#if defined(_MSC_VER) && _MSC_VER < 1200
+static HMODULE
+get_current_module_handle(void)
+{
+#ifdef PCI_SHARED_LIB
+  MEMORY_BASIC_INFORMATION info;
+  size_t len = VirtualQuery(&get_current_module_handle, &info, sizeof(info));
+  if (len != sizeof(info))
+    return NULL;
+  return (HMODULE)info.AllocationBase;
+#else
+  return GetModuleHandleA(NULL);
+#endif
+}
+#define __ImageBase (*(IMAGE_DOS_HEADER *)get_current_module_handle())
+#else
+extern IMAGE_DOS_HEADER __ImageBase;
+#endif
+#endif
+
+#if defined(_WINDLL)
+extern HINSTANCE _hModule;
+#elif defined(_WINDOWS)
+extern HINSTANCE _hInstance;
+#endif
+
 #endif
 
 static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
@@ -224,8 +273,20 @@ pci_init_name_list_path(struct pci_access *a)
     {
       char *path, *sep;
       size_t len;
+
+#if defined(_WIN32) || defined(_WINDLL) || defined(_WINDOWS)
+
+      HMODULE module;
       size_t size;
 
+#if defined(_WIN32)
+      module = (HINSTANCE)&__ImageBase;
+#elif defined(_WINDLL)
+      module = _hModule;
+#elif defined(_WINDOWS)
+      module = _hInstance;
+#endif
+
       /*
        * Module file name can have arbitrary length despite all MS examples say
        * about MAX_PATH upper limit. This limit does not apply for example when
@@ -238,7 +299,7 @@ pci_init_name_list_path(struct pci_access *a)
       size = 256; /* initial buffer size (more than sizeof(PCI_IDS)) */
 retry:
       path = pci_malloc(a, size);
-      len = GetModuleFileNameA(module, path, size-sizeof(PCI_IDS));
+      len = GetModuleFileName(module, path, size-sizeof(PCI_IDS));
       if (len >= size-sizeof(PCI_IDS))
         {
           free(path);
@@ -248,9 +309,26 @@ retry:
       else if (len == 0)
         path[0] = '\0';
 
+#else
+
+      const char *exe_path;
+
+      exe_path = _pgmptr;
+
+      len = strlen(exe_path);
+      path = pci_malloc(a, len+sizeof(PCI_IDS));
+      memcpy(path, exe_path, len+1);
+
+#endif
+
       sep = strrchr(path, '\\');
       if (!sep)
         {
+          /*
+           * If current module path (current executable for static builds or
+           * current DLL library for shared build) cannot be determined then
+           * fallback to the current directory.
+           */
           free(path);
           pci_set_name_list_path(a, PCI_IDS, 0);
         }