//##-------------------------------------------------------------- // // 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 (&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 pIEnumVariant; CComPtr pIUnknown; CComPtr 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 (&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 ( ::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 (&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 (&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 pISdo; hr = varPerClient.pdispVal->QueryInterface ( __uuidof (ISdo), reinterpret_cast (&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 (&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); }