|
|
//=============================================================================
//
// Copyright (c) 1996-1999, Microsoft Corporation, All rights reserved
//
// PERMFILT.CPP
//
// This file implements the classes for standard event filters.
//
// History:
//
// 11/27/96 a-levn Compiles.
//
//=============================================================================
#include "precomp.h"
#include <sddl.h>
#include <stdio.h>
#include "pragmas.h"
#include "permfilt.h"
#include "ess.h"
#include <genutils.h>
long CPermanentFilter::mstatic_lNameHandle = 0; long CPermanentFilter::mstatic_lLanguageHandle = 0; long CPermanentFilter::mstatic_lQueryHandle = 0; long CPermanentFilter::mstatic_lEventNamespaceHandle = 0; long CPermanentFilter::mstatic_lEventAccessHandle = 0; long CPermanentFilter::mstatic_lSidHandle = 0; bool CPermanentFilter::mstatic_bHandlesInitialized = false;
//static
HRESULT CPermanentFilter::InitializeHandles( _IWmiObject* pObject ) { if(mstatic_bHandlesInitialized) return S_FALSE;
CIMTYPE ct; pObject->GetPropertyHandle(FILTER_KEY_PROPNAME, &ct, &mstatic_lNameHandle); pObject->GetPropertyHandle(FILTER_LANGUAGE_PROPNAME, &ct, &mstatic_lLanguageHandle); pObject->GetPropertyHandle(FILTER_QUERY_PROPNAME, &ct, &mstatic_lQueryHandle); pObject->GetPropertyHandle(FILTER_EVENTNAMESPACE_PROPNAME, &ct, &mstatic_lEventNamespaceHandle); pObject->GetPropertyHandleEx(FILTER_EVENTACCESS_PROPNAME, 0, &ct, &mstatic_lEventAccessHandle ); pObject->GetPropertyHandleEx(OWNER_SID_PROPNAME, 0, &ct, &mstatic_lSidHandle); mstatic_bHandlesInitialized = true; return S_OK; } //******************************************************************************
// public
//
// See stdtrig.h for documentation
//
//******************************************************************************
CPermanentFilter::CPermanentFilter(CEssNamespace* pNamespace) : CGenericFilter(pNamespace), m_pEventAccessRelativeSD(NULL), m_pcsQuery(NULL) { }
CPermanentFilter::~CPermanentFilter() { if ( m_pEventAccessRelativeSD != NULL ) { LocalFree( m_pEventAccessRelativeSD ); }
if( m_pcsQuery != NULL ) { CTemporaryHeap::Free(m_pcsQuery, m_pcsQuery->GetLength()); } }
HRESULT CPermanentFilter::Initialize( IWbemClassObject* pObj ) { HRESULT hres;
CWbemPtr<_IWmiObject> pFilterObj;
hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
if ( FAILED(hres) ) { return hres; }
InitializeHandles( pFilterObj );
// Check class
// ===========
if(pFilterObj->InheritsFrom(L"__EventFilter") != S_OK) return WBEM_E_INVALID_OBJECT;
// Determine the query language
// ============================
ULONG ulFlags; CCompressedString* pcsLanguage;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lLanguageHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsLanguage ); if( hres != S_OK || pcsLanguage == NULL) { ERRORTRACE((LOG_ESS, "Event filter with invalid query language is " "rejected\n")); return WBEM_E_INVALID_OBJECT; }
if( pcsLanguage->CompareNoCase("WQL") != 0 ) { ERRORTRACE((LOG_ESS, "Event filter with invalid query language '%S' is " "rejected\n", pcsLanguage->CreateWStringCopy())); return WBEM_E_INVALID_QUERY_TYPE; }
// Get the query
// =============
CCompressedString* pcsQuery;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsQuery ); if( hres != S_OK ) { return WBEM_E_INVALID_OBJECT; }
LPWSTR wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr(); if(wszQuery == NULL) return WBEM_E_OUT_OF_MEMORY; CVectorDeleteMe<WCHAR> vdm1(wszQuery);
// Store it temporarily (until Park is called)
// ===========================================
// Figure out how much space we need
// =================================
int nSpace = pcsQuery->GetLength();
// Allocate this string on the temporary heap
// ==========================================
m_pcsQuery = (CCompressedString*)CTemporaryHeap::Alloc(nSpace); if(m_pcsQuery == NULL) return WBEM_E_OUT_OF_MEMORY;
// Copy the contents
// =================
memcpy((void*)m_pcsQuery, pcsQuery, nSpace);
//
// Get the event namespace
//
if(mstatic_lEventNamespaceHandle) // to protect against old repositories
{ CCompressedString* pcsEventNamespace; hres = pFilterObj->GetPropAddrByHandle( mstatic_lEventNamespaceHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsEventNamespace ); if( FAILED(hres) ) { return hres; } else if ( hres == S_OK ) // o.k if event namespace is null.
{ if( !(m_isEventNamespace = pcsEventNamespace)) { return WBEM_E_OUT_OF_MEMORY; } } } //
// Record the name of this filter
//
CCompressedString* pcsKey; hres = pFilterObj->GetPropAddrByHandle( mstatic_lNameHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsKey ); if( hres != S_OK ) { return WBEM_E_INVALID_OBJECT; }
if(!(m_isKey = pcsKey)) return WBEM_E_OUT_OF_MEMORY;
// Get the SID
// ===========
PSID pSid; ULONG ulNumElements; hres = pFilterObj->GetArrayPropAddrByHandle( mstatic_lSidHandle, 0, &ulNumElements, &pSid ); if ( hres != S_OK ) { return WBEM_E_INVALID_OBJECT; }
m_pOwnerSid = new BYTE[ulNumElements];
if ( m_pOwnerSid == NULL ) { return WBEM_E_OUT_OF_MEMORY; }
memcpy( m_pOwnerSid, pSid, ulNumElements );
//
// Get the event access SD
//
if( mstatic_lEventAccessHandle ) // to protect against old repositories
{ CCompressedString* pcsEventAccess; hres = pFilterObj->GetPropAddrByHandle( mstatic_lEventAccessHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsEventAccess ); if( FAILED(hres) ) { return hres; } else if ( hres == S_OK ) // o.k if event access is null.
{ WString wsEventAccess;
try { wsEventAccess = pcsEventAccess->CreateWStringCopy(); } catch( CX_MemoryException ) { return WBEM_E_OUT_OF_MEMORY; }
ULONG cEventAccessRelativeSD;
if ( !ConvertStringSecurityDescriptorToSecurityDescriptorW( wsEventAccess, SDDL_REVISION_1, &m_pEventAccessRelativeSD, &cEventAccessRelativeSD ) ) { WString wsKey = m_isKey; try { wsKey = m_isKey; } catch( CX_MemoryException ) {} ERRORTRACE((LOG_ESS, "Filter '%S' contained invalid SDDL " "string for event access SD.\n", wsKey )); return HRESULT_FROM_WIN32( GetLastError() ); }
//
// convert the self-relative SD to an absolute SD so we can
// set the owner and group fields ( required by AccessCheck )
//
if ( !InitializeSecurityDescriptor( &m_EventAccessAbsoluteSD, SECURITY_DESCRIPTOR_REVISION )) { return HRESULT_FROM_WIN32( GetLastError() ); }
PACL pAcl; BOOL bAclPresent, bAclDefaulted;
if ( !GetSecurityDescriptorDacl( m_pEventAccessRelativeSD, &bAclPresent, &pAcl, &bAclDefaulted ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } if ( !SetSecurityDescriptorDacl( &m_EventAccessAbsoluteSD, bAclPresent, pAcl, bAclDefaulted ) ) { return HRESULT_FROM_WIN32( GetLastError() ); }
if ( !GetSecurityDescriptorSacl( m_pEventAccessRelativeSD, &bAclPresent, &pAcl, &bAclDefaulted ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } if ( !SetSecurityDescriptorSacl( &m_EventAccessAbsoluteSD, bAclPresent, pAcl, bAclDefaulted ) ) { return HRESULT_FROM_WIN32( GetLastError() ); }
//
// always need to set the owner and group sids. We do this for
// two reasons (1) we want to override the user putting in anything
// they want for these fields, and (2) we want to ensure that
// these fields are set because AccessCheck() requires it.
//
if ( !SetSecurityDescriptorOwner( &m_EventAccessAbsoluteSD, m_pOwnerSid, TRUE ) ) { return HRESULT_FROM_WIN32( GetLastError() ); }
if ( !SetSecurityDescriptorGroup( &m_EventAccessAbsoluteSD, m_pOwnerSid, TRUE ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } } }
// Initialize the generic filter accordingly
// =========================================
hres = CGenericFilter::Create(L"WQL", wszQuery); if(FAILED(hres)) return hres; return WBEM_S_NO_ERROR; }
const PSECURITY_DESCRIPTOR CPermanentFilter::GetEventAccessSD() { if ( m_pEventAccessRelativeSD != NULL ) { return &m_EventAccessAbsoluteSD; } return NULL; }
HRESULT CPermanentFilter::GetCoveringQuery(DELETE_ME LPWSTR& wszQueryLanguage, DELETE_ME LPWSTR& wszQuery, BOOL& bExact, QL_LEVEL_1_RPN_EXPRESSION** ppExp) { HRESULT hres;
if(m_pcsQuery == NULL) { hres = RetrieveQuery(wszQuery); } else { wszQuery = m_pcsQuery->CreateWStringCopy().UnbindPtr(); if(wszQuery == NULL) hres = WBEM_E_OUT_OF_MEMORY; else hres = WBEM_S_NO_ERROR; }
if(FAILED(hres)) return hres;
if(ppExp) { // Parse it
// ========
CTextLexSource src(wszQuery); QL1_Parser parser(&src); int nRes = parser.Parse(ppExp); if (nRes) { ERRORTRACE((LOG_ESS, "Unable to construct event filter with " "unparsable " "query '%S'. The filter is not active\n", wszQuery)); return WBEM_E_UNPARSABLE_QUERY; } }
bExact = TRUE; wszQueryLanguage = CloneWstr(L"WQL");
return WBEM_S_NO_ERROR; }
HRESULT CPermanentFilter::RetrieveQuery(DELETE_ME LPWSTR& wszQuery) { HRESULT hres;
//
// Construct db path
//
DWORD cLen = m_isKey.GetLength() + 100; BSTR strPath = SysAllocStringLen(NULL, cLen ); if(strPath == NULL) return WBEM_E_OUT_OF_MEMORY; CSysFreeMe sfm1(strPath);
StringCchPrintfW( strPath, cLen, L"__EventFilter=\"%s\"", (LPCWSTR)(WString)m_isKey );
//
// Retrieve the object
//
_IWmiObject* pFilterObj; hres = m_pNamespace->GetDbInstance(strPath, &pFilterObj); if(FAILED(hres)) return WBEM_E_INVALID_OBJECT;
CReleaseMe rm(pFilterObj);
InitializeHandles(pFilterObj);
// Extract its properties
// ======================
ULONG ulFlags; CCompressedString* pcsQuery;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsQuery ); if( hres != S_OK ) { return WBEM_E_INVALID_OBJECT; }
wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr();
if(wszQuery == NULL) return WBEM_E_OUT_OF_MEMORY;
return WBEM_S_NO_ERROR; } HRESULT CPermanentFilter::GetEventNamespace( DELETE_ME LPWSTR* pwszNamespace) { if(m_isEventNamespace.IsEmpty()) *pwszNamespace = NULL; else { *pwszNamespace = m_isEventNamespace.CreateLPWSTRCopy(); if(*pwszNamespace == NULL) return WBEM_E_OUT_OF_MEMORY; } return S_OK; } SYSFREE_ME BSTR CPermanentFilter::ComputeKeyFromObj( IWbemClassObject* pObj ) { HRESULT hres; CWbemPtr<_IWmiObject> pFilterObj;
hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
if ( FAILED(hres) ) { return NULL; }
InitializeHandles(pFilterObj);
ULONG ulFlags; CCompressedString* pcsKey;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lNameHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsKey ); if( hres != S_OK ) { return NULL; }
return pcsKey->CreateBSTRCopy(); }
SYSFREE_ME BSTR CPermanentFilter::ComputeKeyFromPath( LPCWSTR wszPath) { // Find the first quote
// ====================
WCHAR* pwcFirstQuote = wcschr(wszPath, L'"'); if(pwcFirstQuote == NULL) return NULL;
// Find the next quote
// ===================
WCHAR* pwcLastQuote = wcschr(pwcFirstQuote+1, L'"'); if(pwcLastQuote == NULL) return NULL;
return SysAllocStringLen(pwcFirstQuote+1, pwcLastQuote - pwcFirstQuote - 1); }
HRESULT CPermanentFilter::CheckValidity( IWbemClassObject* pObj ) { HRESULT hres;
CWbemPtr<_IWmiObject> pFilterObj;
hres = pObj->QueryInterface( IID__IWmiObject, (void**)&pFilterObj );
if ( FAILED(hres) ) { return hres; }
InitializeHandles(pFilterObj);
//
// Check class
//
if(pFilterObj->InheritsFrom(L"__EventFilter") != S_OK) return WBEM_E_INVALID_OBJECT;
//
// Check the query language
//
ULONG ulFlags; CCompressedString* pcsLanguage;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lLanguageHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsLanguage ); if( hres != S_OK ) { return WBEM_E_INVALID_QUERY_TYPE; }
if(pcsLanguage->CompareNoCase("WQL") != 0) return WBEM_E_INVALID_QUERY_TYPE;
//
// Get the query
//
CCompressedString* pcsQuery;
hres = pFilterObj->GetPropAddrByHandle( mstatic_lQueryHandle, WMIOBJECT_FLAG_ENCODING_V1, &ulFlags, (void**)&pcsQuery ); if( hres != S_OK ) { return WBEM_E_INVALID_OBJECT; }
LPWSTR wszQuery = pcsQuery->CreateWStringCopy().UnbindPtr(); if(wszQuery == NULL) return WBEM_E_OUT_OF_MEMORY; CVectorDeleteMe<WCHAR> vdm(wszQuery);
//
// Make sure it is parsable
//
CTextLexSource src(wszQuery); QL1_Parser parser(&src); QL_LEVEL_1_RPN_EXPRESSION* pExp = NULL; int nRes = parser.Parse(&pExp); if (nRes) return WBEM_E_UNPARSABLE_QUERY; delete pExp;
return WBEM_S_NO_ERROR; }
HRESULT CPermanentFilter::ObtainToken(IWbemToken** ppToken) { //
// Get us a token from the token cache
//
return m_pNamespace->GetToken(GetOwner(), ppToken); }
void CPermanentFilter::Park() { if(m_pcsQuery) CTemporaryHeap::Free(m_pcsQuery, m_pcsQuery->GetLength()); m_pcsQuery = NULL; }
|