/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: nil -*- */ /* dllmain.c: DLL entry point for libmate on Win32 * Copyright (C) 2005 Novell, Inc * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include "mate-init.h" /* localedir uses system codepage as it is passed to the non-UTF8ified * gettext library */ static const char* localedir = NULL; /* The others are in UTF-8 */ static char* prefix; static const char* libdir; static const char* datadir; static const char* localstatedir; static const char* sysconfdir; static HMODULE hmodule; G_LOCK_DEFINE_STATIC(mutex); /* Silence gcc with prototype. Yes, this is silly. */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); /* DllMain used to tuck away the libmate DLL's HMODULE */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: hmodule = hinstDLL; break; } return TRUE; } static char* replace_prefix(const char* runtime_prefix, const char* configure_time_path) { if (runtime_prefix && strncmp(configure_time_path, LIBMATE_PREFIX "/", strlen (LIBMATE_PREFIX) + 1) == 0) { return g_strconcat(runtime_prefix, configure_time_path + strlen (LIBMATE_PREFIX), NULL); } else { return g_strdup (configure_time_path); } } /** * mate_win32_get_prefixes: * @hmodule: The handle to a DLL (a HMODULE). * @full_prefix: Where the full UTF-8 path to the DLL's installation folder * will be returned. * @cp_prefix: Where a system codepage version of * the installation folder will be returned. * * This function looks up the installation prefix of the DLL (or EXE) * with handle @hmodule. The prefix using long filenames and in UTF-8 * form is returned in @full_prefix. The prefix using short file names * (if present in the file system) and in the system codepage is * returned in @cp_prefix. To determine the installation prefix, the * full path to the DLL or EXE is first fetched. If the last folder * component in that path is called "bin", its parent folder is used, * otherwise the folder itself. * * If either can't be obtained, %NULL is stored. The caller should be * prepared to handle that. * * The returned character pointers are newly allocated and should be * freed with g_free when not longer needed. */ void mate_win32_get_prefixes(gpointer hmodule, char** full_prefix, char** cp_prefix) { wchar_t wcbfr[1000]; char cpbfr[1000]; g_return_if_fail(full_prefix != NULL); g_return_if_fail(cp_prefix != NULL); *full_prefix = NULL; *cp_prefix = NULL; if (GetModuleFileNameW((HMODULE) hmodule, wcbfr, G_N_ELEMENTS(wcbfr))) { *full_prefix = g_utf16_to_utf8(wcbfr, -1, NULL, NULL, NULL); /* WideCharToMultiByte * Short pathnames always contain only * ASCII, I think, but just in case, be * prepared. */ if (GetShortPathNameW(wcbfr, wcbfr, G_N_ELEMENTS(wcbfr)) && WideCharToMultiByte(CP_ACP, 0, wcbfr, -1, cpbfr, G_N_ELEMENTS(cpbfr), NULL, NULL)) { *cp_prefix = g_strdup(cpbfr); } else if (*full_prefix) { *cp_prefix = g_locale_from_utf8(*full_prefix, -1, NULL, NULL, NULL); } } if (*full_prefix != NULL) { gchar* p = strrchr(*full_prefix, '\\'); if (p != NULL) *p = '\0'; p = strrchr(*full_prefix, '\\'); if (p && (g_ascii_strcasecmp(p + 1, "bin") == 0)) *p = '\0'; } /* cp_prefix is in system codepage */ if (*cp_prefix != NULL) { gchar* p = _mbsrchr(*cp_prefix, '\\'); if (p != NULL) *p = '\0'; p = _mbsrchr (*cp_prefix, '\\'); if (p && (g_ascii_strcasecmp(p + 1, "bin") == 0)) *p = '\0'; } } static void setup(void) { char* cp_prefix; G_LOCK(mutex); if (localedir != NULL) { G_UNLOCK(mutex); return; } mate_win32_get_prefixes(hmodule, &prefix, &cp_prefix); localedir = replace_prefix(cp_prefix, LIBMATE_LOCALEDIR); g_free(cp_prefix); libdir = replace_prefix(prefix, LIBMATE_LIBDIR); datadir = replace_prefix(prefix, LIBMATE_DATADIR); localstatedir = replace_prefix(prefix, LIBMATE_LOCALSTATEDIR); sysconfdir = replace_prefix(prefix, LIBMATE_SYSCONFDIR); G_UNLOCK(mutex); } /* Include libmate-private.h now to get prototypes for the getter * functions, to silence gcc. Can't include earlier as we need the * definitions of the LIBMATE_*DIR macros from the Makefile above. */ #include "libmate-private.h" #define GETTER(varbl) \ const char* _mate_get_##varbl(void) \ { \ setup(); \ return varbl; \ } GETTER(prefix) GETTER(localedir) GETTER(libdir) GETTER(datadir) GETTER(localstatedir) GETTER(sysconfdir)