Blame src/file/dl_win32.c

Packit 5e46da
/*
Packit 5e46da
 * This file is part of libbluray
Packit 5e46da
 * Copyright (C) 2009-2010  Obliter0n
Packit 5e46da
 * Copyright (C) 2009-2010  John Stebbins
Packit 5e46da
 *
Packit 5e46da
 * This library is free software; you can redistribute it and/or
Packit 5e46da
 * modify it under the terms of the GNU Lesser General Public
Packit 5e46da
 * License as published by the Free Software Foundation; either
Packit 5e46da
 * version 2.1 of the License, or (at your option) any later version.
Packit 5e46da
 *
Packit 5e46da
 * This library is distributed in the hope that it will be useful,
Packit 5e46da
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e46da
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 5e46da
 * Lesser General Public License for more details.
Packit 5e46da
 *
Packit 5e46da
 * You should have received a copy of the GNU Lesser General Public
Packit 5e46da
 * License along with this library. If not, see
Packit 5e46da
 * <http://www.gnu.org/licenses/>.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
#if HAVE_CONFIG_H
Packit 5e46da
#include "config.h"
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#include "dl.h"
Packit 5e46da
#include "file.h"
Packit 5e46da
#include "util/macro.h"
Packit 5e46da
#include "util/logging.h"
Packit 5e46da
#include "util/strutl.h"
Packit 5e46da
Packit 5e46da
#include <windows.h>
Packit 5e46da
#include <stdio.h>
Packit 5e46da
#include <string.h>
Packit 5e46da
Packit 5e46da
static const char *dlerror(char *buf, int buf_size)
Packit 5e46da
{
Packit 5e46da
    DWORD error_code = GetLastError();
Packit 5e46da
    wchar_t wbuf[256];
Packit 5e46da
Packit 5e46da
    if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
Packit 5e46da
                        FORMAT_MESSAGE_MAX_WIDTH_MASK,
Packit 5e46da
                        NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
Packit 5e46da
                        wbuf, sizeof(wbuf)/sizeof(wbuf[0]), NULL) ||
Packit 5e46da
        !WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, buf_size, NULL, NULL)) {
Packit 5e46da
Packit 5e46da
#ifdef _MSC_VER
Packit 5e46da
        _snprintf(buf, buf_size, "error %d", (int)error_code);
Packit 5e46da
#else
Packit 5e46da
        snprintf(buf, buf_size, "error %d", (int)error_code);
Packit 5e46da
#endif
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return buf;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void *dl_dlopen(const char *path, const char *version)
Packit 5e46da
{
Packit 5e46da
    (void)version;
Packit 5e46da
Packit 5e46da
    wchar_t wname[MAX_PATH];
Packit 5e46da
    char *name;
Packit 5e46da
    void *result;
Packit 5e46da
    int iresult;
Packit 5e46da
    DWORD flags = 0;
Packit 5e46da
Packit 5e46da
    name = str_printf("%s.dll", path);
Packit 5e46da
    if (!name) {
Packit 5e46da
        BD_DEBUG(DBG_FILE | DBG_CRIT, "out of memory\n");
Packit 5e46da
        return NULL;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    iresult = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, MAX_PATH);
Packit 5e46da
    X_FREE(name);
Packit 5e46da
Packit 5e46da
    if (!iresult) {
Packit 5e46da
        BD_DEBUG(DBG_FILE, "can't convert file name '%s'\n", path);
Packit 5e46da
        return NULL;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
#if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
Packit 5e46da
    if (GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
Packit 5e46da
                       "SetDefaultDllDirectories") != NULL)
Packit 5e46da
#endif
Packit 5e46da
        flags = LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
Packit 5e46da
                LOAD_LIBRARY_SEARCH_SYSTEM32;
Packit 5e46da
Packit 5e46da
    result = LoadLibraryExW(wname, NULL, flags);
Packit 5e46da
Packit 5e46da
    if (!result) {
Packit 5e46da
        char buf[128];
Packit 5e46da
        BD_DEBUG(DBG_FILE, "can't open library '%s': %s\n", path, dlerror(buf, sizeof(buf)));
Packit 5e46da
    } else {
Packit 5e46da
        BD_DEBUG(DBG_FILE, "opened library '%s'\n", path);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return result;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
void *dl_dlsym(void *handle, const char *symbol)
Packit 5e46da
{
Packit 5e46da
    void *result = (void *)GetProcAddress((HMODULE)handle, symbol);
Packit 5e46da
Packit 5e46da
    if (!result) {
Packit 5e46da
        char buf[128];
Packit 5e46da
        BD_DEBUG(DBG_FILE, "GetProcAddress(%p, '%s') failed: %s\n", handle, symbol, dlerror(buf, sizeof(buf)));
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return result;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
int dl_dlclose(void *handle)
Packit 5e46da
{
Packit 5e46da
    FreeLibrary((HMODULE)handle);
Packit 5e46da
    return 0;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
// path-separator
Packit 5e46da
#define PATH_SEPARATOR '\\'
Packit 5e46da
Packit 5e46da
const char *dl_get_path(void)
Packit 5e46da
{
Packit 5e46da
    static char *lib_path    = NULL;
Packit 5e46da
    static int   initialized = 0;
Packit 5e46da
Packit 5e46da
    if (!initialized) {
Packit 5e46da
        initialized = 1;
Packit 5e46da
Packit 5e46da
        static char path[MAX_PATH];
Packit 5e46da
        HMODULE hModule;
Packit 5e46da
        wchar_t wpath[MAX_PATH];
Packit 5e46da
Packit 5e46da
        if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
Packit 5e46da
                              GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
Packit 5e46da
                              (LPCTSTR)&dl_get_path, &hModule)) {
Packit 5e46da
Packit 5e46da
            DWORD dw = GetModuleFileNameW(hModule, wpath, MAX_PATH);
Packit 5e46da
            if (dw > 0 && dw < MAX_PATH) {
Packit 5e46da
Packit 5e46da
                if (WideCharToMultiByte(CP_UTF8, 0, wpath, -1, path, MAX_PATH, NULL, NULL)) {
Packit 5e46da
Packit 5e46da
                    lib_path = path;
Packit 5e46da
                }
Packit 5e46da
            }
Packit 5e46da
        }
Packit 5e46da
Packit 5e46da
        if (lib_path) {
Packit 5e46da
            /* cut library name from path */
Packit 5e46da
            char *p = strrchr(lib_path, PATH_SEPARATOR);
Packit 5e46da
            if (p) {
Packit 5e46da
                *(p+1) = 0;
Packit 5e46da
            }
Packit 5e46da
            BD_DEBUG(DBG_FILE, "library file is %s\n", lib_path);
Packit 5e46da
        } else {
Packit 5e46da
            BD_DEBUG(DBG_FILE | DBG_CRIT, "Can't determine libbluray.dll install path\n");
Packit 5e46da
        }
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return lib_path;
Packit 5e46da
}