From: Pali Rohár Date: Sun, 30 Nov 2025 13:19:52 +0000 (+0100) Subject: windows: Improve win32_change_token() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1f6081f3602e06e71af1cf23170cc023d4eb6ab;p=thirdparty%2Fpciutils.git windows: Improve win32_change_token() Function ImpersonateLoggedOnUser() is not available on older Windows versions. Instead of ImpersonateLoggedOnUser(), use SetThreadToken() on the duplicated token of SecurityImpersonation type, same what is ImpersonateLoggedOnUser() expected to do. --- diff --git a/lib/win32-helpers.c b/lib/win32-helpers.c index acc1f92..24a731d 100644 --- a/lib/win32-helpers.c +++ b/lib/win32-helpers.c @@ -573,23 +573,41 @@ set_privilege(HANDLE token, LUID luid_privilege, BOOL enable) BOOL win32_change_token(HANDLE new_token, HANDLE *old_token) { - HANDLE token; + HANDLE current_token; + HANDLE impersonate_token; - if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &token)) + if (!OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, ¤t_token)) { if (GetLastError() != ERROR_NO_TOKEN) return FALSE; - token = NULL; + current_token = NULL; } - if (!ImpersonateLoggedOnUser(new_token)) + /* + * SetThreadToken() can set only impersonation token, not the primary token + * (which caller passed as argument). Function DuplicateToken() can be used + * to create a new impersonation token as duplicate of the primary token. + */ + if (!DuplicateToken(new_token, SecurityImpersonation, &impersonate_token)) { - if (token) - CloseHandle(token); + if (current_token) + CloseHandle(current_token); return FALSE; } - *old_token = token; + /* + * NULL argument for SetThreadToken() specifies the current thread. + * If thread handle argument is value returned GetCurrentThread() then + * SetThreadToken() function crashes on older Windows versions. + */ + if (!SetThreadToken(NULL, impersonate_token)) + { + if (current_token) + CloseHandle(current_token); + return FALSE; + } + + *old_token = current_token; return TRUE; }