Leaked source code of windows server 2003
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.
 
 
 
 
 
 

733 lines
15 KiB

//*************************************************************
//
// 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 );
}