+ static gchar *home_dir;
+
+ if (g_once_init_enter (&home_dir))
+ {
+ gchar *tmp;
+
+ /* We first check HOME and use it if it is set */
+ tmp = g_strdup (g_getenv ("HOME"));
+
+#ifdef G_OS_WIN32
+ /* Only believe HOME if it is an absolute path and exists.
+ *
+ * We only do this check on Windows for a couple of reasons.
+ * Historically, we only did it there because we used to ignore $HOME
+ * on UNIX. There are concerns about enabling it now on UNIX because
+ * of things like autofs. In short, if the user has a bogus value in
+ * $HOME then they get what they pay for...
+ */
+ if (tmp)
+ {
+ if (!(g_path_is_absolute (tmp) &&
+ g_file_test (tmp, G_FILE_TEST_IS_DIR)))
+ {
+ g_free (tmp);
+ tmp = NULL;
+ }
+ }
+
+ /* In case HOME is Unix-style (it happens), convert it to
+ * Windows style.
+ */
+ if (tmp)
+ {
+ gchar *p;
+ while ((p = strchr (tmp, '/')) != NULL)
+ *p = '\\';
+ }
+
+ if (!tmp)
+ {
+ /* USERPROFILE is probably the closest equivalent to $HOME? */
+ if (g_getenv ("USERPROFILE") != NULL)
+ tmp = g_strdup (g_getenv ("USERPROFILE"));
+ }
+
+ if (!tmp)
+ tmp = get_special_folder (CSIDL_PROFILE);
+
+ if (!tmp)
+ tmp = get_windows_directory_root ();
+#endif /* G_OS_WIN32 */
+
+ if (!tmp)
+ {
+ /* If we didn't get it from any of those methods, we will have
+ * to read the user database entry.
+ */
+ UserDatabaseEntry *entry;
+
+ entry = g_get_user_database_entry ();
+
+ /* Strictly speaking, we should copy this, but we know that
+ * neither will ever be freed, so don't bother...
+ */
+ tmp = entry->home_dir;
+ }
+
+ g_once_init_leave (&home_dir, tmp);
+ }
+
+ return home_dir;