//************************************************************* // // Copyright (c) Microsoft Corporation 1999 - 2000 // All rights reserved // // pollog.cxx // //************************************************************* #include "rsop.hxx" #include #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; }