Add doc comments. (g_win32_get_package_installation_directory): Add one
authorTor Lillqvist <tml@iki.fi>
Wed, 17 Jan 2001 21:37:32 +0000 (21:37 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Wed, 17 Jan 2001 21:37:32 +0000 (21:37 +0000)
2001-01-17  Tor Lillqvist  <tml@iki.fi>

* gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
comments.
(g_win32_get_package_installation_directory): Add one parameter,
the name of a DLL in the package. Add possibility to use that to
deduce the installation directory if not entered into the
Registry. Make the return value dynamically allocated.
(g_win32_get_package_installation_subdirectory): New convenience
function.

* gutils.c (GLIB_LOCALE_DIR)
* gwin32.h: Adapt accordingly.

* testglib.c (main): Adapt tests accordingly.

18 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib.def
glib/glib.def
glib/gutils.c
glib/gwin32.c
glib/gwin32.h
gutils.c
gwin32.c
gwin32.h
testglib.c
tests/testglib.c

index 9798c5e..e22b4e2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index 9798c5e..e22b4e2 100644 (file)
@@ -1,3 +1,19 @@
+2001-01-17  Tor Lillqvist  <tml@iki.fi>
+
+       * gwin32.c (g_win32_getlocale, g_win32_error_message): Add doc
+       comments.
+       (g_win32_get_package_installation_directory): Add one parameter,
+       the name of a DLL in the package. Add possibility to use that to
+       deduce the installation directory if not entered into the
+       Registry. Make the return value dynamically allocated.
+       (g_win32_get_package_installation_subdirectory): New convenience
+       function.
+
+       * gutils.c (GLIB_LOCALE_DIR)
+       * gwin32.h: Adapt accordingly.
+
+       * testglib.c (main): Adapt tests accordingly.
+
 Tue Jan 16 23:20:38 2001  Owen Taylor  <otaylor@redhat.com>
 
        * gutils.c glibintl.h: Optimize for size rather than speed by
index b56d2d3..e414e35 100644 (file)
--- a/glib.def
+++ b/glib.def
@@ -586,6 +586,7 @@ EXPORTS
        g_win32_error_message
        g_win32_ftruncate
        g_win32_get_package_installation_directory
+       g_win32_get_package_installation_subdirectory
        g_win32_getlocale
        g_win32_opendir
        g_win32_readdir
index b56d2d3..e414e35 100644 (file)
@@ -586,6 +586,7 @@ EXPORTS
        g_win32_error_message
        g_win32_ftruncate
        g_win32_get_package_installation_directory
+       g_win32_get_package_installation_subdirectory
        g_win32_getlocale
        g_win32_opendir
        g_win32_readdir
index 221cc19..c48fb2d 100644 (file)
@@ -1009,11 +1009,12 @@ g_get_codeset (void)
 
 #ifdef G_OS_WIN32
 
-#define GLIB_LOCALE_DIR                                \
-  g_strconcat (g_win32_get_package_installation_directory (GETTEXT_PACKAGE), \
-              G_DIR_SEPARATOR_S,                       \
-              "locale",                                \
-              NULL)
+#define GLIB_LOCALE_DIR                                                \
+  g_win32_get_package_installation_subdirectory                        \
+  (GETTEXT_PACKAGE, g_strdup_printf ("glib-%d.%d.dll",         \
+                                    GLIB_MAJOR_VERSION,        \
+                                    GLIB_MINOR_VERSION),       \
+   "locale")
 
 #endif /* G_OS_WIN32 */
 
index 7126b5d..a3577e3 100644 (file)
@@ -526,6 +526,17 @@ g_win32_closedir (DIR *dir)
 #define SUBLANG_UZBEK_CYRILLIC 0x02
 #endif
 
+/**
+ * g_win32_getlocale:
+ *
+ * The setlocale in the Microsoft C library uses locale names of the
+ * form "English_United States.1252" etc. We want the Unixish standard
+ * form "en", "zh_TW" etc. This function gets the current thread
+ * locale from Windows and returns it as a string of the above form
+ * for use in forming file names etc. The returned string should be
+ * deallocated with g_free().
+ */
+
 gchar *
 g_win32_getlocale (void)
 {
@@ -798,6 +809,16 @@ g_win32_getlocale (void)
   return g_strdup (bfr);
 }
 
+/**
+ * g_win32_error_message:
+ * @error: error code
+ *
+ * Translate a Win32 error code (as returned by GetLastError()) into
+ * the corresponding message. The message is either language neutral,
+ * or in the thread's language, or the user's language, the system's
+ * langauge, or US English (see docs for FormatMessage). The returned
+ * string should be deallocated with g_free().
+ */
 gchar *
 g_win32_error_message (gint error)
 {
@@ -823,54 +844,162 @@ g_win32_error_message (gint error)
   return retval;
 }
 
-gchar *
-g_win32_get_package_installation_directory (gchar *package)
+static gchar *
+get_package_directory_from_module (gchar *module_name)
 {
-  static GHashTable *installation_dirs = NULL;
+  static GHashTable *module_dirs = NULL;
+  HMODULE hmodule = NULL;
+  gchar fn[MAX_PATH];
+  gchar *p;
   gchar *result;
+
+  if (module_dirs == NULL)
+    module_dirs = g_hash_table_new (g_str_hash, g_str_equal);
+  
+  result = g_hash_table_lookup (module_dirs, module_name ? module_name : "");
+      
+  if (result)
+    return g_strdup (result);
+
+  if (module_name)
+    {
+      hmodule = GetModuleHandle (module_name);
+      if (!hmodule)
+       return NULL;
+    }
+
+  if (!GetModuleFileName (hmodule, fn, sizeof (fn)))
+    return NULL;
+
+  if ((p = strrchr (fn, '\\')) != NULL)
+    *p = '\0';
+
+  if (module_name)
+    {
+      p = strrchr (fn, '\\');
+      if (p && (g_strcasecmp (p + 1, "bin") == 0 ||
+               g_strcasecmp (p + 1, "lib") == 0))
+       *p = '\0';
+    }
+
+  g_hash_table_insert (module_dirs, module_name ? module_name : "", fn);
+
+  return g_strdup (fn);
+}
+
+/**
+ * g_win32_get_package_installation_directory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ *
+ * Try to determine the installation directory for a software package.
+ * Typically used by GNU software packages.
+ *
+ * @package should be a short identifier for the package. Typically it
+ * is the same identifier as used for GETTEXT_PACKAGE in software
+ * configured accoring to GNU standards. The function first looks in
+ * the Windows Registry for the value #InstallationDirectory in the
+ * key #HKLM\Software\@package, and if that value exists and is a
+ * string, returns that.
+ *
+ * If @package is NULL, or the above value isn't found in the
+ * Registry, but @dll_name is non-NULL, it should name a DLL loaded
+ * into the current process. Typically that would be the name of the
+ * DLL calling this function, looking for its installation
+ * directory. The function then asks Windows what directory that DLL
+ * was loaded from. If that directory's last component is "bin" or
+ * "lib", the parent directory is returned, otherwise the directory
+ * itself. If that DLL isn't loaded, the function proceeds as if
+ * @dll_name was NULL.
+ *
+ * If both @package and @dll_name are NULL, the directory from where
+ * the main executable of the process was loaded is uses instead in
+ * the same way as above.
+ *
+ * The return value should be freed with g_free() when not needed any longer.  */
+
+gchar *
+g_win32_get_package_installation_directory (gchar *package,
+                                           gchar *dll_name)
+{
+  static GHashTable *package_dirs = NULL;
+  gchar *result = NULL;
   gchar *key;
   char win_dir[MAX_PATH];
-  gchar *sep;
   HKEY reg_key = NULL;
   DWORD type;
   DWORD nbytes;
 
-  if (installation_dirs == NULL)
-    installation_dirs = g_hash_table_new (g_str_hash, g_str_equal);
-
-  result = g_hash_table_lookup (installation_dirs, package);
-
-  if (result && result[0])
-    return result;
-
-  key = g_strconcat ("Software\\", package, NULL);
-
-  nbytes = 0;
-  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
-                   KEY_QUERY_VALUE, &reg_key) != ERROR_SUCCESS
-      || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
-                         &type, NULL, &nbytes) != ERROR_SUCCESS
-      || type != REG_SZ)
+  if (package != NULL)
     {
-      /* Uh oh. Use a default %WinDir%\package value */
-      if (GetWindowsDirectory (win_dir, sizeof (win_dir)) == 0)
-       strcpy (win_dir, (GetVersion () >= 0x80000000 ? "C:\\windows" : "C:\\winnt"));
-      sep = (win_dir[strlen (win_dir) - 1] == '\\' ? "" : "\\");
-      result = g_strconcat (win_dir, sep, package, NULL);
+      if (package_dirs == NULL)
+       package_dirs = g_hash_table_new (g_str_hash, g_str_equal);
+      
+      result = g_hash_table_lookup (package_dirs, package);
+      
+      if (result && result[0])
+       return g_strdup (result);
+      
+      key = g_strconcat ("Software\\", package, NULL);
+      
+      nbytes = 0;
+      if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
+                       KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
+         && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                             &type, NULL, &nbytes) == ERROR_SUCCESS
+         && type == REG_SZ)
+       {
+         result = g_malloc (nbytes + 1);
+         RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                          &type, result, &nbytes);
+         result[nbytes] = '\0';
+       }
+
+      if (reg_key != NULL)
+       RegCloseKey (reg_key);
+      
+      g_free (key);
+      
     }
