// [!output IMPL_FILE] : Implementation of [!output CLASS_NAME] #include "stdafx.h" [!if !ATTRIBUTED] #include "[!output PROJECT_NAME].h" [!endif] #include "[!output HEADER_FILE]" ///////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME] // IMPORTANT: the strings defined below are not localizable // Class name [!if CLASS_SPECIFIED] const static WCHAR * s_pMyClassName = L"[!output WMICLASSNAME]"; [!if EXTRINSIC] //properties of the event class [!output WMICLASSNAME]: [!output EXTR_PROPERTY_DEFINITIONS] [!endif] [!else] //TODO: define provided class name, e.g.: const static WCHAR * s_pMyClassName = L"MyClassName"; [!endif] ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::Initialize() // Refer to MSDN documentation for IWbemProviderInit::Initialize() // for details about implementing this method STDMETHODIMP [!output CLASS_NAME]::Initialize(__in_opt LPWSTR pszUser, LONG lFlags, __in LPWSTR pszNamespace, __in_opt LPWSTR pszLocale, IWbemServices *pNamespace, IWbemContext *pCtx, IWbemProviderInitSink *pInitSink) { CImpersonateClientHelper impersonateClient; HRESULT hr = WBEM_S_NO_ERROR; DWORD dwImpersonationLevel = 0; if(SUCCEEDED(hr = impersonateClient.GetCurrentImpersonationLevel(dwImpersonationLevel))) { // If the current thread has impersonation level set to RPC_C_IMP_LEVEL_IDENTIFY or RPC_C_IMP_LEVEL_ANONYMOUS if(dwImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { hr = WBEM_E_ACCESS_DENIED; // Do the access check yourself on the resources accessed based on security configuration for the provider // and change the return code hr appropriately } else { hr = impersonateClient.ImpersonateClient(); } } if(FAILED(hr)) { return hr; } if ( NULL == pNamespace || NULL == pInitSink) { return WBEM_E_INVALID_PARAMETER; } hr = WBEM_E_FAILED; //cache IWbemServices pointer //Note: m_pNamespace is a smart pointer, so it AddRef()'s automatically m_pNamespace = pNamespace; [!if INTRINSIC] //get helper object m_pHelper = new CIntrinsicEventProviderHelper(pNamespace, pCtx); if(m_pHelper == NULL) { return WBEM_E_OUT_OF_MEMORY; } [!endif] [!if EXTRINSIC] //store event class definition //NOTE: the code below assumes that your event class definition doesn't change while //your provider is running. If this is not true, you should implement a consumer //for class modification and class deletion events. Refer to WMI documentation //for event consumers on MSDN. BSTR bstrClassName=SysAllocString(s_pMyClassName); if (NULL == bstrClassName) { hr = WBEM_E_OUT_OF_MEMORY; return hr; } hr = m_pNamespace->GetObject(bstrClassName, 0, pCtx, //passing IWbemContext pointer to prevent deadlocks &m_pEventClass, NULL); SysFreeString(bstrClassName); bstrClassName = NULL; if(FAILED(hr)) { return hr; } //get helper object m_pHelper = new CProviderHelper(pNamespace, pCtx); if(m_pHelper == NULL) { return WBEM_E_OUT_OF_MEMORY; } [!endif] [!if INTRINSIC] //store target class definition BSTR bstrClassName=SysAllocString(s_pMyClassName); if (NULL == bstrClassName) { hr = WBEM_E_OUT_OF_MEMORY; return hr; } hr = m_pNamespace->GetObject(bstrClassName, 0, pCtx, //passing IWbemContext pointer to prevent deadlocks &m_pDataClass, NULL); SysFreeString(bstrClassName); bstrClassName = NULL; if(FAILED(hr)) { return hr; } [!endif] return pInitSink->SetStatus(WBEM_S_INITIALIZED,0); } ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::ProvideEvents() // Refer to MSDN documentation for IWbemEventProvider::ProvideEvents() // for details about implementing this method STDMETHODIMP [!output CLASS_NAME]::ProvideEvents( IWbemObjectSink *pSink, long lFlags) { // WMI calls this method to activate the event provider. // TODO: after you return from this call, start delivering the events as // they occur to the provided sink interface.You may want to create an independent thread // to handle the event delivery. CImpersonateClientHelper impersonateClient; HRESULT hr = WBEM_S_NO_ERROR; DWORD dwImpersonationLevel = 0; if(SUCCEEDED(hr = impersonateClient.GetCurrentImpersonationLevel(dwImpersonationLevel))) { // If the current thread has impersonation level set to RPC_C_IMP_LEVEL_IDENTIFY or RPC_C_IMP_LEVEL_ANONYMOUS if(dwImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { hr = WBEM_E_ACCESS_DENIED; // Do the access check yourself on the resources accessed based on security configuration for the provider // and change the return code hr appropriately } else { hr = impersonateClient.ImpersonateClient(); } } if(FAILED(hr)) { return hr; } [!if INTRINSIC] // To deliver intrinsic events, invoke FireCreationEvent(), FireDeletionEvent() and // FireModificationEvent() methods on m_pHelper. [!endif] // To report a detailed error or status to WMI, you can call ConstructErrorObject() on m_pHelper. // IMPORTANT: do not block this call for more than a few seconds. if ( NULL == pSink ) { return WBEM_E_INVALID_PARAMETER; } //cache sink pointer //Note: m_pSink is a smart pointer, so it AddRef()'s automatically m_pSink = pSink; return WBEM_S_NO_ERROR; } [!if EVENT_SECURITY ] ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::AccessCheck() // Refer to MSDN documentation for IWbemEventProviderSecurity::AccessCheck() // for details about implementing this method // Refer to MSDN documentation of IWbemQuery for parsing queries STDMETHODIMP [!output CLASS_NAME]::AccessCheck( WBEM_CWSTR wszQueryLanguage, WBEM_CWSTR wszQuery, long lSidLength, const BYTE* pSid) { CImpersonateClientHelper impersonateClient; HRESULT hr = WBEM_S_NO_ERROR; DWORD dwImpersonationLevel = 0; if(SUCCEEDED(hr = impersonateClient.GetCurrentImpersonationLevel(dwImpersonationLevel))) { // If the current thread has impersonation level set to RPC_C_IMP_LEVEL_IDENTIFY or RPC_C_IMP_LEVEL_ANONYMOUS if(dwImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { hr = WBEM_E_ACCESS_DENIED; // Do the access check yourself on the resources accessed based on security configuration for the provider // and change the return code hr appropriately } else { hr = impersonateClient.ImpersonateClient(); } } if(FAILED(hr)) { return hr; } // Create WMI Query Parser object to parse the given query CComPtr pQuery; // WBEM Query Parser Object pQuery = NULL; hr = CoCreateInstance(CLSID_WbemQuery, 0, CLSCTX_INPROC_SERVER, IID_IWbemQuery, (LPVOID *)&pQuery); if(SUCCEEDED(hr)) { // TODO: Parse the query and do access checks based on the query } // return failure for now so that the above TODO gets implemented before this class can be used // remove the setting of hr below when code is written to do access checks on the parsed query hr = WBEM_E_ACCESS_DENIED; return hr; } [!endif] [!if QUERY_SINK ] ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::CancelQuery() // Refer to MSDN documentation for IWbemEventProviderQuerySink::CancelQuery() // for details about implementing this method STDMETHODIMP [!output CLASS_NAME]::CancelQuery( unsigned long dwId) { CImpersonateClientHelper impersonateClient; HRESULT hr = WBEM_S_NO_ERROR; DWORD dwImpersonationLevel = 0; if(SUCCEEDED(hr = impersonateClient.GetCurrentImpersonationLevel(dwImpersonationLevel))) { // If the current thread has impersonation level set to RPC_C_IMP_LEVEL_IDENTIFY or RPC_C_IMP_LEVEL_ANONYMOUS if(dwImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { hr = WBEM_E_ACCESS_DENIED; // Do the access check yourself on the resources accessed based on security configuration for the provider // and change the return code hr appropriately } else { hr = impersonateClient.ImpersonateClient(); } } // TODO: implement the cancel return hr; } ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::NewQuery() // Refer to MSDN documentation for IWbemEventProviderQuerySink::NewQuery() // for details about implementing this method // Refer to MSDN documentation of IWbemQuery for parsing queries STDMETHODIMP [!output CLASS_NAME]::NewQuery( unsigned long dwId, __in WBEM_WSTR wszQueryLanguage, __in WBEM_WSTR wszQuery) { CImpersonateClientHelper impersonateClient; HRESULT hr = WBEM_S_NO_ERROR; DWORD dwImpersonationLevel = 0; if(SUCCEEDED(hr = impersonateClient.GetCurrentImpersonationLevel(dwImpersonationLevel))) { // If the current thread has impersonation level set to RPC_C_IMP_LEVEL_IDENTIFY or RPC_C_IMP_LEVEL_ANONYMOUS if(dwImpersonationLevel < RPC_C_IMP_LEVEL_IMPERSONATE) { hr = WBEM_E_ACCESS_DENIED; // Do the access check yourself on the resources accessed based on security configuration for the provider // and change the return code hr appropriately } else { hr = impersonateClient.ImpersonateClient(); } } if(FAILED(hr)) { return hr; } // Create WMI Query Parser object to parse the given query CComPtr pQuery; // WBEM Query Parser Object pQuery = NULL; hr = CoCreateInstance(CLSID_WbemQuery, 0, CLSCTX_INPROC_SERVER, IID_IWbemQuery, (LPVOID *)&pQuery); if(SUCCEEDED(hr)) { // TODO: Parse the query and do query based optimizations } return hr; } [!endif] [!if EXTRINSIC] ////////////////////////////////////////////////////////////////////////////// // [!output CLASS_NAME]::FireEvent() STDMETHODIMP [!output CLASS_NAME]::FireEvent() { HRESULT hr = WBEM_S_NO_ERROR; ATLASSERT(m_pEventClass); CComPtr pEvtInstance; hr = m_pEventClass->SpawnInstance(0, &pEvtInstance); if(FAILED(hr)) { return hr; } //Fill property values of the event object: [!if CLASS_SPECIFIED] [!output EXTRINSIC_PUT_BLOCK] [!else] //TODO: modify commented code below to fill the event property values and variant types //VARIANT var; //VariantInit(&var); //var.vt = VT_BSTR; //put appropriate variant type here //var.bstrVal = ; //put appropriate value here //BSTR bstrEventProperty=SysAllocString(L"EventProperty1"); //if (NULL == bstrEventProperty) //{ // // depending on how the value was created you may need to clean it up here // hr = WBEM_E_OUT_OF_MEMORY; // return hr; //} //hr = pEvtInstance->Put(bstrEventProperty, 0, &var, 0); //SysFreeString(bstrEventProperty); //bstrEventProperty=NULL; //// depending on how the value was created you may need to clean it up here //if(FAILED(hr)) //{ // return hr; //} [!endif] return m_pSink->Indicate(1, &(pEvtInstance.p) ); } [!endif]