Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

617 lines
15 KiB

  1. //##--------------------------------------------------------------
  2. //
  3. // File: clients.cpp
  4. //
  5. // Synopsis: Implementation of CClients class methods
  6. //
  7. //
  8. // History: 9/23/97 MKarki Created
  9. //
  10. // Copyright (C) 1997-98 Microsoft Corporation
  11. // All rights reserved.
  12. //
  13. //----------------------------------------------------------------
  14. #include "radcommon.h"
  15. #include "client.h"
  16. #include "clients.h"
  17. //++--------------------------------------------------------------
  18. //
  19. // Function: CClients
  20. //
  21. // Synopsis: This is the constructor of the Clients class
  22. //
  23. // Arguments: NONE
  24. //
  25. // Returns: NONE
  26. //
  27. // History: MKarki Created 9/26/97
  28. //
  29. //----------------------------------------------------------------
  30. CClients::CClients(
  31. VOID
  32. )
  33. :m_pCClientArray (NULL),
  34. m_hResolverEvent (NULL),
  35. m_pIClassFactory (NULL),
  36. m_bConfigure (TRUE)
  37. {
  38. InitializeCriticalSection (&m_CritSect);
  39. } // end of CClients class constructor
  40. //++--------------------------------------------------------------
  41. //
  42. // Function: ~CClients
  43. //
  44. // Synopsis: This is the destructor of the Clients class
  45. //
  46. // Arguments: NONE
  47. //
  48. // Returns: NONE
  49. //
  50. // History: MKarki Created 9/26/97
  51. //
  52. //----------------------------------------------------------------
  53. CClients::~CClients(
  54. VOID
  55. )
  56. {
  57. //
  58. // free all the objects in the Clients Collection
  59. //
  60. DeleteObjects ();
  61. DeleteCriticalSection (&m_CritSect);
  62. if (NULL != m_pCClientArray)
  63. {
  64. ::CoTaskMemFree (m_pCClientArray);
  65. }
  66. //
  67. // close the event now
  68. //
  69. if (NULL != m_hResolverEvent)
  70. {
  71. ::CloseHandle (m_hResolverEvent);
  72. }
  73. //
  74. // delete the class factory now
  75. //
  76. if (NULL != m_pIClassFactory)
  77. {
  78. m_pIClassFactory->Release ();
  79. }
  80. } // end of CClients class destructor
  81. //++--------------------------------------------------------------
  82. //
  83. // Function: Init
  84. //
  85. // Synopsis: This is the Init public method of the Clients class
  86. // which does the object initialization
  87. //
  88. // Arguments: NONE
  89. //
  90. // Returns: NONE
  91. //
  92. // History: MKarki Created 4/5/98
  93. //
  94. //----------------------------------------------------------------
  95. HRESULT
  96. CClients::Init (
  97. VOID
  98. )
  99. {
  100. HRESULT hr = S_OK;
  101. //
  102. // get the IClassFactory interface to be used to create
  103. // the Client COM objects
  104. //
  105. hr = ::CoGetClassObject (
  106. __uuidof (CClient),
  107. CLSCTX_INPROC_SERVER,
  108. NULL,
  109. IID_IClassFactory,
  110. reinterpret_cast <PVOID*> (&m_pIClassFactory)
  111. );
  112. if (FAILED (hr))
  113. {
  114. IASTracePrintf (
  115. "Unable to object class factor for Client Objects in "
  116. " during Client Collection initialization"
  117. );
  118. return (hr);
  119. }
  120. //
  121. // create the event used to signal exit of resolver thread
  122. //
  123. m_hResolverEvent = ::CreateEvent (
  124. NULL, // security attribs
  125. TRUE, // manual reset
  126. TRUE, // initial state
  127. NULL // event name
  128. );
  129. if (NULL == m_hResolverEvent)
  130. {
  131. IASTracePrintf (
  132. "Unable to create resolver thread event "
  133. " during Client Collection initialization"
  134. );
  135. return (E_FAIL);
  136. }
  137. return (S_OK);
  138. } // end of CClients::Init method
  139. //++--------------------------------------------------------------
  140. //
  141. // Function: Shutdown
  142. //
  143. // Synopsis: This is the Shutdown public method of the Clients class
  144. // which does the object shutdown which is basically
  145. // signalling the resolver thread to exit
  146. //
  147. // Arguments: NONE
  148. //
  149. // Returns: VOID
  150. //
  151. // History: MKarki Created 5/4/98
  152. //
  153. //----------------------------------------------------------------
  154. VOID
  155. CClients::Shutdown (
  156. VOID
  157. )
  158. {
  159. //
  160. // stop the configuration of clients if taking place
  161. //
  162. StopConfiguringClients ();
  163. return;
  164. } // end of CClients::Shutdown method
  165. //++--------------------------------------------------------------
  166. //
  167. // Function: StopConfiguringClients
  168. //
  169. // Synopsis: This is the CClients class private method
  170. // which stops the configuration taking place on
  171. // a worker thread, the call does not return untill
  172. // the worker thread has completed cleanup
  173. //
  174. // Arguments: NONE
  175. //
  176. // Returns: VOID
  177. //
  178. // History: MKarki Created 5/4/98
  179. //
  180. //----------------------------------------------------------------
  181. HRESULT
  182. CClients::StopConfiguringClients (
  183. VOID
  184. )
  185. {
  186. //
  187. // reset the global configure flag and then wait of event
  188. //
  189. m_bConfigure = FALSE;
  190. DWORD dwError = ::WaitForSingleObject (m_hResolverEvent, INFINITE);
  191. if (WAIT_FAILED == dwError)
  192. {
  193. IASTracePrintf (
  194. "Failed on waiting for resolver thread to exit "
  195. "during Clients Collection processing"
  196. );
  197. return (E_FAIL);
  198. }
  199. return (S_OK);
  200. } // end of CClients::StopConfiguringClients method
  201. //++--------------------------------------------------------------
  202. //
  203. // Function: SetClients
  204. //
  205. // Synopsis: This is the initialization method of the
  206. // CClients class objects which loads up the
  207. // values
  208. //
  209. // Arguments:
  210. // [in] VARIANT*
  211. //
  212. // Returns: HRESULT - status
  213. //
  214. // History: MKarki Created 12/16/97
  215. //
  216. //----------------------------------------------------------------
  217. HRESULT
  218. CClients::SetClients (
  219. VARIANT *pVarClients
  220. )
  221. {
  222. HRESULT hr = S_OK;
  223. LONG lCount = 0;
  224. CClient *pIIasClient = NULL;
  225. DWORD dwClientsLeft = 0;
  226. DWORD dwCurrentIndex = 0;
  227. BOOL bStatus = FALSE;
  228. CComVariant varPerClient;
  229. CComPtr <IEnumVARIANT> pIEnumVariant;
  230. CComPtr <IUnknown > pIUnknown;
  231. CComPtr <ISdoCollection> pISdoCollection;
  232. //
  233. // check the input arguments
  234. //
  235. if ((VT_DISPATCH != pVarClients->vt) || (NULL == pVarClients->pdispVal))
  236. {
  237. IASTracePrintf (
  238. "Invalid argument passed in for Clients collection processing"
  239. );
  240. return (E_INVALIDARG);
  241. }
  242. //
  243. // stop any previous client configuration in progress
  244. //
  245. hr = StopConfiguringClients ();
  246. if (FAILED (hr)) {return (hr);}
  247. //
  248. // get the ISdoCollection interface now
  249. //
  250. hr = (pVarClients->pdispVal)->QueryInterface (
  251. __uuidof (ISdoCollection),
  252. reinterpret_cast <PVOID*> (&pISdoCollection)
  253. );
  254. if (FAILED (hr))
  255. {
  256. IASTracePrintf (
  257. "Unable to obtain SDO Collection during Clients Collection "
  258. "processing"
  259. );
  260. return (hr);
  261. }
  262. //
  263. // get the number of objects in the collection
  264. //
  265. hr = pISdoCollection->get_Count (&lCount);
  266. if (FAILED (hr))
  267. {
  268. IASTracePrintf (
  269. "Unable to obtain client object count during Clients Collection "
  270. "processing"
  271. );
  272. return (hr);
  273. }
  274. else if (0 == lCount)
  275. {
  276. DeleteObjects();
  277. return (hr);
  278. }
  279. //
  280. // allocate array of CClient* to temporarily store the CClient
  281. // objects till the addresses are resolved
  282. //
  283. m_pCClientArray = reinterpret_cast <CClient**> (
  284. ::CoTaskMemAlloc (
  285. sizeof (CClient*)*lCount)
  286. );
  287. if (NULL == m_pCClientArray)
  288. {
  289. IASTracePrintf (
  290. "Unable to allocate memory for Client object array "
  291. "during Clients collection processing"
  292. );
  293. hr = E_OUTOFMEMORY;
  294. return (hr);
  295. }
  296. //
  297. // get the enumerator for the clients collection
  298. //
  299. hr = pISdoCollection->get__NewEnum (
  300. reinterpret_cast <IUnknown**> (&pIUnknown)
  301. );
  302. if (FAILED (hr))
  303. {
  304. IASTracePrintf (
  305. "Unable to obtain enumeration object during "
  306. "Clients collection processing"
  307. );
  308. return (hr);
  309. }
  310. //
  311. // get the enum variant
  312. //
  313. hr = pIUnknown->QueryInterface (
  314. IID_IEnumVARIANT,
  315. reinterpret_cast <PVOID*> (&pIEnumVariant)
  316. );
  317. if (FAILED (hr))
  318. {
  319. IASTracePrintf (
  320. "Unable to obtain EnumVariant interface during "
  321. "Clients collection processing"
  322. );
  323. return (hr);
  324. }
  325. //
  326. // get clients out of the collection and initialize
  327. //
  328. hr = pIEnumVariant->Next (1, &varPerClient, &dwClientsLeft);
  329. if (FAILED (hr))
  330. {
  331. IASTracePrintf (
  332. "Unable to obtain variant object during "
  333. "Clients collection processing"
  334. );
  335. return (hr);
  336. }
  337. while ((dwClientsLeft > 0) && (dwCurrentIndex < lCount))
  338. {
  339. //
  340. // get an Sdo pointer from the variant we received
  341. //
  342. CComPtr <ISdo> pISdo;
  343. hr = varPerClient.pdispVal->QueryInterface (
  344. __uuidof (ISdo),
  345. reinterpret_cast <PVOID*> (&pISdo)
  346. );
  347. if (FAILED (hr))
  348. {
  349. IASTracePrintf (
  350. "Unable to obtain SDO interface during "
  351. "Clients collection processing"
  352. );
  353. return (hr);
  354. }
  355. //
  356. // create a new Client object now
  357. //
  358. hr = m_pIClassFactory->CreateInstance (
  359. NULL,
  360. __uuidof (CClient),
  361. reinterpret_cast <PVOID*> (&pIIasClient)
  362. );
  363. if (FAILED (hr))
  364. {
  365. IASTracePrintf (
  366. "Unable to create Client object from factory during "
  367. "Clients collection processing"
  368. );
  369. return (hr);
  370. }
  371. //
  372. // initalize the client
  373. //
  374. hr = pIIasClient->Init (pISdo);
  375. if (FAILED (hr))
  376. {
  377. IASTracePrintf (
  378. "Unable to initialize client object "
  379. "Clients collection processing"
  380. );
  381. //
  382. // delete this object
  383. //
  384. pIIasClient->Release ();
  385. }
  386. else
  387. {
  388. //
  389. // store this CClient class object in the
  390. // object array temporarily
  391. //
  392. m_pCClientArray[dwCurrentIndex] = pIIasClient;
  393. dwCurrentIndex++;
  394. }
  395. //
  396. // clear the perClient value from this variant
  397. //
  398. varPerClient.Clear ();
  399. //
  400. // get next client out of the collection
  401. //
  402. hr = pIEnumVariant->Next (1, &varPerClient, &dwClientsLeft);
  403. if (FAILED (hr))
  404. {
  405. IASTracePrintf (
  406. "Unable to obtain next variant object during "
  407. "Clients collection processing"
  408. );
  409. return (hr);
  410. }
  411. }
  412. //
  413. // we reset the event which will be set by the resolver thread
  414. // when its done and start the resolver thread
  415. //
  416. ::ResetEvent (m_hResolverEvent);
  417. m_bConfigure = TRUE;
  418. bStatus = ::IASRequestThread (::MakeBoundCallback (
  419. this,
  420. &CClients::Resolver,
  421. dwCurrentIndex
  422. )
  423. );
  424. if (FALSE == bStatus)
  425. {
  426. IASTracePrintf (
  427. "Unable to start client resolution thread "
  428. "Clients collection processing"
  429. );
  430. ::SetEvent (m_hResolverEvent);
  431. return (E_FAIL);
  432. }
  433. //
  434. // we have been successfully configured
  435. //
  436. return (S_OK);
  437. } // end of CClients::SetClients method
  438. //++--------------------------------------------------------------
  439. //
  440. // Function: FindObject
  441. //
  442. // Synopsis: This method finds a CClient class object from
  443. // the CClients collection and returns a reference
  444. // to it, without removing it from the collection
  445. //
  446. // Arguments: [in] DWORD - key
  447. // [out] IIasClient**
  448. //
  449. // Returns: NONE
  450. //
  451. //
  452. // History: MKarki Created 9/26/97
  453. //
  454. // Called By:
  455. //
  456. //----------------------------------------------------------------
  457. BOOL
  458. CClients::FindObject (
  459. DWORD dwKey,
  460. IIasClient **ppIIasClient
  461. )
  462. {
  463. EnterCriticalSection(&m_CritSect);
  464. IIasClient* client = m_mapClients.Find(dwKey);
  465. if (ppIIasClient != 0)
  466. {
  467. *ppIIasClient = client;
  468. if (client != 0)
  469. {
  470. client->AddRef();
  471. }
  472. }
  473. LeaveCriticalSection(&m_CritSect);
  474. return client != 0;
  475. }
  476. //++--------------------------------------------------------------
  477. //
  478. // Function: DeleteObjects
  479. //
  480. // Synopsis: This method deletes CClient objects from the
  481. // map
  482. //
  483. // Arguments: none
  484. //
  485. // Returns: VOID
  486. //
  487. // History: MKarki Created 4/4/98
  488. //
  489. // Called By: CClients destructor
  490. //
  491. //----------------------------------------------------------------
  492. VOID
  493. CClients::DeleteObjects (
  494. VOID
  495. )
  496. {
  497. m_mapClients.Clear();
  498. } // end of CClients::DeleteObjects method
  499. //++--------------------------------------------------------------
  500. //
  501. // Function: Resolver
  502. //
  503. // Synopsis: This is the CClients Private method that
  504. // resolves the client IP addresses
  505. //
  506. // Arguments: none
  507. //
  508. // Returns: VOID
  509. //
  510. // History: MKarki Created 4/12/98
  511. //
  512. // Called By: CClients::SetClients public method through
  513. // a worker thread
  514. //
  515. //----------------------------------------------------------------
  516. VOID
  517. CClients::Resolver (
  518. DWORD dwArraySize
  519. )
  520. {
  521. // Set up iterators for the clients array.
  522. CClient **i, **begin = m_pCClientArray, **end = begin + dwArraySize;
  523. // Resolve the client addresses.
  524. for (i = begin; i != end; ++i)
  525. {
  526. (*i)->ResolveAddress();
  527. }
  528. //////////
  529. // Update the client map.
  530. //////////
  531. EnterCriticalSection(&m_CritSect);
  532. DeleteObjects();
  533. try
  534. {
  535. for (i = begin; i != end; ++i)
  536. {
  537. const CClient::Address* paddr = (*i)->GetAddressList();
  538. for ( ; paddr->ipAddress != INADDR_NONE; ++paddr)
  539. {
  540. m_mapClients.Insert(SubNet(paddr->ipAddress, paddr->width), *i);
  541. }
  542. }
  543. }
  544. catch (...)
  545. {
  546. }
  547. LeaveCriticalSection(&m_CritSect);
  548. //////////
  549. // Clean up the array of client objects.
  550. //////////
  551. for (i = begin; i != end; ++i)
  552. {
  553. (*i)->Release();
  554. }
  555. CoTaskMemFree(m_pCClientArray);
  556. m_pCClientArray = NULL;
  557. // Set the event indicating that the Resolver thread is done
  558. SetEvent(m_hResolverEvent);
  559. }