2015-05-12 14:43:25 +00:00
/*
* PROJECT : ReactOS Spooler Router
2017-09-29 17:18:19 +00:00
* LICENSE : GPL - 2.0 + ( https : //spdx.org/licenses/GPL-2.0+)
2015-05-12 14:43:25 +00:00
* PURPOSE : Functions related to switching between security contexts
2017-09-29 17:18:19 +00:00
* COPYRIGHT : Copyright 2015 Colin Finck ( colin @ reactos . org )
2015-05-12 14:43:25 +00:00
*/
# include "precomp.h"
/**
* @ see RevertToPrinterSelf
*/
BOOL WINAPI
ImpersonatePrinterClient ( HANDLE hToken )
{
2015-07-20 16:15:52 +00:00
DWORD cbReturned ;
DWORD dwErrorCode ;
TOKEN_TYPE Type ;
// Sanity check
2015-05-12 14:43:25 +00:00
if ( ! hToken )
{
2015-07-20 16:15:52 +00:00
dwErrorCode = ERROR_INVALID_HANDLE ;
goto Cleanup ;
2015-05-12 14:43:25 +00:00
}
2015-07-20 16:15:52 +00:00
// Get the type of the supplied token.
if ( ! GetTokenInformation ( hToken , TokenType , & Type , sizeof ( TOKEN_TYPE ) , & cbReturned ) )
2015-05-12 14:43:25 +00:00
{
2015-07-20 16:15:52 +00:00
dwErrorCode = GetLastError ( ) ;
ERR ( " GetTokenInformation failed with error %lu! \n " , dwErrorCode ) ;
goto Cleanup ;
}
// Check if this is an impersonation token and only set it as the thread token in this case.
// This is not always an impersonation token, see RevertToPrinterSelf.
if ( Type = = TokenImpersonation )
{
if ( ! SetThreadToken ( NULL , hToken ) )
{
dwErrorCode = GetLastError ( ) ;
ERR ( " SetThreadToken failed with error %lu! \n " , dwErrorCode ) ;
goto Cleanup ;
}
2015-05-12 14:43:25 +00:00
}
2015-07-20 16:15:52 +00:00
Cleanup :
if ( hToken )
CloseHandle ( hToken ) ;
SetLastError ( dwErrorCode ) ;
return ( dwErrorCode = = ERROR_SUCCESS ) ;
2015-05-12 14:43:25 +00:00
}
/**
* RevertToPrinterSelf reverts the security context from the current user ' s context back to the process context .
* As spoolss . dll is used by spoolsv . exe , this is usually the SYSTEM security context .
*
* Unlike the traditional ImpersonateClient and then RevertToSelf approach , we do it the other way round here ,
* because spoolss . dll is delay - loaded by spoolsv . exe in the current user ' s context . Use RevertToPrinterSelf then to
* return to the SYSTEM context for specific tasks .
*/
HANDLE WINAPI
2017-10-30 21:43:47 +00:00
RevertToPrinterSelf ( VOID )
2015-05-12 14:43:25 +00:00
{
2015-07-20 16:15:52 +00:00
DWORD dwErrorCode ;
HANDLE hReturnValue = NULL ;
HANDLE hToken = NULL ;
2015-05-12 14:43:25 +00:00
2015-07-20 16:15:52 +00:00
// All spoolss code is usually called after impersonating the client. In this case, we can retrieve our current thread impersonation token using OpenThreadToken.
// 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.
// 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.
// This behaviour is verified with Windows!
if ( OpenThreadToken ( GetCurrentThread ( ) , TOKEN_IMPERSONATE , TRUE , & hToken ) )
2015-05-12 14:43:25 +00:00
{
2015-07-20 16:15:52 +00:00
// Tell the thread to stop impersonating.
if ( ! SetThreadToken ( NULL , NULL ) )
{
dwErrorCode = GetLastError ( ) ;
ERR ( " SetThreadToken failed with error %lu! \n " , dwErrorCode ) ;
goto Cleanup ;
}
2015-05-12 14:43:25 +00:00
}
2015-07-20 16:15:52 +00:00
else if ( ! OpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & hToken ) )
2015-05-12 14:43:25 +00:00
{
2015-07-20 16:15:52 +00:00
dwErrorCode = GetLastError ( ) ;
ERR ( " OpenProcessToken failed with error %lu! \n " , dwErrorCode ) ;
goto Cleanup ;
2015-05-12 14:43:25 +00:00
}
2015-07-20 16:15:52 +00:00
// We were successful, return a token!
dwErrorCode = ERROR_SUCCESS ;
hReturnValue = hToken ;
// Don't let the cleanup routine close this.
hToken = NULL ;
Cleanup :
if ( hToken )
CloseHandle ( hToken ) ;
SetLastError ( dwErrorCode ) ;
return hReturnValue ;
2015-05-12 14:43:25 +00:00
}