summaryrefslogtreecommitdiff
path: root/lib/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/init.c')
-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);
}