2025-04-27 07:49:33 -04:00

354 lines
8.8 KiB
C++

/*++
Copyright (C) 1997-2001 Microsoft Corporation
Module Name:
LINKLIST.CPP
Abstract:
Class which maintains lists of Objects.
History:
a-davj 04-Mar-97 Created.
--*/
#include "precomp.h"
#include "wmishared.h"
//***************************************************************************
//
// CLinkList::CLinkList
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CLinkList::CLinkList ( CComLink *a_ComLink ) : m_ComLink ( a_ComLink )
{
InitializeCriticalSection(&m_cs);
}
//***************************************************************************
//
// BOOL CLinkList::AddEntry
//
// DESCRIPTION:
//
// Adds an object to the list
//
// PARAMETERS:
//
// pAdd Pointer to object to add
// ot object type
// fa how to dispose of the object
//
// RETURN VALUE:
//
// Return: true if OK.
//
//***************************************************************************
BOOL CLinkList::AddEntry(
IN void * pAdd,
IN ObjType ot,
IN FreeAction fa)
{
int iRet;
ListEntry * pNew = new ListEntry();
if(pNew == NULL)
return FALSE;
pNew->m_pObj = pAdd;
pNew->m_type = ot;
pNew->m_freeAction = fa;
EnterCriticalSection(&m_cs);
iRet = m_Array.Add(pNew);
LeaveCriticalSection(&m_cs);
if(iRet == CFlexArray::no_error)
return TRUE;
else
{
delete pNew;
return FALSE;
}
}
//***************************************************************************
//
// BOOL CLinkList::RemoveEntry
//
// DESCRIPTION:
//
// Removes an object from the list
//
// PARAMETERS:
//
// pDel pointer to object to be removed
// ot object type
//
// RETURN VALUE:
//
// Return: true if OK.
//
//***************************************************************************
BOOL CLinkList::RemoveEntry(
IN void * pDel,
IN ObjType ot)
{
int iCnt;
BOOL bFound = FALSE;
if(pDel == NULL)
return TRUE;
int iRet = CFlexArray::failed;
EnterCriticalSection(&m_cs);
for(iCnt = 0; iCnt < m_Array.Size(); iCnt++)
{
ListEntry * pCurr = (ListEntry *)m_Array.GetAt(iCnt);
if(pCurr != NULL)
if(pCurr->m_pObj == pDel && pCurr->m_type == ot)
{
// Found it. Note that this routine does not need
// to delete the actual object since this routine is
// generally called by the object's destructor.
// =================================================
iRet = m_Array.RemoveAt(iCnt);
delete pCurr;
bFound = TRUE;
break;
}
}
LeaveCriticalSection(&m_cs);
return iRet == CFlexArray::no_error;
}
void CLinkList::ReleaseStubs ()
{
EnterCriticalSection(&m_cs);
for(int iCnt = 0; iCnt < m_Array.Size(); iCnt++)
{
ListEntry * pCurr = (ListEntry *)m_Array.GetAt(iCnt);
if(pCurr != NULL)
{
switch (pCurr->m_type )
{
case PROVIDER:
case ENUMERATOR:
case OBJECTSINK:
case LOGIN:
case CALLRESULT:
{
int iRet = m_Array.RemoveAt(iCnt--);
IUnknown * pObj = (IUnknown *)pCurr->m_pObj;
pObj->Release();
delete pCurr;
m_ComLink->Release2 ( NULL , NONE ) ;
}
break ;
case PROXY:
{
int iRet = m_Array.RemoveAt(iCnt--);
// Tidy up proxy to release server resources
CProxy *pObj = (CProxy *) pCurr->m_pObj;
delete pCurr;
pObj->ReleaseProxyFromServer ();
}
break;
default:
{
}
break ;
}
}
}
LeaveCriticalSection(&m_cs);
}
//***************************************************************************
//
// void CLinkList::Free
//
// DESCRIPTION:
//
// Called by the destructor to get rid of everything. Typcially
// this is used by the comlink destructor and so it must get rid of any
// unused proxies and stubs.
//
//***************************************************************************
void CLinkList::Free(void)
{
int iCnt;
EnterCriticalSection(&m_cs);
for(iCnt = m_Array.Size() -1; iCnt >= 0 ; iCnt--)
{
ListEntry* pCurr = (ListEntry *)m_Array.GetAt(iCnt);
if(pCurr != NULL)
{
// Remove from list, also delete the list object and get rid
// of the object itself since it hasnt gone away on its own.
m_Array.RemoveAt(iCnt);
DisposeOfEntry(pCurr);
delete pCurr;
}
}
LeaveCriticalSection(&m_cs);
}
//***************************************************************************
//
// BOOL CLinkList::GetStub
//
// DESCRIPTION:
//
// Given a stub address and type returns the actual stub (AddRef'd)
//
// PARAMETERS:
//
// dwStubAddr Expected stub address
// ot object type
//
// RETURN VALUE:
//
// Return: true if OK.
//
//***************************************************************************
IUnknown* CLinkList::GetStub(
IN DWORD dwStubAddr,
IN ObjType ot)
{
int iCnt;
EnterCriticalSection(&m_cs);
for(iCnt = 0; iCnt < m_Array.Size(); iCnt++)
{
ListEntry * pCurr = (ListEntry *)m_Array.GetAt(iCnt);
if(pCurr)
{
#ifdef _WIN64
void * pTest = (void *)dwStubAddr;
if(pCurr->m_pObj == pTest && pCurr->m_type == ot)
#else
if((DWORD)pCurr->m_pObj == dwStubAddr && pCurr->m_type == ot)
#endif
{
IUnknown * pObj = (IUnknown *)pCurr->m_pObj;
pObj->AddRef ();
LeaveCriticalSection(&m_cs);
return pObj;
}
}
}
LeaveCriticalSection(&m_cs);
return NULL;
}
//***************************************************************************
//
// void CLinkList::DisposeOfEntry
//
// DESCRIPTION:
//
// Gets rid of a proxy or stub.
//
// PARAMETERS:
//
// pDispose Object to get rid of
//
//***************************************************************************
void CLinkList::DisposeOfEntry(
ListEntry * pDispose)
{
if(pDispose->m_freeAction == RELEASEIT)
{
// This case takes care of ObjectSink objects. They should not
// be deleted, but released.
IUnknown * pObj = (IUnknown *)pDispose->m_pObj;
pObj->Release();
}
else if(pDispose->m_freeAction == NOTIFY)
{
// for proxies, we need to make sure there are no active calls
// so as to avoid deleteing the object out from underneath the
// threads.
IComLinkNotification * pObj = (IComLinkNotification *)pDispose->m_pObj;
pObj->Indicate ( m_ComLink );
}
}
//***************************************************************************
//
// void CLinkList::GetProxy
//
// DESCRIPTION:
//
// Given the remote partners stub address, this finds the corresponding
// proxy address.
//
// PARAMETERS:
//
// dwStub Stub address
//
// Return Value:
//
// Stub address if successful, otherwise it returns 0
//
//***************************************************************************
DWORD CLinkList::GetProxy(IStubAddress& stubAddr)
{
int iCnt;
DWORD dwRet = 0;
EnterCriticalSection(&m_cs);
for(iCnt = 0; iCnt < m_Array.Size(); iCnt++)
{
ListEntry * pCurr = (ListEntry *)m_Array.GetAt(iCnt);
if(pCurr)
if(pCurr->m_type == PROXY)
{
CProxy * pProxy = (CProxy *)pCurr->m_pObj;
if(pProxy && stubAddr.IsEqual (pProxy->GetStubAdd()))
{
#ifdef _WIN64
unsigned __int64 lTemp = (unsigned __int64)pProxy;
dwRet = (DWORD)lTemp;
#else
dwRet = (DWORD)pProxy;
#endif
break;
}
}
}
LeaveCriticalSection(&m_cs);
return dwRet;
}