Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

537 lines
12 KiB

// METHPROV.CPP: implementation of the CBaseMethodProvider class.
//
//////////////////////////////////////////////////////////////////////
#include <atlbase.h>
#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;
}