379 lines
8.5 KiB
C++
379 lines
8.5 KiB
C++
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
COMLINK.CPP
|
|
|
|
Abstract:
|
|
|
|
Declarations for CComLink, which implements a network-independent
|
|
transport for WBEM custom marshaling.
|
|
|
|
History:
|
|
|
|
a-davj 15-Aug-96 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "wmishared.h"
|
|
#include "cominit.h"
|
|
|
|
HANDLE g_Terminate = NULL;
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CComLink::CComLink
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Constructor.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// hRead read handle
|
|
// hWrite write handle
|
|
// Type type of connection
|
|
// hTerm Event which can be set to terminate the object
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
//
|
|
//***************************************************************************
|
|
|
|
CComLink::CComLink (
|
|
|
|
IN LinkType Type
|
|
|
|
) : m_ObjList ( this )
|
|
{
|
|
m_LastReadTime = GetCurrentTime () ;
|
|
|
|
InitializeCriticalSection(&m_cs);
|
|
|
|
m_TerminationEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
|
|
m_WriteMutex = CreateMutex(NULL,FALSE,NULL);
|
|
|
|
// Determine the timeout period, based on the registry entry.
|
|
|
|
m_TimeoutMilliseconds = GetTimeout();
|
|
|
|
// unlike Ole objects which get incremented by the mandatory
|
|
// QueryInterface, this requires an initial nudge for the count.
|
|
// =============================================================
|
|
|
|
m_cRef = 1;
|
|
|
|
ObjectCreated(OBJECT_TYPE_COMLINK);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CComLink::~CComLink
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CComLink::~CComLink()
|
|
{
|
|
if ( m_TerminationEvent )
|
|
{
|
|
SetEvent ( m_TerminationEvent ) ;
|
|
}
|
|
|
|
// Delete the worker threads and the proxy/stub list
|
|
|
|
m_ObjList.Free () ;
|
|
|
|
if ( m_TerminationEvent )
|
|
CloseHandle ( m_TerminationEvent ) ;
|
|
|
|
if ( m_WriteMutex )
|
|
CloseHandle ( m_WriteMutex ) ;
|
|
|
|
DeleteCriticalSection ( & m_cs ) ;
|
|
|
|
ObjectDestroyed(OBJECT_TYPE_COMLINK);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// int CComLink::AddRef2
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Adds to the reference count. Note that if pAdd isnt null, then pAdd is
|
|
// pointing to an object that needs to be notified if this object goes away.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pAdd object to add to the "notify" list
|
|
// ot object type
|
|
// fa how to dispose of the object
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// reference count
|
|
//***************************************************************************
|
|
|
|
int CComLink::AddRef2 (
|
|
|
|
void * pAdd,
|
|
ObjType ot,
|
|
FreeAction fa
|
|
)
|
|
{
|
|
int iRet;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if(pAdd)
|
|
{
|
|
m_ObjList.AddEntry(pAdd, ot, fa); //todo, test result
|
|
}
|
|
|
|
m_cRef++;
|
|
// DEBUGTRACE((LOG,"--AddRef2 after increment %d",m_cRef));
|
|
|
|
iRet = m_cRef;
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// int CComLink::Release2
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Decrements the reference count. Note that if pRemove isnt null, then
|
|
// it points to an object that no longer needs to be notified when this
|
|
// object goes away.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pRemove pointer to object that is to be removed
|
|
// ot object type
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// refernce count
|
|
//
|
|
//***************************************************************************
|
|
|
|
int CComLink::Release2 (
|
|
|
|
IN void *pRemove,
|
|
IN ObjType ot
|
|
)
|
|
{
|
|
int iRet;
|
|
|
|
EnterCriticalSection( gMaintObj.GetCriticalSection () );
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
if(pRemove)
|
|
{
|
|
m_ObjList.RemoveEntry(pRemove, ot); //todo, test result
|
|
}
|
|
|
|
// DEBUGTRACE((LOG,"\n--Release2 count is %d, ot is %d", m_cRef, ot));
|
|
|
|
m_cRef--;
|
|
iRet = m_cRef;
|
|
|
|
if ( iRet == 2 )
|
|
{
|
|
gMaintObj.Indicate ( this ) ;
|
|
}
|
|
|
|
if ( iRet == 1 )
|
|
{
|
|
SetEvent ( m_TerminationEvent ) ;
|
|
gMaintObj.ShutDownComlink ( this ) ;
|
|
Shutdown () ;
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
LeaveCriticalSection( gMaintObj.GetCriticalSection () );
|
|
|
|
if( iRet == 0 )
|
|
{
|
|
delete this ;
|
|
}
|
|
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// int CComLink::Release2
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Decrements the reference count. Note that if pRemove isnt null, then
|
|
// it points to an object that no longer needs to be notified when this
|
|
// object goes away.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pRemove pointer to object that is to be removed
|
|
// ot object type
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// refernce count
|
|
//
|
|
//***************************************************************************
|
|
|
|
int CComLink::Release3 (
|
|
|
|
IN void *pRemove,
|
|
IN ObjType ot
|
|
)
|
|
{
|
|
int iRet;
|
|
|
|
if(pRemove)
|
|
{
|
|
m_ObjList.RemoveEntry(pRemove, ot); //todo, test result
|
|
}
|
|
|
|
// DEBUGTRACE((LOG,"\n--Release2 count is %d, ot is %d", m_cRef, ot));
|
|
|
|
m_cRef--;
|
|
iRet = m_cRef;
|
|
|
|
if ( iRet == 2 )
|
|
{
|
|
gMaintObj.UnLockedIndicate ( this ) ;
|
|
}
|
|
|
|
if ( iRet == 1 )
|
|
{
|
|
SetEvent ( m_TerminationEvent ) ;
|
|
gMaintObj.UnLockedShutDownComlink ( this ) ;
|
|
UnLockedShutdown () ;
|
|
}
|
|
|
|
if( iRet == 0 )
|
|
{
|
|
delete this ;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// DWORD CComLink::GetStatus
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Gets the status.
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// no_error if OK, otherwise failed.
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD CComLink :: GetStatus ()
|
|
{
|
|
if ( m_WriteQueue.GetStatus () != no_error || m_ReadQueue.GetStatus () != no_error )
|
|
{
|
|
return failed;
|
|
}
|
|
else
|
|
{
|
|
return no_error;
|
|
}
|
|
}
|
|
|
|
void CComLink :: ReleaseStubs ()
|
|
{
|
|
m_ObjList.ReleaseStubs () ;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectSinkProxy * CComLink::GetObjectSinkProxy
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Returns a pointer to a new or existing proxy for an object sink.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// stubAddr stub for the clients notification object
|
|
// pServices IWbemServices interface to which the sink proxy is bound
|
|
// createIfNotFound only if TRUE will a new proxy be created
|
|
//
|
|
// RETURN VALUE:
|
|
//
|
|
// Return: NULL if out of memory or bad arugments. Otherwise it is the pointer
|
|
// to a CObjectSinkProxy object.
|
|
//
|
|
// If a proxy is returned, its Ref count will have been incremented by 1.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CObjectSinkProxy * CComLink::GetObjectSinkProxy( IN IStubAddress& stubAddr,
|
|
IN IWbemServices* pServices,
|
|
IN bool createIfNotFound)
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
CObjectSinkProxy * pNoteProxy = NULL;
|
|
if(!stubAddr.IsValid ())
|
|
{
|
|
LeaveCriticalSection(&m_cs);
|
|
return NULL;
|
|
}
|
|
|
|
// First check the list of existing stubs and reuse one if possible. This means that
|
|
// if the client sends the same pointer twice, then WBEMCORE will get the same proxy.
|
|
|
|
|
|
CLinkList * pList = GetListPtr();
|
|
if(pList)
|
|
{
|
|
// Note double cast which is needed since CObjectSinkClientProxy uses multiple
|
|
// inheritance.
|
|
|
|
CProxy * pProxy = (CProxy * )pList->GetProxy(stubAddr);
|
|
if(pProxy)
|
|
{
|
|
pNoteProxy = (CObjectSinkProxy *)pProxy;
|
|
pNoteProxy->AddRef ();
|
|
LeaveCriticalSection(&m_cs);
|
|
return pNoteProxy;
|
|
}
|
|
}
|
|
|
|
// Getting here means we are bereft of an existing usable proxy, so we must make one
|
|
if (createIfNotFound)
|
|
{
|
|
pNoteProxy = CreateObjectSinkProxy (stubAddr, pServices);
|
|
|
|
// Note that a successful call below will increment the refcount on pNoteProxy,
|
|
// which is what we want
|
|
if (!bVerifyPointer (pNoteProxy))
|
|
pNoteProxy = NULL;
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return pNoteProxy;
|
|
}
|
|
|