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.

2824 lines
79 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/ccutils.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) 1993-1994 Intel Corporation.
  12. *
  13. * $Revision: 1.107.1.0 $
  14. * $Date: 20 Jun 1997 14:19:02 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable : 4057 4100 4115 4201 4214 4244)
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #include <winreg.h>
  31. #pragma warning ( default : 4115 4201 4214 )
  32. #include "incommon.h"
  33. #include "callcont.h"
  34. #include "q931.h"
  35. #include "apierror.h"
  36. #include "ccmain.h"
  37. #include "chanman.h"
  38. #include "confman.h"
  39. #include "callman.h"
  40. #include "q931man.h"
  41. #include "userman.h"
  42. #include "ccutils.h"
  43. #include "linkapi.h"
  44. #include "h245man.h"
  45. #include "provider.h"
  46. extern CC_CONFERENCEID InvalidConferenceID;
  47. // The following two procedures are currently obsolete. They're kept
  48. // around in case we need them in the future
  49. #if 0
  50. void * MallocDbg( DWORD dwSize,
  51. PSTR pszFile,
  52. int nLine)
  53. {
  54. void *pMem;
  55. ASSERT(dwSize != 0);
  56. pMem = GlobalAlloc(GMEM_FIXED, dwSize);
  57. #ifdef MEM_TRACE
  58. printf("MALLOC %s %d %lu %08x\n",
  59. pszFile, nLine, dwSize, pMem);
  60. #endif // MEM_TRACE
  61. return pMem;
  62. }
  63. void FreeDbg( void * pMem,
  64. PSTR pszFile,
  65. int nLine)
  66. {
  67. ASSERT(pMem != NULL);
  68. GlobalFree(pMem);
  69. #ifdef MEM_TRACE
  70. printf("FREE %s %d %08x\n",
  71. pszFile, nLine, pMem);
  72. #endif // MEM_TRACE
  73. }
  74. #endif // 0
  75. HRESULT InitializeLock( PLOCK pLock)
  76. {
  77. ASSERT(pLock != NULL);
  78. #ifdef DBG
  79. __try {
  80. // initialize lock (and allocate event immediately)
  81. InitializeCriticalSectionAndSpinCount(&pLock->LockInfoLock,H323_SPIN_COUNT);
  82. } __except ((GetExceptionCode() == STATUS_NO_MEMORY)
  83. ? EXCEPTION_EXECUTE_HANDLER
  84. : EXCEPTION_CONTINUE_SEARCH
  85. ) {
  86. // failure
  87. return CS_NO_MEMORY;
  88. }
  89. pLock->wLockCount = 0;
  90. pLock->wNumQueuedThreads = 0;
  91. pLock->hOwningThread = 0;
  92. #endif
  93. pLock->Lock = CreateMutex(NULL, // security attributes
  94. FALSE, // initial owner
  95. NULL); // name
  96. if (pLock->Lock == NULL) {
  97. #ifdef DBG
  98. DeleteCriticalSection(&pLock->LockInfoLock);
  99. #endif
  100. return CC_INTERNAL_ERROR;
  101. } else
  102. return CC_OK;
  103. }
  104. HRESULT DeleteLock( PLOCK pLock)
  105. {
  106. ASSERT(pLock != NULL);
  107. #ifdef DBG
  108. DeleteCriticalSection(&pLock->LockInfoLock);
  109. #endif
  110. if (CloseHandle(pLock->Lock) == TRUE)
  111. return CC_OK;
  112. else
  113. return CC_INTERNAL_ERROR;
  114. }
  115. HRESULT AcquireLock( PLOCK pLock)
  116. {
  117. HRESULT status;
  118. ASSERT(pLock != NULL);
  119. status = AcquireTimedLock(pLock, INFINITE, NULL);
  120. return status;
  121. }
  122. HRESULT AcquireTimedLock( PLOCK pLock,
  123. DWORD dwTimeout,
  124. BOOL *pbTimedOut)
  125. {
  126. DWORD dwStatus;
  127. ASSERT(pLock != NULL);
  128. #ifdef DBG
  129. EnterCriticalSection(&pLock->LockInfoLock);
  130. (pLock->wNumQueuedThreads)++;
  131. LeaveCriticalSection(&pLock->LockInfoLock);
  132. #endif
  133. dwStatus = WaitForSingleObject(pLock->Lock, dwTimeout);
  134. #ifdef DBG
  135. EnterCriticalSection(&pLock->LockInfoLock);
  136. (pLock->wNumQueuedThreads)--;
  137. (pLock->wLockCount)++;
  138. pLock->hOwningThread = GetCurrentThread();
  139. LeaveCriticalSection(&pLock->LockInfoLock);
  140. #endif
  141. if ((dwStatus != WAIT_OBJECT_0) && (dwStatus != WAIT_TIMEOUT))
  142. return CC_INTERNAL_ERROR;
  143. if (dwStatus == WAIT_TIMEOUT) {
  144. if (pbTimedOut != NULL) {
  145. *pbTimedOut = TRUE;
  146. }
  147. } else {
  148. if (pbTimedOut != NULL) {
  149. *pbTimedOut = FALSE;
  150. }
  151. }
  152. return CC_OK;
  153. }
  154. HRESULT RelinquishLock( PLOCK pLock)
  155. {
  156. ASSERT(pLock != NULL);
  157. #ifdef DBG
  158. EnterCriticalSection(&pLock->LockInfoLock);
  159. (pLock->wLockCount)--;
  160. if (pLock->wLockCount == 0)
  161. pLock->hOwningThread = 0;
  162. LeaveCriticalSection(&pLock->LockInfoLock);
  163. #endif
  164. if (ReleaseMutex(pLock->Lock) == TRUE)
  165. return CC_OK;
  166. else
  167. return CC_INTERNAL_ERROR;
  168. }
  169. HRESULT ValidateOctetString( PCC_OCTETSTRING pOctetString)
  170. {
  171. if (pOctetString == NULL)
  172. return CC_OK;
  173. if ((pOctetString->wOctetStringLength > 0) &&
  174. (pOctetString->pOctetString == NULL))
  175. return CC_BAD_PARAM;
  176. return CC_OK;
  177. }
  178. HRESULT CopyOctetString( PCC_OCTETSTRING *ppDest,
  179. PCC_OCTETSTRING pSource)
  180. {
  181. ASSERT(ppDest != NULL);
  182. if (pSource == NULL) {
  183. *ppDest = NULL;
  184. return CC_OK;
  185. }
  186. *ppDest = (PCC_OCTETSTRING)Malloc(sizeof(CC_OCTETSTRING));
  187. if (*ppDest == NULL)
  188. return CC_NO_MEMORY;
  189. (*ppDest)->wOctetStringLength = pSource->wOctetStringLength;
  190. if ((pSource->wOctetStringLength == 0) ||
  191. (pSource->pOctetString == NULL)) {
  192. pSource->wOctetStringLength = 0;
  193. (*ppDest)->pOctetString = NULL;
  194. } else {
  195. (*ppDest)->pOctetString = (BYTE *)Malloc(pSource->wOctetStringLength);
  196. if ((*ppDest)->pOctetString == NULL) {
  197. Free(*ppDest);
  198. *ppDest = NULL;
  199. return CC_NO_MEMORY;
  200. }
  201. memcpy((*ppDest)->pOctetString, pSource->pOctetString, pSource->wOctetStringLength);
  202. }
  203. return CC_OK;
  204. }
  205. HRESULT FreeOctetString( PCC_OCTETSTRING pOctetString)
  206. {
  207. if (pOctetString == NULL)
  208. return CC_OK;
  209. if ((pOctetString->wOctetStringLength > 0) &&
  210. (pOctetString->pOctetString != NULL))
  211. Free(pOctetString->pOctetString);
  212. Free(pOctetString);
  213. return CC_OK;
  214. }
  215. HRESULT CopySeparateStack( H245_ACCESS_T **ppDest,
  216. H245_ACCESS_T *pSource)
  217. {
  218. ASSERT(ppDest != NULL);
  219. if (pSource == NULL) {
  220. *ppDest = NULL;
  221. return CC_OK;
  222. }
  223. // We currently can't handle IP source route addresses,
  224. // since this address format contains embedded pointers
  225. // that cannot simply be copied
  226. if ((pSource->networkAddress.choice == localAreaAddress_chosen) &&
  227. (pSource->networkAddress.u.localAreaAddress.choice == unicastAddress_chosen) &&
  228. (pSource->networkAddress.u.localAreaAddress.u.unicastAddress.choice == iPSourceRouteAddress_chosen))
  229. return CC_NOT_IMPLEMENTED;
  230. *ppDest = (H245_ACCESS_T *)Malloc(sizeof(H245_ACCESS_T));
  231. if (*ppDest == NULL)
  232. return CC_NO_MEMORY;
  233. **ppDest = *pSource;
  234. return CC_OK;
  235. }
  236. HRESULT FreeSeparateStack( H245_ACCESS_T *pSeparateStack)
  237. {
  238. if (pSeparateStack == NULL)
  239. return CC_OK;
  240. Free(pSeparateStack);
  241. return CC_OK;
  242. }
  243. HRESULT ValidateNonStandardData( PCC_NONSTANDARDDATA pNonStandardData)
  244. {
  245. if (pNonStandardData == NULL)
  246. return CC_OK;
  247. return ValidateOctetString(&pNonStandardData->sData);
  248. }
  249. HRESULT CopyNonStandardData( PCC_NONSTANDARDDATA *ppDest,
  250. PCC_NONSTANDARDDATA pSource)
  251. {
  252. ASSERT(ppDest != NULL);
  253. if (pSource == NULL) {
  254. *ppDest = NULL;
  255. return CC_OK;
  256. }
  257. *ppDest = (PCC_NONSTANDARDDATA)Malloc(sizeof(CC_NONSTANDARDDATA));
  258. if (*ppDest == NULL)
  259. return CC_NO_MEMORY;
  260. **ppDest = *pSource;
  261. if ((pSource->sData.wOctetStringLength == 0) ||
  262. (pSource->sData.pOctetString == NULL)) {
  263. (*ppDest)->sData.wOctetStringLength = 0;
  264. (*ppDest)->sData.pOctetString = NULL;
  265. } else {
  266. (*ppDest)->sData.pOctetString = (BYTE *)Malloc(pSource->sData.wOctetStringLength);
  267. if ((*ppDest)->sData.pOctetString == NULL) {
  268. Free(*ppDest);
  269. return CC_NO_MEMORY;
  270. }
  271. memcpy((*ppDest)->sData.pOctetString,
  272. pSource->sData.pOctetString,
  273. pSource->sData.wOctetStringLength);
  274. }
  275. return CC_OK;
  276. }
  277. HRESULT FreeNonStandardData( PCC_NONSTANDARDDATA pNonStandardData)
  278. {
  279. if (pNonStandardData == NULL)
  280. return CC_OK;
  281. if ((pNonStandardData->sData.wOctetStringLength > 0) &&
  282. (pNonStandardData->sData.pOctetString != NULL))
  283. Free(pNonStandardData->sData.pOctetString);
  284. Free(pNonStandardData);
  285. return CC_OK;
  286. }
  287. HRESULT ValidateVendorInfo( PCC_VENDORINFO pVendorInfo)
  288. {
  289. HRESULT status;
  290. if (pVendorInfo == NULL)
  291. return CC_OK;
  292. status = ValidateOctetString(pVendorInfo->pProductNumber);
  293. if (status != CC_OK)
  294. return status;
  295. status = ValidateOctetString(pVendorInfo->pVersionNumber);
  296. return status;
  297. }
  298. HRESULT CopyVendorInfo( PCC_VENDORINFO *ppDest,
  299. PCC_VENDORINFO pSource)
  300. {
  301. HRESULT status;
  302. ASSERT(ppDest != NULL);
  303. if (pSource == NULL) {
  304. *ppDest = NULL;
  305. return CC_OK;
  306. }
  307. *ppDest = (PCC_VENDORINFO)Malloc(sizeof(CC_VENDORINFO));
  308. if (*ppDest == NULL)
  309. return CC_NO_MEMORY;
  310. **ppDest = *pSource;
  311. status = CopyOctetString(&(*ppDest)->pProductNumber, pSource->pProductNumber);
  312. if (status != CC_OK) {
  313. Free(*ppDest);
  314. return status;
  315. }
  316. status = CopyOctetString(&(*ppDest)->pVersionNumber, pSource->pVersionNumber);
  317. if (status != CC_OK) {
  318. FreeOctetString((*ppDest)->pProductNumber);
  319. Free(*ppDest);
  320. return status;
  321. }
  322. return CC_OK;
  323. }
  324. HRESULT FreeVendorInfo( PCC_VENDORINFO pVendorInfo)
  325. {
  326. if (pVendorInfo == NULL)
  327. return CC_OK;
  328. FreeOctetString(pVendorInfo->pProductNumber);
  329. FreeOctetString(pVendorInfo->pVersionNumber);
  330. Free(pVendorInfo);
  331. return CC_OK;
  332. }
  333. BOOL EqualConferenceIDs( PCC_CONFERENCEID pConferenceID1,
  334. PCC_CONFERENCEID pConferenceID2)
  335. {
  336. ASSERT(pConferenceID1 != NULL);
  337. ASSERT(pConferenceID2 != NULL);
  338. if (memcmp(pConferenceID1->buffer,
  339. pConferenceID2->buffer,
  340. sizeof(pConferenceID1->buffer)) == 0)
  341. return TRUE;
  342. else
  343. return FALSE;
  344. }
  345. BOOL EqualAddrs( PCC_ADDR pAddr1,
  346. PCC_ADDR pAddr2)
  347. {
  348. ASSERT(pAddr1 != NULL);
  349. ASSERT(pAddr2 != NULL);
  350. if (pAddr1->nAddrType != pAddr2->nAddrType)
  351. return FALSE;
  352. if (pAddr1->bMulticast != pAddr2->bMulticast)
  353. return FALSE;
  354. switch (pAddr1->nAddrType) {
  355. case CC_IP_DOMAIN_NAME:
  356. if ((pAddr1->Addr.IP_DomainName.wPort == pAddr2->Addr.IP_DomainName.wPort) &&
  357. (wcscmp(pAddr1->Addr.IP_DomainName.cAddr, pAddr2->Addr.IP_DomainName.cAddr) == 0))
  358. return TRUE;
  359. else
  360. return FALSE;
  361. case CC_IP_DOT:
  362. if ((pAddr1->Addr.IP_Dot.wPort == pAddr2->Addr.IP_Dot.wPort) &&
  363. (wcscmp(pAddr1->Addr.IP_Dot.cAddr, pAddr2->Addr.IP_Dot.cAddr) == 0))
  364. return TRUE;
  365. else
  366. return FALSE;
  367. case CC_IP_BINARY:
  368. if ((pAddr1->Addr.IP_Binary.wPort == pAddr2->Addr.IP_Binary.wPort) &&
  369. (pAddr1->Addr.IP_Binary.dwAddr == pAddr2->Addr.IP_Binary.dwAddr))
  370. return TRUE;
  371. else
  372. return FALSE;
  373. default:
  374. ASSERT(0);
  375. return FALSE;
  376. }
  377. }
  378. HRESULT ValidateTermCapList( PCC_TERMCAPLIST pTermCapList)
  379. {
  380. unsigned i, j;
  381. if (pTermCapList == NULL)
  382. return CC_OK;
  383. for (i = 0; i < pTermCapList->wLength; i++)
  384. if (pTermCapList->pTermCapArray[i] == NULL)
  385. return CC_BAD_PARAM;
  386. // make sure that all capability IDs are unique
  387. for (i = 0; i < pTermCapList->wLength; i++) {
  388. for (j = i + 1; j < pTermCapList->wLength; j++) {
  389. if (pTermCapList->pTermCapArray[i]->CapId == pTermCapList->pTermCapArray[j]->CapId)
  390. return CC_BAD_PARAM;
  391. }
  392. if ((pTermCapList->pTermCapArray[i]->CapId == H245_INVALID_CAPID) ||
  393. (pTermCapList->pTermCapArray[i]->CapId == 0))
  394. return CC_BAD_PARAM;
  395. }
  396. return CC_OK;
  397. }
  398. HRESULT ValidateTermCapDescriptors( PCC_TERMCAPDESCRIPTORS pTermCapDescriptors,
  399. PCC_TERMCAPLIST pTermCapList)
  400. {
  401. WORD i, j, k, l;
  402. H245_TOTCAPDESC_T *pTermCapDescriptor;
  403. H245_SIMCAP_T *pSimCaps;
  404. if (pTermCapDescriptors == NULL)
  405. return CC_OK;
  406. for (i = 0; i < pTermCapDescriptors->wLength; i++) {
  407. pTermCapDescriptor = pTermCapDescriptors->pTermCapDescriptorArray[i];
  408. if ((pTermCapDescriptor->CapDescId > 255) ||
  409. (pTermCapDescriptor->CapDesc.Length == 0) ||
  410. (pTermCapDescriptor->CapDesc.Length > H245_MAX_SIMCAPS))
  411. return CC_BAD_PARAM;
  412. for (j = i + 1; j < pTermCapDescriptors->wLength; j++) {
  413. if (pTermCapDescriptor->CapDescId ==
  414. pTermCapDescriptors->pTermCapDescriptorArray[j]->CapDescId) {
  415. return CC_BAD_PARAM;
  416. }
  417. }
  418. for (j = 0; j < pTermCapDescriptor->CapDesc.Length; j++) {
  419. pSimCaps = &(pTermCapDescriptor->CapDesc.SimCapArray[j]);
  420. if ((pSimCaps->Length == 0) ||
  421. (pSimCaps->Length > H245_MAX_ALTCAPS))
  422. return CC_BAD_PARAM;
  423. for (k = 0; k < pSimCaps->Length; k++) {
  424. for (l = 0; l < pTermCapList->wLength; l++) {
  425. if (pSimCaps->AltCaps[k] ==
  426. pTermCapList->pTermCapArray[l]->CapId)
  427. break;
  428. }
  429. if (l == pTermCapList->wLength)
  430. // the capability descriptor contains a capability ID
  431. // which is not present in the capability table
  432. return CC_BAD_PARAM;
  433. }
  434. }
  435. }
  436. return CC_OK;
  437. }
  438. HRESULT ValidateAddr( PCC_ADDR pAddr)
  439. {
  440. if (pAddr == NULL)
  441. return CC_OK;
  442. if ((pAddr->nAddrType != CC_IP_DOMAIN_NAME) &&
  443. (pAddr->nAddrType != CC_IP_DOT) &&
  444. (pAddr->nAddrType != CC_IP_BINARY))
  445. return CC_BAD_PARAM;
  446. return CC_OK;
  447. }
  448. HRESULT CopyAddr( PCC_ADDR *ppDest,
  449. PCC_ADDR pSource)
  450. {
  451. ASSERT(ppDest != NULL);
  452. if (pSource == NULL) {
  453. *ppDest = NULL;
  454. return CC_OK;
  455. }
  456. *ppDest = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  457. if (*ppDest == NULL)
  458. return CC_NO_MEMORY;
  459. **ppDest = *pSource;
  460. return CC_OK;
  461. }
  462. HRESULT FreeAddr( PCC_ADDR pAddr)
  463. {
  464. if (pAddr == NULL)
  465. return CC_OK;
  466. Free(pAddr);
  467. return CC_OK;
  468. }
  469. HRESULT SetQ931Port( PCC_ADDR pAddr)
  470. {
  471. if (pAddr == NULL)
  472. return CC_OK;
  473. switch (pAddr->nAddrType) {
  474. case CC_IP_DOMAIN_NAME:
  475. if (pAddr->Addr.IP_DomainName.wPort == 0)
  476. pAddr->Addr.IP_DomainName.wPort = CC_H323_HOST_CALL;
  477. return CC_OK;
  478. case CC_IP_DOT:
  479. if (pAddr->Addr.IP_Dot.wPort == 0)
  480. pAddr->Addr.IP_Dot.wPort = CC_H323_HOST_CALL;
  481. return CC_OK;
  482. case CC_IP_BINARY:
  483. if (pAddr->Addr.IP_Binary.wPort == 0)
  484. pAddr->Addr.IP_Binary.wPort = CC_H323_HOST_CALL;
  485. return CC_OK;
  486. }
  487. ASSERT(0);
  488. return CC_INTERNAL_ERROR;
  489. }
  490. HRESULT ValidateDisplay( PWSTR pszDisplay)
  491. {
  492. return CC_OK;
  493. }
  494. HRESULT CopyDisplay( PWSTR *ppDest,
  495. PWSTR pSource)
  496. {
  497. ASSERT(ppDest != NULL);
  498. if (pSource == NULL) {
  499. *ppDest = NULL;
  500. return CC_OK;
  501. }
  502. *ppDest = (WCHAR *)Malloc((wcslen(pSource)+1)*sizeof(WCHAR));
  503. if (*ppDest == NULL)
  504. return CC_NO_MEMORY;
  505. wcscpy(*ppDest, pSource);
  506. return CC_OK;
  507. }
  508. HRESULT FreeDisplay( PWSTR pszDisplay)
  509. {
  510. Free(pszDisplay);
  511. return CC_OK;
  512. }
  513. HRESULT ValidateTerminalID( PCC_OCTETSTRING pTerminalID)
  514. {
  515. return ValidateOctetString(pTerminalID);
  516. }
  517. HRESULT CopyTerminalID( PCC_OCTETSTRING *ppDest,
  518. PCC_OCTETSTRING pSource)
  519. {
  520. ASSERT(ppDest != NULL);
  521. return CopyOctetString(ppDest, pSource);
  522. }
  523. HRESULT FreeTerminalID( PCC_OCTETSTRING pTerminalID)
  524. {
  525. return FreeOctetString(pTerminalID);
  526. }
  527. HRESULT SetTerminalType( TRISTATE tsMultipointController,
  528. BYTE *pbTerminalType)
  529. {
  530. switch (tsMultipointController) {
  531. case TS_TRUE:
  532. *pbTerminalType = 240;
  533. break;
  534. case TS_UNKNOWN:
  535. *pbTerminalType = 70;
  536. break;
  537. case TS_FALSE:
  538. *pbTerminalType = 50;
  539. break;
  540. default:
  541. ASSERT(0);
  542. *pbTerminalType = 0;
  543. break;
  544. }
  545. return CC_OK;
  546. }
  547. HRESULT CopyH245TermCapList( PCC_TERMCAPLIST *ppDest,
  548. PCC_TERMCAPLIST pSource)
  549. {
  550. WORD i;
  551. HRESULT status;
  552. ASSERT(ppDest != NULL);
  553. if (pSource == NULL) {
  554. *ppDest = NULL;
  555. return CC_OK;
  556. }
  557. *ppDest = (PCC_TERMCAPLIST)Malloc(sizeof(CC_TERMCAPLIST));
  558. if (*ppDest == NULL)
  559. return CC_NO_MEMORY;
  560. (*ppDest)->wLength = pSource->wLength;
  561. (*ppDest)->pTermCapArray =
  562. (PPCC_TERMCAP)Malloc(sizeof(PCC_TERMCAP) * pSource->wLength);
  563. if ((*ppDest)->pTermCapArray == NULL) {
  564. (*ppDest)->wLength = 0;
  565. DestroyH245TermCapList(ppDest);
  566. return CC_NO_MEMORY;
  567. }
  568. for (i = 0; i < pSource->wLength; i++) {
  569. status = H245CopyCap(&((*ppDest)->pTermCapArray[i]), pSource->pTermCapArray[i]);
  570. if (status != H245_ERROR_OK) {
  571. (*ppDest)->wLength = i;
  572. DestroyH245TermCapList(ppDest);
  573. return status;
  574. }
  575. }
  576. return CC_OK;
  577. }
  578. HRESULT CopyH245TermCapDescriptors( PCC_TERMCAPDESCRIPTORS *ppDest,
  579. PCC_TERMCAPDESCRIPTORS pSource)
  580. {
  581. WORD i;
  582. HRESULT status;
  583. ASSERT(ppDest != NULL);
  584. if (pSource == NULL) {
  585. *ppDest = NULL;
  586. return CC_OK;
  587. }
  588. (*ppDest) = (PCC_TERMCAPDESCRIPTORS)Malloc(sizeof(CC_TERMCAPDESCRIPTORS));
  589. if (*ppDest == NULL)
  590. return CC_NO_MEMORY;
  591. (*ppDest)->wLength = pSource->wLength;
  592. (*ppDest)->pTermCapDescriptorArray = (H245_TOTCAPDESC_T **)Malloc(sizeof(H245_TOTCAPDESC_T *) *
  593. pSource->wLength);
  594. if ((*ppDest)->pTermCapDescriptorArray == NULL) {
  595. (*ppDest)->wLength = 0;
  596. DestroyH245TermCapDescriptors(ppDest);
  597. return CC_NO_MEMORY;
  598. }
  599. for (i = 0; i < pSource->wLength; i++) {
  600. status = H245CopyCapDescriptor(&((*ppDest)->pTermCapDescriptorArray[i]),
  601. pSource->pTermCapDescriptorArray[i]);
  602. if (status != H245_ERROR_OK) {
  603. (*ppDest)->wLength = i;
  604. DestroyH245TermCapDescriptors(ppDest);
  605. return status;
  606. }
  607. }
  608. return CC_OK;
  609. }
  610. HRESULT CreateH245DefaultTermCapDescriptors(
  611. PCC_TERMCAPDESCRIPTORS *ppDest,
  612. PCC_TERMCAPLIST pTermCapList)
  613. {
  614. H245_TOTCAPDESC_T TermCapDescriptor;
  615. WORD i;
  616. HRESULT status;
  617. ASSERT(ppDest != NULL);
  618. if (pTermCapList == NULL) {
  619. *ppDest = NULL;
  620. return CC_OK;
  621. }
  622. *ppDest = (PCC_TERMCAPDESCRIPTORS)Malloc(sizeof(CC_TERMCAPDESCRIPTORS));
  623. if (*ppDest == NULL)
  624. return CC_NO_MEMORY;
  625. if (pTermCapList->wLength == 0) {
  626. (*ppDest)->wLength = 0;
  627. (*ppDest)->pTermCapDescriptorArray = NULL;
  628. return CC_OK;
  629. }
  630. (*ppDest)->wLength = 1;
  631. (*ppDest)->pTermCapDescriptorArray = (H245_TOTCAPDESC_T **)Malloc(sizeof(H245_TOTCAPDESC_T *));
  632. if ((*ppDest)->pTermCapDescriptorArray == NULL) {
  633. (*ppDest)->wLength = 0;
  634. DestroyH245TermCapDescriptors(ppDest);
  635. return CC_NO_MEMORY;
  636. }
  637. TermCapDescriptor.CapDesc.Length = pTermCapList->wLength;
  638. TermCapDescriptor.CapDescId = 0;
  639. for (i = 0; i < pTermCapList->wLength; i++) {
  640. TermCapDescriptor.CapDesc.SimCapArray[i].Length = 1;
  641. TermCapDescriptor.CapDesc.SimCapArray[i].AltCaps[0] =
  642. pTermCapList->pTermCapArray[i]->CapId;
  643. }
  644. status = H245CopyCapDescriptor(&((*ppDest)->pTermCapDescriptorArray[0]),
  645. &TermCapDescriptor);
  646. if (status != H245_ERROR_OK) {
  647. (*ppDest)->wLength = 0;
  648. DestroyH245TermCapDescriptors(ppDest);
  649. return status;
  650. }
  651. return CC_OK;
  652. }
  653. HRESULT DestroyH245TermCap( PPCC_TERMCAP ppTermCap)
  654. {
  655. ASSERT(ppTermCap != NULL);
  656. if (*ppTermCap == NULL)
  657. return CC_OK;
  658. H245FreeCap(*ppTermCap);
  659. *ppTermCap = NULL;
  660. return CC_OK;
  661. }
  662. HRESULT UnregisterTermCapListFromH245(
  663. PCONFERENCE pConference,
  664. PCC_TERMCAPLIST pTermCapList)
  665. {
  666. WORD i, j;
  667. PCALL pCall;
  668. PCC_HCALL CallList;
  669. WORD wNumCalls;
  670. HRESULT status;
  671. HRESULT SaveStatus;
  672. ASSERT(pConference != NULL);
  673. if (pTermCapList == NULL)
  674. return CC_OK;
  675. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  676. SaveStatus = CC_OK;
  677. for (i = 0; i < pTermCapList->wLength; i++) {
  678. ASSERT(pTermCapList->pTermCapArray[i] != NULL);
  679. for (j = 0; j < wNumCalls; j++) {
  680. if (LockCall(CallList[j], &pCall) == CC_OK) {
  681. status = H245DelLocalCap(pCall->H245Instance,
  682. pTermCapList->pTermCapArray[i]->CapId);
  683. if (status != CC_OK)
  684. SaveStatus = status;
  685. UnlockCall(pCall);
  686. }
  687. }
  688. }
  689. if (CallList != NULL)
  690. Free(CallList);
  691. return SaveStatus;
  692. }
  693. HRESULT DestroyH245TermCapList( PCC_TERMCAPLIST *ppTermCapList)
  694. {
  695. WORD i;
  696. ASSERT(ppTermCapList != NULL);
  697. if (*ppTermCapList == NULL)
  698. return CC_OK;
  699. for (i = 0; i < (*ppTermCapList)->wLength; i++) {
  700. ASSERT((*ppTermCapList)->pTermCapArray[i] != NULL);
  701. H245FreeCap((*ppTermCapList)->pTermCapArray[i]);
  702. }
  703. if ((*ppTermCapList)->pTermCapArray != NULL)
  704. Free((*ppTermCapList)->pTermCapArray);
  705. Free(*ppTermCapList);
  706. *ppTermCapList = NULL;
  707. return CC_OK;
  708. }
  709. HRESULT UnregisterTermCapDescriptorsFromH245(
  710. PCONFERENCE pConference,
  711. PCC_TERMCAPDESCRIPTORS pTermCapDescriptors)
  712. {
  713. WORD i, j;
  714. PCALL pCall;
  715. PCC_HCALL CallList;
  716. WORD wNumCalls;
  717. HRESULT status;
  718. HRESULT SaveStatus;
  719. ASSERT(pConference != NULL);
  720. if (pTermCapDescriptors == NULL)
  721. return CC_OK;
  722. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  723. SaveStatus = CC_OK;
  724. for (i = 0; i < pTermCapDescriptors->wLength; i++) {
  725. ASSERT(pTermCapDescriptors->pTermCapDescriptorArray[i] != NULL);
  726. for (j = 0; j < wNumCalls; j++) {
  727. if (LockCall(CallList[j], &pCall) == CC_OK) {
  728. status = H245DelCapDescriptor(pCall->H245Instance,
  729. pTermCapDescriptors->pTermCapDescriptorArray[i]->CapDescId);
  730. if (status != CC_OK)
  731. SaveStatus = status;
  732. UnlockCall(pCall);
  733. }
  734. }
  735. }
  736. if (CallList != NULL)
  737. Free(CallList);
  738. return SaveStatus;
  739. }
  740. HRESULT DestroyH245TermCapDescriptors( PCC_TERMCAPDESCRIPTORS *ppTermCapDescriptors)
  741. {
  742. WORD i;
  743. ASSERT(ppTermCapDescriptors != NULL);
  744. if (*ppTermCapDescriptors == NULL)
  745. return CC_OK;
  746. for (i = 0; i < (*ppTermCapDescriptors)->wLength; i++) {
  747. ASSERT((*ppTermCapDescriptors)->pTermCapDescriptorArray[i] != NULL);
  748. H245FreeCapDescriptor((*ppTermCapDescriptors)->pTermCapDescriptorArray[i]);
  749. }
  750. if ((*ppTermCapDescriptors)->pTermCapDescriptorArray != NULL)
  751. Free((*ppTermCapDescriptors)->pTermCapDescriptorArray);
  752. Free(*ppTermCapDescriptors);
  753. *ppTermCapDescriptors = NULL;
  754. return CC_OK;
  755. }
  756. HRESULT HostToH245IPNetwork( BYTE *NetworkArray,
  757. DWORD dwAddr)
  758. {
  759. if (NetworkArray == NULL) {
  760. ASSERT(0);
  761. return CC_BAD_PARAM;
  762. }
  763. NetworkArray[0] = HIBYTE(HIWORD(dwAddr));
  764. NetworkArray[1] = LOBYTE(HIWORD(dwAddr));
  765. NetworkArray[2] = HIBYTE(LOWORD(dwAddr));
  766. NetworkArray[3] = LOBYTE(LOWORD(dwAddr));
  767. return CC_OK;
  768. }
  769. HRESULT H245IPNetworkToHost( DWORD *pdwAddr,
  770. BYTE *NetworkArray)
  771. {
  772. if ((pdwAddr == NULL) || (NetworkArray == NULL)) {
  773. ASSERT(0);
  774. return CC_BAD_PARAM;
  775. }
  776. *pdwAddr = NetworkArray[0] * 0x01000000 +
  777. NetworkArray[1] * 0x00010000 +
  778. NetworkArray[2] * 0x00000100 +
  779. NetworkArray[3] * 0x00000001;
  780. return CC_OK;
  781. }
  782. HRESULT ProcessRemoteHangup( CC_HCALL hCall,
  783. HQ931CALL hQ931Initiator,
  784. BYTE bHangupReason)
  785. {
  786. PCALL pCall;
  787. CC_HCONFERENCE hConference;
  788. PCONFERENCE pConference;
  789. HRESULT status;
  790. HQ931CALL hQ931Call;
  791. H245_INST_T H245Instance;
  792. PCHANNEL pChannel;
  793. WORD wNumChannels;
  794. PCC_HCHANNEL ChannelList;
  795. WORD i;
  796. WORD wNumCalls;
  797. PCC_HCALL CallList;
  798. PCALL pOldCall;
  799. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  800. CC_PEER_DROP_CALLBACK_PARAMS PeerDropCallbackParams;
  801. CC_PEER_CHANGE_CAP_CALLBACK_PARAMS PeerChangeCapCallbackParams;
  802. BOOL bConferenceTermCapsChanged;
  803. HRESULT CallbackStatus;
  804. if (hCall == CC_INVALID_HANDLE)
  805. return CC_BAD_PARAM;
  806. status = LockCallAndConference(hCall, &pCall, &pConference);
  807. if (status != CC_OK)
  808. return CC_BAD_PARAM;
  809. hConference = pCall->hConference;
  810. hQ931Call = pCall->hQ931Call;
  811. H245Instance = pCall->H245Instance;
  812. PeerDropCallbackParams.hCall = pCall->hCall;
  813. if (pCall->pPeerParticipantInfo == NULL) {
  814. PeerDropCallbackParams.TerminalLabel.bMCUNumber = 255;
  815. PeerDropCallbackParams.TerminalLabel.bTerminalNumber = 255;
  816. PeerDropCallbackParams.pPeerTerminalID = NULL;
  817. } else {
  818. PeerDropCallbackParams.TerminalLabel = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  819. if (pCall->pPeerParticipantInfo->TerminalIDState == TERMINAL_ID_VALID)
  820. PeerDropCallbackParams.pPeerTerminalID = &pCall->pPeerParticipantInfo->ParticipantInfo.TerminalID;
  821. else
  822. PeerDropCallbackParams.pPeerTerminalID = NULL;
  823. }
  824. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  825. (pConference->tsMultipointController == TS_TRUE))
  826. CreateConferenceTermCaps(pConference, &bConferenceTermCapsChanged);
  827. else
  828. bConferenceTermCapsChanged = FALSE;
  829. // Remove all TX, RX and PROXY channels associated with this call
  830. EnumerateChannelsInConference(&wNumChannels,
  831. &ChannelList,
  832. pConference,
  833. TX_CHANNEL | RX_CHANNEL | PROXY_CHANNEL);
  834. for (i = 0; i < wNumChannels; i++) {
  835. if (LockChannel(ChannelList[i], &pChannel) == CC_OK) {
  836. if (pChannel->hCall == hCall)
  837. FreeChannel(pChannel);
  838. else
  839. UnlockChannel(pChannel);
  840. }
  841. }
  842. if (ChannelList != NULL)
  843. Free(ChannelList);
  844. switch (bHangupReason)
  845. {
  846. case CC_REJECT_NORMAL_CALL_CLEARING:
  847. CallbackStatus = CC_OK;
  848. break;
  849. case CC_REJECT_GATEKEEPER_TERMINATED:
  850. CallbackStatus = CC_GATEKEEPER_REFUSED;
  851. bHangupReason = CC_REJECT_NORMAL_CALL_CLEARING;
  852. break;
  853. default:
  854. CallbackStatus = CC_PEER_REJECT;
  855. } // switch
  856. if (pCall->CallType == THIRD_PARTY_INVITOR) {
  857. MarkCallForDeletion(pCall);
  858. ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData;
  859. ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay;
  860. ConnectCallbackParams.bRejectReason = bHangupReason;
  861. ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList;
  862. ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability;
  863. ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors;
  864. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  865. if (pCall->pQ931DestinationAddr == NULL)
  866. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  867. else
  868. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  869. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  870. ConnectCallbackParams.bMultipointConference = TRUE;
  871. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  872. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  873. ConnectCallbackParams.pAlternateAddress = NULL;
  874. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  875. InvokeUserConferenceCallback(pConference,
  876. CC_CONNECT_INDICATION,
  877. CallbackStatus,
  878. &ConnectCallbackParams);
  879. // Need to validate the conference and call handles; the associated
  880. // objects may have been deleted during user callback on this thread
  881. if (ValidateConference(hConference) == CC_OK)
  882. UnlockConference(pConference);
  883. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  884. FreeCall(pCall);
  885. Q931Hangup(hQ931Call, bHangupReason);
  886. return CC_OK;
  887. }
  888. if (pCall->CallType == THIRD_PARTY_INTERMEDIARY) {
  889. if ((hQ931Initiator == pCall->hQ931CallInvitor) &&
  890. (hQ931Initiator != CC_INVALID_HANDLE)) {
  891. pCall->hQ931CallInvitor = CC_INVALID_HANDLE;
  892. UnlockCall(pCall);
  893. UnlockConference(pConference);
  894. return CC_OK;
  895. } else {
  896. if (pCall->CallState != CALL_COMPLETE) {
  897. if (pCall->hQ931CallInvitor != CC_INVALID_HANDLE)
  898. Q931Hangup(pCall->hQ931CallInvitor, CC_REJECT_UNDEFINED_REASON);
  899. if (ValidateCall(hCall) == CC_OK)
  900. Q931Hangup(pCall->hQ931Call, bHangupReason);
  901. }
  902. }
  903. }
  904. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  905. (pConference->tsMultipointController == TS_TRUE)) {
  906. if (pCall->pPeerParticipantInfo != NULL) {
  907. EnumerateCallsInConference(&wNumCalls,
  908. &CallList,
  909. pConference,
  910. ESTABLISHED_CALL);
  911. for (i = 0; i < wNumCalls; i++) {
  912. if (CallList[i] != hCall) {
  913. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  914. if (pCall->pPeerParticipantInfo != NULL)
  915. H245ConferenceIndication(
  916. pOldCall->H245Instance,
  917. H245_IND_TERMINAL_LEFT, // Indication Type
  918. 0, // SBE number; ignored here
  919. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber, // MCU number
  920. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
  921. if (bConferenceTermCapsChanged)
  922. // Send new term caps
  923. SendTermCaps(pOldCall, pConference);
  924. UnlockCall(pOldCall);
  925. }
  926. }
  927. }
  928. if (CallList != NULL)
  929. Free(CallList);
  930. }
  931. InvokeUserConferenceCallback(pConference,
  932. CC_PEER_DROP_INDICATION,
  933. CC_OK,
  934. &PeerDropCallbackParams);
  935. if (ValidateCall(hCall) == CC_OK)
  936. FreeCall(pCall);
  937. if (ValidateConference(hConference) == CC_OK) {
  938. if (bConferenceTermCapsChanged) {
  939. // Generate CC_PEER_CHANGE_CAP callback
  940. PeerChangeCapCallbackParams.pTermCapList =
  941. pConference->pConferenceTermCapList;
  942. PeerChangeCapCallbackParams.pH2250MuxCapability =
  943. pConference->pConferenceH245H2250MuxCapability;
  944. PeerChangeCapCallbackParams.pTermCapDescriptors =
  945. pConference->pConferenceTermCapDescriptors;
  946. InvokeUserConferenceCallback(pConference,
  947. CC_PEER_CHANGE_CAP_INDICATION,
  948. CC_OK,
  949. &PeerChangeCapCallbackParams);
  950. }
  951. }
  952. if (ValidateConference(hConference) == CC_OK) {
  953. if (pConference->bDeferredDelete) {
  954. ASSERT(pConference->LocalEndpointAttached == DETACHED);
  955. EnumerateCallsInConference(&wNumCalls, NULL, pConference, ALL_CALLS);
  956. if (wNumCalls == 0) {
  957. FreeConference(pConference);
  958. return CC_OK;
  959. }
  960. }
  961. UnlockConference(pConference);
  962. }
  963. return CC_OK;
  964. } else {
  965. status = EnumerateChannelsInConference(&wNumChannels,
  966. &ChannelList,
  967. pConference,
  968. ALL_CHANNELS);
  969. if (status == CC_OK) {
  970. // free all the channels
  971. for (i = 0; i < wNumChannels; i++) {
  972. if (LockChannel(ChannelList[i], &pChannel) == CC_OK)
  973. // Notice that since we're going to hangup, we don't need to
  974. // close any channels
  975. FreeChannel(pChannel);
  976. }
  977. if (ChannelList != NULL)
  978. Free(ChannelList);
  979. }
  980. if (H245Instance != H245_INVALID_ID)
  981. status = H245ShutDown(H245Instance);
  982. else
  983. status = H245_ERROR_OK;
  984. if (status == H245_ERROR_OK) {
  985. status = Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  986. // Q931Hangup may legitimately return CS_BAD_PARAM, because the Q.931 call object
  987. // may have been deleted at this point
  988. if (status == CS_BAD_PARAM)
  989. status = CC_OK;
  990. } else
  991. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  992. if (pConference->bDeferredDelete) {
  993. ASSERT(pConference->LocalEndpointAttached == DETACHED);
  994. FreeConference(pConference);
  995. } else {
  996. ReInitializeConference(pConference);
  997. InvokeUserConferenceCallback(pConference,
  998. CC_CONFERENCE_TERMINATION_INDICATION,
  999. CallbackStatus,
  1000. NULL);
  1001. if (ValidateConference(hConference) == CC_OK)
  1002. UnlockConference(pConference);
  1003. }
  1004. return CC_OK;
  1005. }
  1006. // We should never reach this point
  1007. ASSERT(0);
  1008. }
  1009. HRESULT DefaultSessionTableConstructor(
  1010. CC_HCONFERENCE hConference,
  1011. DWORD dwConferenceToken,
  1012. BOOL bCreate,
  1013. BOOL *pbSessionTableChanged,
  1014. WORD wListCount,
  1015. PCC_TERMCAPLIST pTermCapList[],
  1016. PCC_TERMCAPDESCRIPTORS pTermCapDescriptors[],
  1017. PCC_SESSIONTABLE *ppSessionTable)
  1018. {
  1019. WORD i;
  1020. HRESULT status;
  1021. PCONFERENCE pConference;
  1022. WORD wNumChannels;
  1023. PCC_HCHANNEL ChannelList;
  1024. PCHANNEL pChannel;
  1025. WORD wNumCalls;
  1026. PCC_HCALL CallList;
  1027. PCALL pCall;
  1028. BYTE bSessionID;
  1029. WORD wPort;
  1030. DWORD dwAddr;
  1031. WCHAR szSessionDescription[100];
  1032. WCHAR ss[10];
  1033. ASSERT(hConference != CC_INVALID_HANDLE);
  1034. ASSERT(ppSessionTable != NULL);
  1035. if (*ppSessionTable != NULL) {
  1036. for (i = 0; i < (*ppSessionTable)->wLength; i++) {
  1037. if ((*ppSessionTable)->SessionInfoArray[i].pTermCap != NULL)
  1038. H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap);
  1039. FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTPAddr);
  1040. FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr);
  1041. }
  1042. if ((*ppSessionTable)->SessionInfoArray != NULL)
  1043. Free((*ppSessionTable)->SessionInfoArray);
  1044. Free(*ppSessionTable);
  1045. *ppSessionTable = NULL;
  1046. }
  1047. if (bCreate == FALSE)
  1048. return CC_OK;
  1049. *ppSessionTable = NULL;
  1050. if (pbSessionTableChanged != NULL)
  1051. *pbSessionTableChanged = FALSE;
  1052. status = LockConference(hConference, &pConference);
  1053. if (status != CC_OK)
  1054. return status;
  1055. if ((pConference->ConferenceMode == UNCONNECTED_MODE) ||
  1056. (pConference->ConferenceMode == POINT_TO_POINT_MODE)) {
  1057. UnlockConference(pConference);
  1058. return CC_BAD_PARAM;
  1059. }
  1060. // pConference->ConferenceMode == MULTIPOINT_MODE
  1061. // Create one session entry for each open channel on this conference
  1062. bSessionID = 1;
  1063. wPort = 2050;
  1064. // Set dwAddr
  1065. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  1066. if (wNumCalls == 0) {
  1067. UnlockConference(pConference);
  1068. return CC_INTERNAL_ERROR;
  1069. }
  1070. status = LockCall(CallList[0], &pCall);
  1071. if (status != CC_OK) {
  1072. Free(CallList);
  1073. UnlockConference(pConference);
  1074. return status;
  1075. }
  1076. if (pCall->pQ931LocalConnectAddr == NULL) {
  1077. Free(CallList);
  1078. UnlockCall(pCall);
  1079. UnlockConference(pConference);
  1080. return CC_INTERNAL_ERROR;
  1081. }
  1082. if (pCall->pQ931LocalConnectAddr->nAddrType != CC_IP_BINARY) {
  1083. Free(CallList);
  1084. UnlockCall(pCall);
  1085. UnlockConference(pConference);
  1086. return CC_INTERNAL_ERROR;
  1087. }
  1088. // Construct dwAddr from one of the unicast Q.931 addresses by setting the high
  1089. // nibble of the Q.931 address to 0xE
  1090. dwAddr = (pCall->pQ931LocalConnectAddr->Addr.IP_Binary.dwAddr & 0xEFFFFFFF) | 0xE0000000;
  1091. UnlockCall(pCall);
  1092. Free(CallList);
  1093. EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, TX_CHANNEL);
  1094. *ppSessionTable = (PCC_SESSIONTABLE)Malloc(sizeof(CC_SESSIONTABLE));
  1095. if (*ppSessionTable == NULL) {
  1096. Free(ChannelList);
  1097. UnlockConference(pConference);
  1098. return CC_NO_MEMORY;
  1099. }
  1100. (*ppSessionTable)->wLength = wNumChannels;
  1101. if (wNumChannels == 0)
  1102. (*ppSessionTable)->SessionInfoArray = NULL;
  1103. else {
  1104. (*ppSessionTable)->SessionInfoArray =
  1105. (PCC_SESSIONINFO)Malloc(sizeof(CC_SESSIONINFO) * wNumChannels);
  1106. if ((*ppSessionTable)->SessionInfoArray == NULL) {
  1107. Free(ChannelList);
  1108. UnlockConference(pConference);
  1109. (*ppSessionTable)->wLength = 0;
  1110. DefaultSessionTableConstructor(
  1111. hConference,
  1112. dwConferenceToken,
  1113. FALSE, // bCreate,
  1114. NULL, // pbSessionTableChanged,
  1115. 0, // wListCount,
  1116. NULL, // pTermCapList[],
  1117. NULL, // pTermCapDescriptors[],
  1118. ppSessionTable);
  1119. return CC_NO_MEMORY;
  1120. }
  1121. for (i = 0; i < wNumChannels; i++) {
  1122. (*ppSessionTable)->SessionInfoArray[i].bSessionID = bSessionID++;
  1123. (*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID = 0;
  1124. wcscpy(szSessionDescription, L"Session ");
  1125. _itow((int)(*ppSessionTable)->SessionInfoArray[i].bSessionID,
  1126. ss, 10);
  1127. wcscat(szSessionDescription, ss);
  1128. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength =
  1129. (WORD)((wcslen(szSessionDescription)+1)*sizeof(WCHAR));
  1130. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString =
  1131. (BYTE *)Malloc((*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength);
  1132. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString == NULL) {
  1133. Free(ChannelList);
  1134. UnlockConference(pConference);
  1135. (*ppSessionTable)->wLength = i;
  1136. DefaultSessionTableConstructor(
  1137. hConference,
  1138. dwConferenceToken,
  1139. FALSE, // bCreate,
  1140. NULL, // pbSessionTableChanged,
  1141. 0, // wListCount,
  1142. NULL, // pTermCapList[],
  1143. NULL, // pTermCapDescriptors[],
  1144. ppSessionTable);
  1145. return CC_NO_MEMORY;
  1146. }
  1147. memcpy((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString,
  1148. szSessionDescription,
  1149. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength);
  1150. status = LockChannel(ChannelList[i], &pChannel);
  1151. if (status != CC_OK) {
  1152. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  1153. Free(ChannelList);
  1154. UnlockConference(pConference);
  1155. (*ppSessionTable)->wLength = i;
  1156. DefaultSessionTableConstructor(
  1157. hConference,
  1158. dwConferenceToken,
  1159. FALSE, // bCreate,
  1160. NULL, // pbSessionTableChanged,
  1161. 0, // wListCount,
  1162. NULL, // pTermCapList[],
  1163. NULL, // pTermCapDescriptors[],
  1164. ppSessionTable);
  1165. return CC_NO_MEMORY;
  1166. }
  1167. status = H245CopyCap(&(*ppSessionTable)->SessionInfoArray[i].pTermCap,
  1168. pChannel->pTxH245TermCap);
  1169. UnlockChannel(pChannel);
  1170. if (status != H245_ERROR_OK) {
  1171. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  1172. Free(ChannelList);
  1173. UnlockConference(pConference);
  1174. (*ppSessionTable)->wLength = i;
  1175. DefaultSessionTableConstructor(
  1176. hConference,
  1177. dwConferenceToken,
  1178. FALSE, // bCreate,
  1179. NULL, // pbSessionTableChanged,
  1180. 0, // wListCount,
  1181. NULL, // pTermCapList[],
  1182. NULL, // pTermCapDescriptors[],
  1183. ppSessionTable);
  1184. return status;
  1185. }
  1186. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr =
  1187. (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  1188. if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr == NULL) {
  1189. H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap);
  1190. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  1191. Free(ChannelList);
  1192. UnlockConference(pConference);
  1193. (*ppSessionTable)->wLength = i;
  1194. DefaultSessionTableConstructor(
  1195. hConference,
  1196. dwConferenceToken,
  1197. FALSE, // bCreate,
  1198. NULL, // pbSessionTableChanged,
  1199. 0, // wListCount,
  1200. NULL, // pTermCapList[],
  1201. NULL, // pTermCapDescriptors[],
  1202. ppSessionTable);
  1203. return CC_NO_MEMORY;
  1204. }
  1205. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->nAddrType = CC_IP_BINARY;
  1206. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = TRUE;
  1207. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort = wPort++;
  1208. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr = dwAddr;
  1209. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr =
  1210. (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  1211. if ((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr == NULL) {
  1212. H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap);
  1213. FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTPAddr);
  1214. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  1215. Free(ChannelList);
  1216. UnlockConference(pConference);
  1217. (*ppSessionTable)->wLength = i;
  1218. DefaultSessionTableConstructor(
  1219. hConference,
  1220. dwConferenceToken,
  1221. FALSE, // bCreate,
  1222. NULL, // pbSessionTableChanged,
  1223. 0, // wListCount,
  1224. NULL, // pTermCapList[],
  1225. NULL, // pTermCapDescriptors[],
  1226. ppSessionTable);
  1227. return CC_NO_MEMORY;
  1228. }
  1229. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->nAddrType = CC_IP_BINARY;
  1230. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = TRUE;
  1231. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort = wPort++;
  1232. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr = dwAddr;
  1233. }
  1234. }
  1235. Free(ChannelList);
  1236. UnlockConference(pConference);
  1237. if (pbSessionTableChanged != NULL)
  1238. *pbSessionTableChanged = TRUE;
  1239. return CC_OK;
  1240. }
  1241. HRESULT DefaultTermCapConstructor( CC_HCONFERENCE hConference,
  1242. DWORD dwConferenceToken,
  1243. BOOL bCreate,
  1244. BOOL *pbTermCapsChanged,
  1245. WORD wListCount,
  1246. PCC_TERMCAPLIST pInTermCapList[],
  1247. PCC_TERMCAPDESCRIPTORS pInTermCapDescriptors[],
  1248. PCC_TERMCAPLIST *ppOutTermCapList,
  1249. PCC_TERMCAPDESCRIPTORS *ppOutTermCapDescriptors)
  1250. {
  1251. HRESULT status;
  1252. PCONFERENCE pConference;
  1253. WORD wNumChannels;
  1254. PCC_HCHANNEL ChannelList;
  1255. WORD i;
  1256. PCHANNEL pChannel;
  1257. ASSERT(hConference != CC_INVALID_HANDLE);
  1258. ASSERT(ppOutTermCapList != NULL);
  1259. ASSERT(ppOutTermCapDescriptors != NULL);
  1260. if (*ppOutTermCapList != NULL) {
  1261. DestroyH245TermCapList(ppOutTermCapList);
  1262. *ppOutTermCapList = NULL;
  1263. }
  1264. if (*ppOutTermCapDescriptors != NULL) {
  1265. DestroyH245TermCapDescriptors(ppOutTermCapDescriptors);
  1266. *ppOutTermCapDescriptors = NULL;
  1267. }
  1268. if (bCreate == FALSE)
  1269. return CC_OK;
  1270. *ppOutTermCapList = NULL;
  1271. *ppOutTermCapDescriptors = NULL;
  1272. if (pbTermCapsChanged != NULL)
  1273. *pbTermCapsChanged = FALSE;
  1274. status = LockConference(hConference, &pConference);
  1275. if (status != CC_OK)
  1276. return status;
  1277. if (pConference->LocalEndpointAttached == NEVER_ATTACHED) {
  1278. // Copy the local term caps to the conference term caps
  1279. status = CopyH245TermCapList(ppOutTermCapList, pConference->pLocalH245TermCapList);
  1280. if (status != CC_OK) {
  1281. UnlockConference(pConference);
  1282. return CC_NO_MEMORY;
  1283. }
  1284. // Copy the local term cap descriptors to the conference term cap descriptors
  1285. status = CopyH245TermCapDescriptors(ppOutTermCapDescriptors, pConference->pLocalH245TermCapDescriptors);
  1286. if (status != CC_OK) {
  1287. UnlockConference(pConference);
  1288. return CC_NO_MEMORY;
  1289. }
  1290. } else { // pConference->LocalEndpointAttached != NEVER_ATTACHED
  1291. // Create one term cap entry for each open channel on this conference
  1292. EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, TX_CHANNEL);
  1293. *ppOutTermCapList = (PCC_TERMCAPLIST)Malloc(sizeof(CC_TERMCAPLIST));
  1294. if (*ppOutTermCapList == NULL) {
  1295. Free(ChannelList);
  1296. UnlockConference(pConference);
  1297. return CC_NO_MEMORY;
  1298. }
  1299. (*ppOutTermCapList)->wLength = wNumChannels;
  1300. if (wNumChannels == 0)
  1301. (*ppOutTermCapList)->pTermCapArray = NULL;
  1302. else {
  1303. (*ppOutTermCapList)->pTermCapArray =
  1304. (PPCC_TERMCAP)Malloc(sizeof(PCC_TERMCAP) * wNumChannels);
  1305. if ((*ppOutTermCapList)->pTermCapArray == NULL) {
  1306. Free(ChannelList);
  1307. UnlockConference(pConference);
  1308. (*ppOutTermCapList)->wLength = 0;
  1309. DefaultTermCapConstructor(
  1310. hConference,
  1311. dwConferenceToken,
  1312. FALSE, // bCreate
  1313. NULL, // pbTermCapsChanged
  1314. 0, // wListCount
  1315. NULL, // pInTermCapList[]
  1316. NULL, // pInTermCapDescriptors[]
  1317. ppOutTermCapList,
  1318. ppOutTermCapDescriptors);
  1319. return CC_NO_MEMORY;
  1320. }
  1321. for (i = 0; i < wNumChannels; i++) {
  1322. status = LockChannel(ChannelList[i], &pChannel);
  1323. if (status != CC_OK) {
  1324. Free(ChannelList);
  1325. UnlockConference(pConference);
  1326. (*ppOutTermCapList)->wLength = i;
  1327. DefaultTermCapConstructor(
  1328. hConference,
  1329. dwConferenceToken,
  1330. FALSE, // bCreate
  1331. NULL, // pbTermCapsChanged
  1332. 0, // wListCount
  1333. NULL, // pInTermCapList[]
  1334. NULL, // pInTermCapDescriptors[]
  1335. ppOutTermCapList,
  1336. ppOutTermCapDescriptors);
  1337. return CC_NO_MEMORY;
  1338. }
  1339. status = H245CopyCap(&((*ppOutTermCapList)->pTermCapArray[i]),
  1340. pChannel->pTxH245TermCap);
  1341. UnlockChannel(pChannel);
  1342. if (status != H245_ERROR_OK) {
  1343. Free(ChannelList);
  1344. UnlockConference(pConference);
  1345. (*ppOutTermCapList)->wLength = i;
  1346. DefaultTermCapConstructor(
  1347. hConference,
  1348. dwConferenceToken,
  1349. FALSE, // bCreate
  1350. NULL, // pbTermCapsChanged
  1351. 0, // wListCount
  1352. NULL, // pInTermCapList[]
  1353. NULL, // pInTermCapDescriptors[]
  1354. ppOutTermCapList,
  1355. ppOutTermCapDescriptors);
  1356. return status;
  1357. }
  1358. (*ppOutTermCapList)->pTermCapArray[i]->Dir = H245_CAPDIR_LCLRXTX;
  1359. (*ppOutTermCapList)->pTermCapArray[i]->CapId = (WORD)(i+1);
  1360. }
  1361. }
  1362. Free(ChannelList);
  1363. UnlockConference(pConference);
  1364. // create a new descriptor list
  1365. status = CreateH245DefaultTermCapDescriptors(ppOutTermCapDescriptors,
  1366. *ppOutTermCapList);
  1367. if (status != CC_OK) {
  1368. DefaultTermCapConstructor(
  1369. hConference,
  1370. dwConferenceToken,
  1371. FALSE, // bCreate
  1372. NULL, // pbTermCapsChanged
  1373. 0, // wListCount
  1374. NULL, // pInTermCapList[]
  1375. NULL, // pInTermCapDescriptors[]
  1376. ppOutTermCapList,
  1377. ppOutTermCapDescriptors);
  1378. return CC_NO_MEMORY;
  1379. }
  1380. } // pConference->LocalEndpointAttached != NEVER_ATTACHED
  1381. if (pbTermCapsChanged != NULL)
  1382. *pbTermCapsChanged = TRUE;
  1383. return CC_OK;
  1384. }
  1385. HRESULT AcceptCall( PCALL pCall,
  1386. PCONFERENCE pConference)
  1387. {
  1388. HRESULT status;
  1389. CC_HCALL hCall;
  1390. CC_HCONFERENCE hConference;
  1391. HQ931CALL hQ931Call;
  1392. CC_CONFERENCEID ConferenceID;
  1393. BYTE bTerminalType;
  1394. CC_ADDR H245Addr;
  1395. H245_INST_T H245Instance;
  1396. PCC_VENDORINFO pVendorInfo;
  1397. PCC_NONSTANDARDDATA pNonStandardData;
  1398. PWSTR pszDisplay;
  1399. CC_ENDPOINTTYPE DestinationEndpointType;
  1400. TRISTATE tsMultipointController;
  1401. DWORD dwLinkLayerPhysicalId;
  1402. DWORD dwBandwidth;
  1403. ASSERT(pCall != NULL);
  1404. ASSERT(pConference != NULL);
  1405. hCall = pCall->hCall;
  1406. hConference = pConference->hConference;
  1407. hQ931Call = pCall->hQ931Call;
  1408. ConferenceID = pCall->ConferenceID;
  1409. pCall->hConference = pConference->hConference;
  1410. status = CopyNonStandardData(&pNonStandardData, pCall->pLocalNonStandardData);
  1411. if (status != CC_OK) {
  1412. UnlockConference(pConference);
  1413. FreeCall(pCall);
  1414. Q931RejectCall(hQ931Call, // Q931 call handle
  1415. CC_REJECT_UNDEFINED_REASON, // reject reason
  1416. &ConferenceID,
  1417. NULL, // alternate address
  1418. pNonStandardData); // non-standard data
  1419. return status;
  1420. }
  1421. status = CopyVendorInfo(&pVendorInfo, pConference->pVendorInfo);
  1422. if (status != CC_OK) {
  1423. UnlockConference(pConference);
  1424. FreeCall(pCall);
  1425. Q931RejectCall(hQ931Call, // Q931 call handle
  1426. CC_REJECT_UNDEFINED_REASON, // reject reason
  1427. &ConferenceID,
  1428. NULL, // alternate address
  1429. pNonStandardData); // non-standard data
  1430. FreeNonStandardData(pNonStandardData);
  1431. return status;
  1432. }
  1433. status = CopyDisplay(&pszDisplay, pCall->pszLocalDisplay);
  1434. if (status != CC_OK) {
  1435. UnlockConference(pConference);
  1436. FreeCall(pCall);
  1437. Q931RejectCall(hQ931Call, // Q931 call handle
  1438. CC_REJECT_UNDEFINED_REASON, // reject reason
  1439. &ConferenceID,
  1440. NULL, // alternate address
  1441. pNonStandardData); // non-standard data
  1442. FreeNonStandardData(pNonStandardData);
  1443. FreeVendorInfo(pVendorInfo);
  1444. return status;
  1445. }
  1446. status = MakeH245PhysicalID(&pCall->dwH245PhysicalID);
  1447. if (status != CC_OK) {
  1448. UnlockConference(pConference);
  1449. FreeCall(pCall);
  1450. Q931RejectCall(hQ931Call, // Q931 call handle
  1451. CC_REJECT_UNDEFINED_REASON, // reject reason
  1452. &ConferenceID,
  1453. NULL, // alternate address
  1454. pNonStandardData); // non-standard data
  1455. FreeNonStandardData(pNonStandardData);
  1456. FreeVendorInfo(pVendorInfo);
  1457. FreeDisplay(pszDisplay);
  1458. return status;
  1459. }
  1460. if (pCall->bCallerIsMC) {
  1461. ASSERT(pConference->tsMultipointController != TS_TRUE);
  1462. ASSERT(pConference->bMultipointCapable == TRUE);
  1463. tsMultipointController = TS_FALSE;
  1464. } else
  1465. tsMultipointController = pConference->tsMultipointController;
  1466. //MULTITHREAD
  1467. //Use a tmp ID so we don't clobber the chosen H245Id.
  1468. // H245Id=>
  1469. // <= linkLayerId
  1470. dwLinkLayerPhysicalId = INVALID_PHYS_ID;
  1471. SetTerminalType(tsMultipointController, &bTerminalType);
  1472. pCall->H245Instance = H245Init(H245_CONF_H323, // configuration
  1473. pCall->dwH245PhysicalID, // H245 physical ID
  1474. &dwLinkLayerPhysicalId, // the link layer ID is returned
  1475. hCall, // dwPreserved
  1476. (H245_CONF_IND_CALLBACK_T)H245Callback, // callback
  1477. bTerminalType);
  1478. if (pCall->H245Instance == H245_INVALID_ID) {
  1479. // H245 initialization failure
  1480. UnlockConference(pConference);
  1481. FreeCall(pCall);
  1482. Q931RejectCall(hQ931Call, // Q931 call handle
  1483. CC_REJECT_UNDEFINED_REASON, // reject reason
  1484. &ConferenceID,
  1485. NULL, // alternate address
  1486. pNonStandardData); // non-standard data
  1487. FreeNonStandardData(pNonStandardData);
  1488. FreeVendorInfo(pVendorInfo);
  1489. FreeDisplay(pszDisplay);
  1490. return CC_INTERNAL_ERROR;
  1491. }
  1492. H245Instance = pCall->H245Instance;
  1493. // Set the H.245 TCP/IP address to the same IP address on which
  1494. // the Q.931 connection was made; this ensures that if the host
  1495. // is multi-homed, the H.245 will be made on the same IP address
  1496. // as the Q.931 connection. Set the initial H.245 port to zero,
  1497. // so that it will be dynamically determined.
  1498. ASSERT(pCall->pQ931LocalConnectAddr != NULL);
  1499. H245Addr = *pCall->pQ931LocalConnectAddr;
  1500. switch (pCall->pQ931LocalConnectAddr->nAddrType) {
  1501. case CC_IP_DOMAIN_NAME:
  1502. H245Addr.Addr.IP_DomainName.wPort = 0;
  1503. break;
  1504. case CC_IP_DOT:
  1505. H245Addr.Addr.IP_Dot.wPort = 0;
  1506. break;
  1507. case CC_IP_BINARY:
  1508. H245Addr.Addr.IP_Binary.wPort = 0;
  1509. break;
  1510. default:
  1511. ASSERT(0);
  1512. UnlockConference(pConference);
  1513. FreeCall(pCall);
  1514. H245ShutDown(H245Instance);
  1515. Q931RejectCall(hQ931Call, // Q931 call handle
  1516. CC_REJECT_UNDEFINED_REASON, // reject reason
  1517. &ConferenceID,
  1518. NULL, // alternate address
  1519. pNonStandardData); // non-standard data
  1520. FreeNonStandardData(pNonStandardData);
  1521. FreeVendorInfo(pVendorInfo);
  1522. FreeDisplay(pszDisplay);
  1523. return CC_INTERNAL_ERROR;
  1524. }
  1525. status = linkLayerListen(&dwLinkLayerPhysicalId,
  1526. H245Instance,
  1527. &H245Addr,
  1528. NULL);
  1529. if (status != NOERROR) {
  1530. UnlockConference(pConference);
  1531. FreeCall(pCall);
  1532. H245ShutDown(H245Instance);
  1533. Q931RejectCall(hQ931Call, // Q931 call handle
  1534. CC_REJECT_UNDEFINED_REASON, // reject reason
  1535. &ConferenceID,
  1536. NULL, // alternate address
  1537. pNonStandardData); // non-standard data
  1538. FreeNonStandardData(pNonStandardData);
  1539. FreeVendorInfo(pVendorInfo);
  1540. FreeDisplay(pszDisplay);
  1541. return status;
  1542. }
  1543. dwBandwidth = pCall->dwBandwidth;
  1544. UnlockConference(pConference);
  1545. UnlockCall(pCall);
  1546. DestinationEndpointType.pVendorInfo = pVendorInfo;
  1547. DestinationEndpointType.bIsTerminal = TRUE;
  1548. DestinationEndpointType.bIsGateway = FALSE;
  1549. status = Q931AcceptCall(hQ931Call,
  1550. pszDisplay,
  1551. pNonStandardData, // non-standard data
  1552. &DestinationEndpointType,
  1553. &H245Addr, // H245 address
  1554. dwBandwidth,
  1555. hCall); // user token
  1556. FreeNonStandardData(pNonStandardData);
  1557. FreeVendorInfo(pVendorInfo);
  1558. FreeDisplay(pszDisplay);
  1559. if (status != CS_OK) {
  1560. if (LockCall(hCall, &pCall) == CC_OK)
  1561. FreeCall(pCall);
  1562. H245ShutDown(H245Instance);
  1563. return status;
  1564. }
  1565. status = LockCallAndConference(hCall, &pCall, &pConference);
  1566. if (status != CC_OK) {
  1567. if (LockCall(hCall, &pCall) == CC_OK)
  1568. FreeCall(pCall);
  1569. H245ShutDown(H245Instance);
  1570. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  1571. return status;
  1572. }
  1573. pCall->CallState = TERMCAP;
  1574. pConference->ConferenceID = pCall->ConferenceID;
  1575. status = AddPlacedCallToConference(pCall, pConference);
  1576. if (status != CC_OK) {
  1577. UnlockConference(pConference);
  1578. FreeCall(pCall);
  1579. H245ShutDown(H245Instance);
  1580. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  1581. return status;
  1582. }
  1583. status = SendTermCaps(pCall, pConference);
  1584. if (status != CC_OK) {
  1585. UnlockConference(pConference);
  1586. FreeCall(pCall);
  1587. H245ShutDown(H245Instance);
  1588. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  1589. return status;
  1590. }
  1591. pCall->OutgoingTermCapState = AWAITING_ACK;
  1592. if (pCall->MasterSlaveState == MASTER_SLAVE_NOT_STARTED) {
  1593. status = H245InitMasterSlave(H245Instance,
  1594. H245Instance); // returned as dwTransId in the callback
  1595. if (status != H245_ERROR_OK) {
  1596. UnlockConference(pConference);
  1597. FreeCall(pCall);
  1598. H245ShutDown(H245Instance);
  1599. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  1600. return status;
  1601. }
  1602. pCall->MasterSlaveState = MASTER_SLAVE_IN_PROGRESS;
  1603. }
  1604. if (pCall->bCallerIsMC) {
  1605. pConference->tsMultipointController = TS_FALSE;
  1606. pConference->ConferenceMode = MULTIPOINT_MODE;
  1607. }
  1608. UnlockConference(pConference);
  1609. UnlockCall(pCall);
  1610. return CC_OK;
  1611. }
  1612. HRESULT PlaceCall( PCALL pCall,
  1613. PCONFERENCE pConference)
  1614. {
  1615. CC_HCALL hCall;
  1616. HRESULT status;
  1617. WORD wGoal;
  1618. HQ931CALL hQ931Call;
  1619. PCC_ALIASNAMES pCallerAliasNames;
  1620. PCC_ALIASNAMES pCalleeAliasNames;
  1621. PCC_ALIASNAMES pCalleeExtraAliasNames;
  1622. PCC_ALIASITEM pCalleeExtension;
  1623. PCC_VENDORINFO pVendorInfo;
  1624. PWSTR pszDisplay;
  1625. PCC_NONSTANDARDDATA pNonStandardData;
  1626. WORD wNumCalls;
  1627. PCC_ADDR pConnectAddr;
  1628. PCC_ADDR pDestinationAddr;
  1629. CC_ADDR SourceAddr;
  1630. CC_ENDPOINTTYPE SourceEndpointType;
  1631. BOOL bCallerIsMC;
  1632. WORD wCallType;
  1633. ASSERT(pCall != NULL);
  1634. hCall = pCall->hCall;
  1635. if (pCall->CallState == ENQUEUED) {
  1636. // Enqueue the call on the conference object and HResultLeaveCallControl.
  1637. // There will be exactly one placed call for this conference,
  1638. // which is in the process of being placed. If this call placement
  1639. // completes successfully, all enqueued calls will then be placed.
  1640. // If this call placement fails or is terminated, one enqueued call
  1641. // will be placed
  1642. status = AddEnqueuedCallToConference(pCall, pConference);
  1643. return status;
  1644. }
  1645. // CallState == PLACED
  1646. EnumerateCallsInConference(&wNumCalls,
  1647. NULL,
  1648. pConference,
  1649. PLACED_CALL | ESTABLISHED_CALL);
  1650. if (EqualConferenceIDs(&pConference->ConferenceID, &InvalidConferenceID))
  1651. wGoal = CSG_CREATE;
  1652. else if ((wNumCalls == 0) && (pConference->tsMultipointController != TS_TRUE))
  1653. wGoal = CSG_JOIN;
  1654. else
  1655. wGoal = CSG_INVITE;
  1656. status = AddPlacedCallToConference(pCall, pConference);
  1657. if (status != CC_OK)
  1658. return status;
  1659. status = CopyAddr(&pConnectAddr, pCall->pQ931PeerConnectAddr);
  1660. if (status != CC_OK)
  1661. return status;
  1662. status = CopyAddr(&pDestinationAddr, pCall->pQ931DestinationAddr);
  1663. if (status != CC_OK) {
  1664. FreeAddr(pConnectAddr);
  1665. return status;
  1666. }
  1667. status = Q931CopyAliasNames(&pCallerAliasNames, pCall->pLocalAliasNames);
  1668. if (status != CS_OK) {
  1669. FreeAddr(pConnectAddr);
  1670. FreeAddr(pDestinationAddr);
  1671. return status;
  1672. }
  1673. status = CopyVendorInfo(&pVendorInfo, pConference->pVendorInfo);
  1674. if (status != CC_OK) {
  1675. FreeAddr(pConnectAddr);
  1676. FreeAddr(pDestinationAddr);
  1677. Q931FreeAliasNames(pCallerAliasNames);
  1678. return status;
  1679. }
  1680. status = CopyDisplay(&pszDisplay, pCall->pszLocalDisplay);
  1681. if (status != CC_OK) {
  1682. FreeAddr(pConnectAddr);
  1683. FreeAddr(pDestinationAddr);
  1684. Q931FreeAliasNames(pCallerAliasNames);
  1685. FreeVendorInfo(pVendorInfo);
  1686. return status;
  1687. }
  1688. status = Q931CopyAliasNames(&pCalleeAliasNames, pCall->pPeerAliasNames);
  1689. if (status != CS_OK) {
  1690. FreeAddr(pConnectAddr);
  1691. FreeAddr(pDestinationAddr);
  1692. Q931FreeAliasNames(pCallerAliasNames);
  1693. FreeVendorInfo(pVendorInfo);
  1694. FreeDisplay(pszDisplay);
  1695. return status;
  1696. }
  1697. status = Q931CopyAliasNames(&pCalleeExtraAliasNames,
  1698. pCall->pPeerExtraAliasNames);
  1699. if (status != CS_OK) {
  1700. FreeAddr(pConnectAddr);
  1701. FreeAddr(pDestinationAddr);
  1702. Q931FreeAliasNames(pCallerAliasNames);
  1703. FreeVendorInfo(pVendorInfo);
  1704. FreeDisplay(pszDisplay);
  1705. Q931FreeAliasNames(pCalleeAliasNames);
  1706. return status;
  1707. }
  1708. status = Q931CopyAliasItem(&pCalleeExtension,
  1709. pCall->pPeerExtension);
  1710. if (status != CS_OK) {
  1711. FreeAddr(pConnectAddr);
  1712. FreeAddr(pDestinationAddr);
  1713. Q931FreeAliasNames(pCallerAliasNames);
  1714. FreeVendorInfo(pVendorInfo);
  1715. FreeDisplay(pszDisplay);
  1716. Q931FreeAliasNames(pCalleeAliasNames);
  1717. Q931FreeAliasNames(pCalleeExtraAliasNames);
  1718. return status;
  1719. }
  1720. status = CopyNonStandardData(&pNonStandardData, pCall->pLocalNonStandardData);
  1721. if (status != CC_OK) {
  1722. FreeAddr(pConnectAddr);
  1723. FreeAddr(pDestinationAddr);
  1724. Q931FreeAliasNames(pCallerAliasNames);
  1725. FreeVendorInfo(pVendorInfo);
  1726. FreeDisplay(pszDisplay);
  1727. Q931FreeAliasNames(pCalleeAliasNames);
  1728. Q931FreeAliasNames(pCalleeExtraAliasNames);
  1729. Q931FreeAliasItem(pCalleeExtension);
  1730. return status;
  1731. }
  1732. bCallerIsMC = (pConference->tsMultipointController == TS_TRUE ? TRUE : FALSE);
  1733. // Note that if pConference->ConferenceMode == POINT_TO_POINT_MODE, this call attempt
  1734. // will result in a multipoint call if successful, so set the wCallType accordingly
  1735. wCallType = (WORD)((pConference->ConferenceMode == UNCONNECTED_MODE) ? CC_CALLTYPE_PT_PT : CC_CALLTYPE_N_N);
  1736. SourceEndpointType.pVendorInfo = pVendorInfo;
  1737. SourceEndpointType.bIsTerminal = TRUE;
  1738. SourceEndpointType.bIsGateway = FALSE;
  1739. // Cause our local Q.931 connect address to be placed in the
  1740. // Q.931 setup-UUIE sourceAddress field
  1741. SourceAddr.nAddrType = CC_IP_BINARY;
  1742. SourceAddr.bMulticast = FALSE;
  1743. SourceAddr.Addr.IP_Binary.dwAddr = 0;
  1744. SourceAddr.Addr.IP_Binary.wPort = 0;
  1745. status = Q931PlaceCall(&hQ931Call, // Q931 call handle
  1746. pszDisplay,
  1747. pCallerAliasNames,
  1748. pCalleeAliasNames,
  1749. pCalleeExtraAliasNames, // pCalleeExtraAliasNames
  1750. pCalleeExtension, // pCalleeExtension
  1751. pNonStandardData, // non-standard data
  1752. &SourceEndpointType,
  1753. NULL, // pszCalledPartyNumber
  1754. pConnectAddr,
  1755. pDestinationAddr,
  1756. &SourceAddr, // source address
  1757. bCallerIsMC,
  1758. &pCall->ConferenceID, // conference ID
  1759. wGoal,
  1760. wCallType,
  1761. hCall, // user token
  1762. (Q931_CALLBACK)Q931Callback, // callback
  1763. pCall->dwBandwidth,
  1764. #ifdef GATEKEEPER
  1765. pCall->GkiCall.usCRV); // CRV
  1766. #else
  1767. 0); // CRV
  1768. #endif GATEKEEPER
  1769. FreeAddr(pConnectAddr);
  1770. FreeAddr(pDestinationAddr);
  1771. Q931FreeAliasNames(pCallerAliasNames);
  1772. FreeVendorInfo(pVendorInfo);
  1773. FreeDisplay(pszDisplay);
  1774. Q931FreeAliasNames(pCalleeAliasNames);
  1775. Q931FreeAliasNames(pCalleeExtraAliasNames);
  1776. Q931FreeAliasItem(pCalleeExtension);
  1777. FreeNonStandardData(pNonStandardData);
  1778. if (status != CS_OK)
  1779. return status;
  1780. pCall->hQ931Call = hQ931Call;
  1781. return CC_OK;
  1782. }
  1783. HRESULT SendTermCaps( PCALL pCall,
  1784. PCONFERENCE pConference)
  1785. {
  1786. HRESULT status;
  1787. WORD i;
  1788. H245_TOTCAPDESC_T *pTermCapDescriptor;
  1789. PCC_TERMCAP pH2250MuxCapability;
  1790. PCC_TERMCAPLIST pTermCapList;
  1791. PCC_TERMCAPDESCRIPTORS pTermCapDescriptors;
  1792. ASSERT(pCall != NULL);
  1793. ASSERT(pConference != NULL);
  1794. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  1795. (pConference->tsMultipointController == TS_TRUE)) {
  1796. pH2250MuxCapability = pConference->pConferenceH245H2250MuxCapability;
  1797. pTermCapList = pConference->pConferenceTermCapList;
  1798. pTermCapDescriptors = pConference->pConferenceTermCapDescriptors;
  1799. } else {
  1800. pH2250MuxCapability = pConference->pLocalH245H2250MuxCapability;
  1801. pTermCapList = pConference->pLocalH245TermCapList;
  1802. pTermCapDescriptors = pConference->pLocalH245TermCapDescriptors;
  1803. }
  1804. ASSERT(pH2250MuxCapability != NULL);
  1805. ASSERT(pTermCapList != NULL);
  1806. ASSERT(pTermCapDescriptors != NULL);
  1807. // First send out the H.225.0 capability
  1808. status = H245SetLocalCap(pCall->H245Instance,
  1809. pH2250MuxCapability,
  1810. &pH2250MuxCapability->CapId);
  1811. ASSERT(pH2250MuxCapability->CapId == 0);
  1812. if (status != H245_ERROR_OK)
  1813. return status;
  1814. // Now send out the terminal capabilities
  1815. for (i = 0; i < pTermCapList->wLength; i++) {
  1816. status = H245SetLocalCap(pCall->H245Instance,
  1817. pTermCapList->pTermCapArray[i],
  1818. &pTermCapList->pTermCapArray[i]->CapId);
  1819. if (status != H245_ERROR_OK)
  1820. return status;
  1821. }
  1822. // Finally send out the capability descriptors
  1823. for (i = 0; i < pTermCapDescriptors->wLength; i++) {
  1824. pTermCapDescriptor = pTermCapDescriptors->pTermCapDescriptorArray[i];
  1825. status = H245SetCapDescriptor(pCall->H245Instance,
  1826. &pTermCapDescriptor->CapDesc,
  1827. &pTermCapDescriptor->CapDescId);
  1828. if (status != H245_ERROR_OK)
  1829. return status;
  1830. }
  1831. status = H245SendTermCaps(pCall->H245Instance,
  1832. pCall->H245Instance); // returned as dwTransId in the callback
  1833. return status;
  1834. }
  1835. HRESULT SessionTableToH245CommunicationTable(
  1836. PCC_SESSIONTABLE pSessionTable,
  1837. H245_COMM_MODE_ENTRY_T *pH245CommunicationTable[],
  1838. BYTE *pbCommunicationTableCount)
  1839. {
  1840. WORD i, j;
  1841. WORD wStringLength;
  1842. ASSERT(pH245CommunicationTable != NULL);
  1843. ASSERT(pbCommunicationTableCount != NULL);
  1844. if ((pSessionTable == NULL) || (pSessionTable->wLength == 0)) {
  1845. *pH245CommunicationTable = NULL;
  1846. *pbCommunicationTableCount = 0;
  1847. return CC_OK;
  1848. }
  1849. if (pSessionTable->SessionInfoArray == NULL) {
  1850. *pH245CommunicationTable = NULL;
  1851. *pbCommunicationTableCount = 0;
  1852. return CC_BAD_PARAM;
  1853. }
  1854. *pH245CommunicationTable = (H245_COMM_MODE_ENTRY_T *)Malloc(sizeof(H245_COMM_MODE_ENTRY_T) * pSessionTable->wLength);
  1855. if (*pH245CommunicationTable == NULL) {
  1856. *pbCommunicationTableCount = 0;
  1857. return CC_NO_MEMORY;
  1858. }
  1859. *pbCommunicationTableCount = (BYTE)pSessionTable->wLength;
  1860. for (i = 0; i < pSessionTable->wLength; i++) {
  1861. (*pH245CommunicationTable)[i].pNonStandard = NULL;
  1862. (*pH245CommunicationTable)[i].sessionID = pSessionTable->SessionInfoArray[i].bSessionID;
  1863. if (pSessionTable->SessionInfoArray[i].bAssociatedSessionID == 0)
  1864. (*pH245CommunicationTable)[i].associatedSessionIDPresent = FALSE;
  1865. else {
  1866. (*pH245CommunicationTable)[i].associatedSessionIDPresent = TRUE;
  1867. (*pH245CommunicationTable)[i].associatedSessionID = pSessionTable->SessionInfoArray[i].bAssociatedSessionID;
  1868. }
  1869. (*pH245CommunicationTable)[i].terminalLabelPresent = FALSE;
  1870. wStringLength = pSessionTable->SessionInfoArray[i].SessionDescription.wOctetStringLength;
  1871. if (wStringLength > 0) {
  1872. (*pH245CommunicationTable)[i].pSessionDescription = (unsigned short *)Malloc(sizeof(unsigned short) * wStringLength);
  1873. if ((*pH245CommunicationTable)[i].pSessionDescription == NULL) {
  1874. for (j = 0; j < i; j++)
  1875. Free((*pH245CommunicationTable)[j].pSessionDescription);
  1876. Free(*pH245CommunicationTable);
  1877. *pbCommunicationTableCount = 0;
  1878. return CC_NO_MEMORY;
  1879. }
  1880. memcpy((*pH245CommunicationTable)[i].pSessionDescription,
  1881. pSessionTable->SessionInfoArray[i].SessionDescription.pOctetString,
  1882. wStringLength);
  1883. } else
  1884. (*pH245CommunicationTable)[i].pSessionDescription = NULL;
  1885. (*pH245CommunicationTable)[i].wSessionDescriptionLength = wStringLength;
  1886. (*pH245CommunicationTable)[i].dataType = *pSessionTable->SessionInfoArray[i].pTermCap;
  1887. if (pSessionTable->SessionInfoArray[i].pRTPAddr == NULL)
  1888. (*pH245CommunicationTable)[i].mediaChannelPresent = FALSE;
  1889. else {
  1890. if (pSessionTable->SessionInfoArray[i].pRTPAddr->nAddrType != CC_IP_BINARY) {
  1891. for (j = 0; j <= i; j++)
  1892. if ((*pH245CommunicationTable)[j].pSessionDescription != NULL)
  1893. Free((*pH245CommunicationTable)[j].pSessionDescription);
  1894. Free(*pH245CommunicationTable);
  1895. *pbCommunicationTableCount = 0;
  1896. return CC_BAD_PARAM;
  1897. }
  1898. if (pSessionTable->SessionInfoArray[i].pRTPAddr->bMulticast)
  1899. (*pH245CommunicationTable)[i].mediaChannel.type = H245_IP_MULTICAST;
  1900. else
  1901. (*pH245CommunicationTable)[i].mediaChannel.type = H245_IP_UNICAST;
  1902. (*pH245CommunicationTable)[i].mediaChannel.u.ip.tsapIdentifier =
  1903. pSessionTable->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort;
  1904. HostToH245IPNetwork((*pH245CommunicationTable)[i].mediaChannel.u.ip.network,
  1905. pSessionTable->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr);
  1906. (*pH245CommunicationTable)[i].mediaChannelPresent = TRUE;
  1907. }
  1908. if (pSessionTable->SessionInfoArray[i].pRTCPAddr == NULL)
  1909. (*pH245CommunicationTable)[i].mediaControlChannelPresent = FALSE;
  1910. else {
  1911. if (pSessionTable->SessionInfoArray[i].pRTCPAddr->nAddrType != CC_IP_BINARY) {
  1912. for (j = 0; j <= i; j++)
  1913. if ((*pH245CommunicationTable)[j].pSessionDescription != NULL)
  1914. Free((*pH245CommunicationTable)[j].pSessionDescription);
  1915. Free(*pH245CommunicationTable);
  1916. *pbCommunicationTableCount = 0;
  1917. return CC_BAD_PARAM;
  1918. }
  1919. if (pSessionTable->SessionInfoArray[i].pRTCPAddr->bMulticast)
  1920. (*pH245CommunicationTable)[i].mediaControlChannel.type = H245_IP_MULTICAST;
  1921. else
  1922. (*pH245CommunicationTable)[i].mediaControlChannel.type = H245_IP_UNICAST;
  1923. (*pH245CommunicationTable)[i].mediaControlChannel.u.ip.tsapIdentifier =
  1924. pSessionTable->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort;
  1925. HostToH245IPNetwork((*pH245CommunicationTable)[i].mediaControlChannel.u.ip.network,
  1926. pSessionTable->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr);
  1927. (*pH245CommunicationTable)[i].mediaControlChannelPresent = TRUE;
  1928. }
  1929. (*pH245CommunicationTable)[i].mediaGuaranteed = FALSE;
  1930. (*pH245CommunicationTable)[i].mediaGuaranteedPresent = TRUE;
  1931. (*pH245CommunicationTable)[i].mediaControlGuaranteed = FALSE;
  1932. (*pH245CommunicationTable)[i].mediaControlGuaranteedPresent = TRUE;
  1933. }
  1934. return CC_OK;
  1935. }
  1936. HRESULT H245CommunicationTableToSessionTable(
  1937. H245_COMM_MODE_ENTRY_T H245CommunicationTable[],
  1938. BYTE bCommunicationTableCount,
  1939. PCC_SESSIONTABLE *ppSessionTable)
  1940. {
  1941. WORD i, j;
  1942. HRESULT status;
  1943. ASSERT(ppSessionTable != NULL);
  1944. if (H245CommunicationTable == NULL)
  1945. if (bCommunicationTableCount == 0) {
  1946. *ppSessionTable = NULL;
  1947. return CC_OK;
  1948. } else
  1949. return CC_BAD_PARAM;
  1950. else
  1951. if (bCommunicationTableCount == 0)
  1952. return CC_BAD_PARAM;
  1953. *ppSessionTable = (PCC_SESSIONTABLE)Malloc(sizeof(CC_SESSIONTABLE));
  1954. if (*ppSessionTable == NULL)
  1955. return CC_NO_MEMORY;
  1956. (*ppSessionTable)->wLength = bCommunicationTableCount;
  1957. (*ppSessionTable)->SessionInfoArray = (PCC_SESSIONINFO)Malloc(sizeof(CC_SESSIONINFO) * bCommunicationTableCount);
  1958. if ((*ppSessionTable)->SessionInfoArray == NULL) {
  1959. Free(*ppSessionTable);
  1960. *ppSessionTable = NULL;
  1961. return CC_NO_MEMORY;
  1962. }
  1963. for (i = 0; i < bCommunicationTableCount; i++) {
  1964. (*ppSessionTable)->SessionInfoArray[i].bSessionID = H245CommunicationTable[i].sessionID;
  1965. if (H245CommunicationTable[i].associatedSessionIDPresent)
  1966. (*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID =
  1967. H245CommunicationTable[i].associatedSessionID;
  1968. else
  1969. (*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID = 0;
  1970. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength =
  1971. H245CommunicationTable[i].wSessionDescriptionLength;
  1972. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength == 0)
  1973. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString = NULL;
  1974. else {
  1975. (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString =
  1976. (BYTE *)Malloc(H245CommunicationTable[i].wSessionDescriptionLength);
  1977. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString == NULL) {
  1978. for (j = 0; j < i; j++) {
  1979. H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap);
  1980. if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL)
  1981. Free((*ppSessionTable)->SessionInfoArray[j].pRTPAddr);
  1982. if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL)
  1983. Free((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr);
  1984. }
  1985. Free((*ppSessionTable)->SessionInfoArray);
  1986. Free(*ppSessionTable);
  1987. return CC_NO_MEMORY;
  1988. }
  1989. memcpy((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString,
  1990. H245CommunicationTable[i].pSessionDescription,
  1991. H245CommunicationTable[i].wSessionDescriptionLength);
  1992. }
  1993. status = H245CopyCap(&(*ppSessionTable)->SessionInfoArray[i].pTermCap,
  1994. &H245CommunicationTable[i].dataType);
  1995. if (status != H245_ERROR_OK) {
  1996. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL)
  1997. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  1998. for (j = 0; j < i; j++) {
  1999. H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap);
  2000. if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL)
  2001. Free((*ppSessionTable)->SessionInfoArray[j].pRTPAddr);
  2002. if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL)
  2003. Free((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr);
  2004. }
  2005. Free((*ppSessionTable)->SessionInfoArray);
  2006. Free(*ppSessionTable);
  2007. return status;
  2008. }
  2009. if ((H245CommunicationTable[i].mediaChannelPresent) &&
  2010. ((H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST) ||
  2011. (H245CommunicationTable[i].mediaChannel.type == H245_IP_UNICAST))) {
  2012. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  2013. if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr == NULL) {
  2014. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL)
  2015. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  2016. H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap);
  2017. for (j = 0; j < i; j++) {
  2018. H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap);
  2019. if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL)
  2020. Free((*ppSessionTable)->SessionInfoArray[j].pRTPAddr);
  2021. if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL)
  2022. Free((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr);
  2023. }
  2024. Free((*ppSessionTable)->SessionInfoArray);
  2025. Free(*ppSessionTable);
  2026. return CC_NO_MEMORY;
  2027. }
  2028. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->nAddrType = CC_IP_BINARY;
  2029. if (H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST)
  2030. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = TRUE;
  2031. else
  2032. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = FALSE;
  2033. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort =
  2034. H245CommunicationTable[i].mediaChannel.u.ip.tsapIdentifier;
  2035. H245IPNetworkToHost(&(*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr,
  2036. H245CommunicationTable[i].mediaChannel.u.ip.network);
  2037. } else
  2038. (*ppSessionTable)->SessionInfoArray[i].pRTPAddr = NULL;
  2039. if ((H245CommunicationTable[i].mediaControlChannelPresent) &&
  2040. ((H245CommunicationTable[i].mediaControlChannel.type == H245_IP_MULTICAST) ||
  2041. (H245CommunicationTable[i].mediaControlChannel.type == H245_IP_UNICAST))) {
  2042. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  2043. if ((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr == NULL) {
  2044. if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL)
  2045. Free((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString);
  2046. H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap);
  2047. if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr != NULL)
  2048. Free((*ppSessionTable)->SessionInfoArray[i].pRTPAddr);
  2049. for (j = 0; j < i; j++) {
  2050. H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap);
  2051. if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL)
  2052. Free((*ppSessionTable)->SessionInfoArray[j].pRTPAddr);
  2053. if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL)
  2054. Free((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr);
  2055. }
  2056. Free((*ppSessionTable)->SessionInfoArray);
  2057. Free(*ppSessionTable);
  2058. return CC_NO_MEMORY;
  2059. }
  2060. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->nAddrType = CC_IP_BINARY;
  2061. if (H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST)
  2062. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = TRUE;
  2063. else
  2064. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = FALSE;
  2065. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort =
  2066. H245CommunicationTable[i].mediaControlChannel.u.ip.tsapIdentifier;
  2067. H245IPNetworkToHost(&(*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr,
  2068. H245CommunicationTable[i].mediaControlChannel.u.ip.network);
  2069. } else
  2070. (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr = NULL;
  2071. }
  2072. return CC_OK;
  2073. }
  2074. HRESULT FreeH245CommunicationTable( H245_COMM_MODE_ENTRY_T H245CommunicationTable[],
  2075. BYTE bCommunicationTableCount)
  2076. {
  2077. WORD i;
  2078. if (H245CommunicationTable == NULL)
  2079. if (bCommunicationTableCount == 0)
  2080. return CC_OK;
  2081. else
  2082. return CC_BAD_PARAM;
  2083. else
  2084. if (bCommunicationTableCount == 0)
  2085. return CC_BAD_PARAM;
  2086. for (i = 0; i < bCommunicationTableCount; i++)
  2087. if (H245CommunicationTable[i].pSessionDescription != NULL)
  2088. Free(H245CommunicationTable[i].pSessionDescription);
  2089. Free(H245CommunicationTable);
  2090. return CC_OK;
  2091. }
  2092. HRESULT _PrepareTermCapLists( PCONFERENCE pConference,
  2093. WORD *pwListCount,
  2094. PCC_TERMCAPLIST **ppTermCapList,
  2095. PCC_TERMCAPDESCRIPTORS **ppTermCapDescriptorList,
  2096. PCALL *pCallList[])
  2097. {
  2098. WORD i;
  2099. WORD wNumCalls;
  2100. WORD wOffset;
  2101. PCC_HCALL CallList;
  2102. PCALL pCall;
  2103. ASSERT(pConference != NULL);
  2104. ASSERT(pwListCount != NULL);
  2105. ASSERT(ppTermCapList != NULL);
  2106. ASSERT(ppTermCapDescriptorList != NULL);
  2107. ASSERT(pCallList != NULL);
  2108. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  2109. if ((pConference->LocalEndpointAttached == DETACHED) && (wNumCalls > 0))
  2110. wOffset = 0;
  2111. else
  2112. // LocalEndpointAttached is either UNATTACHED or ATTACHED, or there are no calls
  2113. // in the conference; in the latter case, we need to have some term caps in
  2114. // order to form the conference term cap set (which cannot be empty)
  2115. wOffset = 1;
  2116. *pwListCount = (WORD)(wNumCalls + wOffset);
  2117. *ppTermCapList = (PCC_TERMCAPLIST *)Malloc(sizeof(PCC_TERMCAPLIST) * (*pwListCount));
  2118. if (*ppTermCapList == NULL) {
  2119. Free(CallList);
  2120. return CC_NO_MEMORY;
  2121. }
  2122. *ppTermCapDescriptorList = (PCC_TERMCAPDESCRIPTORS *)Malloc(sizeof(PCC_TERMCAPDESCRIPTORS) * (*pwListCount));
  2123. if (*ppTermCapDescriptorList == NULL) {
  2124. Free(CallList);
  2125. Free(*ppTermCapList);
  2126. return CC_NO_MEMORY;
  2127. }
  2128. *pCallList = (PCALL *)Malloc(sizeof(PCALL) * (*pwListCount));
  2129. if (*pCallList == NULL) {
  2130. Free(CallList);
  2131. Free(*ppTermCapList);
  2132. Free(*ppTermCapDescriptorList);
  2133. return CC_NO_MEMORY;
  2134. }
  2135. // Fill in pTermCapList and pTermCapDescriptorList
  2136. if (wOffset == 1) {
  2137. // The local endpoint is attached to the conference, so fill in the first
  2138. // slot in both lists with the local term cap and descriptor lists
  2139. (*ppTermCapList)[0] = pConference->pLocalH245TermCapList;
  2140. (*ppTermCapDescriptorList)[0] = pConference->pLocalH245TermCapDescriptors;
  2141. }
  2142. for (i = 0; i < wNumCalls; i++) {
  2143. if (LockCall(CallList[i], &pCall) == CC_OK) {
  2144. (*ppTermCapList)[i+wOffset] = pCall->pPeerH245TermCapList;
  2145. (*ppTermCapDescriptorList)[i+wOffset] = pCall->pPeerH245TermCapDescriptors;
  2146. (*pCallList)[i] = pCall;
  2147. } else {
  2148. (*ppTermCapList)[i+wOffset] = NULL;
  2149. (*ppTermCapDescriptorList)[i+wOffset] = NULL;
  2150. (*pCallList)[i] = NULL;
  2151. }
  2152. }
  2153. for (i = 0; i < wOffset; i++)
  2154. (*pCallList)[wNumCalls+i] = NULL;
  2155. Free(CallList);
  2156. return CC_OK;
  2157. }
  2158. HRESULT _FreeTermCapLists( WORD wListCount,
  2159. PCC_TERMCAPLIST *pTermCapList,
  2160. PCC_TERMCAPDESCRIPTORS *pTermCapDescriptorList,
  2161. PCALL pCallList[])
  2162. {
  2163. WORD i;
  2164. for (i = 0; i < wListCount; i++)
  2165. if (pCallList[i] != NULL)
  2166. UnlockCall(pCallList[i]);
  2167. if (pTermCapList != NULL)
  2168. Free(pTermCapList);
  2169. if (pTermCapDescriptorList != NULL)
  2170. Free(pTermCapDescriptorList);
  2171. Free(pCallList);
  2172. return CC_OK;
  2173. }
  2174. HRESULT CreateConferenceSessionTable(
  2175. PCONFERENCE pConference,
  2176. BOOL *pbSessionTableChanged)
  2177. {
  2178. HRESULT status;
  2179. PCALL *pCallList;
  2180. PCC_TERMCAPLIST *pTermCapList;
  2181. PCC_TERMCAPDESCRIPTORS *pTermCapDescriptorList;
  2182. WORD wListCount;
  2183. ASSERT(pConference != NULL);
  2184. if (pConference->bSessionTableInternallyConstructed == TRUE) {
  2185. status = FreeConferenceSessionTable(pConference);
  2186. if (status != CC_OK)
  2187. return status;
  2188. pConference->bSessionTableInternallyConstructed = FALSE;
  2189. }
  2190. status = _PrepareTermCapLists(pConference,
  2191. &wListCount,
  2192. &pTermCapList,
  2193. &pTermCapDescriptorList,
  2194. &pCallList);
  2195. if (status != CC_OK)
  2196. return status;
  2197. status = pConference->SessionTableConstructor(
  2198. pConference->hConference,
  2199. pConference->dwConferenceToken,
  2200. TRUE, // bCreate
  2201. pbSessionTableChanged,
  2202. wListCount,
  2203. pTermCapList,
  2204. pTermCapDescriptorList,
  2205. &pConference->pSessionTable);
  2206. _FreeTermCapLists(wListCount,
  2207. pTermCapList,
  2208. pTermCapDescriptorList,
  2209. pCallList);
  2210. return status;
  2211. }
  2212. HRESULT FreeConferenceSessionTable( PCONFERENCE pConference)
  2213. {
  2214. HRESULT status;
  2215. ASSERT(pConference != NULL);
  2216. if (pConference->bSessionTableInternallyConstructed)
  2217. status = DefaultSessionTableConstructor(
  2218. pConference->hConference,
  2219. pConference->dwConferenceToken,
  2220. FALSE, // bCreate
  2221. NULL, // pbSessionTableChanged
  2222. 0, // wListCount
  2223. NULL, // pTermCapList[]
  2224. NULL, // pTermCapDescriptors[]
  2225. &pConference->pSessionTable);
  2226. else
  2227. status = pConference->SessionTableConstructor(
  2228. pConference->hConference,
  2229. pConference->dwConferenceToken,
  2230. FALSE, // bCreate
  2231. NULL, // pbSessionTableChanged
  2232. 0, // wListCount
  2233. NULL, // pTermCapList[]
  2234. NULL, // pTermCapDescriptors[]
  2235. &pConference->pSessionTable);
  2236. pConference->pSessionTable = NULL;
  2237. return status;
  2238. }
  2239. HRESULT CreateConferenceTermCaps( PCONFERENCE pConference,
  2240. BOOL *pbTermCapsChanged)
  2241. {
  2242. HRESULT status;
  2243. WORD wListCount;
  2244. PCALL *pCallList;
  2245. PCC_TERMCAPLIST *pInTermCapList;
  2246. PCC_TERMCAPDESCRIPTORS *pInTermCapDescriptors;
  2247. ASSERT(pConference != NULL);
  2248. if (pConference->pConferenceH245H2250MuxCapability != NULL)
  2249. H245FreeCap(pConference->pConferenceH245H2250MuxCapability);
  2250. ASSERT(pConference->pLocalH245H2250MuxCapability != NULL);
  2251. status = H245CopyCap(&pConference->pConferenceH245H2250MuxCapability,
  2252. pConference->pLocalH245H2250MuxCapability);
  2253. if (status != H245_ERROR_OK)
  2254. return status;
  2255. status = _PrepareTermCapLists(pConference,
  2256. &wListCount,
  2257. &pInTermCapList,
  2258. &pInTermCapDescriptors,
  2259. &pCallList);
  2260. if (status != CC_OK)
  2261. return status;
  2262. status = UnregisterTermCapListFromH245(pConference,
  2263. pConference->pConferenceTermCapList);
  2264. if (status != CC_OK)
  2265. return status;
  2266. status = UnregisterTermCapDescriptorsFromH245(pConference,
  2267. pConference->pConferenceTermCapDescriptors);
  2268. if (status != CC_OK)
  2269. return status;
  2270. status = pConference->TermCapConstructor(
  2271. pConference->hConference,
  2272. pConference->dwConferenceToken,
  2273. TRUE, // bCreate
  2274. pbTermCapsChanged,
  2275. wListCount,
  2276. pInTermCapList,
  2277. pInTermCapDescriptors,
  2278. &pConference->pConferenceTermCapList,
  2279. &pConference->pConferenceTermCapDescriptors);
  2280. _FreeTermCapLists(wListCount,
  2281. pInTermCapList,
  2282. pInTermCapDescriptors,
  2283. pCallList);
  2284. return status;
  2285. }
  2286. HRESULT FreeConferenceTermCaps( PCONFERENCE pConference)
  2287. {
  2288. HRESULT status;
  2289. ASSERT(pConference != NULL);
  2290. status = pConference->TermCapConstructor(
  2291. pConference->hConference,
  2292. pConference->dwConferenceToken,
  2293. FALSE, // bCreate
  2294. NULL, // pbTermCapsChanged
  2295. 0, // wListCount
  2296. NULL, // pInTermCapList[]
  2297. NULL, // pInTermCapDescriptors[]
  2298. &pConference->pConferenceTermCapList,
  2299. &pConference->pConferenceTermCapDescriptors);
  2300. pConference->pConferenceTermCapList = NULL;
  2301. pConference->pConferenceTermCapDescriptors = NULL;
  2302. return status;
  2303. }
  2304. HRESULT FindEnqueuedRequest( PCALL_QUEUE pQueueHead,
  2305. CC_HCALL hEnqueuedCall)
  2306. {
  2307. PCALL_QUEUE pQueueItem;
  2308. ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
  2309. pQueueItem = pQueueHead;
  2310. while (pQueueItem != NULL) {
  2311. if (pQueueItem->hCall == hEnqueuedCall)
  2312. break;
  2313. pQueueItem = pQueueItem->pNext;
  2314. }
  2315. if (pQueueItem == NULL)
  2316. return CC_BAD_PARAM;
  2317. else
  2318. return CC_OK;
  2319. }
  2320. HRESULT EnqueueRequest( PCALL_QUEUE *ppQueueHead,
  2321. CC_HCALL hEnqueuedCall)
  2322. {
  2323. PCALL_QUEUE pQueueItem;
  2324. ASSERT(ppQueueHead != NULL);
  2325. ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
  2326. // Make sure we're not enqueuing a duplicate request
  2327. pQueueItem = *ppQueueHead;
  2328. while (pQueueItem != NULL) {
  2329. if (pQueueItem->hCall == hEnqueuedCall)
  2330. return CC_OK;
  2331. pQueueItem = pQueueItem->pNext;
  2332. }
  2333. pQueueItem = (PCALL_QUEUE)Malloc(sizeof(CALL_QUEUE));
  2334. if (pQueueItem == NULL)
  2335. return CC_NO_MEMORY;
  2336. pQueueItem->hCall = hEnqueuedCall;
  2337. pQueueItem->pPrev = NULL;
  2338. pQueueItem->pNext = *ppQueueHead;
  2339. if (*ppQueueHead != NULL)
  2340. (*ppQueueHead)->pPrev = pQueueItem;
  2341. *ppQueueHead = pQueueItem;
  2342. return CC_OK;
  2343. }
  2344. HRESULT DequeueRequest( PCALL_QUEUE *ppQueueHead,
  2345. PCC_HCALL phEnqueuedCall)
  2346. {
  2347. PCALL_QUEUE pQueueItem;
  2348. ASSERT(ppQueueHead != NULL);
  2349. if (phEnqueuedCall != NULL)
  2350. *phEnqueuedCall = CC_INVALID_HANDLE;
  2351. if (*ppQueueHead == NULL)
  2352. return CC_BAD_PARAM;
  2353. pQueueItem = *ppQueueHead;
  2354. *ppQueueHead = (*ppQueueHead)->pNext;
  2355. if (*ppQueueHead != NULL)
  2356. (*ppQueueHead)->pPrev = NULL;
  2357. if (phEnqueuedCall != NULL)
  2358. *phEnqueuedCall = pQueueItem->hCall;
  2359. Free(pQueueItem);
  2360. return CC_OK;
  2361. }
  2362. HRESULT DequeueSpecificRequest( PCALL_QUEUE *ppQueueHead,
  2363. CC_HCALL hEnqueuedCall)
  2364. {
  2365. PCALL_QUEUE pQueueItem;
  2366. ASSERT(ppQueueHead != NULL);
  2367. ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
  2368. pQueueItem = *ppQueueHead;
  2369. while (pQueueItem != NULL)
  2370. if (pQueueItem->hCall == hEnqueuedCall)
  2371. break;
  2372. else
  2373. pQueueItem = pQueueItem->pNext;
  2374. if (pQueueItem == NULL)
  2375. return CC_BAD_PARAM;
  2376. if (pQueueItem->pNext != NULL)
  2377. pQueueItem->pNext->pPrev = pQueueItem->pPrev;
  2378. if (pQueueItem->pPrev == NULL)
  2379. *ppQueueHead = pQueueItem->pNext;
  2380. else
  2381. pQueueItem->pPrev->pNext = pQueueItem->pNext;
  2382. Free(pQueueItem);
  2383. return CC_OK;
  2384. }