https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2afb483a9e1af19289a51f...
commit 2afb483a9e1af19289a51f22000eaaa6d8d8f333 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Sat Jun 30 17:43:08 2018 +0200 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@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);