-  else
+  if (result)
     {
-      result = g_malloc (nbytes + 1);
-      RegQueryValueEx (reg_key, "InstallationDirectory", 0,
-                      &type, result, &nbytes);
-      result[nbytes] = '\0';
+      g_hash_table_insert (package_dirs, package, result);
+      return g_strdup (result);
     }
-  g_hash_table_insert (installation_dirs, package, result);
 
-  if (reg_key != NULL)
-    RegCloseKey (reg_key);
+  if (dll_name != NULL)
+    result = get_package_directory_from_module (dll_name);
 
-  g_free (key);
+  if (result == NULL)
+    result = get_package_directory_from_module (NULL);
 
   return result;
 }
+
+/**
+ * g_win32_get_package_installation_subdirectory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ * @subdir: A subdirectory of the package installation directory.
+ *
+ * Returns a string containg the path of the subdirectory @subdir in
+ * the return value from calling
+ * g_win32_get_package_installation_directory() with the @package and
+ * @dll_name parameters. The return value should be freed with
+ * g_free() when no longer needed.
+ */
+
+gchar *
+g_win32_get_package_installation_subdirectory (gchar *package,
+                                              gchar *dll_name,
+                                              gchar *subdir)
+{
+  gchar *prefix;
+  gchar *sep;
+
+  prefix = g_win32_get_package_installation_directory (package, dll_name);
+
+  sep = (prefix[strlen (prefix) - 1] == '\\' ? "" : "\\");
+
+  return g_strconcat (prefix, sep, subdir, NULL);
+}
index faa81c7..b30ab15 100644 (file)
@@ -110,7 +110,12 @@ gchar *            g_win32_getlocale  (void);
  */
 gchar *         g_win32_error_message (gint error);
 
