Sync to Wine-0_9_3:
[reactos.git] / reactos / lib / shell32 / shellpath.c
index 72f3589..fe6aef1 100644 (file)
@@ -805,7 +805,7 @@ static const WCHAR szSHUserFolders[] = {'S','o','f','t','w','a','r','e','\\','M'
 /* This defaults to L"Documents and Settings" on Windows 2000/XP, but we're
  * acting more Windows 9x-like for now.
  */
-static const WCHAR szDefaultProfileDirW[] = {'w','i','n','d','o','w','s','\\','p','r','o','f','i','l','e','s','\0'};
+static const WCHAR szDefaultProfileDirW[] = {'p','r','o','f','i','l','e','s','\0'};
 static const WCHAR AllUsersW[] = {'A','l','l',' ','U','s','e','r','s','\0'};
 
 typedef enum _CSIDL_Type {
@@ -1240,13 +1240,6 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
  *   CSIDL_Type_AllUsers: %ALLUSERSPROFILE%
  *   CSIDL_Type_CurrVer:  %SystemDrive%
  *   (Others might make sense too, but as yet are unneeded.)
- * FIXME: there are two special cases for the default value:
- * - the "My Documents" (CSIDL_PERSONAL) entry should be $HOME
- * - the CSIDL_DESKTOP and CSIDL_DESKTOPDIRECTORY (which have the same path)
- *   should be $HOME/Desktop if it exists
- * But, $HOME doesn't seem to be inherited into the Wine environment.  I could
- * use getenv, but this returns me a UNIX path, which may or may not be
- * reachable from any currently mounted DOS drives.
  */
 static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
 {
@@ -1261,11 +1254,59 @@ static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
     if (!pszPath)
         return E_INVALIDARG;
 
+    /* Try special cases first */
+    hr = E_FAIL;
+    switch (folder)
+    {
+        case CSIDL_PERSONAL:
+        case CSIDL_MYMUSIC:
+        case CSIDL_MYPICTURES:
+        case CSIDL_MYVIDEO:
+        {
+            const char *home = getenv("HOME");
+
+            /* special case for "My Documents", map to $HOME */
+            if (home)
+            {
+                WCHAR homeW[MAX_PATH];
+
+                MultiByteToWideChar(CP_ACP, 0, home, -1, homeW, MAX_PATH);
+                if (GetFullPathNameW(homeW, MAX_PATH, pszPath, NULL) != 0 &&
+                 PathIsDirectoryW(pszPath))
+                    hr = S_OK;
+            }
+            break;
+        }
+        case CSIDL_DESKTOP:
+        case CSIDL_DESKTOPDIRECTORY:
+        {
+            const char *home = getenv("HOME");
+
+            /* special case for Desktop, map to $HOME/Desktop if it exists */
+            if (home)
+            {
+                WCHAR desktopW[MAX_PATH];
+
+                MultiByteToWideChar(CP_ACP, 0, home, -1, desktopW, MAX_PATH);
+                PathAppendW(desktopW, DesktopW);
+                if (GetFullPathNameW(desktopW, MAX_PATH, pszPath, NULL) != 0 &&
+                 PathIsDirectoryW(pszPath))
+                    hr = S_OK;
+            }
+            break;
+        }
+    }
+    if (SUCCEEDED(hr))
+        return hr;
+
+    /* Either the folder was unhandled, or a suitable default wasn't found,
+     * so use one of the resource-based defaults
+     */
     if (CSIDL_Data[folder].szDefaultPath &&
      IS_INTRESOURCE(CSIDL_Data[folder].szDefaultPath))
     {
         if (LoadStringW(shell32_hInstance,
-         (UINT)CSIDL_Data[folder].szDefaultPath, resourcePath, MAX_PATH))
+         LOWORD(CSIDL_Data[folder].szDefaultPath), resourcePath, MAX_PATH))
         {
             hr = S_OK;
             pDefaultPath = resourcePath;
@@ -1457,57 +1498,6 @@ static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE folder,
     return hr;
 }
 
-static HRESULT _SHOpenProfilesKey(PHKEY pKey)
-{
-    LONG lRet;
-    DWORD disp;
-
-    lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, NULL, 0,
-     KEY_ALL_ACCESS, NULL, pKey, &disp);
-    return HRESULT_FROM_WIN32(lRet);
-}
-
-/* Reads the value named szValueName from the key profilesKey (assumed to be
- * opened by _SHOpenProfilesKey) into szValue, which is assumed to be MAX_PATH
- * WCHARs in length.  If it doesn't exist, returns szDefault (and saves
- * szDefault to the registry).
- */
-static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName,
- LPWSTR szValue, LPCWSTR szDefault)
-{
-    HRESULT hr;
-    DWORD type, dwPathLen = MAX_PATH * sizeof(WCHAR);
-    LONG lRet;
-
-    TRACE("%p,%s,%p,%s\n", profilesKey, debugstr_w(szValueName), szValue,
-     debugstr_w(szDefault));
-    lRet = RegQueryValueExW(profilesKey, szValueName, NULL, &type,
-     (LPBYTE)szValue, &dwPathLen);
-    if (!lRet && (type == REG_SZ || type == REG_EXPAND_SZ) && dwPathLen
-     && *szValue)
-    {
-        dwPathLen /= sizeof(WCHAR);
-        szValue[dwPathLen] = '\0';
-        hr = S_OK;
-    }
-    else
-    {
-        /* Missing or invalid value, set a default */
-        lstrcpynW(szValue, szDefault, MAX_PATH);
-        TRACE("Setting missing value %s to %s\n", debugstr_w(szValueName),
-                                                  debugstr_w(szValue));
-        lRet = RegSetValueExW(profilesKey, szValueName, 0, REG_EXPAND_SZ,
-                              (LPBYTE)szValue,
-                              (strlenW(szValue) + 1) * sizeof(WCHAR));
-        if (lRet)
-            hr = HRESULT_FROM_WIN32(lRet);
-        else
-            hr = S_OK;
-    }
-    TRACE("returning 0x%08lx (output value is %s)\n", hr, debugstr_w(szValue));
-    return hr;
-}
-
 /* From the original Wine source:
  *
  * Attempts to expand environment variables from szSrc into szDest, which is
@@ -1529,7 +1519,7 @@ static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR szValueName,
 static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest)
 {
     HRESULT hr = S_OK;
-    WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 };
+    WCHAR szTemp[MAX_PATH];
 
     TRACE("%s, %p\n", debugstr_w(szSrc), szDest);
 
@@ -1572,8 +1562,14 @@ end:
 /*************************************************************************
  * SHGetFolderPathW                    [SHELL32.@]
  *
+ * Convert nFolder to path.  
+ *
+ * RETURNS
+ *  Success: S_OK
+ *  Failure: standard HRESULT error codes.
+ *
  * NOTES
- * Converts nFolder to path.  Most values can be overridden in either
+ * Most values can be overridden in either
  * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
  * or in the same location in HKLM.
  * The registry usage is explained by the following tech note:
@@ -1587,13 +1583,13 @@ end:
  * http://www.microsoft.com/windows2000/techinfo/reskit/en-us/default.asp?url=/windows2000/techinfo/reskit/en-us/regentry/36276.asp
  * the HKCU paths take precedence over the HKLM paths.
  *
- **********************************************************************/
+ */
 HRESULT WINAPI SHGetFolderPathW(
-       HWND hwndOwner,
-       int nFolder,
-       HANDLE hToken,
-       DWORD dwFlags,
-       LPWSTR pszPath)
+       HWND hwndOwner,    /* [I] owner window */
+       int nFolder,       /* [I] CSIDL identifying the folder */
+       HANDLE hToken,     /* [I] access token */
+       DWORD dwFlags,     /* [I] which path to return */
+       LPWSTR pszPath)    /* [O] converted path */
 {
     HRESULT    hr;
     WCHAR      szBuildPath[MAX_PATH], szTemp[MAX_PATH];
@@ -1699,6 +1695,8 @@ end:
 
 /*************************************************************************
  * SHGetFolderPathA                    [SHELL32.@]
+ *
+ * See SHGetFolderPathW.
  */
 HRESULT WINAPI SHGetFolderPathA(
        HWND hwndOwner,
@@ -1805,16 +1803,20 @@ static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
      CSIDL_PROGRAMS,
      CSIDL_PERSONAL,
      CSIDL_FAVORITES,
+     CSIDL_APPDATA,
      CSIDL_STARTUP,
      CSIDL_RECENT,
      CSIDL_SENDTO,
      CSIDL_STARTMENU,
+     CSIDL_MYMUSIC,
+     CSIDL_MYVIDEO,
      CSIDL_DESKTOPDIRECTORY,
      CSIDL_NETHOOD,
      CSIDL_TEMPLATES,
      CSIDL_PRINTHOOD,
      CSIDL_COOKIES,
      CSIDL_HISTORY,
+     CSIDL_MYPICTURES
     };
     WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
     LPCWSTR pUserShellFolderPath, pShellFolderPath;
@@ -1937,11 +1939,7 @@ BOOL WINAPI SHGetSpecialFolderPathAW (
 /*************************************************************************
  * SHGetFolderLocation [SHELL32.@]
  *
- * NOTES
  * Gets the folder locations from the registry and creates a pidl.
- * Creates missing reg keys and directories.
- * Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
- * virtual folders that are handled here.
  *
  * PARAMS
  *   hwndOwner  [I]
@@ -1951,7 +1949,14 @@ BOOL WINAPI SHGetSpecialFolderPathAW (
  *   dwReserved [I] must be zero
  *   ppidl      [O] PIDL of a special folder
  *
+ * RETURNS
+ *  Success: S_OK
+ *  Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
+ *
  * NOTES
+ *  Creates missing reg keys and directories.
+ *  Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
+ *  virtual folders that are handled here.
  */
 HRESULT WINAPI SHGetFolderLocation(
        HWND hwndOwner,