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.

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