Leaked source code of windows server 2003
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.

388 lines
8.8 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/Listman.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.22 $
  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 "listman.h"
  33. static BOOL bListenInited = FALSE;
  34. static struct {
  35. PLISTEN pHead;
  36. LOCK Lock;
  37. } ListenTable;
  38. static struct {
  39. CC_HLISTEN hListen;
  40. LOCK Lock;
  41. } ListenHandle;
  42. HRESULT InitListenManager()
  43. {
  44. ASSERT(bListenInited == FALSE);
  45. ListenTable.pHead = NULL;
  46. InitializeLock(&ListenTable.Lock);
  47. ListenHandle.hListen = CC_INVALID_HANDLE + 1;
  48. InitializeLock(&ListenHandle.Lock);
  49. bListenInited = TRUE;
  50. return CC_OK;
  51. }
  52. HRESULT DeInitListenManager()
  53. {
  54. PLISTEN pListen;
  55. PLISTEN pNextListen;
  56. if (bListenInited == FALSE)
  57. return CC_OK;
  58. pListen = ListenTable.pHead;
  59. while (pListen != NULL) {
  60. AcquireLock(&pListen->Lock);
  61. pNextListen = pListen->pNextInTable;
  62. FreeListen(pListen);
  63. pListen = pNextListen;
  64. }
  65. DeleteLock(&ListenHandle.Lock);
  66. DeleteLock(&ListenTable.Lock);
  67. bListenInited = FALSE;
  68. return CC_OK;
  69. }
  70. HRESULT _AddListenToTable( PLISTEN pListen)
  71. {
  72. ASSERT(pListen != NULL);
  73. ASSERT(pListen->hListen != CC_INVALID_HANDLE);
  74. ASSERT(pListen->bInTable == FALSE);
  75. AcquireLock(&ListenTable.Lock);
  76. pListen->pNextInTable = ListenTable.pHead;
  77. pListen->pPrevInTable = NULL;
  78. if (ListenTable.pHead != NULL)
  79. ListenTable.pHead->pPrevInTable = pListen;
  80. ListenTable.pHead = pListen;
  81. pListen->bInTable = TRUE;
  82. RelinquishLock(&ListenTable.Lock);
  83. return CC_OK;
  84. }
  85. HRESULT _RemoveListenFromTable( PLISTEN pListen)
  86. {
  87. CC_HLISTEN hListen;
  88. BOOL bTimedOut;
  89. ASSERT(pListen != NULL);
  90. ASSERT(pListen->bInTable == TRUE);
  91. // Caller must have a lock on the listen object;
  92. // in order to avoid deadlock, we must:
  93. // 1. unlock the listen object,
  94. // 2. lock the ListenTable,
  95. // 3. locate the listen object in the ListenTable (note that
  96. // after step 2, the listen object may be deleted from the
  97. // ListenTable by another thread),
  98. // 4. lock the listen object (someone else may have the lock)
  99. // 5. remove the listen object from the ListenTable,
  100. // 6. unlock the ListenTable
  101. //
  102. // The caller can now safely unlock and destroy the listen object,
  103. // since no other thread will be able to find the object (its been
  104. // removed from the ListenTable), and therefore no other thread will
  105. // be able to lock it.
  106. // Save the listen handle; its the only way to look up
  107. // the listen object in the ListenTable. Note that we
  108. // can't use pListen to find the listen object, since
  109. // pListen may be free'd up, and another listen object
  110. // allocated at the same address
  111. hListen = pListen->hListen;
  112. // step 1
  113. RelinquishLock(&pListen->Lock);
  114. step2:
  115. // step 2
  116. AcquireLock(&ListenTable.Lock);
  117. // step 3
  118. pListen = ListenTable.pHead;
  119. while ((pListen != NULL) && (pListen->hListen != hListen))
  120. pListen = pListen->pNextInTable;
  121. if (pListen != NULL) {
  122. // step 4
  123. AcquireTimedLock(&pListen->Lock,10,&bTimedOut);
  124. if (bTimedOut) {
  125. RelinquishLock(&ListenTable.Lock);
  126. Sleep(0);
  127. goto step2;
  128. }
  129. // step 5
  130. if (pListen->pPrevInTable == NULL)
  131. ListenTable.pHead = pListen->pNextInTable;
  132. else
  133. pListen->pPrevInTable->pNextInTable = pListen->pNextInTable;
  134. if (pListen->pNextInTable != NULL)
  135. pListen->pNextInTable->pPrevInTable = pListen->pPrevInTable;
  136. pListen->pNextInTable = NULL;
  137. pListen->pPrevInTable = NULL;
  138. pListen->bInTable = FALSE;
  139. }
  140. // step 6
  141. RelinquishLock(&ListenTable.Lock);
  142. if (pListen == NULL)
  143. return CC_BAD_PARAM;
  144. else
  145. return CC_OK;
  146. }
  147. HRESULT _MakeListenHandle( PCC_HLISTEN phListen)
  148. {
  149. AcquireLock(&ListenHandle.Lock);
  150. *phListen = ListenHandle.hListen++;
  151. RelinquishLock(&ListenHandle.Lock);
  152. return CC_OK;
  153. }
  154. HRESULT AllocAndLockListen( PCC_HLISTEN phListen,
  155. PCC_ADDR pListenAddr,
  156. HQ931LISTEN hQ931Listen,
  157. PCC_ALIASNAMES pLocalAliasNames,
  158. DWORD_PTR dwListenToken,
  159. CC_LISTEN_CALLBACK ListenCallback,
  160. PPLISTEN ppListen)
  161. {
  162. HRESULT status;
  163. ASSERT(bListenInited == TRUE);
  164. // all parameters should have been validated by the caller
  165. ASSERT(phListen != NULL);
  166. ASSERT(pListenAddr != NULL);
  167. ASSERT(ListenCallback != NULL);
  168. ASSERT(ppListen != NULL);
  169. // set phListen now, in case we encounter an error
  170. *phListen = CC_INVALID_HANDLE;
  171. *ppListen = (PLISTEN)MemAlloc(sizeof(LISTEN));
  172. if (*ppListen == NULL)
  173. return CC_NO_MEMORY;
  174. (*ppListen)->bInTable = FALSE;
  175. status = _MakeListenHandle(&(*ppListen)->hListen);
  176. if (status != CC_OK) {
  177. MemFree(*ppListen);
  178. return status;
  179. }
  180. // make a local copy of the ListenAddr
  181. (*ppListen)->ListenAddr = *pListenAddr;
  182. (*ppListen)->hQ931Listen = hQ931Listen;
  183. (*ppListen)->dwListenToken = dwListenToken;
  184. (*ppListen)->pLocalAliasNames = NULL;
  185. (*ppListen)->ListenCallback = ListenCallback;
  186. (*ppListen)->pNextInTable = NULL;
  187. (*ppListen)->pPrevInTable = NULL;
  188. (*ppListen)->pLocalAliasNames = NULL;
  189. InitializeLock(&(*ppListen)->Lock);
  190. AcquireLock(&(*ppListen)->Lock);
  191. *phListen = (*ppListen)->hListen;
  192. // make a local copy of the local alias names
  193. status = Q931CopyAliasNames(&(*ppListen)->pLocalAliasNames, pLocalAliasNames);
  194. if (status != CS_OK) {
  195. FreeListen(*ppListen);
  196. *phListen = CC_INVALID_HANDLE;
  197. return status;
  198. }
  199. // add the Listen to the Listen table
  200. status = _AddListenToTable(*ppListen);
  201. if (status != CC_OK)
  202. FreeListen(*ppListen);
  203. return status;
  204. }
  205. // Caller must have a lock on the Listen object
  206. HRESULT FreeListen( PLISTEN pListen)
  207. {
  208. CC_HLISTEN hListen;
  209. ASSERT(pListen != NULL);
  210. // caller must have a lock on the Listen object,
  211. // so there's no need to re-lock it
  212. hListen = pListen->hListen;
  213. if (pListen->bInTable == TRUE)
  214. if (_RemoveListenFromTable(pListen) == CC_BAD_PARAM)
  215. // the Listen object was deleted by another thread,
  216. // so just return CC_OK
  217. return CC_OK;
  218. if (pListen->pLocalAliasNames != NULL)
  219. Q931FreeAliasNames(pListen->pLocalAliasNames);
  220. // Since the listen object has been removed from the ListenTable,
  221. // no other thread will be able to find the listen object and obtain
  222. // a lock, so its safe to unlock the listen object and delete it here
  223. RelinquishLock(&pListen->Lock);
  224. DeleteLock(&pListen->Lock);
  225. MemFree(pListen);
  226. return CC_OK;
  227. }
  228. HRESULT LockListen( CC_HLISTEN hListen,
  229. PPLISTEN ppListen)
  230. {
  231. BOOL bTimedOut;
  232. ASSERT(hListen != CC_INVALID_HANDLE);
  233. ASSERT(ppListen != NULL);
  234. step1:
  235. AcquireLock(&ListenTable.Lock);
  236. *ppListen = ListenTable.pHead;
  237. while ((*ppListen != NULL) && ((*ppListen)->hListen != hListen))
  238. *ppListen = (*ppListen)->pNextInTable;
  239. if (*ppListen != NULL) {
  240. AcquireTimedLock(&(*ppListen)->Lock,10,&bTimedOut);
  241. if (bTimedOut) {
  242. RelinquishLock(&ListenTable.Lock);
  243. Sleep(0);
  244. goto step1;
  245. }
  246. }
  247. RelinquishLock(&ListenTable.Lock);
  248. if (*ppListen == NULL)
  249. return CC_BAD_PARAM;
  250. else
  251. return CC_OK;
  252. }
  253. HRESULT ValidateListen( CC_HLISTEN hListen)
  254. {
  255. PLISTEN pListen;
  256. ASSERT(hListen != CC_INVALID_HANDLE);
  257. AcquireLock(&ListenTable.Lock);
  258. pListen = ListenTable.pHead;
  259. while ((pListen != NULL) && (pListen->hListen != hListen))
  260. pListen = pListen->pNextInTable;
  261. RelinquishLock(&ListenTable.Lock);
  262. if (pListen == NULL)
  263. return CC_BAD_PARAM;
  264. else
  265. return CC_OK;
  266. }
  267. HRESULT UnlockListen( PLISTEN pListen)
  268. {
  269. ASSERT(pListen != NULL);
  270. RelinquishLock(&pListen->Lock);
  271. return CC_OK;
  272. }
  273. HRESULT GetLastListenAddress( PCC_ADDR pListenAddr)
  274. {
  275. HRESULT status;
  276. PLISTEN pListen;
  277. PLISTEN pLastListen;
  278. ASSERT(pListenAddr != NULL);
  279. AcquireLock(&ListenTable.Lock);
  280. pListen = ListenTable.pHead;
  281. pLastListen = pListen;
  282. while (pListen != NULL) {
  283. if (pLastListen->hListen < pListen->hListen)
  284. pLastListen = pListen;
  285. pListen = pListen->pNextInTable;
  286. }
  287. if (pLastListen == NULL)
  288. status = CC_BAD_PARAM;
  289. else {
  290. status = CC_OK;
  291. *pListenAddr = pLastListen->ListenAddr;
  292. }
  293. RelinquishLock(&ListenTable.Lock);
  294. return status;
  295. }
  296.