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.

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