[PATCH 1/2] shell32: Move and split _SHCreateSymbolicLinks()

Olivier F. R. Dierick o.dierick at piezo-forte.be
Sun Feb 16 18:26:48 CST 2020


Prepare the helper function for rework by moving it above the function
that will use it and splitting it by kind of directories.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22974
Signed-off-by: Olivier F. R. Dierick <o.dierick at piezo-forte.be>
---
 dlls/shell32/shellpath.c | 638 +++++++++++++++++++++++++++--------------------
 1 file changed, 373 insertions(+), 265 deletions(-)

diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
index b6350ea..293c51b 100644
--- a/dlls/shell32/shellpath.c
+++ b/dlls/shell32/shellpath.c
@@ -4030,6 +4030,379 @@ cleanup:
     return hr;
 }
 
+/******************************************************************************
+ * _SHAppendToUnixPath  [Internal]
+ *
+ * Helper function for _SHCreateSymbolicLinks. Appends pwszSubPath (or the
+ * corresponding resource, if IS_INTRESOURCE) to the unix base path 'szBasePath'
+ * and replaces backslashes with slashes.
+ *
+ * PARAMS
+ *  szBasePath  [IO] The unix base path, which will be appended to (CP_UNXICP).
+ *  pwszSubPath [I]  Sub-path or resource id (use MAKEINTRESOURCEW).
+ *
+ * RETURNS
+ *  Success: TRUE,
+ *  Failure: FALSE
+ */
+static inline BOOL _SHAppendToUnixPath(char *szBasePath, LPCWSTR pwszSubPath) {
+    WCHAR wszSubPath[MAX_PATH];
+    int cLen = strlen(szBasePath);
+    char *pBackslash;
+
+    if (IS_INTRESOURCE(pwszSubPath)) {
+        if (!LoadStringW(shell32_hInstance, LOWORD(pwszSubPath), wszSubPath, MAX_PATH)) {
+            /* Fall back to hard coded defaults. */
+            switch (LOWORD(pwszSubPath)) {
+                case IDS_PERSONAL:
+                    lstrcpyW(wszSubPath, DocumentsW);
+                    break;
+                case IDS_MYMUSIC:
+                    lstrcpyW(wszSubPath, My_MusicW);
+                    break;
+                case IDS_MYPICTURES:
+                    lstrcpyW(wszSubPath, My_PicturesW);
+                    break;
+                case IDS_MYVIDEOS:
+                    lstrcpyW(wszSubPath, My_VideosW);
+                    break;
+                case IDS_DOWNLOADS:
+                    lstrcpyW(wszSubPath, DownloadsW);
+                    break;
+                case IDS_TEMPLATES:
+                    lstrcpyW(wszSubPath, TemplatesW);
+                    break;
+                default:
+                    ERR("LoadString(%d) failed!\n", LOWORD(pwszSubPath));
+                    return FALSE;
+            }
+        }
+    } else {
+        lstrcpyW(wszSubPath, pwszSubPath);
+    }
+
+    if (szBasePath[cLen-1] != '/') szBasePath[cLen++] = '/';
+
+    if (!WideCharToMultiByte(CP_UNIXCP, 0, wszSubPath, -1, szBasePath + cLen,
+                             FILENAME_MAX - cLen, NULL, NULL))
+    {
+        return FALSE;
+    }
+
+    pBackslash = szBasePath + cLen;
+    while ((pBackslash = strchr(pBackslash, '\\'))) *pBackslash = '/';
+
+    return TRUE;
+}
+
+/******************************************************************************
+ * _SHCreateMyDocumentsSymbolicLink  [Internal]
+ *
+ * Sets up a symbolic link for the 'My Documents' shell folder to point into
+ * the users home directory.
+ */
+static void _SHCreateMyDocumentsSymbolicLink(void)
+{
+    UINT aidsMyStuff[] = { IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC, IDS_DOWNLOADS, IDS_TEMPLATES };
+    static const char * const xdg_dirs[] = { "DOCUMENTS" };
+    static const unsigned int num = ARRAY_SIZE(xdg_dirs);
+    WCHAR wszTempPath[MAX_PATH];
+    char szPersonalTarget[FILENAME_MAX], *pszPersonal;
+    char szMyStuffTarget[FILENAME_MAX];
+    struct stat statFolder;
+    const char *pszHome;
+    HRESULT hr;
+    char ** xdg_results;
+    UINT i;
+
+    /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */
+    hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
+                          SHGFP_TYPE_DEFAULT, wszTempPath);
+    if (FAILED(hr)) return;
+    pszPersonal = wine_get_unix_file_name(wszTempPath);
+    if (!pszPersonal) return;
+
+    hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
+    if (FAILED(hr)) xdg_results = NULL;
+
+    pszHome = getenv("HOME");
+    if (pszHome && !stat(pszHome, &statFolder) && S_ISDIR(statFolder.st_mode))
+    {
+        while (1)
+        {
+            /* Check if there's already a Wine-specific 'My Documents' folder */
+            strcpy(szPersonalTarget, pszHome);
+            if (_SHAppendToUnixPath(szPersonalTarget, MAKEINTRESOURCEW(IDS_PERSONAL)) &&
+                !stat(szPersonalTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
+            {
+                /* '$HOME/My Documents' exists. Create 'My Pictures',
+                 * 'My Videos' and 'My Music' subfolders or fail silently if
+                 * they already exist.
+                 */
+                for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
+                {
+                    strcpy(szMyStuffTarget, szPersonalTarget);
+                    if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
+                        mkdir(szMyStuffTarget, 0777);
+                }
+                break;
+            }
+
+            /* Try to point to the XDG Documents folder */
+            if (xdg_results && xdg_results[0] &&
+               !stat(xdg_results[0], &statFolder) &&
+               S_ISDIR(statFolder.st_mode))
+            {
+                strcpy(szPersonalTarget, xdg_results[0]);
+                break;
+            }
+
+            /* Or the hardcoded / OS X Documents folder */
+            strcpy(szPersonalTarget, pszHome);
+            if (_SHAppendToUnixPath(szPersonalTarget, DocumentsW) &&
+               !stat(szPersonalTarget, &statFolder) &&
+               S_ISDIR(statFolder.st_mode))
+                break;
+
+            /* As a last resort point to $HOME. */
+            strcpy(szPersonalTarget, pszHome);
+            break;
+        }
+
+        /* Replace 'My Documents' directory with a symlink or fail silently if not empty. */
+        remove(pszPersonal);
+        symlink(szPersonalTarget, pszPersonal);
+    }
+    else
+    {
+        /* '$HOME' doesn't exist. Create 'My Pictures', 'My Videos' and 'My Music' subdirs
+         * in '%USERPROFILE%\\My Documents' or fail silently if they already exist. */
+        pszHome = NULL;
+        strcpy(szPersonalTarget, pszPersonal);
+        for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
+            strcpy(szMyStuffTarget, szPersonalTarget);
+            if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
+                mkdir(szMyStuffTarget, 0777);
+        }
+    }
+
+    heap_free(pszPersonal);
+
+    /* Free resources allocated by XDG_UserDirLookup() */
+    if (xdg_results)
+    {
+        for (i = 0; i < num; i++)
+            heap_free(xdg_results[i]);
+        heap_free(xdg_results);
+    }
+}
+
+/******************************************************************************
+ * _SHCreateMyStuffSymbolicLink  [Internal]
+ *
+ * Sets up a symbolic link for one of the 'My Whatever' shell folders to point
+ * into the users home directory.
+ *
+ * PARAMS
+ *  nFolder  [I] CSIDL identifying the folder.
+ */
+static void _SHCreateMyStuffSymbolicLink(int nFolder)
+{
+    UINT aidsMyStuff[] = { IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC, IDS_DOWNLOADS, IDS_TEMPLATES };
+    const WCHAR* MyOSXStuffW[] = { PicturesW, MoviesW, MusicW, DownloadsW, TemplatesW };
+    int acsidlMyStuff[] = { CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_MYMUSIC, CSIDL_DOWNLOADS, CSIDL_TEMPLATES };
+    static const char * const xdg_dirs[] = { "PICTURES", "VIDEOS", "MUSIC", "DOWNLOAD", "TEMPLATES" };
+    static const unsigned int num = ARRAY_SIZE(xdg_dirs);
+    WCHAR wszTempPath[MAX_PATH];
+    char szPersonalTarget[FILENAME_MAX], *pszPersonal;
+    char szMyStuffTarget[FILENAME_MAX], *pszMyStuff;
+    struct stat statFolder;
+    const char *pszHome;
+    HRESULT hr;
+    char ** xdg_results;
+    DWORD folder = nFolder & CSIDL_FOLDER_MASK;
+    UINT i;
+
+    for (i = 0; i < ARRAY_SIZE(acsidlMyStuff) && acsidlMyStuff[i] != folder; i++);
+    if (i >= ARRAY_SIZE(acsidlMyStuff)) return;
+
+    /* Get the real path of the existing 'My Documents' shell folder. */
+    hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
+                          SHGFP_TYPE_DEFAULT, wszTempPath);
+    if (FAILED(hr)) return;
+    pszPersonal = wine_get_unix_file_name(wszTempPath);
+    if (!pszPersonal) return;
+
+    strcpy(szPersonalTarget, pszPersonal);
+    if (!stat(pszPersonal, &statFolder) && S_ISLNK(statFolder.st_mode))
+    {
+        int cLen = readlink(pszPersonal, szPersonalTarget, FILENAME_MAX-1);
+        if (cLen >= 0) szPersonalTarget[cLen] = '\0';
+    }
+    heap_free(pszPersonal);
+
+    hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
+    if (FAILED(hr)) xdg_results = NULL;
+
+    pszHome = getenv("HOME");
+
+    while (1)
+    {
+        /* Create the current 'My Whatever' folder and get its unix path. */
+        hr = SHGetFolderPathW(NULL, acsidlMyStuff[i]|CSIDL_FLAG_CREATE, NULL,
+                              SHGFP_TYPE_DEFAULT, wszTempPath);
+        if (FAILED(hr)) break;
+
+        pszMyStuff = wine_get_unix_file_name(wszTempPath);
+        if (!pszMyStuff) break;
+
+        while (1)
+        {
+            /* Check for the Wine-specific '$HOME/My Documents' subfolder */
+            strcpy(szMyStuffTarget, szPersonalTarget);
+            if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])) &&
+                !stat(szMyStuffTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
+                break;
+
+            /* Try the XDG_XXX_DIR folder */
+            if (xdg_results && xdg_results[i])
+            {
+                strcpy(szMyStuffTarget, xdg_results[i]);
+                break;
+            }
+
+            /* Or the OS X folder (these are never localized) */
+            if (pszHome)
+            {
+                strcpy(szMyStuffTarget, pszHome);
+                if (_SHAppendToUnixPath(szMyStuffTarget, MyOSXStuffW[i]) &&
+                    !stat(szMyStuffTarget, &statFolder) &&
+                    S_ISDIR(statFolder.st_mode))
+                    break;
+            }
+
+            /* As a last resort point to the same location as 'My Documents' */
+            strcpy(szMyStuffTarget, szPersonalTarget);
+            break;
+        }
+        remove(pszMyStuff);
+        symlink(szMyStuffTarget, pszMyStuff);
+        heap_free(pszMyStuff);
+        break;
+    }
+
+    /* Free resources allocated by XDG_UserDirLookup() */
+    if (xdg_results)
+    {
+        for (i = 0; i < num; i++)
+            heap_free(xdg_results[i]);
+        heap_free(xdg_results);
+    }
+}
+
+/******************************************************************************
+ * _SHCreateDesktopSymbolicLink  [Internal]
+ *
+ * Sets up a symbolic link for the 'Desktop' shell folder to point into the
+ * users home directory.
+ */
+static void _SHCreateDesktopSymbolicLink(void)
+{
+    UINT i;
+    static const char * const xdg_dirs[] = { "DESKTOP" };
+    static const unsigned int num = ARRAY_SIZE(xdg_dirs);
+    WCHAR wszTempPath[MAX_PATH];
+    char *pszPersonal;
+    char szDesktopTarget[FILENAME_MAX], *pszDesktop;
+    struct stat statFolder;
+    const char *pszHome;
+    HRESULT hr;
+    char ** xdg_results;
+    char * xdg_desktop_dir;
+
+    /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */
+    hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
+                          SHGFP_TYPE_DEFAULT, wszTempPath);
+    if (FAILED(hr)) return;
+    pszPersonal = wine_get_unix_file_name(wszTempPath);
+    if (!pszPersonal) return;
+
+    hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
+    if (FAILED(hr)) xdg_results = NULL;
+
+    pszHome = getenv("HOME");
+
+    if (pszHome)
+        strcpy(szDesktopTarget, pszHome);
+    else
+        strcpy(szDesktopTarget, pszPersonal);
+    heap_free(pszPersonal);
+
+    xdg_desktop_dir = xdg_results ? xdg_results[0] : NULL;
+    if (xdg_desktop_dir ||
+        (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
+        !stat(szDesktopTarget, &statFolder) && S_ISDIR(statFolder.st_mode)))
+    {
+        hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, NULL,
+                              SHGFP_TYPE_DEFAULT, wszTempPath);
+        if (SUCCEEDED(hr) && (pszDesktop = wine_get_unix_file_name(wszTempPath)))
+        {
+            remove(pszDesktop);
+            if (xdg_desktop_dir)
+                symlink(xdg_desktop_dir, pszDesktop);
+            else
+                symlink(szDesktopTarget, pszDesktop);
+            heap_free(pszDesktop);
+        }
+    }
+
+    /* Free resources allocated by XDG_UserDirLookup() */
+    if (xdg_results)
+    {
+        for (i = 0; i < num; i++)
+            heap_free(xdg_results[i]);
+        heap_free(xdg_results);
+    }
+}
+
+/******************************************************************************
+ * _SHCreateSymbolicLinks  [Internal]
+ *
+ * Sets up symbol links for various shell folders to point into the user's home
+ * directory. We do an educated guess about what the user would probably want:
+ * - If there is a 'My Documents' directory in $HOME, the user probably wants
+ *   wine's 'My Documents' to point there. Furthermore, we infer that the user
+ *   is a Windows lover and has no problem with wine creating subfolders for
+ *   'My Pictures', 'My Music', 'My Videos' etc. under '$HOME/My Documents', if
+ *   those do not already exist. We put appropriate symbolic links in place for
+ *   those, too.
+ * - If there is no 'My Documents' directory in $HOME, we let 'My Documents'
+ *   point directly to $HOME. We assume the user to be a unix hacker who does not
+ *   want wine to create anything anywhere besides the .wine directory. So, if
+ *   there already is a 'My Music' directory in $HOME, we symlink the 'My Music'
+ *   shell folder to it. But if not, then we check XDG_MUSIC_DIR - "well known"
+ *   directory, and try to link to that. If that fails, then we symlink to
+ *   $HOME directly. The same holds for 'My Pictures', 'My Videos' etc.
+ * - The Desktop shell folder is symlinked to XDG_DESKTOP_DIR. If that does not
+ *   exist, then we try '$HOME/Desktop'. If that does not exist, then we leave
+ *   it alone.
+ * ('My Music',... above in fact means LoadString(IDS_MYMUSIC))
+ */
+static void _SHCreateSymbolicLinks(void)
+{
+    UINT i;
+    int acsidlMyStuff[] = { CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_MYMUSIC, CSIDL_DOWNLOADS, CSIDL_TEMPLATES };
+
+    _SHCreateMyDocumentsSymbolicLink();
+
+    /* Create symbolic links for 'My Pictures', 'My Videos', 'My Music', 'Downloads' and 'Templates'. */
+    for (i=0; i < ARRAY_SIZE(acsidlMyStuff); i++)
+        _SHCreateMyStuffSymbolicLink(acsidlMyStuff[i]);
+
+    /* Last but not least, the Desktop folder */
+    _SHCreateDesktopSymbolicLink();
+}
+
 /*************************************************************************
  * SHGetFolderPathAndSubDirW		[SHELL32.@]
  */
