Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

276 lines
7.8 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: imprsnat.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 2-16-96 srikants Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <imprsnat.hxx>
#include <ciregkey.hxx>
BOOL CImpersonateSystem::_fIsRunningAsSystem = TRUE;
BOOL CImpersonateSystem::IsRunningAsSystem()
{
return CImpersonateSystem::_fIsRunningAsSystem;
}
void CImpersonateSystem::SetRunningAsSystem()
{
CImpersonateSystem::_fIsRunningAsSystem = TRUE;
}
//+---------------------------------------------------------------------------
//
// Member: CImpersonateSystem::MakePrivileged
//
// Synopsis: This call makes the caller a "privileged" user by reverting
// to the "original" context.
//
// History: 2-19-96 srikants Created
//
// Notes: We are assuming that the "original" context of the thread
// is a "privileged" context.
//
//----------------------------------------------------------------------------
void CImpersonateSystem::MakePrivileged()
{
Win4Assert( !_fRevertedToSystem );
//
// The typical path here is failure, and it's expensive for NT to
// convert the NTSTATUS to a Win32 error. So call NT.
//
NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
TOKEN_DUPLICATE | TOKEN_QUERY |
TOKEN_IMPERSONATE,
TRUE, // Access check against the process
&_hClientToken );
if ( NT_ERROR( status ) )
{
if ( STATUS_NO_TOKEN == status )
{
//
// This thread is currently not impersonating anyone. We don't
// have to become system. We should already have the correct
// privileges.
//
}
else
{
ciDebugOut(( DEB_ERROR,
"NtOpenThreadToken() failed with error %#x\n",
status ));
THROW( CException( status ) );
}
}
else
{
_fRevertedToSystem = RevertToSelf();
//
// NTRAID#DB-NTBUG9-84492-2000/07/31-dlee Indexing Service assumes in multiple places that RevertToSelf will always succeed
// what should we do if we fail to revert to self?
//
if ( !_fRevertedToSystem )
{
ciDebugOut(( DEB_ERROR,
"RevertToSelf() failed with error %d\n", GetLastError() ));
}
}
}
//+---------------------------------------------------------------------------
//
// Member: CImpersonateSystem::~CImpersonateSystem
//
// Synopsis: ~dtor of the CImpersonateSystem class. Will restore the
// context of the thread before making it privileged.
//
// History: 2-19-96 srikants Created
//
// Notes:
//
//----------------------------------------------------------------------------
CImpersonateSystem::~CImpersonateSystem()
{
if ( _fRevertedToSystem )
{
Win4Assert( INVALID_HANDLE_VALUE != _hClientToken );
BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
if ( !fResult )
{
DWORD dwError = GetLastError();
ciDebugOut(( DEB_ERROR, "ImpersonateLoggedOnUser failed with error code %d\n",
dwError ));
}
}
if ( INVALID_HANDLE_VALUE != _hClientToken )
{
CloseHandle( _hClientToken );
}
}
//+---------------------------------------------------------------------------
//
// Function: IsImpersonated
//
// Synopsis: Tests if the caller is impersonated.
//
// Returns: TRUE if impersonated; FALSE if not.
//
// History: 12-31-96 srikants Created
//
//----------------------------------------------------------------------------
BOOL CImpersonateSystem::IsImpersonated()
{
BOOL fImpersonated = FALSE;
HANDLE hThreadToken;
NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
TOKEN_QUERY,
TRUE, // Access check against the process
&hThreadToken );
if ( NT_SUCCESS( status ) )
{
CloseHandle( hThreadToken );
fImpersonated = TRUE;
}
else
{
if ( STATUS_NO_TOKEN != status )
{
ciDebugOut(( DEB_ERROR,
"NtOpenThreadToken() failed with error %#x\n",
status ));
fImpersonated = TRUE;
}
}
return fImpersonated;
}
//+---------------------------------------------------------------------------
//
// Member: CImpersonateClient::Impersonate
//
// Synopsis: Assume a client context.
//
// History: 19 Mar 96 AlanW Created
//
// Notes: We are assuming that the "original" context of the thread
// is a "privileged" context.
//
//----------------------------------------------------------------------------
void CImpersonateClient::Impersonate()
{
if ( INVALID_HANDLE_VALUE != _hClientToken )
{
BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
if ( !fResult )
{
ciDebugOut(( DEB_ERROR,
"ImpersonateLoggedOnUser failed with error code %d\n",
GetLastError() ));
}
}
}
//+---------------------------------------------------------------------------
//
// Member: CImpersonateClient::~CImpersonateClient
//
// Synopsis: ~dtor of the CImpersonateClient class. Will restore the
// context of the thread before impersonating (assumed to be
// running as "system" previously).
//
// History: 19 Mar 96 AlanW Created
//
// Notes:
//
//----------------------------------------------------------------------------
CImpersonateClient::~CImpersonateClient()
{
if ( INVALID_HANDLE_VALUE != _hClientToken )
{
BOOL fRevertedToSystem = RevertToSelf();
if ( !fRevertedToSystem )
{
ciDebugOut(( DEB_ERROR,
"RevertToSelf() failed with error %d\n",
GetLastError() ));
}
}
}
//+---------------------------------------------------------------------------
//
// Function: VerifyThreadHasAdminPrivilege, public
//
// Synopsis: Checks to see if the client has administrative access.
//
// Arguments: - NONE -
//
// Returns: Nothing, throws if access is denied.
//
// Notes: The ACL on the HKEY_CURRENT_MACHINE\system\CurrentControlSet\
// Control\ContentIndex registry key is used to determine if
// access is permitted.
//
// History: 26 Jun 96 AlanW Created.
// History: 1 Oct 96 dlee Stole from idq and renamed
//
//----------------------------------------------------------------------------
void VerifyThreadHasAdminPrivilege()
{
HKEY hNewKey = (HKEY) INVALID_HANDLE_VALUE;
LONG dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
wcsRegAdminSubKey,
0,
KEY_WRITE,
&hNewKey );
if ( ERROR_SUCCESS == dwError )
{
RegCloseKey( hNewKey );
}
else if ( ERROR_ACCESS_DENIED == dwError )
{
THROW( CException( STATUS_ACCESS_DENIED ) );
}
else
{
ciDebugOut(( DEB_ERROR,
"Can't open reg key %ws, error %d\n",
wcsRegAdminSubKey, dwError ));
THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
}
} //VerifyThreadHasAdminPrivilege