From cb994350c427b8c5e514ecb26fd036d889cfd839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Tue, 30 Mar 2021 20:27:25 +0000 Subject: [PATCH] GWin32Mount: Don't use SHGetFileInfoW() for mount displaynames This function can create long delays when used on disconnected or just weird volumes. Use IShellFolder::GetDisplayNameOf() instead. Fixes #2096 --- gio/gwin32mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/gio/gwin32mount.c b/gio/gwin32mount.c index 6388beb11..f5be8adfa 100644 --- a/gio/gwin32mount.c +++ b/gio/gwin32mount.c @@ -143,14 +143,52 @@ g_win32_mount_init (GWin32Mount *win32_mount) { } +/* wdrive doesn't need to end with a path separator. + wdrive must use backslashes as path separators, not slashes. + IShellFolder::ParseDisplayName() takes non-const string as input, + so wdrive can't be a const string. + Returns the name on success (free with g_free), + NULL otherwise. + */ +static gchar * +get_mount_display_name (gunichar2 *wdrive) +{ + IShellFolder *desktop; + PIDLIST_RELATIVE volume; + STRRET volume_name; + gchar *result = NULL; + + /* Get the desktop folder object reference */ + if (!SUCCEEDED (SHGetDesktopFolder (&desktop))) + return result; + + if (SUCCEEDED (IShellFolder_ParseDisplayName (desktop, NULL, NULL, wdrive, NULL, &volume, NULL))) + { + volume_name.uType = STRRET_WSTR; + + if (SUCCEEDED (IShellFolder_GetDisplayNameOf (desktop, volume, SHGDN_FORADDRESSBAR, &volume_name))) + { + wchar_t *volume_name_wchar; + + if (SUCCEEDED (StrRetToStrW (&volume_name, volume, &volume_name_wchar))) + { + result = g_utf16_to_utf8 (volume_name_wchar, -1, NULL, NULL, NULL); + CoTaskMemFree (volume_name_wchar); + } + } + CoTaskMemFree (volume); + } + + IShellFolder_Release (desktop); + + return result; +} + static gchar * _win32_get_displayname (const char *drive) { gunichar2 *wdrive = g_utf8_to_utf16 (drive, -1, NULL, NULL, NULL); - gchar *name = NULL; - SHFILEINFOW sfi; - if (SHGetFileInfoW(wdrive, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME)) - name = g_utf16_to_utf8 (sfi.szDisplayName, -1, NULL, NULL, NULL); + gchar *name = get_mount_display_name (wdrive); g_free (wdrive); return name ? name : g_strdup (drive);