1+ #![ allow( dead_code) ]
2+ #![ cfg( windows) ]
3+
4+ use std:: ptr;
5+ use std:: ffi:: c_void;
6+ use std:: mem:: { size_of, zeroed} ;
7+ use std:: os:: raw:: c_ulong;
8+
9+ #[ link( name = "advapi32" ) ]
10+ unsafe extern "system" {
11+ fn OpenProcessToken ( process : * mut c_void , access : c_ulong , token : * mut * mut c_void ) -> i32 ;
12+ fn GetTokenInformation (
13+ token_handle : * mut c_void ,
14+ token_info_class : c_ulong ,
15+ token_info : * mut c_void ,
16+ token_info_length : c_ulong ,
17+ return_length : * mut c_ulong ,
18+ ) -> i32 ;
19+ fn GetCurrentProcess ( ) -> * mut c_void ;
20+ fn CloseHandle ( handle : * mut c_void ) -> i32 ;
21+ }
22+
23+ const TOKEN_QUERY : c_ulong = 0x0008 ;
24+ const TOKEN_ELEVATION : c_ulong = 20 ;
25+
26+ #[ repr( C ) ]
27+ struct TokenElevation {
28+ token_is_elevated : c_ulong ,
29+ }
30+
31+ /// A safe wrapper around a Windows access token handle.
32+ struct AccessToken {
33+ handle : * mut c_void ,
34+ }
35+
36+ impl AccessToken {
37+ /// Opens the access token for the current process.
38+ fn open ( ) -> Option < Self > {
39+ let process = unsafe { GetCurrentProcess ( ) } ;
40+ let mut token_handle: * mut c_void = ptr:: null_mut ( ) ;
41+
42+ let success = unsafe { OpenProcessToken ( process, TOKEN_QUERY , & mut token_handle) } ;
43+ if success == 0 {
44+ return None ;
45+ }
46+
47+ Some ( Self { handle : token_handle } )
48+ }
49+
50+ /// Checks if the token is elevated (i.e., running as an administrator).
51+ fn is_elevated ( & self ) -> bool {
52+ let mut elevation: TokenElevation = unsafe { zeroed ( ) } ;
53+ let mut return_length: c_ulong = 0 ;
54+
55+ let success = unsafe {
56+ GetTokenInformation (
57+ self . handle ,
58+ TOKEN_ELEVATION ,
59+ & mut elevation as * mut _ as * mut c_void ,
60+ size_of :: < TokenElevation > ( ) as c_ulong ,
61+ & mut return_length,
62+ )
63+ } ;
64+
65+ success != 0 && elevation. token_is_elevated != 0
66+ }
67+ }
68+
69+ impl Drop for AccessToken {
70+ /// Ensures the token handle is always closed properly.
71+ fn drop ( & mut self ) {
72+ unsafe { CloseHandle ( self . handle ) } ;
73+ }
74+ }
75+
76+ /// Safe function to check if the user is an administrator.
77+ pub fn is_admin ( ) -> bool {
78+ if let Some ( token) = AccessToken :: open ( ) {
79+ token. is_elevated ( )
80+ } else {
81+ false
82+ }
83+ }
0 commit comments