Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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