|
|
//*************************************************************
//
// Copyright (c) Microsoft Corporation 1999 - 2000
// All rights reserved
//
// context.cxx
//
//*************************************************************
#include "rsop.hxx"
#include <strsafe.h>
CRsopContext::CRsopContext( PRSOP_TARGET pRsopTarget, BOOL bReportingMode, WCHAR* wszExtensionGuid ) : _pWbemServices( pRsopTarget->pWbemServices ), _wszNameSpace( NULL ), _pRsopTarget( pRsopTarget ), _bEnabled( TRUE ), _dwMode( bReportingMode ? MODE_REPORTING : MODE_PLANNING ), _phrLoggingStatus ( NULL ), _hPolicyAccess( NULL ), _wszExtensionGuid( wszExtensionGuid ), _hkRsop( NULL ) { _pWbemServices->AddRef(); }
CRsopContext::CRsopContext( IWbemServices* pWbemServices, HRESULT* phrLoggingStatus, WCHAR* wszExtensionGuid ) : _pWbemServices( pWbemServices ), _wszNameSpace( NULL ), _pRsopTarget( NULL ), _bEnabled( pWbemServices != NULL ), _dwMode( MODE_DIAGNOSTIC ), _phrLoggingStatus ( phrLoggingStatus ), _hPolicyAccess( NULL ), _wszExtensionGuid( wszExtensionGuid ), _hkRsop( NULL ) { if ( _bEnabled ) { _pWbemServices->AddRef(); } }
CRsopContext::CRsopContext( WCHAR* wszExtensionGuid ) : _pWbemServices( NULL ), _wszNameSpace( NULL ), _pRsopTarget( NULL ), _bEnabled( FALSE ), _dwMode( MODE_DIAGNOSTIC ), _phrLoggingStatus ( NULL ), _hPolicyAccess( NULL ), _wszExtensionGuid( wszExtensionGuid ), _hkRsop( NULL ) {}
CRsopContext::~CRsopContext() { ASSERT( ! _hPolicyAccess );
//
// Set the final logging status
//
if ( _bEnabled && _phrLoggingStatus ) { *_phrLoggingStatus = S_OK; }
if ( _pWbemServices ) { _pWbemServices->Release(); }
delete [] _wszNameSpace;
if ( _hkRsop ) { RegCloseKey( _hkRsop ); } }
BOOL CRsopContext::IsRsopEnabled() { return _bEnabled; }
BOOL CRsopContext::IsPlanningModeEnabled() { return ( _dwMode == MODE_PLANNING ) || ( _dwMode == MODE_REPORTING ); }
BOOL CRsopContext::IsDiagnosticModeEnabled() { return _dwMode == MODE_DIAGNOSTIC; }
BOOL CRsopContext::IsReportingModeEnabled() { return ( _dwMode == MODE_REPORTING ); }
HRESULT CRsopContext::GetRsopStatus() { HRESULT hr;
hr = S_OK;
if ( _phrLoggingStatus ) { hr = *_phrLoggingStatus; }
return hr; }
void CRsopContext::SetNameSpace ( WCHAR* wszNameSpace ) { _wszNameSpace = wszNameSpace;
if ( _wszNameSpace ) { EnableRsop(); } }
void CRsopContext::EnableRsop() { _bEnabled = (NULL != _pWbemServices) || ( NULL != _wszNameSpace ); }
void CRsopContext::DisableRsop( HRESULT hrReason ) { if ( _bEnabled && _phrLoggingStatus ) { *_phrLoggingStatus = hrReason; }
_bEnabled = FALSE; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CRsopContext::Bind
//
// Purpose: Bind to a policy database and return an interface
// for the user or machine namespace
//
// Params:
//
//
// Return value: S_OK if successful, S_FALSE if already init'd,
// other facility error if, the function fails.
//
// Notes:
//
//------------------------------------------------------------
HRESULT CRsopContext::Bind( IWbemServices** ppWbemServices ) { HRESULT hr;
ASSERT ( _bEnabled );
hr = S_OK;
//
// Only bind to the database if we don't already have an interface
//
if ( ! _pWbemServices ) { //
// If we don't have one, we'll have to bind
// using the namespace path
//
hr = _PolicyDatabase.Bind( _wszNameSpace, &_pWbemServices); }
//
// If we already have an interface, return that
//
if ( _pWbemServices ) { *ppWbemServices = _pWbemServices; hr = S_FALSE; }
if ( FAILED(hr) ) { DisableRsop( hr ); }
return hr; }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CRsopContext::GetNameSpace
//
// Purpose: Gets the namespace to which this context is bound
//
// Params: ppwszNameSpace -- out parameter that will point
// to the address of a string that has the namespace --
// this memory should be freed by the caller
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CRsopContext::GetNameSpace( WCHAR** ppwszNameSpace ) { LPWSTR wszNamespaceEnd; LPWSTR wszNameSpace; CVariant var; IWbemClassObject* pWbemClassObject;
XBStr xbstrPath( L"__PATH" ); XBStr xbstrClass( RSOP_POLICY_SETTING );
if ( ! xbstrPath || ! xbstrClass ) { return E_OUTOFMEMORY; }
HRESULT hr;
pWbemClassObject = NULL;
//
// Get the class
//
hr = _pWbemServices->GetObject( xbstrClass, 0L, NULL, &pWbemClassObject, NULL );
if ( SUCCEEDED( hr ) ) { //
// Read the path property of the class from the class object
//
hr = pWbemClassObject->Get( xbstrPath, 0L, (VARIANT*) &var, NULL, NULL);
pWbemClassObject->Release(); }
//
// Now parse the path to obtain the parent namespace of
// the class, which is the namespace in which the
// IWbemServices pointer resides
//
//
// Find the end of the class name so we can null-terminate it
//
if ( SUCCEEDED( hr ) ) { //
// Look for the delimiter that terminates the class name
//
wszNamespaceEnd = wcschr( ((VARIANT*) &var)->bstrVal, L':' );
//
// If we found the delimiter, terminate the string there
//
if ( wszNamespaceEnd ) { *wszNamespaceEnd = L'\0'; } //
// Allocate space for the namespace string
//
DWORD dwNSLength = wcslen( ((VARIANT*) &var)->bstrVal ) + 1; wszNameSpace = new WCHAR [ dwNSLength ]; //
// If we got space for the namespace, copy it
//
if ( wszNameSpace ) { hr = StringCchCopy( wszNameSpace, dwNSLength, ((VARIANT*) &var)->bstrVal ); ASSERT( SUCCEEDED(hr) );
*ppwszNameSpace = wszNameSpace; } else { hr = E_OUTOFMEMORY; } }
return hr; }
HRESULT CRsopContext::MoveContextState( CRsopContext* pRsopContext ) { _pWbemServices = pRsopContext->_pWbemServices;
if ( _pWbemServices ) { _pWbemServices->AddRef(); }
_bEnabled = pRsopContext->_bEnabled;
_dwMode = pRsopContext->_dwMode;
_phrLoggingStatus = pRsopContext->_phrLoggingStatus;
pRsopContext->_phrLoggingStatus = NULL;
delete [] _wszNameSpace; _wszNameSpace = pRsopContext->_wszNameSpace;
pRsopContext->_wszNameSpace = NULL;
_pRsopTarget = pRsopContext->_pRsopTarget;
_wszExtensionGuid = pRsopContext->_wszExtensionGuid;
_hkRsop = pRsopContext->_hkRsop;
pRsopContext->_hkRsop = NULL;
return S_OK; }
HRESULT CRsopContext::GetExclusiveLoggingAccess( BOOL bMachine ) { HRESULT hr;
hr = S_OK;
ASSERT( ! _hPolicyAccess );
//
// We require exclusive access in diagnostic mode only --
// in planning mode, we have implicit exclusive access
//
if ( IsRsopEnabled() && IsDiagnosticModeEnabled() ) { _hPolicyAccess = EnterCriticalPolicySection( bMachine );
//
// On failure, disable logging
//
if ( ! _hPolicyAccess ) { LONG Status;
Status = GetLastError();
hr = HRESULT_FROM_WIN32( Status );
if ( SUCCEEDED( hr ) ) { hr = E_FAIL; }
DisableRsop( hr ); } } return hr; } void CRsopContext::ReleaseExclusiveLoggingAccess() { if ( _hPolicyAccess ) { LeaveCriticalPolicySection( _hPolicyAccess ); _hPolicyAccess = NULL; } }
LONG CRsopContext::GetRsopNamespaceKeyPath( PSID pUserSid, WCHAR** ppwszDiagnostic ) { LONG Status; UNICODE_STRING SidString; WCHAR* wszUserSubkey; HRESULT hr = S_OK;
*ppwszDiagnostic = NULL;
RtlInitUnicodeString( &SidString, NULL );
wszUserSubkey = NULL;
Status = ERROR_SUCCESS;
//
// First, get the subkey
//
if ( pUserSid ) { NTSTATUS NtStatus;
NtStatus = RtlConvertSidToUnicodeString( &SidString, pUserSid, TRUE);
if ( NT_SUCCESS( NtStatus ) ) { wszUserSubkey = SidString.Buffer; } else { Status = RtlNtStatusToDosError( NtStatus ); } } else { wszUserSubkey = MACHINESUBKEY; }
//
// If we have obtained the full subkey, we can now
// generate the path for it
//
if ( ERROR_SUCCESS == Status ) { DWORD cchLen;
//
// Space for the user sid string + the pathsep
//
cchLen = lstrlen ( wszUserSubkey ) + 1;
//
// Space for the gp extension state parent + extension list key (includes both pathseps and null terminator) +
// + the cse subkey
//
cchLen += ( sizeof( GPSTATEKEY ) + sizeof( EXTENSIONLISTKEY ) ) / sizeof( *wszUserSubkey ) + lstrlen( _wszExtensionGuid ) + 1;
*ppwszDiagnostic = new WCHAR[ cchLen ];
if ( *ppwszDiagnostic ) { hr = StringCchCopy( *ppwszDiagnostic, cchLen, GPSTATEKEY L"\\" ); ASSERT(SUCCEEDED(hr));
hr = StringCchCat( *ppwszDiagnostic, cchLen, wszUserSubkey ); ASSERT(SUCCEEDED(hr));
hr = StringCchCat( *ppwszDiagnostic, cchLen, EXTENSIONLISTKEY ); ASSERT(SUCCEEDED(hr));
hr = StringCchCat( *ppwszDiagnostic, cchLen, _wszExtensionGuid ); ASSERT(SUCCEEDED(hr)); } else { Status = ERROR_OUTOFMEMORY; } }
//
// Free allocated resources
//
if ( SidString.Buffer ) { RtlFreeUnicodeString( &SidString ); }
return Status; }
void CRsopContext::InitializeContext( PSID pUserSid ) { LONG Status; WCHAR* wszNameSpace; WCHAR* wszNameSpaceKeyPath;
//
// In planning mode, all initialization is
// already done, there is nothing to do here
//
if ( IsPlanningModeEnabled() ) { return; }
//
// Return successfully if we already have our key.
//
if ( _hkRsop ) return; Status = ERROR_SUCCESS;
//
// First, we need to get the rsop subkey -- we must ensure that it exists
//
Status = GetRsopNamespaceKeyPath( pUserSid, &wszNameSpaceKeyPath);
if ( ERROR_SUCCESS == Status ) { //
// We create a key under the user's per machine policy
// subtree. This key must be persistent so that extensions
// that process policy outside of the policy engine context
// or in no changes when the policy engine does not pass
// a namepsace to the extension can know whether RSoP is enabled
// or not and where to log the data
//
Status = RegCreateKeyEx( HKEY_LOCAL_MACHINE, wszNameSpaceKeyPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &_hkRsop, NULL );
delete [] wszNameSpaceKeyPath; }
if ( ERROR_SUCCESS != Status ) { HRESULT hr;
hr = HRESULT_FROM_WIN32( Status );
DisableRsop( hr ); } }
void CRsopContext::InitializeSavedNameSpace() { LONG Status; if ( ! _hkRsop ) { return; }
//
// In planning mode, all initialization is
// already done, there is nothing to do here
//
if ( IsPlanningModeEnabled() ) { return; } Status = ERROR_SUCCESS; //
// If we already have a namespace, there is no need to use the saved
// namespace, so we can leave since we've ensured the existence of the namespace key
//
if ( HasNameSpace() ) { return; } //
// The rsop namespace for this user is stored in the registry --
// we query this below
//
DWORD Size;
Size = 0;
Status = RegQueryValueEx( _hkRsop, RSOPNAMESPACE, NULL, NULL, NULL, &Size);
if ( ERROR_SUCCESS == Status ) { WCHAR* wszNameSpace;
wszNameSpace = (WCHAR*) new BYTE [ Size ];
if ( ! wszNameSpace ) { Status = ERROR_OUTOFMEMORY;
goto CRsopContext__InitializeSavedNameSpace__Exit; }
Status = RegQueryValueEx( _hkRsop, RSOPNAMESPACE, NULL, NULL, (LPBYTE) wszNameSpace, &Size);
if ( ERROR_SUCCESS != Status ) { delete [] wszNameSpace; wszNameSpace = NULL; } else { SetNameSpace( wszNameSpace ); } }
CRsopContext__InitializeSavedNameSpace__Exit: if ( ERROR_SUCCESS != Status ) { HRESULT hr;
hr = HRESULT_FROM_WIN32( Status );
DisableRsop( hr ); } }
void CRsopContext::SaveNameSpace() { WCHAR* wszNameSpace; HRESULT hr;
if ( ! IsRsopEnabled() ) { return; }
if ( IsPlanningModeEnabled() ) { return; } wszNameSpace = NULL;
//
// Retrieve the rsop namespace -- note that the retrieved
// string should be freed
//
hr = GetNameSpace( &wszNameSpace );
if ( SUCCEEDED( hr ) ) { #if DBG
DWORD DebugStatus = #endif // DBG
RegSetValueEx( _hkRsop, RSOPNAMESPACE, 0, REG_SZ, (LPBYTE) wszNameSpace, (lstrlen( wszNameSpace ) + 1) * sizeof(WCHAR) ); }
delete [] wszNameSpace; }
void CRsopContext::DeleteSavedNameSpace() { if ( IsPlanningModeEnabled() ) { return; } #if DBG
DWORD DebugStatus = #endif // DBG
RegDeleteValue( _hkRsop, RSOPNAMESPACE ); }
|