649df49a15d29353164a2726117fd89a48e36761
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Functions related to switching between security contexts
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
11 * @see RevertToPrinterSelf
14 ImpersonatePrinterClient(HANDLE hToken
)
23 dwErrorCode
= ERROR_INVALID_HANDLE
;
27 // Get the type of the supplied token.
28 if (!GetTokenInformation(hToken
, TokenType
, &Type
, sizeof(TOKEN_TYPE
), &cbReturned
))
30 dwErrorCode
= GetLastError();
31 ERR("GetTokenInformation failed with error %lu!\n", dwErrorCode
);
35 // Check if this is an impersonation token and only set it as the thread token in this case.
36 // This is not always an impersonation token, see RevertToPrinterSelf.
37 if (Type
== TokenImpersonation
)
39 if (!SetThreadToken(NULL
, hToken
))
41 dwErrorCode
= GetLastError();
42 ERR("SetThreadToken failed with error %lu!\n", dwErrorCode
);
51 SetLastError(dwErrorCode
);
52 return (dwErrorCode
== ERROR_SUCCESS
);
56 * RevertToPrinterSelf reverts the security context from the current user's context back to the process context.
57 * As spoolss.dll is used by spoolsv.exe, this is usually the SYSTEM security context.
59 * Unlike the traditional ImpersonateClient and then RevertToSelf approach, we do it the other way round here,
60 * because spoolss.dll is delay-loaded by spoolsv.exe in the current user's context. Use RevertToPrinterSelf then to
61 * return to the SYSTEM context for specific tasks.
67 HANDLE hReturnValue
= NULL
;
70 // All spoolss code is usually called after impersonating the client. In this case, we can retrieve our current thread impersonation token using OpenThreadToken.
71 // But in rare occasions, spoolss code is also called from a higher-privileged thread that doesn't impersonate the client. Then we don't get an impersonation token.
72 // Anyway, we can't just return nothing in this case, because this is being treated as failure by the caller. So we return the token of the current process.
73 // This behaviour is verified with Windows!
74 if (OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE
, TRUE
, &hToken
))
76 // Tell the thread to stop impersonating.
77 if (!SetThreadToken(NULL
, NULL
))
79 dwErrorCode
= GetLastError();
80 ERR("SetThreadToken failed with error %lu!\n", dwErrorCode
);
84 else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
86 dwErrorCode
= GetLastError();
87 ERR("OpenProcessToken failed with error %lu!\n", dwErrorCode
);
91 // We were successful, return a token!
92 dwErrorCode
= ERROR_SUCCESS
;
93 hReturnValue
= hToken
;
95 // Don't let the cleanup routine close this.
102 SetLastError(dwErrorCode
);