Leaked source code of windows server 2003
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.

1476 lines
45 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_MCSNC);
  3. /*
  4. * privchnl.cpp
  5. *
  6. * Copyright (c) 1993 - 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the implementation file for the PrivateChannel class. It
  10. * contains the code that distinguishes this class from that of its parent,
  11. * Channel.
  12. *
  13. * This class maintains an authorized user list, and includes the code
  14. * necessary to use that list. No user will be allowed to join or send
  15. * data on a private channel unless they are either the channel manager
  16. * or an admitted user.
  17. *
  18. * Private Instance Variables:
  19. * m_uidChannelManager
  20. * This is the User ID of the user that convened the private channel.
  21. * Only this user is allowed to manipulate the authorized user list.
  22. * When a private channel becomes invalid (as the result of a channel
  23. * disband request or indication), this value will be set to 0.
  24. * m_AuthorizedUserList
  25. * This is a collection containing the user IDs of those users that
  26. * have been admitted to the private channel by the channel manager.
  27. * Other than the manager, these are the only users that are allowed
  28. * to join or send data on the channel. When a private channel becomes
  29. * invalid (as the result of a channel disband request or indication),
  30. * this list will be cleared.
  31. * m_fDisbandRequestPending
  32. * This is a boolean flag that gets set when a disband request is
  33. * forwarded upward to the top provider. This prevents this channel
  34. * from issuing a disband indication to the channel manager when it
  35. * comes back down the tree from the top provider.
  36. *
  37. * Private Member Functions:
  38. * ValidateUserID
  39. * This member function is called to verify that a specified user ID
  40. * corresponds to a valid user in the sub-tree of the local provider.
  41. * BuildAttachmentLists
  42. * This member function is called to build two lists of attachments
  43. * from a master user ID list. The first list contains all local
  44. * attachments whose user ID is in the specified list. The second
  45. * list contains all remote attachments whose user ID is in the
  46. * specified list. These lists are used to issue various indications
  47. * to specified users without sending any to the same attachment.
  48. * BuildUserIDList
  49. * This member function is called to build a list of users that lie
  50. * in the direction of a specified attachment. These lists are
  51. * sent along with PDUs that require them.
  52. *
  53. * Caveats:
  54. * None.
  55. *
  56. * Author:
  57. * James P. Galvin, Jr.
  58. */
  59. /*
  60. * External Interfaces
  61. */
  62. #include "privchnl.h"
  63. /*
  64. * PrivateChannel ()
  65. *
  66. * Public
  67. *
  68. * Functional Description:
  69. * This is the primary constructor for PrivateChannel objects. It creates
  70. * an object with all instance variable initialized, but with no
  71. * attachments (i.e. no users are joined to the channel automatically).
  72. *
  73. * Note that most instance variable initialization is done by invoking the
  74. * equivalent constructor in the base class.
  75. *
  76. * Upon successful completion, a channel convene confirm is automatically
  77. * issued to the channel manager, if the channel manager is in the sub-tree
  78. * of this provider. Note that if the channel manager is NOT in this
  79. * sub-tree, then this private channel object was probably created as the
  80. * result of a channel admit indication, and no channel convene confirm
  81. * will be issued.
  82. */
  83. PrivateChannel::PrivateChannel (
  84. ChannelID channel_id,
  85. UserID channel_manager,
  86. PDomain local_provider,
  87. PConnection top_provider,
  88. CChannelList2 *channel_list,
  89. CAttachmentList *attachment_list)
  90. :
  91. Channel(channel_id, local_provider, top_provider, channel_list, attachment_list),
  92. m_AuthorizedUserList(),
  93. m_uidChannelManager(channel_manager),
  94. m_fDisbandRequestPending(FALSE)
  95. {
  96. /*
  97. * Check to see if the channel manager lies in the sub-tree of this
  98. * provider. If so, then this object was created as the result of a
  99. * channel convene request or confirm, and it is necessary to issue the
  100. * confirm toward that user. If not, then this object was created as the
  101. * result of a channel admit indication, and it is not necessary to send
  102. * the channel convene confirm.
  103. */
  104. if (ValidateUserID(m_uidChannelManager))
  105. {
  106. PChannel lpChannel;
  107. /*
  108. * Determine which attachment leads to the channel manager by asking
  109. * the channel object corresponding to it. Then issue the confirm
  110. * to that attachment.
  111. */
  112. if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
  113. {
  114. CAttachment *pAtt = lpChannel->GetAttachment();
  115. if (pAtt)
  116. {
  117. pAtt->ChannelConveneConfirm(RESULT_SUCCESSFUL,
  118. m_uidChannelManager, channel_id);
  119. }
  120. else
  121. {
  122. ERROR_OUT(("PrivateChannel::PrivateChannel: null attachment"));
  123. }
  124. }
  125. }
  126. }
  127. /*
  128. * PrivateChannel ()
  129. *
  130. * Public
  131. *
  132. * Functional Description:
  133. * This is a secondary constructor that is only used during merge
  134. * operations. The intent of this constructor is to create an equivalent
  135. * object without issuing any of the confirms.
  136. *
  137. * Note that the additional constructor allows for the creator to specify
  138. * that there is an attachment already joined to the channel upon creation.
  139. */
  140. PrivateChannel::PrivateChannel (
  141. ChannelID channel_id,
  142. UserID channel_manager,
  143. PDomain local_provider,
  144. PConnection top_provider,
  145. CChannelList2 *channel_list,
  146. CAttachmentList *attachment_list,
  147. CUidList *admitted_list,
  148. PConnection pConn)
  149. :
  150. Channel(channel_id, local_provider, top_provider, channel_list, attachment_list, pConn),
  151. m_AuthorizedUserList(),
  152. m_uidChannelManager(channel_manager),
  153. m_fDisbandRequestPending(FALSE)
  154. {
  155. UserID uid;
  156. /*
  157. * Copy the initial contents of the admitted list into the authorized
  158. * user list.
  159. */
  160. admitted_list->Reset();
  161. while (NULL != (uid = admitted_list->Iterate()))
  162. {
  163. m_AuthorizedUserList.Append(uid);
  164. }
  165. }
  166. /*
  167. * ~PrivateChannel ()
  168. *
  169. * Public
  170. *
  171. * Functional Description:
  172. * This destructor walks through the admitted list, sending expel
  173. * indications to any admitted users that are locally attached. If the
  174. * channel manager is locally attached, and this channel is being deleted
  175. * a reason other than a previous disband request, then a disband
  176. * indication will be sent to the channel manager.
  177. */
  178. PrivateChannel::~PrivateChannel ()
  179. {
  180. CAttachmentList local_attachment_list;
  181. CAttachmentList remote_attachment_list;
  182. CAttachment *pAtt;
  183. CUidList user_id_list;
  184. /*
  185. * Assemble lists of the attachments that lead to authorized users in
  186. * the sub-tree of this provider.
  187. */
  188. BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
  189. &remote_attachment_list);
  190. /*
  191. * For each local attachment, issue a channel expel indication letting the
  192. * user know that the channel is no longer valid.
  193. */
  194. local_attachment_list.Reset();
  195. while (NULL != (pAtt = local_attachment_list.Iterate()))
  196. {
  197. /*
  198. * Get the next attachment from the list and build a list of the users
  199. * that lie in the direction of that attachment.
  200. */
  201. BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
  202. /*
  203. * Send the indication.
  204. */
  205. pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
  206. }
  207. /*
  208. * If the channel manager is a locally attached user, then send it a
  209. * ChannelDisbandIndication informing it that the channel is no longer
  210. * valid.
  211. */
  212. if ((m_fDisbandRequestPending == FALSE) && ValidateUserID(m_uidChannelManager))
  213. {
  214. PChannel lpChannel;
  215. if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
  216. {
  217. CAttachment *pAtt1 = lpChannel->GetAttachment();
  218. if (m_pAttachmentList->Find(pAtt1) && pAtt1->IsUserAttachment())
  219. {
  220. PUser pUser = (PUser) pAtt1;
  221. pUser->ChannelDisbandIndication(Channel_ID);
  222. }
  223. }
  224. }
  225. /*
  226. * Clear the lists associated with this object. Note that this also
  227. * prevents the base class destructor from issuing ChannelLeaveIndications
  228. * to any local attachments in the joined attachment list (which would be
  229. * inappropriate).
  230. */
  231. m_AuthorizedUserList.Clear();
  232. m_JoinedAttachmentList.Clear();
  233. }
  234. /*
  235. * Channel_Type GetChannelType ()
  236. *
  237. * Public
  238. *
  239. * Functional Description:
  240. * Objects of this class are always private channels, so simply return
  241. * PRIVATE_CHANNEL.
  242. */
  243. Channel_Type PrivateChannel::GetChannelType ()
  244. {
  245. return (PRIVATE_CHANNEL);
  246. }
  247. /*
  248. * BOOL IsValid ()
  249. *
  250. * Public
  251. *
  252. * Functional Description:
  253. * By convention, if the m_uidChannelManager is in the sub-tree of this
  254. * provider OR if there are any users in the authorized user list, then
  255. * the private channel is valid. Otherwise it is not, and can be deleted
  256. * by the domain object.
  257. */
  258. BOOL PrivateChannel::IsValid ()
  259. {
  260. UserID uid;
  261. CUidList deletion_list;
  262. /*
  263. * Loop through the authorized user list making a list of those entries
  264. * that are no longer valid.
  265. */
  266. m_AuthorizedUserList.Reset();
  267. while (NULL != (uid = m_AuthorizedUserList.Iterate()))
  268. {
  269. if (ValidateUserID(uid) == FALSE)
  270. deletion_list.Append(uid);
  271. }
  272. /*
  273. * Loop through the deletion list created above, deleting those user IDs
  274. * that are no longer valid.
  275. */
  276. deletion_list.Reset();
  277. while (NULL != (uid = deletion_list.Iterate()))
  278. {
  279. m_AuthorizedUserList.Remove(uid);
  280. }
  281. /*
  282. * If this is the Top Provider, then the channel manager should ALWAYS be
  283. * in the sub-tree. If it is not, then this indicates that the channel
  284. * manager has detached (willingly or otherwise). When this happens it
  285. * is necessary to simulate a channel disband request (only if there are
  286. * other admitted users who need to receive a channel expel indication).
  287. */
  288. if ((m_pConnToTopProvider == NULL) &&
  289. (ValidateUserID(m_uidChannelManager) == FALSE) &&
  290. (m_AuthorizedUserList.IsEmpty() == FALSE))
  291. {
  292. TRACE_OUT (("PrivateChannel::IsValid: "
  293. "simulating ChannelDisbandRequest"));
  294. ChannelDisbandRequest(NULL, m_uidChannelManager, Channel_ID);
  295. }
  296. /*
  297. * Check to see if the channel manager is in the sub-tree of this provider
  298. * or if the authorized user list is not empty. If either is TRUE, then
  299. * then the channel is still valid.
  300. */
  301. return (ValidateUserID(m_uidChannelManager) || (m_AuthorizedUserList.IsEmpty() == FALSE));
  302. }
  303. /*
  304. * CAttachment *GetAttachment ()
  305. *
  306. * Public
  307. *
  308. * Functional Description:
  309. * Return a pointer to the attachment leading to the channel manager.
  310. */
  311. CAttachment *PrivateChannel::GetAttachment(void)
  312. {
  313. if (ValidateUserID(m_uidChannelManager))
  314. {
  315. PChannel lpChannel;
  316. if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
  317. {
  318. return lpChannel->GetAttachment();
  319. }
  320. }
  321. return NULL;
  322. }
  323. /*
  324. * Void IssueMergeRequest ()
  325. *
  326. * Public
  327. *
  328. * Functional Description:
  329. * Issue a merge request for the information contained in this
  330. * PrivateChannel object.
  331. */
  332. Void PrivateChannel::IssueMergeRequest ()
  333. {
  334. ChannelAttributes channel_attributes;
  335. CChannelAttributesList merge_channel_list;
  336. CChannelIDList purge_channel_list;
  337. if (m_pConnToTopProvider != NULL)
  338. {
  339. /*
  340. * Fill in the fields of the channel attributes structure so that it
  341. * accurately describes this channel. Then put the structure into the
  342. * merge channel list.
  343. */
  344. channel_attributes.channel_type = PRIVATE_CHANNEL;
  345. if (m_JoinedAttachmentList.IsEmpty() )
  346. channel_attributes.u.private_channel_attributes.joined = FALSE;
  347. else
  348. channel_attributes.u.private_channel_attributes.joined = TRUE;
  349. channel_attributes.u.private_channel_attributes.channel_id = Channel_ID;
  350. channel_attributes.u.private_channel_attributes.channel_manager = m_uidChannelManager;
  351. channel_attributes.u.private_channel_attributes.admitted_list = &m_AuthorizedUserList;
  352. merge_channel_list.Append(&channel_attributes);
  353. /*
  354. * Send the merge request to the indicated provider.
  355. */
  356. m_pConnToTopProvider->MergeChannelsRequest(&merge_channel_list, &purge_channel_list);
  357. }
  358. }
  359. /*
  360. * Void ChannelJoinRequest ()
  361. *
  362. * Public
  363. *
  364. * Functional Description:
  365. * This function overrides the base class implementation. The main
  366. * difference is that this implementation only allows a user to join
  367. * the private channel if it is either the channel manager or in the
  368. * authorized user list.
  369. */
  370. Void PrivateChannel::ChannelJoinRequest (
  371. CAttachment *pOrigAtt,
  372. UserID uidInitiator,
  373. ChannelID channel_id)
  374. {
  375. /*
  376. * See if the requesting user is either the channel manager or in the
  377. * authorized user list.
  378. */
  379. if ((uidInitiator == m_uidChannelManager) || m_AuthorizedUserList.Find(uidInitiator))
  380. {
  381. /*
  382. * See if anyone is currently joined to the channel in this sub-tree
  383. */
  384. if (m_JoinedAttachmentList.IsEmpty())
  385. {
  386. /*
  387. * If this is the Top Provider, then this request can be handled
  388. * locally.
  389. */
  390. if (IsTopProvider())
  391. {
  392. /*
  393. * There is no one in this sub-tree joined to the channel. It
  394. * will therefore be necessary to add the originator to the
  395. * attachment list.
  396. */
  397. TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
  398. "user %04X joining private channel = %04X",
  399. (UINT) uidInitiator, (UINT) Channel_ID));
  400. m_JoinedAttachmentList.Append(pOrigAtt);
  401. /*
  402. * Send a ChannelJoinConfirm downward to the originator.
  403. */
  404. pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
  405. }
  406. else
  407. {
  408. /*
  409. * This is not the Top Provider. Forward the join request
  410. * upward to the Top Provider.
  411. */
  412. TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
  413. "forwarding join request to Top Provider"));
  414. m_pConnToTopProvider->ChannelJoinRequest(uidInitiator, Channel_ID);
  415. }
  416. }
  417. /*
  418. * There is at least one attachment joined to the channel, which means
  419. * that we do not have to forward the join request upward (even if
  420. * this is not the Top Provider). Now check to see if the requesting
  421. * originator is already joined to the channel.
  422. */
  423. else if (m_JoinedAttachmentList.Find(pOrigAtt) == FALSE)
  424. {
  425. /*
  426. * The originator is not yet joined to the channel, so add it to
  427. * the channel.
  428. */
  429. TRACE_OUT (("PrivateChannel::ChannelJoinRequest: "
  430. "user %04X joining private channel = %04X",
  431. (UINT) uidInitiator, (UINT) Channel_ID));
  432. m_JoinedAttachmentList.Append(pOrigAtt);
  433. /*
  434. * Send a ChannelJoinConfirm downward to the originator.
  435. */
  436. pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
  437. }
  438. else
  439. {
  440. /*
  441. * The originator is already joined to the channel. Go ahead and
  442. * issue a successful channel join confirm.
  443. */
  444. WARNING_OUT (("PrivateChannel::ChannelJoinRequest: "
  445. "already joined to channel"));
  446. pOrigAtt->ChannelJoinConfirm(RESULT_SUCCESSFUL, uidInitiator, channel_id, Channel_ID);
  447. }
  448. }
  449. else
  450. {
  451. /*
  452. * Someone is trying to join a private channel that they are not
  453. * admitted to. Reject the request without further processing.
  454. */
  455. WARNING_OUT (("PrivateChannel::ChannelJoinRequest: "
  456. "rejecting attempt to join private channel"));
  457. pOrigAtt->ChannelJoinConfirm(RESULT_NOT_ADMITTED, uidInitiator, channel_id, 0);
  458. }
  459. }
  460. /*
  461. * Void ChannelDisbandRequest ()
  462. *
  463. * Public
  464. *
  465. * Functional Description:
  466. * This MCS command is initially sent by a user that wishes to disband a
  467. * private channel that it previously created. If the requesting user is
  468. * the private channel manager, then the request will be processed. If
  469. * this is not the Top Provider, the request will be forwarded upward.
  470. */
  471. Void PrivateChannel::ChannelDisbandRequest (
  472. CAttachment *,
  473. UserID uidInitiator,
  474. ChannelID)
  475. {
  476. CUidList user_id_list;
  477. /*
  478. * Check to see if the requesting user is the channel manager. Only
  479. * process the request if it is.
  480. */
  481. if (uidInitiator == m_uidChannelManager)
  482. {
  483. /*
  484. * See if this is the Top Provider. If it is, then the request can
  485. * be processed locally. Otherwise, pass the request upward toward
  486. * the Top Provider.
  487. */
  488. if (IsTopProvider())
  489. {
  490. CAttachmentList local_attachment_list;
  491. CAttachmentList remote_attachment_list;
  492. CAttachment *pAtt;
  493. TRACE_OUT (("PrivateChannel::ChannelDisbandRequest: "
  494. "disbanding channel = %04X", Channel_ID));
  495. /*
  496. * Go construct lists of the current unique local and remote
  497. * attachments. These lists will be used to transmit the proper
  498. * channel expel and channel disband indications.
  499. */
  500. BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
  501. &remote_attachment_list);
  502. /*
  503. * It is also necessary to send the disband indication to the
  504. * channel manager, if it is valid and in the sub-tree of this
  505. * provider. Determine what attachment leads to the channel
  506. * manager, and make sure that attachment is in the remote
  507. * attachment list, if valid.
  508. */
  509. if (ValidateUserID(m_uidChannelManager))
  510. {
  511. PChannel lpChannel;
  512. if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
  513. {
  514. pAtt = lpChannel->GetAttachment();
  515. if (m_pAttachmentList->Find(pAtt) && pAtt->IsConnAttachment())
  516. {
  517. if (remote_attachment_list.Find(pAtt) == FALSE)
  518. {
  519. remote_attachment_list.Append(pAtt);
  520. }
  521. }
  522. }
  523. else
  524. {
  525. ERROR_OUT(("PrivateChannel::ChannelDisbandRequest: can't locate channel"));
  526. }
  527. }
  528. /*
  529. * Loop through the local attachment list sending channel expel
  530. * indications to each attachment contained therein.
  531. */
  532. local_attachment_list.Reset();
  533. while (NULL != (pAtt = local_attachment_list.Iterate()))
  534. {
  535. /*
  536. * Get the next attachment from the list and build a list of
  537. * the users that lie in the direction of that attachment.
  538. */
  539. BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
  540. /*
  541. * Send the expel indication to the locally attached user.
  542. */
  543. pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
  544. }
  545. /*
  546. * Loop through the remote attachment list sending channel disband
  547. * indications to each attachment contained therein.
  548. */
  549. remote_attachment_list.Reset();
  550. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  551. {
  552. /*
  553. * Send the disband indication to the remotely attached
  554. * provider.
  555. */
  556. pAtt->ChannelDisbandIndication(Channel_ID);
  557. }
  558. /*
  559. * Set m_uidChannelManager to 0 and clear the authorized user list as
  560. * an indicator that this private channel object is no longer
  561. * valid, and cannot be used. The next time the domain object
  562. * calls IsValid, it will return FALSE allowing the domain object
  563. * to delete this object.
  564. */
  565. m_uidChannelManager = 0;
  566. m_AuthorizedUserList.Clear();
  567. }
  568. else
  569. {
  570. /*
  571. * Set a flag indicating that a disband request has been sent
  572. * upward. This flag will be used to prevent a disband indication
  573. * from being sent to the channel manager as it flows back down
  574. * the domain tree.
  575. */
  576. m_fDisbandRequestPending = TRUE;
  577. /*
  578. * This is not the Top Provider, so forward the request toward
  579. * the Top Provider. This will result in a channel disband
  580. * indication at a future time.
  581. */
  582. TRACE_OUT (("PrivateChannel::ChannelDisbandRequest: "
  583. "forwarding request to Top Provider"));
  584. m_pConnToTopProvider->ChannelDisbandRequest(uidInitiator, Channel_ID);
  585. }
  586. }
  587. else
  588. {
  589. /*
  590. * Someone is trying to disband a private channel that they are not
  591. * the channel manager for. Ignore the request.
  592. */
  593. WARNING_OUT (("PrivateChannel::ChannelDisbandRequest: "
  594. "ignoring request from non-channel manager"));
  595. }
  596. }
  597. /*
  598. * Void ChannelDisbandIndication ()
  599. *
  600. * Public
  601. *
  602. * Functional Description:
  603. * This MCS command is initially sent by the Top Provider when it decides
  604. * to delete a private channel from the domain. It travels downward to
  605. * all attachments and connections that contain an admitted user or the
  606. * channel manager in their sub-tree.
  607. */
  608. Void PrivateChannel::ChannelDisbandIndication (
  609. ChannelID)
  610. {
  611. CAttachmentList local_attachment_list;
  612. CAttachmentList remote_attachment_list;
  613. CAttachment *pAtt;
  614. CUidList user_id_list;
  615. TRACE_OUT (("PrivateChannel::ChannelDisbandIndication: "
  616. "disbanding channel = %04X", Channel_ID));
  617. /*
  618. * Build the lists of unique local and remote attachments. These lists
  619. * will be used to issue the appropriate indications.
  620. */
  621. BuildAttachmentLists (&m_AuthorizedUserList, &local_attachment_list,
  622. &remote_attachment_list);
  623. /*
  624. * It is also necessary to send the disband indication to the channel
  625. * manager, if it is valid and in the sub-tree of this provider.
  626. * Determine what attachment leads to the channel manager, and make sure
  627. * that attachment is in the remote attachment list, if valid.
  628. */
  629. if (ValidateUserID(m_uidChannelManager))
  630. {
  631. PChannel lpChannel;
  632. if (NULL != (lpChannel = m_pChannelList2->Find(m_uidChannelManager)))
  633. {
  634. pAtt = lpChannel->GetAttachment();
  635. if ((m_fDisbandRequestPending == FALSE) ||
  636. (m_pAttachmentList->Find(pAtt) && pAtt->IsConnAttachment()))
  637. {
  638. if (remote_attachment_list.Find(pAtt) == FALSE)
  639. {
  640. remote_attachment_list.Append(pAtt);
  641. }
  642. }
  643. }
  644. else
  645. {
  646. ERROR_OUT(("PrivateChannel::ChannelDisbandIndication: can't locate channel"));
  647. }
  648. }
  649. /*
  650. * Loop through the local attachment list sending channel expel indications
  651. * to each attachment contained therein.
  652. */
  653. local_attachment_list.Reset();
  654. while (NULL != (pAtt = local_attachment_list.Iterate()))
  655. {
  656. /*
  657. * Get the next attachment from the list and build a list of
  658. * the users that lie in the direction of that attachment.
  659. */
  660. BuildUserIDList(&m_AuthorizedUserList, pAtt, &user_id_list);
  661. /*
  662. * Send the expel indication to the locally attached user.
  663. */
  664. pAtt->ChannelExpelIndication(Channel_ID, &user_id_list);
  665. }
  666. /*
  667. * Loop through the remote attachment list sending channel disband
  668. * indications to each attachment contained therein.
  669. */
  670. remote_attachment_list.Reset();
  671. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  672. {
  673. /*
  674. * Send the disband indication to the remotely attached provider.
  675. */
  676. pAtt->ChannelDisbandIndication(Channel_ID);
  677. }
  678. /*
  679. * Set m_uidChannelManager to 0 and clear the authorized user list as an
  680. * indicator that this private channel object is no longer valid, and
  681. * cannot be used. The next time the domain object calls IsValid, it will
  682. * return FALSE allowing the domain object to delete this object.
  683. */
  684. m_uidChannelManager = 0;
  685. m_AuthorizedUserList.Clear();
  686. }
  687. /*
  688. * Void ChannelAdmitRequest ()
  689. *
  690. * Public
  691. *
  692. * Functional Description:
  693. * This MCS command is initially sent by the manager of a private channel
  694. * when it wishes to expand the authorized user list of that channel. If
  695. * this is the Top Provider, then the request can be handled locally.
  696. * Otherwise, it must be forwarded upward to the Top Provider.
  697. */
  698. Void PrivateChannel::ChannelAdmitRequest (
  699. CAttachment *,
  700. UserID uidInitiator,
  701. ChannelID,
  702. CUidList *user_id_list)
  703. {
  704. UserID uid;
  705. CUidList admitted_id_list;
  706. CUidList user_id_subset;
  707. /*
  708. * Check to see if the requesting user is the channel manager. Only
  709. * process the request if it is.
  710. */
  711. if (uidInitiator == m_uidChannelManager)
  712. {
  713. /*
  714. * See if this is the Top Provider. If it is, then the request can
  715. * be processed locally. Otherwise, pass the request upward toward
  716. * the Top Provider.
  717. */
  718. if (IsTopProvider())
  719. {
  720. CAttachmentList local_attachment_list;
  721. CAttachmentList remote_attachment_list;
  722. CAttachment *pAtt;
  723. TRACE_OUT (("PrivateChannel::ChannelAdmitRequest: "
  724. "admitting users to channel = %04X", Channel_ID));
  725. /*
  726. * Iterate through the list of users to be admitted, adding all
  727. * valid users to the local authorized user list.
  728. */
  729. user_id_list->Reset();
  730. while (NULL != (uid = user_id_list->Iterate()))
  731. {
  732. /*
  733. * Make sure that the user ID corresponds to a valid user in
  734. * the domain.
  735. */
  736. if (ValidateUserID(uid))
  737. {
  738. /*
  739. * If the user is not already in the authorized user list,
  740. * then add it.
  741. */
  742. if (m_AuthorizedUserList.Find(uid) == FALSE)
  743. {
  744. m_AuthorizedUserList.Append(uid);
  745. admitted_id_list.Append(uid);
  746. }
  747. }
  748. }
  749. /*
  750. * Build lists of unique attachments which can then be used to
  751. * issue the appropriate admit indications. This prevents the
  752. * transmission of an admit indication to the same attachment more
  753. * than once.
  754. */
  755. BuildAttachmentLists (&admitted_id_list, &local_attachment_list,
  756. &remote_attachment_list);
  757. /*
  758. * Iterate through the local attachment list issuing an admit
  759. * indication to each attachment contained therein.
  760. */
  761. local_attachment_list.Reset();
  762. while (NULL != (pAtt = local_attachment_list.Iterate()))
  763. {
  764. /*
  765. * Get the next attachment from the list and build a list of
  766. * the users that lie in the direction of that attachment.
  767. */
  768. BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
  769. /*
  770. * Send the admit indication to the named attachment.
  771. */
  772. pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
  773. }
  774. /*
  775. * Iterate through the remote attachment list issuing an admit
  776. * indication to each attachment contained therein.
  777. */
  778. remote_attachment_list.Reset();
  779. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  780. {
  781. /*
  782. * Get the next attachment from the list and build a list of
  783. * the users that lie in the direction of that attachment.
  784. */
  785. BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
  786. /*
  787. * Send the admit indication to the named attachment.
  788. */
  789. pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
  790. }
  791. }
  792. else
  793. {
  794. /*
  795. * This is not the Top Provider, so forward the request toward
  796. * the Top Provider. This will result in a channel admit
  797. * indication at a future time.
  798. */
  799. TRACE_OUT (("PrivateChannel::ChannelAdmitRequest: "
  800. "forwarding request to Top Provider"));
  801. m_pConnToTopProvider->ChannelAdmitRequest(uidInitiator, Channel_ID, user_id_list);
  802. }
  803. }
  804. else
  805. {
  806. /*
  807. * Someone is trying to admit users to a private channel that they are
  808. * not the channel manager for. Ignore the request.
  809. */
  810. WARNING_OUT (("PrivateChannel::ChannelAdmitRequest: "
  811. "ignoring request from non-channel manager"));
  812. }
  813. }
  814. /*
  815. * Void ChannelAdmitIndication ()
  816. *
  817. * Public
  818. *
  819. * Functional Description:
  820. * This MCS command is initially sent by the Top Provider when it receives
  821. * a channel admit indication from the manager of a private channel. This
  822. * indication is broadcast downward to all providers that contain an
  823. * admitted user somewhere in their sub-tree. A side-effect of this
  824. * indication is that a private channel will be created in the information
  825. * base if one does not already exist.
  826. */
  827. Void PrivateChannel::ChannelAdmitIndication (
  828. PConnection,
  829. UserID uidInitiator,
  830. ChannelID,
  831. CUidList *user_id_list)
  832. {
  833. UserID uid;
  834. CUidList admitted_id_list;
  835. CAttachmentList local_attachment_list;
  836. CAttachmentList remote_attachment_list;
  837. CAttachment *pAtt;
  838. CUidList user_id_subset;
  839. TRACE_OUT (("PrivateChannel::ChannelAdmitIndication: "
  840. "admitting users to channel = %04X", (UINT) Channel_ID));
  841. /*
  842. * Iterate through the list of users to be admitted, adding all
  843. * valid users to the local authorized user list.
  844. */
  845. user_id_list->Reset();
  846. while (NULL != (uid = user_id_list->Iterate()))
  847. {
  848. /*
  849. * Make sure that the user ID corresponds to a valid user in
  850. * the domain.
  851. */
  852. if (ValidateUserID(uid))
  853. {
  854. /*
  855. * If the user is not already in the authorized user list,
  856. * then add it.
  857. */
  858. if (m_AuthorizedUserList.Find(uid) == FALSE)
  859. {
  860. m_AuthorizedUserList.Append(uid);
  861. admitted_id_list.Append(uid);
  862. }
  863. }
  864. }
  865. /*
  866. * Build lists of unique attachments which can then be used to
  867. * issue the appropriate admit indications. This prevents the
  868. * transmission of an admit indication to the same attachment more
  869. * than once.
  870. */
  871. BuildAttachmentLists (&admitted_id_list, &local_attachment_list,
  872. &remote_attachment_list);
  873. /*
  874. * Iterate through the local attachment list issuing an admit
  875. * indication to each attachment contained therein.
  876. */
  877. local_attachment_list.Reset();
  878. while (NULL != (pAtt = local_attachment_list.Iterate()))
  879. {
  880. /*
  881. * Get the next attachment from the list and build a list of
  882. * the users that lie in the direction of that attachment.
  883. */
  884. BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
  885. /*
  886. * Send the admit indication to the named attachment.
  887. */
  888. pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
  889. }
  890. /*
  891. * Iterate through the remote attachment list issuing an admit
  892. * indication to each attachment contained therein.
  893. */
  894. remote_attachment_list.Reset();
  895. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  896. {
  897. /*
  898. * Get the next attachment from the list and build a list of
  899. * the users that lie in the direction of that attachment.
  900. */
  901. BuildUserIDList(&admitted_id_list, pAtt, &user_id_subset);
  902. /*
  903. * Send the admit indication to the named attachment.
  904. */
  905. pAtt->ChannelAdmitIndication(uidInitiator, Channel_ID, &user_id_subset);
  906. }
  907. }
  908. /*
  909. * Void ChannelExpelRequest ()
  910. *
  911. * Public
  912. *
  913. * Functional Description:
  914. * This MCS command is initially sent by the manager of a private channel
  915. * when it wishes to shrink the authorized user list of that channel. If
  916. * the channel is in the local information base, the request is sent to it.
  917. * Otherwise, the request is ignored.
  918. */
  919. Void PrivateChannel::ChannelExpelRequest (
  920. CAttachment *,
  921. UserID uidInitiator,
  922. ChannelID,
  923. CUidList *user_id_list)
  924. {
  925. UserID uid;
  926. CUidList expelled_id_list;
  927. CUidList user_id_subset;
  928. /*
  929. * Check to see if the requesting user is the channel manager. Only
  930. * process the request if it is.
  931. */
  932. if (uidInitiator == m_uidChannelManager)
  933. {
  934. /*
  935. * See if this is the Top Provider. If it is, then the request can
  936. * be processed locally. Otherwise, pass the request upward toward
  937. * the Top Provider.
  938. */
  939. if (m_pConnToTopProvider == NULL)
  940. {
  941. CAttachmentList local_attachment_list;
  942. CAttachmentList remote_attachment_list;
  943. CAttachment *pAtt;
  944. TRACE_OUT (("PrivateChannel::ChannelExpelRequest: "
  945. "expelling users from channel = %04X", Channel_ID));
  946. /*
  947. * Iterate through the list of users to be expelled, removing all
  948. * valid users from the local authorized user list.
  949. */
  950. user_id_list->Reset();
  951. while (NULL != (uid = user_id_list->Iterate()))
  952. {
  953. /*
  954. * If the user is in the authorized user list, then remove it.
  955. */
  956. if (m_AuthorizedUserList.Find(uid))
  957. {
  958. m_AuthorizedUserList.Remove(uid);
  959. expelled_id_list.Append(uid);
  960. }
  961. }
  962. /*
  963. * Build lists of unique attachments which can then be used to
  964. * issue the appropriate expel indications. This prevents the
  965. * transmission of an expel indication to the same attachment more
  966. * than once.
  967. */
  968. BuildAttachmentLists (&expelled_id_list, &local_attachment_list,
  969. &remote_attachment_list);
  970. /*
  971. * Iterate through the local attachment list issuing an expel
  972. * indication to each attachment contained therein.
  973. */
  974. local_attachment_list.Reset();
  975. while (NULL != (pAtt = local_attachment_list.Iterate()))
  976. {
  977. /*
  978. * Get the next attachment from the list and build a list of
  979. * the users that lie in the direction of that attachment.
  980. */
  981. BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
  982. /*
  983. * Send the expel indication to the named attachment.
  984. */
  985. pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
  986. /*
  987. * Since this is a locally attached user, it is necessary to
  988. * simulate a channel leave request from the user, indicating
  989. * the fact that it can no longer use the channel.
  990. */
  991. ChannelLeaveRequest(pAtt, (CChannelIDList *) &user_id_subset);
  992. }
  993. /*
  994. * Iterate through the remote attachment list issuing an expel
  995. * indication to each attachment contained therein.
  996. */
  997. remote_attachment_list.Reset();
  998. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  999. {
  1000. /*
  1001. * Get the next attachment from the list and build a list of
  1002. * the users that lie in the direction of that attachment.
  1003. */
  1004. BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
  1005. /*
  1006. * Send the expel indication to the named attachment.
  1007. */
  1008. pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
  1009. }
  1010. }
  1011. else
  1012. {
  1013. /*
  1014. * This is not the Top Provider, so forward the request toward
  1015. * the Top Provider. This will result in a channel expel
  1016. * indication at a future time.
  1017. */
  1018. TRACE_OUT (("PrivateChannel::ChannelExpelRequest: "
  1019. "forwarding request to Top Provider"));
  1020. m_pConnToTopProvider->ChannelExpelRequest(uidInitiator, Channel_ID, user_id_list);
  1021. }
  1022. }
  1023. else
  1024. {
  1025. /*
  1026. * Someone is trying to admit users to a private channel that they are
  1027. * not the channel manager for. Ignore the request.
  1028. */
  1029. WARNING_OUT (("PrivateChannel::ChannelExpelRequest: "
  1030. "ignoring request from non-channel manager"));
  1031. }
  1032. }
  1033. /*
  1034. * Void ChannelExpelIndication ()
  1035. *
  1036. * Public
  1037. *
  1038. * Functional Description:
  1039. * This MCS command is initially sent by the Top Provider when it receives
  1040. * a request from the manager of a private channel to reduce the
  1041. * authorized user list. It travels downward to all attachments and
  1042. * connections that contain an admitted user or the channel manager in
  1043. * their sub-tree.
  1044. */
  1045. Void PrivateChannel::ChannelExpelIndication (
  1046. PConnection,
  1047. ChannelID,
  1048. CUidList *user_id_list)
  1049. {
  1050. UserID uid;
  1051. CUidList expelled_id_list;
  1052. CAttachmentList local_attachment_list;
  1053. CAttachmentList remote_attachment_list;
  1054. CAttachment *pAtt;
  1055. CUidList user_id_subset;
  1056. TRACE_OUT (("PrivateChannel::ChannelExpelIndication: "
  1057. "expelling users from channel = %04X", Channel_ID));
  1058. /*
  1059. * Iterate through the list of users to be expelled, removing all
  1060. * valid users from the local authorized user list.
  1061. */
  1062. user_id_list->Reset();
  1063. while (NULL != (uid = user_id_list->Iterate()))
  1064. {
  1065. /*
  1066. * If the user is in the authorized user list, then remove it.
  1067. */
  1068. if (m_AuthorizedUserList.Find(uid))
  1069. {
  1070. m_AuthorizedUserList.Remove(uid);
  1071. expelled_id_list.Append(uid);
  1072. }
  1073. }
  1074. /*
  1075. * Build lists of unique attachments which can then be used to
  1076. * issue the appropriate expel indications. This prevents the
  1077. * transmission of an expel indication to the same attachment more
  1078. * than once.
  1079. */
  1080. BuildAttachmentLists (&expelled_id_list, &local_attachment_list,
  1081. &remote_attachment_list);
  1082. /*
  1083. * Iterate through the local attachment list issuing an expel
  1084. * indication to each attachment contained therein.
  1085. */
  1086. local_attachment_list.Reset();
  1087. while (NULL != (pAtt = local_attachment_list.Iterate()))
  1088. {
  1089. /*
  1090. * Get the next attachment from the list and build a list of
  1091. * the users that lie in the direction of that attachment.
  1092. */
  1093. BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
  1094. /*
  1095. * Send the expel indication to the named attachment.
  1096. */
  1097. pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
  1098. /*
  1099. * Since this is a locally attached user, it is necessary to
  1100. * simulate a channel leave request from the user, indicating
  1101. * the fact that it can no longer use the channel.
  1102. */
  1103. ChannelLeaveRequest(pAtt, (CChannelIDList *) &user_id_subset);
  1104. }
  1105. /*
  1106. * Iterate through the remote attachment list issuing an expel
  1107. * indication to each attachment contained therein.
  1108. */
  1109. remote_attachment_list.Reset();
  1110. while (NULL != (pAtt = remote_attachment_list.Iterate()))
  1111. {
  1112. /*
  1113. * Get the next attachment from the list and build a list of
  1114. * the users that lie in the direction of that attachment.
  1115. */
  1116. BuildUserIDList(&expelled_id_list, pAtt, &user_id_subset);
  1117. /*
  1118. * Send the expel indication to the named attachment.
  1119. */
  1120. pAtt->ChannelExpelIndication(Channel_ID, &user_id_subset);
  1121. }
  1122. }
  1123. /*
  1124. * Void SendDataRequest ()
  1125. *
  1126. * Public
  1127. *
  1128. * Functional Description:
  1129. * This MCS command is initially sent by a user that wishes to send data
  1130. * to other users who are joined to a specified channel. This routine
  1131. * is executed in the case that it is a private channel. It verifies
  1132. * that the user is authorized to use the channel before allowing the data
  1133. * to be sent.
  1134. */
  1135. Void PrivateChannel::SendDataRequest (
  1136. CAttachment *pOrigAtt,
  1137. UINT type,
  1138. PDataPacket data_packet)
  1139. {
  1140. UserID uidInitiator;
  1141. uidInitiator = data_packet->GetInitiator();
  1142. if ((uidInitiator == m_uidChannelManager) || m_AuthorizedUserList.Find(uidInitiator))
  1143. {
  1144. /*
  1145. * The channel usage is authorized, so forward the request to the
  1146. * base class implementation for processing.
  1147. */
  1148. Channel::SendDataRequest(pOrigAtt, type, data_packet);
  1149. }
  1150. else
  1151. {
  1152. /*
  1153. * Someone is trying to send data on a private channel that they are
  1154. * not authorized to use. Ignore the request.
  1155. */
  1156. WARNING_OUT (("PrivateChannel::SendDataRequest: "
  1157. "ignoring request from non-authorized user"));
  1158. }
  1159. }
  1160. /*
  1161. * BOOL ValidateUserID ()
  1162. *
  1163. * Private
  1164. *
  1165. * Functional Description:
  1166. * This function is called whenever another member function of this class
  1167. * wants to check and see if a specified user is still valid in the
  1168. * domain channel list.
  1169. *
  1170. * Formal Parameters:
  1171. * user_id (i)
  1172. * This is the ID of the user being checked out.
  1173. *
  1174. * Return Value:
  1175. * TRUE if the user is valid. FALSE otherwise.
  1176. *
  1177. * Side Effects:
  1178. * None.
  1179. */
  1180. BOOL PrivateChannel::ValidateUserID (
  1181. UserID user_id)
  1182. {
  1183. PChannel channel;
  1184. /*
  1185. * First check to see if the user ID is in the channel list at all. This
  1186. * prevents an attempt to read an invalid entry from the dictionary.
  1187. */
  1188. if (NULL != (channel = m_pChannelList2->Find(user_id)))
  1189. {
  1190. /*
  1191. * We know that the ID is in the dictionary, but we don't know for sure
  1192. * whether or not it is a user ID channel. So check this. If it is a
  1193. * user channel, then set the valid flag to TRUE.
  1194. */
  1195. if (channel->GetChannelType () == USER_CHANNEL)
  1196. return TRUE;
  1197. }
  1198. return FALSE;
  1199. }
  1200. /*
  1201. * Void BuildAttachmentLists ()
  1202. *
  1203. * Private
  1204. *
  1205. * Functional Description:
  1206. * This function is called upon to build a list of unique attachments that
  1207. * lead to the users in the specified list. It builds two attachment
  1208. * lists. The first has an entry for each unique local attachment. The
  1209. * second for each remote attachment. The key to each list is the
  1210. * attachment.
  1211. *
  1212. * Formal Parameters:
  1213. * user_id_list (i)
  1214. * This is the list of users for which the list is to be built.
  1215. * local_attachment_list (i)
  1216. * This is the dictionary that is to contain the list of unique
  1217. * local attachments.
  1218. * remote_attachment_list (i)
  1219. * This is the dictionary that is to contain the list of unique
  1220. * remote attachments.
  1221. *
  1222. * Return Value:
  1223. * None.
  1224. *
  1225. * Side Effects:
  1226. * None.
  1227. */
  1228. Void PrivateChannel::BuildAttachmentLists (
  1229. CUidList *user_id_list,
  1230. CAttachmentList *local_attachment_list,
  1231. CAttachmentList *remote_attachment_list)
  1232. {
  1233. UserID uid;
  1234. /*
  1235. * Loop through the passed in user ID list building a dictionary of local
  1236. * attachments (those leading to locally attached users) and a dictionary
  1237. * of remote attachments (those leading to remotely connected providers).
  1238. * These dictionaries will be used by this provider to issue various
  1239. * indications downward, without sending multiple indications to the same
  1240. * attachment.
  1241. */
  1242. user_id_list->Reset();
  1243. while (NULL != (uid = user_id_list->Iterate()))
  1244. {
  1245. /*
  1246. * Check to see if the user ID refers to a valid user in the sub-tree
  1247. * of this provider.
  1248. */
  1249. if (ValidateUserID(uid))
  1250. {
  1251. PChannel lpChannel;
  1252. /*
  1253. * Determine which attachment leads to the user in question.
  1254. */
  1255. if (NULL != (lpChannel = m_pChannelList2->Find(uid)))
  1256. {
  1257. CAttachment *pAtt = lpChannel->GetAttachment();
  1258. /*
  1259. * This module builds separate lists for those users that are
  1260. * attached locally and those attached remotely.
  1261. */
  1262. if (m_pAttachmentList->Find(pAtt))
  1263. {
  1264. if (pAtt->IsUserAttachment())
  1265. {
  1266. /*
  1267. * This attachment is a local one (meaning that it leads to a
  1268. * locally attached user, rather than another MCS provider).
  1269. * Check to see if this attachment has already been put into
  1270. * the dictionary while processing a previous user ID.
  1271. */
  1272. if (local_attachment_list->Find(pAtt) == FALSE)
  1273. local_attachment_list->Append(pAtt);
  1274. }
  1275. else
  1276. {
  1277. /*
  1278. * This attachment is a remote one (meaning that it leads to
  1279. * another MCS provider, rather than a locally attached user).
  1280. * Check to see if this attachment has already been put into
  1281. * the dictionary while processing a previous user ID.
  1282. */
  1283. if (remote_attachment_list->Find(pAtt) == FALSE)
  1284. remote_attachment_list->Append(pAtt);
  1285. }
  1286. }
  1287. else
  1288. {
  1289. ERROR_OUT(("PrivateChannel::BuildAttachmentLists: can't find this attachment=0x%p", pAtt));
  1290. }
  1291. }
  1292. else
  1293. {
  1294. ERROR_OUT(("PrivateChannel::BuildAttachmentLists: can't locate channel"));
  1295. }
  1296. }
  1297. else
  1298. {
  1299. /*
  1300. * This user ID does not correspond to a valid user in the sub-tree
  1301. * of this provider. Therefore, discard the ID.
  1302. */
  1303. ERROR_OUT (("PrivateChannel::BuildAttachmentLists: "
  1304. "ERROR - user ID not valid"));
  1305. }
  1306. }
  1307. }
  1308. /*
  1309. * Void BuildUserIDList ()
  1310. *
  1311. * Private
  1312. *
  1313. * Functional Description:
  1314. * This function is called upon to build a list of all users in the
  1315. * specified list that are in the direction of the specified attachment.
  1316. *
  1317. * Formal Parameters:
  1318. * user_id_list (i)
  1319. * This is the list of users for which the list is to be built.
  1320. * attachment (i)
  1321. * This is the attachment that the caller wishes to have a list of
  1322. * user IDs for.
  1323. * user_id_subset (o)
  1324. * This is the subset of the passed in user IDs that are in the
  1325. * direction of the specified attachment.
  1326. *
  1327. * Return Value:
  1328. * None.
  1329. *
  1330. * Side Effects:
  1331. * None.
  1332. */
  1333. Void PrivateChannel::BuildUserIDList (
  1334. CUidList *user_id_list,
  1335. CAttachment *pAtt,
  1336. CUidList *user_id_subset)
  1337. {
  1338. UserID uid;
  1339. /*
  1340. * Clear out the subset list, so that we start fresh.
  1341. */
  1342. user_id_subset->Clear();
  1343. /*
  1344. * Loop through the specified user list, checking to see which users
  1345. * lie in the direction of the specified attachment.
  1346. */
  1347. user_id_list->Reset();
  1348. while (NULL != (uid = user_id_list->Iterate()))
  1349. {
  1350. /*
  1351. * Check to see if the user ID refers to a valid user in the sub-tree
  1352. * of this provider.
  1353. */
  1354. if (ValidateUserID(uid))
  1355. {
  1356. PChannel lpChannel;
  1357. /*
  1358. * Check to see if this user is the direction of the specified
  1359. * attachment. If it is, then put it into the user ID subset that
  1360. * we are building.
  1361. */
  1362. if (NULL != (lpChannel = m_pChannelList2->Find(uid)))
  1363. {
  1364. if (lpChannel->GetAttachment () == pAtt)
  1365. user_id_subset->Append(uid);
  1366. }
  1367. else
  1368. {
  1369. ERROR_OUT(("PrivateChannel::BuildUserIDList: can't locate channel"));
  1370. }
  1371. }
  1372. else
  1373. {
  1374. /*
  1375. * This user ID does not correspond to a valid user in the sub-tree
  1376. * of this provider. Therefore, discard the ID.
  1377. */
  1378. ERROR_OUT (("PrivateChannel::BuildUserIDList: "
  1379. "ERROR - user ID not valid"));
  1380. }
  1381. }
  1382. }
  1383.