[take 2] shell32: Check if token references the current user

ge at gse.nl ge at gse.nl
Thu Jan 10 14:01:17 CST 2008


Incorporates feedback by Juan Lang

Changelog:
  Ge van Geldorp <ge at thinstall.com>
  Check if token references the current user
  Fixes bug 10905

---
 dlls/shell32/shellpath.c |   99 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
index 5be77d7..c1f5e2a 100644
--- a/dlls/shell32/shellpath.c
+++ b/dlls/shell32/shellpath.c
@@ -1359,6 +1359,100 @@ static HRESULT _SHGetCurrentVersionPath(DWORD dwFlags, BYTE folder,
     return hr;
 }
 
+static PSID _GetUserFromToken(HANDLE Token)
+{
+    char InfoBuffer[64];
+    PTOKEN_USER UserInfo;
+    DWORD InfoSize;
+    PSID Sid;
+    DWORD SidSize;
+
+    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;
+        }
+    }
+
+    SidSize = GetLengthSid(UserInfo->User.Sid);
+    Sid = HeapAlloc(GetProcessHeap(), 0, SidSize);
+    if (Sid == NULL)
+    {
+        if (UserInfo != (PTOKEN_USER) InfoBuffer)
+            HeapFree(GetProcessHeap(), 0, UserInfo);
+        return NULL;
+    }
+
+    if (! CopySid(SidSize, Sid, UserInfo->User.Sid))
+    {
+        HeapFree(GetProcessHeap(), 0, Sid);
+        Sid = NULL;
+    }
+
+    if (UserInfo != (PTOKEN_USER) InfoBuffer)
+        HeapFree(GetProcessHeap(), 0, UserInfo);
+
+    return Sid;
+}
+
+/*
+ * Return TRUE if the token references the currently logged in user
+ */
+BOOL _IsCurrentUserToken(HANDLE hToken)
+{
+    PSID UserFromToken;
+    BOOL IsCurrentUser;
+
+    if (hToken == NULL)
+        return TRUE;
+    if (hToken == (HANDLE) -1)
+        return FALSE;
+
+    IsCurrentUser = FALSE;
+    UserFromToken = _GetUserFromToken(hToken);
+    if (UserFromToken != NULL)
+    {
+        HANDLE ProcessToken;
+        if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
+                             &ProcessToken))
+        {
+            PSID CurrentUser;
+            CurrentUser = _GetUserFromToken(ProcessToken);
+            if (CurrentUser != NULL)
+            {
+                if (EqualSid(CurrentUser, UserFromToken))
+                {
+                    TRACE("Token is for current user\n");
+                    IsCurrentUser = TRUE;
+                }
+                HeapFree(GetProcessHeap(), 0, CurrentUser);
+            }
+            else
+                ERR("Failed to get current user sid, error %d\n",
+                    GetLastError());
+            CloseHandle(ProcessToken);
+        }
+        else
+            ERR("Failed to open process token, error %d\n", GetLastError());
+        HeapFree(GetProcessHeap(), 0, UserFromToken);
+    }
+    else
+        ERR("Failed to get user sid from token, error %d\n",
+            GetLastError());
+
+    return IsCurrentUser;
+}
+
 /* Gets the user's path (unexpanded) for the CSIDL with index folder:
  * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it.  Otherwise
  * calls _SHGetUserShellFolderPath for it.  Where it looks depends on hToken:
@@ -1382,14 +1476,15 @@ static HRESULT _SHGetUserProfilePath(HANDLE hToken, DWORD dwFlags, BYTE folder,
         return E_INVALIDARG;
 
     /* Only the current user and the default user are supported right now
-     * I'm afraid.
+     * I'm afraid. We do handle the case where the token references the
+     * current user.
      * 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)
+    if (hToken != NULL && hToken != (HANDLE)-1 && ! _IsCurrentUserToken(hToken))
     {
         FIXME("unsupported for user other than current or default\n");
         return E_FAIL;
-- 
1.5.2.4




More information about the wine-patches mailing list