@@ -51,15 +51,16 @@ mod impl_ {
51
51
use windows:: {
52
52
core:: { Error , PCWSTR } ,
53
53
Win32 :: {
54
- Foundation :: { HANDLE , PSID } ,
54
+ Foundation :: { CloseHandle , BOOL , HANDLE , PSID } ,
55
55
Security :: {
56
56
Authorization :: { GetNamedSecurityInfoW , SE_FILE_OBJECT } ,
57
- EqualSid , GetTokenInformation , TokenOwner , OWNER_SECURITY_INFORMATION , PSECURITY_DESCRIPTOR ,
58
- TOKEN_OWNER , TOKEN_QUERY ,
57
+ CheckTokenMembership , EqualSid , GetTokenInformation , IsWellKnownSid , TokenOwner ,
58
+ WinBuiltinAdministratorsSid , OWNER_SECURITY_INFORMATION , PSECURITY_DESCRIPTOR , TOKEN_OWNER ,
59
+ TOKEN_QUERY ,
59
60
} ,
60
61
System :: {
61
62
Memory :: LocalFree ,
62
- Threading :: { GetCurrentProcess , OpenProcessToken } ,
63
+ Threading :: { GetCurrentProcess , GetCurrentThread , OpenProcessToken , OpenThreadToken } ,
63
64
} ,
64
65
} ,
65
66
} ;
@@ -68,6 +69,13 @@ mod impl_ {
68
69
let mut is_owned = false ;
69
70
let path = path. as_ref ( ) ;
70
71
72
+ // Home is not actually owned by the corresponding user
73
+ // but it can be considered de-facto owned by the user
74
+ // Ignore errors here and just do the regular checks below
75
+ if Some ( path) == dirs:: home_dir ( ) . as_deref ( ) {
76
+ return Ok ( true ) ;
77
+ }
78
+
71
79
#[ allow( unsafe_code) ]
72
80
unsafe {
73
81
let mut folder_owner = PSID :: default ( ) ;
@@ -86,7 +94,10 @@ mod impl_ {
86
94
// Workaround for https://github.com/microsoft/win32metadata/issues/884
87
95
if result. is_ok ( ) {
88
96
let mut token = HANDLE :: default ( ) ;
89
- OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & mut token) . ok ( ) ?;
97
+ // Use the current thread token if possible, otherwise open the process token
98
+ OpenThreadToken ( GetCurrentThread ( ) , TOKEN_QUERY , true , & mut token)
99
+ . ok ( )
100
+ . or_else ( |_| OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & mut token) . ok ( ) ) ?;
90
101
91
102
let mut buffer_size = 0 ;
92
103
let mut buffer = Vec :: < u8 > :: new ( ) ;
@@ -106,6 +117,16 @@ mod impl_ {
106
117
let token_owner = ( * token_owner) . Owner ;
107
118
108
119
is_owned = EqualSid ( folder_owner, token_owner) . as_bool ( ) ;
120
+
121
+ // Admin-group owned folders are considered owned by the current user, if they are in the admin group
122
+ if !is_owned && IsWellKnownSid ( token_owner, WinBuiltinAdministratorsSid ) . as_bool ( ) {
123
+ let mut is_member = BOOL :: default ( ) ;
124
+ // TODO: re-use the handle
125
+ match CheckTokenMembership ( HANDLE :: default ( ) , token_owner, & mut is_member) . ok ( ) {
126
+ Err ( e) => err_msg = Some ( format ! ( "Couldn't check if user is an administrator: {}" , e) ) ,
127
+ Ok ( ( ) ) => is_owned = is_member. as_bool ( ) ,
128
+ }
129
+ }
109
130
} else {
110
131
err_msg = format ! (
111
132
"Couldn't get actual token information for current process with err: {}" ,
@@ -120,6 +141,7 @@ mod impl_ {
120
141
)
121
142
. into ( ) ;
122
143
}
144
+ CloseHandle ( token) ;
123
145
} else {
124
146
err_msg = format ! (
125
147
"Couldn't get security information for path '{}' with err {}" ,
0 commit comments