-gchar *         g_win32_get_package_installation_directory (gchar *package);
+gchar *         g_win32_get_package_installation_directory (gchar *package,
+                                                           gchar *dll_name);
+
+gchar *         g_win32_get_package_installation_subdirectory (gchar *package,
+                                                              gchar *dll_name,
+                                                              gchar *subdir);
 
 G_END_DECLS
 
index 221cc19..c48fb2d 100644 (file)
--- a/gutils.c
+++ b/gutils.c
@@ -1009,11 +1009,12 @@ g_get_codeset (void)
 
 #ifdef G_OS_WIN32
 
-#define GLIB_LOCALE_DIR                                \
-  g_strconcat (g_win32_get_package_installation_directory (GETTEXT_PACKAGE), \
-              G_DIR_SEPARATOR_S,                       \
-              "locale",                                \
-              NULL)
+#define GLIB_LOCALE_DIR                                                \
+  g_win32_get_package_installation_subdirectory                        \
+  (GETTEXT_PACKAGE, g_strdup_printf ("glib-%d.%d.dll",         \
+                                    GLIB_MAJOR_VERSION,        \
+                                    GLIB_MINOR_VERSION),       \
+   "locale")
 
 #endif /* G_OS_WIN32 */
 
index 7126b5d..a3577e3 100644 (file)
--- a/gwin32.c
+++ b/gwin32.c
@@ -526,6 +526,17 @@ g_win32_closedir (DIR *dir)
 #define SUBLANG_UZBEK_CYRILLIC 0x02
 #endif
 
