// METHPROV.CPP: implementation of the CBaseMethodProvider class. // ////////////////////////////////////////////////////////////////////// #include #include "HMAgent.h" #include "methprov.h" ////////////////////////////////////////////////////////////////////// // global data extern CSystem* g_pSystem; extern HANDLE g_hConfigLock; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CBaseMethodProvider::CBaseMethodProvider() { OutputDebugString(L"CBaseMethodProvider::CBaseMethodProvider()\n"); MY_ASSERT(g_pSystem); m_pSystem = g_pSystem; m_cRef = 0L; m_pIWbemServices = NULL; } CBaseMethodProvider::~CBaseMethodProvider() { OutputDebugString(L"CBaseMethodProvider::~CBaseMethodProvider()\n"); if (m_pIWbemServices) { m_pIWbemServices->Release(); } m_pIWbemServices = NULL; } ////////////////////////////////////////////////////////////////////// // IUnknown Implementation ////////////////////////////////////////////////////////////////////// STDMETHODIMP CBaseMethodProvider::QueryInterface(REFIID riid, LPVOID* ppv) { *ppv = NULL; if(riid== IID_IWbemServices) { *ppv=(IWbemServices*)this; } if(IID_IUnknown==riid || riid== IID_IWbemProviderInit) { *ppv=(IWbemProviderInit*)this; } if (NULL!=*ppv) { AddRef(); return S_OK; } else { return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) CBaseMethodProvider::AddRef(void) { return InterlockedIncrement((long*)&m_cRef); } STDMETHODIMP_(ULONG) CBaseMethodProvider::Release(void) { LONG lCount = InterlockedDecrement((long*)&m_cRef); if (0 != lCount) { return lCount; } delete this; return 0L; } ////////////////////////////////////////////////////////////////////// // IWbemProviderInit Implementation ////////////////////////////////////////////////////////////////////// HRESULT CBaseMethodProvider::Initialize(LPWSTR pszUser, LONG lFlags, LPWSTR pszNamespace, LPWSTR pszLocale, IWbemServices __RPC_FAR *pNamespace, IWbemContext __RPC_FAR *pCtx, IWbemProviderInitSink __RPC_FAR *pInitSink) { OutputDebugString(L"CBaseMethodProvider::Initialize()\n"); if (NULL == pNamespace) { return WBEM_E_INVALID_PARAMETER; } m_pIWbemServices = pNamespace; m_pIWbemServices->AddRef(); pInitSink->SetStatus(WBEM_S_INITIALIZED, 0); return WBEM_S_NO_ERROR; } ////////////////////////////////////////////////////////////////////// // IWbemService Implementation ////////////////////////////////////////////////////////////////////// HRESULT CBaseMethodProvider::ExecMethodAsync(const BSTR ObjectPath, const BSTR MethodName, long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams, IWbemObjectSink* pResultSink) { CComVariant var; CComVariant v; IWbemClassObject * pClass = NULL; IWbemClassObject * pOutClass = NULL; IWbemClassObject* pOutParams = NULL; SAFEARRAY* psa = NULL; LPTSTR szOriginalSystem = NULL; LPTSTR szOriginalParentGUID = NULL; LPTSTR szGUID = NULL; DWORD iRetValue; HRESULT hRetRes; BOOL bForceReplace; DWORD dwErr = 0; MY_OUTPUT(L"CBaseMethodProvider::ExecMethodAsync()", 1); // // Do some minimal error checking. // if(MethodName == NULL || pInParams == NULL || pResultSink == NULL) { return WBEM_E_INVALID_PARAMETER; } if (!g_pSystem) { hRetRes=WBEM_E_FAILED; goto error; } hRetRes = m_pIWbemServices->GetObject(ObjectPath, 0, pCtx, &pClass, NULL); if(hRetRes != S_OK) { MY_HRESASSERT(hRetRes); goto error; } // Call the appropriate method. // retval == 0 means success... // Get the input argument hRetRes = pInParams->Get(L"TargetGUID", 0, &var, NULL, NULL); MY_HRESASSERT(hRetRes); if (hRetRes != S_OK) { goto error; } if (V_VT(&var)==VT_NULL) { hRetRes = WBEM_E_INVALID_PARAMETER; goto error; } hRetRes = pClass->GetMethod(MethodName, 0, NULL, &pOutClass); MY_HRESASSERT(hRetRes); if (hRetRes != S_OK) { goto error; } hRetRes = pOutClass->SpawnInstance(0, &pOutParams); MY_HRESASSERT(hRetRes); if (hRetRes != S_OK) { goto error; } // now we need to acquire the Mutex, not before! MY_OUTPUT(L"BLOCK - BLOCK CBaseMethodProvider::ExecMethodAsync BLOCK - g_hConfigLock BLOCK WAIT", 4); dwErr = WaitForSingleObject(g_hConfigLock, HM_ASYNC_TIMEOUT); if(dwErr != WAIT_OBJECT_0) { if(dwErr = WAIT_TIMEOUT) { TRACE_MUTEX(L"TIMEOUT MUTEX"); return WBEM_S_TIMEDOUT; } else { MY_OUTPUT(L"WaitForSingleObject on Mutex failed",4); return WBEM_E_FAILED; } } MY_OUTPUT(L"BLOCK - BLOCK CBaseMethodProvider::ExecMethodAsync BLOCK - g_hConfigLock BLOCK GOT IT", 4); try { if (!wcscmp(MethodName, L"Delete")) { hRetRes = m_pSystem->FindAndDeleteByGUID(V_BSTR(&var)); iRetValue = hRetRes; } else if (!wcscmp(MethodName, L"ResetAndCheckNow")) { hRetRes = m_pSystem->FindAndResetDEStateByGUID(V_BSTR(&var)); iRetValue = hRetRes; } else if (!wcscmp(MethodName, L"ResetDataCollectorStatistics")) { hRetRes = m_pSystem->FindAndResetDEStatisticsByGUID(V_BSTR(&var)); iRetValue = hRetRes; } else if (!wcscmp(MethodName, L"CopyWithActions")) { hRetRes = m_pSystem->FindAndCopyWithActionsByGUID(V_BSTR(&var), &psa, &szOriginalParentGUID); if (hRetRes==S_OK) { // This method returns values, and so create an instance of the // output argument class. DWORD dwNameLen = MAX_COMPUTERNAME_LENGTH + 1; TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; if (GetComputerName(szComputerName, &dwNameLen)) { hRetRes = PutStrProperty(pOutParams, L"OriginalSystem", szComputerName); } else { hRetRes = PutStrProperty(pOutParams, L"OriginalSystem", L"LocalMachine"); } if(FAILED(hRetRes)) { goto error; } hRetRes = PutStrProperty(pOutParams, L"OriginalParentGUID", szOriginalParentGUID); if(FAILED(hRetRes)) { goto error; } hRetRes = PutSAProperty(pOutParams, L"Instances", psa); if(FAILED(hRetRes)) { goto error; } // Don't need to delete this below unless there was an error! // We do not free this if we sent it in a Put. // Because, we do a VariantClear(&v); inside of PutSAProperty. psa = NULL; iRetValue = 0; } else { iRetValue = hRetRes; MY_OUTPUT(L"failed to get instance!", 1); } } else if (!wcscmp(MethodName, L"PasteWithActions")) { hRetRes = pInParams->Get(L"Instances", 0L, &v, NULL, NULL); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } if (V_VT(&v)==VT_NULL) { iRetValue = 1; } else { MY_ASSERT(V_VT(&v)==(VT_UNKNOWN|VT_ARRAY)); hRetRes = GetStrProperty(pInParams, L"OriginalSystem", &szOriginalSystem); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } hRetRes = GetStrProperty(pInParams, L"OriginalParentGUID", &szOriginalParentGUID); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } hRetRes = GetBoolProperty(pInParams, L"ForceReplace", &bForceReplace); MY_ASSERT(hRetRes==S_OK); if(FAILED(hRetRes)) { goto error; } hRetRes = m_pSystem->FindAndPasteWithActionsByGUID(V_BSTR(&var), v.parray, szOriginalSystem, szOriginalParentGUID, bForceReplace); if(FAILED(hRetRes)) { goto error; } iRetValue = hRetRes; } // // Send the output object back to the client via the sink. } else if (!wcscmp(MethodName, L"Copy")) { hRetRes = m_pSystem->FindAndCopyByGUID(V_BSTR(&var), &psa, &szOriginalParentGUID); if (hRetRes==S_OK) { // This method returns values, and so create an instance of the // output argument class. DWORD dwNameLen = MAX_COMPUTERNAME_LENGTH + 1; TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; if (GetComputerName(szComputerName, &dwNameLen)) { hRetRes = PutStrProperty(pOutParams, L"OriginalSystem", szComputerName); } else { hRetRes = PutStrProperty(pOutParams, L"OriginalSystem", L"LocalMachine"); } if(FAILED(hRetRes)) { goto error; } hRetRes = PutStrProperty(pOutParams, L"OriginalParentGUID", szOriginalParentGUID); szOriginalParentGUID = NULL; // Don't need to delete this below, as we are pointing it to something if(FAILED(hRetRes)) { goto error; } hRetRes = PutSAProperty(pOutParams, L"Instances", psa); if(FAILED(hRetRes)) { goto error; } // Don't need to delete this below unless there was an error! // We do not free this if we sent it in a Put. // Because, we do a VariantClear(&v); inside of PutSAProperty. psa = NULL; iRetValue = 0; } else { iRetValue = hRetRes; szOriginalParentGUID = NULL; // Don't need to delete this below, as we are pointing it to something MY_OUTPUT(L"failed to get instance!", 1); } } else if (!wcscmp(MethodName, L"Paste")) { hRetRes = pInParams->Get(L"Instances", 0L, &v, NULL, NULL); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } if (V_VT(&v)==VT_NULL) { iRetValue = 1; } else { MY_ASSERT(V_VT(&v)==(VT_UNKNOWN|VT_ARRAY)); hRetRes = GetStrProperty(pInParams, L"OriginalSystem", &szOriginalSystem); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } hRetRes = GetStrProperty(pInParams, L"OriginalParentGUID", &szOriginalParentGUID); MY_ASSERT(hRetRes==S_OK); if (hRetRes != S_OK) { goto error; } hRetRes = GetBoolProperty(pInParams, L"ForceReplace", &bForceReplace); MY_ASSERT(hRetRes==S_OK); if(FAILED(hRetRes)) { goto error; } hRetRes = m_pSystem->FindAndPasteByGUID(V_BSTR(&var), v.parray, szOriginalSystem, szOriginalParentGUID, bForceReplace); if(FAILED(hRetRes)) { goto error; } iRetValue = hRetRes; } // // Send the output object back to the client via the sink. } else if (!_wcsicmp(MethodName, L"Move")) { #ifdef SAVE hRetRes = GetStrProperty(pInParams, L"TargetParentGUID", &szGUID); MY_ASSERT(hRetRes==S_OK); if(FAILED(hRetRes)) { goto error; } hRetRes = m_pSystem->Move(V_BSTR(&var), szGUID); iRetValue = hRetRes; if(FAILED(hRetRes)) { goto error; } #endif hRetRes = S_OK; iRetValue = hRetRes; } else if (!wcscmp(MethodName, L"DeleteConfigurationActionAssociation")) { hRetRes = GetStrProperty(pInParams, L"ActionGUID", &szGUID); MY_ASSERT(hRetRes==S_OK); if(FAILED(hRetRes)) { goto error; } hRetRes = m_pSystem->DeleteConfigActionAssoc(V_BSTR(&var), szGUID); iRetValue = hRetRes; if(FAILED(hRetRes)) { goto error; } } else { hRetRes = WBEM_E_NOT_SUPPORTED; goto error; } } catch (...) { hRetRes = S_FALSE; iRetValue = S_FALSE; MY_ASSERT(FALSE); } // // Set the return value // VariantClear(&var); var.vt = VT_I4; var.lVal = iRetValue; hRetRes = pOutParams->Put(L"ReturnValue" , 0, &var, 0); if(FAILED(hRetRes)) { goto error; } // Send the output object back to the client via the sink. hRetRes = pResultSink->Indicate(1, &pOutParams); if(FAILED(hRetRes)) { goto error; } error: // all done now, set the status if(SUCCEEDED(hRetRes)) { pResultSink->SetStatus(0,WBEM_S_NO_ERROR,NULL,NULL); } else { MY_ASSERT(FALSE); pResultSink->SetStatus(0,hRetRes,NULL,NULL); } if (pClass) pClass->Release(); if (pOutClass) pOutClass->Release(); if (pOutParams) pOutParams->Release(); if (szOriginalSystem) delete [] szOriginalSystem; if (szOriginalParentGUID) delete [] szOriginalParentGUID; if (psa) { MY_ASSERT(FALSE); SafeArrayDestroy(psa); } if (szGUID) delete [] szGUID; MY_OUTPUT(L"BLOCK - BLOCK CBaseMethodProvider::ExecMethodAsync g_hConfigLock BLOCK - RELEASE IT", 4); ReleaseMutex(g_hConfigLock); MY_OUTPUT(L"BLOCK - BLOCK CBaseMethodProvider::ExecMethodAsync g_hConfigLock BLOCK - RELEASED", 4); return hRetRes; }