windows-nt/Source/XPSP1/NT/net/ias/protocol/radius/clients.cpp
2020-09-26 16:20:57 +08:00

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);
}