summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2022-11-18 21:54:53 +0100
committerPali Rohár <pali@kernel.org>2022-11-18 21:54:53 +0100
commita7a7aaeaa9feca5377a0da891d2d444db20cdb7d (patch)
tree3a8ae65867433438ed0d8e1d07f49dc48dc11344
parent0382965825caa27deaac3ab6a25145c896b9053b (diff)
downloadpciutils-a7a7aaeaa9feca5377a0da891d2d444db20cdb7d.tar.gz
libpci: windows: Fix locating path to pci.ids file for DLL builds
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.
-rw-r--r--lib/init.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/lib/init.c b/lib/init.c
index 9cb64f3..590dfb4 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -14,7 +14,56 @@
#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);
}