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.

609 lines
22 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/callcon2.c_v $
  4. *
  5. * INTEL Corporation Prorietary Information
  6. *
  7. * This listing is supplied under the terms of a license agreement
  8. * with INTEL Corporation and may not be copied nor disclosed except
  9. * in accordance with the terms of that agreement.
  10. *
  11. * Copyright (c) 1996 Intel Corporation.
  12. *
  13. * $Revision: 1.35 $
  14. * $Date: 03 Mar 1997 09:08:16 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. * Notes:
  22. *
  23. ***************************************************************************/
  24. #ifdef GATEKEEPER
  25. #include "precomp.h"
  26. #include "apierror.h"
  27. #include "incommon.h"
  28. #include "callcont.h"
  29. #include "q931.h"
  30. #include "ccmain.h"
  31. #include "confman.h"
  32. #include "listman.h"
  33. #include "q931man.h"
  34. #include "h245man.h"
  35. #include "callman.h"
  36. #include "userman.h"
  37. #include "chanman.h"
  38. #include "hangman.h"
  39. #include "linkapi.h"
  40. #include "h245api.h"
  41. #include "ccutils.h"
  42. #include "callman2.h"
  43. #define HResultLeave(x) return x
  44. extern CC_CONFERENCEID InvalidConferenceID;
  45. //
  46. // Complete CC_xxx Operations
  47. //
  48. HRESULT ListenReject (CC_HLISTEN hListen, HRESULT Reason)
  49. {
  50. HRESULT status;
  51. PLISTEN pListen;
  52. CC_LISTEN_CALLBACK_PARAMS ListenCallbackParams;
  53. ASSERT(GKIExists());
  54. status = LockListen(hListen, &pListen);
  55. if (status == CC_OK) {
  56. ListenCallbackParams.hCall = CC_INVALID_HANDLE;
  57. ListenCallbackParams.pCallerAliasNames = NULL;
  58. ListenCallbackParams.pCalleeAliasNames = NULL;
  59. ListenCallbackParams.pNonStandardData = NULL;
  60. ListenCallbackParams.pszDisplay = NULL;
  61. ListenCallbackParams.pVendorInfo = NULL;
  62. ListenCallbackParams.ConferenceID = InvalidConferenceID;
  63. ListenCallbackParams.pCallerAddr = NULL;
  64. ListenCallbackParams.pCalleeAddr = NULL;
  65. ListenCallbackParams.dwListenToken = pListen->dwListenToken;
  66. // Invoke the user callback -- the listen object is locked during the callback,
  67. // but the associated call object is unlocked (to prevent deadlock if
  68. // CC_AcceptCall() or CC_RejectCall() is called during the callback from a
  69. // different thread, and the callback thread blocks pending completion of
  70. // CC_AcceptCall() or CC_RejectCall())
  71. InvokeUserListenCallback(pListen,
  72. Reason,
  73. &ListenCallbackParams);
  74. // Need to validate the listen handle; the associated object may have been
  75. // deleted during the user callback by this thread
  76. if (ValidateListen(hListen) == CC_OK) {
  77. HQ931LISTEN hQ931Listen = pListen->hQ931Listen;
  78. UnlockListen(pListen);
  79. status = Q931CancelListen(hQ931Listen);
  80. if (LockListen(hListen, &pListen) == CC_OK) {
  81. FreeListen(pListen);
  82. }
  83. }
  84. }
  85. HResultLeave(status);
  86. } // ListenReject()
  87. HRESULT PlaceCallConfirm (void *pCallVoid, void *pConferenceVoid)
  88. {
  89. register PCALL pCall = (PCALL) pCallVoid;
  90. HRESULT status;
  91. ASSERT(GKIExists());
  92. // Free Alias lists
  93. if (pCall->GkiCall.pCalleeAliasNames != NULL) {
  94. Q931FreeAliasNames(pCall->GkiCall.pCalleeAliasNames);
  95. pCall->GkiCall.pCalleeAliasNames = NULL;
  96. }
  97. if (pCall->GkiCall.pCalleeExtraAliasNames != NULL) {
  98. Q931FreeAliasNames(pCall->GkiCall.pCalleeExtraAliasNames);
  99. pCall->GkiCall.pCalleeExtraAliasNames = NULL;
  100. }
  101. if (pCall->pQ931PeerConnectAddr == NULL) {
  102. pCall->pQ931PeerConnectAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR));
  103. if (pCall->pQ931PeerConnectAddr == NULL)
  104. return PlaceCallReject(pCallVoid, pConferenceVoid, CC_NO_MEMORY);
  105. }
  106. pCall->pQ931PeerConnectAddr->nAddrType = CC_IP_BINARY;
  107. pCall->pQ931PeerConnectAddr->bMulticast = FALSE;
  108. pCall->pQ931PeerConnectAddr->Addr.IP_Binary.wPort = pCall->GkiCall.wPort;
  109. pCall->pQ931PeerConnectAddr->Addr.IP_Binary.dwAddr = ntohl(pCall->GkiCall.dwIpAddress);
  110. status = PlaceCall(pCall, (PCONFERENCE)pConferenceVoid);
  111. if (status != CC_OK)
  112. PlaceCallReject(pCallVoid, pConferenceVoid, status);
  113. return status;
  114. } // PlaceCallConfirm()
  115. HRESULT PlaceCallReject (void *pCallVoid, void *pConferenceVoid, HRESULT Reason)
  116. {
  117. register PCALL pCall = (PCALL) pCallVoid;
  118. register PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid;
  119. CC_HCONFERENCE hConference;
  120. HRESULT status = CC_OK;
  121. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams = {0};
  122. CC_HCALL hCall;
  123. PCALL pCall2;
  124. ASSERT(GKIExists());
  125. ASSERT(pCall != NULL);
  126. ASSERT(pConference != NULL);
  127. // Free Alias lists
  128. if (pCall->GkiCall.pCalleeAliasNames != NULL) {
  129. Q931FreeAliasNames(pCall->GkiCall.pCalleeAliasNames);
  130. pCall->GkiCall.pCalleeAliasNames = NULL;
  131. }
  132. if (pCall->GkiCall.pCalleeExtraAliasNames != NULL) {
  133. Q931FreeAliasNames(pCall->GkiCall.pCalleeExtraAliasNames);
  134. pCall->GkiCall.pCalleeExtraAliasNames = NULL;
  135. }
  136. // Inform Call Control client of failure
  137. ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData;
  138. ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay;
  139. ConnectCallbackParams.bRejectReason = 0;
  140. ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList;
  141. ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability;
  142. ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors;
  143. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  144. if (pCall->pQ931DestinationAddr == NULL)
  145. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  146. else
  147. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  148. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  149. if (pConference->ConferenceMode == MULTIPOINT_MODE)
  150. ConnectCallbackParams.bMultipointConference = TRUE;
  151. else
  152. ConnectCallbackParams.bMultipointConference = FALSE;
  153. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  154. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  155. ConnectCallbackParams.pAlternateAddress = NULL;
  156. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  157. hConference = pConference->hConference;
  158. InvokeUserConferenceCallback(pConference,
  159. CC_CONNECT_INDICATION,
  160. Reason,
  161. &ConnectCallbackParams);
  162. if (ValidateConference(hConference) == CC_OK) {
  163. // Start up an enqueued call, if one exists
  164. for ( ; ; ) {
  165. status = RemoveEnqueuedCallFromConference(pConference, &hCall);
  166. if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE))
  167. break;
  168. status = LockCall(hCall, &pCall2);
  169. if (status == CC_OK) {
  170. pCall2->CallState = PLACED;
  171. status = PlaceCall(pCall2, pConference);
  172. UnlockCall(pCall2);
  173. if (status == CC_OK)
  174. break;
  175. }
  176. }
  177. }
  178. HResultLeave(status);
  179. } // PlaceCallReject()
  180. HRESULT AcceptCallConfirm (void *pCallVoid, void *pConferenceVoid)
  181. {
  182. CC_HCALL hCall = ((PCALL)pCallVoid)->hCall;
  183. CC_HCONFERENCE hConference = ((PCONFERENCE)pConferenceVoid)->hConference;
  184. HRESULT status;
  185. ASSERT(GKIExists());
  186. status = AcceptCall((PCALL)pCallVoid, (PCONFERENCE)pConferenceVoid);
  187. LockConference(hConference, (PPCONFERENCE)&pConferenceVoid);
  188. LockCall(hCall, (PPCALL)&pCallVoid);
  189. if (status != CC_OK && pCallVoid != NULL && pConferenceVoid != NULL)
  190. AcceptCallReject(pCallVoid, pConferenceVoid, status);
  191. return status;
  192. } // AcceptCallConfirm()
  193. HRESULT AcceptCallReject (void *pCallVoid, void *pConferenceVoid, HRESULT Reason)
  194. {
  195. register PCALL pCall = (PCALL) pCallVoid;
  196. register PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid;
  197. HRESULT status = CC_OK;
  198. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams = {0};
  199. ASSERT(GKIExists());
  200. status = Q931RejectCall(pCall->hQ931Call, // Q931 call handle
  201. CC_REJECT_GATEKEEPER_RESOURCES,
  202. &pCall->ConferenceID, // Conference Identifier
  203. NULL, // alternate address
  204. pCall->pLocalNonStandardData);
  205. ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData;
  206. ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay;
  207. ConnectCallbackParams.bRejectReason = 0;
  208. ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList;
  209. ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability;
  210. ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors;
  211. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  212. if (pCall->pQ931DestinationAddr == NULL)
  213. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  214. else
  215. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  216. if (pConference->ConferenceMode == MULTIPOINT_MODE)
  217. ConnectCallbackParams.bMultipointConference = TRUE;
  218. else
  219. ConnectCallbackParams.bMultipointConference = FALSE;
  220. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  221. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  222. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  223. ConnectCallbackParams.pAlternateAddress = NULL;
  224. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  225. InvokeUserConferenceCallback(pConference,
  226. CC_CONNECT_INDICATION,
  227. Reason,
  228. &ConnectCallbackParams);
  229. HResultLeave(status);
  230. } // AcceptCallReject()
  231. #if 0
  232. HRESULT CancelCallConfirm (void *pCallVoid, void *pConferenceVoid)
  233. {
  234. PCALL pCall = (PCALL) pCallVoid;
  235. PCONFERENCE pConference = (PCONFERENCE) pConferenceVoid;
  236. HRESULT status;
  237. H245_INST_T H245Instance;
  238. HQ931CALL hQ931Call;
  239. CC_HCONFERENCE hConference;
  240. HRESULT SaveStatus;
  241. CC_HCALL hCall;
  242. ASSERT(GKIExists());
  243. H245Instance = pCall->H245Instance;
  244. hQ931Call = pCall->hQ931Call;
  245. hConference = pCall->hConference;
  246. FreeCall(pCall);
  247. if (H245Instance != H245_INVALID_ID)
  248. SaveStatus = H245ShutDown(H245Instance);
  249. else
  250. SaveStatus = H245_ERROR_OK;
  251. if (SaveStatus == H245_ERROR_OK) {
  252. SaveStatus = Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  253. // Q931Hangup may legitimately return CS_BAD_PARAM, because the Q.931 call object
  254. // may have been deleted at this point
  255. if (SaveStatus == CS_BAD_PARAM)
  256. SaveStatus = CC_OK;
  257. } else
  258. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  259. // Start up an enqueued call, if one exists
  260. for ( ; ; ) {
  261. status = RemoveEnqueuedCallFromConference(pConference, &hCall);
  262. if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE))
  263. break;
  264. status = LockCall(hCall, &pCall);
  265. if (status == CC_OK) {
  266. pCall->CallState = PLACED;
  267. status = PlaceCall(pCall, pConference);
  268. UnlockCall(pCall);
  269. if (status == CC_OK)
  270. break;
  271. }
  272. }
  273. UnlockConference(pConference);
  274. if (SaveStatus != CC_OK)
  275. status = SaveStatus;
  276. HResultLeave(status);
  277. } // CancelCallConfirm()
  278. HRESULT CancelCallReject (void *pCallVoid, void *pConferenceVoid)
  279. {
  280. // I don't care what the Gatekeeper says; I'm shutting down the call!
  281. return CancelCallConfirm(pCallVoid, pConferenceVoid);
  282. } // CancelCallReject()
  283. #endif
  284. HRESULT OpenChannelConfirm (CC_HCHANNEL hChannel)
  285. {
  286. HRESULT status;
  287. PCHANNEL pChannel;
  288. PCONFERENCE pConference;
  289. WORD wNumCalls;
  290. PCC_HCALL CallList;
  291. HRESULT SaveStatus;
  292. unsigned i;
  293. PCALL pCall;
  294. ASSERT(GKIExists());
  295. status = LockChannelAndConference(hChannel, &pChannel, &pConference);
  296. if (status == CC_OK) {
  297. // Open a logical channel for each established call
  298. status = EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  299. if (status == CC_OK) {
  300. SaveStatus = CC_OK;
  301. for (i = 0; i < wNumCalls; ++i) {
  302. if (LockCall(CallList[i], &pCall) == CC_OK) {
  303. status = H245OpenChannel(pCall->H245Instance, // H245 instance
  304. pChannel->hChannel, // dwTransId
  305. pChannel->wLocalChannelNumber,
  306. pChannel->pTxH245TermCap, // TxMode
  307. pChannel->pTxMuxTable, // TxMux
  308. H245_INVALID_PORT_NUMBER, // TxPort
  309. pChannel->pRxH245TermCap, // RxMode
  310. pChannel->pRxMuxTable, // RxMux
  311. pChannel->pSeparateStack);
  312. if (status == H245_ERROR_OK)
  313. (pChannel->wNumOutstandingRequests)++;
  314. else
  315. SaveStatus = status;
  316. UnlockCall(pCall);
  317. }
  318. }
  319. if (CallList != NULL)
  320. MemFree(CallList);
  321. if (pChannel->wNumOutstandingRequests == 0) {
  322. // all open channel requests failed
  323. FreeChannel(pChannel);
  324. }
  325. else {
  326. UnlockChannel(pChannel);
  327. }
  328. if (SaveStatus != CC_OK)
  329. status = SaveStatus;
  330. }
  331. else {
  332. FreeChannel(pChannel);
  333. }
  334. UnlockConference(pConference);
  335. }
  336. HResultLeave(status);
  337. } // OpenChannelConfirm()
  338. HRESULT OpenChannelReject (CC_HCHANNEL hChannel, HRESULT Reason)
  339. {
  340. PCHANNEL pChannel;
  341. PCONFERENCE pConference;
  342. CC_HCONFERENCE hConference;
  343. HRESULT status;
  344. CC_TX_CHANNEL_OPEN_CALLBACK_PARAMS Params = {0};
  345. ASSERT(GKIExists());
  346. status = LockChannelAndConference(hChannel, &pChannel, &pConference);
  347. if (status == CC_OK) {
  348. // Inform Call Control client of failure
  349. Params.hChannel = hChannel;
  350. Params.pPeerRTPAddr = pChannel->pPeerRTPAddr;
  351. Params.pPeerRTCPAddr = pChannel->pPeerRTCPAddr;
  352. Params.dwRejectReason = 0;
  353. Params.dwUserToken = pChannel->dwUserToken;
  354. hConference = pConference->hConference;
  355. InvokeUserConferenceCallback(pConference,
  356. CC_TX_CHANNEL_OPEN_INDICATION,
  357. Reason,
  358. &Params);
  359. if (ValidateChannel(hChannel) == CC_OK)
  360. FreeChannel(pChannel);
  361. if (ValidateConference(hConference) == CC_OK)
  362. UnlockConference(pConference);
  363. }
  364. HResultLeave(status);
  365. } // OpenChannelReject()
  366. HRESULT AcceptChannelConfirm(CC_HCHANNEL hChannel)
  367. {
  368. HRESULT status;
  369. PCHANNEL pChannel;
  370. PCONFERENCE pConference;
  371. CC_HCONFERENCE hConference;
  372. PCALL pCall;
  373. unsigned i;
  374. H245_MUX_T H245MuxTable;
  375. CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params;
  376. ASSERT(GKIExists());
  377. status = LockChannelAndConference(hChannel, &pChannel, &pConference);
  378. if (status != CC_OK)
  379. HResultLeave(status);
  380. status = LockCall(pChannel->hCall, &pCall);
  381. if (status != CC_OK) {
  382. UnlockChannel(pChannel);
  383. UnlockConference(pConference);
  384. HResultLeave(status);
  385. }
  386. if (pChannel->wNumOutstandingRequests != 0) {
  387. PCC_ADDR pRTPAddr = pChannel->pLocalRTPAddr;
  388. PCC_ADDR pRTCPAddr = pChannel->pLocalRTCPAddr;
  389. if ((pChannel->bMultipointChannel) &&
  390. (pConference->tsMultipointController == TS_TRUE)) {
  391. // Supply the RTP and RTCP addresses in the OpenLogicalChannelAck
  392. if (pConference->pSessionTable != NULL) {
  393. for (i = 0; i < pConference->pSessionTable->wLength; ++i) {
  394. if (pConference->pSessionTable->SessionInfoArray[i].bSessionID ==
  395. pChannel->bSessionID) {
  396. pRTPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTPAddr;
  397. pRTCPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTCPAddr;
  398. break;
  399. }
  400. }
  401. }
  402. }
  403. H245MuxTable.Kind = H245_H2250ACK;
  404. H245MuxTable.u.H2250ACK.nonStandardList = NULL;
  405. if (pRTPAddr != NULL) {
  406. if (pRTPAddr->bMulticast)
  407. H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_MULTICAST;
  408. else
  409. H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_UNICAST;
  410. H245MuxTable.u.H2250ACK.mediaChannel.u.ip.tsapIdentifier =
  411. pRTPAddr->Addr.IP_Binary.wPort;
  412. HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaChannel.u.ip.network,
  413. pRTPAddr->Addr.IP_Binary.dwAddr);
  414. H245MuxTable.u.H2250ACK.mediaChannelPresent = TRUE;
  415. } else
  416. H245MuxTable.u.H2250ACK.mediaChannelPresent = FALSE;
  417. if (pRTCPAddr != NULL) {
  418. if (pRTCPAddr->bMulticast)
  419. H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_MULTICAST;
  420. else
  421. H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_UNICAST;
  422. H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.tsapIdentifier =
  423. pRTCPAddr->Addr.IP_Binary.wPort;
  424. HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.network,
  425. pRTCPAddr->Addr.IP_Binary.dwAddr);
  426. H245MuxTable.u.H2250ACK.mediaControlChannelPresent = TRUE;
  427. } else
  428. H245MuxTable.u.H2250ACK.mediaControlChannelPresent = FALSE;
  429. H245MuxTable.u.H2250ACK.dynamicRTPPayloadTypePresent = FALSE;
  430. H245MuxTable.u.H2250ACK.sessionIDPresent = TRUE;
  431. H245MuxTable.u.H2250ACK.sessionID = pChannel->bSessionID;
  432. status = H245OpenChannelAccept(pCall->H245Instance,
  433. 0, // dwTransId
  434. pChannel->wRemoteChannelNumber, // Rx channel
  435. &H245MuxTable,
  436. 0, // Tx channel
  437. NULL, // Tx mux
  438. H245_INVALID_PORT_NUMBER,// Port
  439. pChannel->pSeparateStack);
  440. if (status == CC_OK)
  441. pChannel->wNumOutstandingRequests = 0;
  442. else
  443. --(pChannel->wNumOutstandingRequests);
  444. }
  445. pChannel->tsAccepted = TS_TRUE;
  446. Params.hChannel = hChannel;
  447. if (status == CC_OK)
  448. UnlockChannel(pChannel);
  449. else
  450. FreeChannel(pChannel);
  451. UnlockCall(pCall);
  452. hConference = pConference->hConference;
  453. InvokeUserConferenceCallback(pConference,
  454. CC_ACCEPT_CHANNEL_INDICATION,
  455. status,
  456. &Params);
  457. if (ValidateConference(hConference) == CC_OK)
  458. UnlockConference(pConference);
  459. HResultLeave(status);
  460. } // AcceptChannelConfirm(void()
  461. HRESULT AcceptChannelReject (CC_HCHANNEL hChannel, HRESULT Reason)
  462. {
  463. HRESULT status;
  464. PCHANNEL pChannel;
  465. PCONFERENCE pConference;
  466. CC_HCONFERENCE hConference;
  467. CC_ACCEPT_CHANNEL_CALLBACK_PARAMS Params;
  468. ASSERT(GKIExists());
  469. status = LockChannelAndConference(hChannel, &pChannel, &pConference);
  470. if (status == CC_OK) {
  471. Params.hChannel = hChannel;
  472. FreeChannel(pChannel);
  473. hConference = pConference->hConference;
  474. InvokeUserConferenceCallback(pConference,
  475. CC_ACCEPT_CHANNEL_INDICATION,
  476. Reason,
  477. &Params);
  478. if (ValidateConference(hConference) == CC_OK)
  479. UnlockConference(pConference);
  480. }
  481. HResultLeave(status);
  482. } // AcceptChannelReject()
  483. //
  484. // Handle gratuitous messages from Gatekeeper
  485. //
  486. // Note: pCall assumed locked when called!
  487. HRESULT Disengage(void *pCallVoid)
  488. {
  489. CC_HCALL hCall = ((PCALL)pCallVoid)->hCall;
  490. HRESULT status;
  491. UnlockCall((PCALL)pCallVoid);
  492. status = ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_GATEKEEPER_TERMINATED);
  493. HResultLeave(status);
  494. } // Disengage()
  495. // Note: pCall assumed locked when called!
  496. HRESULT BandwidthShrunk(void *pCallVoid,
  497. void *pConferenceVoid,
  498. unsigned uBandwidthAllocated,
  499. long lBandwidthChange)
  500. {
  501. PCALL pCall = (PCALL) pCallVoid;
  502. PCONFERENCE pConference = (PCONFERENCE)pConferenceVoid;
  503. CC_BANDWIDTH_CALLBACK_PARAMS Params;
  504. ASSERT(GKIExists());
  505. Params.hCall = pCall->hCall;
  506. Params.dwBandwidthTotal = uBandwidthAllocated;
  507. Params.lBandwidthChange = lBandwidthChange;
  508. InvokeUserConferenceCallback(pConference,
  509. CC_BANDWIDTH_CHANGED_INDICATION,
  510. CC_OK,
  511. &Params);
  512. HResultLeave(CC_OK);
  513. } // BandwidthShrunk()
  514. #else // GATEKEEPER
  515. static char ch; // Kludge around warning C4206: nonstandard extension used : translation unit is empty
  516. #endif // GATEKEEPER
  517.