+/**
+ * g_win32_getlocale:
+ *
+ * The setlocale in the Microsoft C library uses locale names of the
+ * form "English_United States.1252" etc. We want the Unixish standard
+ * form "en", "zh_TW" etc. This function gets the current thread
+ * locale from Windows and returns it as a string of the above form
+ * for use in forming file names etc. The returned string should be
+ * deallocated with g_free().
+ */
+
 gchar *
 g_win32_getlocale (void)
 {
@@ -798,6 +809,16 @@ g_win32_getlocale (void)
   return g_strdup (bfr);
 }
 
+/**
+ * g_win32_error_message:
+ * @error: error code
+ *
+ * Translate a Win32 error code (as returned by GetLastError()) into
+ * the corresponding message. The message is either language neutral,
+ * or in the thread's language, or the user's language, the system's
+ * langauge, or US English (see docs for FormatMessage). The returned
+ * string should be deallocated with g_free().
+ */
 gchar *
 g_win32_error_message (gint error)
 {
@@ -823,54 +844,162 @@ g_win32_error_message (gint error)
   return retval;
 }
 
-gchar *
-g_win32_get_package_installation_directory (gchar *package)
+static gchar *
+get_package_directory_from_module (gchar *module_name)
 {
-  static GHashTable *installation_dirs = NULL;
+  static GHashTable *module_dirs = NULL;
+  HMODULE hmodule = NULL;
+  gchar fn[MAX_PATH];
+  gchar *p;
   gchar *result;
+
+  if (module_dirs == NULL)
+    module_dirs = g_hash_table_new (g_str_hash, g_str_equal);
+  
+  result = g_hash_table_lookup (module_dirs, module_name ? module_name : "");
+      
+  if (result)
+    return g_strdup (result);
+
+  if (module_name)
+    {
+      hmodule = GetModuleHandle (module_name);
+      if (!hmodule)
+       return NULL;
+    }
+
+  if (!GetModuleFileName (hmodule, fn, sizeof (fn)))
+    return NULL;
+
+  if ((p = strrchr (fn, '\\')) != NULL)
+    *p = '\0';
+
+  if (module_name)
+    {
+      p = strrchr (fn, '\\');
+      if (p && (g_strcasecmp (p + 1, "bin") == 0 ||
+               g_strcasecmp (p + 1, "lib") == 0))
+       *p = '\0';
+    }
+
+  g_hash_table_insert (module_dirs, module_name ? module_name : "", fn);
+
+  return g_strdup (fn);
+}
+
+/**
+ * g_win32_get_package_installation_directory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ *
+ * Try to determine the installation directory for a software package.
+ * Typically used by GNU software packages.
+ *
+ * @package should be a short identifier for the package. Typically it
+ * is the same identifier as used for GETTEXT_PACKAGE in software
+ * configured accoring to GNU standards. The function first looks in
+ * the Windows Registry for the value #InstallationDirectory in the
+ * key #HKLM\Software\@package, and if that value exists and is a
+ * string, returns that.
+ *
+ * If @package is NULL, or the above value isn't found in the
+ * Registry, but @dll_name is non-NULL, it should name a DLL loaded
+ * into the current process. Typically that would be the name of the
+ * DLL calling this function, looking for its installation
+ * directory. The function then asks Windows what directory that DLL
+ * was loaded from. If that directory's last component is "bin" or
+ * "lib", the parent directory is returned, otherwise the directory
+ * itself. If that DLL isn't loaded, the function proceeds as if
+ * @dll_name was NULL.
+ *
+ * If both @package and @dll_name are NULL, the directory from where
+ * the main executable of the process was loaded is uses instead in
+ * the same way as above.
+ *
+ * The return value should be freed with g_free() when not needed any longer.  */
+
+gchar *
+g_win32_get_package_installation_directory (gchar *package,
+                                           gchar *dll_name)
+{
+  static GHashTable *package_dirs = NULL;
+  gchar *result = NULL;
   gchar *key;
   char win_dir[MAX_PATH];
-  gchar *sep;
   HKEY reg_key = NULL;
   DWORD type;
   DWORD nbytes;
 
-  if (installation_dirs == NULL)
-    installation_dirs = g_hash_table_new (g_str_hash, g_str_equal);
-
-  result = g_hash_table_lookup (installation_dirs, package);
-
-  if (result && result[0])
-    return result;
-
-  key = g_strconcat ("Software\\", package, NULL);
-
-  nbytes = 0;
-  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
-                   KEY_QUERY_VALUE, &reg_key) != ERROR_SUCCESS
-      || RegQueryValueEx (reg_key, "InstallationDirectory", 0,
-                         &type, NULL, &nbytes) != ERROR_SUCCESS
-      || type != REG_SZ)
+  if (package != NULL)
     {
-      /* Uh oh. Use a default %WinDir%\package value */
-      if (GetWindowsDirectory (win_dir, sizeof (win_dir)) == 0)
-       strcpy (win_dir, (GetVersion () >= 0x80000000 ? "C:\\windows" : "C:\\winnt"));
-      sep = (win_dir[strlen (win_dir) - 1] == '\\' ? "" : "\\");
-      result = g_strconcat (win_dir, sep, package, NULL);
+      if (package_dirs == NULL)
+       package_dirs = g_hash_table_new (g_str_hash, g_str_equal);
+      
+      result = g_hash_table_lookup (package_dirs, package);
+      
+      if (result && result[0])
+       return g_strdup (result);
+      
+      key = g_strconcat ("Software\\", package, NULL);
+      
+      nbytes = 0;
+      if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
+                       KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
+         && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                             &type, NULL, &nbytes) == ERROR_SUCCESS
+         && type == REG_SZ)
+       {
+         result = g_malloc (nbytes + 1);
+         RegQueryValueEx (reg_key, "InstallationDirectory", 0,
+                          &type, result, &nbytes);
+         result[nbytes] = '\0';
+       }
+
+      if (reg_key != NULL)
+       RegCloseKey (reg_key);
+      
+      g_free (key);
+      
     }
