mirror of
https://github.com/reactos/reactos.git
synced 2024-12-01 15:33:31 +08:00
[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__ .
This commit is contained in:
parent
6abc9f5b5a
commit
2afb483a9e
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user