[PATCH] Support getting the shell folder path for users other =

Juan Lang juan.lang at gmail.com
Tue Jan 15 12:24:36 CST 2008


than the current user and=0A=
the default user=0A=
---=0A=
 dlls/shell32/shellpath.c |   95 =
+++++++++++++++++++++++++++++++++++++++-------=0A=
 1 files changed, 80 insertions(+), 15 deletions(-)=0A=
=0A=
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c=0A=
index 5be77d7..a372ca6 100644=0A=
--- a/dlls/shell32/shellpath.c=0A=
+++ b/dlls/shell32/shellpath.c=0A=
@@ -46,6 +46,7 @@ #include "undocshell.h"=0A=
 #include "pidl.h"=0A=
 #include "wine/unicode.h"=0A=
 #include "shlwapi.h"=0A=
+#include "sddl.h"=0A=
 =0A=
 WINE_DEFAULT_DEBUG_CHANNEL(shell);=0A=
 =0A=
@@ -1359,6 +1360,52 @@ static HRESULT _SHGetCurrentVersionPath(=0A=
     return hr;=0A=
 }=0A=
 =0A=
+static PSID _GetUserFromToken(HANDLE Token)=0A=
+{=0A=
+    char InfoBuffer[64];=0A=
+    PTOKEN_USER UserInfo;=0A=
+    DWORD InfoSize;=0A=
+    PSID Sid;=0A=
+    DWORD SidSize;=0A=
+=0A=
+    UserInfo =3D (PTOKEN_USER) InfoBuffer;=0A=
+    if (! GetTokenInformation(Token, TokenUser, InfoBuffer, =
sizeof(InfoBuffer),=0A=
+                              &InfoSize))=0A=
+    {=0A=
+        if (GetLastError() !=3D ERROR_INSUFFICIENT_BUFFER)=0A=
+            return NULL;=0A=
+        UserInfo =3D HeapAlloc(GetProcessHeap(), 0, InfoSize);=0A=
+        if (UserInfo =3D=3D NULL)=0A=
+            return NULL;=0A=
+        if (! GetTokenInformation(Token, TokenUser, UserInfo, InfoSize,=0A=
+                                  &InfoSize))=0A=
+        {=0A=
+            HeapFree(GetProcessHeap(), 0, UserInfo);=0A=
+            return NULL;=0A=
+        }=0A=
+    }=0A=
+=0A=
+    SidSize =3D GetLengthSid(UserInfo->User.Sid);=0A=
+    Sid =3D HeapAlloc(GetProcessHeap(), 0, SidSize);=0A=
+    if (Sid =3D=3D NULL)=0A=
+    {=0A=
+        if (UserInfo !=3D (PTOKEN_USER) InfoBuffer)=0A=
+            HeapFree(GetProcessHeap(), 0, UserInfo);=0A=
+        return NULL;=0A=
+    }=0A=
+=0A=
+    if (! CopySid(SidSize, Sid, UserInfo->User.Sid))=0A=
+    {=0A=
+        HeapFree(GetProcessHeap(), 0, Sid);=0A=
+        Sid =3D NULL;=0A=
+    }=0A=
+=0A=
+    if (UserInfo !=3D (PTOKEN_USER) InfoBuffer)=0A=
+        HeapFree(GetProcessHeap(), 0, UserInfo);=0A=
+=0A=
+    return Sid;=0A=
+}=0A=
+=0A=
 /* Gets the user's path (unexpanded) for the CSIDL with index folder:=0A=
  * If SHGFP_TYPE_DEFAULT is set, calls _SHGetDefaultValue for it.  =
Otherwise=0A=
  * calls _SHGetUserShellFolderPath for it.  Where it looks depends on =
hToken:=0A=
@@ -1381,24 +1428,18 @@ static HRESULT _SHGetUserProfilePath(HAN=0A=
     if (!pszPath)=0A=
         return E_INVALIDARG;=0A=
 =0A=
-    /* Only the current user and the default user are supported right =
now=0A=
-     * I'm afraid.=0A=
-     * FIXME: should be able to call GetTokenInformation on the token,=0A=
-     * then call ConvertSidToStringSidW on it to get the user prefix.=0A=
-     * But Wine's registry doesn't store user info by sid, it stores it=0A=
-     * by user name (and I don't know how to convert from a token to a=0A=
-     * user name).=0A=
-     */=0A=
-    if (hToken !=3D NULL && hToken !=3D (HANDLE)-1)=0A=
-    {=0A=
-        FIXME("unsupported for user other than current or default\n");=0A=
-        return E_FAIL;=0A=
-    }=0A=
-=0A=
     if (dwFlags & SHGFP_TYPE_DEFAULT)=0A=
+    {=0A=
+        if (hToken !=3D NULL && hToken !=3D (HANDLE)-1)=0A=
+        {=0A=
+            FIXME("unsupported for user other than current or =
default\n");=0A=
+            return E_FAIL;=0A=
+        }=0A=
         hr =3D _SHGetDefaultValue(folder, pszPath);=0A=
+    }=0A=
     else=0A=
     {=0A=
+        LPWSTR sidStr =3D NULL;=0A=
         LPCWSTR userPrefix =3D NULL;=0A=
         HKEY hRootKey;=0A=
 =0A=
@@ -1407,8 +1448,30 @@ static HRESULT _SHGetUserProfilePath(HAN=0A=
             hRootKey =3D HKEY_USERS;=0A=
             userPrefix =3D DefaultW;=0A=
         }=0A=
-        else /* hToken =3D=3D NULL, other values disallowed above */=0A=
+        else if (hToken =3D=3D NULL)=0A=
             hRootKey =3D HKEY_CURRENT_USER;=0A=
+        else=0A=
+        {=0A=
+            PSID sid;=0A=
+=0A=
+            hRootKey =3D HKEY_USERS;=0A=
+            if ((sid =3D _GetUserFromToken(hToken)))=0A=
+            {=0A=
+                if (!ConvertSidToStringSidW(sid, &sidStr))=0A=
+                {=0A=
+                    hr =3D HRESULT_FROM_WIN32(GetLastError());=0A=
+                    HeapFree(GetProcessHeap(), 0, sid);=0A=
+                    goto error;=0A=
+                }=0A=
+                userPrefix =3D sidStr;=0A=
+                HeapFree(GetProcessHeap(), 0, sid);=0A=
+            }=0A=
+            else=0A=
+            {=0A=
+                hr =3D E_FAIL;=0A=
+                goto error;=0A=
+            }=0A=
+        }=0A=
         hr =3D _SHGetUserShellFolderPath(hRootKey, userPrefix,=0A=
          CSIDL_Data[folder].szValueName, pszPath);=0A=
         if (FAILED(hr) && hRootKey !=3D HKEY_LOCAL_MACHINE)=0A=
@@ -1416,7 +1479,9 @@ static HRESULT _SHGetUserProfilePath(HAN=0A=
              CSIDL_Data[folder].szValueName, pszPath);=0A=
         if (FAILED(hr))=0A=
             hr =3D _SHGetDefaultValue(folder, pszPath);=0A=
+        LocalFree(sidStr);=0A=
     }=0A=
+error:=0A=
     TRACE("returning 0x%08x (output path is %s)\n", hr, =
debugstr_w(pszPath));=0A=
     return hr;=0A=
 }=0A=
-- =0A=
1.4.1=0A=
=0A=

------=_NextPart_000_000C_01C85DB3.A326B050--




More information about the wine-patches mailing list