-  else
+  if (result)
     {
-      result = g_malloc (nbytes + 1);
-      RegQueryValueEx (reg_key, "InstallationDirectory", 0,
-                      &type, result, &nbytes);
-      result[nbytes] = '\0';
+      g_hash_table_insert (package_dirs, package, result);
+      return g_strdup (result);
     }
-  g_hash_table_insert (installation_dirs, package, result);
 
-  if (reg_key != NULL)
-    RegCloseKey (reg_key);
+  if (dll_name != NULL)
+    result = get_package_directory_from_module (dll_name);
 
-  g_free (key);
+  if (result == NULL)
+    result = get_package_directory_from_module (NULL);
 
   return result;
 }
+
+/**
+ * g_win32_get_package_installation_subdirectory:
+ * @package: An identifier for a software package, or NULL
+ * @dll_name: The name of a DLL that a package provides, or NULL
+ * @subdir: A subdirectory of the package installation directory.
+ *
+ * Returns a string containg the path of the subdirectory @subdir in
+ * the return value from calling
+ * g_win32_get_package_installation_directory() with the @package and
+ * @dll_name parameters. The return value should be freed with
+ * g_free() when no longer needed.
+ */
+
+gchar *
+g_win32_get_package_installation_subdirectory (gchar *package,
+                                              gchar *dll_name,
+                                              gchar *subdir)
+{
+  gchar *prefix;
+  gchar *sep;
+
+  prefix = g_win32_get_package_installation_directory (package, dll_name);
+
+  sep = (prefix[strlen (prefix) - 1] == '\\' ? "" : "\\");
+
+  return g_strconcat (prefix, sep, subdir, NULL);
+}
index faa81c7..b30ab15 100644 (file)
--- a/gwin32.h
+++ b/gwin32.h
@@ -110,7 +110,12 @@ gchar *            g_win32_getlocale  (void);
  */
 gchar *         g_win32_error_message (gint error);
 
