diff options
Diffstat (limited to 'lib/init.c')
-rw-r--r-- | lib/init.c | 80 |
1 files changed, 79 insertions, 1 deletions
@@ -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); } |