https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2afb483a9e1af19289a51…
commit 2afb483a9e1af19289a51f22000eaaa6d8d8f333
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Jun 30 17:43:08 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sat Jun 30 18:20:08 2018 +0200
[SHELL32] Shell Profile Folders fixes.
- Fix a regression introduced in r65415 (1795a3bf) where the directory
paths stored in "Windows\CurrentVersion\Explorer\User Shell Folders"
were stored in expanded format instead of in unexpanded format:
_SHGetDefaultValue() *MUST* return unexpanded paths by design!!
- Augment _SHExpandEnvironmentStrings() and _SHGetUserShellFolderPath()
to take a user token handle to be able to correctly resolve/expand
user-specific directory paths.
- Fix _SHExpandEnvironmentStrings() so that it always retrieve the
correct current user / all-users directory paths by calling userenv
functions, instead of hardcoding a broken logic. As a result this
removes the "C:\Documents and Settings\SYSTEM" ghost directory we got
during ReactOS installation.
- Delimit the changes with respect to Wine by #if(n)def __REACTOS__ .
---
dll/win32/shell32/wine/shellpath.c | 131 ++++++++++++++++++++++++++++++++-----
1 file changed, 115 insertions(+), 16 deletions(-)
diff --git a/dll/win32/shell32/wine/shellpath.c b/dll/win32/shell32/wine/shellpath.c
index a6f5d63741..2637c179d5 100644
--- a/dll/win32/shell32/wine/shellpath.c
+++ b/dll/win32/shell32/wine/shellpath.c
@@ -41,6 +41,8 @@
#include <wine/debug.h>
#include <wine/unicode.h>
+#include <shlwapi_undoc.h>
+
#include <userenv.h>
#include "pidl.h"
@@ -624,9 +626,11 @@ static const WCHAR DefaultW[] =
{'.','D','e','f','a','u','l','t','\0'};
static const WCHAR AllUsersProfileW[] =
{'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%','\0'};
static const WCHAR UserProfileW[] =
{'%','U','S','E','R','P','R','O','F','I','L','E','%','\0'};
static const WCHAR SystemDriveW[] =
{'%','S','y','s','t','e','m','D','r','i','v','e','%','\0'};
+#ifndef __REACTOS__
static const WCHAR ProfileListW[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','
','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','r','o','f','i','l','e','L','i','s','t',0};
static const WCHAR ProfilesDirectoryW[] =
{'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0};
static const WCHAR AllUsersProfileValueW[] =
{'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e','\0'};
+#endif
static const WCHAR szSHFolders[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','S','h','e','l','l','
','F','o','l','d','e','r','s','\0'};
static const WCHAR szSHUserFolders[] =
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','U','s','e','r','
','S','h','e','l','l','
','F','o','l','d','e','r','s','\0'};
static const WCHAR szDefaultProfileDirW[] =
{'u','s','e','r','s',0};
@@ -1396,7 +1400,11 @@ static const CSIDL_DATA CSIDL_Data[] =
#endif
};
+#ifndef __REACTOS__
static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest);
+#else
+static HRESULT _SHExpandEnvironmentStrings(HANDLE hToken, LPCWSTR szSrc, LPWSTR szDest,
DWORD cchDest);
+#endif
/* Gets the value named value from the registry key
* rootKey\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
@@ -1407,7 +1415,11 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest);
* Returns successful error code if the value was retrieved from the registry,
* and a failure otherwise.
*/
+#ifndef __REACTOS__
static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR userPrefix,
+#else
+static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, HANDLE hToken, LPCWSTR
userPrefix,
+#endif
LPCWSTR value, LPWSTR path)
{
HRESULT hr;
@@ -1459,7 +1471,11 @@ static HRESULT _SHGetUserShellFolderPath(HKEY rootKey, LPCWSTR
userPrefix,
{
WCHAR szTemp[MAX_PATH];
+#ifndef __REACTOS__
_SHExpandEnvironmentStrings(path, szTemp);
+#else
+ _SHExpandEnvironmentStrings(hToken, path, szTemp, _countof(szTemp));
+#endif
lstrcpynW(path, szTemp, MAX_PATH);
}
ret = RegSetValueExW(shellFolderKey, value, 0, REG_SZ, (LPBYTE)path,
@@ -1512,9 +1528,12 @@ BOOL _SHGetUserProfileDirectoryW(HANDLE hToken, LPWSTR szPath,
LPDWORD lpcchPath
* CSIDL_Type_CurrVer: %SystemDrive%
* (Others might make sense too, but as yet are unneeded.)
*/
+#ifndef __REACTOS__
+static HRESULT _SHGetDefaultValue(BYTE folder, LPWSTR pszPath)
+#else
static HRESULT _SHGetDefaultValue(HANDLE hToken, BYTE folder, LPWSTR pszPath)
+#endif
{
- DWORD cchSize;
HRESULT hr;
WCHAR resourcePath[MAX_PATH];
@@ -1525,6 +1544,13 @@ static HRESULT _SHGetDefaultValue(HANDLE hToken, BYTE folder,
LPWSTR pszPath)
if (!pszPath)
return E_INVALIDARG;
+#ifdef __REACTOS__
+ if (hToken != NULL && hToken != (HANDLE)-1)
+ {
+ FIXME("unsupported for user other than current or default\n");
+ }
+#endif
+
if (!is_win64)
{
BOOL is_wow64;
@@ -1546,21 +1572,17 @@ static HRESULT _SHGetDefaultValue(HANDLE hToken, BYTE folder,
LPWSTR pszPath)
switch (CSIDL_Data[folder].type)
{
- case CSIDL_Type_User:
- cchSize = MAX_PATH;
- if (!_SHGetUserProfileDirectoryW(hToken, pszPath, &cchSize))
- return HRESULT_FROM_WIN32(GetLastError());
- break;
- case CSIDL_Type_AllUsers:
- cchSize = MAX_PATH;
- if (!GetAllUsersProfileDirectoryW(pszPath, &cchSize))
- return HRESULT_FROM_WIN32(GetLastError());
- break;
- case CSIDL_Type_CurrVer:
- strcpyW(pszPath, SystemDriveW);
- break;
- default:
- ; /* no corresponding env. var, do nothing */
+ case CSIDL_Type_User:
+ strcpyW(pszPath, UserProfileW);
+ break;
+ case CSIDL_Type_AllUsers:
+ strcpyW(pszPath, AllUsersProfileW);
+ break;
+ case CSIDL_Type_CurrVer:
+ strcpyW(pszPath, SystemDriveW);
+ break;
+ default:
+ ; /* no corresponding env. var, do nothing */
}
hr = S_OK;
@@ -1610,7 +1632,11 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE
folder,
return E_INVALIDARG;
if (dwFlags & SHGFP_TYPE_DEFAULT)
+#ifndef __REACTOS__
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
hr = _SHGetDefaultValue(NULL, folder, pszPath);
+#endif
else
{
HKEY hKey;
@@ -1625,7 +1651,11 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE
folder,
&dwType, (LPBYTE)pszPath, &dwPathLen) ||
(dwType != REG_SZ && dwType != REG_EXPAND_SZ))
{
+#ifndef __REACTOS__
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
hr = _SHGetDefaultValue(NULL, folder, pszPath);
+#endif
dwType = REG_EXPAND_SZ;
switch (folder)
{
@@ -1715,7 +1745,11 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags,
BYTE folder,
if (dwFlags & SHGFP_TYPE_DEFAULT)
{
+#ifndef __REACTOS__
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
hr = _SHGetDefaultValue(hToken, folder, pszPath);
+#endif
}
else
{
@@ -1748,11 +1782,19 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags,
BYTE folder,
szValueName = &buffer[0];
}
+#ifndef __REACTOS__
hr = _SHGetUserShellFolderPath(hRootKey, userPrefix, szValueName, pszPath);
if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, szValueName,
pszPath);
+ if (FAILED(hr))
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
+ hr = _SHGetUserShellFolderPath(hRootKey, hToken, userPrefix, szValueName,
pszPath);
+ if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
+ hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, hToken, NULL, szValueName,
pszPath);
if (FAILED(hr))
hr = _SHGetDefaultValue(hToken, folder, pszPath);
+#endif
if (userPrefix != NULL && userPrefix != DefaultW)
LocalFree((HLOCAL) userPrefix);
}
@@ -1781,18 +1823,31 @@ static HRESULT _SHGetAllUsersProfilePath(DWORD dwFlags, BYTE
folder,
return E_INVALIDARG;
if (dwFlags & SHGFP_TYPE_DEFAULT)
+#ifndef __REACTOS__
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
hr = _SHGetDefaultValue(NULL, folder, pszPath);
+#endif
else
{
+#ifndef __REACTOS__
hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL,
+#else
+ hr = _SHGetUserShellFolderPath(HKEY_LOCAL_MACHINE, NULL, NULL,
+#endif
CSIDL_Data[folder].szValueName, pszPath);
if (FAILED(hr))
+#ifndef __REACTOS__
+ hr = _SHGetDefaultValue(folder, pszPath);
+#else
hr = _SHGetDefaultValue(NULL, folder, pszPath);
+#endif
}
TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
return hr;
}
+#ifndef __REACTOS__
static HRESULT _SHOpenProfilesKey(PHKEY pKey)
{
LONG lRet;
@@ -1843,6 +1898,7 @@ static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR
szValueName,
TRACE("returning 0x%08x (output value is %s)\n", hr, debugstr_w(szValue));
return hr;
}
+#endif
/* Attempts to expand environment variables from szSrc into szDest, which is
* assumed to be MAX_PATH characters in length. Before referring to the
@@ -1856,11 +1912,19 @@ static HRESULT _SHGetProfilesValue(HKEY profilesKey, LPCWSTR
szValueName,
* If one of the directly handled environment variables is expanded, only
* expands a single variable, and only in the beginning of szSrc.
*/
+#ifndef __REACTOS__
static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR szDest)
+#else
+static HRESULT _SHExpandEnvironmentStrings(HANDLE hToken, LPCWSTR szSrc, LPWSTR szDest,
DWORD cchDest)
+#endif
{
HRESULT hr;
+#ifndef __REACTOS__
WCHAR szTemp[MAX_PATH], szProfilesPrefix[MAX_PATH] = { 0 };
HKEY key = NULL;
+#else
+ WCHAR szTemp[MAX_PATH];
+#endif
TRACE("%s, %p\n", debugstr_w(szSrc), szDest);
@@ -1873,6 +1937,7 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest)
hr = S_OK;
goto end;
}
+#ifndef __REACTOS__
/* Get the profile prefix, we'll probably be needing it */
hr = _SHOpenProfilesKey(&key);
if (SUCCEEDED(hr))
@@ -1886,6 +1951,9 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest)
hr = _SHGetProfilesValue(key, ProfilesDirectoryW, szProfilesPrefix, def_val );
}
+#else
+ hr = S_OK;
+#endif
*szDest = 0;
strcpyW(szTemp, szSrc);
@@ -1893,27 +1961,44 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest)
{
if (!strncmpiW(szTemp, AllUsersProfileW, strlenW(AllUsersProfileW)))
{
+#ifndef __REACTOS__
WCHAR szAllUsers[MAX_PATH];
strcpyW(szDest, szProfilesPrefix);
hr = _SHGetProfilesValue(key, AllUsersProfileValueW,
szAllUsers, AllUsersW);
PathAppendW(szDest, szAllUsers);
+#else
+ DWORD cchSize = cchDest;
+ if (!GetAllUsersProfileDirectoryW(szDest, &cchSize))
+ return HRESULT_FROM_WIN32(GetLastError());
+#endif
PathAppendW(szDest, szTemp + strlenW(AllUsersProfileW));
}
else if (!strncmpiW(szTemp, UserProfileW, strlenW(UserProfileW)))
{
+#ifndef __REACTOS__
WCHAR userName[MAX_PATH];
DWORD userLen = MAX_PATH;
strcpyW(szDest, szProfilesPrefix);
GetUserNameW(userName, &userLen);
PathAppendW(szDest, userName);
+#else
+ DWORD cchSize = cchDest;
+ if (!_SHGetUserProfileDirectoryW(hToken, szDest, &cchSize))
+ return HRESULT_FROM_WIN32(GetLastError());
+#endif
PathAppendW(szDest, szTemp + strlenW(UserProfileW));
}
else if (!strncmpiW(szTemp, SystemDriveW, strlenW(SystemDriveW)))
{
+#ifndef __REACTOS__
GetSystemDirectoryW(szDest, MAX_PATH);
+#else
+ if (!GetSystemDirectoryW(szDest, cchDest))
+ return HRESULT_FROM_WIN32(GetLastError());
+#endif
if (szDest[1] != ':')
{
FIXME("non-drive system paths unsupported\n");
@@ -1927,9 +2012,17 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest)
}
else
{
+#ifndef __REACTOS__
DWORD ret = ExpandEnvironmentStringsW(szSrc, szDest, MAX_PATH);
+#else
+ DWORD ret = SHExpandEnvironmentStringsForUserW(hToken, szSrc, szDest,
cchDest);
+#endif
+#ifndef __REACTOS__
if (ret > MAX_PATH)
+#else
+ if (ret > cchDest)
+#endif
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
else if (ret == 0)
hr = HRESULT_FROM_WIN32(GetLastError());
@@ -1945,8 +2038,10 @@ static HRESULT _SHExpandEnvironmentStrings(LPCWSTR szSrc, LPWSTR
szDest)
}
}
end:
+#ifndef __REACTOS__
if (key)
RegCloseKey(key);
+#endif
TRACE("returning 0x%08x (input was %s, output is %s)\n", hr,
debugstr_w(szSrc), debugstr_w(szDest));
return hr;
@@ -2122,7 +2217,11 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
/* Expand environment strings if necessary */
if (*szTemp == '%')
+#ifndef __REACTOS__
hr = _SHExpandEnvironmentStrings(szTemp, szBuildPath);
+#else
+ hr = _SHExpandEnvironmentStrings(hToken, szTemp, szBuildPath,
_countof(szBuildPath));
+#endif
else
strcpyW(szBuildPath, szTemp);