@@ -4382,271 +4755,6 @@ static HRESULT _SHRegisterCommonShellFolders(void)
 }
 
 /******************************************************************************
- * _SHAppendToUnixPath  [Internal]
- *
- * Helper function for _SHCreateSymbolicLinks. Appends pwszSubPath (or the 
- * corresponding resource, if IS_INTRESOURCE) to the unix base path 'szBasePath' 
- * and replaces backslashes with slashes.
- *
- * PARAMS
- *  szBasePath  [IO] The unix base path, which will be appended to (CP_UNXICP).
- *  pwszSubPath [I]  Sub-path or resource id (use MAKEINTRESOURCEW).
- *
- * RETURNS
- *  Success: TRUE,
- *  Failure: FALSE
- */
-static inline BOOL _SHAppendToUnixPath(char *szBasePath, LPCWSTR pwszSubPath) {
-    WCHAR wszSubPath[MAX_PATH];
-    int cLen = strlen(szBasePath);
-    char *pBackslash;
-
-    if (IS_INTRESOURCE(pwszSubPath)) {
-        if (!LoadStringW(shell32_hInstance, LOWORD(pwszSubPath), wszSubPath, MAX_PATH)) {
-            /* Fall back to hard coded defaults. */
-            switch (LOWORD(pwszSubPath)) {
-                case IDS_PERSONAL:
-                    lstrcpyW(wszSubPath, DocumentsW);
-                    break;
-                case IDS_MYMUSIC:
-                    lstrcpyW(wszSubPath, My_MusicW);
-                    break;
-                case IDS_MYPICTURES:
-                    lstrcpyW(wszSubPath, My_PicturesW);
-                    break;
-                case IDS_MYVIDEOS:
-                    lstrcpyW(wszSubPath, My_VideosW);
-                    break;
-                case IDS_DOWNLOADS:
-                    lstrcpyW(wszSubPath, DownloadsW);
-                    break;
-                case IDS_TEMPLATES:
-                    lstrcpyW(wszSubPath, TemplatesW);
-                    break;
-                default:
-                    ERR("LoadString(%d) failed!\n", LOWORD(pwszSubPath));
-                    return FALSE;
-            }
-        }
-    } else {
-        lstrcpyW(wszSubPath, pwszSubPath);
-    }
- 
-    if (szBasePath[cLen-1] != '/') szBasePath[cLen++] = '/';
- 
-    if (!WideCharToMultiByte(CP_UNIXCP, 0, wszSubPath, -1, szBasePath + cLen,
-                             FILENAME_MAX - cLen, NULL, NULL))
-    {
-        return FALSE;
-    }
- 
-    pBackslash = szBasePath + cLen;
-    while ((pBackslash = strchr(pBackslash, '\\'))) *pBackslash = '/';
- 
-    return TRUE;
-}
-
-/******************************************************************************
- * _SHCreateSymbolicLinks  [Internal]
- * 
- * Sets up symbol links for various shell folders to point into the user's home
- * directory. We do an educated guess about what the user would probably want:
- * - If there is a 'My Documents' directory in $HOME, the user probably wants
- *   wine's 'My Documents' to point there. Furthermore, we infer that the user
- *   is a Windows lover and has no problem with wine creating subfolders for
- *   'My Pictures', 'My Music', 'My Videos' etc. under '$HOME/My Documents', if
- *   those do not already exist. We put appropriate symbolic links in place for
- *   those, too.
- * - If there is no 'My Documents' directory in $HOME, we let 'My Documents'
- *   point directly to $HOME. We assume the user to be a unix hacker who does not
- *   want wine to create anything anywhere besides the .wine directory. So, if
- *   there already is a 'My Music' directory in $HOME, we symlink the 'My Music'
- *   shell folder to it. But if not, then we check XDG_MUSIC_DIR - "well known"
- *   directory, and try to link to that. If that fails, then we symlink to
- *   $HOME directly. The same holds for 'My Pictures', 'My Videos' etc.
- * - The Desktop shell folder is symlinked to XDG_DESKTOP_DIR. If that does not
- *   exist, then we try '$HOME/Desktop'. If that does not exist, then we leave
- *   it alone.
- * ('My Music',... above in fact means LoadString(IDS_MYMUSIC))
- */
-static void _SHCreateSymbolicLinks(void)
-{
-    static const UINT aidsMyStuff[] = {
-        IDS_MYPICTURES, IDS_MYVIDEOS, IDS_MYMUSIC, IDS_DOWNLOADS, IDS_TEMPLATES
-    };
-    static const WCHAR * const MyOSXStuffW[] = {
-        PicturesW, MoviesW, MusicW, DownloadsW, TemplatesW
-    };
-    static const int acsidlMyStuff[] = {
-        CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_MYMUSIC, CSIDL_DOWNLOADS, CSIDL_TEMPLATES
-    };
-    static const char * const xdg_dirs[] = {
-        "PICTURES", "VIDEOS", "MUSIC", "DOWNLOAD", "TEMPLATES", "DOCUMENTS", "DESKTOP"
-    };
-    static const unsigned int num = ARRAY_SIZE(xdg_dirs);
-    WCHAR wszTempPath[MAX_PATH];
-    char szPersonalTarget[FILENAME_MAX], *pszPersonal;
-    char szMyStuffTarget[FILENAME_MAX], *pszMyStuff;
-    char szDesktopTarget[FILENAME_MAX], *pszDesktop;
-    struct stat statFolder;
-    const char *pszHome;
-    HRESULT hr;
-    char ** xdg_results;
-    char * xdg_desktop_dir;
-    UINT i;
-
-    /* Create all necessary profile sub-dirs up to 'My Documents' and get the unix path. */
-    hr = SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL,
-                          SHGFP_TYPE_DEFAULT, wszTempPath);
-    if (FAILED(hr)) return;
-    pszPersonal = wine_get_unix_file_name(wszTempPath);
-    if (!pszPersonal) return;
-
-    hr = XDG_UserDirLookup(xdg_dirs, num, &xdg_results);
-    if (FAILED(hr)) xdg_results = NULL;
-
-    pszHome = getenv("HOME");
-    if (pszHome && !stat(pszHome, &statFolder) && S_ISDIR(statFolder.st_mode))
-    {
-        while (1)
-        {
-            /* Check if there's already a Wine-specific 'My Documents' folder */
-            strcpy(szPersonalTarget, pszHome);
-            if (_SHAppendToUnixPath(szPersonalTarget, MAKEINTRESOURCEW(IDS_PERSONAL)) &&
-                !stat(szPersonalTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
-            {
-                /* '$HOME/My Documents' exists. Create subfolders for
-                 * 'My Pictures', 'My Videos', 'My Music' etc. or fail silently
-                 * if they already exist.
-                 */
-                for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++)
-                {
-                    strcpy(szMyStuffTarget, szPersonalTarget);
-                    if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
-                        mkdir(szMyStuffTarget, 0777);
-                }
-                break;
-            }
-
-            /* Try to point to the XDG Documents folder */
-            if (xdg_results && xdg_results[num-2] &&
-               !stat(xdg_results[num-2], &statFolder) &&
-               S_ISDIR(statFolder.st_mode))
-            {
-                strcpy(szPersonalTarget, xdg_results[num-2]);
-                break;
-            }
-
-            /* Or the hardcoded / OS X Documents folder */
-            strcpy(szPersonalTarget, pszHome);
-            if (_SHAppendToUnixPath(szPersonalTarget, DocumentsW) &&
-               !stat(szPersonalTarget, &statFolder) &&
-               S_ISDIR(statFolder.st_mode))
-                break;
-
-            /* As a last resort point to $HOME. */
-            strcpy(szPersonalTarget, pszHome);
-            break;
-        }
-
-        /* Replace 'My Documents' directory with a symlink or fail silently if not empty. */
-        remove(pszPersonal);
-        symlink(szPersonalTarget, pszPersonal);
-    }
-    else
-    {
-        /* '$HOME' doesn't exist. Create subdirs for 'My Pictures', 'My Videos',
-         * 'My Music' etc. in '%USERPROFILE%\My Documents' or fail silently if
-         * they already exist. */
-        pszHome = NULL;
-        strcpy(szPersonalTarget, pszPersonal);
-        for (i = 0; i < ARRAY_SIZE(aidsMyStuff); i++) {
-            strcpy(szMyStuffTarget, szPersonalTarget);
-            if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])))
-                mkdir(szMyStuffTarget, 0777);
-        }
-    }
-
-    /* Create symbolic links for 'My Pictures', 'My Videos', 'My Music' etc. */
-    for (i=0; i < ARRAY_SIZE(aidsMyStuff); i++)
-    {
-        /* Create the current 'My Whatever' folder and get its unix path. */
-        hr = SHGetFolderPathW(NULL, acsidlMyStuff[i]|CSIDL_FLAG_CREATE, NULL,
-                              SHGFP_TYPE_DEFAULT, wszTempPath);
-        if (FAILED(hr)) continue;
-
-        pszMyStuff = wine_get_unix_file_name(wszTempPath);
-        if (!pszMyStuff) continue;
-        
-        while (1)
-        {
-            /* Check for the Wine-specific '$HOME/My Documents' subfolder */
-            strcpy(szMyStuffTarget, szPersonalTarget);
-            if (_SHAppendToUnixPath(szMyStuffTarget, MAKEINTRESOURCEW(aidsMyStuff[i])) &&
-                !stat(szMyStuffTarget, &statFolder) && S_ISDIR(statFolder.st_mode))
-                break;
-
-            /* Try the XDG_XXX_DIR folder */
-            if (xdg_results && xdg_results[i])
-            {
-                strcpy(szMyStuffTarget, xdg_results[i]);
-                break;
-            }
-
-            /* Or the OS X folder (these are never localized) */
-            if (pszHome)
-            {
-                strcpy(szMyStuffTarget, pszHome);
-                if (_SHAppendToUnixPath(szMyStuffTarget, MyOSXStuffW[i]) &&
-                    !stat(szMyStuffTarget, &statFolder) &&
-                    S_ISDIR(statFolder.st_mode))
-                    break;
-            }
-
-            /* As a last resort point to the same location as 'My Documents' */
-            strcpy(szMyStuffTarget, szPersonalTarget);
-            break;
-        }
-        remove(pszMyStuff);
-        symlink(szMyStuffTarget, pszMyStuff);
-        heap_free(pszMyStuff);
-    }
-
-    /* Last but not least, the Desktop folder */
-    if (pszHome)
-        strcpy(szDesktopTarget, pszHome);
-    else
-        strcpy(szDesktopTarget, pszPersonal);
-    heap_free(pszPersonal);
-
-    xdg_desktop_dir = xdg_results ? xdg_results[num - 1] : NULL;
-    if (xdg_desktop_dir ||
-        (_SHAppendToUnixPath(szDesktopTarget, DesktopW) &&
-        !stat(szDesktopTarget, &statFolder) && S_ISDIR(statFolder.st_mode)))
-    {
-        hr = SHGetFolderPathW(NULL, CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE, NULL,
-                              SHGFP_TYPE_DEFAULT, wszTempPath);
-        if (SUCCEEDED(hr) && (pszDesktop = wine_get_unix_file_name(wszTempPath))) 
-        {
-            remove(pszDesktop);
-            if (xdg_desktop_dir)
-                symlink(xdg_desktop_dir, pszDesktop);
-            else
-                symlink(szDesktopTarget, pszDesktop);
-            heap_free(pszDesktop);
-        }
-    }
-
-    /* Free resources allocated by XDG_UserDirLookup() */
-    if (xdg_results)
-    {
-        for (i = 0; i < num; i++)
-            heap_free(xdg_results[i]);
-        heap_free(xdg_results);
-    }
-}
-
-/******************************************************************************
  * create_extra_folders  [Internal]
  *
  * Create some extra folders that don't have a standard CSIDL definition.
-- 
2.1.4




More information about the wine-devel mailing list