From 2aad95254c19df21fc0f7c4413ca3874c8d87997 Mon Sep 17 00:00:00 2001 From: "Olivier F. R. Dierick" Date: Wed, 19 Feb 2020 00:16:44 +0100 Subject: [PATCH] shell32: Create user folder symlinks on lookup and only if it's missing. Change the logic so that when a user folder already exists in the prefix, as a real directory or symbolic link, it's left as-is. Also create a symbolic link, instead of a real directory, when looking up a user folder that is currently missing. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22974 Signed-off-by: Olivier F. R. Dierick Signed-off-by: Alexandre Julliard --- dlls/shell32/shellpath.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c index d32529bae3e..71267ecf580 100644 --- a/dlls/shell32/shellpath.c +++ b/dlls/shell32/shellpath.c @@ -4116,8 +4116,8 @@ static void _SHCreateMyDocumentsSymbolicLink(const UINT * aidsMyStuff, const UIN const char *pszHome; char ** xdg_results; - /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */ - pszPersonal = _SHGetFolderUnixPath(CSIDL_PERSONAL|CSIDL_FLAG_CREATE); + /* Get the unix path of 'My Documents'. */ + pszPersonal = _SHGetFolderUnixPath(CSIDL_PERSONAL|CSIDL_FLAG_DONT_VERIFY); if (!pszPersonal) return; _SHGetXDGUserDirs(xdg_dirs, num, &xdg_results); @@ -4161,8 +4161,8 @@ static void _SHCreateMyDocumentsSymbolicLink(const UINT * aidsMyStuff, const UIN break; } - /* Replace 'My Documents' directory with a symlink or fail silently if not empty. */ - remove(pszPersonal); + /* Create symbolic link to 'My Documents' or fail silently if a directory + * or symlink exists. */ symlink(szPersonalTarget, pszPersonal); } else @@ -4233,8 +4233,8 @@ static void _SHCreateMyStuffSymbolicLink(int nFolder) while (1) { - /* Create the current 'My Whatever' folder and get its unix path. */ - pszMyStuff = _SHGetFolderUnixPath(acsidlMyStuff[i]|CSIDL_FLAG_CREATE); + /* Get the current 'My Whatever' folder unix path. */ + pszMyStuff = _SHGetFolderUnixPath(acsidlMyStuff[i]|CSIDL_FLAG_DONT_VERIFY); if (!pszMyStuff) break; while (1) @@ -4266,7 +4266,6 @@ static void _SHCreateMyStuffSymbolicLink(int nFolder) strcpy(szMyStuffTarget, szPersonalTarget); break; } - remove(pszMyStuff); symlink(szMyStuffTarget, pszMyStuff); heap_free(pszMyStuff); break; @@ -4311,10 +4310,9 @@ static void _SHCreateDesktopSymbolicLink(void) (_SHAppendToUnixPath(szDesktopTarget, DesktopW) && !stat(szDesktopTarget, &statFolder) && S_ISDIR(statFolder.st_mode))) { - pszDesktop = _SHGetFolderUnixPath(CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE); + pszDesktop = _SHGetFolderUnixPath(CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_DONT_VERIFY); if (pszDesktop) { - remove(pszDesktop); if (xdg_desktop_dir) symlink(xdg_desktop_dir, pszDesktop); else @@ -4599,6 +4597,10 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW( goto end; } + /* create symbolic links rather than directories for specific + * user shell folders */ + _SHCreateSymbolicLink(folder); + /* create directory/directories */ ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL); if (ret && ret != ERROR_ALREADY_EXISTS) @@ -5232,6 +5234,10 @@ HRESULT WINAPI SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, DWORD flags, HANDLE t goto failed; } + /* create symbolic links rather than directories for specific + * user shell folders */ + _SHCreateSymbolicLink(folder); + /* create directory/directories */ ret = SHCreateDirectoryExW(NULL, pathW, NULL); if (ret && ret != ERROR_ALREADY_EXISTS)