-gchar *         g_win32_get_package_installation_directory (gchar *package);
+gchar *         g_win32_get_package_installation_directory (gchar *package,
+                                                           gchar *dll_name);
+
+gchar *         g_win32_get_package_installation_subdirectory (gchar *package,
+                                                              gchar *dll_name,
+                                                              gchar *subdir);
 
 G_END_DECLS
 
index 05dd7d5..7cbd939 100644 (file)
@@ -388,6 +388,11 @@ main (int   argc,
   GError *error;
   char *name_used;
   gchar *p;
+#ifdef G_OS_WIN32
+  gchar *glib_dll = g_strdup_printf ("glib-%d.%d.dll",
+                                    GLIB_MAJOR_VERSION,
+                                    GLIB_MINOR_VERSION);
+#endif
 
   g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n",
           glib_major_version,
@@ -1145,10 +1150,17 @@ main (int   argc,
 #ifdef G_OS_WIN32
   g_print ("current locale: %s\n", g_win32_getlocale ());
 
-  g_print ("GLib installation directory (used for message catalogs): %s\n",
-          g_win32_get_package_installation_directory (GETTEXT_PACKAGE));
+  g_print ("GLib installation directory, from Registry entry for %s if available: %s\n",
+          GETTEXT_PACKAGE,
+          g_win32_get_package_installation_directory (GETTEXT_PACKAGE, NULL));
+  g_print ("Ditto, or from GLib DLL name: %s\n",
+          g_win32_get_package_installation_directory (GETTEXT_PACKAGE, glib_dll));
+  g_print ("Ditto, only from GLib DLL name: %s\n",
+          g_win32_get_package_installation_directory (NULL, glib_dll));
+  g_print ("locale subdirectory of GLib installation directory: %s\n",
+          g_win32_get_package_installation_subdirectory (NULL, glib_dll, "locale"));
   g_print ("GTK+ 2.0 installation directory, if available: %s\n",
-          g_win32_get_package_installation_directory ("gtk20"));
+          g_win32_get_package_installation_directory ("gtk20", NULL));
 #endif
 
   g_print ("checking file functions...\n");
index 05dd7d5..7cbd939 100644 (file)
@@ -388,6 +388,11 @@ main (int   argc,
   GError *error;
   char *name_used;
   gchar *p;
+#ifdef G_OS_WIN32
+  gchar *glib_dll = g_strdup_printf ("glib-%d.%d.dll",
+                                    GLIB_MAJOR_VERSION,
+                                    GLIB_MINOR_VERSION);
+#endif
 
   g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n",
           glib_major_version,
@@ -1145,10 +1150,17 @@ main (int   argc,
 #ifdef G_OS_WIN32
   g_print ("current locale: %s\n", g_win32_getlocale ());
 
-  g_print ("GLib installation directory (used for message catalogs): %s\n",
-          g_win32_get_package_installation_directory (GETTEXT_PACKAGE));
+  g_print ("GLib installation directory, from Registry entry for %s if available: %s\n",
+          GETTEXT_PACKAGE,
+          g_win32_get_package_installation_directory (GETTEXT_PACKAGE, NULL));
+  g_print ("Ditto, or from GLib DLL name: %s\n",
+          g_win32_get_package_installation_directory (GETTEXT_PACKAGE, glib_dll));
+  g_print ("Ditto, only from GLib DLL name: %s\n",
+          g_win32_get_package_installation_directory (NULL, glib_dll));
+  g_print ("locale subdirectory of GLib installation directory: %s\n",
+          g_win32_get_package_installation_subdirectory (NULL, glib_dll, "locale"));
   g_print ("GTK+ 2.0 installation directory, if available: %s\n",
-          g_win32_get_package_installation_directory ("gtk20"));
+          g_win32_get_package_installation_directory ("gtk20", NULL));
 #endif
 
   g_print ("checking file functions...\n");