mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 14:42:10 +01:00
Improve g_get_system_data_dirs() on Windows. A library that calls
2005-04-08 Tor Lillqvist <tml@novell.com> Improve g_get_system_data_dirs() on Windows. A library that calls g_get_system_data_dirs() might be installed in a different top-level prefix than GLib or the application being run. * glib/gutils.h (g_win32_get_system_data_dirs): New static function defined in this header. Calls g_win32_get_system_data_dirs_for_module() passing the address of itself as parameter. g_get_system_data_dirs() is #defined as this function. * glib/gutils.c (g_win32_get_system_data_dirs_for_module): New function. If the address parameter is non-NULL, the corresponding module's installation location is used for one of the returned path names, in addition to the COMMON_APPDATA, COMMON_DOCUMENTS, glib top-level and application top-level folders. (g_get_system_data_dirs): Now just for backward compatibility on Win32. Just call g_win32_get_system_data_dirs_for_module(NULL). * glib/glib.symbols: Add g_win32_get_system_data_dirs_for_module.
This commit is contained in:
parent
30942cba28
commit
5a88294fc3
20
ChangeLog
20
ChangeLog
@ -1,5 +1,25 @@
|
||||
2005-04-08 Tor Lillqvist <tml@novell.com>
|
||||
|
||||
Improve g_get_system_data_dirs() on Windows. A library that calls
|
||||
g_get_system_data_dirs() might be installed in a different
|
||||
top-level prefix than GLib or the application being run.
|
||||
|
||||
* glib/gutils.h (g_win32_get_system_data_dirs): New static
|
||||
function defined in this header. Calls
|
||||
g_win32_get_system_data_dirs_for_module() passing the address of
|
||||
itself as parameter. g_get_system_data_dirs() is #defined as this
|
||||
function.
|
||||
|
||||
* glib/gutils.c (g_win32_get_system_data_dirs_for_module): New
|
||||
function. If the address parameter is non-NULL, the corresponding
|
||||
module's installation location is used for one of the returned
|
||||
path names, in addition to the COMMON_APPDATA, COMMON_DOCUMENTS,
|
||||
glib top-level and application top-level folders.
|
||||
(g_get_system_data_dirs): Now just for backward compatibility on
|
||||
Win32. Just call g_win32_get_system_data_dirs_for_module(NULL).
|
||||
|
||||
* glib/glib.symbols: Add g_win32_get_system_data_dirs_for_module.
|
||||
|
||||
* glib/gutils.c (read_aliases): Not used on Windows.
|
||||
(unalias_lang): Don't do anything on Windows, there is no
|
||||
/usr/share/locale/locale.alias file..
|
||||
|
@ -1,5 +1,25 @@
|
||||
2005-04-08 Tor Lillqvist <tml@novell.com>
|
||||
|
||||
Improve g_get_system_data_dirs() on Windows. A library that calls
|
||||
g_get_system_data_dirs() might be installed in a different
|
||||
top-level prefix than GLib or the application being run.
|
||||
|
||||
* glib/gutils.h (g_win32_get_system_data_dirs): New static
|
||||
function defined in this header. Calls
|
||||
g_win32_get_system_data_dirs_for_module() passing the address of
|
||||
itself as parameter. g_get_system_data_dirs() is #defined as this
|
||||
function.
|
||||
|
||||
* glib/gutils.c (g_win32_get_system_data_dirs_for_module): New
|
||||
function. If the address parameter is non-NULL, the corresponding
|
||||
module's installation location is used for one of the returned
|
||||
path names, in addition to the COMMON_APPDATA, COMMON_DOCUMENTS,
|
||||
glib top-level and application top-level folders.
|
||||
(g_get_system_data_dirs): Now just for backward compatibility on
|
||||
Win32. Just call g_win32_get_system_data_dirs_for_module(NULL).
|
||||
|
||||
* glib/glib.symbols: Add g_win32_get_system_data_dirs_for_module.
|
||||
|
||||
* glib/gutils.c (read_aliases): Not used on Windows.
|
||||
(unalias_lang): Don't do anything on Windows, there is no
|
||||
/usr/share/locale/locale.alias file..
|
||||
|
@ -1,5 +1,25 @@
|
||||
2005-04-08 Tor Lillqvist <tml@novell.com>
|
||||
|
||||
Improve g_get_system_data_dirs() on Windows. A library that calls
|
||||
g_get_system_data_dirs() might be installed in a different
|
||||
top-level prefix than GLib or the application being run.
|
||||
|
||||
* glib/gutils.h (g_win32_get_system_data_dirs): New static
|
||||
function defined in this header. Calls
|
||||
g_win32_get_system_data_dirs_for_module() passing the address of
|
||||
itself as parameter. g_get_system_data_dirs() is #defined as this
|
||||
function.
|
||||
|
||||
* glib/gutils.c (g_win32_get_system_data_dirs_for_module): New
|
||||
function. If the address parameter is non-NULL, the corresponding
|
||||
module's installation location is used for one of the returned
|
||||
path names, in addition to the COMMON_APPDATA, COMMON_DOCUMENTS,
|
||||
glib top-level and application top-level folders.
|
||||
(g_get_system_data_dirs): Now just for backward compatibility on
|
||||
Win32. Just call g_win32_get_system_data_dirs_for_module(NULL).
|
||||
|
||||
* glib/glib.symbols: Add g_win32_get_system_data_dirs_for_module.
|
||||
|
||||
* glib/gutils.c (read_aliases): Not used on Windows.
|
||||
(unalias_lang): Don't do anything on Windows, there is no
|
||||
/usr/share/locale/locale.alias file..
|
||||
|
@ -1,5 +1,25 @@
|
||||
2005-04-08 Tor Lillqvist <tml@novell.com>
|
||||
|
||||
Improve g_get_system_data_dirs() on Windows. A library that calls
|
||||
g_get_system_data_dirs() might be installed in a different
|
||||
top-level prefix than GLib or the application being run.
|
||||
|
||||
* glib/gutils.h (g_win32_get_system_data_dirs): New static
|
||||
function defined in this header. Calls
|
||||
g_win32_get_system_data_dirs_for_module() passing the address of
|
||||
itself as parameter. g_get_system_data_dirs() is #defined as this
|
||||
function.
|
||||
|
||||
* glib/gutils.c (g_win32_get_system_data_dirs_for_module): New
|
||||
function. If the address parameter is non-NULL, the corresponding
|
||||
module's installation location is used for one of the returned
|
||||
path names, in addition to the COMMON_APPDATA, COMMON_DOCUMENTS,
|
||||
glib top-level and application top-level folders.
|
||||
(g_get_system_data_dirs): Now just for backward compatibility on
|
||||
Win32. Just call g_win32_get_system_data_dirs_for_module(NULL).
|
||||
|
||||
* glib/glib.symbols: Add g_win32_get_system_data_dirs_for_module.
|
||||
|
||||
* glib/gutils.c (read_aliases): Not used on Windows.
|
||||
(unalias_lang): Don't do anything on Windows, there is no
|
||||
/usr/share/locale/locale.alias file..
|
||||
|
@ -1174,6 +1174,9 @@ g_get_real_name_utf8
|
||||
#endif
|
||||
g_get_system_config_dirs
|
||||
g_get_system_data_dirs
|
||||
#ifdef G_OS_WIN32
|
||||
g_win32_get_system_data_dirs_for_module
|
||||
#endif
|
||||
g_get_tmp_dir PRIVATE
|
||||
#ifdef G_OS_WIN32
|
||||
g_get_tmp_dir_utf8
|
||||
|
262
glib/gutils.c
262
glib/gutils.c
@ -70,6 +70,10 @@
|
||||
# define STRICT /* Strict typing, please */
|
||||
# include <windows.h>
|
||||
# undef STRICT
|
||||
# ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
||||
# define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
|
||||
# define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
|
||||
# endif
|
||||
# include <lmcons.h> /* For UNLEN */
|
||||
#endif /* G_PLATFORM_WIN32 */
|
||||
|
||||
@ -2043,6 +2047,174 @@ g_get_user_cache_dir (void)
|
||||
return cache_dir;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
#undef g_get_system_data_dirs
|
||||
|
||||
static HMODULE
|
||||
get_module_for_address (gconstpointer address)
|
||||
{
|
||||
/* Holds the g_utils_global lock */
|
||||
|
||||
static gboolean beenhere = FALSE;
|
||||
typedef BOOL (WINAPI *t_GetModuleHandleExA) (DWORD, LPCTSTR, HMODULE *);
|
||||
static t_GetModuleHandleExA p_GetModuleHandleExA = NULL;
|
||||
HMODULE hmodule;
|
||||
|
||||
if (!address)
|
||||
return NULL;
|
||||
|
||||
if (!beenhere)
|
||||
{
|
||||
p_GetModuleHandleExA =
|
||||
(t_GetModuleHandleExA) GetProcAddress (LoadLibrary ("kernel32.dll"),
|
||||
"GetModuleHandleExA");
|
||||
beenhere = TRUE;
|
||||
}
|
||||
|
||||
if (p_GetModuleHandleExA == NULL ||
|
||||
!(*p_GetModuleHandleExA) (GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
address, &hmodule))
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
VirtualQuery (address, &mbi, sizeof (mbi));
|
||||
hmodule = (HMODULE) mbi.AllocationBase;
|
||||
}
|
||||
|
||||
return hmodule;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_module_share_dir (gconstpointer address)
|
||||
{
|
||||
HMODULE hmodule;
|
||||
gchar *filename = NULL;
|
||||
gchar *p, *retval;
|
||||
|
||||
hmodule = get_module_for_address (address);
|
||||
if (hmodule == NULL)
|
||||
return NULL;
|
||||
|
||||
if (G_WIN32_IS_NT_BASED ())
|
||||
{
|
||||
wchar_t wfilename[MAX_PATH];
|
||||
if (GetModuleFileNameW (hmodule, wfilename, G_N_ELEMENTS (wfilename)))
|
||||
filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
char cpfilename[MAX_PATH];
|
||||
if (GetModuleFileNameA (hmodule, cpfilename, G_N_ELEMENTS (cpfilename)))
|
||||
filename = g_locale_to_utf8 (cpfilename, -1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((p = strrchr (filename, G_DIR_SEPARATOR)) != NULL)
|
||||
*p = '\0';
|
||||
|
||||
p = strrchr (filename, G_DIR_SEPARATOR);
|
||||
if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0))
|
||||
*p = '\0';
|
||||
|
||||
retval = g_build_filename (filename, "share", NULL);
|
||||
g_free (filename);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
G_CONST_RETURN gchar * G_CONST_RETURN *
|
||||
g_win32_get_system_data_dirs_for_module (gconstpointer address)
|
||||
{
|
||||
GArray *data_dirs;
|
||||
HMODULE hmodule;
|
||||
static GHashTable *per_module_data_dirs = NULL;
|
||||
gchar **retval;
|
||||
gchar *p;
|
||||
|
||||
if (address)
|
||||
{
|
||||
G_LOCK (g_utils_global);
|
||||
hmodule = get_module_for_address (address);
|
||||
if (hmodule != NULL)
|
||||
{
|
||||
if (per_module_data_dirs == NULL)
|
||||
per_module_data_dirs = g_hash_table_new (NULL, NULL);
|
||||
else
|
||||
{
|
||||
retval = g_hash_table_lookup (per_module_data_dirs, hmodule);
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
G_UNLOCK (g_utils_global);
|
||||
return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_dirs = g_array_new (TRUE, TRUE, sizeof (char *));
|
||||
|
||||
/* Documents and Settings\All Users\Application Data */
|
||||
p = get_special_folder (CSIDL_COMMON_APPDATA);
|
||||
if (p)
|
||||
g_array_append_val (data_dirs, p);
|
||||
|
||||
/* Documents and Settings\All Users\Documents */
|
||||
p = get_special_folder (CSIDL_COMMON_DOCUMENTS);
|
||||
if (p)
|
||||
g_array_append_val (data_dirs, p);
|
||||
|
||||
/* Using the above subfolders of Documents and Settings perhaps
|
||||
* makes sense from a Windows perspective.
|
||||
*
|
||||
* But looking at the actual use cases of this function in GTK+
|
||||
* and GNOME software, what we really want is the "share"
|
||||
* subdirectory of the installation directory for the package
|
||||
* our caller is a part of.
|
||||
*
|
||||
* The address parameter, if non-NULL, points to a function in the
|
||||
* calling module. Use that to determine that module's installation
|
||||
* folder, and use its "share" subfolder.
|
||||
*
|
||||
* Additionally, also use the "share" subfolder of the installation
|
||||
* locations of GLib and the .exe file being run.
|
||||
*
|
||||
* To guard against none of the above being what is really wanted,
|
||||
* callers of this function should have Win32-specific code to look
|
||||
* up their installation folder themselves, and handle a subfolder
|
||||
* "share" of it in the same way as the folders returned from this
|
||||
* function.
|
||||
*/
|
||||
|
||||
p = get_module_share_dir (address);
|
||||
if (p)
|
||||
g_array_append_val (data_dirs, p);
|
||||
|
||||
p = g_win32_get_package_installation_subdirectory (NULL, dll_name, "share");
|
||||
if (p)
|
||||
g_array_append_val (data_dirs, p);
|
||||
|
||||
p = g_win32_get_package_installation_subdirectory (NULL, NULL, "share");
|
||||
if (p)
|
||||
g_array_append_val (data_dirs, p);
|
||||
|
||||
retval = (gchar **) g_array_free (data_dirs, FALSE);
|
||||
|
||||
if (address)
|
||||
{
|
||||
if (hmodule != NULL)
|
||||
g_hash_table_insert (per_module_data_dirs, hmodule, retval);
|
||||
G_UNLOCK (g_utils_global);
|
||||
}
|
||||
|
||||
return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_get_system_data_dirs:
|
||||
*
|
||||
@ -2053,6 +2225,28 @@ g_get_user_cache_dir (void)
|
||||
* the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
|
||||
* XDG Base Directory Specification</ulink>
|
||||
*
|
||||
* On Windows the first elements in the list are the Application Data
|
||||
* and Documents folders for All Users. (These can be determined only
|
||||
* on Windows 2000 or later and are not present in the list on other
|
||||
* Windows versions.) See documentation for CSIDL_COMMON_APPDATA and
|
||||
* CSIDL_COMMON_DOCUMENTS.
|
||||
*
|
||||
* Then follows the "share" subfolder in the installation folder for
|
||||
* the package containing the DLL that calls this function, if it can
|
||||
* be determined.
|
||||
*
|
||||
* Finally the list contains the "share" subfolder in the installation
|
||||
* folder for GLib, and in the installation folder for the package the
|
||||
* application's .exe file belongs to.
|
||||
*
|
||||
* The installation folders above are determined by looking up the
|
||||
* folder where the module (DLL or EXE) in question is located. If the
|
||||
* folder's name is "bin", its parent is used, otherwise the folder
|
||||
* itself.
|
||||
*
|
||||
* Note that on Windows the returned list can vary depending on where
|
||||
* this function is called.
|
||||
*
|
||||
* Return value: a %NULL-terminated array of strings owned by GLib that must
|
||||
* not be modified or freed.
|
||||
* Since: 2.6
|
||||
@ -2060,78 +2254,16 @@ g_get_user_cache_dir (void)
|
||||
G_CONST_RETURN gchar * G_CONST_RETURN *
|
||||
g_get_system_data_dirs (void)
|
||||
{
|
||||
gchar *data_dirs, **data_dir_vector;
|
||||
gchar **data_dir_vector;
|
||||
|
||||
G_LOCK (g_utils_global);
|
||||
|
||||
if (!g_system_data_dirs)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *glib_top_share_dir, *exe_top_share_dir;
|
||||
|
||||
/* Documents and Settings\All Users\Application Data */
|
||||
char *appdata = get_special_folder (CSIDL_COMMON_APPDATA);
|
||||
/* Documents and Settings\All Users\Documents */
|
||||
char *docs = get_special_folder (CSIDL_COMMON_DOCUMENTS);
|
||||
|
||||
if (appdata && docs)
|
||||
{
|
||||
data_dirs = g_strconcat (appdata,
|
||||
G_SEARCHPATH_SEPARATOR_S,
|
||||
docs,
|
||||
NULL);
|
||||
g_free (appdata);
|
||||
g_free (docs);
|
||||
}
|
||||
else if (appdata)
|
||||
data_dirs = appdata;
|
||||
else if (docs)
|
||||
data_dirs = docs;
|
||||
else
|
||||
data_dirs = g_strdup ("");
|
||||
|
||||
/* Using the above subfolders of Documents and Settings perhaps
|
||||
* makes sense from a Windows perspective.
|
||||
*
|
||||
* But looking at the actual use cases of this function in GTK+
|
||||
* and GNOME software, what we really want is the "share"
|
||||
* subdirectory of the installation directory for the package
|
||||
* our caller is a part of.
|
||||
*
|
||||
* As we don't know who calls us, punt, and use the installation
|
||||
* location of GLib, and of the .exe file being run. To guard
|
||||
* against neither of those being what we really want, callers
|
||||
* of this function should have Win32-specific code to look up
|
||||
* their installation folder themselves, and handle a subfolder
|
||||
* "share" of it in the same way as the folders returned from
|
||||
* this function.
|
||||
*/
|
||||
glib_top_share_dir = g_win32_get_package_installation_subdirectory (NULL, dll_name, "share");
|
||||
|
||||
if (glib_top_share_dir)
|
||||
{
|
||||
gchar *tem = data_dirs;
|
||||
data_dirs = g_strconcat (data_dirs, G_SEARCHPATH_SEPARATOR_S,
|
||||
glib_top_share_dir, NULL);
|
||||
g_free (tem);
|
||||
g_free (glib_top_share_dir);
|
||||
}
|
||||
|
||||
exe_top_share_dir = g_win32_get_package_installation_subdirectory (NULL, NULL, "share");
|
||||
|
||||
if (exe_top_share_dir)
|
||||
{
|
||||
gchar *tem = data_dirs;
|
||||
data_dirs = g_strconcat (data_dirs, G_SEARCHPATH_SEPARATOR_S,
|
||||
exe_top_share_dir, NULL);
|
||||
g_free (tem);
|
||||
g_free (exe_top_share_dir);
|
||||
}
|
||||
|
||||
data_dir_vector = g_strsplit (data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
|
||||
g_free (data_dirs);
|
||||
data_dir_vector = (gchar **) g_win32_get_system_data_dirs_for_module (NULL);
|
||||
#else
|
||||
data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
|
||||
gchar *data_dirs = (gchar *) g_getenv ("XDG_DATA_DIRS");
|
||||
|
||||
if (!data_dirs || !data_dirs[0])
|
||||
data_dirs = "/usr/local/share/:/usr/share/";
|
||||
|
@ -125,6 +125,17 @@ G_CONST_RETURN gchar* g_get_user_data_dir (void);
|
||||
G_CONST_RETURN gchar* g_get_user_config_dir (void);
|
||||
G_CONST_RETURN gchar* g_get_user_cache_dir (void);
|
||||
G_CONST_RETURN gchar* G_CONST_RETURN * g_get_system_data_dirs (void);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
G_CONST_RETURN gchar* G_CONST_RETURN * g_win32_get_system_data_dirs_for_module (gconstpointer address);
|
||||
static G_CONST_RETURN gchar * G_CONST_RETURN *
|
||||
g_win32_get_system_data_dirs (void)
|
||||
{
|
||||
return g_win32_get_system_data_dirs_for_module (&g_win32_get_system_data_dirs);
|
||||
}
|
||||
#define g_get_system_data_dirs g_win32_get_system_data_dirs
|
||||
#endif
|
||||
|
||||
G_CONST_RETURN gchar* G_CONST_RETURN * g_get_system_config_dirs (void);
|
||||
|
||||
G_CONST_RETURN gchar* G_CONST_RETURN * g_get_language_names (void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user