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.

1089 lines
26 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/callman.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.69.1.1 $
  14. * $Date: 23 Jun 1997 15:58:00 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable: 4115 4201 4214)
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #pragma warning ( default: 4115 4201 4214)
  31. #include "incommon.h"
  32. #include "callcont.h"
  33. #include "q931.h"
  34. #include "ccmain.h"
  35. #include "h245man.h"
  36. #include "confman.h"
  37. #include "callman.h"
  38. #include "ccutils.h"
  39. #include "callman2.h"
  40. static BOOL bCallInited = FALSE;
  41. #define HASH_TABLE_SIZE 11
  42. static struct {
  43. PCALL pHead[HASH_TABLE_SIZE];
  44. LOCK Lock;
  45. } CallTable;
  46. static struct {
  47. CC_HCALL hCall;
  48. LOCK Lock;
  49. } CallHandle;
  50. HRESULT _LockCallAndConferenceMarkedForDeletion(
  51. CC_HCALL hCall,
  52. PPCALL ppCall,
  53. PPCONFERENCE ppConference);
  54. HRESULT InitCallManager()
  55. {
  56. int i;
  57. ASSERT(bCallInited == FALSE);
  58. for (i = 0; i < HASH_TABLE_SIZE; i++)
  59. CallTable.pHead[i] = NULL;
  60. InitializeLock(&CallTable.Lock);
  61. CallHandle.hCall = CC_INVALID_HANDLE + 1;
  62. InitializeLock(&CallHandle.Lock);
  63. bCallInited = TRUE;
  64. return CC_OK;
  65. }
  66. HRESULT DeInitCallManager()
  67. {
  68. HRESULT status;
  69. HRESULT SaveStatus;
  70. int i;
  71. PCALL pCall;
  72. PCALL pNextCall;
  73. H245_INST_T H245Instance;
  74. if (bCallInited == FALSE)
  75. return CC_OK;
  76. SaveStatus = CC_OK;
  77. for (i = 0; i < HASH_TABLE_SIZE; i++) {
  78. pCall = CallTable.pHead[i];
  79. while (pCall != NULL) {
  80. AcquireLock(&pCall->Lock);
  81. pNextCall = pCall->pNextInTable;
  82. H245Instance = pCall->H245Instance;
  83. FreeCall(pCall);
  84. if (H245Instance != H245_INVALID_ID) {
  85. status = H245ShutDown(H245Instance);
  86. if (status != H245_ERROR_OK)
  87. SaveStatus = status;
  88. }
  89. pCall = pNextCall;
  90. }
  91. }
  92. DeleteLock(&CallHandle.Lock);
  93. DeleteLock(&CallTable.Lock);
  94. bCallInited = FALSE;
  95. return SaveStatus;
  96. }
  97. #define _Hash(hCall) ((hCall) % HASH_TABLE_SIZE)
  98. HRESULT _AddCallToTable( PCALL pCall)
  99. {
  100. int index;
  101. ASSERT(pCall != NULL);
  102. ASSERT(pCall->hCall != CC_INVALID_HANDLE);
  103. ASSERT(pCall->bInTable == FALSE);
  104. AcquireLock(&CallTable.Lock);
  105. index = _Hash(pCall->hCall);
  106. pCall->pNextInTable = CallTable.pHead[index];
  107. pCall->pPrevInTable = NULL;
  108. if (CallTable.pHead[index] != NULL)
  109. CallTable.pHead[index]->pPrevInTable = pCall;
  110. CallTable.pHead[index] = pCall;
  111. pCall->bInTable = TRUE;
  112. RelinquishLock(&CallTable.Lock);
  113. return CC_OK;
  114. }
  115. HRESULT _RemoveCallFromTable( PCALL pCall)
  116. {
  117. CC_HCALL hCall;
  118. int index;
  119. BOOL bTimedOut;
  120. ASSERT(pCall != NULL);
  121. ASSERT(pCall->bInTable == TRUE);
  122. // Caller must have a lock on the call object;
  123. // in order to avoid deadlock, we must:
  124. // 1. unlock the Call object,
  125. // 2. lock the CallTable,
  126. // 3. locate the call object in the CallTable (note that
  127. // after step 2, the call object may be deleted from the
  128. // CallTable by another thread),
  129. // 4. lock the Call object (someone else may have the lock)
  130. // 5. remove the call object from the CallTable,
  131. // 6. unlock the CallTable
  132. //
  133. // The caller can now safely unlock and destroy the call object,
  134. // since no other thread will be able to find the object (its been
  135. // removed from the CallTable), and therefore no other thread will
  136. // be able to lock it.
  137. // Save the call handle; its the only way to look up
  138. // the call object in the CallTable. Note that we
  139. // can't use pCall to find the call object, since
  140. // pCall may be free'd up, and another call object
  141. // allocated at the same address
  142. hCall = pCall->hCall;
  143. // step 1
  144. RelinquishLock(&pCall->Lock);
  145. step2:
  146. // step 2
  147. AcquireLock(&CallTable.Lock);
  148. index = _Hash(hCall);
  149. // step 3
  150. pCall = CallTable.pHead[index];
  151. while ((pCall != NULL) && (pCall->hCall != hCall))
  152. pCall = pCall->pNextInTable;
  153. if (pCall != NULL) {
  154. // step 4
  155. AcquireTimedLock(&pCall->Lock,10,&bTimedOut);
  156. if (bTimedOut) {
  157. RelinquishLock(&CallTable.Lock);
  158. Sleep(0);
  159. goto step2;
  160. }
  161. // step 5
  162. if (pCall->pPrevInTable == NULL)
  163. CallTable.pHead[index] = pCall->pNextInTable;
  164. else
  165. pCall->pPrevInTable->pNextInTable = pCall->pNextInTable;
  166. if (pCall->pNextInTable != NULL)
  167. pCall->pNextInTable->pPrevInTable = pCall->pPrevInTable;
  168. pCall->pNextInTable = NULL;
  169. pCall->pPrevInTable = NULL;
  170. pCall->bInTable = FALSE;
  171. }
  172. // step 6
  173. RelinquishLock(&CallTable.Lock);
  174. if (pCall == NULL)
  175. return CC_BAD_PARAM;
  176. else
  177. return CC_OK;
  178. }
  179. HRESULT _MakeCallHandle( PCC_HCALL phCall)
  180. {
  181. AcquireLock(&CallHandle.Lock);
  182. *phCall = CallHandle.hCall++;
  183. RelinquishLock(&CallHandle.Lock);
  184. return CC_OK;
  185. }
  186. HRESULT AllocAndLockCall( PCC_HCALL phCall,
  187. CC_HCONFERENCE hConference,
  188. HQ931CALL hQ931Call,
  189. HQ931CALL hQ931CallInvitor,
  190. PCC_ALIASNAMES pLocalAliasNames,
  191. PCC_ALIASNAMES pPeerAliasNames,
  192. PCC_ALIASNAMES pPeerExtraAliasNames,
  193. PCC_ALIASITEM pPeerExtension,
  194. PCC_NONSTANDARDDATA pLocalNonStandardData,
  195. PCC_NONSTANDARDDATA pPeerNonStandardData,
  196. PWSTR pszLocalDisplay,
  197. PWSTR pszPeerDisplay,
  198. PCC_VENDORINFO pPeerVendorInfo,
  199. PCC_ADDR pQ931LocalConnectAddr,
  200. PCC_ADDR pQ931PeerConnectAddr,
  201. PCC_ADDR pQ931DestinationAddr,
  202. PCC_ADDR pSourceCallSignalAddr,
  203. CALLTYPE CallType,
  204. BOOL bCallerIsMC,
  205. DWORD dwUserToken,
  206. CALLSTATE InitialCallState,
  207. DWORD dwBandwidth,
  208. PCC_CONFERENCEID pConferenceID,
  209. PPCALL ppCall)
  210. {
  211. HRESULT status;
  212. ASSERT(bCallInited == TRUE);
  213. // all parameters should have been validated by the caller
  214. ASSERT(phCall != NULL);
  215. ASSERT(ppCall != NULL);
  216. ASSERT(pConferenceID != NULL);
  217. // set phCall now, in case we encounter an error
  218. *phCall = CC_INVALID_HANDLE;
  219. *ppCall = (PCALL)Malloc(sizeof(CALL));
  220. if (*ppCall == NULL)
  221. return CC_NO_MEMORY;
  222. memset(*ppCall, 0, sizeof(CALL));
  223. (*ppCall)->bInTable = FALSE;
  224. (*ppCall)->hConference = hConference;
  225. (*ppCall)->hQ931Call = hQ931Call;
  226. (*ppCall)->hQ931CallInvitor = hQ931CallInvitor;
  227. (*ppCall)->pPeerParticipantInfo = NULL;
  228. (*ppCall)->bMarkedForDeletion = FALSE;
  229. (*ppCall)->H245Instance = H245_INVALID_ID;
  230. (*ppCall)->dwH245PhysicalID = 0;
  231. (*ppCall)->dwUserToken = dwUserToken;
  232. (*ppCall)->pLocalNonStandardData = NULL;
  233. (*ppCall)->pPeerNonStandardData = NULL;
  234. (*ppCall)->pQ931LocalConnectAddr = NULL;
  235. (*ppCall)->pQ931PeerConnectAddr = NULL;
  236. (*ppCall)->pQ931DestinationAddr = NULL;
  237. (*ppCall)->pszLocalDisplay = NULL;
  238. (*ppCall)->pszPeerDisplay = NULL;
  239. (*ppCall)->pPeerVendorInfo = NULL;
  240. (*ppCall)->pLocalAliasNames = NULL;
  241. (*ppCall)->pPeerAliasNames = NULL;
  242. (*ppCall)->pPeerExtraAliasNames = NULL;
  243. (*ppCall)->pPeerExtension = NULL;
  244. (*ppCall)->OutgoingTermCapState = NEED_TO_SEND_TERMCAP;
  245. (*ppCall)->IncomingTermCapState = AWAITING_TERMCAP;
  246. (*ppCall)->MasterSlaveState = MASTER_SLAVE_NOT_STARTED;
  247. (*ppCall)->pPeerH245TermCapList = NULL;
  248. (*ppCall)->pPeerH245H2250MuxCapability = NULL;
  249. (*ppCall)->pPeerH245TermCapDescriptors = NULL;
  250. (*ppCall)->CallState = InitialCallState;
  251. (*ppCall)->dwBandwidth = dwBandwidth;
  252. (*ppCall)->ConferenceID = *pConferenceID;
  253. (*ppCall)->CallType = CallType;
  254. (*ppCall)->bCallerIsMC = bCallerIsMC;
  255. (*ppCall)->bLinkEstablished = FALSE;
  256. (*ppCall)->pNext = NULL;
  257. (*ppCall)->pPrev = NULL;
  258. (*ppCall)->pNextInTable = NULL;
  259. (*ppCall)->pPrevInTable = NULL;
  260. InitializeLock(&(*ppCall)->Lock);
  261. AcquireLock(&(*ppCall)->Lock);
  262. status = _MakeCallHandle(&(*ppCall)->hCall);
  263. if (status != CC_OK) {
  264. FreeCall(*ppCall);
  265. return status;
  266. }
  267. // make a local copy of the local non-standard data, if supplied
  268. status = CopyNonStandardData(&(*ppCall)->pLocalNonStandardData,
  269. pLocalNonStandardData);
  270. if (status != CC_OK) {
  271. FreeCall(*ppCall);
  272. return status;
  273. }
  274. // make a local copy of the peer's non-standard data, if supplied
  275. status = CopyNonStandardData(&(*ppCall)->pPeerNonStandardData,
  276. pPeerNonStandardData);
  277. if (status != CC_OK) {
  278. FreeCall(*ppCall);
  279. return status;
  280. }
  281. // make a copy of the local connect address, if supplied
  282. if (pQ931LocalConnectAddr != NULL) {
  283. (*ppCall)->pQ931LocalConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  284. if ((*ppCall)->pQ931LocalConnectAddr == NULL) {
  285. FreeCall(*ppCall);
  286. return CC_NO_MEMORY;
  287. }
  288. *(*ppCall)->pQ931LocalConnectAddr = *pQ931LocalConnectAddr;
  289. }
  290. // make a copy of the peer's connect address, if supplied
  291. if (pQ931PeerConnectAddr != NULL) {
  292. (*ppCall)->pQ931PeerConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  293. if ((*ppCall)->pQ931PeerConnectAddr == NULL) {
  294. FreeCall(*ppCall);
  295. return CC_NO_MEMORY;
  296. }
  297. *(*ppCall)->pQ931PeerConnectAddr = *pQ931PeerConnectAddr;
  298. }
  299. // make a copy of the destination address, if supplied
  300. if (pQ931DestinationAddr != NULL) {
  301. (*ppCall)->pQ931DestinationAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  302. if ((*ppCall)->pQ931DestinationAddr == NULL) {
  303. FreeCall(*ppCall);
  304. return CC_NO_MEMORY;
  305. }
  306. *(*ppCall)->pQ931DestinationAddr = *pQ931DestinationAddr;
  307. }
  308. // make a copy of the source call signal address, if supplied
  309. if (pSourceCallSignalAddr != NULL) {
  310. (*ppCall)->pSourceCallSignalAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  311. if ((*ppCall)->pSourceCallSignalAddr == NULL) {
  312. FreeCall(*ppCall);
  313. return CC_NO_MEMORY;
  314. }
  315. *(*ppCall)->pSourceCallSignalAddr = *pSourceCallSignalAddr;
  316. }
  317. // make a local copy of the local alias names
  318. status = Q931CopyAliasNames(&((*ppCall)->pLocalAliasNames), pLocalAliasNames);
  319. if (status != CS_OK) {
  320. FreeCall(*ppCall);
  321. return status;
  322. }
  323. // make a local copy of the peer alias names
  324. status = Q931CopyAliasNames(&((*ppCall)->pPeerAliasNames), pPeerAliasNames);
  325. if (status != CS_OK) {
  326. FreeCall(*ppCall);
  327. return status;
  328. }
  329. // make a local copy of the peer extra alias names
  330. status = Q931CopyAliasNames(&((*ppCall)->pPeerExtraAliasNames),
  331. pPeerExtraAliasNames);
  332. if (status != CS_OK) {
  333. FreeCall(*ppCall);
  334. return status;
  335. }
  336. // make a local copy of the peer extension
  337. status = Q931CopyAliasItem(&((*ppCall)->pPeerExtension),
  338. pPeerExtension);
  339. if (status != CS_OK) {
  340. FreeCall(*ppCall);
  341. return status;
  342. }
  343. status = CopyDisplay(&(*ppCall)->pszLocalDisplay, pszLocalDisplay);
  344. if (status != CC_OK) {
  345. FreeCall(*ppCall);
  346. return status;
  347. }
  348. status = CopyDisplay(&(*ppCall)->pszPeerDisplay, pszPeerDisplay);
  349. if (status != CC_OK) {
  350. FreeCall(*ppCall);
  351. return status;
  352. }
  353. status = CopyVendorInfo(&(*ppCall)->pPeerVendorInfo, pPeerVendorInfo);
  354. if (status != CC_OK) {
  355. FreeCall(*ppCall);
  356. return status;
  357. }
  358. *phCall = (*ppCall)->hCall;
  359. // add the Call to the Call table
  360. status = _AddCallToTable(*ppCall);
  361. if (status != CC_OK)
  362. FreeCall(*ppCall);
  363. return status;
  364. }
  365. // Caller must have a lock on the Call object
  366. HRESULT FreeCall( PCALL pCall)
  367. {
  368. HRESULT status;
  369. CC_HCALL hCall;
  370. PCONFERENCE pConference;
  371. ASSERT(pCall != NULL);
  372. #ifdef GATEKEEPER
  373. if (pCall->GkiCall.uGkiCallState != 0)
  374. GkiCloseCall(&pCall->GkiCall);
  375. #endif // GATEKEEPER
  376. // caller must have a lock on the Call object,
  377. // so there's no need to re-lock it
  378. hCall = pCall->hCall;
  379. if (pCall->hConference != CC_INVALID_HANDLE) {
  380. UnlockCall(pCall);
  381. status = _LockCallAndConferenceMarkedForDeletion(hCall, &pCall, &pConference);
  382. if (status != CC_OK)
  383. return status;
  384. }
  385. if (pCall->bInTable == TRUE)
  386. if (_RemoveCallFromTable(pCall) == CC_BAD_PARAM)
  387. // the Call object was deleted by another thread,
  388. // so just return CC_OK
  389. return CC_OK;
  390. if (pCall->pPeerParticipantInfo != NULL) {
  391. if (pCall->CallType == VIRTUAL_CALL)
  392. FreePeerParticipantInfo(NULL, pCall->pPeerParticipantInfo);
  393. else
  394. FreePeerParticipantInfo(pConference, pCall->pPeerParticipantInfo);
  395. }
  396. // If the call object is associated with a conference object, deassociate it.
  397. if (pCall->hConference != CC_INVALID_HANDLE) {
  398. RemoveCallFromConference(pCall, pConference);
  399. UnlockConference(pConference);
  400. }
  401. if (pCall->pLocalNonStandardData != NULL)
  402. FreeNonStandardData(pCall->pLocalNonStandardData);
  403. if (pCall->pPeerNonStandardData != NULL)
  404. FreeNonStandardData(pCall->pPeerNonStandardData);
  405. if (pCall->pQ931LocalConnectAddr != NULL)
  406. Free(pCall->pQ931LocalConnectAddr);
  407. if (pCall->pQ931PeerConnectAddr != NULL)
  408. Free(pCall->pQ931PeerConnectAddr);
  409. if (pCall->pQ931DestinationAddr != NULL)
  410. Free(pCall->pQ931DestinationAddr);
  411. if (pCall->pSourceCallSignalAddr != NULL)
  412. Free(pCall->pSourceCallSignalAddr);
  413. if (pCall->pPeerH245TermCapList != NULL)
  414. DestroyH245TermCapList(&(pCall->pPeerH245TermCapList));
  415. if (pCall->pPeerH245H2250MuxCapability != NULL)
  416. DestroyH245TermCap(&(pCall->pPeerH245H2250MuxCapability));
  417. if (pCall->pPeerH245TermCapDescriptors != NULL)
  418. DestroyH245TermCapDescriptors(&(pCall->pPeerH245TermCapDescriptors));
  419. if (pCall->pLocalAliasNames != NULL)
  420. Q931FreeAliasNames(pCall->pLocalAliasNames);
  421. if (pCall->pPeerAliasNames != NULL)
  422. Q931FreeAliasNames(pCall->pPeerAliasNames);
  423. if (pCall->pPeerExtraAliasNames != NULL)
  424. Q931FreeAliasNames(pCall->pPeerExtraAliasNames);
  425. if (pCall->pPeerExtension != NULL)
  426. Q931FreeAliasItem(pCall->pPeerExtension);
  427. if (pCall->pszLocalDisplay != NULL)
  428. FreeDisplay(pCall->pszLocalDisplay);
  429. if (pCall->pszPeerDisplay != NULL)
  430. FreeDisplay(pCall->pszPeerDisplay);
  431. if (pCall->pPeerVendorInfo != NULL)
  432. FreeVendorInfo(pCall->pPeerVendorInfo);
  433. #ifdef GATEKEEPER
  434. if (pCall->GkiCall.uGkiCallState != 0)
  435. GkiFreeCall(&pCall->GkiCall);
  436. #endif // GATEKEEPER
  437. // Since the call object has been removed from the CallTable,
  438. // no other thread will be able to find the call object and obtain
  439. // a lock, so its safe to unlock the call object and delete it here
  440. RelinquishLock(&pCall->Lock);
  441. DeleteLock(&pCall->Lock);
  442. Free(pCall);
  443. return CC_OK;
  444. }
  445. HRESULT _LockQ931CallMarkedForDeletion(
  446. CC_HCALL hCall,
  447. HQ931CALL hQ931Call,
  448. PPCALL ppCall)
  449. {
  450. int index;
  451. BOOL bTimedOut;
  452. // If hCall != CC_INVALID_HANDLE, the search is based on hCall;
  453. // otherwise, the search is based on hQ931Call
  454. ASSERT(ppCall != NULL);
  455. step1:
  456. AcquireLock(&CallTable.Lock);
  457. if (hCall != CC_INVALID_HANDLE) {
  458. index = _Hash(hCall);
  459. *ppCall = CallTable.pHead[index];
  460. while ((*ppCall != NULL) && ((*ppCall)->hCall != hCall))
  461. *ppCall = (*ppCall)->pNextInTable;
  462. } else {
  463. // Perform an exhaustive search based on hQ931Call
  464. for (index = 0; index < HASH_TABLE_SIZE; index++) {
  465. *ppCall = CallTable.pHead[index];
  466. while ((*ppCall != NULL) && ((*ppCall)->hQ931Call != hQ931Call))
  467. *ppCall = (*ppCall)->pNextInTable;
  468. if (*ppCall != NULL)
  469. break;
  470. }
  471. }
  472. if (*ppCall != NULL) {
  473. AcquireTimedLock(&(*ppCall)->Lock,10,&bTimedOut);
  474. if (bTimedOut) {
  475. RelinquishLock(&CallTable.Lock);
  476. Sleep(0);
  477. goto step1;
  478. }
  479. }
  480. RelinquishLock(&CallTable.Lock);
  481. if (*ppCall == NULL)
  482. return CC_BAD_PARAM;
  483. else
  484. return CC_OK;
  485. }
  486. HRESULT LockQ931Call( CC_HCALL hCall,
  487. HQ931CALL hQ931Call,
  488. PPCALL ppCall)
  489. {
  490. HRESULT status;
  491. status = _LockQ931CallMarkedForDeletion(hCall, hQ931Call, ppCall);
  492. if (status != CC_OK)
  493. return status;
  494. if ((*ppCall)->bMarkedForDeletion) {
  495. UnlockCall(*ppCall);
  496. return CC_BAD_PARAM;
  497. }
  498. return CC_OK;
  499. }
  500. HRESULT LockCall( CC_HCALL hCall,
  501. PPCALL ppCall)
  502. {
  503. ASSERT(hCall != CC_INVALID_HANDLE);
  504. ASSERT(ppCall != NULL);
  505. return LockQ931Call(hCall, // Call Control call handle (used in this call)
  506. 0, // Q931 call handle (ignored in this call)
  507. ppCall);
  508. }
  509. HRESULT _LockCallMarkedForDeletion( CC_HCALL hCall,
  510. PPCALL ppCall)
  511. {
  512. ASSERT(hCall != CC_INVALID_HANDLE);
  513. ASSERT(ppCall != NULL);
  514. return _LockQ931CallMarkedForDeletion(hCall, // Call Control call handle (used in this call)
  515. 0, // Q931 call handle (ignored in this call)
  516. ppCall);
  517. }
  518. HRESULT LockCallAndConference( CC_HCALL hCall,
  519. PPCALL ppCall,
  520. PPCONFERENCE ppConference)
  521. {
  522. HRESULT status;
  523. CC_HCONFERENCE hConference;
  524. ASSERT(hCall != CC_INVALID_HANDLE);
  525. ASSERT(ppCall != NULL);
  526. ASSERT(ppConference != NULL);
  527. status = LockCall(hCall, ppCall);
  528. if (status != CC_OK)
  529. return status;
  530. if ((*ppCall)->hConference == CC_INVALID_HANDLE) {
  531. UnlockCall(*ppCall);
  532. return CC_BAD_PARAM;
  533. }
  534. hConference = (*ppCall)->hConference;
  535. UnlockCall(*ppCall);
  536. status = LockConference(hConference, ppConference);
  537. if (status != CC_OK)
  538. return status;
  539. status = LockCall(hCall, ppCall);
  540. if (status != CC_OK) {
  541. UnlockConference(*ppConference);
  542. return status;
  543. }
  544. return CC_OK;
  545. }
  546. HRESULT _LockCallAndConferenceMarkedForDeletion(
  547. CC_HCALL hCall,
  548. PPCALL ppCall,
  549. PPCONFERENCE ppConference)
  550. {
  551. HRESULT status;
  552. CC_HCONFERENCE hConference;
  553. ASSERT(hCall != CC_INVALID_HANDLE);
  554. ASSERT(ppCall != NULL);
  555. ASSERT(ppConference != NULL);
  556. status = _LockCallMarkedForDeletion(hCall, ppCall);
  557. if (status != CC_OK)
  558. return status;
  559. if ((*ppCall)->hConference == CC_INVALID_HANDLE) {
  560. UnlockCall(*ppCall);
  561. return CC_BAD_PARAM;
  562. }
  563. hConference = (*ppCall)->hConference;
  564. UnlockCall(*ppCall);
  565. status = LockConference(hConference, ppConference);
  566. if (status != CC_OK)
  567. return status;
  568. status = _LockCallMarkedForDeletion(hCall, ppCall);
  569. if (status != CC_OK) {
  570. UnlockConference(*ppConference);
  571. return status;
  572. }
  573. return CC_OK;
  574. }
  575. HRESULT MarkCallForDeletion( PCALL pCall)
  576. {
  577. ASSERT(pCall != NULL);
  578. ASSERT(pCall->bMarkedForDeletion == FALSE);
  579. pCall->bMarkedForDeletion = TRUE;
  580. return CC_OK;
  581. }
  582. HRESULT ValidateCall( CC_HCALL hCall)
  583. {
  584. PCALL pCall;
  585. int index;
  586. ASSERT(hCall != CC_INVALID_HANDLE);
  587. AcquireLock(&CallTable.Lock);
  588. index = _Hash(hCall);
  589. pCall = CallTable.pHead[index];
  590. while ((pCall != NULL) && (pCall->hCall != hCall))
  591. pCall = pCall->pNextInTable;
  592. if (pCall != NULL)
  593. if (pCall->bMarkedForDeletion == TRUE)
  594. pCall = NULL;
  595. RelinquishLock(&CallTable.Lock);
  596. if (pCall == NULL)
  597. return CC_BAD_PARAM;
  598. else
  599. return CC_OK;
  600. }
  601. HRESULT ValidateCallMarkedForDeletion(
  602. CC_HCALL hCall)
  603. {
  604. PCALL pCall;
  605. int index;
  606. ASSERT(hCall != CC_INVALID_HANDLE);
  607. AcquireLock(&CallTable.Lock);
  608. index = _Hash(hCall);
  609. pCall = CallTable.pHead[index];
  610. while ((pCall != NULL) && (pCall->hCall != hCall))
  611. pCall = pCall->pNextInTable;
  612. RelinquishLock(&CallTable.Lock);
  613. if (pCall == NULL)
  614. return CC_BAD_PARAM;
  615. else
  616. return CC_OK;
  617. }
  618. HRESULT UnlockCall( PCALL pCall)
  619. {
  620. ASSERT(pCall != NULL);
  621. RelinquishLock(&pCall->Lock);
  622. return CC_OK;
  623. }
  624. HRESULT AddLocalNonStandardDataToCall(
  625. PCALL pCall,
  626. PCC_NONSTANDARDDATA pLocalNonStandardData)
  627. {
  628. HRESULT status;
  629. ASSERT(pCall != NULL);
  630. if (pCall->pLocalNonStandardData != NULL)
  631. FreeNonStandardData(pCall->pLocalNonStandardData);
  632. status = CopyNonStandardData(&pCall->pLocalNonStandardData, pLocalNonStandardData);
  633. return status;
  634. }
  635. HRESULT AddLocalDisplayToCall( PCALL pCall,
  636. PWSTR pszLocalDisplay)
  637. {
  638. HRESULT status;
  639. ASSERT(pCall != NULL);
  640. if (pCall->pszLocalDisplay != NULL)
  641. FreeDisplay(pCall->pszLocalDisplay);
  642. status = CopyDisplay(&pCall->pszLocalDisplay, pszLocalDisplay);
  643. return status;
  644. }
  645. HRESULT AllocatePeerParticipantInfo(PCONFERENCE pConference,
  646. PPARTICIPANTINFO *ppPeerParticipantInfo)
  647. {
  648. HRESULT status;
  649. H245_TERMINAL_LABEL_T H245TerminalLabel;
  650. ASSERT(ppPeerParticipantInfo != NULL);
  651. if (pConference == NULL) {
  652. H245TerminalLabel.mcuNumber = 0;
  653. H245TerminalLabel.terminalNumber = 0;
  654. } else {
  655. status = AllocateTerminalNumber(pConference, &H245TerminalLabel);
  656. if (status != CC_OK) {
  657. *ppPeerParticipantInfo = NULL;
  658. return status;
  659. }
  660. }
  661. *ppPeerParticipantInfo = (PPARTICIPANTINFO)Malloc(sizeof(PARTICIPANTINFO));
  662. if (*ppPeerParticipantInfo == NULL)
  663. return CC_NO_MEMORY;
  664. (*ppPeerParticipantInfo)->TerminalIDState = TERMINAL_ID_INVALID;
  665. (*ppPeerParticipantInfo)->ParticipantInfo.TerminalLabel.bMCUNumber = (BYTE)H245TerminalLabel.mcuNumber;
  666. (*ppPeerParticipantInfo)->ParticipantInfo.TerminalLabel.bTerminalNumber = (BYTE)H245TerminalLabel.terminalNumber;
  667. (*ppPeerParticipantInfo)->ParticipantInfo.TerminalID.pOctetString = NULL;
  668. (*ppPeerParticipantInfo)->ParticipantInfo.TerminalID.wOctetStringLength = 0;
  669. (*ppPeerParticipantInfo)->pEnqueuedRequestsForTerminalID = NULL;
  670. return CC_OK;
  671. }
  672. HRESULT FreePeerParticipantInfo( PCONFERENCE pConference,
  673. PPARTICIPANTINFO pPeerParticipantInfo)
  674. {
  675. HRESULT status = CC_OK;
  676. ASSERT(pPeerParticipantInfo != NULL);
  677. if (pConference != NULL)
  678. status = FreeTerminalNumber(pConference,
  679. pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
  680. while (DequeueRequest(&pPeerParticipantInfo->pEnqueuedRequestsForTerminalID, NULL) == CC_OK);
  681. if (pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString != NULL)
  682. Free(pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString);
  683. Free(pPeerParticipantInfo);
  684. return status;
  685. }
  686. #ifdef GATEKEEPER
  687. HRESULT LockGkiCallAndConference( HANDLE hGkiCall,
  688. PGKICALL * ppGkiCall,
  689. void * * ppConference,
  690. DWORD * phCall,
  691. DWORD * phConference)
  692. {
  693. unsigned int uIndex;
  694. PCALL pCall;
  695. PCONFERENCE pConference;
  696. CC_HCONFERENCE hConference;
  697. BOOL bTimedOut;
  698. ASSERT(hGkiCall != 0);
  699. ASSERT(ppGkiCall != NULL);
  700. ASSERT(ppConference != NULL);
  701. ASSERT(phCall != NULL);
  702. ASSERT(phConference != NULL);
  703. step1:
  704. AcquireLock(&CallTable.Lock);
  705. // Perform an exhaustive search based on hGkiCall
  706. for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex)
  707. {
  708. pCall = CallTable.pHead[uIndex];
  709. while (pCall)
  710. {
  711. if (pCall->GkiCall.hGkiCall == hGkiCall)
  712. {
  713. AcquireTimedLock(&pCall->Lock,10,&bTimedOut);
  714. if (bTimedOut) {
  715. RelinquishLock(&CallTable.Lock);
  716. Sleep(0);
  717. goto step1;
  718. }
  719. hConference = pCall->hConference;
  720. if (pCall->bMarkedForDeletion || hConference == CC_INVALID_HANDLE)
  721. {
  722. RelinquishLock(&pCall->Lock);
  723. RelinquishLock(&CallTable.Lock);
  724. return CC_BAD_PARAM;
  725. }
  726. RelinquishLock(&pCall->Lock);
  727. if (LockConference(hConference, &pConference) != CC_OK)
  728. {
  729. RelinquishLock(&CallTable.Lock);
  730. return CC_BAD_PARAM;
  731. }
  732. AcquireLock(&pCall->Lock);
  733. *ppGkiCall = &pCall->GkiCall;
  734. *ppConference = (void *)pConference;
  735. *phCall = pCall->hCall;
  736. *phConference = pCall->hConference;
  737. RelinquishLock(&CallTable.Lock);
  738. return NOERROR;
  739. }
  740. pCall = pCall->pNextInTable;
  741. } // while
  742. }
  743. RelinquishLock(&CallTable.Lock);
  744. return CC_BAD_PARAM;
  745. } // LockGkiCallAndConference()
  746. HRESULT UnlockGkiCallAndConference( PGKICALL pGkiCall,
  747. void * pConference,
  748. DWORD hCall,
  749. DWORD hConference)
  750. {
  751. if (ValidateConference(hConference) == CC_OK)
  752. UnlockConference((PCONFERENCE)pConference);
  753. if (ValidateCall(hCall) == CC_OK)
  754. UnlockCall(pGkiCall->pCall);
  755. return NOERROR;
  756. } // UnlockGkiCallAndConference()
  757. HRESULT LockGkiCall(HANDLE hGkiCall, PPGKICALL ppGkiCall)
  758. {
  759. unsigned int uIndex;
  760. PCALL pCall;
  761. BOOL bTimedOut;
  762. ASSERT(hGkiCall != 0);
  763. ASSERT(ppGkiCall != NULL);
  764. step1:
  765. AcquireLock(&CallTable.Lock);
  766. // Perform an exhaustive search based on hGkiCall
  767. for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex)
  768. {
  769. pCall = CallTable.pHead[uIndex];
  770. while (pCall)
  771. {
  772. if (pCall->GkiCall.hGkiCall == hGkiCall)
  773. {
  774. AcquireTimedLock(&pCall->Lock,10,&bTimedOut);
  775. if (bTimedOut) {
  776. RelinquishLock(&CallTable.Lock);
  777. Sleep(0);
  778. goto step1;
  779. }
  780. if (pCall->bMarkedForDeletion)
  781. {
  782. RelinquishLock(&pCall->Lock);
  783. *ppGkiCall = NULL;
  784. RelinquishLock(&CallTable.Lock);
  785. return CC_BAD_PARAM;
  786. }
  787. *ppGkiCall = &pCall->GkiCall;
  788. RelinquishLock(&CallTable.Lock);
  789. return NOERROR;
  790. }
  791. pCall = pCall->pNextInTable;
  792. } // while
  793. }
  794. *ppGkiCall = NULL;
  795. RelinquishLock(&CallTable.Lock);
  796. return CC_BAD_PARAM;
  797. } // LockGkiCall()
  798. HRESULT UnlockGkiCall(PGKICALL pGkiCall)
  799. {
  800. return UnlockCall(pGkiCall->pCall);
  801. } // UnlockGkiCall()
  802. HRESULT ApplyToAllCalls(PGKICALLFUN pGkiCallFun)
  803. {
  804. unsigned uIndex;
  805. PCALL pCall;
  806. DWORD hCall;
  807. PCONFERENCE pConference;
  808. DWORD hConference;
  809. HRESULT status;
  810. BOOL bTimedOut;
  811. step1:
  812. AcquireLock(&CallTable.Lock);
  813. // Apply pGkiCallFun to all calls in table
  814. for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex)
  815. {
  816. pCall = CallTable.pHead[uIndex];
  817. while (pCall)
  818. {
  819. AcquireTimedLock(&pCall->Lock,10,&bTimedOut);
  820. if (bTimedOut) {
  821. RelinquishLock(&CallTable.Lock);
  822. Sleep(0);
  823. goto step1;
  824. }
  825. hConference = pCall->hConference;
  826. if (pCall->bMarkedForDeletion || hConference == CC_INVALID_HANDLE)
  827. {
  828. RelinquishLock(&pCall->Lock);
  829. }
  830. else
  831. {
  832. RelinquishLock(&pCall->Lock);
  833. if (LockConference(hConference, &pConference) == CC_OK)
  834. {
  835. AcquireLock(&pCall->Lock);
  836. hCall = pCall->hCall;
  837. status = pGkiCallFun(&pCall->GkiCall, pConference);
  838. if (ValidateConference(hConference) == NOERROR)
  839. UnlockConference(pConference);
  840. if (ValidateCall(hCall) != NOERROR)
  841. {
  842. // Call was deleted
  843. RelinquishLock(&CallTable.Lock);
  844. if (status != NOERROR)
  845. return status;
  846. // Start all over again
  847. goto step1;
  848. }
  849. RelinquishLock(&pCall->Lock);
  850. if (status != NOERROR)
  851. {
  852. RelinquishLock(&CallTable.Lock);
  853. return status;
  854. }
  855. }
  856. }
  857. pCall = pCall->pNextInTable;
  858. } // while
  859. }
  860. RelinquishLock(&CallTable.Lock);
  861. return NOERROR;
  862. } // ApplyToAllCalls()
  863. #endif // GATEKEEPER