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.
 
 
 
 
 
 

768 lines
17 KiB

//*************************************************************
//
// Copyright (c) Microsoft Corporation 1999 - 2000
// All rights reserved
//
// pollog.cxx
//
//*************************************************************
#include "rsop.hxx"
#include <strsafe.h>
#define RECORD_ENUMERATION_TIMEOUT -1
#define WQL_LANGUAGE L"WQL"
#define WSZGENERAL_CRITERIA_TEMPLATE L"select * from %s"
#define WSZSPECIFIC_CRITERIA_TEMPLATE WSZGENERAL_CRITERIA_TEMPLATE L" where %s"
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyLog::CPolicyLog
//
// Purpose: Constructor for CPolicyLog class
//
// Params: none
//
// Return value: none
//
// Notes:
//
//------------------------------------------------------------
CPolicyLog::CPolicyLog() :
_pRsopContext(NULL )
{}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::InitLog
//
// Purpose: Initializes the logging class so that it
// can create / delete / edit record in the database
//
// Params:
// pRsopContext -- context used to bind to the namespace
// wszPolicyType -- string corresponding to the record
// (policy) type -- this is the name of a class defined
// in the database schema.
//
// Return value: S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::InitLog(
CRsopContext* pRsopContext,
WCHAR* wszPolicyType)
{
HRESULT hr;
_pRsopContext = pRsopContext;
if ( ! _pRsopContext->IsRsopEnabled() )
{
return S_OK;
}
//
// Set our internal automation compatible version
// of the policy type with the caller's specification --
// return if we cannot set this value
//
_wszClass = wszPolicyType;
XBStr xbstrClass;
xbstrClass = wszPolicyType;
if ( ! xbstrClass )
{
return E_OUTOFMEMORY;
}
//
// Now, bind the context to get the correct namespace
//
hr = pRsopContext->Bind( &_xWbemServices );
if ( FAILED(hr) )
{
return hr;
}
//
// Be sure to AddRef it, since we don't want it to
// go away when we're done
//
_xWbemServices->AddRef();
//
// Now we attempt to get an interface to the class of policy
// requested by the caller
//
hr = GetRecordCreator(
&xbstrClass,
&_xRecordCreator);
if (FAILED(hr))
{
return hr;
}
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::UninitLog
//
// Purpose: Uninitializes the logging class so that all
// its resources are freed
//
// Params: none
//
// Return value: none
//
// Notes:
//
//------------------------------------------------------------
void CPolicyLog::UninitLog()
{
_xEnum = NULL;
_xWbemServices = NULL;
_xRecordCreator = NULL;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyLog::AddBlankRecord
//
// Purpose: Creates a blank record in the policy database,
// and connects the supplied CPolicyRecord with the
// newly created record
//
// Params: pRecord -- reference to a CPolicyRecord which will
// be associated with the new record if this funciton
// succeeds.
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::AddBlankRecord(CPolicyRecord* pRecord)
{
HRESULT hr;
IWbemClassObject* pRecordInterface;
if ( ! _pRsopContext->IsRsopEnabled() )
{
return S_OK;
}
pRecordInterface = NULL;
//
// Use the record creator interface to create
// an instance of the class of record associated
// with this log
//
hr = _xRecordCreator->SpawnInstance(
0,
&pRecordInterface);
if (FAILED(hr))
{
return hr;
}
//
// Initialize the CPolicyRecord so that it is
// associated with the newly created record
//
pRecord->InitRecord(pRecordInterface);
return S_OK;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyLog::CommitRecord
//
// Purpose: Commits an edited policy record to the database
//
// Params: pRecord -- the record to commit
//
// Return value: S_OK if successful, other error if not
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::CommitRecord(CPolicyRecord* pRecord)
{
return _xWbemServices->PutInstance(
pRecord->GetRecordInterface(),
WBEM_FLAG_CREATE_OR_UPDATE,
NULL,
NULL);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::WriteNewRecord
//
// Purpose: Creates a new record in the database, populates
// that record with information specific to the CPolicyRecord
// object, and commits the record.
//
// Params: pRecord -- reference to a CPolicyRecord which contains
// information that should be written to the database
//
// Return S_OK if success, error otherwise
//
// Notes: The pRecord object may not be passed to this
// method more than once
//
//------------------------------------------------------------
HRESULT CPolicyLog::WriteNewRecord(CPolicyRecord* pRecord)
{
HRESULT hr;
if ( ! _pRsopContext->IsRsopEnabled() )
{
return S_OK;
}
//
// Now, let's attempt to add a blank entry for this record to the database
//
hr = AddBlankRecord( pRecord );
if (FAILED(hr))
{
return hr;
}
//
// Write the information for this record into the blank log record
//
hr = pRecord->Write();
if (FAILED(hr))
{
return hr;
}
//
// We've written the record, now commit it permanently to the log
// in the database
//
hr = CommitRecord( pRecord );
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::GetRecordCreator
//
// Purpose: Returns an interface that allows for the creation
// of records of a specified class in the database
//
// Params: pStrClass -- a string named with a class as defined
// by the database schema that indicates the class for
// which we require an interface
//
// ppClass -- out param returning an interface to the
// record creator for a given class
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::GetRecordCreator(
XBStr* pxStrClass,
IWbemClassObject** ppClass)
{
HRESULT hr;
//
// Call the method of the namespace interface to return
// an instance of the specified class defined in that namespace
//
hr = _xWbemServices->GetObject(
*pxStrClass,
0L,
NULL,
ppClass,
NULL );
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::GetNextRecord
//
// Purpose: Associates a CPolicyRecord with a database
// record that's next in the current enumeration
//
// Params: pRecord -- CPolicyRecord to be associated with
// the next db record in the enumeration
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::GetNextRecord( CPolicyRecord* pRecord )
{
ULONG ulReturned;
IWbemClassObject* pInstance;
HRESULT hr;
ulReturned = 1;
//
// Use the enumeration interface to return a record interface
// to the next item in the enumeration -- we choose
// here to enumerate one at a time as this is not
// optimzed for speed currently.
//
hr = _xEnum->Next(
RECORD_ENUMERATION_TIMEOUT,
1,
&pInstance,
&ulReturned );
//
// If we received one item back with a success code,
// we have retrieved an interface -- associate
// the retrieved interface with the caller-specified
// pRecord
//
if ( (S_OK == hr) && (1 == ulReturned) )
{
pRecord->InitRecord( pInstance );
}
else
{
ASSERT(FAILED(hr) || (S_FALSE == hr));
}
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyLog::OpenExistingRecord
//
// Purpose: Associates a CPolicyRecord with a database
// record that corresponds to a path emitted by
// CPolicyRecord's GetPath method
//
// Params: pRecord -- CPolicyRecord to be associated with
// the existing database item
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT
CPolicyLog::OpenExistingRecord( CPolicyRecord* pRecord )
{
HRESULT hr;
WCHAR* wszPath = NULL;
DWORD cchLength = MAX_PATH;
BSTR PathName = NULL;
wszPath = (WCHAR*)LocalAlloc(LPTR, cchLength*sizeof(WCHAR));
if ( wszPath == NULL )
{
return E_OUTOFMEMORY;
}
hr = pRecord->GetPath( wszPath, &cchLength );
if ( FAILED( hr ) )
{
LocalFree( wszPath );
return hr;
}
if ( S_OK == hr )
{
PathName = SysAllocString( wszPath );
LocalFree( wszPath );
wszPath = NULL;
}
else
{
LocalFree( wszPath );
wszPath = (WCHAR*)LocalAlloc(LPTR, cchLength*sizeof(WCHAR));
if ( wszPath != NULL )
{
hr = pRecord->GetPath( wszPath, &cchLength );
if ( FAILED(hr) )
{
LocalFree( wszPath );
return hr;
}
PathName = SysAllocString( wszPath );
LocalFree( wszPath );
wszPath = NULL;
}
}
if ( ! PathName )
{
return E_OUTOFMEMORY;
}
if ( SUCCEEDED( hr ) )
{
IWbemClassObject* pInstance;
pInstance = NULL;
if ( _xWbemServices )
{
hr = _xWbemServices->GetObject(
PathName,
WBEM_FLAG_RETURN_WBEM_COMPLETE,
NULL,
&pInstance,
NULL);
}
else
{
hr = E_OUTOFMEMORY;
}
if ( SUCCEEDED( hr ) )
{
pRecord->InitRecord( pInstance );
}
}
SysFreeString( PathName );
if ( SUCCEEDED( hr ) )
{
pRecord->_bNewRecord = FALSE;
}
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::DeleteRecord
//
// Purpose: Deletes the record associated with this CPolicyRecord
// from the database
//
// Params: pRecord -- CPolicyRecord associated with
// the record to delete
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::DeleteRecord(
CPolicyRecord* pRecord,
BOOL bDeleteStatus)
{
CVariant var;
HRESULT hr;
//
// If specified by the caller, delete any associated status records
//
if ( bDeleteStatus )
{
hr = DeleteStatusRecords( pRecord );
if ( FAILED(hr) )
{
return hr;
}
}
//
// Retrieve the database path of the record to delete
//
hr = pRecord->GetRecordInterface()->Get(
WMI_PATH_PROPERTY,
0L,
(VARIANT*) &var,
NULL,
NULL);
if ( FAILED(hr) )
{
return hr;
}
//
// Now that we have the path, we can use it to delete the record
// by supplying it to the namespace's delete instance method --
// this will delete the record from the namespace
//
hr = _xWbemServices->DeleteInstance(
((VARIANT*) &var)->bstrVal,
0L,
NULL,
NULL );
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::DeleteRecord
//
// Purpose: Deletes the record associated with this CPolicyRecord
// from the database
//
// Params: pRecord -- CPolicyRecord associated with
// the record to delete
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::DeleteStatusRecords( CPolicyRecord* pRecord )
{
HRESULT hr;
//
// If there is a setting status associated with
// this error, delete it
//
hr = RsopResetPolicySettingStatus(
0,
_xWbemServices,
pRecord->GetRecordInterface());
return hr;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::ClearLog
//
// Purpose: Clears all records of this log's class (policy type)
// from the log's associated namespace
//
// Params: none
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::ClearLog(
WCHAR* wszSpecifiedCriteria,
BOOL bDeleteStatus)
{
HRESULT hr;
if ( ! _pRsopContext->IsRsopEnabled() )
{
return S_OK;
}
//
// Retrieve an enumerator for the specified criteria
//
hr = GetEnum( wszSpecifiedCriteria );
if (FAILED(hr))
{
return hr;
}
//
// We will iterate through all existing records
//
for (;;)
{
CPolicyRecord CurrentRecord;
//
// Retrieve the current record from the
// namespace
//
hr = GetNextRecord(&CurrentRecord);
if (FAILED(hr))
{
return hr;
}
//
// If there are no more records to retrieve,
// we are done and can exit the loop.
//
if (S_FALSE == hr)
{
break;
}
//
// Delete the current record from the namespace
//
hr = DeleteRecord( &CurrentRecord, bDeleteStatus );
}
FreeEnum();
return S_OK;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::ClearLog
//
// Purpose: Deletes all instances of this class from the namespace
//
// Params: none
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
HRESULT CPolicyLog::GetEnum( WCHAR* wszSpecifiedCriteria )
{
HRESULT hr;
if ( _xEnum )
{
return E_FAIL;
}
//
// Generate criteria from the caller's specification
//
WCHAR* wszCriteria;
DWORD dwCritLength = ( wszSpecifiedCriteria ? lstrlen(wszSpecifiedCriteria) : 0 ) +
sizeof( WSZSPECIFIC_CRITERIA_TEMPLATE ) / sizeof(WCHAR) +
lstrlen( _wszClass ) + 1;
wszCriteria = new WCHAR [ dwCritLength ];
if ( ! wszCriteria )
{
return E_OUTOFMEMORY;
}
//
// This creates a query for instances of the class supported by this log
// that adhere to the caller's specifications (usually asserts the value of some property)
//
if ( wszSpecifiedCriteria )
{
//
// Include the user's criteria if specified
//
hr = StringCchPrintf(wszCriteria,
dwCritLength,
WSZSPECIFIC_CRITERIA_TEMPLATE,
_wszClass,
wszSpecifiedCriteria);
ASSERT(SUCCEEDED(hr));
}
else
{
//
// If the user specified no criteria, do not attempt to include it
//
hr = StringCchPrintf(wszCriteria,
dwCritLength,
WSZGENERAL_CRITERIA_TEMPLATE,
_wszClass);
ASSERT(SUCCEEDED(hr));
}
hr = E_OUTOFMEMORY;
XBStr Query( wszCriteria );
XBStr QueryLanguage( WQL_LANGUAGE );
if ( Query && QueryLanguage )
{
//
// Use this method to obtain an enumerator for instances
// satisfying the specified criteria
//
hr = _xWbemServices->ExecQuery(
QueryLanguage,
Query,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&_xEnum );
}
delete [] wszCriteria;
if ( FAILED(hr) )
{
return hr;
}
return S_OK;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Function: CPolicyRecord::ClearLog
//
// Purpose: Deletes all instances of this class from the namespace
//
// Params: none
//
// Return S_OK if success, error otherwise
//
// Notes:
//
//------------------------------------------------------------
void CPolicyLog::FreeEnum()
{
//
// This will release the interface and set it to NULL so
// that we know that it is released;
//
_xEnum = 0;
}