windows-nt/Source/XPSP1/NT/admin/wmi/wbem/providers/viewprovider/vpsinks.cpp
2020-09-26 16:20:57 +08:00

490 lines
7.9 KiB
C++

//***************************************************************************
//
// VPSINKS.CPP
//
// Module: WBEM VIEW PROVIDER
//
// Purpose: Contains the sinks implementations
//
// Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "precomp.h"
#include <provexpt.h>
#include <provcoll.h>
#include <provtempl.h>
#include <provmt.h>
#include <typeinfo.h>
#include <process.h>
#include <objbase.h>
#include <objidl.h>
#include <stdio.h>
#include <wbemidl.h>
#include <provcont.h>
#include <provevt.h>
#include <provthrd.h>
#include <provlog.h>
#include <cominit.h>
#include <dsgetdc.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <instpath.h>
#include <genlex.h>
#include <sql_1.h>
#include <objpath.h>
#include <vpdefs.h>
#include <vpcfac.h>
#include <vpquals.h>
#include <vpserv.h>
#include <vptasks.h>
extern CRITICAL_SECTION g_CriticalSection;
CWbemClassObjectWithIndex :: CWbemClassObjectWithIndex(DWORD a_indx, IWbemClassObject *a_pObj)
: m_pObject(NULL), m_ReferenceCount(0), m_nsindex(a_indx)
{
if (a_pObj)
{
a_pObj->AddRef();
m_pObject = a_pObj;
}
}
CWbemClassObjectWithIndex :: ~CWbemClassObjectWithIndex()
{
if (m_pObject)
{
m_pObject->Release();
}
}
ULONG CWbemClassObjectWithIndex :: AddRef ()
{
return InterlockedIncrement(&m_ReferenceCount);
}
ULONG CWbemClassObjectWithIndex :: Release ()
{
ULONG t_Ref;
if ( (t_Ref = InterlockedDecrement(&m_ReferenceCount)) == 0 )
{
delete this ;
return 0 ;
}
else
{
return t_Ref ;
}
}
CObjectSinkResults::CObjectSinkResults(WbemTaskObject* parent, DWORD index)
{
m_ReferenceCount = 0;
m_index = index;
m_bSet = FALSE;
m_hr = 0;
m_parent = parent;
m_parent->AddRef();
m_ObjArray.SetSize(0, 10); //grow by 10s
}
CObjectSinkResults::~CObjectSinkResults()
{
if (m_parent != NULL)
{
m_parent->Release();
}
m_ObjArray.RemoveAll();
}
ULONG CObjectSinkResults::AddRef()
{
return InterlockedIncrement(&m_ReferenceCount);
}
ULONG CObjectSinkResults::Release()
{
LONG t_Ref;
if ( (t_Ref = InterlockedDecrement(&m_ReferenceCount)) == 0 )
{
delete this ;
return 0 ;
}
else
{
return t_Ref ;
}
}
void CObjectSinkResults::SetStatus(HRESULT hr, CViewProvObjectSink *pSnk)
{
if (m_CriticalSection.Lock())
{
if (SUCCEEDED(m_hr))
{
m_hr = hr;
}
RemoveSink(pSnk);
m_bSet = TRUE;
if (m_parent != NULL)
{
m_parent->SetStatus(hr, m_index);
}
m_CriticalSection.Unlock();
}
}
void CObjectSinkResults::SetSink(CViewProvObjectSink *pSnk)
{
if (m_CriticalSection.Lock())
{
m_realSnks.AddTail(pSnk);
m_CriticalSection.Unlock();
}
}
BOOL CObjectSinkResults::RemoveSink(CViewProvObjectSink *pSnk)
{
BOOL retVal = FALSE;
if (m_CriticalSection.Lock())
{
POSITION t_pos = m_realSnks.GetHeadPosition();
while (t_pos)
{
POSITION t_badPos = t_pos;
CViewProvObjectSink * t_pSnk = m_realSnks.GetNext(t_pos);
if (pSnk == t_pSnk)
{
m_realSnks.RemoveAt(t_badPos);
retVal = TRUE;
break;
}
}
m_CriticalSection.Unlock();
}
return retVal;
}
void CObjectSinkResults::Disconnect()
{
//can't call disconnect when locked, since this calls CancelAsyncCall
CList<CViewProvObjectSink*,CViewProvObjectSink*> t_realSnks;
if (m_CriticalSection.Lock())
{
while (m_realSnks.GetCount() > 0)
{
CViewProvObjectSink* t_pSnk = m_realSnks.RemoveTail();
if (t_pSnk)
{
t_pSnk->AddRef();
t_realSnks.AddTail(t_pSnk);
}
}
if (m_parent != NULL)
{
m_parent->Release();
m_parent = NULL;
}
m_CriticalSection.Unlock();
}
while (t_realSnks.GetCount() > 0)
{
CViewProvObjectSink* t_pSnk = t_realSnks.RemoveTail();
if (t_pSnk)
{
t_pSnk->Disconnect();
t_pSnk->Release();
}
}
}
HRESULT CObjectSinkResults::Indicate(LONG count, IWbemClassObject** ppObjArray, DWORD a_indx)
{
HRESULT hr = WBEM_NO_ERROR;
if ( (count > 0) && m_CriticalSection.Lock() )
{
if (m_parent != NULL)
{
m_parent->SetResultReceived();
for (LONG x = 0; x < count; x++)
{
if (ppObjArray[x] != NULL)
{
CWbemClassObjectWithIndex *t_clsWrap = new CWbemClassObjectWithIndex(a_indx, ppObjArray[x]);
t_clsWrap->AddRef();
m_ObjArray.Add(t_clsWrap);
}
else
{
hr = WBEM_E_INVALID_PARAMETER;
}
}
}
else
{
hr = WBEM_E_CALL_CANCELLED;
}
m_CriticalSection.Unlock();
}
else
{
if (count < 0)
{
hr = WBEM_E_INVALID_PARAMETER;
}
}
return hr;
}
CViewProvObjectSink::CViewProvObjectSink(CObjectSinkResults* parent, CWbemServerWrap *pServ, DWORD a_indx)
:m_parent(NULL), m_ServWrap(NULL), m_nsindex(a_indx)
{
EnterCriticalSection(&g_CriticalSection);
CViewProvClassFactory :: objectsInProgress++;
LeaveCriticalSection(&g_CriticalSection);
m_ReferenceCount = 0;
m_parent = parent;
m_parent->AddRef();
m_parent->SetSink(this);
m_ServWrap = pServ;
m_ServWrap->AddRef();
m_RemoteSink = NULL;
m_DoCancel = TRUE;
}
CViewProvObjectSink::~CViewProvObjectSink()
{
if (m_parent != NULL)
{
//set status has not been called so call it...
m_parent->SetStatus(WBEM_E_FAILED, this);
m_parent->Release();
}
if (m_ServWrap != NULL)
{
m_ServWrap->Release();
}
if (m_RemoteSink != NULL)
{
m_RemoteSink->Release();
}
EnterCriticalSection(&g_CriticalSection);
CViewProvClassFactory :: objectsInProgress--;
LeaveCriticalSection(&g_CriticalSection);
}
STDMETHODIMP CViewProvObjectSink::QueryInterface (REFIID refIID, LPVOID FAR * ppV)
{
if (ppV == NULL)
{
return E_INVALIDARG;
}
*ppV = NULL ;
if ( refIID == IID_IUnknown )
{
*ppV = ( IWbemObjectSink* ) this ;
}
else if ( refIID == IID_IWbemObjectSink )
{
*ppV = ( IWbemObjectSink* ) this ;
}
if ( *ppV )
{
( ( LPUNKNOWN ) *ppV )->AddRef () ;
return S_OK ;
}
else
{
return E_NOINTERFACE ;
}
}
STDMETHODIMP_(ULONG) CViewProvObjectSink::AddRef()
{
return InterlockedIncrement(&m_ReferenceCount);
}
STDMETHODIMP_(ULONG) CViewProvObjectSink::Release()
{
LONG t_Ref;
if ( (t_Ref = InterlockedDecrement(&m_ReferenceCount)) == 0 )
{
delete this ;
return 0 ;
}
else
{
return t_Ref ;
}
}
HRESULT CViewProvObjectSink::Indicate(LONG count, IWbemClassObject** ppObjArray)
{
HRESULT hr = WBEM_NO_ERROR;
if (m_lock.Lock())
{
if (m_parent != NULL)
{
hr = m_parent->Indicate(count, ppObjArray, m_nsindex);
}
m_lock.Unlock();
}
return hr;
}
HRESULT CViewProvObjectSink::SetStatus(LONG lFlags, HRESULT hr, BSTR bStr, IWbemClassObject* pObj)
{
if (m_lock.Lock())
{
if (m_parent != NULL)
{
m_parent->SetStatus(hr, this);
m_parent->Release();
m_parent = NULL;
DisAssociate();
m_DoCancel = FALSE;
}
m_lock.Unlock();
}
return WBEM_NO_ERROR;
}
void CViewProvObjectSink::Disconnect()
{
BOOL doCancel = FALSE;
if (m_lock.Lock())
{
if (m_DoCancel)
{
doCancel = TRUE;
m_DoCancel = FALSE;
if (m_parent != NULL)
{
m_parent->Release();
m_parent = NULL;
}
}
m_lock.Unlock();
}
if (doCancel)
{
if (m_ServWrap != NULL)
{
IWbemServices *ptmpServ = m_ServWrap->GetServerOrProxy();
if (ptmpServ)
{
if (m_RemoteSink != NULL)
{
ptmpServ->CancelAsyncCall(this);
}
else
{
ptmpServ->CancelAsyncCall(m_RemoteSink);
DisAssociate();
}
m_ServWrap->ReturnServerOrProxy(ptmpServ);
}
m_ServWrap->Release();
m_ServWrap = NULL;
}
}
}
IWbemObjectSink* CViewProvObjectSink::Associate()
{
IUnsecuredApartment* pUA = NULL;
if ( SUCCEEDED(CViewProvServ::GetUnsecApp(&pUA)) )
{
IUnknown* pUnk = NULL;
if ( SUCCEEDED(pUA->CreateObjectStub(this, &pUnk)) )
{
if ( FAILED(pUnk->QueryInterface(IID_IWbemObjectSink, (void **)&m_RemoteSink)) )
{
pUnk = NULL;
}
pUnk->Release();
}
pUA->Release();
}
return m_RemoteSink;
}
void CViewProvObjectSink::DisAssociate()
{
if (m_RemoteSink != NULL)
{
m_RemoteSink->Release();
m_RemoteSink = NULL;
}
if (m_lock.Lock())
{
if (m_parent != NULL)
{
m_parent->Release();
m_parent = NULL;
}
m_lock.Unlock();
}
}