@@ -62,6 +62,62 @@ def hasUiAccess():
6262 finally :
6363 ctypes .windll .kernel32 .CloseHandle (token )
6464
65+ #: Value from the TOKEN_INFORMATION_CLASS enumeration:
66+ #: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_information_class
67+ #: When calling The Win32 GetTokenInformation function, the buffer receives a TOKEN_ORIGIN value.
68+ #: If the token resulted from a logon that used explicit credentials, such as passing a name, domain,
69+ #: and password to the LogonUser function, then the TOKEN_ORIGIN structure will contain the ID of
70+ #: the logon session that created it.
71+ #: If the token resulted from network authentication, then this value will be zero.
72+ TOKEN_ORIGIN = 17 # TokenOrigin in winnt.h
73+
74+
75+ class TokenOrigin (ctypes .Structure ):
76+ """TOKEN_ORIGIN structure: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_origin
77+ This structure is used in calls to the Win32 GetTokenInformation function.
78+ """
79+ _fields_ = [
80+ ("originatingLogonSession" , ctypes .c_ulonglong ) # OriginatingLogonSession in C structure
81+ ]
82+
83+
84+ def getProcessLogonSessionId (processHandle : int ) -> int :
85+ """
86+ Retrieves the ID of the logon session that created the process that the given processHandle belongs to.
87+ The function calls several Win32 functions:
88+ * OpenProcessToken: opens the access token associated with a process.
89+ * GetTokenInformation: retrieves a specified type of information about an access token.
90+ The calling process must have appropriate access rights to obtain the information.
91+ GetTokenInformation is called with the TokenOrigin Value from the TOKEN_INFORMATION_CLASS enumeration.
92+ The resulting structure contains the session ID of the logon session that will be returned.
93+ * CloseHandle: To close the token handle.
94+ """
95+ token = ctypes .wintypes .HANDLE ()
96+ if not ctypes .windll .advapi32 .OpenProcessToken (
97+ processHandle ,
98+ winKernel .MAXIMUM_ALLOWED ,
99+ ctypes .byref (token )
100+ ):
101+ raise ctypes .WinError ()
102+ try :
103+ val = TokenOrigin ()
104+ if not ctypes .windll .advapi32 .GetTokenInformation (
105+ token ,
106+ TOKEN_ORIGIN ,
107+ ctypes .byref (val ),
108+ ctypes .sizeof (val ),
109+ ctypes .byref (ctypes .wintypes .DWORD ())
110+ ):
111+ raise ctypes .WinError ()
112+ return val .originatingLogonSession
113+ finally :
114+ ctypes .windll .kernel32 .CloseHandle (token )
115+
116+
117+ @functools .lru_cache (maxsize = 1 )
118+ def getCurrentProcessLogonSessionId () -> int :
119+ return getProcessLogonSessionId (winKernel .GetCurrentProcess ())
120+
65121
66122def execElevated (path , params = None , wait = False , handleAlreadyElevated = False ):
67123 import subprocess
0 commit comments