618 lines
15 KiB
C++
618 lines
15 KiB
C++
|
//##--------------------------------------------------------------
|
||
|
//
|
||
|
// File: clients.cpp
|
||
|
//
|
||
|
// Synopsis: Implementation of CClients class methods
|
||
|
//
|
||
|
//
|
||
|
// History: 9/23/97 MKarki Created
|
||
|
//
|
||
|
// Copyright (C) 1997-98 Microsoft Corporation
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
#include "radcommon.h"
|
||
|
#include "client.h"
|
||
|
#include "clients.h"
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CClients
|
||
|
//
|
||
|
// Synopsis: This is the constructor of the Clients class
|
||
|
//
|
||
|
// Arguments: NONE
|
||
|
//
|
||
|
// Returns: NONE
|
||
|
//
|
||
|
// History: MKarki Created 9/26/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
CClients::CClients(
|
||
|
VOID
|
||
|
)
|
||
|
:m_pCClientArray (NULL),
|
||
|
m_hResolverEvent (NULL),
|
||
|
m_pIClassFactory (NULL),
|
||
|
m_bConfigure (TRUE)
|
||
|
{
|
||
|
InitializeCriticalSection (&m_CritSect);
|
||
|
|
||
|
} // end of CClients class constructor
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ~CClients
|
||
|
//
|
||
|
// Synopsis: This is the destructor of the Clients class
|
||
|
//
|
||
|
// Arguments: NONE
|
||
|
//
|
||
|
// Returns: NONE
|
||
|
//
|
||
|
// History: MKarki Created 9/26/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
CClients::~CClients(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// free all the objects in the Clients Collection
|
||
|
//
|
||
|
DeleteObjects ();
|
||
|
|
||
|
DeleteCriticalSection (&m_CritSect);
|
||
|
|
||
|
if (NULL != m_pCClientArray)
|
||
|
{
|
||
|
::CoTaskMemFree (m_pCClientArray);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// close the event now
|
||
|
//
|
||
|
if (NULL != m_hResolverEvent)
|
||
|
{
|
||
|
::CloseHandle (m_hResolverEvent);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// delete the class factory now
|
||
|
//
|
||
|
if (NULL != m_pIClassFactory)
|
||
|
{
|
||
|
m_pIClassFactory->Release ();
|
||
|
}
|
||
|
|
||
|
} // end of CClients class destructor
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: Init
|
||
|
//
|
||
|
// Synopsis: This is the Init public method of the Clients class
|
||
|
// which does the object initialization
|
||
|
//
|
||
|
// Arguments: NONE
|
||
|
//
|
||
|
// Returns: NONE
|
||
|
//
|
||
|
// History: MKarki Created 4/5/98
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CClients::Init (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
//
|
||
|
// get the IClassFactory interface to be used to create
|
||
|
// the Client COM objects
|
||
|
//
|
||
|
hr = ::CoGetClassObject (
|
||
|
__uuidof (CClient),
|
||
|
CLSCTX_INPROC_SERVER,
|
||
|
NULL,
|
||
|
IID_IClassFactory,
|
||
|
reinterpret_cast <PVOID*> (&m_pIClassFactory)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to object class factor for Client Objects in "
|
||
|
" during Client Collection initialization"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// create the event used to signal exit of resolver thread
|
||
|
//
|
||
|
m_hResolverEvent = ::CreateEvent (
|
||
|
NULL, // security attribs
|
||
|
TRUE, // manual reset
|
||
|
TRUE, // initial state
|
||
|
NULL // event name
|
||
|
);
|
||
|
if (NULL == m_hResolverEvent)
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to create resolver thread event "
|
||
|
" during Client Collection initialization"
|
||
|
);
|
||
|
return (E_FAIL);
|
||
|
}
|
||
|
|
||
|
return (S_OK);
|
||
|
|
||
|
} // end of CClients::Init method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: Shutdown
|
||
|
//
|
||
|
// Synopsis: This is the Shutdown public method of the Clients class
|
||
|
// which does the object shutdown which is basically
|
||
|
// signalling the resolver thread to exit
|
||
|
//
|
||
|
// Arguments: NONE
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
// History: MKarki Created 5/4/98
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
VOID
|
||
|
CClients::Shutdown (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// stop the configuration of clients if taking place
|
||
|
//
|
||
|
StopConfiguringClients ();
|
||
|
|
||
|
return;
|
||
|
|
||
|
} // end of CClients::Shutdown method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: StopConfiguringClients
|
||
|
//
|
||
|
// Synopsis: This is the CClients class private method
|
||
|
// which stops the configuration taking place on
|
||
|
// a worker thread, the call does not return untill
|
||
|
// the worker thread has completed cleanup
|
||
|
//
|
||
|
// Arguments: NONE
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
// History: MKarki Created 5/4/98
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CClients::StopConfiguringClients (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// reset the global configure flag and then wait of event
|
||
|
//
|
||
|
m_bConfigure = FALSE;
|
||
|
|
||
|
DWORD dwError = ::WaitForSingleObject (m_hResolverEvent, INFINITE);
|
||
|
if (WAIT_FAILED == dwError)
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Failed on waiting for resolver thread to exit "
|
||
|
"during Clients Collection processing"
|
||
|
);
|
||
|
return (E_FAIL);
|
||
|
}
|
||
|
|
||
|
return (S_OK);
|
||
|
|
||
|
} // end of CClients::StopConfiguringClients method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SetClients
|
||
|
//
|
||
|
// Synopsis: This is the initialization method of the
|
||
|
// CClients class objects which loads up the
|
||
|
// values
|
||
|
//
|
||
|
// Arguments:
|
||
|
// [in] VARIANT*
|
||
|
//
|
||
|
// Returns: HRESULT - status
|
||
|
//
|
||
|
// History: MKarki Created 12/16/97
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CClients::SetClients (
|
||
|
VARIANT *pVarClients
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LONG lCount = 0;
|
||
|
CClient *pIIasClient = NULL;
|
||
|
DWORD dwClientsLeft = 0;
|
||
|
DWORD dwCurrentIndex = 0;
|
||
|
BOOL bStatus = FALSE;
|
||
|
CComVariant varPerClient;
|
||
|
CComPtr <IEnumVARIANT> pIEnumVariant;
|
||
|
CComPtr <IUnknown > pIUnknown;
|
||
|
CComPtr <ISdoCollection> pISdoCollection;
|
||
|
|
||
|
//
|
||
|
// check the input arguments
|
||
|
//
|
||
|
if ((VT_DISPATCH != pVarClients->vt) || (NULL == pVarClients->pdispVal))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Invalid argument passed in for Clients collection processing"
|
||
|
);
|
||
|
return (E_INVALIDARG);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// stop any previous client configuration in progress
|
||
|
//
|
||
|
hr = StopConfiguringClients ();
|
||
|
if (FAILED (hr)) {return (hr);}
|
||
|
|
||
|
//
|
||
|
// get the ISdoCollection interface now
|
||
|
//
|
||
|
hr = (pVarClients->pdispVal)->QueryInterface (
|
||
|
__uuidof (ISdoCollection),
|
||
|
reinterpret_cast <PVOID*> (&pISdoCollection)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain SDO Collection during Clients Collection "
|
||
|
"processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get the number of objects in the collection
|
||
|
//
|
||
|
hr = pISdoCollection->get_Count (&lCount);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain client object count during Clients Collection "
|
||
|
"processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
else if (0 == lCount)
|
||
|
{
|
||
|
DeleteObjects();
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// allocate array of CClient* to temporarily store the CClient
|
||
|
// objects till the addresses are resolved
|
||
|
//
|
||
|
m_pCClientArray = reinterpret_cast <CClient**> (
|
||
|
::CoTaskMemAlloc (
|
||
|
sizeof (CClient*)*lCount)
|
||
|
);
|
||
|
if (NULL == m_pCClientArray)
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to allocate memory for Client object array "
|
||
|
"during Clients collection processing"
|
||
|
);
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get the enumerator for the clients collection
|
||
|
//
|
||
|
hr = pISdoCollection->get__NewEnum (
|
||
|
reinterpret_cast <IUnknown**> (&pIUnknown)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain enumeration object during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get the enum variant
|
||
|
//
|
||
|
hr = pIUnknown->QueryInterface (
|
||
|
IID_IEnumVARIANT,
|
||
|
reinterpret_cast <PVOID*> (&pIEnumVariant)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain EnumVariant interface during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get clients out of the collection and initialize
|
||
|
//
|
||
|
hr = pIEnumVariant->Next (1, &varPerClient, &dwClientsLeft);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain variant object during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
while ((dwClientsLeft > 0) && (dwCurrentIndex < lCount))
|
||
|
{
|
||
|
//
|
||
|
// get an Sdo pointer from the variant we received
|
||
|
//
|
||
|
CComPtr <ISdo> pISdo;
|
||
|
hr = varPerClient.pdispVal->QueryInterface (
|
||
|
__uuidof (ISdo),
|
||
|
reinterpret_cast <PVOID*> (&pISdo)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain SDO interface during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// create a new Client object now
|
||
|
//
|
||
|
hr = m_pIClassFactory->CreateInstance (
|
||
|
NULL,
|
||
|
__uuidof (CClient),
|
||
|
reinterpret_cast <PVOID*> (&pIIasClient)
|
||
|
);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to create Client object from factory during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// initalize the client
|
||
|
//
|
||
|
hr = pIIasClient->Init (pISdo);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to initialize client object "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
//
|
||
|
// delete this object
|
||
|
//
|
||
|
pIIasClient->Release ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// store this CClient class object in the
|
||
|
// object array temporarily
|
||
|
//
|
||
|
m_pCClientArray[dwCurrentIndex] = pIIasClient;
|
||
|
dwCurrentIndex++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// clear the perClient value from this variant
|
||
|
//
|
||
|
varPerClient.Clear ();
|
||
|
|
||
|
//
|
||
|
// get next client out of the collection
|
||
|
//
|
||
|
hr = pIEnumVariant->Next (1, &varPerClient, &dwClientsLeft);
|
||
|
if (FAILED (hr))
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to obtain next variant object during "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
return (hr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// we reset the event which will be set by the resolver thread
|
||
|
// when its done and start the resolver thread
|
||
|
//
|
||
|
::ResetEvent (m_hResolverEvent);
|
||
|
m_bConfigure = TRUE;
|
||
|
bStatus = ::IASRequestThread (::MakeBoundCallback (
|
||
|
this,
|
||
|
&CClients::Resolver,
|
||
|
dwCurrentIndex
|
||
|
)
|
||
|
);
|
||
|
if (FALSE == bStatus)
|
||
|
{
|
||
|
IASTracePrintf (
|
||
|
"Unable to start client resolution thread "
|
||
|
"Clients collection processing"
|
||
|
);
|
||
|
::SetEvent (m_hResolverEvent);
|
||
|
return (E_FAIL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// we have been successfully configured
|
||
|
//
|
||
|
|
||
|
return (S_OK);
|
||
|
|
||
|
} // end of CClients::SetClients method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: FindObject
|
||
|
//
|
||
|
// Synopsis: This method finds a CClient class object from
|
||
|
// the CClients collection and returns a reference
|
||
|
// to it, without removing it from the collection
|
||
|
//
|
||
|
// Arguments: [in] DWORD - key
|
||
|
// [out] IIasClient**
|
||
|
//
|
||
|
// Returns: NONE
|
||
|
//
|
||
|
//
|
||
|
// History: MKarki Created 9/26/97
|
||
|
//
|
||
|
// Called By:
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
BOOL
|
||
|
CClients::FindObject (
|
||
|
DWORD dwKey,
|
||
|
IIasClient **ppIIasClient
|
||
|
)
|
||
|
{
|
||
|
EnterCriticalSection(&m_CritSect);
|
||
|
|
||
|
IIasClient* client = m_mapClients.Find(dwKey);
|
||
|
|
||
|
if (ppIIasClient != 0)
|
||
|
{
|
||
|
*ppIIasClient = client;
|
||
|
|
||
|
if (client != 0)
|
||
|
{
|
||
|
client->AddRef();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&m_CritSect);
|
||
|
|
||
|
return client != 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DeleteObjects
|
||
|
//
|
||
|
// Synopsis: This method deletes CClient objects from the
|
||
|
// map
|
||
|
//
|
||
|
// Arguments: none
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
// History: MKarki Created 4/4/98
|
||
|
//
|
||
|
// Called By: CClients destructor
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
VOID
|
||
|
CClients::DeleteObjects (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
m_mapClients.Clear();
|
||
|
} // end of CClients::DeleteObjects method
|
||
|
|
||
|
//++--------------------------------------------------------------
|
||
|
//
|
||
|
// Function: Resolver
|
||
|
//
|
||
|
// Synopsis: This is the CClients Private method that
|
||
|
// resolves the client IP addresses
|
||
|
//
|
||
|
// Arguments: none
|
||
|
//
|
||
|
// Returns: VOID
|
||
|
//
|
||
|
// History: MKarki Created 4/12/98
|
||
|
//
|
||
|
// Called By: CClients::SetClients public method through
|
||
|
// a worker thread
|
||
|
//
|
||
|
//----------------------------------------------------------------
|
||
|
VOID
|
||
|
CClients::Resolver (
|
||
|
DWORD dwArraySize
|
||
|
)
|
||
|
{
|
||
|
// Set up iterators for the clients array.
|
||
|
CClient **i, **begin = m_pCClientArray, **end = begin + dwArraySize;
|
||
|
|
||
|
// Resolve the client addresses.
|
||
|
for (i = begin; i != end; ++i)
|
||
|
{
|
||
|
(*i)->ResolveAddress();
|
||
|
}
|
||
|
|
||
|
//////////
|
||
|
// Update the client map.
|
||
|
//////////
|
||
|
|
||
|
EnterCriticalSection(&m_CritSect);
|
||
|
|
||
|
DeleteObjects();
|
||
|
|
||
|
try
|
||
|
{
|
||
|
for (i = begin; i != end; ++i)
|
||
|
{
|
||
|
const CClient::Address* paddr = (*i)->GetAddressList();
|
||
|
|
||
|
for ( ; paddr->ipAddress != INADDR_NONE; ++paddr)
|
||
|
{
|
||
|
m_mapClients.Insert(SubNet(paddr->ipAddress, paddr->width), *i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection(&m_CritSect);
|
||
|
|
||
|
//////////
|
||
|
// Clean up the array of client objects.
|
||
|
//////////
|
||
|
|
||
|
for (i = begin; i != end; ++i)
|
||
|
{
|
||
|
(*i)->Release();
|
||
|
}
|
||
|
|
||
|
CoTaskMemFree(m_pCClientArray);
|
||
|
m_pCClientArray = NULL;
|
||
|
|
||
|
// Set the event indicating that the Resolver thread is done
|
||
|
SetEvent(m_hResolverEvent);
|
||
|
}
|