shell32: Support getting the shell folder path for users other than the current user and the default user.
This commit is contained in:
parent
f761b90801
commit
35d7f70612
|
@ -47,6 +47,7 @@
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "shlwapi.h"
|
#include "shlwapi.h"
|
||||||
#include "xdg.h"
|
#include "xdg.h"
|
||||||
|
#include "sddl.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
@ -1356,6 +1357,39 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LPWSTR _GetUserSidStringFromToken(HANDLE Token)
|
||||||
|
{
|
||||||
|
char InfoBuffer[64];
|
||||||
|
PTOKEN_USER UserInfo;
|
||||||
|
DWORD InfoSize;
|
||||||
|
LPWSTR SidStr;
|
||||||
|
|
||||||
|
UserInfo = (PTOKEN_USER) InfoBuffer;
|
||||||
|
if (! GetTokenInformation(Token, TokenUser, InfoBuffer, sizeof(InfoBuffer),
|
||||||
|
&InfoSize))
|
||||||
|
{
|
||||||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
return NULL;
|
||||||
|
UserInfo = HeapAlloc(GetProcessHeap(), 0, InfoSize);
|
||||||
|
if (UserInfo == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (! GetTokenInformation(Token, TokenUser, UserInfo, InfoSize,
|
||||||
|
&InfoSize))
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, UserInfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ConvertSidToStringSidW(UserInfo->User.Sid, &SidStr))
|
||||||
|
SidStr = NULL;
|
||||||
|
|
||||||
|
if (UserInfo != (PTOKEN_USER) InfoBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, UserInfo);
|
||||||
|
|
||||||
|
return SidStr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Gets the user's path (unexpanded) for the CSIDL with index folder:
|
/* Gets the user's path (unexpanded) for the CSIDL with index folder:
|
||||||
* If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it. Otherwise
|
* If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it. Otherwise
|
||||||
* calls _SHGetUserShellFolderPath for it. Where it looks depends on hToken:
|
* calls _SHGetUserShellFolderPath for it. Where it looks depends on hToken:
|
||||||
|
@ -1378,22 +1412,15 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
|
||||||
if (!pszPath)
|
if (!pszPath)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
/* Only the current user and the default user are supported right now
|
|
||||||
* I'm afraid.
|
|
||||||
* FIXME: should be able to call GetTokenInformation on the token,
|
|
||||||
* then call ConvertSidToStringSidW on it to get the user prefix.
|
|
||||||
* But Wine's registry doesn't store user info by sid, it stores it
|
|
||||||
* by user name (and I don't know how to convert from a token to a
|
|
||||||
* user name).
|
|
||||||
*/
|
|
||||||
if (hToken != NULL && hToken != (HANDLE)-1)
|
|
||||||
{
|
|
||||||
FIXME("unsupported for user other than current or default\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dwFlags & SHGFP_TYPE_DEFAULT)
|
if (dwFlags & SHGFP_TYPE_DEFAULT)
|
||||||
|
{
|
||||||
|
if (hToken != NULL && hToken != (HANDLE)-1)
|
||||||
|
{
|
||||||
|
FIXME("unsupported for user other than current or default\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
hr = _SHGetDefaultValue(folder, pszPath);
|
hr = _SHGetDefaultValue(folder, pszPath);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPCWSTR userPrefix = NULL;
|
LPCWSTR userPrefix = NULL;
|
||||||
|
@ -1404,8 +1431,18 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
|
||||||
hRootKey = HKEY_USERS;
|
hRootKey = HKEY_USERS;
|
||||||
userPrefix = DefaultW;
|
userPrefix = DefaultW;
|
||||||
}
|
}
|
||||||
else /* hToken == NULL, other values disallowed above */
|
else if (hToken == NULL)
|
||||||
hRootKey = HKEY_CURRENT_USER;
|
hRootKey = HKEY_CURRENT_USER;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hRootKey = HKEY_USERS;
|
||||||
|
userPrefix = _GetUserSidStringFromToken(hToken);
|
||||||
|
if (userPrefix == NULL)
|
||||||
|
{
|
||||||
|
hr = E_FAIL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
hr = _SHGetUserShellFolderPath(hRootKey, userPrefix,
|
hr = _SHGetUserShellFolderPath(hRootKey, userPrefix,
|
||||||
CSIDL_Data[folder].szValueName, pszPath);
|
CSIDL_Data[folder].szValueName, pszPath);
|
||||||
if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
|
if (FAILED(hr) && hRootKey != HKEY_LOCAL_MACHINE)
|
||||||
|
@ -1413,7 +1450,10 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
|
||||||
CSIDL_Data[folder].szValueName, pszPath);
|
CSIDL_Data[folder].szValueName, pszPath);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
hr = _SHGetDefaultValue(folder, pszPath);
|
hr = _SHGetDefaultValue(folder, pszPath);
|
||||||
|
if (userPrefix != NULL && userPrefix != DefaultW)
|
||||||
|
LocalFree((HLOCAL) userPrefix);
|
||||||
}
|
}
|
||||||
|
error:
|
||||||
TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
|
TRACE("returning 0x%08x (output path is %s)\n", hr, debugstr_w(pszPath));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue