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.

338 lines
7.2 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/Hangman.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.16 $
  14. * $Date: 22 Jan 1997 14:55:52 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #include "precomp.h"
  26. #include "apierror.h"
  27. #include "incommon.h"
  28. #include "callcont.h"
  29. #include "q931.h"
  30. #include "ccmain.h"
  31. #include "ccutils.h"
  32. #include "hangman.h"
  33. static BOOL bHangupInited = FALSE;
  34. static struct {
  35. PHANGUP pHead;
  36. LOCK Lock;
  37. } HangupTable;
  38. static struct {
  39. HHANGUP hHangup;
  40. LOCK Lock;
  41. } HangupHandle;
  42. HRESULT InitHangupManager()
  43. {
  44. ASSERT(bHangupInited == FALSE);
  45. HangupTable.pHead = NULL;
  46. InitializeLock(&HangupTable.Lock);
  47. HangupHandle.hHangup = CC_INVALID_HANDLE + 1;
  48. InitializeLock(&HangupHandle.Lock);
  49. bHangupInited = TRUE;
  50. return CC_OK;
  51. }
  52. HRESULT DeInitHangupManager()
  53. {
  54. PHANGUP pHangup;
  55. PHANGUP pNextHangup;
  56. if (bHangupInited == FALSE)
  57. return CC_OK;
  58. pHangup = HangupTable.pHead;
  59. while (pHangup != NULL) {
  60. AcquireLock(&pHangup->Lock);
  61. pNextHangup = pHangup->pNextInTable;
  62. FreeHangup(pHangup);
  63. pHangup = pNextHangup;
  64. }
  65. DeleteLock(&HangupHandle.Lock);
  66. DeleteLock(&HangupTable.Lock);
  67. bHangupInited = FALSE;
  68. return CC_OK;
  69. }
  70. HRESULT _AddHangupToTable( PHANGUP pHangup)
  71. {
  72. ASSERT(pHangup != NULL);
  73. ASSERT(pHangup->hHangup != CC_INVALID_HANDLE);
  74. ASSERT(pHangup->bInTable == FALSE);
  75. AcquireLock(&HangupTable.Lock);
  76. pHangup->pNextInTable = HangupTable.pHead;
  77. pHangup->pPrevInTable = NULL;
  78. if (HangupTable.pHead != NULL)
  79. HangupTable.pHead->pPrevInTable = pHangup;
  80. HangupTable.pHead = pHangup;
  81. pHangup->bInTable = TRUE;
  82. RelinquishLock(&HangupTable.Lock);
  83. return CC_OK;
  84. }
  85. HRESULT _RemoveHangupFromTable( PHANGUP pHangup)
  86. {
  87. HHANGUP hHangup;
  88. BOOL bTimedOut;
  89. ASSERT(pHangup != NULL);
  90. ASSERT(pHangup->bInTable == TRUE);
  91. // Caller must have a lock on the hangup object;
  92. // in order to avoid deadlock, we must:
  93. // 1. unlock the hangup object,
  94. // 2. lock the HangupTable,
  95. // 3. locate the hangup object in the HangupTable (note that
  96. // after step 2, the hangup object may be deleted from the
  97. // HangupTable by another thread),
  98. // 4. lock the hangup object (someone else may have the lock)
  99. // 5. remove the hangup object from the HangupTable,
  100. // 6. unlock the HangupTable
  101. //
  102. // The caller can now safely unlock and destroy the hangup object,
  103. // since no other thread will be able to find the object (its been
  104. // removed from the HangupTable), and therefore no other thread will
  105. // be able to lock it.
  106. // Save the hangup handle; its the only way to look up
  107. // the hangup object in the HangupTable. Note that we
  108. // can't use pHangup to find the hangup object, since
  109. // pHangup may be free'd up, and another hangup object
  110. // allocated at the same address
  111. hHangup = pHangup->hHangup;
  112. // step 1
  113. RelinquishLock(&pHangup->Lock);
  114. step2:
  115. // step 2
  116. AcquireLock(&HangupTable.Lock);
  117. // step 3
  118. pHangup = HangupTable.pHead;
  119. while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
  120. pHangup = pHangup->pNextInTable;
  121. if (pHangup != NULL) {
  122. // step 4
  123. AcquireTimedLock(&pHangup->Lock,10,&bTimedOut);
  124. if (bTimedOut) {
  125. RelinquishLock(&HangupTable.Lock);
  126. Sleep(0);
  127. goto step2;
  128. }
  129. // step 5
  130. if (pHangup->pPrevInTable == NULL)
  131. HangupTable.pHead = pHangup->pNextInTable;
  132. else
  133. pHangup->pPrevInTable->pNextInTable = pHangup->pNextInTable;
  134. if (pHangup->pNextInTable != NULL)
  135. pHangup->pNextInTable->pPrevInTable = pHangup->pPrevInTable;
  136. pHangup->pNextInTable = NULL;
  137. pHangup->pPrevInTable = NULL;
  138. pHangup->bInTable = FALSE;
  139. }
  140. // step 6
  141. RelinquishLock(&HangupTable.Lock);
  142. if (pHangup == NULL)
  143. return CC_BAD_PARAM;
  144. else
  145. return CC_OK;
  146. }
  147. HRESULT _MakeHangupHandle( PHHANGUP phHangup)
  148. {
  149. AcquireLock(&HangupHandle.Lock);
  150. *phHangup = HangupHandle.hHangup++;
  151. RelinquishLock(&HangupHandle.Lock);
  152. return CC_OK;
  153. }
  154. HRESULT AllocAndLockHangup( PHHANGUP phHangup,
  155. CC_HCONFERENCE hConference,
  156. DWORD_PTR dwUserToken,
  157. PPHANGUP ppHangup)
  158. {
  159. HRESULT status;
  160. ASSERT(bHangupInited == TRUE);
  161. // all parameters should have been validated by the caller
  162. ASSERT(phHangup != NULL);
  163. ASSERT(hConference != CC_INVALID_HANDLE);
  164. ASSERT(ppHangup != NULL);
  165. // set phHangup now, in case we encounter an error
  166. *phHangup = CC_INVALID_HANDLE;
  167. *ppHangup = (PHANGUP)MemAlloc(sizeof(HANGUP));
  168. if (*ppHangup == NULL)
  169. return CC_NO_MEMORY;
  170. (*ppHangup)->bInTable = FALSE;
  171. status = _MakeHangupHandle(&(*ppHangup)->hHangup);
  172. if (status != CC_OK) {
  173. MemFree(*ppHangup);
  174. return status;
  175. }
  176. (*ppHangup)->hConference = hConference;
  177. (*ppHangup)->wNumCalls = 0;
  178. (*ppHangup)->dwUserToken = dwUserToken;
  179. (*ppHangup)->pNextInTable = NULL;
  180. (*ppHangup)->pPrevInTable = NULL;
  181. InitializeLock(&(*ppHangup)->Lock);
  182. AcquireLock(&(*ppHangup)->Lock);
  183. *phHangup = (*ppHangup)->hHangup;
  184. // add the Hangup to the Hangup table
  185. status = _AddHangupToTable(*ppHangup);
  186. if (status != CC_OK)
  187. FreeHangup(*ppHangup);
  188. return status;
  189. }
  190. // Caller must have a lock on the Hangup object
  191. HRESULT FreeHangup( PHANGUP pHangup)
  192. {
  193. HHANGUP hHangup;
  194. ASSERT(pHangup != NULL);
  195. // caller must have a lock on the Hangup object,
  196. // so there's no need to re-lock it
  197. hHangup = pHangup->hHangup;
  198. if (pHangup->bInTable == TRUE)
  199. if (_RemoveHangupFromTable(pHangup) == CC_BAD_PARAM)
  200. // the Hangup object was deleted by another thread,
  201. // so just return CC_OK
  202. return CC_OK;
  203. // Since the hangup object has been removed from the HangupTable,
  204. // no other thread will be able to find the hangup object and obtain
  205. // a lock, so its safe to unlock the hangup object and delete it here
  206. RelinquishLock(&pHangup->Lock);
  207. DeleteLock(&pHangup->Lock);
  208. MemFree(pHangup);
  209. return CC_OK;
  210. }
  211. HRESULT LockHangup( HHANGUP hHangup,
  212. PPHANGUP ppHangup)
  213. {
  214. BOOL bTimedOut;
  215. ASSERT(hHangup != CC_INVALID_HANDLE);
  216. ASSERT(ppHangup != NULL);
  217. step1:
  218. AcquireLock(&HangupTable.Lock);
  219. *ppHangup = HangupTable.pHead;
  220. while ((*ppHangup != NULL) && ((*ppHangup)->hHangup != hHangup))
  221. *ppHangup = (*ppHangup)->pNextInTable;
  222. if (*ppHangup != NULL) {
  223. AcquireTimedLock(&(*ppHangup)->Lock,10,&bTimedOut);
  224. if (bTimedOut) {
  225. RelinquishLock(&HangupTable.Lock);
  226. Sleep(0);
  227. goto step1;
  228. }
  229. }
  230. RelinquishLock(&HangupTable.Lock);
  231. if (*ppHangup == NULL)
  232. return CC_BAD_PARAM;
  233. else
  234. return CC_OK;
  235. }
  236. HRESULT ValidateHangup( HHANGUP hHangup)
  237. {
  238. PHANGUP pHangup;
  239. ASSERT(hHangup != CC_INVALID_HANDLE);
  240. AcquireLock(&HangupTable.Lock);
  241. pHangup = HangupTable.pHead;
  242. while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
  243. pHangup = pHangup->pNextInTable;
  244. RelinquishLock(&HangupTable.Lock);
  245. if (pHangup == NULL)
  246. return CC_BAD_PARAM;
  247. else
  248. return CC_OK;
  249. }
  250. HRESULT UnlockHangup( PHANGUP pHangup)
  251. {
  252. ASSERT(pHangup != NULL);
  253. RelinquishLock(&pHangup->Lock);
  254. return CC_OK;
  255. }
  256.