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.

5148 lines
146 KiB

  1. //============================================================================
  2. // Copyright (c) 2000, Microsoft Corporation
  3. //
  4. // File: kmddsp.c
  5. //
  6. // History:
  7. // Dan Knudson (DanKn) 11-Apr-1995 Created
  8. // Yi Sun (YiSun) June-29-2000 Rewriten
  9. //
  10. // Abstract:
  11. //============================================================================
  12. #include "nt.h"
  13. #include "ntrtl.h"
  14. #include "nturtl.h"
  15. #include "windows.h"
  16. #include "rtutils.h"
  17. #include "winioctl.h"
  18. #include "ntddndis.h"
  19. #include "ndistapi.h"
  20. #include "intrface.h"
  21. //
  22. // NOTE: the following are defined in both ndistapi.h & tapi.h (or tspi.h)
  23. // and cause (more or less non-interesting) build warnings, so we
  24. // undefine them after the first #include to do away with this
  25. //
  26. #undef LAST_LINEMEDIAMODE
  27. #undef TSPI_MESSAGE_BASE
  28. #undef LINE_NEWCALL
  29. #undef LINE_CALLDEVSPECIFIC
  30. #undef LINE_CREATE
  31. #include "tapi.h"
  32. #include "tspi.h"
  33. #include "kmddsp.h"
  34. #define OUTBOUND_CALL_KEY ((DWORD) 'OCAL')
  35. #define INBOUND_CALL_KEY ((DWORD) 'ICAL')
  36. #define LINE_KEY ((DWORD) 'KLIN')
  37. #define ASYNCREQWRAPPER_KEY ((DWORD) 'ARWK')
  38. #define INVALID_KEY ((DWORD) 'XXXX')
  39. #define EVENT_BUFFER_SIZE 1024
  40. typedef LONG (*POSTPROCESSPROC)(PASYNC_REQUEST_WRAPPER, LONG, PDWORD_PTR);
  41. typedef struct _ASYNC_REQUEST_WRAPPER
  42. {
  43. // NOTE: overlapped must remain 1st field in this struct
  44. OVERLAPPED Overlapped;
  45. DWORD dwKey;
  46. DWORD dwRequestID;
  47. POSTPROCESSPROC pfnPostProcess;
  48. CRITICAL_SECTION CritSec;
  49. ULONG RefCount;
  50. DWORD_PTR dwRequestSpecific;
  51. // NOTE: NdisTapiRequest must follow a ptr to avoid alignment problem
  52. NDISTAPI_REQUEST NdisTapiRequest;
  53. } ASYNC_REQUEST_WRAPPER, *PASYNC_REQUEST_WRAPPER;
  54. #define REF_ASYNC_REQUEST_WRAPPER(_pAsyncReqWrapper) \
  55. { \
  56. EnterCriticalSection(&_pAsyncReqWrapper->CritSec); \
  57. _pAsyncReqWrapper->RefCount++; \
  58. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  59. }
  60. #define DEREF_ASYNC_REQUEST_WRAPPER(_pAsyncReqWrapper) \
  61. { \
  62. EnterCriticalSection(&_pAsyncReqWrapper->CritSec); \
  63. if (--(_pAsyncReqWrapper->RefCount) == 0) { \
  64. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  65. DeleteCriticalSection(&_pAsyncReqWrapper->CritSec); \
  66. FreeRequest(_pAsyncReqWrapper); \
  67. _pAsyncReqWrapper = NULL; \
  68. } else { \
  69. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  70. } \
  71. }
  72. typedef struct _ASYNC_EVENTS_THREAD_INFO
  73. {
  74. HANDLE hThread; // thread handle
  75. PNDISTAPI_EVENT_DATA pBuf; // ptr to a buf for async events
  76. DWORD dwBufSize; // size of the previous buffer
  77. } ASYNC_EVENTS_THREAD_INFO, *PASYNC_EVENTS_THREAD_INFO;
  78. typedef struct _DRVCALL
  79. {
  80. DWORD dwKey;
  81. DWORD dwDeviceID;
  82. HTAPICALL htCall; // TAPI's handle to the call
  83. HDRVCALL hdCall; // TSP's handle to the call
  84. HDRV_CALL hd_Call; // NDISTAPI's call handle
  85. HDRVLINE hdLine; // TSP's handle to the line
  86. union
  87. {
  88. struct _DRVCALL *pPrev; // for inbound calls only
  89. DWORD dwPendingCallState; // for outbound calls only
  90. };
  91. union
  92. {
  93. struct _DRVCALL *pNext; // for inbound calls only
  94. DWORD dwPendingCallStateMode; // for outbound calls only
  95. };
  96. union
  97. {
  98. HTAPI_CALL ht_Call; // for inbound calls only
  99. DWORD dwPendingMediaMode; // for outbound calls only
  100. };
  101. BOOL bIncomplete;
  102. BOOL bDropped;
  103. BOOL bIdle;
  104. } DRVCALL, *PDRVCALL;
  105. typedef struct _DRVLINE
  106. {
  107. DWORD dwKey;
  108. DWORD dwDeviceID;
  109. HTAPILINE htLine; // TAPI's line handle
  110. HDRV_LINE hd_Line; // NDISTAPI's line handle
  111. PDRVCALL pInboundCalls; // inbound call list
  112. // the following two related to PNP/POWER
  113. GUID Guid;
  114. NDIS_WAN_MEDIUM_SUBTYPE MediaType;
  115. } DRVLINE, *PDRVLINE;
  116. // globals
  117. HANDLE ghDriverSync, ghDriverAsync, ghCompletionPort;
  118. PASYNC_EVENTS_THREAD_INFO gpAsyncEventsThreadInfo;
  119. DWORD gdwRequestID;
  120. ASYNC_COMPLETION gpfnCompletionProc;
  121. CRITICAL_SECTION gRequestIDCritSec;
  122. LINEEVENT gpfnLineEvent;
  123. HPROVIDER ghProvider;
  124. //
  125. // debug globals
  126. //
  127. #if DBG
  128. DWORD gdwDebugLevel;
  129. #endif // DBG
  130. DWORD gdwTraceID = INVALID_TRACEID;
  131. //
  132. // creates a log using the RAS tracing utility
  133. // also prints it onto the attached debugger
  134. // if a debug build is running
  135. //
  136. VOID
  137. TspLog(
  138. IN DWORD dwDebugLevel,
  139. IN PCHAR pchFormat,
  140. ...
  141. )
  142. {
  143. va_list arglist;
  144. CHAR chNewFmt[256];
  145. va_start(arglist, pchFormat);
  146. switch (dwDebugLevel)
  147. {
  148. case DL_ERROR:
  149. strcpy(chNewFmt, "!!! ");
  150. break;
  151. case DL_WARNING:
  152. strcpy(chNewFmt, "!! ");
  153. break;
  154. case DL_INFO:
  155. strcpy(chNewFmt, "! ");
  156. break;
  157. case DL_TRACE:
  158. strcpy(chNewFmt, " ");
  159. break;
  160. }
  161. strcat(chNewFmt, pchFormat);
  162. #if DBG
  163. if (dwDebugLevel <= gdwDebugLevel)
  164. {
  165. #if 0
  166. DbgPrint("++KMDDSP++ ");
  167. DbgPrint(chNewFmt, arglist);
  168. DbgPrint("\n");
  169. #else
  170. char szBuffer[256];
  171. OutputDebugString("++KMDDSP++ ");
  172. wvsprintf(szBuffer, chNewFmt, arglist);
  173. OutputDebugString(szBuffer);
  174. OutputDebugString("\n");
  175. #endif
  176. }
  177. #endif // DBG
  178. if (gdwTraceID != INVALID_TRACEID)
  179. {
  180. TraceVprintfEx(gdwTraceID,
  181. (dwDebugLevel << 16) | TRACE_USE_MASK | TRACE_USE_MSEC,
  182. chNewFmt,
  183. arglist);
  184. }
  185. va_end(arglist);
  186. #if DBG
  187. if (DL_ERROR == dwDebugLevel)
  188. {
  189. //DebugBreak();
  190. }
  191. #endif // DBG
  192. }
  193. #if DBG
  194. #define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e,f)
  195. void
  196. PASCAL
  197. InsertVarDataString(
  198. LPVOID pStruct,
  199. LPDWORD pdwXxxSize,
  200. LPVOID pNewStruct,
  201. LPDWORD pdwNewXxxSize,
  202. DWORD dwFixedStructSize,
  203. char *pszFieldName
  204. )
  205. #else
  206. #define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e)
  207. void
  208. PASCAL
  209. InsertVarDataString(
  210. LPVOID pStruct,
  211. LPDWORD pdwXxxSize,
  212. LPVOID pNewStruct,
  213. LPDWORD pdwNewXxxSize,
  214. DWORD dwFixedStructSize
  215. )
  216. #endif
  217. {
  218. DWORD dwXxxSize, dwTotalSize, dwXxxOffset;
  219. //
  220. // If the dwXxxSize field of the old struct is non-zero, then
  221. // we need to do a ascii->unicode conversion on it. Check to
  222. // make sure that the size/offset are valid (if not set the
  223. // data size/offset in the new struct to 0) and then convert.
  224. //
  225. if ((dwXxxSize = *pdwXxxSize))
  226. {
  227. dwXxxOffset = *(pdwXxxSize + 1);
  228. #if DBG
  229. dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
  230. if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
  231. dwXxxOffset < dwFixedStructSize ||
  232. dwXxxOffset >= dwTotalSize ||
  233. (dwXxxSize + dwXxxOffset) > dwTotalSize)
  234. {
  235. TspLog(DL_ERROR,
  236. "INSERTVARDATASTRING: bad %s values - size(x%x), "\
  237. "offset(x%x)",
  238. pszFieldName, dwXxxSize, dwXxxOffset);
  239. *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
  240. return;
  241. }
  242. #endif
  243. // make sure the string is NULL terminated
  244. *(((LPBYTE)pStruct) + (dwXxxOffset + dwXxxSize - 1)) = '\0';
  245. MultiByteToWideChar(
  246. CP_ACP,
  247. MB_PRECOMPOSED,
  248. ((LPBYTE) pStruct) + dwXxxOffset,
  249. dwXxxSize,
  250. (LPWSTR) (((LPBYTE) pNewStruct) +
  251. ((LPVARSTRING) pNewStruct)->dwUsedSize),
  252. dwXxxSize * sizeof (WCHAR)
  253. );
  254. *pdwNewXxxSize = dwXxxSize * sizeof (WCHAR);
  255. *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
  256. ((LPVARSTRING) pNewStruct)->dwUsedSize += (dwXxxSize * sizeof (WCHAR));
  257. }
  258. }
  259. #if DBG
  260. #define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e,f)
  261. void
  262. PASCAL
  263. InsertVarData(
  264. LPVOID pStruct,
  265. LPDWORD pdwXxxSize,
  266. LPVOID pNewStruct,
  267. LPDWORD pdwNewXxxSize,
  268. DWORD dwFixedStructSize,
  269. char *pszFieldName
  270. )
  271. #else
  272. #define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e)
  273. void
  274. PASCAL
  275. InsertVarData(
  276. LPVOID pStruct,
  277. LPDWORD pdwXxxSize,
  278. LPVOID pNewStruct,
  279. LPDWORD pdwNewXxxSize,
  280. DWORD dwFixedStructSize
  281. )
  282. #endif
  283. {
  284. DWORD dwTotalSize, dwXxxSize, dwXxxOffset;
  285. if ((dwXxxSize = *pdwXxxSize))
  286. {
  287. dwXxxOffset = *(pdwXxxSize + 1);
  288. #if DBG
  289. dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
  290. if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
  291. dwXxxOffset < dwFixedStructSize ||
  292. dwXxxOffset >= dwTotalSize ||
  293. (dwXxxSize + dwXxxOffset) > dwTotalSize)
  294. {
  295. TspLog(DL_ERROR,
  296. "INSERTVARDATA: bad %s values - size(x%x), offset(x%x)",
  297. pszFieldName, dwXxxSize, dwXxxOffset);
  298. *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
  299. return;
  300. }
  301. #endif
  302. CopyMemory(
  303. ((LPBYTE) pNewStruct) + ((LPVARSTRING) pNewStruct)->dwUsedSize,
  304. ((LPBYTE) pStruct) + dwXxxOffset,
  305. dwXxxSize
  306. );
  307. *pdwNewXxxSize = dwXxxSize;
  308. *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
  309. ((LPVARSTRING) pNewStruct)->dwUsedSize += dwXxxSize;
  310. }
  311. }
  312. static char *pszOidNames[] =
  313. {
  314. "Accept",
  315. "Answer",
  316. "Close",
  317. "CloseCall",
  318. "ConditionalMediaDetection",
  319. "ConfigDialog",
  320. "DevSpecific",
  321. "Dial",
  322. "Drop",
  323. "GetAddressCaps",
  324. "GetAddressID",
  325. "GetAddressStatus",
  326. "GetCallAddressID",
  327. "GetCallInfo",
  328. "GetCallStatus",
  329. "GetDevCaps",
  330. "GetDevConfig",
  331. "GetExtensionID",
  332. "GetID",
  333. "GetLineDevStatus",
  334. "MakeCall",
  335. "NegotiateExtVersion",
  336. "Open",
  337. "ProviderInitialize",
  338. "ProviderShutdown",
  339. "SecureCall",
  340. "SelectExtVersion",
  341. "SendUserUserInfo",
  342. "SetAppSpecific",
  343. "StCallParams",
  344. "StDefaultMediaDetection",
  345. "SetDevConfig",
  346. "SetMediaMode",
  347. "SetStatusMessages"
  348. };
  349. //
  350. // translates NDIS TAPI status codes into LINEERR_XXX
  351. //
  352. LONG
  353. WINAPI
  354. TranslateDriverResult(
  355. ULONG ulRes
  356. )
  357. {
  358. typedef struct _RESULT_LOOKUP
  359. {
  360. ULONG NdisTapiResult;
  361. LONG TapiResult;
  362. } RESULT_LOOKUP, *PRESULT_LOOKUP;
  363. typedef ULONG NDIS_STATUS;
  364. #define NDIS_STATUS_SUCCESS 0x00000000L
  365. #define NDIS_STATUS_RESOURCES 0xC000009AL
  366. #define NDIS_STATUS_FAILURE 0xC0000001L
  367. #define NDIS_STATUS_INVALID_OID 0xC0010017L
  368. static RESULT_LOOKUP aResults[] =
  369. {
  370. //
  371. // Defined in NDIS.H
  372. //
  373. { NDIS_STATUS_SUCCESS ,0 },
  374. //
  375. // These errors are defined in NDISTAPI.H
  376. //
  377. { NDIS_STATUS_TAPI_ADDRESSBLOCKED ,LINEERR_ADDRESSBLOCKED },
  378. { NDIS_STATUS_TAPI_BEARERMODEUNAVAIL ,LINEERR_BEARERMODEUNAVAIL },
  379. { NDIS_STATUS_TAPI_CALLUNAVAIL ,LINEERR_CALLUNAVAIL },
  380. { NDIS_STATUS_TAPI_DIALBILLING ,LINEERR_DIALBILLING },
  381. { NDIS_STATUS_TAPI_DIALDIALTONE ,LINEERR_DIALDIALTONE },
  382. { NDIS_STATUS_TAPI_DIALPROMPT ,LINEERR_DIALPROMPT },
  383. { NDIS_STATUS_TAPI_DIALQUIET ,LINEERR_DIALQUIET },
  384. { NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION,LINEERR_INCOMPATIBLEEXTVERSION},
  385. { NDIS_STATUS_TAPI_INUSE ,LINEERR_INUSE },
  386. { NDIS_STATUS_TAPI_INVALADDRESS ,LINEERR_INVALADDRESS },
  387. { NDIS_STATUS_TAPI_INVALADDRESSID ,LINEERR_INVALADDRESSID },
  388. { NDIS_STATUS_TAPI_INVALADDRESSMODE ,LINEERR_INVALADDRESSMODE },
  389. { NDIS_STATUS_TAPI_INVALBEARERMODE ,LINEERR_INVALBEARERMODE },
  390. { NDIS_STATUS_TAPI_INVALCALLHANDLE ,LINEERR_INVALCALLHANDLE },
  391. { NDIS_STATUS_TAPI_INVALCALLPARAMS ,LINEERR_INVALCALLPARAMS },
  392. { NDIS_STATUS_TAPI_INVALCALLSTATE ,LINEERR_INVALCALLSTATE },
  393. { NDIS_STATUS_TAPI_INVALDEVICECLASS ,LINEERR_INVALDEVICECLASS },
  394. { NDIS_STATUS_TAPI_INVALLINEHANDLE ,LINEERR_INVALLINEHANDLE },
  395. { NDIS_STATUS_TAPI_INVALLINESTATE ,LINEERR_INVALLINESTATE },
  396. { NDIS_STATUS_TAPI_INVALMEDIAMODE ,LINEERR_INVALMEDIAMODE },
  397. { NDIS_STATUS_TAPI_INVALRATE ,LINEERR_INVALRATE },
  398. { NDIS_STATUS_TAPI_NODRIVER ,LINEERR_NODRIVER },
  399. { NDIS_STATUS_TAPI_OPERATIONUNAVAIL ,LINEERR_OPERATIONUNAVAIL },
  400. { NDIS_STATUS_TAPI_RATEUNAVAIL ,LINEERR_RATEUNAVAIL },
  401. { NDIS_STATUS_TAPI_RESOURCEUNAVAIL ,LINEERR_RESOURCEUNAVAIL },
  402. { NDIS_STATUS_TAPI_STRUCTURETOOSMALL ,LINEERR_STRUCTURETOOSMALL },
  403. { NDIS_STATUS_TAPI_USERUSERINFOTOOBIG ,LINEERR_USERUSERINFOTOOBIG },
  404. { NDIS_STATUS_TAPI_ALLOCATED ,LINEERR_ALLOCATED },
  405. { NDIS_STATUS_TAPI_INVALADDRESSSTATE ,LINEERR_INVALADDRESSSTATE },
  406. { NDIS_STATUS_TAPI_INVALPARAM ,LINEERR_INVALPARAM },
  407. { NDIS_STATUS_TAPI_NODEVICE ,LINEERR_NODEVICE },
  408. //
  409. // These errors are defined in NDIS.H
  410. //
  411. { NDIS_STATUS_RESOURCES ,LINEERR_NOMEM },
  412. { NDIS_STATUS_FAILURE ,LINEERR_OPERATIONFAILED },
  413. { NDIS_STATUS_INVALID_OID ,LINEERR_OPERATIONFAILED },
  414. //
  415. //
  416. //
  417. { NDISTAPIERR_UNINITIALIZED ,LINEERR_OPERATIONFAILED },
  418. { NDISTAPIERR_BADDEVICEID ,LINEERR_OPERATIONFAILED },
  419. { NDISTAPIERR_DEVICEOFFLINE ,LINEERR_OPERATIONFAILED },
  420. //
  421. // The terminating fields
  422. //
  423. { 0xffffffff, 0xffffffff }
  424. };
  425. int i;
  426. for (i = 0; aResults[i].NdisTapiResult != 0xffffffff; i++)
  427. {
  428. if (ulRes == aResults[i].NdisTapiResult)
  429. {
  430. return (aResults[i].TapiResult);
  431. }
  432. }
  433. TspLog(DL_WARNING, "TranslateDriverResult: unknown driver result(%x)",
  434. ulRes);
  435. return LINEERR_OPERATIONFAILED;
  436. }
  437. //
  438. // NOTE: for functions that need to acquire (read, write) locks for both
  439. // a line and a call, we enforce the order to be line first, call
  440. // second to avoid potential DEADLOCK.
  441. //
  442. LONG
  443. GetLineObjWithReadLock(
  444. IN HDRVLINE hdLine,
  445. OUT PDRVLINE *ppLine
  446. )
  447. {
  448. LONG lRes;
  449. PDRVLINE pLine;
  450. lRes = GetObjWithReadLock((HANDLE)hdLine, &pLine);
  451. if (lRes != TAPI_SUCCESS)
  452. {
  453. return LINEERR_INVALLINEHANDLE;
  454. }
  455. ASSERT(pLine != NULL);
  456. if (pLine->dwKey != LINE_KEY)
  457. {
  458. TspLog(DL_WARNING, "GetLineObjWithReadLock: obj(%p) has bad key(%x)",
  459. hdLine, pLine->dwKey);
  460. ReleaseObjReadLock((HANDLE)hdLine);
  461. return LINEERR_INVALLINEHANDLE;
  462. }
  463. *ppLine = pLine;
  464. return lRes;
  465. }
  466. LONG
  467. GetLineObjWithWriteLock(
  468. IN HDRVLINE hdLine,
  469. OUT PDRVLINE *ppLine
  470. )
  471. {
  472. LONG lRes;
  473. PDRVLINE pLine;
  474. lRes = GetObjWithWriteLock((HANDLE)hdLine, &pLine);
  475. if (lRes != TAPI_SUCCESS)
  476. {
  477. return LINEERR_INVALLINEHANDLE;
  478. }
  479. ASSERT(pLine != NULL);
  480. if (pLine->dwKey != LINE_KEY)
  481. {
  482. TspLog(DL_WARNING, "GetLineObjWithWriteLock: obj(%p) has bad key(%x)",
  483. hdLine, pLine->dwKey);
  484. ReleaseObjWriteLock((HANDLE)hdLine);
  485. return LINEERR_INVALLINEHANDLE;
  486. }
  487. *ppLine = pLine;
  488. return lRes;
  489. }
  490. LONG
  491. GetCallObjWithReadLock(
  492. IN HDRVCALL hdCall,
  493. OUT PDRVCALL *ppCall
  494. )
  495. {
  496. LONG lRes;
  497. PDRVCALL pCall;
  498. lRes = GetObjWithReadLock((HANDLE)hdCall, &pCall);
  499. if (lRes != TAPI_SUCCESS)
  500. {
  501. return LINEERR_INVALCALLHANDLE;
  502. }
  503. ASSERT(pCall != NULL);
  504. if (pCall->dwKey != INBOUND_CALL_KEY &&
  505. pCall->dwKey != OUTBOUND_CALL_KEY)
  506. {
  507. TspLog(DL_WARNING, "GetCallObjWithReadLock: obj(%p) has bad key(%x)",
  508. hdCall, pCall->dwKey);
  509. ReleaseObjReadLock((HANDLE)hdCall);
  510. return LINEERR_INVALCALLHANDLE;
  511. }
  512. *ppCall = pCall;
  513. return lRes;
  514. }
  515. LONG
  516. GetCallObjWithWriteLock(
  517. IN HDRVCALL hdCall,
  518. OUT PDRVCALL *ppCall
  519. )
  520. {
  521. LONG lRes;
  522. PDRVCALL pCall;
  523. lRes = GetObjWithWriteLock((HANDLE)hdCall, &pCall);
  524. if (lRes != TAPI_SUCCESS)
  525. {
  526. return LINEERR_INVALCALLHANDLE;
  527. }
  528. ASSERT(pCall != NULL);
  529. if (pCall->dwKey != INBOUND_CALL_KEY &&
  530. pCall->dwKey != OUTBOUND_CALL_KEY)
  531. {
  532. TspLog(DL_WARNING, "GetCallObjWithWriteLock: obj(%p) has bad key(%x)",
  533. hdCall, pCall->dwKey);
  534. ReleaseObjWriteLock((HANDLE)hdCall);
  535. return LINEERR_INVALCALLHANDLE;
  536. }
  537. *ppCall = pCall;
  538. return lRes;
  539. }
  540. LONG
  541. GetLineHandleFromCallHandle(
  542. IN HDRVCALL hdCall,
  543. OUT HDRVLINE *phdLine
  544. )
  545. {
  546. LONG lRes;
  547. PDRVCALL pCall;
  548. lRes = GetObjWithReadLock((HANDLE)hdCall, &pCall);
  549. if (lRes != TAPI_SUCCESS)
  550. {
  551. return LINEERR_INVALCALLHANDLE;
  552. }
  553. ASSERT(pCall != NULL);
  554. if (pCall->dwKey != INBOUND_CALL_KEY &&
  555. pCall->dwKey != OUTBOUND_CALL_KEY)
  556. {
  557. TspLog(DL_WARNING,
  558. "GetLineHandleFromCallHandle: obj(%p) has bad key(%x)",
  559. hdCall, pCall->dwKey);
  560. ReleaseObjReadLock((HANDLE)hdCall);
  561. return LINEERR_INVALCALLHANDLE;
  562. }
  563. *phdLine = pCall->hdLine;
  564. ReleaseObjReadLock((HANDLE)hdCall);
  565. return lRes;
  566. }
  567. LONG
  568. GetLineAndCallObjWithReadLock(
  569. HTAPI_LINE ht_Line,
  570. HTAPI_CALL ht_Call,
  571. PDRVLINE *ppLine,
  572. PDRVCALL *ppCall
  573. )
  574. {
  575. LONG lRes;
  576. PDRVCALL pCall;
  577. PDRVLINE pLine;
  578. lRes = GetLineObjWithReadLock((HDRVLINE)ht_Line, &pLine);
  579. if (lRes != TAPI_SUCCESS)
  580. {
  581. return lRes;
  582. }
  583. *ppLine = pLine;
  584. //
  585. // figure out whether this is an inbound call or
  586. // outbound call: for inbound calls, ht_Call is
  587. // generated by NDISTAPI and bit 0 is 1;
  588. // for outbound calls, ht_Call is a TSP handle
  589. // and we make sure that bit 0 is 0
  590. //
  591. if (ht_Call & 0x1)
  592. {
  593. // inbound call: we need to walk the list
  594. // of inbound calls on this line and
  595. // find the right one
  596. if ((pCall = pLine->pInboundCalls) != NULL)
  597. {
  598. while (pCall && (pCall->ht_Call != ht_Call))
  599. {
  600. pCall = pCall->pNext;
  601. }
  602. }
  603. if (NULL == pCall || pCall->dwKey != INBOUND_CALL_KEY)
  604. {
  605. TspLog(DL_WARNING,
  606. "GetLineAndCallObjWithReadLock: "\
  607. "inbound ht_call(%p) closed already",
  608. ht_Call);
  609. ReleaseObjReadLock((HANDLE)ht_Line);
  610. return LINEERR_INVALCALLHANDLE;
  611. }
  612. // call the following to increase the ref count
  613. lRes = AcquireObjReadLock((HANDLE)pCall->hdCall);
  614. if (lRes != TAPI_SUCCESS)
  615. {
  616. ReleaseObjReadLock((HANDLE)ht_Line);
  617. return lRes;
  618. }
  619. *ppCall = pCall;
  620. return TAPI_SUCCESS;
  621. }
  622. // ht_Call is a TSP handle and the call is OUTBOUND
  623. lRes = GetObjWithReadLock((HANDLE)ht_Call, &pCall);
  624. if (lRes != TAPI_SUCCESS)
  625. {
  626. ReleaseObjReadLock((HANDLE)ht_Line);
  627. return lRes;
  628. }
  629. ASSERT(pCall != NULL);
  630. if (pCall->dwKey != OUTBOUND_CALL_KEY)
  631. {
  632. TspLog(DL_WARNING,
  633. "GetLineAndCallObjWithReadLock: bad call handle(%p, %x)",
  634. ht_Call, pCall->dwKey);
  635. ReleaseObjReadLock((HANDLE)ht_Call);
  636. ReleaseObjReadLock((HANDLE)ht_Line);
  637. return LINEERR_INVALCALLHANDLE;
  638. }
  639. *ppCall = pCall;
  640. return TAPI_SUCCESS;
  641. }
  642. //
  643. // allocates mem for a NDISTAPI_REQUEST plus some initialization
  644. //
  645. LONG
  646. WINAPI
  647. PrepareSyncRequest(
  648. ULONG Oid,
  649. ULONG ulDeviceID,
  650. DWORD dwDataSize,
  651. PNDISTAPI_REQUEST *ppNdisTapiRequest
  652. )
  653. {
  654. PNDISTAPI_REQUEST pNdisTapiRequest =
  655. (PNDISTAPI_REQUEST)AllocRequest(dwDataSize + sizeof(NDISTAPI_REQUEST));
  656. if (NULL == pNdisTapiRequest)
  657. {
  658. TspLog(DL_ERROR,
  659. "PrepareSyncRequest: failed to alloc sync req for oid(%x)",
  660. Oid);
  661. return LINEERR_NOMEM;
  662. }
  663. pNdisTapiRequest->Oid = Oid;
  664. pNdisTapiRequest->ulDeviceID = ulDeviceID;
  665. pNdisTapiRequest->ulDataSize = dwDataSize;
  666. EnterCriticalSection(&gRequestIDCritSec);
  667. // setting ulRequestId of NDIS_TAPI_xxxx
  668. if ((*((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
  669. {
  670. gdwRequestID = 1;
  671. }
  672. LeaveCriticalSection(&gRequestIDCritSec);
  673. *ppNdisTapiRequest = pNdisTapiRequest;
  674. return TAPI_SUCCESS;
  675. }
  676. //
  677. // allocates mem for a ASYNC_REQUEST_WRAPPER plus some initialization
  678. //
  679. LONG
  680. WINAPI
  681. PrepareAsyncRequest(
  682. ULONG Oid,
  683. ULONG ulDeviceID,
  684. DWORD dwRequestID,
  685. DWORD dwDataSize,
  686. PASYNC_REQUEST_WRAPPER *ppAsyncReqWrapper
  687. )
  688. {
  689. PNDISTAPI_REQUEST pNdisTapiRequest;
  690. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  691. // alloc & init an async request wrapper
  692. pAsyncReqWrapper = (PASYNC_REQUEST_WRAPPER)
  693. AllocRequest(dwDataSize + sizeof(ASYNC_REQUEST_WRAPPER));
  694. if (NULL == pAsyncReqWrapper)
  695. {
  696. TspLog(DL_ERROR,
  697. "PrepareAsyncRequest: failed to alloc async req for oid(%x)",
  698. Oid);
  699. return LINEERR_NOMEM;
  700. }
  701. // don't need to create an event when using completion ports
  702. pAsyncReqWrapper->Overlapped.hEvent = (HANDLE)NULL;
  703. pAsyncReqWrapper->dwKey = ASYNCREQWRAPPER_KEY;
  704. pAsyncReqWrapper->dwRequestID = dwRequestID;
  705. pAsyncReqWrapper->pfnPostProcess = (POSTPROCESSPROC)NULL;
  706. // initialize the critical section, ref the request wrapper.
  707. // NOTE: this crit sec will be deleted by the last deref.
  708. InitializeCriticalSection(&pAsyncReqWrapper->CritSec);
  709. pAsyncReqWrapper->RefCount = 1;
  710. // safely initialize the driver request
  711. pNdisTapiRequest = &(pAsyncReqWrapper->NdisTapiRequest);
  712. pNdisTapiRequest->Oid = Oid;
  713. pNdisTapiRequest->ulDeviceID = ulDeviceID;
  714. pNdisTapiRequest->ulDataSize = dwDataSize;
  715. EnterCriticalSection(&gRequestIDCritSec);
  716. if ((*((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
  717. {
  718. gdwRequestID = 1;
  719. }
  720. LeaveCriticalSection(&gRequestIDCritSec);
  721. *ppAsyncReqWrapper = pAsyncReqWrapper;
  722. return TAPI_SUCCESS;
  723. }
  724. //
  725. // makes a non-overlapped request to ndistapi.sys
  726. // so it doesn't return until the req is completed
  727. //
  728. LONG
  729. WINAPI
  730. SyncDriverRequest(
  731. DWORD dwIoControlCode,
  732. PNDISTAPI_REQUEST pNdisTapiRequest
  733. )
  734. {
  735. BOOL bRes;
  736. DWORD cbReturned;
  737. TspLog(DL_INFO,
  738. "SyncDriverRequest: oid(%s), devID(%x), reqID(%x), hdCall(%x)",
  739. pszOidNames[pNdisTapiRequest->Oid - OID_TAPI_ACCEPT],
  740. pNdisTapiRequest->ulDeviceID,
  741. *((ULONG *)pNdisTapiRequest->Data),
  742. *(((ULONG *)pNdisTapiRequest->Data) + 1));
  743. // mark the request as being processed by the driver
  744. MarkRequest(pNdisTapiRequest);
  745. bRes = DeviceIoControl(ghDriverSync,
  746. dwIoControlCode,
  747. pNdisTapiRequest,
  748. (DWORD)(sizeof(NDISTAPI_REQUEST) +
  749. pNdisTapiRequest->ulDataSize),
  750. pNdisTapiRequest,
  751. (DWORD)(sizeof(NDISTAPI_REQUEST) +
  752. pNdisTapiRequest->ulDataSize),
  753. &cbReturned,
  754. 0);
  755. // unmark the request now that the ioctl is completed
  756. UnmarkRequest(pNdisTapiRequest);
  757. if (bRes != TRUE)
  758. {
  759. TspLog(DL_ERROR, "SyncDriverRequest: IoCtl(Oid %x) failed(%d)",
  760. pNdisTapiRequest->Oid, GetLastError());
  761. return (LINEERR_OPERATIONFAILED);
  762. }
  763. else
  764. {
  765. // the errors returned by ndistapi.sys don't match the TAPI
  766. // LINEERR_'s, so return the translated values (but preserve
  767. // the original driver return val so it's possible to distinguish
  768. // between NDISTAPIERR_DEVICEOFFLINE & LINEERR_OPERATIONUNAVAIL,
  769. // etc.)
  770. return (TranslateDriverResult(pNdisTapiRequest->ulReturnValue));
  771. }
  772. }
  773. //
  774. // make an overlapped call
  775. //
  776. LONG
  777. WINAPI
  778. AsyncDriverRequest(
  779. DWORD dwIoControlCode,
  780. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper
  781. )
  782. {
  783. BOOL bRes;
  784. LONG lRes;
  785. DWORD dwRequestSize, cbReturned, dwLastError;
  786. TspLog(DL_INFO,
  787. "AsyncDriverRequest: oid(%s), devID(%x), ReqID(%x), "
  788. "reqID(%x), hdCall(%x)",
  789. pszOidNames[pAsyncReqWrapper->NdisTapiRequest.Oid -
  790. OID_TAPI_ACCEPT],
  791. pAsyncReqWrapper->NdisTapiRequest.ulDeviceID,
  792. pAsyncReqWrapper->dwRequestID,
  793. *((ULONG *)pAsyncReqWrapper->NdisTapiRequest.Data),
  794. *(((ULONG *)pAsyncReqWrapper->NdisTapiRequest.Data) + 1));
  795. lRes = (LONG)pAsyncReqWrapper->dwRequestID;
  796. dwRequestSize = sizeof(NDISTAPI_REQUEST) +
  797. (pAsyncReqWrapper->NdisTapiRequest.ulDataSize - 1);
  798. REF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  799. // mark the request as being processed by the driver
  800. MarkRequest(pAsyncReqWrapper);
  801. bRes = DeviceIoControl(
  802. ghDriverAsync,
  803. dwIoControlCode,
  804. &pAsyncReqWrapper->NdisTapiRequest,
  805. dwRequestSize,
  806. &pAsyncReqWrapper->NdisTapiRequest,
  807. dwRequestSize,
  808. &cbReturned,
  809. &pAsyncReqWrapper->Overlapped
  810. );
  811. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  812. if (bRes != TRUE) {
  813. dwLastError = GetLastError();
  814. if (dwLastError != ERROR_IO_PENDING) {
  815. TspLog(DL_ERROR, "AsyncDriverRequest: IoCtl(oid %x) failed(%d)",
  816. pAsyncReqWrapper->NdisTapiRequest.Oid, dwLastError);
  817. // the ioctl failed and was not pended
  818. // this does not trigger the completion port
  819. // so we have to cleanup here.
  820. (*gpfnCompletionProc)(pAsyncReqWrapper->dwRequestID,
  821. LINEERR_OPERATIONFAILED);
  822. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  823. }
  824. }
  825. return lRes;
  826. }
  827. //
  828. // reports to TAPI events that occur on the line or on calls on the line
  829. //
  830. VOID
  831. WINAPI
  832. ProcessEvent(
  833. PNDIS_TAPI_EVENT pEvent
  834. )
  835. {
  836. LONG lRes;
  837. ULONG ulMsg = pEvent->ulMsg;
  838. HTAPI_LINE ht_Line = (HTAPI_LINE)pEvent->htLine;
  839. HTAPI_CALL ht_Call = (HTAPI_CALL)pEvent->htCall;
  840. TspLog(DL_INFO,
  841. "ProcessEvent: event(%p), msg(%x), ht_line(%p), ht_call(%p), "\
  842. "p1(%p), p2(%p), p3(%p)",
  843. pEvent, ulMsg, ht_Line, ht_Call,
  844. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  845. switch (ulMsg)
  846. {
  847. case LINE_ADDRESSSTATE:
  848. case LINE_CLOSE:
  849. case LINE_DEVSPECIFIC:
  850. case LINE_LINEDEVSTATE:
  851. {
  852. PDRVLINE pLine;
  853. lRes = GetLineObjWithReadLock((HDRVLINE)ht_Line, &pLine);
  854. if (lRes != TAPI_SUCCESS)
  855. {
  856. break;
  857. }
  858. TspLog(DL_INFO,
  859. "PE::fnLineEvent: msg(%x), line(%p), p1(%p), p2(%p), p3(%p)",
  860. ulMsg, pLine->htLine,
  861. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  862. (*gpfnLineEvent)(pLine->htLine,
  863. (HTAPICALL)NULL,
  864. ulMsg,
  865. (DWORD_PTR)pEvent->ulParam1,
  866. (DWORD_PTR)pEvent->ulParam2,
  867. (DWORD_PTR)pEvent->ulParam3);
  868. ReleaseObjReadLock((HANDLE)ht_Line);
  869. break;
  870. }
  871. case LINE_CALLDEVSPECIFIC:
  872. case LINE_CALLINFO:
  873. {
  874. PDRVLINE pLine;
  875. PDRVCALL pCall;
  876. HDRVLINE hdLine;
  877. lRes = GetLineAndCallObjWithReadLock(ht_Line, ht_Call, &pLine, &pCall);
  878. if (lRes != TAPI_SUCCESS)
  879. {
  880. break;
  881. }
  882. hdLine = pCall->hdLine;
  883. TspLog(DL_INFO,
  884. "PE::fnLineEvent: msg(%x), htline(%p), htcall(%p), "\
  885. "p1(%p), p2(%p), p3(%p)",
  886. ulMsg, pLine->htLine, pCall->htCall,
  887. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  888. (*gpfnLineEvent)(pLine->htLine,
  889. pCall->htCall,
  890. ulMsg,
  891. (DWORD_PTR)pEvent->ulParam1,
  892. (DWORD_PTR)pEvent->ulParam2,
  893. (DWORD_PTR)pEvent->ulParam3);
  894. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  895. ReleaseObjReadLock((HANDLE)hdLine);
  896. break;
  897. }
  898. case LINE_CALLSTATE:
  899. {
  900. PDRVLINE pLine;
  901. PDRVCALL pCall;
  902. HDRVLINE hdLine;
  903. lRes = GetLineAndCallObjWithReadLock(ht_Line, ht_Call, &pLine, &pCall);
  904. // we may still receive a few events
  905. // for calls that have been closed/dropped
  906. if (lRes != TAPI_SUCCESS)
  907. {
  908. break;
  909. }
  910. hdLine = pCall->hdLine;
  911. //
  912. // for outbound calls there exists a race condition between
  913. // receiving the first call state msg(s) and receiving the
  914. // make call completion notification (if we pass a call state
  915. // msg on to tapi for a call that hasn't been completed yet
  916. // tapi will just discard the msg since the htCall really
  917. // isn't valid at that point). So if htCall references a
  918. // valid outbound call which hasn't completed yet, we'll save
  919. // the call state params, and pass them on to tapi after we
  920. // get & indicate a (successful) completion notification.
  921. //
  922. if ((OUTBOUND_CALL_KEY == pCall->dwKey) &&
  923. (TRUE == pCall->bIncomplete))
  924. {
  925. TspLog(DL_INFO,
  926. "ProcessEvent: incomplete outbound call, saving state");
  927. pCall->dwPendingCallState = (DWORD)pEvent->ulParam1;
  928. pCall->dwPendingCallStateMode = (DWORD)pEvent->ulParam2;
  929. pCall->dwPendingMediaMode = (DWORD)pEvent->ulParam3;
  930. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  931. ReleaseObjReadLock((HANDLE)hdLine);
  932. break;
  933. }
  934. if (pCall->bIdle)
  935. {
  936. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  937. ReleaseObjReadLock((HANDLE)hdLine);
  938. break;
  939. }
  940. else if (LINECALLSTATE_DISCONNECTED == pEvent->ulParam1 ||
  941. LINECALLSTATE_IDLE == pEvent->ulParam1)
  942. {
  943. HDRVCALL hdCall = pCall->hdCall;
  944. // we need to acquire a write lock to update bIdle,
  945. // make sure releasing the read lock before doing so.
  946. ReleaseObjReadLock((HANDLE)hdCall);
  947. lRes = AcquireObjWriteLock((HANDLE)hdCall);
  948. if (lRes != TAPI_SUCCESS)
  949. {
  950. TspLog(DL_WARNING,
  951. "ProcessEvent: failed to acquire write lock for call(%p)",
  952. hdCall);
  953. ReleaseObjReadLock((HANDLE)hdLine);
  954. break;
  955. }
  956. pCall->bIdle = TRUE;
  957. ReleaseObjWriteLock((HANDLE)hdCall);
  958. // reacquire the read lock
  959. lRes = AcquireObjReadLock((HANDLE)hdCall);
  960. if (lRes != TAPI_SUCCESS)
  961. {
  962. TspLog(DL_WARNING,
  963. "ProcessEvent: failed to reacquire read lock for call(%p)",
  964. hdCall);
  965. ReleaseObjReadLock((HANDLE)hdLine);
  966. break;
  967. }
  968. }
  969. TspLog(DL_INFO,
  970. "PE::fnLineEvent(CALLSTATE): htline(%p), htcall(%p), "\
  971. "p1(%p), p2(%p), p3(%p)",
  972. pLine->htLine, pCall->htCall,
  973. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  974. (*gpfnLineEvent)(pLine->htLine,
  975. pCall->htCall,
  976. ulMsg,
  977. (DWORD_PTR)pEvent->ulParam1,
  978. (DWORD_PTR)pEvent->ulParam2,
  979. (DWORD_PTR)pEvent->ulParam3);
  980. //
  981. // For old style miniports we want to indicate an IDLE
  982. // immediately following the disconnected (several of
  983. // the initial NDIS WAN miniports did not indicate an
  984. // IDLE call state due to doc confusion)
  985. //
  986. if (LINECALLSTATE_DISCONNECTED == pEvent->ulParam1)
  987. {
  988. TspLog(DL_INFO,
  989. "PE::fnLineEvent(CALLSTATE_IDLE): htline(%p), htcall(%p), p3(%p)",
  990. pLine->htLine, pCall->htCall, pEvent->ulParam3);
  991. (*gpfnLineEvent)(pLine->htLine,
  992. pCall->htCall,
  993. ulMsg,
  994. (DWORD_PTR)LINECALLSTATE_IDLE,
  995. (DWORD_PTR)0,
  996. (DWORD_PTR)pEvent->ulParam3);
  997. }
  998. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  999. ReleaseObjReadLock((HANDLE)hdLine);
  1000. break;
  1001. }
  1002. case LINE_NEWCALL:
  1003. {
  1004. HDRVCALL hdCall;
  1005. PDRVCALL pCall;
  1006. PDRVLINE pLine;
  1007. lRes = GetLineObjWithWriteLock((HDRVLINE)ht_Line, &pLine);
  1008. if (lRes != TAPI_SUCCESS)
  1009. {
  1010. break;
  1011. }
  1012. // alloc & initialize a new DRVCALL object
  1013. if (pCall = AllocCallObj(sizeof(DRVCALL)))
  1014. {
  1015. pCall->dwKey = INBOUND_CALL_KEY;
  1016. pCall->hd_Call = (HDRV_CALL)pEvent->ulParam1;
  1017. pCall->ht_Call = (HTAPI_CALL)pEvent->ulParam2;
  1018. pCall->hdLine = (HDRVLINE)ht_Line;
  1019. pCall->bIncomplete = FALSE;
  1020. }
  1021. //
  1022. // if the new call object allocation failed above then we
  1023. // want to tell the driver to drop & close the call,
  1024. // then just break
  1025. //
  1026. if (NULL == pCall)
  1027. {
  1028. PNDISTAPI_REQUEST pNdisTapiRequestDrop;
  1029. PNDISTAPI_REQUEST pNdisTapiRequestCloseCall;
  1030. PNDIS_TAPI_DROP pNdisTapiDrop;
  1031. PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
  1032. if ((lRes = PrepareSyncRequest(
  1033. OID_TAPI_DROP, // opcode
  1034. pLine->dwDeviceID, // device id
  1035. sizeof(NDIS_TAPI_DROP), // size of drve req data
  1036. &pNdisTapiRequestDrop // ptr to ptr to request buf
  1037. )) != TAPI_SUCCESS)
  1038. {
  1039. ReleaseObjWriteLock((HANDLE)ht_Line);
  1040. break;
  1041. }
  1042. pNdisTapiDrop = (PNDIS_TAPI_DROP)pNdisTapiRequestDrop->Data;
  1043. pNdisTapiDrop->hdCall = (HDRV_CALL) pEvent->ulParam1;
  1044. pNdisTapiDrop->ulUserUserInfoSize = 0;
  1045. SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequestDrop);
  1046. FreeRequest(pNdisTapiRequestDrop);
  1047. if ((lRes = PrepareSyncRequest(
  1048. OID_TAPI_CLOSE_CALL, // opcode
  1049. pLine->dwDeviceID, // device id
  1050. sizeof(NDIS_TAPI_CLOSE_CALL), // size of drve req data
  1051. &pNdisTapiRequestCloseCall // ptr to ptr to request buf
  1052. )) != TAPI_SUCCESS)
  1053. {
  1054. ReleaseObjWriteLock((HANDLE)ht_Line);
  1055. break;
  1056. }
  1057. pNdisTapiCloseCall =
  1058. (PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequestCloseCall->Data;
  1059. pNdisTapiCloseCall->hdCall = (HDRV_CALL) pEvent->ulParam1;
  1060. SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO,
  1061. pNdisTapiRequestCloseCall);
  1062. FreeRequest(pNdisTapiRequestCloseCall);
  1063. ReleaseObjWriteLock((HANDLE)ht_Line);
  1064. break;
  1065. }
  1066. ASSERT(pCall != NULL);
  1067. pCall->dwDeviceID = pLine->dwDeviceID;
  1068. // make sure releasing write lock before calling OpenObjHandle()
  1069. // to avoid deadlock on acquiring write lock for the global mapper
  1070. ReleaseObjWriteLock((HANDLE)ht_Line);
  1071. lRes = OpenObjHandle(pCall, FreeCallObj, (HANDLE *)&hdCall);
  1072. if (lRes != TAPI_SUCCESS)
  1073. {
  1074. TspLog(DL_ERROR,
  1075. "ProcessEvent: failed to map obj(%p) to handle",
  1076. pCall);
  1077. FreeCallObj(pCall);
  1078. break;
  1079. }
  1080. // reacquire the write lock
  1081. lRes = AcquireObjWriteLock((HANDLE)ht_Line);
  1082. if (lRes != TAPI_SUCCESS)
  1083. {
  1084. TspLog(DL_ERROR,
  1085. "ProcessEvent: failed to reacquire write lock for obj(%p)",
  1086. ht_Line);
  1087. CloseObjHandle((HANDLE)hdCall);
  1088. break;
  1089. }
  1090. // save the TSP handle
  1091. pCall->hdCall = hdCall;
  1092. // send the LINE_NEWCALL to TAPI, getting back the TAPI call handle
  1093. TspLog(DL_INFO,
  1094. "PE::fnLineEvent(NEWCALL): htline(%p), call(%p)",
  1095. pLine->htLine, hdCall);
  1096. (*gpfnLineEvent)(pLine->htLine,
  1097. (HTAPICALL) NULL,
  1098. LINE_NEWCALL,
  1099. (DWORD_PTR)hdCall,
  1100. (DWORD_PTR)&pCall->htCall,
  1101. 0);
  1102. //
  1103. // insert the new call into the line's inbound calls list
  1104. // regardless of the result of the LINE_NEWCALL
  1105. // if it failed, we'll destroy the call next, and
  1106. // TSPI_lineCloseCall will expect the call to be
  1107. // in the line's inbound call list
  1108. //
  1109. if ((pCall->pNext = pLine->pInboundCalls) != NULL)
  1110. {
  1111. pCall->pNext->pPrev = pCall;
  1112. }
  1113. pLine->pInboundCalls = pCall;
  1114. ReleaseObjWriteLock((HANDLE)ht_Line);
  1115. //
  1116. // if TAPI didn't create it's own representation of this
  1117. // cal (if pCall->htCall == NULL), then either:
  1118. //
  1119. // 1) the line is in the process of being closed, or
  1120. // 2) TAPI was unable to allocate the necessary resources
  1121. //
  1122. // ...so we'll close the call
  1123. //
  1124. if (NULL == pCall->htCall)
  1125. {
  1126. TspLog(DL_WARNING, "ProcessEvent: TAPI failed to create "
  1127. "its own handle for the new call, so we close the call");
  1128. TSPI_lineCloseCall(hdCall);
  1129. }
  1130. break;
  1131. }
  1132. case LINE_CREATE:
  1133. TspLog(DL_INFO,
  1134. "PE::fnLineEvent(CREATE): ghProvider(%p), p2(%p), p3(%p)",
  1135. ghProvider, pEvent->ulParam2, pEvent->ulParam3);
  1136. (*gpfnLineEvent)((HTAPILINE) NULL,
  1137. (HTAPICALL) NULL,
  1138. ulMsg,
  1139. (DWORD_PTR)ghProvider,
  1140. (DWORD_PTR)pEvent->ulParam2,
  1141. (DWORD_PTR)pEvent->ulParam3);
  1142. break;
  1143. default:
  1144. TspLog(DL_ERROR, "ProcessEvent: unknown msg(%x)", ulMsg);
  1145. break;
  1146. } // switch
  1147. }
  1148. //
  1149. // thread proc that retrieves and processes completed requests
  1150. // and async events
  1151. //
  1152. VOID
  1153. AsyncEventsThread(
  1154. LPVOID lpParams
  1155. )
  1156. {
  1157. OVERLAPPED overlapped;
  1158. DWORD cbReturned;
  1159. //
  1160. // send an IOCTL to retrieve async events
  1161. //
  1162. overlapped.hEvent = NULL; // don't need event when using completion ports
  1163. gpAsyncEventsThreadInfo->pBuf->ulTotalSize =
  1164. gpAsyncEventsThreadInfo->dwBufSize - sizeof(NDISTAPI_EVENT_DATA) + 1;
  1165. gpAsyncEventsThreadInfo->pBuf->ulUsedSize = 0;
  1166. if (DeviceIoControl(
  1167. ghDriverAsync,
  1168. IOCTL_NDISTAPI_GET_LINE_EVENTS,
  1169. gpAsyncEventsThreadInfo->pBuf,
  1170. sizeof(NDISTAPI_EVENT_DATA),
  1171. gpAsyncEventsThreadInfo->pBuf,
  1172. gpAsyncEventsThreadInfo->dwBufSize,
  1173. &cbReturned,
  1174. &overlapped
  1175. ) != TRUE)
  1176. {
  1177. DWORD dwLastError = GetLastError();
  1178. if (dwLastError != ERROR_IO_PENDING)
  1179. {
  1180. TspLog(DL_ERROR,
  1181. "AsyncEventsThread: IoCtl(GetEvent) failed(%d)",
  1182. dwLastError);
  1183. }
  1184. ASSERT(ERROR_IO_PENDING == dwLastError);
  1185. }
  1186. // loop waiting for completed requests and retrieving async events
  1187. while (1)
  1188. {
  1189. BOOL bRes;
  1190. LPOVERLAPPED lpOverlapped;
  1191. PNDIS_TAPI_EVENT pEvent;
  1192. // wait for a request to complete
  1193. while (1) {
  1194. DWORD dwNumBytesTransferred;
  1195. DWORD_PTR dwCompletionKey;
  1196. bRes = GetQueuedCompletionStatus(
  1197. ghCompletionPort,
  1198. &dwNumBytesTransferred,
  1199. &dwCompletionKey,
  1200. &lpOverlapped,
  1201. (DWORD)-1); // infinite wait
  1202. if (bRes) {
  1203. //
  1204. // GetQueuedCompletion returned success so if our
  1205. // overlapped field is non-NULL then process the
  1206. // event. If the overlapped field is NULL try
  1207. // to get another event.
  1208. //
  1209. if (lpOverlapped != NULL) {
  1210. break;
  1211. }
  1212. TspLog(DL_WARNING,
  1213. "AsyncEventsThread: GetQueuedCompletionStatus "\
  1214. "lpOverlapped == NULL!");
  1215. } else {
  1216. //
  1217. // Error returned from GetQueuedCompletionStatus so
  1218. // shutdown the thread.
  1219. //
  1220. TspLog(DL_ERROR,
  1221. "AsyncEventsThread: GetQueuedCompletionStatus "\
  1222. "failed(%d)", GetLastError());
  1223. TspLog(DL_WARNING, "AsyncEventsThread: exiting thread");
  1224. ExitThread (0);
  1225. }
  1226. }
  1227. //
  1228. // check the returned overlapped struct to determine if
  1229. // we have some events to process or a completed request
  1230. //
  1231. if (lpOverlapped == &overlapped)
  1232. {
  1233. DWORD i;
  1234. TspLog(DL_INFO, "AsyncEventsThread: got a line event");
  1235. // handle the events
  1236. pEvent = (PNDIS_TAPI_EVENT)gpAsyncEventsThreadInfo->pBuf->Data;
  1237. for (i = 0;
  1238. i < (gpAsyncEventsThreadInfo->pBuf->ulUsedSize /
  1239. sizeof(NDIS_TAPI_EVENT));
  1240. i++
  1241. )
  1242. {
  1243. ProcessEvent(pEvent);
  1244. pEvent++;
  1245. }
  1246. //
  1247. // send another IOCTL to retrieve new async events
  1248. //
  1249. overlapped.hEvent = NULL;
  1250. gpAsyncEventsThreadInfo->pBuf->ulTotalSize =
  1251. gpAsyncEventsThreadInfo->dwBufSize -
  1252. sizeof(NDISTAPI_EVENT_DATA) + 1;
  1253. gpAsyncEventsThreadInfo->pBuf->ulUsedSize = 0;
  1254. if (DeviceIoControl(
  1255. ghDriverAsync,
  1256. IOCTL_NDISTAPI_GET_LINE_EVENTS,
  1257. gpAsyncEventsThreadInfo->pBuf,
  1258. sizeof(NDISTAPI_EVENT_DATA),
  1259. gpAsyncEventsThreadInfo->pBuf,
  1260. gpAsyncEventsThreadInfo->dwBufSize,
  1261. &cbReturned,
  1262. &overlapped
  1263. ) != TRUE)
  1264. {
  1265. DWORD dwLastError = GetLastError();
  1266. if (dwLastError != ERROR_IO_PENDING) {
  1267. TspLog(DL_ERROR,
  1268. "AsyncEventsThread: IoCtl(GetEvent) failed(%d)",
  1269. dwLastError);
  1270. TspLog(DL_INFO, "AsyncEventsThread: exiting thread");
  1271. ExitThread (0);
  1272. }
  1273. }
  1274. }
  1275. else
  1276. {
  1277. LONG lRes;
  1278. DWORD dwRequestID, callStateMsgParams[5];
  1279. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper =
  1280. (PASYNC_REQUEST_WRAPPER)lpOverlapped;
  1281. TspLog(DL_INFO, "AsyncEventsThread: got a completed req");
  1282. // verify that pointer is valid
  1283. if (pAsyncReqWrapper->dwKey != ASYNCREQWRAPPER_KEY) {
  1284. TspLog(DL_WARNING, "AsyncEventsThread: got a bogus req");
  1285. continue;
  1286. }
  1287. dwRequestID = pAsyncReqWrapper->dwRequestID;
  1288. // unmark the request now that the ioctl is completed
  1289. UnmarkRequest(pAsyncReqWrapper);
  1290. lRes = TranslateDriverResult(
  1291. pAsyncReqWrapper->NdisTapiRequest.ulReturnValue
  1292. );
  1293. TspLog(DL_INFO,
  1294. "AsyncEventsThread: req(%p) with reqID(%x) returned lRes(%x)",
  1295. pAsyncReqWrapper, dwRequestID, lRes);
  1296. // call the post processing proc if appropriate
  1297. callStateMsgParams[0] = 0;
  1298. if (pAsyncReqWrapper->pfnPostProcess)
  1299. {
  1300. (*pAsyncReqWrapper->pfnPostProcess)(
  1301. pAsyncReqWrapper,
  1302. lRes,
  1303. callStateMsgParams
  1304. );
  1305. }
  1306. // free the async request wrapper
  1307. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  1308. // call completion proc
  1309. TspLog(DL_TRACE,
  1310. "AsyncEventsThread: call compproc with ReqID(%x), lRes(%x)",
  1311. dwRequestID, lRes);
  1312. (*gpfnCompletionProc)(dwRequestID, lRes);
  1313. // when outbounding call completes, we need to
  1314. // report back the saved call state
  1315. if (callStateMsgParams[0])
  1316. {
  1317. TspLog(DL_INFO,
  1318. "AsyncEventsThread: report back the saved call state");
  1319. TspLog(DL_INFO,
  1320. "AET::fnLineEvent(CALLSTATE): htline(%p), htcall(%p), "\
  1321. "p1(%p), p2(%p), p3(%p)",
  1322. callStateMsgParams[0], callStateMsgParams[1],
  1323. callStateMsgParams[2], callStateMsgParams[3],
  1324. callStateMsgParams[4]);
  1325. (*gpfnLineEvent)((HTAPILINE)ULongToPtr(callStateMsgParams[0]),
  1326. (HTAPICALL)ULongToPtr(callStateMsgParams[1]),
  1327. LINE_CALLSTATE,
  1328. (DWORD_PTR)callStateMsgParams[2],
  1329. (DWORD_PTR)callStateMsgParams[3],
  1330. (DWORD_PTR)callStateMsgParams[4]);
  1331. }
  1332. }
  1333. } // while
  1334. }
  1335. HDRV_CALL
  1336. GetNdisTapiHandle(
  1337. PDRVCALL pCall,
  1338. LONG *plRes
  1339. )
  1340. {
  1341. HDRVCALL hdCall;
  1342. PDRVCALL pCallLocal = pCall;
  1343. LONG lRes;
  1344. ASSERT(pCallLocal != NULL);
  1345. hdCall = pCall->hdCall;
  1346. if(plRes != NULL)
  1347. {
  1348. *plRes = TAPI_SUCCESS;
  1349. }
  1350. //
  1351. // if the call is outbound, wait until the make call request
  1352. // has completed so we don't send a bad NDISTAPI handle down
  1353. // to the driver
  1354. //
  1355. if (OUTBOUND_CALL_KEY == pCallLocal->dwKey)
  1356. {
  1357. ASSERT(plRes != NULL);
  1358. if (pCallLocal->bIncomplete)
  1359. {
  1360. TspLog(DL_INFO,
  1361. "GetNdisTapiHandle: wait for the outbound call to complete...");
  1362. do
  1363. {
  1364. ASSERT(plRes != NULL);
  1365. //
  1366. // Release the lock before going to sleep.
  1367. // otherwise we get into a deadlock.
  1368. //
  1369. ReleaseObjReadLock((HANDLE) hdCall);
  1370. Sleep(250);
  1371. //
  1372. // ReAcquire Lock. break if we can't
  1373. //
  1374. lRes = GetCallObjWithReadLock(hdCall, &pCallLocal);
  1375. if(lRes != TAPI_SUCCESS)
  1376. {
  1377. *plRes = lRes;
  1378. break;
  1379. }
  1380. } while (pCallLocal->bIncomplete);
  1381. }
  1382. }
  1383. return pCall->hd_Call;
  1384. }
  1385. DWORD
  1386. GetDestAddressLength(
  1387. LPCWSTR lpszDestAddress,
  1388. DWORD dwOrgDALength,
  1389. UINT *pCodePage
  1390. )
  1391. {
  1392. DWORD dwLength;
  1393. ASSERT(lpszDestAddress != NULL);
  1394. ASSERT(pCodePage != NULL);
  1395. if (*pCodePage == CP_ACP)
  1396. {
  1397. // If code page is CP_ACP, return the original length to
  1398. // keep the old behavior.
  1399. dwLength = dwOrgDALength;
  1400. }
  1401. else
  1402. {
  1403. dwLength = WideCharToMultiByte(
  1404. *pCodePage,
  1405. 0,
  1406. lpszDestAddress,
  1407. dwOrgDALength,
  1408. NULL,
  1409. 0,
  1410. NULL,
  1411. NULL
  1412. );
  1413. if (dwLength == 0)
  1414. {
  1415. // WideCharToMultiByte() failed, use CP_ACP to show
  1416. // the old behavior.
  1417. *pCodePage = CP_ACP;
  1418. dwLength = dwOrgDALength;
  1419. }
  1420. }
  1421. return dwLength;
  1422. }
  1423. //
  1424. // TSPI_lineXXX functions
  1425. //
  1426. LONG
  1427. TSPIAPI
  1428. TSPI_lineAccept(
  1429. DRV_REQUESTID dwRequestID,
  1430. HDRVCALL hdCall,
  1431. LPCSTR lpsUserUserInfo,
  1432. DWORD dwSize
  1433. )
  1434. {
  1435. static DWORD dwSum = 0;
  1436. LONG lRes;
  1437. PDRVCALL pCall;
  1438. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1439. PNDIS_TAPI_ACCEPT pNdisTapiAccept;
  1440. TspLog(DL_TRACE, "lineAccept(%d): reqID(%x), call(%p)",
  1441. ++dwSum, dwRequestID, hdCall);
  1442. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1443. if (lRes != TAPI_SUCCESS)
  1444. {
  1445. return lRes;
  1446. }
  1447. if ((lRes = PrepareAsyncRequest(
  1448. OID_TAPI_ACCEPT, // opcode
  1449. pCall->dwDeviceID, // device id
  1450. dwRequestID, // request id
  1451. sizeof(NDIS_TAPI_ACCEPT) + dwSize, // size of drv request data
  1452. &pAsyncReqWrapper // ptr to ptr to request buf
  1453. )) != TAPI_SUCCESS)
  1454. {
  1455. ReleaseObjReadLock((HANDLE)hdCall);
  1456. return lRes;
  1457. }
  1458. pNdisTapiAccept =
  1459. (PNDIS_TAPI_ACCEPT)pAsyncReqWrapper->NdisTapiRequest.Data;
  1460. pNdisTapiAccept->hdCall = GetNdisTapiHandle(pCall, NULL);
  1461. if ((pNdisTapiAccept->ulUserUserInfoSize = dwSize) != 0)
  1462. {
  1463. CopyMemory(pNdisTapiAccept->UserUserInfo, lpsUserUserInfo, dwSize);
  1464. }
  1465. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  1466. ReleaseObjReadLock((HANDLE)hdCall);
  1467. return lRes;
  1468. }
  1469. LONG
  1470. TSPIAPI
  1471. TSPI_lineAnswer(
  1472. DRV_REQUESTID dwRequestID,
  1473. HDRVCALL hdCall,
  1474. LPCSTR lpsUserUserInfo,
  1475. DWORD dwSize
  1476. )
  1477. {
  1478. static DWORD dwSum = 0;
  1479. LONG lRes;
  1480. PDRVCALL pCall;
  1481. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1482. PNDIS_TAPI_ANSWER pNdisTapiAnswer;
  1483. TspLog(DL_TRACE, "lineAnswer(%d): reqID(%x), call(%p)",
  1484. ++dwSum, dwRequestID, hdCall);
  1485. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1486. if (lRes != TAPI_SUCCESS)
  1487. {
  1488. return lRes;
  1489. }
  1490. if ((lRes = PrepareAsyncRequest(
  1491. OID_TAPI_ANSWER, // opcode
  1492. pCall->dwDeviceID, // device id
  1493. dwRequestID, // request id
  1494. sizeof(NDIS_TAPI_ANSWER) + dwSize, // size of drv request data
  1495. &pAsyncReqWrapper // ptr to ptr to request buf
  1496. )) != TAPI_SUCCESS)
  1497. {
  1498. ReleaseObjReadLock((HANDLE)hdCall);
  1499. return lRes;
  1500. }
  1501. pNdisTapiAnswer =
  1502. (PNDIS_TAPI_ANSWER)pAsyncReqWrapper->NdisTapiRequest.Data;
  1503. pNdisTapiAnswer->hdCall = GetNdisTapiHandle(pCall, NULL);
  1504. if ((pNdisTapiAnswer->ulUserUserInfoSize = dwSize) != 0)
  1505. {
  1506. CopyMemory(pNdisTapiAnswer->UserUserInfo, lpsUserUserInfo, dwSize);
  1507. }
  1508. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  1509. ReleaseObjReadLock((HANDLE)hdCall);
  1510. return lRes;
  1511. }
  1512. LONG
  1513. TSPIAPI
  1514. TSPI_lineClose(
  1515. HDRVLINE hdLine
  1516. )
  1517. {
  1518. static DWORD dwSum = 0;
  1519. LONG lRes;
  1520. PDRVLINE pLine;
  1521. PNDISTAPI_REQUEST pNdisTapiRequest;
  1522. PNDIS_TAPI_CLOSE pNdisTapiClose;
  1523. TspLog(DL_TRACE, "lineClose(%d): line(%p)", ++dwSum, hdLine);
  1524. lRes = GetLineObjWithWriteLock(hdLine, &pLine);
  1525. if (lRes != TAPI_SUCCESS)
  1526. {
  1527. return lRes;
  1528. }
  1529. if ((lRes = PrepareSyncRequest(
  1530. OID_TAPI_CLOSE, // opcode
  1531. pLine->dwDeviceID, // device id
  1532. sizeof(NDIS_TAPI_CLOSE), // size of drve req data
  1533. &pNdisTapiRequest // ptr to ptr to request buffer
  1534. )) != TAPI_SUCCESS)
  1535. {
  1536. ReleaseObjWriteLock((HANDLE)hdLine);
  1537. return lRes;
  1538. }
  1539. pNdisTapiClose = (PNDIS_TAPI_CLOSE)pNdisTapiRequest->Data;
  1540. // mark line as invalid so any related events that show up
  1541. // will be discarded.
  1542. pLine->dwKey = INVALID_KEY;
  1543. pNdisTapiClose->hdLine = pLine->hd_Line;
  1544. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  1545. FreeRequest(pNdisTapiRequest);
  1546. if (TAPI_SUCCESS == lRes)
  1547. {
  1548. lRes = DecommitNegotiatedTSPIVersion(pLine->dwDeviceID);
  1549. }
  1550. ReleaseObjWriteLock((HANDLE)hdLine);
  1551. // release line resources
  1552. CloseObjHandle((HANDLE)hdLine);
  1553. return lRes;
  1554. }
  1555. LONG
  1556. TSPIAPI
  1557. TSPI_lineCloseCall(
  1558. HDRVCALL hdCall
  1559. )
  1560. {
  1561. static DWORD dwSum = 0;
  1562. LONG lRes;
  1563. HDRVLINE hdLine;
  1564. PDRVLINE pLine;
  1565. PDRVCALL pCall;
  1566. PNDISTAPI_REQUEST pNdisTapiRequestCloseCall;
  1567. PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
  1568. BOOL bInboundCall;
  1569. HDRV_CALL NdisTapiHandle;
  1570. TspLog(DL_TRACE, "lineCloseCall(%d): call(%p)", ++dwSum, hdCall);
  1571. lRes = GetLineHandleFromCallHandle(hdCall, &hdLine);
  1572. if (lRes != TAPI_SUCCESS)
  1573. {
  1574. return lRes;
  1575. }
  1576. //
  1577. // Initially we can't acquire the write lock directly
  1578. // because we might spin-wait in GetNdisTapiHandle so
  1579. // we grab the readlock instead.
  1580. //
  1581. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  1582. if (lRes != TAPI_SUCCESS)
  1583. {
  1584. return lRes;
  1585. }
  1586. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1587. if (lRes != TAPI_SUCCESS)
  1588. {
  1589. ReleaseObjReadLock((HANDLE)hdLine);
  1590. return lRes;
  1591. }
  1592. bInboundCall = (INBOUND_CALL_KEY == pCall->dwKey);
  1593. NdisTapiHandle = GetNdisTapiHandle(pCall, &lRes);
  1594. if(lRes != TAPI_SUCCESS)
  1595. {
  1596. ReleaseObjReadLock((HANDLE) hdLine);
  1597. return lRes;
  1598. }
  1599. ReleaseObjReadLock((HANDLE)hdCall);
  1600. ReleaseObjReadLock((HANDLE)hdLine);
  1601. //
  1602. // Now acquire the write lock
  1603. //
  1604. lRes = AcquireObjWriteLock((HANDLE)hdLine);
  1605. if (lRes != TAPI_SUCCESS) {
  1606. return lRes;
  1607. }
  1608. lRes = AcquireObjWriteLock((HANDLE)hdCall);
  1609. if (lRes != TAPI_SUCCESS) {
  1610. ReleaseObjWriteLock((HANDLE)hdLine);
  1611. return lRes;
  1612. }
  1613. if ((lRes = PrepareSyncRequest(
  1614. OID_TAPI_CLOSE_CALL, // opcode
  1615. pCall->dwDeviceID, // device id
  1616. sizeof(NDIS_TAPI_CLOSE_CALL), // size of drve req data
  1617. &pNdisTapiRequestCloseCall // ptr to ptr to request buffer
  1618. )) != TAPI_SUCCESS)
  1619. {
  1620. ReleaseObjWriteLock((HANDLE)hdCall);
  1621. ReleaseObjWriteLock((HANDLE)hdLine);
  1622. return lRes;
  1623. }
  1624. // @@@ for legacy NDISWAN ISDN miniports:
  1625. // since there's no more "automatic" call dropping in
  1626. // TAPI when an app has closed the line & there are
  1627. // existing non-IDLE calls, legacy NDIS WAN ISDN miniports
  1628. // rely on seeing an OID_TAPI_DROP, we need to synthesize
  1629. // this behavior if the call has not previously be dropped.
  1630. if (!pCall->bDropped)
  1631. {
  1632. PNDISTAPI_REQUEST pNdisTapiRequestDrop;
  1633. PNDIS_TAPI_DROP pNdisTapiDrop;
  1634. TspLog(DL_INFO, "lineCloseCall: synthesize DROP req");
  1635. if ((lRes = PrepareSyncRequest(
  1636. OID_TAPI_DROP, // opcode
  1637. pCall->dwDeviceID, // device id
  1638. sizeof(NDIS_TAPI_DROP), // size of drve req data
  1639. &pNdisTapiRequestDrop // ptr to ptr to request buffer
  1640. )) != TAPI_SUCCESS)
  1641. {
  1642. FreeRequest(pNdisTapiRequestCloseCall);
  1643. ReleaseObjWriteLock((HANDLE)hdCall);
  1644. ReleaseObjWriteLock((HANDLE)hdLine);
  1645. return lRes;
  1646. }
  1647. pNdisTapiDrop = (PNDIS_TAPI_DROP)pNdisTapiRequestDrop->Data;
  1648. pNdisTapiDrop->hdCall = NdisTapiHandle;
  1649. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequestDrop);
  1650. // done with the drop sync req
  1651. FreeRequest(pNdisTapiRequestDrop);
  1652. if (lRes != TAPI_SUCCESS)
  1653. {
  1654. FreeRequest(pNdisTapiRequestCloseCall);
  1655. ReleaseObjWriteLock((HANDLE)hdCall);
  1656. ReleaseObjWriteLock((HANDLE)hdLine);
  1657. return lRes;
  1658. }
  1659. }
  1660. // mark the call as bad so any events get discarded
  1661. pCall->dwKey = INVALID_KEY;
  1662. // set up the params & call the driver
  1663. pNdisTapiCloseCall = (PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequestCloseCall->Data;
  1664. pNdisTapiCloseCall->hdCall = NdisTapiHandle;
  1665. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO,
  1666. pNdisTapiRequestCloseCall);
  1667. FreeRequest(pNdisTapiRequestCloseCall);
  1668. // if inbound call, remove it from the list
  1669. if (bInboundCall)
  1670. {
  1671. if (pCall->pNext)
  1672. {
  1673. pCall->pNext->pPrev = pCall->pPrev;
  1674. }
  1675. if (pCall->pPrev)
  1676. {
  1677. pCall->pPrev->pNext = pCall->pNext;
  1678. }
  1679. else
  1680. {
  1681. pLine->pInboundCalls = pCall->pNext;
  1682. }
  1683. }
  1684. ReleaseObjWriteLock((HANDLE)hdCall);
  1685. ReleaseObjWriteLock((HANDLE)hdLine);
  1686. // free the call struct now that the call is closed
  1687. CloseObjHandle((HANDLE)hdCall);
  1688. return lRes;
  1689. }
  1690. LONG
  1691. TSPIAPI
  1692. TSPI_lineConditionalMediaDetection(
  1693. HDRVLINE hdLine,
  1694. DWORD dwMediaModes,
  1695. LPLINECALLPARAMS const lpCallParams
  1696. )
  1697. {
  1698. static DWORD dwSum = 0;
  1699. LONG lRes;
  1700. PDRVLINE pLine;
  1701. PNDISTAPI_REQUEST pNdisTapiRequest;
  1702. PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION pNdisTapiConditionalMediaDetection;
  1703. TspLog(DL_TRACE, "lineConditionalMediaDetection(%d): line(%p), mode(%x)",
  1704. ++dwSum, hdLine, dwMediaModes);
  1705. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  1706. if (lRes != TAPI_SUCCESS)
  1707. {
  1708. return lRes;
  1709. }
  1710. if ((lRes = PrepareSyncRequest(
  1711. OID_TAPI_CONDITIONAL_MEDIA_DETECTION, // opcode
  1712. pLine->dwDeviceID, // device id
  1713. sizeof(NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) +
  1714. (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)),
  1715. &pNdisTapiRequest // ptr to ptr to
  1716. // req buffer
  1717. )) != TAPI_SUCCESS)
  1718. {
  1719. ReleaseObjReadLock((HANDLE)hdLine);
  1720. return lRes;
  1721. }
  1722. pNdisTapiConditionalMediaDetection =
  1723. (PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) pNdisTapiRequest->Data;
  1724. pNdisTapiConditionalMediaDetection->hdLine = pLine->hd_Line;
  1725. pNdisTapiConditionalMediaDetection->ulMediaModes = dwMediaModes;
  1726. CopyMemory(
  1727. &pNdisTapiConditionalMediaDetection->LineCallParams,
  1728. lpCallParams,
  1729. lpCallParams->dwTotalSize
  1730. );
  1731. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  1732. FreeRequest(pNdisTapiRequest);
  1733. ReleaseObjReadLock((HANDLE)hdLine);
  1734. return lRes;
  1735. }
  1736. LONG
  1737. PASCAL
  1738. TSPI_lineDevSpecific_postProcess(
  1739. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  1740. LONG lRes,
  1741. PDWORD_PTR callStateMsgParams
  1742. )
  1743. {
  1744. TspLog(DL_TRACE, "lineDevSpecific_post: lRes(%x)", lRes);
  1745. if (TAPI_SUCCESS == lRes)
  1746. {
  1747. PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =
  1748. (PNDIS_TAPI_DEV_SPECIFIC)pAsyncReqWrapper->NdisTapiRequest.Data;
  1749. CopyMemory(
  1750. (LPVOID) pAsyncReqWrapper->dwRequestSpecific,
  1751. pNdisTapiDevSpecific->Params,
  1752. pNdisTapiDevSpecific->ulParamsSize
  1753. );
  1754. }
  1755. return lRes;
  1756. }
  1757. LONG
  1758. TSPIAPI
  1759. TSPI_lineDevSpecific(
  1760. DRV_REQUESTID dwRequestID,
  1761. HDRVLINE hdLine,
  1762. DWORD dwAddressID,
  1763. HDRVCALL hdCall,
  1764. LPVOID lpParams,
  1765. DWORD dwSize
  1766. )
  1767. {
  1768. static DWORD dwSum = 0;
  1769. LONG lRes;
  1770. PDRVLINE pLine;
  1771. PDRVCALL pCall = NULL;
  1772. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1773. PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific;
  1774. TspLog(DL_TRACE,
  1775. "lineDevSpecific(%d): reqID(%x), line(%p), addressID(%x), call(%p)",
  1776. ++dwSum, dwRequestID, hdLine, dwAddressID, hdCall);
  1777. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  1778. if (lRes != TAPI_SUCCESS)
  1779. {
  1780. return lRes;
  1781. }
  1782. if ((lRes = PrepareAsyncRequest(
  1783. OID_TAPI_DEV_SPECIFIC, // opcode
  1784. pLine->dwDeviceID, // device id
  1785. dwRequestID, // request id
  1786. sizeof(NDIS_TAPI_DEV_SPECIFIC) + // size of drv request data
  1787. (dwSize - 1),
  1788. &pAsyncReqWrapper // ptr to ptr to request buffer
  1789. )) != TAPI_SUCCESS)
  1790. {
  1791. ReleaseObjReadLock((HANDLE)hdLine);
  1792. return lRes;
  1793. }
  1794. pNdisTapiDevSpecific =
  1795. (PNDIS_TAPI_DEV_SPECIFIC)pAsyncReqWrapper->NdisTapiRequest.Data;
  1796. pNdisTapiDevSpecific->hdLine = pLine->hd_Line;
  1797. pNdisTapiDevSpecific->ulAddressID = dwAddressID;
  1798. if (hdCall)
  1799. {
  1800. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1801. if (lRes != TAPI_SUCCESS)
  1802. {
  1803. FreeRequest(pAsyncReqWrapper);
  1804. ReleaseObjReadLock((HANDLE)hdLine);
  1805. return lRes;
  1806. }
  1807. pNdisTapiDevSpecific->hdCall = GetNdisTapiHandle(pCall, &lRes);
  1808. if(lRes != TAPI_SUCCESS)
  1809. {
  1810. FreeRequest(pAsyncReqWrapper);
  1811. return lRes;
  1812. }
  1813. }
  1814. else
  1815. {
  1816. pNdisTapiDevSpecific->hdCall = (HDRV_CALL)NULL;
  1817. }
  1818. pNdisTapiDevSpecific->ulParamsSize = dwSize;
  1819. CopyMemory(pNdisTapiDevSpecific->Params, lpParams, dwSize);
  1820. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)lpParams;
  1821. pAsyncReqWrapper->pfnPostProcess = TSPI_lineDevSpecific_postProcess;
  1822. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pAsyncReqWrapper);
  1823. if (pCall != NULL)
  1824. {
  1825. ReleaseObjReadLock((HANDLE)hdCall);
  1826. }
  1827. ReleaseObjReadLock((HANDLE)hdLine);
  1828. return lRes;
  1829. }
  1830. LONG
  1831. TSPIAPI
  1832. TSPI_lineDial(
  1833. DRV_REQUESTID dwRequestID,
  1834. HDRVCALL hdCall,
  1835. LPCWSTR lpszDestAddress,
  1836. DWORD dwCountryCode
  1837. )
  1838. {
  1839. static DWORD dwSum = 0;
  1840. LONG lRes;
  1841. PDRVCALL pCall;
  1842. DWORD dwLength = lstrlenW (lpszDestAddress) + 1;
  1843. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1844. PNDIS_TAPI_DIAL pNdisTapiDial;
  1845. TspLog(DL_TRACE, "lineDial(%d): reqID(%x), call(%p)",
  1846. ++dwSum, dwRequestID, hdCall);
  1847. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1848. if (lRes != TAPI_SUCCESS)
  1849. {
  1850. return lRes;
  1851. }
  1852. if ((lRes = PrepareAsyncRequest(
  1853. OID_TAPI_DIAL, // opcode
  1854. pCall->dwDeviceID, // device id
  1855. dwRequestID, // request id
  1856. sizeof(NDIS_TAPI_DIAL) + dwLength, // size of driver req buffer
  1857. &pAsyncReqWrapper // ptr to ptr to req buffer
  1858. )) != TAPI_SUCCESS)
  1859. {
  1860. ReleaseObjReadLock((HANDLE)hdCall);
  1861. return lRes;
  1862. }
  1863. pNdisTapiDial =
  1864. (PNDIS_TAPI_DIAL)pAsyncReqWrapper->NdisTapiRequest.Data;
  1865. pNdisTapiDial->hdCall = GetNdisTapiHandle(pCall, &lRes);
  1866. if(lRes != TAPI_SUCCESS)
  1867. {
  1868. FreeRequest(pAsyncReqWrapper);
  1869. return lRes;
  1870. }
  1871. pNdisTapiDial->ulDestAddressSize = dwLength;
  1872. WideCharToMultiByte(CP_ACP, 0, lpszDestAddress,
  1873. -1, (LPSTR)pNdisTapiDial->szDestAddress,
  1874. dwLength, NULL, NULL);
  1875. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  1876. ReleaseObjReadLock((HANDLE)hdCall);
  1877. return lRes;
  1878. }
  1879. LONG
  1880. PASCAL
  1881. TSPI_lineDrop_postProcess(
  1882. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  1883. LONG lRes,
  1884. PDWORD_PTR callStateMsgParams
  1885. )
  1886. {
  1887. BOOL bSendCallStateIdleMsg = FALSE;
  1888. LONG lSuc;
  1889. HDRVLINE hdLine;
  1890. HDRVCALL hdCall;
  1891. PDRVLINE pLine;
  1892. PDRVCALL pCall;
  1893. HTAPILINE htLine;
  1894. HTAPICALL htCall;
  1895. TspLog(DL_TRACE, "lineDrop_post: lRes(%x)", lRes);
  1896. hdCall = (HDRVCALL)(pAsyncReqWrapper->dwRequestSpecific);
  1897. lSuc = GetLineHandleFromCallHandle(hdCall, &hdLine);
  1898. if (lSuc != TAPI_SUCCESS)
  1899. {
  1900. return lSuc;
  1901. }
  1902. lSuc = GetLineObjWithReadLock(hdLine, &pLine);
  1903. if (lSuc != TAPI_SUCCESS)
  1904. {
  1905. return lSuc;
  1906. }
  1907. lSuc = GetCallObjWithWriteLock(hdCall, &pCall);
  1908. if (lSuc != TAPI_SUCCESS)
  1909. {
  1910. ReleaseObjReadLock((HANDLE)hdLine);
  1911. return lSuc;
  1912. }
  1913. //
  1914. // @@@ Some old-style miniports, notably pcimac, don't indicate
  1915. // IDLE msgs when they get a drop request- so we synthesize this
  1916. // for them (only if and IDLE hasn't already been sent)
  1917. //
  1918. if (TAPI_SUCCESS == lRes)
  1919. {
  1920. ASSERT(INBOUND_CALL_KEY == pCall->dwKey ||
  1921. OUTBOUND_CALL_KEY == pCall->dwKey);
  1922. htCall = pCall->htCall;
  1923. htLine = pLine->htLine;
  1924. if (!pCall->bIdle)
  1925. {
  1926. pCall->bIdle = bSendCallStateIdleMsg = TRUE;
  1927. }
  1928. if (bSendCallStateIdleMsg)
  1929. {
  1930. TspLog(DL_INFO,
  1931. "postDrop::fnLineEvent(CALLSTATE_IDLE): htline(%p), htcall(%p)",
  1932. htLine, htCall);
  1933. (*gpfnLineEvent)(htLine,
  1934. htCall,
  1935. LINE_CALLSTATE,
  1936. LINECALLSTATE_IDLE,
  1937. 0,
  1938. 0);
  1939. }
  1940. }
  1941. ReleaseObjWriteLock((HANDLE)hdCall);
  1942. ReleaseObjReadLock((HANDLE)hdLine);
  1943. return lRes;
  1944. }
  1945. LONG
  1946. TSPIAPI
  1947. TSPI_lineDrop(
  1948. DRV_REQUESTID dwRequestID,
  1949. HDRVCALL hdCall,
  1950. LPCSTR lpsUserUserInfo,
  1951. DWORD dwSize
  1952. )
  1953. {
  1954. static DWORD dwSum = 0;
  1955. LONG lRes;
  1956. PDRVCALL pCall;
  1957. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1958. PNDIS_TAPI_DROP pNdisTapiDrop;
  1959. HDRV_CALL NdisTapiHandle;
  1960. TspLog(DL_TRACE, "lineDrop(%d): reqID(%x), call(%p)",
  1961. ++dwSum, dwRequestID, hdCall);
  1962. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1963. if (lRes != TAPI_SUCCESS)
  1964. {
  1965. return lRes;
  1966. }
  1967. NdisTapiHandle = GetNdisTapiHandle(pCall, &lRes);
  1968. if(lRes != TAPI_SUCCESS)
  1969. {
  1970. return lRes;
  1971. }
  1972. ReleaseObjReadLock((HANDLE)hdCall);
  1973. lRes = AcquireObjWriteLock((HANDLE)hdCall);
  1974. if (lRes != TAPI_SUCCESS) {
  1975. return lRes;
  1976. }
  1977. if ((lRes = PrepareAsyncRequest(
  1978. OID_TAPI_DROP, // opcode
  1979. pCall->dwDeviceID, // device id
  1980. dwRequestID, // request id
  1981. sizeof(NDIS_TAPI_DROP) + dwSize, // size of driver req buffer
  1982. &pAsyncReqWrapper // ptr to ptr to req buffer
  1983. )) != TAPI_SUCCESS)
  1984. {
  1985. ReleaseObjWriteLock((HANDLE)hdCall);
  1986. return lRes;
  1987. }
  1988. pNdisTapiDrop =
  1989. (PNDIS_TAPI_DROP)pAsyncReqWrapper->NdisTapiRequest.Data;
  1990. pNdisTapiDrop->hdCall = NdisTapiHandle;
  1991. //
  1992. // @@@: the following is for legacy NDISWAN ISDN miniports
  1993. //
  1994. // Safely mark the call as dropped so the CloseCall code
  1995. // won't follow up with another "automatic" drop
  1996. //
  1997. pCall->bDropped = TRUE;
  1998. if ((pNdisTapiDrop->ulUserUserInfoSize = dwSize) != 0)
  1999. {
  2000. CopyMemory(pNdisTapiDrop->UserUserInfo, lpsUserUserInfo, dwSize);
  2001. }
  2002. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)hdCall;
  2003. pAsyncReqWrapper->pfnPostProcess = TSPI_lineDrop_postProcess;
  2004. ReleaseObjWriteLock((HANDLE)hdCall);
  2005. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  2006. return lRes;
  2007. }
  2008. LONG
  2009. TSPIAPI
  2010. TSPI_lineGetAddressCaps(
  2011. DWORD dwDeviceID,
  2012. DWORD dwAddressID,
  2013. DWORD dwTSPIVersion,
  2014. DWORD dwExtVersion,
  2015. LPLINEADDRESSCAPS lpAddressCaps
  2016. )
  2017. {
  2018. static DWORD dwSum = 0;
  2019. LONG lRes;
  2020. PNDISTAPI_REQUEST pNdisTapiRequest;
  2021. PLINE_ADDRESS_CAPS pCaps;
  2022. PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps;
  2023. TspLog(DL_TRACE,
  2024. "lineGetAddressCaps(%d): deviceID(%x), addressID(%x), "\
  2025. "TSPIV(%x), ExtV(%x)",
  2026. ++dwSum, dwDeviceID, dwAddressID);
  2027. if ((lRes = PrepareSyncRequest(
  2028. OID_TAPI_GET_ADDRESS_CAPS, // opcode
  2029. dwDeviceID, // device id
  2030. sizeof(NDIS_TAPI_GET_ADDRESS_CAPS) + // size of req data
  2031. (lpAddressCaps->dwTotalSize - sizeof(LINE_ADDRESS_CAPS)),
  2032. &pNdisTapiRequest // ptr to ptr to req buf
  2033. )) != TAPI_SUCCESS)
  2034. {
  2035. return lRes;
  2036. }
  2037. pNdisTapiGetAddressCaps =
  2038. (PNDIS_TAPI_GET_ADDRESS_CAPS)pNdisTapiRequest->Data;
  2039. pNdisTapiGetAddressCaps->ulDeviceID = dwDeviceID;
  2040. pNdisTapiGetAddressCaps->ulAddressID = dwAddressID;
  2041. pNdisTapiGetAddressCaps->ulExtVersion = dwExtVersion;
  2042. pCaps = &pNdisTapiGetAddressCaps->LineAddressCaps;
  2043. pCaps->ulTotalSize = lpAddressCaps->dwTotalSize;
  2044. pCaps->ulNeededSize = pCaps->ulUsedSize = sizeof (LINE_ADDRESS_CAPS);
  2045. ZeroMemory(
  2046. &pCaps->ulLineDeviceID,
  2047. sizeof(LINE_ADDRESS_CAPS) - 3 * sizeof(ULONG)
  2048. );
  2049. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2050. if (lRes != TAPI_SUCCESS)
  2051. {
  2052. FreeRequest(pNdisTapiRequest);
  2053. return lRes;
  2054. }
  2055. //
  2056. // Do some post processing to the returned data structure
  2057. // before passing it back to tapi:
  2058. // 1. Pad the area between the fixed 1.0 structure and the
  2059. // var data that the miniports pass back with 0's so a
  2060. // bad app that disregards the 1.0 version negotiation &
  2061. // references new 1.4 or 2.0 structure fields won't blow up
  2062. // 2. Convert ascii strings to unicode, & rebase all var data
  2063. //
  2064. //
  2065. // The real needed size is the sum of that requested by the
  2066. // underlying driver, plus padding for the new TAPI 1.4/2.0
  2067. // structure fields, plus the size of the var data returned
  2068. // by the driver to account for the ascii->unicode conversion.
  2069. // @@@ Granted, we are very liberal in computing the value for
  2070. // this last part, but at least this way it's fast & we'll
  2071. // never have too little buffer space.
  2072. //
  2073. lpAddressCaps->dwNeededSize =
  2074. pCaps->ulNeededSize +
  2075. (sizeof(LINEADDRESSCAPS) - // v2.0 struct
  2076. sizeof(LINE_ADDRESS_CAPS)) + // v1.0 struct
  2077. (pCaps->ulNeededSize - sizeof(LINE_ADDRESS_CAPS));
  2078. //
  2079. // Copy over the fixed fields that don't need changing, i.e.
  2080. // everything from dwAddressSharing to dwCallCompletionModes
  2081. //
  2082. lpAddressCaps->dwLineDeviceID = dwDeviceID;
  2083. CopyMemory(
  2084. &lpAddressCaps->dwAddressSharing,
  2085. &pCaps->ulAddressSharing,
  2086. sizeof(LINE_ADDRESS_CAPS) - (12 * sizeof(DWORD))
  2087. );
  2088. if (lpAddressCaps->dwNeededSize > lpAddressCaps->dwTotalSize)
  2089. {
  2090. lpAddressCaps->dwUsedSize =
  2091. (lpAddressCaps->dwTotalSize < sizeof(LINEADDRESSCAPS) ?
  2092. lpAddressCaps->dwTotalSize : sizeof(LINEADDRESSCAPS));
  2093. }
  2094. else
  2095. {
  2096. lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS); // v2.0 struct
  2097. INSERTVARDATASTRING(
  2098. pCaps,
  2099. &pCaps->ulAddressSize,
  2100. lpAddressCaps,
  2101. &lpAddressCaps->dwAddressSize,
  2102. sizeof(LINE_ADDRESS_CAPS),
  2103. "LINE_ADDRESS_CAPS.Address"
  2104. );
  2105. INSERTVARDATA(
  2106. pCaps,
  2107. &pCaps->ulDevSpecificSize,
  2108. lpAddressCaps,
  2109. &lpAddressCaps->dwDevSpecificSize,
  2110. sizeof(LINE_ADDRESS_CAPS),
  2111. "LINE_ADDRESS_CAPS.DevSpecific"
  2112. );
  2113. if (pCaps->ulCompletionMsgTextSize != 0)
  2114. {
  2115. // @@@ convert ComplMsgText to unicode???
  2116. INSERTVARDATA(
  2117. pCaps,
  2118. &pCaps->ulCompletionMsgTextSize,
  2119. lpAddressCaps,
  2120. &lpAddressCaps->dwCompletionMsgTextSize,
  2121. sizeof (LINE_ADDRESS_CAPS),
  2122. "LINE_ADDRESS_CAPS.CompletionMsgText"
  2123. );
  2124. lpAddressCaps->dwNumCompletionMessages =
  2125. pCaps->ulNumCompletionMessages;
  2126. lpAddressCaps->dwCompletionMsgTextEntrySize =
  2127. pCaps->ulCompletionMsgTextEntrySize;
  2128. }
  2129. // make sure dwNeededSize == dwUsedSize
  2130. lpAddressCaps->dwNeededSize = lpAddressCaps->dwUsedSize;
  2131. }
  2132. FreeRequest(pNdisTapiRequest);
  2133. return lRes;
  2134. }
  2135. LONG
  2136. TSPIAPI
  2137. TSPI_lineGetAddressID(
  2138. HDRVLINE hdLine,
  2139. LPDWORD lpdwAddressID,
  2140. DWORD dwAddressMode,
  2141. LPCWSTR lpsAddress,
  2142. DWORD dwSize
  2143. )
  2144. {
  2145. static DWORD dwSum = 0;
  2146. LONG lRes;
  2147. PDRVLINE pLine;
  2148. PNDISTAPI_REQUEST pNdisTapiRequest;
  2149. PNDIS_TAPI_GET_ADDRESS_ID pNdisTapiGetAddressID;
  2150. TspLog(DL_TRACE, "lineGetAddressID(%d): line(%p), addressMode(%x)",
  2151. ++dwSum, hdLine, dwAddressMode);
  2152. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  2153. if (lRes != TAPI_SUCCESS)
  2154. {
  2155. return lRes;
  2156. }
  2157. if ((lRes = PrepareSyncRequest(
  2158. OID_TAPI_GET_ADDRESS_ID, // opcode
  2159. pLine->dwDeviceID, // device id
  2160. sizeof(NDIS_TAPI_GET_ADDRESS_ID) + // size of req data
  2161. dwSize / 2 - 1,
  2162. &pNdisTapiRequest // ptr to ptr to req buf
  2163. )) != TAPI_SUCCESS)
  2164. {
  2165. ReleaseObjReadLock((HANDLE)hdLine);
  2166. return lRes;
  2167. }
  2168. pNdisTapiGetAddressID = (PNDIS_TAPI_GET_ADDRESS_ID)pNdisTapiRequest->Data;
  2169. pNdisTapiGetAddressID->hdLine = pLine->hd_Line;
  2170. pNdisTapiGetAddressID->ulAddressMode = dwAddressMode;
  2171. pNdisTapiGetAddressID->ulAddressSize = dwSize / 2;
  2172. WideCharToMultiByte(CP_ACP, 0, lpsAddress, dwSize,
  2173. (LPSTR)pNdisTapiGetAddressID->szAddress, dwSize / 2, NULL, NULL);
  2174. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2175. if (TAPI_SUCCESS == lRes)
  2176. {
  2177. *lpdwAddressID = pNdisTapiGetAddressID->ulAddressID;
  2178. TspLog(DL_INFO, "lineGetAddressID: addressID(%x)", *lpdwAddressID);
  2179. }
  2180. FreeRequest(pNdisTapiRequest);
  2181. ReleaseObjReadLock((HANDLE)hdLine);
  2182. return lRes;
  2183. }
  2184. LONG
  2185. TSPIAPI
  2186. TSPI_lineGetAddressStatus(
  2187. HDRVLINE hdLine,
  2188. DWORD dwAddressID,
  2189. LPLINEADDRESSSTATUS lpAddressStatus
  2190. )
  2191. {
  2192. static DWORD dwSum = 0;
  2193. LONG lRes;
  2194. PDRVLINE pLine;
  2195. PNDISTAPI_REQUEST pNdisTapiRequest;
  2196. PLINE_ADDRESS_STATUS pStatus;
  2197. PNDIS_TAPI_GET_ADDRESS_STATUS pNdisTapiGetAddressStatus;
  2198. TspLog(DL_TRACE, "lineGetAddressStatus(%d): line(%p), addressID(%x)",
  2199. ++dwSum, hdLine, dwAddressID);
  2200. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  2201. if (lRes != TAPI_SUCCESS)
  2202. {
  2203. return lRes;
  2204. }
  2205. if ((lRes = PrepareSyncRequest(
  2206. OID_TAPI_GET_ADDRESS_STATUS, // opcode
  2207. pLine->dwDeviceID, // device id
  2208. sizeof(NDIS_TAPI_GET_ADDRESS_STATUS) + // size of req data
  2209. (lpAddressStatus->dwTotalSize - sizeof(LINE_ADDRESS_STATUS)),
  2210. &pNdisTapiRequest // ptr to ptr to req buf
  2211. )) != TAPI_SUCCESS)
  2212. {
  2213. ReleaseObjReadLock((HANDLE)hdLine);
  2214. return lRes;
  2215. }
  2216. pNdisTapiGetAddressStatus =
  2217. (PNDIS_TAPI_GET_ADDRESS_STATUS)pNdisTapiRequest->Data;
  2218. pNdisTapiGetAddressStatus->hdLine = pLine->hd_Line;
  2219. pNdisTapiGetAddressStatus->ulAddressID = dwAddressID;
  2220. pStatus = &pNdisTapiGetAddressStatus->LineAddressStatus;
  2221. pStatus->ulTotalSize = lpAddressStatus->dwTotalSize;
  2222. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_ADDRESS_STATUS);
  2223. ZeroMemory(&pStatus->ulNumInUse,
  2224. sizeof(LINE_ADDRESS_STATUS) - 3 * sizeof(ULONG));
  2225. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2226. if (TAPI_SUCCESS == lRes)
  2227. {
  2228. CopyMemory(
  2229. lpAddressStatus,
  2230. &pNdisTapiGetAddressStatus->LineAddressStatus,
  2231. pNdisTapiGetAddressStatus->LineAddressStatus.ulUsedSize
  2232. );
  2233. }
  2234. FreeRequest(pNdisTapiRequest);
  2235. ReleaseObjReadLock((HANDLE)hdLine);
  2236. return lRes;
  2237. }
  2238. LONG
  2239. TSPIAPI
  2240. TSPI_lineGetCallAddressID(
  2241. HDRVCALL hdCall,
  2242. LPDWORD lpdwAddressID
  2243. )
  2244. {
  2245. static DWORD dwSum = 0;
  2246. LONG lRes;
  2247. PDRVCALL pCall;
  2248. PNDISTAPI_REQUEST pNdisTapiRequest;
  2249. PNDIS_TAPI_GET_CALL_ADDRESS_ID pNdisTapiGetCallAddressID;
  2250. TspLog(DL_TRACE, "lineGetCallAddressID(%d): call(%p)", ++dwSum, hdCall);
  2251. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2252. if (lRes != TAPI_SUCCESS)
  2253. {
  2254. return lRes;
  2255. }
  2256. if ((lRes = PrepareSyncRequest(
  2257. OID_TAPI_GET_CALL_ADDRESS_ID, // opcode
  2258. pCall->dwDeviceID, // device id
  2259. sizeof(NDIS_TAPI_GET_CALL_ADDRESS_ID), // size of req data
  2260. &pNdisTapiRequest // ptr to ptr to req buf
  2261. )) != TAPI_SUCCESS)
  2262. {
  2263. ReleaseObjReadLock((HANDLE)hdCall);
  2264. return lRes;
  2265. }
  2266. pNdisTapiGetCallAddressID =
  2267. (PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
  2268. pNdisTapiGetCallAddressID->hdCall = GetNdisTapiHandle(pCall, &lRes);
  2269. if(lRes != TAPI_SUCCESS)
  2270. {
  2271. FreeRequest(pNdisTapiRequest);
  2272. return lRes;
  2273. }
  2274. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2275. if (TAPI_SUCCESS == lRes)
  2276. {
  2277. *lpdwAddressID = pNdisTapiGetCallAddressID->ulAddressID;
  2278. TspLog(DL_INFO, "lineGetCallAddressID: addressID(%x)", *lpdwAddressID);
  2279. }
  2280. FreeRequest(pNdisTapiRequest);
  2281. ReleaseObjReadLock((HANDLE)hdCall);
  2282. return lRes;
  2283. }
  2284. LONG
  2285. TSPIAPI
  2286. TSPI_lineGetCallInfo(
  2287. HDRVCALL hdCall,
  2288. LPLINECALLINFO lpCallInfo
  2289. )
  2290. {
  2291. static DWORD dwSum = 0;
  2292. LONG lRes;
  2293. PDRVCALL pCall;
  2294. PNDISTAPI_REQUEST pNdisTapiRequest;
  2295. PLINE_CALL_INFO pInfo;
  2296. PNDIS_TAPI_GET_CALL_INFO pNdisTapiGetCallInfo;
  2297. TspLog(DL_TRACE, "lineGetCallInfo(%d): call(%p)", ++dwSum, hdCall);
  2298. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2299. if (lRes != TAPI_SUCCESS)
  2300. {
  2301. return lRes;
  2302. }
  2303. if ((lRes = PrepareSyncRequest(
  2304. OID_TAPI_GET_CALL_INFO, // opcode
  2305. pCall->dwDeviceID, // device id
  2306. sizeof(NDIS_TAPI_GET_CALL_INFO) + // size of req data
  2307. (lpCallInfo->dwTotalSize - sizeof(LINE_CALL_INFO)),
  2308. &pNdisTapiRequest // ptr to ptr to req buf
  2309. )) != TAPI_SUCCESS)
  2310. {
  2311. ReleaseObjReadLock((HANDLE)hdCall);
  2312. return lRes;
  2313. }
  2314. pNdisTapiGetCallInfo = (PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
  2315. pNdisTapiGetCallInfo->hdCall = GetNdisTapiHandle(pCall, &lRes);
  2316. if(lRes != TAPI_SUCCESS)
  2317. {
  2318. FreeRequest(pNdisTapiRequest);
  2319. return lRes;
  2320. }
  2321. pInfo = &pNdisTapiGetCallInfo->LineCallInfo;
  2322. pInfo->ulTotalSize = lpCallInfo->dwTotalSize;
  2323. pInfo->ulNeededSize = pInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
  2324. ZeroMemory(&pInfo->hLine, sizeof(LINE_CALL_INFO) - 3 * sizeof(ULONG));
  2325. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2326. if (lRes != TAPI_SUCCESS)
  2327. {
  2328. FreeRequest(pNdisTapiRequest);
  2329. ReleaseObjReadLock((HANDLE)hdCall);
  2330. return lRes;
  2331. }
  2332. //
  2333. // Do some post processing to the returned data structure
  2334. // before passing it back to tapi:
  2335. // 1. Pad the area between the fixed 1.0 structure and the
  2336. // var data that the miniports pass back with 0's so a
  2337. // bad app that disregards the 1.0 version negotiation &
  2338. // references new 1.4 or 2.0 structure fields won't blow up
  2339. // 2. Convert ascii strings to unicode, & rebase all var data
  2340. //
  2341. //
  2342. // The real needed size is the sum of that requested by the
  2343. // underlying driver, plus padding for the new TAPI 1.4/2.0
  2344. // structure fields, plus the size of the var data returned
  2345. // by the driver to account for the ascii->unicode conversion.
  2346. // @@@ Granted, we are very liberal in computing the value for
  2347. // this last part, but at least this way it's fast & we'll
  2348. // never have too little buffer space.
  2349. //
  2350. lpCallInfo->dwNeededSize =
  2351. pInfo->ulNeededSize +
  2352. (sizeof(LINECALLINFO) - // v2.0 struct
  2353. sizeof(LINE_CALL_INFO)) + // v1.0 struct
  2354. (pInfo->ulNeededSize - sizeof(LINE_CALL_INFO));
  2355. //
  2356. // Copy over the fixed fields that don't need changing,
  2357. // i.e. everything from dwLineDeviceID to dwTrunk
  2358. //
  2359. CopyMemory(
  2360. &lpCallInfo->dwLineDeviceID,
  2361. &pInfo->ulLineDeviceID,
  2362. 23 * sizeof(DWORD)
  2363. );
  2364. if (lpCallInfo->dwNeededSize > lpCallInfo->dwTotalSize)
  2365. {
  2366. lpCallInfo->dwUsedSize =
  2367. (lpCallInfo->dwTotalSize < sizeof(LINECALLINFO) ?
  2368. lpCallInfo->dwTotalSize : sizeof(LINECALLINFO));
  2369. }
  2370. else
  2371. {
  2372. lpCallInfo->dwUsedSize = sizeof(LINECALLINFO); // v2.0 struct
  2373. lpCallInfo->dwCallerIDFlags = pInfo->ulCallerIDFlags;
  2374. INSERTVARDATASTRING(
  2375. pInfo,
  2376. &pInfo->ulCallerIDSize,
  2377. lpCallInfo,
  2378. &lpCallInfo->dwCallerIDSize,
  2379. sizeof(LINE_CALL_INFO),
  2380. "LINE_CALL_INFO.CallerID"
  2381. );
  2382. INSERTVARDATASTRING(
  2383. pInfo,
  2384. &pInfo->ulCallerIDNameSize,
  2385. lpCallInfo,
  2386. &lpCallInfo->dwCallerIDNameSize,
  2387. sizeof(LINE_CALL_INFO),
  2388. "LINE_CALL_INFO.CallerIDName"
  2389. );
  2390. lpCallInfo->dwCalledIDFlags = pInfo->ulCalledIDFlags;
  2391. INSERTVARDATASTRING(
  2392. pInfo,
  2393. &pInfo->ulCalledIDSize,
  2394. lpCallInfo,
  2395. &lpCallInfo->dwCalledIDSize,
  2396. sizeof(LINE_CALL_INFO),
  2397. "LINE_CALL_INFO.CalledID"
  2398. );
  2399. INSERTVARDATASTRING(
  2400. pInfo,
  2401. &pInfo->ulCalledIDNameSize,
  2402. lpCallInfo,
  2403. &lpCallInfo->dwCalledIDNameSize,
  2404. sizeof(LINE_CALL_INFO),
  2405. "LINE_CALL_INFO.CalledIDName"
  2406. );
  2407. lpCallInfo->dwConnectedIDFlags = pInfo->ulConnectedIDFlags;
  2408. INSERTVARDATASTRING(
  2409. pInfo,
  2410. &pInfo->ulConnectedIDSize,
  2411. lpCallInfo,
  2412. &lpCallInfo->dwConnectedIDSize,
  2413. sizeof(LINE_CALL_INFO),
  2414. "LINE_CALL_INFO.ConnectID"
  2415. );
  2416. INSERTVARDATASTRING(
  2417. pInfo,
  2418. &pInfo->ulConnectedIDNameSize,
  2419. lpCallInfo,
  2420. &lpCallInfo->dwConnectedIDNameSize,
  2421. sizeof(LINE_CALL_INFO),
  2422. "LINE_CALL_INFO.ConnectIDName"
  2423. );
  2424. lpCallInfo->dwRedirectionIDFlags = pInfo->ulRedirectionIDFlags;
  2425. INSERTVARDATASTRING(
  2426. pInfo,
  2427. &pInfo->ulRedirectionIDSize,
  2428. lpCallInfo,
  2429. &lpCallInfo->dwRedirectionIDSize,
  2430. sizeof(LINE_CALL_INFO),
  2431. "LINE_CALL_INFO.RedirectionID"
  2432. );
  2433. INSERTVARDATASTRING(
  2434. pInfo,
  2435. &pInfo->ulRedirectionIDNameSize,
  2436. lpCallInfo,
  2437. &lpCallInfo->dwRedirectionIDNameSize,
  2438. sizeof(LINE_CALL_INFO),
  2439. "LINE_CALL_INFO.RedirectionIDName"
  2440. );
  2441. lpCallInfo->dwRedirectingIDFlags = pInfo->ulRedirectingIDFlags;
  2442. INSERTVARDATASTRING(
  2443. pInfo,
  2444. &pInfo->ulRedirectingIDSize,
  2445. lpCallInfo,
  2446. &lpCallInfo->dwRedirectingIDSize,
  2447. sizeof(LINE_CALL_INFO),
  2448. "LINE_CALL_INFO.RedirectingID"
  2449. );
  2450. INSERTVARDATASTRING(
  2451. pInfo,
  2452. &pInfo->ulRedirectingIDNameSize,
  2453. lpCallInfo,
  2454. &lpCallInfo->dwRedirectingIDNameSize,
  2455. sizeof(LINE_CALL_INFO),
  2456. "LINE_CALL_INFO.RedirectingIDName"
  2457. );
  2458. INSERTVARDATA(
  2459. pInfo,
  2460. &pInfo->ulDisplaySize,
  2461. lpCallInfo,
  2462. &lpCallInfo->dwDisplaySize,
  2463. sizeof(LINE_CALL_INFO),
  2464. "LINE_CALL_INFO.Display"
  2465. );
  2466. INSERTVARDATA(
  2467. pInfo,
  2468. &pInfo->ulUserUserInfoSize,
  2469. lpCallInfo,
  2470. &lpCallInfo->dwUserUserInfoSize,
  2471. sizeof(LINE_CALL_INFO),
  2472. "LINE_CALL_INFO.UserUserInfo"
  2473. );
  2474. INSERTVARDATA(
  2475. pInfo,
  2476. &pInfo->ulHighLevelCompSize,
  2477. lpCallInfo,
  2478. &lpCallInfo->dwHighLevelCompSize,
  2479. sizeof(LINE_CALL_INFO),
  2480. "LINE_CALL_INFO.HighLevelComp"
  2481. );
  2482. INSERTVARDATA(
  2483. pInfo,
  2484. &pInfo->ulLowLevelCompSize,
  2485. lpCallInfo,
  2486. &lpCallInfo->dwLowLevelCompSize,
  2487. sizeof(LINE_CALL_INFO),
  2488. "LINE_CALL_INFO.LowLevelComp"
  2489. );
  2490. INSERTVARDATA(
  2491. pInfo,
  2492. &pInfo->ulChargingInfoSize,
  2493. lpCallInfo,
  2494. &lpCallInfo->dwChargingInfoSize,
  2495. sizeof(LINE_CALL_INFO),
  2496. "LINE_CALL_INFO.ChargingInfo"
  2497. );
  2498. INSERTVARDATA(
  2499. pInfo,
  2500. &pInfo->ulTerminalModesSize,
  2501. lpCallInfo,
  2502. &lpCallInfo->dwTerminalModesSize,
  2503. sizeof(LINE_CALL_INFO),
  2504. "LINE_CALL_INFO.TerminalModes"
  2505. );
  2506. INSERTVARDATA(
  2507. pInfo,
  2508. &pInfo->ulDevSpecificSize,
  2509. lpCallInfo,
  2510. &lpCallInfo->dwDevSpecificSize,
  2511. sizeof(LINE_CALL_INFO),
  2512. "LINE_CALL_INFO.DevSpecific"
  2513. );
  2514. // make sure that dwNeededSize == dwUsedSize
  2515. lpCallInfo->dwNeededSize = lpCallInfo->dwUsedSize;
  2516. }
  2517. FreeRequest(pNdisTapiRequest);
  2518. ReleaseObjReadLock((HANDLE)hdCall);
  2519. return lRes;
  2520. }
  2521. LONG
  2522. TSPIAPI
  2523. TSPI_lineGetCallStatus(
  2524. HDRVCALL hdCall,
  2525. LPLINECALLSTATUS lpCallStatus
  2526. )
  2527. {
  2528. static DWORD dwSum = 0;
  2529. LONG lRes;
  2530. PDRVCALL pCall;
  2531. PNDISTAPI_REQUEST pNdisTapiRequest;
  2532. PLINE_CALL_STATUS pStatus;
  2533. PNDIS_TAPI_GET_CALL_STATUS pNdisTapiGetCallStatus;
  2534. TspLog(DL_TRACE, "lineGetCallStatus(%d): call(%p)", ++dwSum, hdCall);
  2535. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2536. if (lRes != TAPI_SUCCESS)
  2537. {
  2538. return lRes;
  2539. }
  2540. if ((lRes = PrepareSyncRequest(
  2541. OID_TAPI_GET_CALL_STATUS, // opcode
  2542. pCall->dwDeviceID, // device id
  2543. sizeof(NDIS_TAPI_GET_CALL_STATUS) + // size of req data
  2544. (lpCallStatus->dwTotalSize - sizeof(LINE_CALL_STATUS)),
  2545. &pNdisTapiRequest // ptr to ptr to req buf
  2546. )) != TAPI_SUCCESS)
  2547. {
  2548. ReleaseObjReadLock((HANDLE)hdCall);
  2549. return lRes;
  2550. }
  2551. pNdisTapiGetCallStatus = (PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
  2552. pNdisTapiGetCallStatus->hdCall = GetNdisTapiHandle(pCall, &lRes);
  2553. if(lRes != TAPI_SUCCESS)
  2554. {
  2555. FreeRequest(pNdisTapiRequest);
  2556. return lRes;
  2557. }
  2558. pStatus = &pNdisTapiGetCallStatus->LineCallStatus;
  2559. pStatus->ulTotalSize = lpCallStatus->dwTotalSize;
  2560. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
  2561. ZeroMemory(&pStatus->ulCallState,
  2562. sizeof(LINE_CALL_STATUS) - 3 * sizeof(ULONG));
  2563. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2564. if (lRes != TAPI_SUCCESS)
  2565. {
  2566. FreeRequest(pNdisTapiRequest);
  2567. ReleaseObjReadLock((HANDLE)hdCall);
  2568. return lRes;
  2569. }
  2570. //
  2571. // Do some post processing to the returned data structure
  2572. // before passing it back to tapi:
  2573. // 1. Pad the area between the fixed 1.0 structure and the
  2574. // var data that the miniports pass back with 0's so a
  2575. // bad app that disregards the 1.0 version negotiation &
  2576. // references new 1.4 or 2.0 structure fields won't blow up
  2577. // (no embedded ascii strings to convert to unicode)
  2578. //
  2579. //
  2580. // The real needed size is the sum of that requested by the
  2581. // underlying driver, plus padding for the new TAPI 1.4/2.0
  2582. // structure fields. (There are no embedded ascii strings to
  2583. // convert to unicode, so no extra space needed for that.)
  2584. //
  2585. lpCallStatus->dwNeededSize =
  2586. pStatus->ulNeededSize +
  2587. (sizeof(LINECALLSTATUS) - // v2.0 struct
  2588. sizeof(LINE_CALL_STATUS)); // v1.0 struct
  2589. //
  2590. // Copy over the fixed fields that don't need changing,
  2591. // i.e. everything from dwLineDeviceID to dwCallCompletionModes
  2592. //
  2593. CopyMemory(
  2594. &lpCallStatus->dwCallState,
  2595. &pStatus->ulCallState,
  2596. 4 * sizeof(DWORD)
  2597. );
  2598. if (lpCallStatus->dwNeededSize > lpCallStatus->dwTotalSize)
  2599. {
  2600. lpCallStatus->dwUsedSize =
  2601. (lpCallStatus->dwTotalSize < sizeof(LINECALLSTATUS) ?
  2602. lpCallStatus->dwTotalSize : sizeof(LINECALLSTATUS));
  2603. }
  2604. else
  2605. {
  2606. lpCallStatus->dwUsedSize = sizeof(LINECALLSTATUS);
  2607. // v2.0 struct
  2608. INSERTVARDATA(
  2609. pStatus,
  2610. &pStatus->ulDevSpecificSize,
  2611. lpCallStatus,
  2612. &lpCallStatus->dwDevSpecificSize,
  2613. sizeof(LINE_CALL_STATUS),
  2614. "LINE_CALL_STATUS.DevSpecific"
  2615. );
  2616. }
  2617. FreeRequest(pNdisTapiRequest);
  2618. ReleaseObjReadLock((HANDLE)hdCall);
  2619. return lRes;
  2620. }
  2621. LINEDEVCAPS *
  2622. GetLineDevCaps(
  2623. IN DWORD dwDeviceID,
  2624. IN DWORD dwExtVersion
  2625. )
  2626. {
  2627. LONG lRes;
  2628. PNDISTAPI_REQUEST pNdisTapiRequest;
  2629. PLINE_DEV_CAPS pCaps;
  2630. PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps;
  2631. DWORD dwNeededSize;
  2632. LINEDEVCAPS *pLineDevCaps;
  2633. DWORD dwTotalSize = sizeof(LINEDEVCAPS) + 0x80;
  2634. get_caps:
  2635. pLineDevCaps = (LINEDEVCAPS *)MALLOC(dwTotalSize);
  2636. if (NULL == pLineDevCaps)
  2637. {
  2638. TspLog(DL_ERROR, "GetLineDevCaps: failed to alloc mem of size(%x)",
  2639. dwTotalSize);
  2640. return NULL;
  2641. }
  2642. pLineDevCaps->dwTotalSize = dwTotalSize;
  2643. if ((lRes = PrepareSyncRequest(
  2644. OID_TAPI_GET_DEV_CAPS, // opcode
  2645. dwDeviceID, // device id
  2646. sizeof(NDIS_TAPI_GET_DEV_CAPS) + // size of req data
  2647. (dwTotalSize - sizeof(LINE_DEV_CAPS)),
  2648. &pNdisTapiRequest // ptr to ptr to req buf
  2649. )) != TAPI_SUCCESS)
  2650. {
  2651. return NULL;
  2652. }
  2653. pNdisTapiGetDevCaps = (PNDIS_TAPI_GET_DEV_CAPS)pNdisTapiRequest->Data;
  2654. pNdisTapiGetDevCaps->ulDeviceID = dwDeviceID;
  2655. pNdisTapiGetDevCaps->ulExtVersion = dwExtVersion;
  2656. pCaps = &pNdisTapiGetDevCaps->LineDevCaps;
  2657. pCaps->ulTotalSize = dwTotalSize;
  2658. pCaps->ulNeededSize = pCaps->ulUsedSize = sizeof(LINE_DEV_CAPS);
  2659. ZeroMemory(&pCaps->ulProviderInfoSize,
  2660. sizeof(LINE_DEV_CAPS) - 3 * sizeof(ULONG));
  2661. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2662. if (lRes != TAPI_SUCCESS)
  2663. {
  2664. FreeRequest(pNdisTapiRequest);
  2665. return NULL;
  2666. }
  2667. //
  2668. // The real needed size is the sum of that requested by the
  2669. // underlying driver, plus padding for the new TAPI 1.4/2.0
  2670. // structure fields, plus the size of the var data returned
  2671. // by the driver to account for the ascii->unicode conversion.
  2672. // @@@ Granted, we are very liberal in computing the value for
  2673. // this last part, but at least this way it's fast & we'll
  2674. // never have too little buffer space.
  2675. //
  2676. TspLog(DL_TRACE,
  2677. "GetLineDevCaps: ulNeeded(%x), LINEDEVCAPS(%x), LINE_DEV_CAPS(%x)",
  2678. pCaps->ulNeededSize, sizeof(LINEDEVCAPS), sizeof(LINE_DEV_CAPS));
  2679. dwNeededSize =
  2680. pCaps->ulNeededSize +
  2681. (sizeof(LINEDEVCAPS) - // v2.0 struct
  2682. sizeof(LINE_DEV_CAPS)) + // v1.0 struct
  2683. (pCaps->ulNeededSize - sizeof(LINE_DEV_CAPS));
  2684. TspLog(DL_TRACE, "GetLineDevCaps: dwNeededSize(%x), dwTotalSize(%x)",
  2685. dwNeededSize, dwTotalSize);
  2686. if (dwNeededSize > dwTotalSize)
  2687. {
  2688. // free up the old req
  2689. FreeRequest(pNdisTapiRequest);
  2690. // free the old buffer
  2691. FREE(pLineDevCaps);
  2692. // try again with a larger buffer
  2693. dwTotalSize = dwNeededSize;
  2694. goto get_caps;
  2695. }
  2696. ASSERT(dwNeededSize <= dwTotalSize);
  2697. //
  2698. // Copy over the fixed fields that don't need changing,
  2699. // i.e. everything from dwPermanentLineID to dwNumTerminals
  2700. //
  2701. CopyMemory(
  2702. &pLineDevCaps->dwPermanentLineID,
  2703. &pCaps->ulPermanentLineID,
  2704. sizeof(LINE_DEV_CAPS) - (14 * sizeof(DWORD))
  2705. );
  2706. // set the local flag to indicate that
  2707. // the line can't be used from remote machine
  2708. pLineDevCaps->dwDevCapFlags |= LINEDEVCAPFLAGS_LOCAL;
  2709. //
  2710. // Do some post processing to the returned data structure
  2711. // before passing it back to tapi:
  2712. // 1. Pad the area between the fixed 1.0 structure and the
  2713. // var data that the miniports pass back with 0's so a
  2714. // bad app that disregards the 1.0 version negotiation &
  2715. // references new 1.4 or 2.0 structure fields won't blow up
  2716. // 2. Convert ascii strings to unicode, & rebase all var data
  2717. //
  2718. pLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS); // v2.0 struct
  2719. INSERTVARDATASTRING(
  2720. pCaps,
  2721. &pCaps->ulProviderInfoSize,
  2722. pLineDevCaps,
  2723. &pLineDevCaps->dwProviderInfoSize,
  2724. sizeof(LINE_DEV_CAPS),
  2725. "LINE_DEV_CAPS.ProviderInfo"
  2726. );
  2727. INSERTVARDATASTRING(
  2728. pCaps,
  2729. &pCaps->ulSwitchInfoSize,
  2730. pLineDevCaps,
  2731. &pLineDevCaps->dwSwitchInfoSize,
  2732. sizeof(LINE_DEV_CAPS),
  2733. "LINE_DEV_CAPS.SwitchInfo"
  2734. );
  2735. INSERTVARDATASTRING(
  2736. pCaps,
  2737. &pCaps->ulLineNameSize,
  2738. pLineDevCaps,
  2739. &pLineDevCaps->dwLineNameSize,
  2740. sizeof(LINE_DEV_CAPS),
  2741. "LINE_DEV_CAPS.LineName"
  2742. );
  2743. INSERTVARDATA(
  2744. pCaps,
  2745. &pCaps->ulTerminalCapsSize,
  2746. pLineDevCaps,
  2747. &pLineDevCaps->dwTerminalCapsSize,
  2748. sizeof(LINE_DEV_CAPS),
  2749. "LINE_DEV_CAPS.TerminalCaps"
  2750. );
  2751. // @@@ convert DevCaps.TermText to unicode???
  2752. pLineDevCaps->dwTerminalTextEntrySize =
  2753. pCaps->ulTerminalTextEntrySize;
  2754. INSERTVARDATA(
  2755. pCaps,
  2756. &pCaps->ulTerminalTextSize,
  2757. pLineDevCaps,
  2758. &pLineDevCaps->dwTerminalTextSize,
  2759. sizeof(LINE_DEV_CAPS),
  2760. "LINE_DEV_CAPS.TerminalText"
  2761. );
  2762. INSERTVARDATA(
  2763. pCaps,
  2764. &pCaps->ulDevSpecificSize,
  2765. pLineDevCaps,
  2766. &pLineDevCaps->dwDevSpecificSize,
  2767. sizeof(LINE_DEV_CAPS),
  2768. "LINE_DEV_CAPS.DevSpecific"
  2769. );
  2770. // make sure dwNeededSize == dwUsedSize
  2771. pLineDevCaps->dwNeededSize = pLineDevCaps->dwUsedSize;
  2772. FreeRequest(pNdisTapiRequest);
  2773. return pLineDevCaps;
  2774. }
  2775. LONG
  2776. TSPIAPI
  2777. TSPI_lineGetDevCaps(
  2778. DWORD dwDeviceID,
  2779. DWORD dwTSPIVersion,
  2780. DWORD dwExtVersion,
  2781. LPLINEDEVCAPS lpLineDevCaps
  2782. )
  2783. {
  2784. static DWORD dwSum = 0;
  2785. LONG lRes;
  2786. TspLog(DL_TRACE, "lineGetDevCaps(%d): deviceID(%x), TSPIV(%x), ExtV(%x)",
  2787. ++dwSum, dwDeviceID, dwTSPIVersion, dwExtVersion);
  2788. lRes = GetDevCaps(dwDeviceID, dwTSPIVersion, dwExtVersion, lpLineDevCaps);
  2789. return lRes;
  2790. }
  2791. LONG
  2792. TSPIAPI
  2793. TSPI_lineGetDevConfig(
  2794. DWORD dwDeviceID,
  2795. LPVARSTRING lpDeviceConfig,
  2796. LPCWSTR lpszDeviceClass
  2797. )
  2798. {
  2799. static DWORD dwSum = 0;
  2800. LONG lRes;
  2801. DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
  2802. PNDISTAPI_REQUEST pNdisTapiRequest;
  2803. PVAR_STRING pConfig;
  2804. PNDIS_TAPI_GET_DEV_CONFIG pNdisTapiGetDevConfig;
  2805. TspLog(DL_TRACE, "lineGetDevConfig(%d): deviceID(%x)", ++dwSum, dwDeviceID);
  2806. if ((lRes = PrepareSyncRequest(
  2807. OID_TAPI_GET_DEV_CONFIG, // opcode
  2808. dwDeviceID, // device id
  2809. sizeof(NDIS_TAPI_GET_DEV_CONFIG) + // size of req data
  2810. (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING)) + dwLength,
  2811. &pNdisTapiRequest // ptr to ptr to req buf
  2812. )) != TAPI_SUCCESS)
  2813. {
  2814. return lRes;
  2815. }
  2816. pNdisTapiGetDevConfig = (PNDIS_TAPI_GET_DEV_CONFIG)pNdisTapiRequest->Data;
  2817. pNdisTapiGetDevConfig->ulDeviceID = dwDeviceID;
  2818. pNdisTapiGetDevConfig->ulDeviceClassSize = dwLength;
  2819. pNdisTapiGetDevConfig->ulDeviceClassOffset =
  2820. sizeof(NDIS_TAPI_GET_DEV_CONFIG) +
  2821. (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING));
  2822. pConfig = &pNdisTapiGetDevConfig->DeviceConfig;
  2823. pConfig->ulTotalSize = lpDeviceConfig->dwTotalSize;
  2824. pConfig->ulNeededSize = pConfig->ulUsedSize = sizeof(VAR_STRING);
  2825. pConfig->ulStringFormat =
  2826. pConfig->ulStringSize =
  2827. pConfig->ulStringOffset = 0;
  2828. // NOTE: old miniports expect strings to be ascii
  2829. WideCharToMultiByte(CP_ACP, 0, lpszDeviceClass, -1,
  2830. (LPSTR) (((LPBYTE) pNdisTapiGetDevConfig) +
  2831. pNdisTapiGetDevConfig->ulDeviceClassOffset),
  2832. dwLength, NULL, NULL);
  2833. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2834. if (TAPI_SUCCESS == lRes)
  2835. {
  2836. CopyMemory(
  2837. lpDeviceConfig,
  2838. &pNdisTapiGetDevConfig->DeviceConfig,
  2839. pNdisTapiGetDevConfig->DeviceConfig.ulUsedSize
  2840. );
  2841. }
  2842. FreeRequest(pNdisTapiRequest);
  2843. return lRes;
  2844. }
  2845. LONG
  2846. TSPIAPI
  2847. TSPI_lineGetExtensionID(
  2848. DWORD dwDeviceID,
  2849. DWORD dwTSPIVersion,
  2850. LPLINEEXTENSIONID lpExtensionID
  2851. )
  2852. {
  2853. static DWORD dwSum = 0;
  2854. LONG lRes;
  2855. PNDISTAPI_REQUEST pNdisTapiRequest;
  2856. PNDIS_TAPI_GET_EXTENSION_ID pNdisTapiGetExtensionID;
  2857. TspLog(DL_TRACE, "lineGetExtensionID(%d): deviceID(%x), TSPIV(%x)",
  2858. ++dwSum, dwDeviceID, dwTSPIVersion);
  2859. if ((lRes = PrepareSyncRequest(
  2860. OID_TAPI_GET_EXTENSION_ID, // opcode
  2861. dwDeviceID, // device id
  2862. sizeof(NDIS_TAPI_GET_EXTENSION_ID), // size of req data
  2863. &pNdisTapiRequest // ptr to ptr to req buf
  2864. )) != TAPI_SUCCESS)
  2865. {
  2866. return lRes;
  2867. }
  2868. pNdisTapiGetExtensionID =
  2869. (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
  2870. pNdisTapiGetExtensionID->ulDeviceID = dwDeviceID;
  2871. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  2872. if (TAPI_SUCCESS == lRes)
  2873. {
  2874. CopyMemory(
  2875. lpExtensionID,
  2876. &pNdisTapiGetExtensionID->LineExtensionID,
  2877. sizeof(LINE_EXTENSION_ID)
  2878. );
  2879. }
  2880. else
  2881. {
  2882. //
  2883. // Rather than indicating a failure, we'll just zero out the
  2884. // ext id (implying driver doesn't support extensions) and
  2885. // return success to tapisrv so it'll complete the open ok
  2886. //
  2887. ZeroMemory(lpExtensionID, sizeof(LINE_EXTENSION_ID));
  2888. lRes = TAPI_SUCCESS;
  2889. }
  2890. FreeRequest(pNdisTapiRequest);
  2891. return lRes;
  2892. }
  2893. LONG
  2894. TSPIAPI
  2895. TSPI_lineGetID(
  2896. HDRVLINE hdLine,
  2897. DWORD dwAddressID,
  2898. HDRVCALL hdCall,
  2899. DWORD dwSelect,
  2900. LPVARSTRING lpDeviceID,
  2901. LPCWSTR lpszDeviceClass,
  2902. HANDLE hTargetProcess
  2903. )
  2904. {
  2905. static DWORD dwSum = 0;
  2906. LONG lRes;
  2907. PDRVLINE pLine = NULL;
  2908. PDRVCALL pCall = NULL;
  2909. PNDISTAPI_REQUEST pNdisTapiRequest;
  2910. DWORD dwLength = lstrlenW(lpszDeviceClass) + 1;
  2911. DWORD dwDeviceID;
  2912. PUCHAR pchDest;
  2913. PVAR_STRING pID;
  2914. PNDIS_TAPI_GET_ID pNdisTapiGetID;
  2915. TspLog(DL_TRACE,
  2916. "lineGetID(%d): line(%p), call(%p), addressID(%x), select(%x)",
  2917. ++dwSum, hdLine, hdCall, dwAddressID, dwSelect);
  2918. ASSERT(LINECALLSELECT_LINE == dwSelect ||
  2919. LINECALLSELECT_ADDRESS == dwSelect ||
  2920. LINECALLSELECT_CALL == dwSelect);
  2921. if (LINECALLSELECT_LINE == dwSelect ||
  2922. LINECALLSELECT_ADDRESS == dwSelect)
  2923. {
  2924. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  2925. if (lRes != TAPI_SUCCESS)
  2926. {
  2927. return lRes;
  2928. }
  2929. }
  2930. if (LINECALLSELECT_CALL == dwSelect)
  2931. {
  2932. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2933. if (lRes != TAPI_SUCCESS)
  2934. {
  2935. return lRes;
  2936. }
  2937. }
  2938. //
  2939. // Kmddsp will field this specific call on behalf of the
  2940. // wan miniports. It returns the guid and media string
  2941. // of the adapter that this line lives on
  2942. //
  2943. if (LINECALLSELECT_LINE == dwSelect &&
  2944. !wcscmp(lpszDeviceClass, L"LineGuid"))
  2945. {
  2946. lpDeviceID->dwNeededSize =
  2947. sizeof(VARSTRING) + sizeof(GUID) +
  2948. sizeof(pLine->MediaType) + sizeof('\0');
  2949. if (lpDeviceID->dwTotalSize < lpDeviceID->dwNeededSize)
  2950. {
  2951. if (pCall != NULL)
  2952. {
  2953. ReleaseObjReadLock((HANDLE)hdCall);
  2954. }
  2955. if (pLine != NULL)
  2956. {
  2957. ReleaseObjReadLock((HANDLE)hdLine);
  2958. }
  2959. return LINEERR_STRUCTURETOOSMALL;
  2960. }
  2961. lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
  2962. lpDeviceID->dwStringFormat = STRINGFORMAT_ASCII;
  2963. pchDest = (PUCHAR)lpDeviceID + sizeof(*lpDeviceID);
  2964. lpDeviceID->dwStringOffset = (DWORD)(pchDest - (PUCHAR)lpDeviceID);
  2965. lpDeviceID->dwStringSize =
  2966. sizeof(GUID) + sizeof(pLine->MediaType) +sizeof('\0');
  2967. MoveMemory(
  2968. pchDest,
  2969. (PUCHAR)&pLine->Guid,
  2970. sizeof(pLine->Guid)
  2971. );
  2972. pchDest += sizeof(pLine->Guid);
  2973. MoveMemory(
  2974. pchDest,
  2975. &pLine->MediaType,
  2976. sizeof(pLine->MediaType)
  2977. );
  2978. pchDest += sizeof(pLine->MediaType);
  2979. *pchDest = '\0';
  2980. TspLog(DL_INFO, "lineGetID: obj(%p)", hdLine);
  2981. TspLog(
  2982. DL_INFO,
  2983. "Guid %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x",
  2984. pLine->Guid.Data1, pLine->Guid.Data2,
  2985. pLine->Guid.Data3, pLine->Guid.Data4[0],
  2986. pLine->Guid.Data4[1], pLine->Guid.Data4[2],
  2987. pLine->Guid.Data4[3], pLine->Guid.Data4[4],
  2988. pLine->Guid.Data4[5], pLine->Guid.Data4[6],
  2989. pLine->Guid.Data4[7]
  2990. );
  2991. TspLog(DL_INFO, "MediaType: %d", pLine->MediaType);
  2992. if (pCall != NULL)
  2993. {
  2994. ReleaseObjReadLock((HANDLE)hdCall);
  2995. }
  2996. if (pLine != NULL)
  2997. {
  2998. ReleaseObjReadLock((HANDLE)hdLine);
  2999. }
  3000. return TAPI_SUCCESS;
  3001. }
  3002. dwDeviceID = (LINECALLSELECT_CALL == dwSelect) ?
  3003. pCall->dwDeviceID : pLine->dwDeviceID;
  3004. if ((lRes = PrepareSyncRequest(
  3005. OID_TAPI_GET_ID, // opcode
  3006. dwDeviceID, // device id
  3007. sizeof(NDIS_TAPI_GET_ID) + // size of req data
  3008. (lpDeviceID->dwTotalSize - sizeof(VAR_STRING)) + dwLength,
  3009. &pNdisTapiRequest // ptr to ptr to req buf
  3010. )) != TAPI_SUCCESS)
  3011. {
  3012. if (pCall != NULL)
  3013. {
  3014. ReleaseObjReadLock((HANDLE)hdCall);
  3015. }
  3016. if (pLine != NULL)
  3017. {
  3018. ReleaseObjReadLock((HANDLE)hdLine);
  3019. }
  3020. return lRes;
  3021. }
  3022. pNdisTapiGetID = (PNDIS_TAPI_GET_ID)pNdisTapiRequest->Data;
  3023. if (LINECALLSELECT_LINE == dwSelect ||
  3024. LINECALLSELECT_ADDRESS == dwSelect)
  3025. {
  3026. pNdisTapiGetID->hdLine = pLine->hd_Line;
  3027. }
  3028. pNdisTapiGetID->ulAddressID = dwAddressID;
  3029. if (LINECALLSELECT_CALL == dwSelect)
  3030. {
  3031. pNdisTapiGetID->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3032. if(lRes != TAPI_SUCCESS)
  3033. {
  3034. if(pLine != NULL)
  3035. {
  3036. ReleaseObjReadLock((HANDLE) hdLine);
  3037. }
  3038. return lRes;
  3039. }
  3040. }
  3041. pNdisTapiGetID->ulSelect = dwSelect;
  3042. pNdisTapiGetID->ulDeviceClassSize = dwLength;
  3043. pNdisTapiGetID->ulDeviceClassOffset = sizeof(NDIS_TAPI_GET_ID) +
  3044. (lpDeviceID->dwTotalSize - sizeof(VAR_STRING));
  3045. pID = &pNdisTapiGetID->DeviceID;
  3046. pID->ulTotalSize = lpDeviceID->dwTotalSize;
  3047. pID->ulNeededSize = pID->ulUsedSize = sizeof(VAR_STRING);
  3048. pID->ulStringFormat = pID->ulStringSize = pID->ulStringOffset = 0;
  3049. // NOTE: old miniports expect strings to be ascii
  3050. WideCharToMultiByte(
  3051. CP_ACP, 0, lpszDeviceClass, -1,
  3052. (LPSTR) (((LPBYTE) pNdisTapiGetID) +
  3053. pNdisTapiGetID->ulDeviceClassOffset),
  3054. dwLength, NULL, NULL);
  3055. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3056. if (TAPI_SUCCESS == lRes)
  3057. {
  3058. CopyMemory(
  3059. lpDeviceID,
  3060. &pNdisTapiGetID->DeviceID,
  3061. pNdisTapiGetID->DeviceID.ulUsedSize
  3062. );
  3063. }
  3064. FreeRequest(pNdisTapiRequest);
  3065. if (pCall != NULL)
  3066. {
  3067. ReleaseObjReadLock((HANDLE)hdCall);
  3068. }
  3069. if (pLine != NULL)
  3070. {
  3071. ReleaseObjReadLock((HANDLE)hdLine);
  3072. }
  3073. return lRes;
  3074. }
  3075. LONG
  3076. TSPIAPI
  3077. TSPI_lineGetLineDevStatus(
  3078. HDRVLINE hdLine,
  3079. LPLINEDEVSTATUS lpLineDevStatus
  3080. )
  3081. {
  3082. static DWORD dwSum = 0;
  3083. LONG lRes;
  3084. PDRVLINE pLine;
  3085. PNDISTAPI_REQUEST pNdisTapiRequest;
  3086. PLINE_DEV_STATUS pStatus;
  3087. PNDIS_TAPI_GET_LINE_DEV_STATUS pNdisTapiGetLineDevStatus;
  3088. TspLog(DL_TRACE, "lineGetLineDevStatus(%d): line(%p)", ++dwSum, hdLine);
  3089. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3090. if (lRes != TAPI_SUCCESS)
  3091. {
  3092. return lRes;
  3093. }
  3094. if ((lRes = PrepareSyncRequest(
  3095. OID_TAPI_GET_LINE_DEV_STATUS, // opcode
  3096. pLine->dwDeviceID, // device id
  3097. sizeof(NDIS_TAPI_GET_LINE_DEV_STATUS) + // size of req data
  3098. (lpLineDevStatus->dwTotalSize - sizeof(LINE_DEV_STATUS)),
  3099. &pNdisTapiRequest // ptr to ptr to req buf
  3100. )) != TAPI_SUCCESS)
  3101. {
  3102. ReleaseObjReadLock((HANDLE)hdLine);
  3103. return lRes;
  3104. }
  3105. pNdisTapiGetLineDevStatus =
  3106. (PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
  3107. pNdisTapiGetLineDevStatus->hdLine = pLine->hd_Line;
  3108. pStatus = &pNdisTapiGetLineDevStatus->LineDevStatus;
  3109. pStatus->ulTotalSize = lpLineDevStatus->dwTotalSize;
  3110. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
  3111. ZeroMemory(&pStatus->ulNumOpens,
  3112. sizeof(LINE_DEV_STATUS) - 3 * sizeof(ULONG));
  3113. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3114. if (lRes != TAPI_SUCCESS)
  3115. {
  3116. FreeRequest(pNdisTapiRequest);
  3117. ReleaseObjReadLock((HANDLE)hdLine);
  3118. return lRes;
  3119. }
  3120. //
  3121. // Do some post processing to the returned data structure
  3122. // before passing it back to tapi:
  3123. // 1. Pad the area between the fixed 1.0 structure and the
  3124. // var data that the miniports pass back with 0's so a
  3125. // bad app that disregards the 1.0 version negotiation &
  3126. // references new 1.4 or 2.0 structure fields won't blow up
  3127. // (no embedded ascii strings to convert to unicode)
  3128. //
  3129. //
  3130. // The real needed size is the sum of that requested by the
  3131. // underlying driver, plus padding for the new TAPI 1.4/2.0
  3132. // structure fields. (There are no embedded ascii strings to
  3133. // convert to unicode, so no extra space needed for that.)
  3134. //
  3135. lpLineDevStatus->dwNeededSize =
  3136. pStatus->ulNeededSize +
  3137. (sizeof(LINEDEVSTATUS) - // v2.0 struct
  3138. sizeof(LINE_DEV_STATUS)); // v1.0 struct
  3139. //
  3140. // Copy over the fixed fields that don't need changing,
  3141. // i.e. everything from dwNumActiveCalls to dwDevStatusFlags
  3142. //
  3143. CopyMemory(
  3144. &lpLineDevStatus->dwNumActiveCalls,
  3145. &pStatus->ulNumActiveCalls,
  3146. sizeof(LINE_DEV_STATUS) - (9 * sizeof(DWORD))
  3147. );
  3148. if (lpLineDevStatus->dwNeededSize > lpLineDevStatus->dwTotalSize)
  3149. {
  3150. lpLineDevStatus->dwUsedSize =
  3151. (lpLineDevStatus->dwTotalSize < sizeof(LINEDEVSTATUS) ?
  3152. lpLineDevStatus->dwTotalSize : sizeof(LINEDEVSTATUS));
  3153. }
  3154. else
  3155. {
  3156. lpLineDevStatus->dwUsedSize = sizeof(LINEDEVSTATUS);
  3157. // v2.0 struct
  3158. INSERTVARDATA(
  3159. pStatus,
  3160. &pStatus->ulTerminalModesSize,
  3161. lpLineDevStatus,
  3162. &lpLineDevStatus->dwTerminalModesSize,
  3163. sizeof(LINE_DEV_STATUS),
  3164. "LINE_DEV_STATUS.TerminalModes"
  3165. );
  3166. INSERTVARDATA(
  3167. pStatus,
  3168. &pStatus->ulDevSpecificSize,
  3169. lpLineDevStatus,
  3170. &lpLineDevStatus->dwDevSpecificSize,
  3171. sizeof(LINE_DEV_STATUS),
  3172. "LINE_DEV_STATUS.DevSpecific"
  3173. );
  3174. }
  3175. FreeRequest(pNdisTapiRequest);
  3176. ReleaseObjReadLock((HANDLE)hdLine);
  3177. return lRes;
  3178. }
  3179. LONG
  3180. TSPIAPI
  3181. TSPI_lineGetNumAddressIDs(
  3182. HDRVLINE hdLine,
  3183. LPDWORD lpdwNumAddressIDs
  3184. )
  3185. {
  3186. static DWORD dwSum = 0;
  3187. LONG lRes;
  3188. PDRVLINE pLine;
  3189. TspLog(DL_TRACE, "lineGetNumAddressIDs(%d): line(%p)", ++dwSum, hdLine);
  3190. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3191. if (lRes != TAPI_SUCCESS)
  3192. {
  3193. return lRes;
  3194. }
  3195. lRes = GetNumAddressIDs(pLine->dwDeviceID, lpdwNumAddressIDs);
  3196. if (TAPI_SUCCESS == lRes)
  3197. {
  3198. TspLog(DL_INFO, "lineGetNumAddressIDs: numAddressIDs(%x)",
  3199. *lpdwNumAddressIDs);
  3200. }
  3201. ReleaseObjReadLock((HANDLE)hdLine);
  3202. return lRes;
  3203. }
  3204. LONG
  3205. PASCAL
  3206. TSPI_lineMakeCall_postProcess(
  3207. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  3208. LONG lRes,
  3209. PDWORD_PTR callStateMsgParams
  3210. )
  3211. {
  3212. LONG lSuc;
  3213. HDRVLINE hdLine;
  3214. PDRVLINE pLine;
  3215. HDRVCALL hdCall;
  3216. PDRVCALL pCall;
  3217. TspLog(DL_TRACE, "lineMakeCall_post: lRes(%x)", lRes);
  3218. hdCall = (HDRVCALL)(pAsyncReqWrapper->dwRequestSpecific);
  3219. lSuc = GetLineHandleFromCallHandle(hdCall, &hdLine);
  3220. if (lSuc != TAPI_SUCCESS)
  3221. {
  3222. return lSuc;
  3223. }
  3224. lSuc = GetLineObjWithReadLock(hdLine, &pLine);
  3225. if (lSuc != TAPI_SUCCESS)
  3226. {
  3227. return lSuc;
  3228. }
  3229. lSuc = GetCallObjWithWriteLock(hdCall, &pCall);
  3230. if (lSuc != TAPI_SUCCESS)
  3231. {
  3232. ReleaseObjReadLock((HANDLE)hdLine);
  3233. return lSuc;
  3234. }
  3235. if (TAPI_SUCCESS == lRes)
  3236. {
  3237. PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
  3238. pAsyncReqWrapper->NdisTapiRequest.Data;
  3239. // check to see if a call state msg was received before we had
  3240. // the chance to process the completion notification, & if so
  3241. // fill in the msg params
  3242. if (pCall->dwPendingCallState)
  3243. {
  3244. callStateMsgParams[0] = (DWORD_PTR)pLine->htLine;
  3245. callStateMsgParams[1] = (DWORD_PTR)pCall->htCall;
  3246. callStateMsgParams[2] = pCall->dwPendingCallState;
  3247. callStateMsgParams[3] = pCall->dwPendingCallStateMode;
  3248. callStateMsgParams[4] = pCall->dwPendingMediaMode;
  3249. }
  3250. pCall->hd_Call = pNdisTapiMakeCall->hdCall;
  3251. pCall->bIncomplete = FALSE;
  3252. ReleaseObjWriteLock((HANDLE)hdCall);
  3253. ReleaseObjReadLock((HANDLE)hdLine);
  3254. }
  3255. else
  3256. {
  3257. pCall->dwKey = INVALID_KEY;
  3258. ReleaseObjWriteLock((HANDLE)hdCall);
  3259. ReleaseObjReadLock((HANDLE)hdLine);
  3260. CloseObjHandle((HANDLE)hdCall);
  3261. }
  3262. return lRes;
  3263. }
  3264. LONG
  3265. TSPIAPI
  3266. TSPI_lineMakeCall(
  3267. DRV_REQUESTID dwRequestID,
  3268. HDRVLINE hdLine,
  3269. HTAPICALL htCall,
  3270. LPHDRVCALL lphdCall,
  3271. LPCWSTR lpszDestAddress,
  3272. DWORD dwCountryCode,
  3273. LPLINECALLPARAMS const lpCallParams
  3274. )
  3275. {
  3276. static DWORD dwSum = 0;
  3277. LONG lRes;
  3278. PDRVLINE pLine;
  3279. PDRVCALL pCall;
  3280. HDRVCALL hdCall;
  3281. DWORD dwDALength, dwCPLength, dwOrgDALength;
  3282. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3283. PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall;
  3284. UINT nCodePage;
  3285. TspLog(DL_TRACE, "lineMakeCall(%d): reqID(%x), line(%p)",
  3286. ++dwSum, dwRequestID, hdLine);
  3287. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3288. if (lRes != TAPI_SUCCESS)
  3289. {
  3290. return lRes;
  3291. }
  3292. // alloc & init a DRVCALL
  3293. if (!(pCall = AllocCallObj(sizeof(DRVCALL))))
  3294. {
  3295. TspLog(DL_ERROR, "lineMakeCall: failed to create call obj");
  3296. ReleaseObjReadLock((HANDLE)hdLine);
  3297. return LINEERR_NOMEM;
  3298. }
  3299. pCall->dwKey = OUTBOUND_CALL_KEY;
  3300. pCall->dwDeviceID = pLine->dwDeviceID;
  3301. pCall->htCall = htCall;
  3302. pCall->hdLine = hdLine;
  3303. pCall->bIncomplete = TRUE;
  3304. // set nCodePage depending on the medium type
  3305. nCodePage = (pLine->MediaType == NdisWanMediumPppoe) ? CP_UTF8 : CP_ACP;
  3306. // init the request
  3307. dwOrgDALength = (lpszDestAddress ? (lstrlenW (lpszDestAddress) + 1) : 0);
  3308. dwDALength = (lpszDestAddress ?
  3309. GetDestAddressLength(lpszDestAddress, dwOrgDALength, &nCodePage) : 0);
  3310. dwCPLength = (lpCallParams ?
  3311. (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)) : 0);
  3312. if ((lRes = PrepareAsyncRequest(
  3313. OID_TAPI_MAKE_CALL, // opcode
  3314. pLine->dwDeviceID, // device id
  3315. dwRequestID, // request id
  3316. sizeof(NDIS_TAPI_MAKE_CALL) +
  3317. dwDALength + dwCPLength, // size
  3318. &pAsyncReqWrapper // ptr to ptr to request buffer
  3319. )) != TAPI_SUCCESS)
  3320. {
  3321. FreeCallObj(pCall);
  3322. ReleaseObjReadLock((HANDLE)hdLine);
  3323. return lRes;
  3324. }
  3325. pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
  3326. pAsyncReqWrapper->NdisTapiRequest.Data;
  3327. // make sure releasing read lock before calling OpenObjHandle()
  3328. // to avoid deadlock on acquiring write lock for the global mapper
  3329. ReleaseObjReadLock((HANDLE)hdLine);
  3330. lRes = OpenObjHandle(pCall, FreeCallObj, (HANDLE *)&hdCall);
  3331. if (lRes != TAPI_SUCCESS)
  3332. {
  3333. TspLog(DL_ERROR,
  3334. "lineMakeCall: failed to map obj(%p) to handle",
  3335. pCall);
  3336. FreeRequest(pAsyncReqWrapper);
  3337. FreeCallObj(pCall);
  3338. return lRes;
  3339. }
  3340. // reacquire the read lock
  3341. lRes = AcquireObjReadLock((HANDLE)hdLine);
  3342. if (lRes != TAPI_SUCCESS)
  3343. {
  3344. TspLog(DL_ERROR,
  3345. "lineMakeCall: failed to reacquire read lock for obj(%p)",
  3346. hdLine);
  3347. FreeRequest(pAsyncReqWrapper);
  3348. CloseObjHandle((HANDLE)hdCall);
  3349. return lRes;
  3350. }
  3351. // save the TSP handle
  3352. pCall->hdCall = hdCall;
  3353. pNdisTapiMakeCall->hdLine = pLine->hd_Line;
  3354. pNdisTapiMakeCall->htCall = (HTAPI_CALL)hdCall;
  3355. pNdisTapiMakeCall->ulDestAddressSize = dwDALength;
  3356. if (lpszDestAddress)
  3357. {
  3358. pNdisTapiMakeCall->ulDestAddressOffset =
  3359. sizeof(NDIS_TAPI_MAKE_CALL) + dwCPLength;
  3360. // old miniports expect strings to be ascii
  3361. WideCharToMultiByte(
  3362. nCodePage,
  3363. 0,
  3364. lpszDestAddress,
  3365. dwOrgDALength,
  3366. (LPSTR) (((LPBYTE) pNdisTapiMakeCall) +
  3367. pNdisTapiMakeCall->ulDestAddressOffset),
  3368. dwDALength,
  3369. NULL,
  3370. NULL
  3371. );
  3372. }
  3373. else
  3374. {
  3375. pNdisTapiMakeCall->ulDestAddressOffset = 0;
  3376. }
  3377. if (lpCallParams)
  3378. {
  3379. pNdisTapiMakeCall->bUseDefaultLineCallParams = FALSE;
  3380. CopyMemory(
  3381. &pNdisTapiMakeCall->LineCallParams,
  3382. lpCallParams,
  3383. lpCallParams->dwTotalSize
  3384. );
  3385. if (lpCallParams->dwOrigAddressSize != 0)
  3386. {
  3387. WideCharToMultiByte(
  3388. CP_ACP,
  3389. 0,
  3390. (LPCWSTR) (((LPBYTE) lpCallParams) +
  3391. lpCallParams->dwOrigAddressOffset),
  3392. lpCallParams->dwOrigAddressSize / sizeof (WCHAR),
  3393. (LPSTR) (((LPBYTE) &pNdisTapiMakeCall->LineCallParams) +
  3394. lpCallParams->dwOrigAddressOffset),
  3395. lpCallParams->dwOrigAddressSize,
  3396. NULL,
  3397. NULL
  3398. );
  3399. pNdisTapiMakeCall->LineCallParams.ulOrigAddressSize /= 2;
  3400. }
  3401. }
  3402. else
  3403. {
  3404. pNdisTapiMakeCall->bUseDefaultLineCallParams = TRUE;
  3405. }
  3406. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)hdCall;
  3407. pAsyncReqWrapper->pfnPostProcess = TSPI_lineMakeCall_postProcess;
  3408. *lphdCall = hdCall;
  3409. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pAsyncReqWrapper);
  3410. ReleaseObjReadLock((HANDLE)hdLine);
  3411. return lRes;
  3412. }
  3413. LONG
  3414. TSPIAPI
  3415. TSPI_lineNegotiateExtVersion(
  3416. DWORD dwDeviceID,
  3417. DWORD dwTSPIVersion,
  3418. DWORD dwLowVersion,
  3419. DWORD dwHighVersion,
  3420. LPDWORD lpdwExtVersion
  3421. )
  3422. {
  3423. static DWORD dwSum = 0;
  3424. LONG lRes;
  3425. PNDISTAPI_REQUEST pNdisTapiRequest;
  3426. PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion;
  3427. TspLog(DL_TRACE,
  3428. "lineNegotiateExtVersion(%d): deviceID(%x), TSPIV(%x), "\
  3429. "LowV(%x), HighV(%x)",
  3430. ++dwSum, dwDeviceID, dwTSPIVersion, dwLowVersion, dwHighVersion);
  3431. if ((lRes = PrepareSyncRequest(
  3432. OID_TAPI_NEGOTIATE_EXT_VERSION, // opcode
  3433. dwDeviceID, // device id
  3434. sizeof(NDIS_TAPI_NEGOTIATE_EXT_VERSION), // size of req data
  3435. &pNdisTapiRequest // ptr to ptr to req buf
  3436. )) != TAPI_SUCCESS)
  3437. {
  3438. return lRes;
  3439. }
  3440. pNdisTapiNegotiateExtVersion =
  3441. (PNDIS_TAPI_NEGOTIATE_EXT_VERSION)pNdisTapiRequest->Data;
  3442. pNdisTapiNegotiateExtVersion->ulDeviceID = dwDeviceID;
  3443. pNdisTapiNegotiateExtVersion->ulLowVersion = dwLowVersion;
  3444. pNdisTapiNegotiateExtVersion->ulHighVersion = dwHighVersion;
  3445. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3446. if (TAPI_SUCCESS == lRes)
  3447. {
  3448. *lpdwExtVersion = pNdisTapiNegotiateExtVersion->ulExtVersion;
  3449. // save version for future verification
  3450. lRes = SetNegotiatedExtVersion(dwDeviceID, *lpdwExtVersion);
  3451. }
  3452. else
  3453. {
  3454. TspLog(DL_WARNING, "lineNegotiateExtVersion: syncRequest returned(%x)",
  3455. lRes);
  3456. }
  3457. FreeRequest(pNdisTapiRequest);
  3458. return lRes;
  3459. }
  3460. LONG
  3461. TSPIAPI
  3462. TSPI_lineNegotiateTSPIVersion(
  3463. DWORD dwDeviceID,
  3464. DWORD dwLowVersion,
  3465. DWORD dwHighVersion,
  3466. LPDWORD lpdwTSPIVersion
  3467. )
  3468. {
  3469. static DWORD dwSum = 0;
  3470. LONG lRes;
  3471. TspLog(DL_TRACE, "lineNegotiateTSPIVersion(%d): deviceID(%x)",
  3472. ++dwSum, dwDeviceID);
  3473. *lpdwTSPIVersion = 0x00010003; // until the ndistapi spec widened
  3474. // save version for future verification
  3475. lRes = SetNegotiatedTSPIVersion(dwDeviceID, 0x00010003);
  3476. if (TAPI_SUCCESS == lRes)
  3477. {
  3478. TspLog(DL_INFO, "lineNegotiateTSPIVersion: TSPIVersion(%x)",
  3479. *lpdwTSPIVersion);
  3480. }
  3481. return lRes;
  3482. }
  3483. LONG
  3484. TSPIAPI
  3485. TSPI_lineOpen(
  3486. DWORD dwDeviceID,
  3487. HTAPILINE htLine,
  3488. LPHDRVLINE lphdLine,
  3489. DWORD dwTSPIVersion,
  3490. LINEEVENT lpfnEventProc
  3491. )
  3492. {
  3493. static DWORD dwSum = 0;
  3494. LONG lRes;
  3495. PDRVLINE pLine;
  3496. HDRVLINE hdLine;
  3497. PNDISTAPI_REQUEST pNdisTapiRequest;
  3498. PNDIS_TAPI_OPEN pNdisTapiOpen;
  3499. GUID Guid;
  3500. NDIS_WAN_MEDIUM_SUBTYPE MediaType;
  3501. PNDISTAPI_OPENDATA OpenData;
  3502. TspLog(DL_TRACE, "lineOpen(%d): deviceID(%x), htLine(%p)",
  3503. ++dwSum, dwDeviceID, htLine);
  3504. // alloc & init a DRVLINE
  3505. if (!(pLine = AllocLineObj(sizeof(DRVLINE))))
  3506. {
  3507. TspLog(DL_ERROR, "lineOpen: failed to create line obj");
  3508. return LINEERR_NOMEM;
  3509. }
  3510. pLine->dwKey = LINE_KEY;
  3511. pLine->dwDeviceID = dwDeviceID;
  3512. pLine->htLine = htLine;
  3513. if ((lRes = PrepareSyncRequest(
  3514. OID_TAPI_OPEN, // opcode
  3515. dwDeviceID, // device id
  3516. sizeof(NDIS_TAPI_OPEN) +
  3517. sizeof(NDISTAPI_OPENDATA), // size
  3518. &pNdisTapiRequest // ptr to ptr to request buffer
  3519. )) != TAPI_SUCCESS)
  3520. {
  3521. FreeLineObj(pLine);
  3522. return lRes;
  3523. }
  3524. pNdisTapiOpen = (PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
  3525. pNdisTapiOpen->ulDeviceID = dwDeviceID;
  3526. lRes = OpenObjHandle(pLine, FreeLineObj, (HANDLE *)&hdLine);
  3527. if (lRes != TAPI_SUCCESS)
  3528. {
  3529. TspLog(DL_ERROR, "lineOpen: failed to map obj(%p) to handle", pLine);
  3530. FreeLineObj(pLine);
  3531. FreeRequest(pNdisTapiRequest);
  3532. return lRes;
  3533. }
  3534. pNdisTapiOpen->htLine = (HTAPI_LINE)hdLine;
  3535. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3536. if (lRes != TAPI_SUCCESS)
  3537. {
  3538. CloseObjHandle((HANDLE)hdLine);
  3539. FreeRequest(pNdisTapiRequest);
  3540. return lRes;
  3541. }
  3542. OpenData = (PNDISTAPI_OPENDATA)
  3543. ((PUCHAR)pNdisTapiOpen + sizeof(NDIS_TAPI_OPEN));
  3544. MoveMemory(&pLine->Guid,&OpenData->Guid, sizeof(pLine->Guid));
  3545. pLine->MediaType = OpenData->MediaType;
  3546. TspLog(DL_INFO, "lineOpen: obj(%p)", hdLine);
  3547. TspLog(
  3548. DL_INFO,
  3549. "Guid: %4.4x-%4.4x-%2.2x%2.2x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x",
  3550. pLine->Guid.Data1, pLine->Guid.Data2,
  3551. pLine->Guid.Data3, pLine->Guid.Data4[0],
  3552. pLine->Guid.Data4[1], pLine->Guid.Data4[2],
  3553. pLine->Guid.Data4[3], pLine->Guid.Data4[4],
  3554. pLine->Guid.Data4[5], pLine->Guid.Data4[6],
  3555. pLine->Guid.Data4[7]
  3556. );
  3557. TspLog(DL_INFO, "MediaType(%ld)", pLine->MediaType);
  3558. pLine->hd_Line = pNdisTapiOpen->hdLine;
  3559. *lphdLine = hdLine;
  3560. lRes = CommitNegotiatedTSPIVersion(dwDeviceID);
  3561. FreeRequest(pNdisTapiRequest);
  3562. return lRes;
  3563. }
  3564. LONG
  3565. TSPIAPI
  3566. TSPI_lineSecureCall(
  3567. DRV_REQUESTID dwRequestID,
  3568. HDRVCALL hdCall
  3569. )
  3570. {
  3571. static DWORD dwSum = 0;
  3572. LONG lRes;
  3573. PDRVCALL pCall;
  3574. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3575. PNDIS_TAPI_SECURE_CALL pNdisTapiSecureCall;
  3576. TspLog(DL_TRACE, "lineSecureCall(%d): reqID(%x), call(%p)",
  3577. ++dwSum, dwRequestID, hdCall);
  3578. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3579. if (lRes != TAPI_SUCCESS)
  3580. {
  3581. return lRes;
  3582. }
  3583. if ((lRes = PrepareAsyncRequest(
  3584. OID_TAPI_SECURE_CALL, // opcode
  3585. pCall->dwDeviceID, // device id
  3586. dwRequestID, // req id
  3587. sizeof(NDIS_TAPI_SECURE_CALL), // size
  3588. &pAsyncReqWrapper // ptr to ptr to request buf
  3589. )) != TAPI_SUCCESS)
  3590. {
  3591. ReleaseObjReadLock((HANDLE)hdCall);
  3592. return lRes;
  3593. }
  3594. pNdisTapiSecureCall =
  3595. (PNDIS_TAPI_SECURE_CALL)pAsyncReqWrapper->NdisTapiRequest.Data;
  3596. pNdisTapiSecureCall->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3597. if(lRes != TAPI_SUCCESS)
  3598. {
  3599. FreeRequest(pAsyncReqWrapper);
  3600. return lRes;
  3601. }
  3602. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  3603. ReleaseObjReadLock((HANDLE)hdCall);
  3604. return lRes;
  3605. }
  3606. LONG
  3607. TSPIAPI
  3608. TSPI_lineSelectExtVersion(
  3609. HDRVLINE hdLine,
  3610. DWORD dwExtVersion
  3611. )
  3612. {
  3613. static DWORD dwSum = 0;
  3614. LONG lRes;
  3615. PDRVLINE pLine;
  3616. PNDISTAPI_REQUEST pNdisTapiRequest;
  3617. PNDIS_TAPI_SELECT_EXT_VERSION pNdisTapiSelectExtVersion;
  3618. TspLog(DL_TRACE, "lineSelectExtVersion(%d): line(%p), ExtV(%x)",
  3619. ++dwSum, hdLine, dwExtVersion);
  3620. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3621. if (lRes != TAPI_SUCCESS)
  3622. {
  3623. return lRes;
  3624. }
  3625. if ((lRes = PrepareSyncRequest(
  3626. OID_TAPI_SELECT_EXT_VERSION, // opcode
  3627. pLine->dwDeviceID, // device id
  3628. sizeof(NDIS_TAPI_SELECT_EXT_VERSION), // size
  3629. &pNdisTapiRequest // ptr to ptr to req buf
  3630. )) != TAPI_SUCCESS)
  3631. {
  3632. ReleaseObjReadLock((HANDLE)hdLine);
  3633. return lRes;
  3634. }
  3635. pNdisTapiSelectExtVersion =
  3636. (PNDIS_TAPI_SELECT_EXT_VERSION)pNdisTapiRequest->Data;
  3637. pNdisTapiSelectExtVersion->hdLine = pLine->hd_Line;
  3638. pNdisTapiSelectExtVersion->ulExtVersion = dwExtVersion;
  3639. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3640. if (TAPI_SUCCESS == lRes)
  3641. {
  3642. lRes = SetSelectedExtVersion(pLine->dwDeviceID, dwExtVersion);
  3643. }
  3644. FreeRequest(pNdisTapiRequest);
  3645. ReleaseObjReadLock((HANDLE)hdLine);
  3646. return lRes;
  3647. }
  3648. LONG
  3649. TSPIAPI
  3650. TSPI_lineSendUserUserInfo(
  3651. DRV_REQUESTID dwRequestID,
  3652. HDRVCALL hdCall,
  3653. LPCSTR lpsUserUserInfo,
  3654. DWORD dwSize
  3655. )
  3656. {
  3657. static DWORD dwSum = 0;
  3658. LONG lRes;
  3659. PDRVCALL pCall;
  3660. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3661. PNDIS_TAPI_SEND_USER_USER_INFO pNdisTapiSendUserUserInfo;
  3662. TspLog(DL_TRACE, "lineSendUserUserInfo(%d): reqID(%x), call(%p)",
  3663. ++dwSum, dwRequestID, hdCall);
  3664. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3665. if (lRes != TAPI_SUCCESS)
  3666. {
  3667. return lRes;
  3668. }
  3669. if ((lRes = PrepareAsyncRequest(
  3670. OID_TAPI_SEND_USER_USER_INFO, // opcode
  3671. pCall->dwDeviceID, // device id
  3672. dwRequestID, // request id
  3673. sizeof(NDIS_TAPI_SEND_USER_USER_INFO) + dwSize,
  3674. &pAsyncReqWrapper // ptr to ptr to req buf
  3675. )) != TAPI_SUCCESS)
  3676. {
  3677. ReleaseObjReadLock((HANDLE)hdCall);
  3678. return lRes;
  3679. }
  3680. pNdisTapiSendUserUserInfo = (PNDIS_TAPI_SEND_USER_USER_INFO)
  3681. pAsyncReqWrapper->NdisTapiRequest.Data;
  3682. pNdisTapiSendUserUserInfo->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3683. if(lRes != TAPI_SUCCESS)
  3684. {
  3685. FreeRequest(pAsyncReqWrapper);
  3686. return lRes;
  3687. }
  3688. if (pNdisTapiSendUserUserInfo->ulUserUserInfoSize = dwSize)
  3689. {
  3690. CopyMemory(
  3691. pNdisTapiSendUserUserInfo->UserUserInfo,
  3692. lpsUserUserInfo,
  3693. dwSize
  3694. );
  3695. }
  3696. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  3697. ReleaseObjReadLock((HANDLE)hdCall);
  3698. return lRes;
  3699. }
  3700. LONG
  3701. TSPIAPI
  3702. TSPI_lineSetAppSpecific(
  3703. HDRVCALL hdCall,
  3704. DWORD dwAppSpecific
  3705. )
  3706. {
  3707. static DWORD dwSum = 0;
  3708. LONG lRes;
  3709. PDRVCALL pCall;
  3710. PNDISTAPI_REQUEST pNdisTapiRequest;
  3711. PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific;
  3712. TspLog(DL_TRACE, "lineSetAppSpecific(%d): call(%p)", ++dwSum, hdCall);
  3713. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3714. if (lRes != TAPI_SUCCESS)
  3715. {
  3716. return lRes;
  3717. }
  3718. if ((lRes = PrepareSyncRequest(
  3719. OID_TAPI_SET_APP_SPECIFIC, // opcode
  3720. pCall->dwDeviceID, // device id
  3721. sizeof(NDIS_TAPI_SET_APP_SPECIFIC), // size
  3722. &pNdisTapiRequest // ptr to ptr to req buf
  3723. )) != TAPI_SUCCESS)
  3724. {
  3725. ReleaseObjReadLock((HANDLE)hdCall);
  3726. return lRes;
  3727. }
  3728. pNdisTapiSetAppSpecific =
  3729. (PNDIS_TAPI_SET_APP_SPECIFIC)pNdisTapiRequest->Data;
  3730. pNdisTapiSetAppSpecific->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3731. if(lRes != TAPI_SUCCESS)
  3732. {
  3733. FreeRequest(pNdisTapiRequest);
  3734. return lRes;
  3735. }
  3736. pNdisTapiSetAppSpecific->ulAppSpecific = dwAppSpecific;
  3737. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3738. FreeRequest(pNdisTapiRequest);
  3739. ReleaseObjReadLock((HANDLE)hdCall);
  3740. return lRes;
  3741. }
  3742. LONG
  3743. TSPIAPI
  3744. TSPI_lineSetCallParams(
  3745. DRV_REQUESTID dwRequestID,
  3746. HDRVCALL hdCall,
  3747. DWORD dwBearerMode,
  3748. DWORD dwMinRate,
  3749. DWORD dwMaxRate,
  3750. LPLINEDIALPARAMS const lpDialParams
  3751. )
  3752. {
  3753. static DWORD dwSum = 0;
  3754. LONG lRes;
  3755. PDRVCALL pCall;
  3756. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3757. PNDIS_TAPI_SET_CALL_PARAMS pNdisTapiSetCallParams;
  3758. TspLog(DL_TRACE, "lineSetCallParams(%d): reqID(%x), call(%p)",
  3759. ++dwSum, dwRequestID, hdCall);
  3760. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3761. if (lRes != TAPI_SUCCESS)
  3762. {
  3763. return lRes;
  3764. }
  3765. if ((lRes = PrepareAsyncRequest(
  3766. OID_TAPI_SET_CALL_PARAMS, // opcode
  3767. pCall->dwDeviceID, // device id
  3768. dwRequestID, // request id
  3769. sizeof(NDIS_TAPI_SET_CALL_PARAMS), // size
  3770. &pAsyncReqWrapper // ptr to ptr to request buf
  3771. )) != TAPI_SUCCESS)
  3772. {
  3773. ReleaseObjReadLock((HANDLE)hdCall);
  3774. return lRes;
  3775. }
  3776. pNdisTapiSetCallParams =
  3777. (PNDIS_TAPI_SET_CALL_PARAMS)pAsyncReqWrapper->NdisTapiRequest.Data;
  3778. pNdisTapiSetCallParams->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3779. if(lRes != TAPI_SUCCESS)
  3780. {
  3781. FreeRequest(pAsyncReqWrapper);
  3782. return lRes;
  3783. }
  3784. pNdisTapiSetCallParams->ulBearerMode = dwBearerMode;
  3785. pNdisTapiSetCallParams->ulMinRate = dwMinRate;
  3786. pNdisTapiSetCallParams->ulMaxRate = dwMaxRate;
  3787. if (lpDialParams)
  3788. {
  3789. pNdisTapiSetCallParams->bSetLineDialParams = TRUE;
  3790. CopyMemory(
  3791. &pNdisTapiSetCallParams->LineDialParams,
  3792. lpDialParams,
  3793. sizeof(LINE_DIAL_PARAMS)
  3794. );
  3795. }
  3796. else
  3797. {
  3798. pNdisTapiSetCallParams->bSetLineDialParams = FALSE;
  3799. }
  3800. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  3801. ReleaseObjReadLock((HANDLE)hdCall);
  3802. return lRes;
  3803. }
  3804. LONG
  3805. TSPIAPI
  3806. TSPI_lineSetDefaultMediaDetection(
  3807. HDRVLINE hdLine,
  3808. DWORD dwMediaModes
  3809. )
  3810. {
  3811. static DWORD dwSum = 0;
  3812. LONG lRes;
  3813. PDRVLINE pLine;
  3814. PNDISTAPI_REQUEST pNdisTapiRequest;
  3815. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pNdisTapiSetDefaultMediaDetection;
  3816. TspLog(DL_TRACE, "lineSetDefaultMediaDetection(%d): line(%p), mode(%x)",
  3817. ++dwSum, hdLine, dwMediaModes);
  3818. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3819. if (lRes != TAPI_SUCCESS)
  3820. {
  3821. return lRes;
  3822. }
  3823. if ((lRes = PrepareSyncRequest(
  3824. OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, // opcode
  3825. pLine->dwDeviceID, // device id
  3826. sizeof(NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION), // size
  3827. &pNdisTapiRequest // ptr to ptr to req buf
  3828. )) != TAPI_SUCCESS)
  3829. {
  3830. ReleaseObjReadLock((HANDLE)hdLine);
  3831. return lRes;
  3832. }
  3833. pNdisTapiSetDefaultMediaDetection =
  3834. (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) pNdisTapiRequest->Data;
  3835. pNdisTapiSetDefaultMediaDetection->hdLine = pLine->hd_Line;
  3836. pNdisTapiSetDefaultMediaDetection->ulMediaModes = dwMediaModes;
  3837. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3838. FreeRequest(pNdisTapiRequest);
  3839. ReleaseObjReadLock((HANDLE)hdLine);
  3840. return lRes;
  3841. }
  3842. LONG
  3843. TSPIAPI
  3844. TSPI_lineSetDevConfig(
  3845. DWORD dwDeviceID,
  3846. LPVOID const lpDeviceConfig,
  3847. DWORD dwSize,
  3848. LPCWSTR lpszDeviceClass
  3849. )
  3850. {
  3851. static DWORD dwSum = 0;
  3852. LONG lRes;
  3853. DWORD dwLength = lstrlenW(lpszDeviceClass) + 1;
  3854. PNDISTAPI_REQUEST pNdisTapiRequest;
  3855. PNDIS_TAPI_SET_DEV_CONFIG pNdisTapiSetDevConfig;
  3856. TspLog(DL_TRACE, "lineSetDevConfig(%d): deviceID(%x)", ++dwSum, dwDeviceID);
  3857. if ((lRes = PrepareSyncRequest(
  3858. OID_TAPI_SET_DEV_CONFIG, // opcode
  3859. dwDeviceID, // device id
  3860. sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwLength + dwSize,
  3861. &pNdisTapiRequest // ptr to ptr to req buf
  3862. )) != TAPI_SUCCESS)
  3863. {
  3864. return lRes;
  3865. }
  3866. pNdisTapiSetDevConfig = (PNDIS_TAPI_SET_DEV_CONFIG)pNdisTapiRequest->Data;
  3867. pNdisTapiSetDevConfig->ulDeviceID = dwDeviceID;
  3868. pNdisTapiSetDevConfig->ulDeviceClassSize = dwLength;
  3869. pNdisTapiSetDevConfig->ulDeviceClassOffset =
  3870. sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwSize - 1;
  3871. pNdisTapiSetDevConfig->ulDeviceConfigSize = dwSize;
  3872. CopyMemory(
  3873. pNdisTapiSetDevConfig->DeviceConfig,
  3874. lpDeviceConfig,
  3875. dwSize
  3876. );
  3877. // NOTE: old miniports expect strings to be ascii
  3878. WideCharToMultiByte(CP_ACP, 0, lpszDeviceClass, -1,
  3879. (LPSTR) (((LPBYTE) pNdisTapiSetDevConfig) +
  3880. pNdisTapiSetDevConfig->ulDeviceClassOffset),
  3881. dwLength, NULL, NULL);
  3882. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3883. FreeRequest(pNdisTapiRequest);
  3884. return lRes;
  3885. }
  3886. LONG
  3887. TSPIAPI
  3888. TSPI_lineSetMediaMode(
  3889. HDRVCALL hdCall,
  3890. DWORD dwMediaMode
  3891. )
  3892. {
  3893. static DWORD dwSum = 0;
  3894. LONG lRes;
  3895. PDRVCALL pCall;
  3896. PNDISTAPI_REQUEST pNdisTapiRequest;
  3897. PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode;
  3898. TspLog(DL_TRACE, "lineSetMediaMode(%d): call(%p), mode(%x)",
  3899. ++dwSum, hdCall, dwMediaMode);
  3900. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3901. if (lRes != TAPI_SUCCESS)
  3902. {
  3903. return lRes;
  3904. }
  3905. if ((lRes = PrepareSyncRequest(
  3906. OID_TAPI_SET_MEDIA_MODE, // opcode
  3907. pCall->dwDeviceID, // device id
  3908. sizeof(NDIS_TAPI_SET_MEDIA_MODE), // size
  3909. &pNdisTapiRequest // ptr to ptr to req buf
  3910. )) != TAPI_SUCCESS)
  3911. {
  3912. ReleaseObjReadLock((HANDLE)hdCall);
  3913. return lRes;
  3914. }
  3915. pNdisTapiSetMediaMode = (PNDIS_TAPI_SET_MEDIA_MODE)pNdisTapiRequest->Data;
  3916. pNdisTapiSetMediaMode->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3917. if(lRes != TAPI_SUCCESS)
  3918. {
  3919. FreeRequest(pNdisTapiRequest);
  3920. return lRes;
  3921. }
  3922. pNdisTapiSetMediaMode->ulMediaMode = dwMediaMode;
  3923. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3924. FreeRequest(pNdisTapiRequest);
  3925. ReleaseObjReadLock((HANDLE)hdCall);
  3926. return lRes;
  3927. }
  3928. LONG
  3929. TSPIAPI
  3930. TSPI_lineSetStatusMessages(
  3931. HDRVLINE hdLine,
  3932. DWORD dwLineStates,
  3933. DWORD dwAddressStates
  3934. )
  3935. {
  3936. static DWORD dwSum = 0;
  3937. LONG lRes;
  3938. PDRVLINE pLine;
  3939. PNDISTAPI_REQUEST pNdisTapiRequest;
  3940. PNDIS_TAPI_SET_STATUS_MESSAGES pNdisTapiSetStatusMessages;
  3941. TspLog(DL_TRACE, "lineSetStatusMessages(%d): line(%p)", ++dwSum, hdLine);
  3942. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3943. if (lRes != TAPI_SUCCESS)
  3944. {
  3945. return lRes;
  3946. }
  3947. if ((lRes = PrepareSyncRequest(
  3948. OID_TAPI_SET_STATUS_MESSAGES, // opcode
  3949. pLine->dwDeviceID, // device id
  3950. sizeof(NDIS_TAPI_SET_STATUS_MESSAGES), // size
  3951. &pNdisTapiRequest // ptr to ptr to req buf
  3952. )) != TAPI_SUCCESS)
  3953. {
  3954. ReleaseObjReadLock((HANDLE)hdLine);
  3955. return lRes;
  3956. }
  3957. pNdisTapiSetStatusMessages =
  3958. (PNDIS_TAPI_SET_STATUS_MESSAGES)pNdisTapiRequest->Data;
  3959. pNdisTapiSetStatusMessages->hdLine = pLine->hd_Line;
  3960. pNdisTapiSetStatusMessages->ulLineStates = dwLineStates;
  3961. pNdisTapiSetStatusMessages->ulAddressStates = dwAddressStates;
  3962. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3963. FreeRequest(pNdisTapiRequest);
  3964. ReleaseObjReadLock((HANDLE)hdLine);
  3965. return lRes;
  3966. }
  3967. //
  3968. // TAPI_providerXxx funcs
  3969. //
  3970. LONG
  3971. TSPIAPI
  3972. TSPI_providerEnumDevices(
  3973. DWORD dwPermanentProviderID,
  3974. LPDWORD lpdwNumLines,
  3975. LPDWORD lpdwNumPhones,
  3976. HPROVIDER hProvider,
  3977. LINEEVENT lpfnLineCreateProc,
  3978. PHONEEVENT lpfnPhoneCreateProc
  3979. )
  3980. {
  3981. TspLog(DL_TRACE, "providerEnumDevices: permProvID(%x)",
  3982. dwPermanentProviderID);
  3983. //
  3984. // NOTE: We really enum devs in providerInit, see the
  3985. // special case note there
  3986. //
  3987. *lpdwNumLines = 0;
  3988. *lpdwNumPhones = 0;
  3989. gpfnLineEvent = lpfnLineCreateProc;
  3990. ghProvider = hProvider;
  3991. return 0;
  3992. }
  3993. LONG
  3994. TSPIAPI
  3995. TSPI_providerInit(
  3996. DWORD dwTSPIVersion,
  3997. DWORD dwPermanentProviderID,
  3998. DWORD dwLineDeviceIDBase,
  3999. DWORD dwPhoneDeviceIDBase,
  4000. DWORD_PTR dwNumLines,
  4001. DWORD_PTR dwNumPhones,
  4002. ASYNC_COMPLETION lpfnCompletionProc,
  4003. LPDWORD lpdwTSPIOptions
  4004. )
  4005. {
  4006. LONG lRes = LINEERR_OPERATIONFAILED;
  4007. char szDeviceName[] = "NDISTAPI";
  4008. char szTargetPath[] = "\\Device\\NdisTapi";
  4009. char szCompleteDeviceName[] = "\\\\.\\NDISTAPI";
  4010. DWORD cbReturned, dwThreadID;
  4011. DWORD adwConnectInfo[2];
  4012. TspLog(DL_TRACE, "providerInit: perfProvID(%x), lineDevIDBase(%x)",
  4013. dwPermanentProviderID, dwLineDeviceIDBase);
  4014. //
  4015. // inform tapisrv that we support multiple simultaneous requests
  4016. // (the WAN wrapper handles request serialization for miniports)
  4017. //
  4018. *lpdwTSPIOptions = 0;
  4019. //
  4020. // create symbolic link to the kernel-mode driver
  4021. //
  4022. DefineDosDevice(DDD_RAW_TARGET_PATH, szDeviceName, szTargetPath);
  4023. //
  4024. // open driver handles
  4025. //
  4026. if ((ghDriverSync = CreateFileA(
  4027. szCompleteDeviceName,
  4028. GENERIC_READ | GENERIC_WRITE,
  4029. FILE_SHARE_READ | FILE_SHARE_WRITE,
  4030. NULL, // no security attrs
  4031. OPEN_EXISTING,
  4032. FILE_ATTRIBUTE_NORMAL,
  4033. NULL // no template file
  4034. )) == INVALID_HANDLE_VALUE)
  4035. {
  4036. TspLog(DL_ERROR, "providerInit: CreateFile(%s, sync) failed(%ld)",
  4037. szCompleteDeviceName, GetLastError());
  4038. goto providerInit_error0;
  4039. }
  4040. if ((ghDriverAsync = CreateFileA(
  4041. szCompleteDeviceName,
  4042. GENERIC_READ | GENERIC_WRITE,
  4043. FILE_SHARE_READ | FILE_SHARE_WRITE,
  4044. NULL, // no security attrs
  4045. OPEN_EXISTING,
  4046. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  4047. NULL // no template file
  4048. )) == INVALID_HANDLE_VALUE)
  4049. {
  4050. TspLog(DL_ERROR, "providerInit: CreateFile(%s, async) failed(%ld)",
  4051. szCompleteDeviceName, GetLastError());
  4052. goto providerInit_error1;
  4053. }
  4054. //
  4055. // create io completion port
  4056. //
  4057. if ((ghCompletionPort = CreateIoCompletionPort(ghDriverAsync, NULL, 0, 0))
  4058. == INVALID_HANDLE_VALUE)
  4059. {
  4060. TspLog(DL_ERROR, "providerInit: CreateIoCompletionPort failed(%ld)",
  4061. GetLastError());
  4062. goto providerInit_error2;
  4063. }
  4064. //
  4065. // connect to driver- we send it a device ID base & it returns
  4066. // the number of devices it supports
  4067. //
  4068. {
  4069. adwConnectInfo[0] = dwLineDeviceIDBase;
  4070. adwConnectInfo[1] = 1;
  4071. if (!DeviceIoControl(
  4072. ghDriverSync,
  4073. IOCTL_NDISTAPI_CONNECT,
  4074. adwConnectInfo,
  4075. 2 * sizeof(DWORD),
  4076. adwConnectInfo,
  4077. 2 * sizeof(DWORD),
  4078. &cbReturned,
  4079. (LPOVERLAPPED)NULL
  4080. ) ||
  4081. (cbReturned < sizeof(DWORD)))
  4082. {
  4083. TspLog(DL_ERROR, "providerInit: CONNECT failed(%ld)",
  4084. GetLastError());
  4085. goto providerInit_error3;
  4086. }
  4087. }
  4088. // init mapper, allocator and dev list
  4089. if (InitializeMapper() != TAPI_SUCCESS)
  4090. {
  4091. goto providerInit_error3_5;
  4092. }
  4093. InitAllocator();
  4094. //
  4095. // alloc the resources needed by the AsyncEventThread, and then
  4096. // create the thread
  4097. //
  4098. if ((gpAsyncEventsThreadInfo = (PASYNC_EVENTS_THREAD_INFO)
  4099. MALLOC(sizeof(ASYNC_EVENTS_THREAD_INFO))) == NULL)
  4100. {
  4101. TspLog(DL_ERROR, "providerInit: failed to alloc thread info");
  4102. goto providerInit_error4;
  4103. }
  4104. gpAsyncEventsThreadInfo->dwBufSize = EVENT_BUFFER_SIZE;
  4105. if ((gpAsyncEventsThreadInfo->pBuf = (PNDISTAPI_EVENT_DATA)
  4106. MALLOC(EVENT_BUFFER_SIZE)) == NULL)
  4107. {
  4108. TspLog(DL_ERROR, "providerInit: failed to alloc event buf");
  4109. goto providerInit_error5;
  4110. }
  4111. if ((gpAsyncEventsThreadInfo->hThread = CreateThread(
  4112. (LPSECURITY_ATTRIBUTES)NULL, // no security attrs
  4113. 0, // default stack size
  4114. (LPTHREAD_START_ROUTINE) // func addr
  4115. AsyncEventsThread,
  4116. (LPVOID)NULL, // thread param
  4117. 0, // create flags
  4118. &dwThreadID // thread id
  4119. )) == NULL)
  4120. {
  4121. TspLog(DL_ERROR, "providerInit: CreateThread failed(%ld)",
  4122. GetLastError());
  4123. goto providerInit_error7;
  4124. }
  4125. gdwRequestID = 1;
  4126. //
  4127. // !!! Special case for KMDDSP.TSP only !!!
  4128. //
  4129. // For KMDDSP.TSP only, TAPISRV.EXE will pass pointers in the
  4130. // dwNumLines/dwNumPhones variables rather than an actual
  4131. // number of lines/phones, thereby allowing the driver to tell
  4132. // TAPISRV.EXE how many devices are currently registered.
  4133. //
  4134. // This is really due to a design/interface problem in NDISTAPI.SYS.
  4135. // Since the current CONNECT IOCTLS expects both a device ID base &
  4136. // returns the num devs, we can't really do this in
  4137. // TSPI_providerEnumDevices as the device ID base is unknown
  4138. // at that point
  4139. //
  4140. *((LPDWORD)dwNumLines) = adwConnectInfo[0];
  4141. *((LPDWORD)dwNumPhones) = 0;
  4142. //
  4143. // if here success
  4144. //
  4145. gpfnCompletionProc = lpfnCompletionProc;
  4146. lRes = TAPI_SUCCESS;
  4147. goto providerInit_return;
  4148. //
  4149. // clean up resources if an error occured & then return
  4150. //
  4151. providerInit_error7:
  4152. FREE(gpAsyncEventsThreadInfo->pBuf);
  4153. providerInit_error5:
  4154. FREE(gpAsyncEventsThreadInfo);
  4155. providerInit_error4:
  4156. UninitAllocator();
  4157. UninitializeMapper();
  4158. providerInit_error3_5:
  4159. providerInit_error3:
  4160. CloseHandle(ghCompletionPort);
  4161. providerInit_error2:
  4162. CloseHandle(ghDriverAsync);
  4163. providerInit_error1:
  4164. CloseHandle(ghDriverSync);
  4165. providerInit_error0:
  4166. DefineDosDevice(DDD_REMOVE_DEFINITION, szDeviceName, NULL);
  4167. providerInit_return:
  4168. TspLog(DL_INFO, "providerInit: lRes(%x)", lRes);
  4169. return lRes;
  4170. }
  4171. LONG
  4172. TSPIAPI
  4173. TSPI_providerCreateLineDevice(
  4174. DWORD_PTR dwTempID,
  4175. DWORD dwDeviceID
  4176. )
  4177. {
  4178. DWORD cbReturned;
  4179. NDISTAPI_CREATE_INFO CreateInfo;
  4180. CreateInfo.TempID = dwTempID;
  4181. CreateInfo.DeviceID = dwDeviceID;
  4182. TspLog(DL_TRACE, "providerCreateLineDevice: tempID(%x), deviceID(%x)",
  4183. dwTempID, dwDeviceID);
  4184. if (!DeviceIoControl(
  4185. ghDriverSync,
  4186. IOCTL_NDISTAPI_CREATE,
  4187. &CreateInfo,
  4188. sizeof(CreateInfo),
  4189. &CreateInfo,
  4190. sizeof(CreateInfo),
  4191. &cbReturned,
  4192. (LPOVERLAPPED)NULL
  4193. ))
  4194. {
  4195. TspLog(DL_ERROR, "providerCreateLineDevice: failed(%ld) to create",
  4196. GetLastError());
  4197. return LINEERR_OPERATIONFAILED;
  4198. }
  4199. return TAPI_SUCCESS;
  4200. }
  4201. LONG
  4202. TSPIAPI
  4203. TSPI_providerShutdown(
  4204. DWORD dwTSPIVersion,
  4205. DWORD dwPermanentProviderID
  4206. )
  4207. {
  4208. char deviceName[] = "NDISTAPI";
  4209. ASYNC_REQUEST_WRAPPER asyncRequestWrapper;
  4210. TspLog(DL_TRACE, "providerShutdown: perfProvID(%x)", dwPermanentProviderID);
  4211. // @@@ all we ought to have to do here is send a DISCONNECT IOCTL
  4212. //
  4213. // Close the driver & remove the symbolic link
  4214. //
  4215. CancelIo(ghDriverSync);
  4216. CancelIo(ghDriverAsync);
  4217. CloseHandle (ghDriverSync);
  4218. CloseHandle (ghDriverAsync);
  4219. CloseHandle (ghCompletionPort);
  4220. DefineDosDevice (DDD_REMOVE_DEFINITION, deviceName, NULL);
  4221. WaitForSingleObject(gpAsyncEventsThreadInfo->hThread, INFINITE);
  4222. CloseHandle(gpAsyncEventsThreadInfo->hThread);
  4223. FREE(gpAsyncEventsThreadInfo->pBuf);
  4224. FREE(gpAsyncEventsThreadInfo);
  4225. UninitAllocator();
  4226. UninitializeMapper();
  4227. return TAPI_SUCCESS;
  4228. }
  4229. BOOL
  4230. WINAPI
  4231. DllMain(
  4232. HANDLE hDLL,
  4233. DWORD dwReason,
  4234. LPVOID lpReserved
  4235. )
  4236. {
  4237. switch (dwReason)
  4238. {
  4239. case DLL_PROCESS_ATTACH:
  4240. {
  4241. #if DBG
  4242. {
  4243. HKEY hKey;
  4244. DWORD dwDataSize, dwDataType;
  4245. TCHAR szTelephonyKey[] =
  4246. "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
  4247. TCHAR szKmddspDebugLevel[] = "KmddspDebugLevel";
  4248. RegOpenKeyEx(
  4249. HKEY_LOCAL_MACHINE,
  4250. szTelephonyKey,
  4251. 0,
  4252. KEY_ALL_ACCESS,
  4253. &hKey
  4254. );
  4255. dwDataSize = sizeof(DWORD);
  4256. gdwDebugLevel = DL_WARNING;
  4257. RegQueryValueEx(
  4258. hKey,
  4259. szKmddspDebugLevel,
  4260. 0,
  4261. &dwDataType,
  4262. (LPBYTE)&gdwDebugLevel,
  4263. &dwDataSize
  4264. );
  4265. RegCloseKey(hKey);
  4266. }
  4267. #endif
  4268. gdwTraceID = TraceRegisterA("KMDDSP");
  4269. ASSERT(gdwTraceID != INVALID_TRACEID);
  4270. TspLog(DL_TRACE, "DLL_PROCESS_ATTACH");
  4271. //
  4272. // Init global sync objects
  4273. //
  4274. InitializeCriticalSection(&gRequestIDCritSec);
  4275. InitLineDevList();
  4276. break;
  4277. }
  4278. case DLL_PROCESS_DETACH:
  4279. {
  4280. TspLog(DL_TRACE, "DLL_PROCESS_DETACH");
  4281. UninitLineDevList();
  4282. DeleteCriticalSection(&gRequestIDCritSec);
  4283. TraceDeregisterA(gdwTraceID);
  4284. break;
  4285. }
  4286. } // switch
  4287. return TRUE;
  4288. }