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.

415 lines
11 KiB

  1. //============================================================================
  2. // Copyright (c) 2000, Microsoft Corporation
  3. //
  4. // File: devlist.c
  5. //
  6. // History:
  7. // Yi Sun July-26-2000 Created
  8. //
  9. // Abstract:
  10. // TSPI_lineGetDevCaps queries a specified line device to determine
  11. // its telephony capabilities. The returned cap structure doesn't change
  12. // with time. This allows us to be able to save that structure so that
  13. // we don't have to take a user/kernel transition for every GetCaps call.
  14. // We also save negotiated/committed TSPI version and extension version
  15. // so that we can verify version numbers passed in with a GetCaps call.
  16. // Since TSPI_lineGetNumAddressIDs is based on TSPI_lineGetDevCaps, by
  17. // implementing this optimization, we also save an IOCTL call for every
  18. // GetNumAddressIDs call.
  19. //============================================================================
  20. #include "nt.h"
  21. #include "ntrtl.h"
  22. #include "nturtl.h"
  23. #include "windows.h"
  24. #include "tapi.h"
  25. #include "ndptsp.h"
  26. typedef struct _LINE_DEV_NODE
  27. {
  28. struct _LINE_DEV_NODE *pNext;
  29. LINEDEVCAPS *pCaps;
  30. DWORD dwDeviceID;
  31. DWORD dwNegTSPIV; // negotiated TSPI version
  32. DWORD dwComTSPIV; // committed TSPI version
  33. DWORD dwNegExtV; // negotiated ext version
  34. DWORD dwComExtV; // committed ext version
  35. } LINE_DEV_NODE, *PLINE_DEV_NODE;
  36. typedef struct _LINE_DEV_LIST
  37. {
  38. CRITICAL_SECTION critSec;
  39. PLINE_DEV_NODE pHead;
  40. } LINE_DEV_LIST, *PLINE_DEV_LIST;
  41. static LINE_DEV_LIST gLineDevList;
  42. //
  43. // call InitLineDevList() in DllMain(): DLL_PROCESS_ATTACH
  44. // to make sure that the dev list is initialized before
  45. // TSPI version negotiation happens
  46. //
  47. VOID
  48. InitLineDevList()
  49. {
  50. InitializeCriticalSection(&gLineDevList.critSec);
  51. gLineDevList.pHead = NULL;
  52. }
  53. //
  54. // call UninitLineDevList() in DllMain(): DLL_PROCESS_DETACH
  55. //
  56. VOID
  57. UninitLineDevList()
  58. {
  59. while (gLineDevList.pHead != NULL)
  60. {
  61. PLINE_DEV_NODE pNode = gLineDevList.pHead;
  62. gLineDevList.pHead = gLineDevList.pHead->pNext;
  63. if (pNode->pCaps != NULL)
  64. {
  65. FREE(pNode->pCaps);
  66. }
  67. FREE(pNode);
  68. }
  69. DeleteCriticalSection(&gLineDevList.critSec);
  70. }
  71. PLINE_DEV_NODE
  72. GetLineDevNode(
  73. IN DWORD dwDeviceID
  74. )
  75. {
  76. PLINE_DEV_NODE pNode;
  77. EnterCriticalSection(&gLineDevList.critSec);
  78. pNode = gLineDevList.pHead;
  79. while ((pNode != NULL) && (pNode->dwDeviceID != dwDeviceID))
  80. {
  81. pNode = pNode->pNext;
  82. }
  83. if (pNode != NULL)
  84. {
  85. LeaveCriticalSection(&gLineDevList.critSec);
  86. return pNode;
  87. }
  88. // pNode == NULL
  89. // so allocate and zeroinit a node
  90. pNode = (PLINE_DEV_NODE)MALLOC(sizeof(LINE_DEV_NODE));
  91. if (NULL == pNode)
  92. {
  93. TspLog(DL_ERROR, "GetLineDevNode: failed to alloc LINE_DEV_NODE");
  94. LeaveCriticalSection(&gLineDevList.critSec);
  95. return NULL;
  96. }
  97. ASSERT(pNode != NULL);
  98. // init pNode
  99. pNode->dwDeviceID = dwDeviceID;
  100. // insert pNode into the list
  101. pNode->pNext = gLineDevList.pHead;
  102. gLineDevList.pHead = pNode;
  103. LeaveCriticalSection(&gLineDevList.critSec);
  104. return pNode;
  105. }
  106. //
  107. // TSPI_lineNegotiateTSPIVersion calls this function to pass
  108. // the negotiated TSPI version number
  109. //
  110. LONG
  111. SetNegotiatedTSPIVersion(
  112. IN DWORD dwDeviceID,
  113. IN DWORD dwTSPIVersion
  114. )
  115. {
  116. PLINE_DEV_NODE pNode;
  117. TspLog(DL_TRACE, "SetNegotiatedTSPIVersion: deviceID(%x), TSPIV(%x)",
  118. dwDeviceID, dwTSPIVersion);
  119. EnterCriticalSection(&gLineDevList.critSec);
  120. pNode = GetLineDevNode(dwDeviceID);
  121. if (NULL == pNode)
  122. {
  123. LeaveCriticalSection(&gLineDevList.critSec);
  124. return LINEERR_NOMEM;
  125. }
  126. pNode->dwNegTSPIV = dwTSPIVersion;
  127. LeaveCriticalSection(&gLineDevList.critSec);
  128. return TAPI_SUCCESS;
  129. }
  130. //
  131. // TSPI_lineNegotiateExtVersion calls this function to pass
  132. // the negotiated extension version number
  133. //
  134. LONG
  135. SetNegotiatedExtVersion(
  136. IN DWORD dwDeviceID,
  137. IN DWORD dwExtVersion
  138. )
  139. {
  140. PLINE_DEV_NODE pNode;
  141. TspLog(DL_TRACE, "SetNegotiatedExtVersion: deviceID(%x), ExtV(%x)",
  142. dwDeviceID, dwExtVersion);
  143. EnterCriticalSection(&gLineDevList.critSec);
  144. pNode = GetLineDevNode(dwDeviceID);
  145. if (NULL == pNode)
  146. {
  147. LeaveCriticalSection(&gLineDevList.critSec);
  148. return LINEERR_NOMEM;
  149. }
  150. pNode->dwNegExtV = dwExtVersion;
  151. LeaveCriticalSection(&gLineDevList.critSec);
  152. return TAPI_SUCCESS;
  153. }
  154. //
  155. // TSPI_lineSelectExtVersion calls this function to commit/decommit
  156. // extension version. The ext version is decommitted by selecting ext
  157. // version 0
  158. //
  159. LONG
  160. SetSelectedExtVersion(
  161. IN DWORD dwDeviceID,
  162. IN DWORD dwExtVersion
  163. )
  164. {
  165. PLINE_DEV_NODE pNode;
  166. TspLog(DL_TRACE, "SetSelectedExtVersion: deviceID(%x), ExtV(%x)",
  167. dwDeviceID, dwExtVersion);
  168. EnterCriticalSection(&gLineDevList.critSec);
  169. pNode = GetLineDevNode(dwDeviceID);
  170. if (NULL == pNode)
  171. {
  172. LeaveCriticalSection(&gLineDevList.critSec);
  173. return LINEERR_NOMEM;
  174. }
  175. if ((dwExtVersion != 0) && (dwExtVersion != pNode->dwNegExtV))
  176. {
  177. TspLog(DL_ERROR,
  178. "SetSelectedExtVersion: ext version(%x) not match "\
  179. "the negotiated one(%x)",
  180. dwExtVersion, pNode->dwNegExtV);
  181. LeaveCriticalSection(&gLineDevList.critSec);
  182. return LINEERR_INCOMPATIBLEEXTVERSION;
  183. }
  184. pNode->dwComExtV = dwExtVersion;
  185. LeaveCriticalSection(&gLineDevList.critSec);
  186. return TAPI_SUCCESS;
  187. }
  188. //
  189. // TSPI_lineOpen calls this function to commit TSPI version
  190. //
  191. LONG
  192. CommitNegotiatedTSPIVersion(
  193. IN DWORD dwDeviceID
  194. )
  195. {
  196. PLINE_DEV_NODE pNode;
  197. TspLog(DL_TRACE, "CommitNegotiatedTSPIVersion: deviceID(%x)", dwDeviceID);
  198. EnterCriticalSection(&gLineDevList.critSec);
  199. pNode = GetLineDevNode(dwDeviceID);
  200. if (NULL == pNode)
  201. {
  202. LeaveCriticalSection(&gLineDevList.critSec);
  203. return LINEERR_NOMEM;
  204. }
  205. pNode->dwComTSPIV = pNode->dwNegTSPIV;
  206. LeaveCriticalSection(&gLineDevList.critSec);
  207. return TAPI_SUCCESS;
  208. }
  209. //
  210. // TSPI_lineClose calls this function to decommit TSPI version
  211. //
  212. LONG
  213. DecommitNegotiatedTSPIVersion(
  214. IN DWORD dwDeviceID
  215. )
  216. {
  217. PLINE_DEV_NODE pNode;
  218. TspLog(DL_TRACE, "DecommitNegotiatedTSPIVersion: deviceID(%x)", dwDeviceID);
  219. EnterCriticalSection(&gLineDevList.critSec);
  220. pNode = GetLineDevNode(dwDeviceID);
  221. if (NULL == pNode)
  222. {
  223. LeaveCriticalSection(&gLineDevList.critSec);
  224. return LINEERR_NOMEM;
  225. }
  226. pNode->dwComTSPIV = 0;
  227. LeaveCriticalSection(&gLineDevList.critSec);
  228. return TAPI_SUCCESS;
  229. }
  230. //
  231. // actual implementation of TSPI_lineGetNumAddressIDs
  232. //
  233. LONG
  234. GetNumAddressIDs(
  235. IN DWORD dwDeviceID,
  236. OUT DWORD *pdwNumAddressIDs
  237. )
  238. {
  239. PLINE_DEV_NODE pNode;
  240. EnterCriticalSection(&gLineDevList.critSec);
  241. pNode = GetLineDevNode(dwDeviceID);
  242. if (NULL == pNode)
  243. {
  244. LeaveCriticalSection(&gLineDevList.critSec);
  245. return LINEERR_NOMEM;
  246. }
  247. ASSERT(pNode != NULL);
  248. if (NULL == pNode->pCaps)
  249. {
  250. pNode->pCaps = GetLineDevCaps(dwDeviceID, pNode->dwComExtV);
  251. if (NULL == pNode->pCaps)
  252. {
  253. LeaveCriticalSection(&gLineDevList.critSec);
  254. return LINEERR_NOMEM;
  255. }
  256. }
  257. ASSERT(pNode->pCaps != NULL);
  258. *pdwNumAddressIDs = pNode->pCaps->dwNumAddresses;
  259. LeaveCriticalSection(&gLineDevList.critSec);
  260. return TAPI_SUCCESS;
  261. }
  262. //
  263. // actual implementation of TSPI_lineGetDevCaps
  264. //
  265. LONG
  266. GetDevCaps(
  267. IN DWORD dwDeviceID,
  268. IN DWORD dwTSPIVersion,
  269. IN DWORD dwExtVersion,
  270. OUT LINEDEVCAPS *pLineDevCaps
  271. )
  272. {
  273. PLINE_DEV_NODE pNode;
  274. EnterCriticalSection(&gLineDevList.critSec);
  275. pNode = GetLineDevNode(dwDeviceID);
  276. if (NULL == pNode)
  277. {
  278. LeaveCriticalSection(&gLineDevList.critSec);
  279. return LINEERR_NOMEM;
  280. }
  281. ASSERT(pNode != NULL);
  282. //
  283. // check the version numbers
  284. //
  285. if ((pNode->dwComTSPIV != 0) && (dwTSPIVersion != pNode->dwComTSPIV))
  286. {
  287. TspLog(DL_ERROR,
  288. "GetDevCaps: tspi version(%x) not match"\
  289. "the committed one(%x)",
  290. dwTSPIVersion, pNode->dwComTSPIV);
  291. LeaveCriticalSection(&gLineDevList.critSec);
  292. return LINEERR_INCOMPATIBLEAPIVERSION;
  293. }
  294. if ((pNode->dwComExtV != 0) && (dwExtVersion != pNode->dwComExtV))
  295. {
  296. TspLog(DL_ERROR,
  297. "GetDevCaps: ext version(%x) not match "\
  298. "the committed one(%x)",
  299. dwExtVersion, pNode->dwComExtV);
  300. LeaveCriticalSection(&gLineDevList.critSec);
  301. return LINEERR_INCOMPATIBLEEXTVERSION;
  302. }
  303. if (NULL == pNode->pCaps)
  304. {
  305. pNode->pCaps = GetLineDevCaps(dwDeviceID, dwExtVersion);
  306. if (NULL == pNode->pCaps)
  307. {
  308. LeaveCriticalSection(&gLineDevList.critSec);
  309. return LINEERR_NOMEM;
  310. }
  311. }
  312. ASSERT(pNode->pCaps != NULL);
  313. //
  314. // copy caps over
  315. //
  316. if (pNode->pCaps->dwNeededSize > pLineDevCaps->dwTotalSize)
  317. {
  318. pLineDevCaps->dwNeededSize = pNode->pCaps->dwNeededSize;
  319. pLineDevCaps->dwUsedSize =
  320. (pLineDevCaps->dwTotalSize < sizeof(LINEDEVCAPS) ?
  321. pLineDevCaps->dwTotalSize : sizeof(LINEDEVCAPS));
  322. ASSERT(pLineDevCaps->dwUsedSize >= 10);
  323. // reset dwProviderInfoSize to dwLineNameOffset to 0
  324. ZeroMemory(&pLineDevCaps->dwProviderInfoSize, 7 * sizeof(DWORD));
  325. // copy over dwPermanentLineID
  326. pLineDevCaps->dwPermanentLineID = pNode->pCaps->dwPermanentLineID;
  327. // copy everything from dwStringFormat
  328. CopyMemory(&pLineDevCaps->dwStringFormat,
  329. &pNode->pCaps->dwStringFormat,
  330. pLineDevCaps->dwUsedSize - 10 * sizeof(DWORD));
  331. // we don't need to set dwTerminalCaps(Size, Offset),
  332. // dwTerminalText(Size, Offset), etc. to 0
  333. // because these fields have been preset with 0
  334. // before the service provider was called
  335. }
  336. else
  337. {
  338. // copy over all fields except dwTotalSize
  339. CopyMemory(&pLineDevCaps->dwNeededSize,
  340. &pNode->pCaps->dwNeededSize,
  341. pNode->pCaps->dwNeededSize - sizeof(DWORD));
  342. }
  343. LeaveCriticalSection(&gLineDevList.critSec);
  344. return TAPI_SUCCESS;
  345. }