/* 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 {
* 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)
{
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;
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
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);
/*************************************************************************
* 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:
* 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];
/*************************************************************************
* SHGetFolderPathA [SHELL32.@]
+ *
+ * See SHGetFolderPathW.
*/
HRESULT WINAPI SHGetFolderPathA(
HWND hwndOwner,
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;
/*************************************************************************
* 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]
* 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,