Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7440 lines
212 KiB

  1. //============================================================================
  2. // Copyright (c) 2000, Microsoft Corporation
  3. //
  4. // File: ndptsp.c
  5. //
  6. // History:
  7. // Dan Knudson (DanKn) 11-Apr-1995 Created
  8. // Richard Machin (RMachin) 05-05-97 NDIS 5.0 changes
  9. // Radu Simionescu (RaduS) 10-Feb-1999 UI config
  10. // Yi Sun (YiSun) June-29-2000 Rewriten
  11. //
  12. // Abstract:
  13. //============================================================================
  14. #define NDIS_TAPI_CURRENT_VERSION 0x00030000
  15. #define TAPI_CURRENT_VERSION NDIS_TAPI_CURRENT_VERSION
  16. #include "nt.h"
  17. #include "ntrtl.h"
  18. #include "nturtl.h"
  19. #include "windows.h"
  20. #include "rtutils.h"
  21. #include "winioctl.h"
  22. #include "ntddndis.h"
  23. #include "ndistapi.h"
  24. #include "ndpif.h"
  25. //
  26. // NOTE: the following are defined in both ndistapi.h & tapi.h (or tspi.h)
  27. // and cause (more or less non-interesting) build warnings, so we
  28. // undefine them after the first #include to do away with this
  29. //
  30. #undef LAST_LINEMEDIAMODE
  31. #undef TSPI_MESSAGE_BASE
  32. #undef LINE_NEWCALL
  33. #undef LINE_CALLDEVSPECIFIC
  34. #undef LINE_CREATE
  35. #include "tapi.h"
  36. #include "tspi.h"
  37. #include "ndptsp.h"
  38. #include "resource.h"
  39. #define OUTBOUND_CALL_KEY ((DWORD) 'OCAL')
  40. #define INBOUND_CALL_KEY ((DWORD) 'ICAL')
  41. #define LINE_KEY ((DWORD) 'KLIN')
  42. #define ASYNCREQWRAPPER_KEY ((DWORD) 'ARWK')
  43. #define MSP_KEY ((DWORD) 'MSPK')
  44. #define INVALID_KEY ((DWORD) 'XXXX')
  45. #define EVENT_BUFFER_SIZE 1024
  46. #define RCA_SAP_STRING L"WAN/RCA"
  47. #define NDPTSP_UIDLL L"NDPTSP.TSP"
  48. #define WINDOWS_REGKEY_ROOT L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion"
  49. #define NDPTSP_SUBKEY L"NdpTsp"
  50. #define NDPTSP_NOTIFY_SUBKEY L"ForceRefresh"
  51. #define NDPTSP_REGKEY_ROOT \
  52. WINDOWS_REGKEY_ROOT L"\\" NDPTSP_SUBKEY
  53. #define NDPTSP_NOTIFY_REGKEY_ROOT \
  54. NDPTSP_REGKEY_ROOT L"\\" NDPTSP_NOTIFY_SUBKEY
  55. typedef struct _NDP_MEDIA_TYPE
  56. {
  57. DWORD dwResourceID; // Resource ID for the localized string
  58. PWSTR pwszString;
  59. DWORD dwMediaMode;
  60. PWSTR pwszRegString; // Name of the registry value
  61. } NDP_MEDIA_TYPE;
  62. NDP_MEDIA_TYPE NdpModeArray[] = {
  63. IDS_TYPE_DIGITALDATA, NULL,
  64. LINEMEDIAMODE_DIGITALDATA, L"Digita lData",
  65. IDS_TYPE_INTERACTIVEVOICE, NULL,
  66. LINEMEDIAMODE_INTERACTIVEVOICE, L"Intera ctiveVoice",
  67. IDS_TYPE_G3FAX, NULL,
  68. LINEMEDIAMODE_G3FAX, L"G3Fax" ,
  69. IDS_TYPE_G4FAX, NULL,
  70. LINEMEDIAMODE_G4FAX, L"G4Fax"
  71. };
  72. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  73. #define NUM_NDP_MODES ARRAYSIZE(NdpModeArray)
  74. typedef struct _ADDRESS_MAP
  75. {
  76. PWSTR pwszAddress;
  77. DWORD dwAddressLength;
  78. struct _ADDRESS_MAP *pNext;
  79. struct _ADDRESS_MAP *pPrev;
  80. } ADDRESS_MAP, *PADDRESS_MAP;
  81. typedef struct _CONFIG_UI_CTX
  82. {
  83. PADDRESS_MAP pAddressMapListArray[NUM_NDP_MODES];
  84. HWND hwndListBox;
  85. DWORD dwCrtTypeIndex;
  86. } CONFIG_UI_CTX;
  87. //
  88. // help support
  89. //
  90. #define NDPTSP_HELP_FILE L"tapi.hlp"
  91. #ifndef IDH_DISABLEHELP
  92. #define IDH_DISABLEHELP ((DWORD)-1)
  93. #endif
  94. #define IDH_MEDIA_MAP_MEDIA_TYPE 10011
  95. #define IDH_MEDIA_MAP_ADDRESS_GROUP 10012
  96. #define IDH_MEDIA_MAP_ADDRESS_LIST 10013
  97. #define IDH_MEDIA_MAP_ADD_ADDRESS 10014
  98. #define IDH_MEDIA_MAP_DELETE_ADDRESS 10015
  99. #define IDH_MEDIA_ADD_ADD_ADDRESS 10016
  100. static const DWORD g_aHelpIDs_IDD_MEDIA_MAP[]=
  101. {
  102. IDC_MEDIA_TYPE, IDH_MEDIA_MAP_MEDIA_TYPE, // Drop-down list
  103. IDC_ADDRESS_GROUP, IDH_MEDIA_MAP_ADDRESS_GROUP, // Group box
  104. IDC_ADDRESS_LIST, IDH_MEDIA_MAP_ADDRESS_LIST, // List box
  105. IDC_ADD_ADDRESS, IDH_MEDIA_MAP_ADD_ADDRESS, // Add button
  106. IDC_DELETE_ADDRESS, IDH_MEDIA_MAP_DELETE_ADDRESS, // Delete button
  107. 0, 0
  108. };
  109. const DWORD g_aHelpIDs_IDD_MEDIA_ADD[]=
  110. {
  111. IDC_ADD_ADDRESS, IDH_MEDIA_ADD_ADD_ADDRESS, // edit box
  112. 0, 0
  113. };
  114. typedef LONG (*POSTPROCESSPROC)(PASYNC_REQUEST_WRAPPER, LONG, PDWORD_PTR);
  115. typedef struct _ASYNC_REQUEST_WRAPPER
  116. {
  117. // NOTE: overlapped must remain 1st field in this struct
  118. OVERLAPPED Overlapped;
  119. DWORD dwKey;
  120. DWORD dwRequestID;
  121. POSTPROCESSPROC pfnPostProcess;
  122. CRITICAL_SECTION CritSec;
  123. ULONG RefCount;
  124. DWORD_PTR dwRequestSpecific;
  125. // NOTE: NdisTapiRequest must follow a ptr to avoid alignment problem
  126. NDISTAPI_REQUEST NdisTapiRequest;
  127. } ASYNC_REQUEST_WRAPPER, *PASYNC_REQUEST_WRAPPER;
  128. #define REF_ASYNC_REQUEST_WRAPPER(_pAsyncReqWrapper) \
  129. { \
  130. EnterCriticalSection(&_pAsyncReqWrapper->CritSec); \
  131. _pAsyncReqWrapper->RefCount++; \
  132. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  133. }
  134. #define DEREF_ASYNC_REQUEST_WRAPPER(_pAsyncReqWrapper) \
  135. { \
  136. EnterCriticalSection(&_pAsyncReqWrapper->CritSec); \
  137. if (--(_pAsyncReqWrapper->RefCount) == 0) { \
  138. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  139. DeleteCriticalSection(&_pAsyncReqWrapper->CritSec); \
  140. FreeRequest(_pAsyncReqWrapper); \
  141. _pAsyncReqWrapper = NULL; \
  142. } else { \
  143. LeaveCriticalSection(&_pAsyncReqWrapper->CritSec); \
  144. } \
  145. }
  146. typedef struct _ASYNC_EVENTS_THREAD_INFO
  147. {
  148. HANDLE hThread; // thread handle
  149. PNDISTAPI_EVENT_DATA pBuf; // ptr to a buf for async events
  150. DWORD dwBufSize; // size of the previous buffer
  151. } ASYNC_EVENTS_THREAD_INFO, *PASYNC_EVENTS_THREAD_INFO;
  152. typedef struct _DRVCALL
  153. {
  154. DWORD dwKey;
  155. DWORD dwDeviceID;
  156. HTAPICALL htCall; // TAPI's handle to the call
  157. HDRVCALL hdCall; // TSP's handle to the call
  158. HDRV_CALL hd_Call; // NDPROXY's call handle
  159. HDRVLINE hdLine; // TSP's handle to the line
  160. union
  161. {
  162. struct _DRVCALL *pPrev; // for inbound calls only
  163. DWORD dwPendingCallState; // for outbound calls only
  164. };
  165. union
  166. {
  167. struct _DRVCALL *pNext; // for inbound calls only
  168. DWORD dwPendingCallStateMode; // for outbound calls only
  169. };
  170. union
  171. {
  172. HTAPI_CALL ht_Call; // for inbound calls only
  173. DWORD dwPendingMediaMode; // for outbound calls only
  174. };
  175. BOOL bIncomplete;
  176. BOOL bDropped;
  177. } DRVCALL, *PDRVCALL;
  178. typedef struct _DRVMSPLINE
  179. {
  180. DWORD dwKey;
  181. DWORD dwAddressID;
  182. HDRVLINE hdLine;
  183. HTAPIMSPLINE htMSPLine;
  184. BOOL bStreamingStarted;
  185. } DRVMSPLINE, *PDRVMSPLINE;
  186. typedef struct _DRVLINE
  187. {
  188. DWORD dwKey;
  189. DWORD dwDeviceID;
  190. HTAPILINE htLine; // TAPI's line handle
  191. HDRV_LINE hd_Line; // NDPROXY's line handle
  192. PDRVCALL pInboundCalls; // inbound call list
  193. HANDLE hMSPMutex;
  194. PDRVMSPLINE pMSPLine;
  195. // the following two related to PNP/POWER
  196. GUID Guid;
  197. NDIS_WAN_MEDIUM_SUBTYPE MediaType;
  198. } DRVLINE, *PDRVLINE;
  199. // globals
  200. HANDLE ghDriverSync, ghDriverAsync, ghCompletionPort;
  201. PASYNC_EVENTS_THREAD_INFO gpAsyncEventsThreadInfo;
  202. PADDRESS_MAP gpAddressMapListArray[NUM_NDP_MODES];
  203. BOOL gbAddressMapListLoaded;
  204. CRITICAL_SECTION gAddressMapCritSec;
  205. DWORD gdwRequestID;
  206. ASYNC_COMPLETION gpfnCompletionProc;
  207. CRITICAL_SECTION gRequestIDCritSec;
  208. DWORD gInitResult;
  209. LINEEVENT gpfnLineEvent;
  210. HPROVIDER ghProvider;
  211. HINSTANCE ghInstance;
  212. //
  213. // CLSID for the RCA MSP.
  214. // @@@ we should grab this from an include directory in the MSP
  215. // sources, but that can only be done when the MSP/TSP source is
  216. // moved to the right place.
  217. //
  218. const CLSID CLSID_RCAMSP = {
  219. 0x11D59011, 0xCF23, 0x11d1,
  220. {0xA0, 0x2D, 0x00, 0xC0, 0x4F, 0xB6, 0x80, 0x9F}
  221. };
  222. //
  223. // debug globals
  224. //
  225. #if DBG
  226. DWORD gdwDebugLevel;
  227. #endif // DBG
  228. DWORD gdwTraceID = INVALID_TRACEID;
  229. //
  230. // creates a log using the RAS tracing utility
  231. // also prints it onto the attached debugger
  232. // if a debug build is running
  233. //
  234. VOID
  235. TspLog(
  236. IN DWORD dwDebugLevel,
  237. IN PCHAR pchFormat,
  238. ...
  239. )
  240. {
  241. va_list arglist;
  242. CHAR chNewFmt[256];
  243. va_start(arglist, pchFormat);
  244. switch (dwDebugLevel)
  245. {
  246. case DL_ERROR:
  247. strcpy(chNewFmt, "!!! ");
  248. break;
  249. case DL_WARNING:
  250. strcpy(chNewFmt, "!! ");
  251. break;
  252. case DL_INFO:
  253. strcpy(chNewFmt, "! ");
  254. break;
  255. case DL_TRACE:
  256. strcpy(chNewFmt, " ");
  257. break;
  258. }
  259. strcat(chNewFmt, pchFormat);
  260. #if DBG
  261. if (dwDebugLevel <= gdwDebugLevel)
  262. {
  263. #if 0
  264. DbgPrint("++NDPTSP++ ");
  265. DbgPrint(chNewFmt, arglist);
  266. DbgPrint("\n");
  267. #else
  268. char szBuffer[256];
  269. OutputDebugString("++NDPTSP++ ");
  270. wvsprintf(szBuffer, chNewFmt, arglist);
  271. OutputDebugString(szBuffer);
  272. OutputDebugString("\n");
  273. #endif
  274. }
  275. #endif // DBG
  276. if (gdwTraceID != INVALID_TRACEID)
  277. {
  278. TraceVprintfEx(gdwTraceID,
  279. (dwDebugLevel << 16) | TRACE_USE_MASK | TRACE_USE_MSEC,
  280. chNewFmt,
  281. arglist);
  282. }
  283. va_end(arglist);
  284. #if DBG
  285. if (DL_ERROR == dwDebugLevel)
  286. {
  287. //DebugBreak();
  288. }
  289. #endif // DBG
  290. }
  291. #if DBG
  292. #define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e,f)
  293. void
  294. PASCAL
  295. InsertVarDataString(
  296. LPVOID pStruct,
  297. LPDWORD pdwXxxSize,
  298. LPVOID pNewStruct,
  299. LPDWORD pdwNewXxxSize,
  300. DWORD dwFixedStructSize,
  301. char *pszFieldName
  302. )
  303. #else
  304. #define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e)
  305. void
  306. PASCAL
  307. InsertVarDataString(
  308. LPVOID pStruct,
  309. LPDWORD pdwXxxSize,
  310. LPVOID pNewStruct,
  311. LPDWORD pdwNewXxxSize,
  312. DWORD dwFixedStructSize
  313. )
  314. #endif
  315. {
  316. DWORD dwXxxSize, dwTotalSize, dwXxxOffset;
  317. //
  318. // If the dwXxxSize field of the old struct is non-zero, then
  319. // we need to do a ascii->unicode conversion on it. Check to
  320. // make sure that the size/offset are valid (if not set the
  321. // data size/offset in the new struct to 0) and then convert.
  322. //
  323. if ((dwXxxSize = *pdwXxxSize))
  324. {
  325. dwXxxOffset = *(pdwXxxSize + 1);
  326. #if DBG
  327. dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
  328. if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
  329. dwXxxOffset < dwFixedStructSize ||
  330. dwXxxOffset >= dwTotalSize ||
  331. (dwXxxSize + dwXxxOffset) > dwTotalSize)
  332. {
  333. TspLog(DL_ERROR,
  334. "INSERTVARDATASTRING: bad %s values - size(x%x), "\
  335. "offset(x%x)",
  336. pszFieldName, dwXxxSize, dwXxxOffset);
  337. *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
  338. return;
  339. }
  340. #endif
  341. // make sure the string is NULL terminated
  342. *(((LPBYTE)pStruct) + (dwXxxOffset + dwXxxSize - 1)) = '\0';
  343. MultiByteToWideChar(
  344. CP_ACP,
  345. MB_PRECOMPOSED,
  346. ((LPBYTE) pStruct) + dwXxxOffset,
  347. dwXxxSize,
  348. (LPWSTR) (((LPBYTE) pNewStruct) +
  349. ((LPVARSTRING) pNewStruct)->dwUsedSize),
  350. dwXxxSize * sizeof(WCHAR)
  351. );
  352. *pdwNewXxxSize = dwXxxSize * sizeof(WCHAR);
  353. *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
  354. ((LPVARSTRING) pNewStruct)->dwUsedSize += (dwXxxSize * sizeof(WCHAR));
  355. }
  356. }
  357. #if DBG
  358. #define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e,f)
  359. void
  360. PASCAL
  361. InsertVarData(
  362. LPVOID pStruct,
  363. LPDWORD pdwXxxSize,
  364. LPVOID pNewStruct,
  365. LPDWORD pdwNewXxxSize,
  366. DWORD dwFixedStructSize,
  367. char *pszFieldName
  368. )
  369. #else
  370. #define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e)
  371. void
  372. PASCAL
  373. InsertVarData(
  374. LPVOID pStruct,
  375. LPDWORD pdwXxxSize,
  376. LPVOID pNewStruct,
  377. LPDWORD pdwNewXxxSize,
  378. DWORD dwFixedStructSize
  379. )
  380. #endif
  381. {
  382. DWORD dwTotalSize, dwXxxSize, dwXxxOffset;
  383. if ((dwXxxSize = *pdwXxxSize))
  384. {
  385. dwXxxOffset = *(pdwXxxSize + 1);
  386. #if DBG
  387. dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
  388. if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
  389. dwXxxOffset < dwFixedStructSize ||
  390. dwXxxOffset >= dwTotalSize ||
  391. (dwXxxSize + dwXxxOffset) > dwTotalSize)
  392. {
  393. TspLog(DL_ERROR,
  394. "INSERTVARDATA: bad %s values - size(x%x), offset(x%x)",
  395. pszFieldName, dwXxxSize, dwXxxOffset);
  396. *pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
  397. return;
  398. }
  399. #endif
  400. CopyMemory(
  401. ((LPBYTE) pNewStruct) + ((LPVARSTRING) pNewStruct)->dwUsedSize,
  402. ((LPBYTE) pStruct) + dwXxxOffset,
  403. dwXxxSize
  404. );
  405. *pdwNewXxxSize = dwXxxSize;
  406. *(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
  407. ((LPVARSTRING) pNewStruct)->dwUsedSize += dwXxxSize;
  408. }
  409. }
  410. BOOL
  411. IsValidAddressChar(
  412. WCHAR wch
  413. )
  414. {
  415. // 0..9, A..F, * # .
  416. if (iswdigit(wch) || (wch >= L'A' && wch <= L'F') ||
  417. (wch >= L'a' && wch <= L'f') || wch == L'*' ||
  418. wch == L'#' || wch == L'.')
  419. {
  420. return TRUE;
  421. }
  422. return FALSE;
  423. }
  424. int
  425. CompareAddressChars(
  426. WCHAR wch1,
  427. WCHAR wch2
  428. )
  429. {
  430. // convert lowercase to uppercase
  431. wch1 = (WCHAR)towupper(wch1);
  432. wch2 = (WCHAR)towupper(wch2);
  433. return (int)(wch1-wch2);
  434. }
  435. int
  436. CompareAddresses(
  437. PCWSTR pwszAddress1,
  438. PCWSTR pwszAddress2
  439. )
  440. {
  441. WCHAR const * pCrt1,* pCrt2;
  442. int iResult;
  443. pCrt1 = pwszAddress1;
  444. pCrt2 = pwszAddress2;
  445. while (1)
  446. {
  447. // skip invalid chars from the first string
  448. while (*pCrt1 && !IsValidAddressChar(*pCrt1))
  449. {
  450. pCrt1++;
  451. }
  452. // skip invalid chars from the second string
  453. while (*pCrt2 && !IsValidAddressChar(*pCrt2))
  454. {
  455. pCrt2++;
  456. }
  457. if (!*pCrt1 && !*pCrt2)
  458. {
  459. return 0;
  460. }
  461. if (!*pCrt1)
  462. {
  463. return 1;
  464. }
  465. if (!*pCrt2)
  466. {
  467. return -1;
  468. }
  469. iResult = CompareAddressChars(*pCrt1, *pCrt2);
  470. if (iResult!=0)
  471. {
  472. return iResult;
  473. }
  474. pCrt1++;
  475. pCrt2++;
  476. }
  477. }
  478. BOOL
  479. FindAddressInOneList(
  480. PADDRESS_MAP pAddress,
  481. PCWSTR pwszAddress,
  482. PADDRESS_MAP *pAddressEntry
  483. )
  484. {
  485. while (pAddress!=NULL)
  486. {
  487. if (0 == CompareAddresses(pAddress->pwszAddress, pwszAddress))
  488. {
  489. // found !
  490. *pAddressEntry = pAddress;
  491. return TRUE;
  492. }
  493. pAddress = pAddress->pNext;
  494. }
  495. // not found
  496. return FALSE;
  497. }
  498. BOOL
  499. FindAddressInLists(
  500. PADDRESS_MAP *pAddressListArray,
  501. PCWSTR pwszAddress,
  502. DWORD *pdwModeIndex,
  503. PADDRESS_MAP *pAddressEntry
  504. )
  505. {
  506. DWORD dwModeCnt;
  507. for (dwModeCnt=0; dwModeCnt<NUM_NDP_MODES; dwModeCnt++)
  508. {
  509. if (FindAddressInOneList(pAddressListArray[dwModeCnt],
  510. pwszAddress,
  511. pAddressEntry))
  512. {
  513. *pdwModeIndex = dwModeCnt;
  514. return TRUE;
  515. }
  516. }
  517. // not found
  518. return FALSE;
  519. }
  520. void
  521. FreeAddressList(
  522. PADDRESS_MAP pAddressList
  523. )
  524. {
  525. PADDRESS_MAP pCrtCell;
  526. PADDRESS_MAP pPrevCell;
  527. pCrtCell = pAddressList;
  528. while (pCrtCell!=NULL)
  529. {
  530. if (pCrtCell->pwszAddress)
  531. {
  532. FREE(pCrtCell->pwszAddress);
  533. }
  534. pPrevCell = pCrtCell;
  535. pCrtCell = pCrtCell->pNext;
  536. FREE(pPrevCell);
  537. }
  538. }
  539. void
  540. FreeAllAddressLists(
  541. PADDRESS_MAP *pAddressListArray
  542. )
  543. {
  544. DWORD dwModeCnt;
  545. for (dwModeCnt=0; dwModeCnt<NUM_NDP_MODES; dwModeCnt++)
  546. {
  547. FreeAddressList(pAddressListArray[dwModeCnt]);
  548. }
  549. }
  550. INT_PTR
  551. CALLBACK
  552. ProviderConfigDetailDlgProc(
  553. HWND hDlg,
  554. UINT uMsg,
  555. WPARAM wParam,
  556. LPARAM lParam
  557. )
  558. {
  559. LONG lStatus;
  560. CONFIG_UI_CTX *UIContext;
  561. PADDRESS_MAP pAddressList;
  562. PADDRESS_MAP pAddress;
  563. PADDRESS_MAP pLastCell;
  564. DWORD dwStart;
  565. DWORD dwEnd;
  566. DWORD dwStrLength;
  567. DWORD dwTmp;
  568. PADDRESS_MAP pAddressEntry;
  569. PWSTR pwszAddress = NULL;
  570. PWSTR pwszCrt;
  571. WCHAR wszTmp[0x40];
  572. DWORD dwLengthW;
  573. DWORD dwErrorID;
  574. // decode
  575. switch (uMsg) {
  576. case WM_HELP:
  577. // F1 key or the "?" button is pressed
  578. (void) WinHelpW(((LPHELPINFO) lParam)->hItemHandle,
  579. NDPTSP_HELP_FILE,
  580. HELP_WM_HELP,
  581. (DWORD_PTR) (LPVOID) g_aHelpIDs_IDD_MEDIA_ADD);
  582. break;
  583. case WM_CONTEXTMENU:
  584. // Right-mouse click on a dialog control
  585. (void) WinHelpW((HWND) wParam,
  586. NDPTSP_HELP_FILE,
  587. HELP_CONTEXTMENU,
  588. (DWORD_PTR) (LPVOID) g_aHelpIDs_IDD_MEDIA_ADD);
  589. break;
  590. case WM_INITDIALOG:
  591. SetWindowLongPtr(hDlg,
  592. DWLP_USER,
  593. lParam);
  594. SetFocus(GetDlgItem(hDlg, IDC_ADD_ADDRESS));
  595. break;
  596. case WM_COMMAND:
  597. UIContext = (CONFIG_UI_CTX *)GetWindowLongPtr(hDlg, DWLP_USER);
  598. // decode command
  599. switch (LOWORD(wParam)) {
  600. case IDOK:
  601. pAddressList = NULL;
  602. pLastCell = NULL;
  603. dwErrorID = 0;
  604. // Get the text
  605. SendDlgItemMessageW(hDlg, IDC_ADD_ADDRESS, EM_SETSEL, 0, -1);
  606. SendDlgItemMessageW(hDlg, IDC_ADD_ADDRESS,
  607. EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
  608. dwEnd++; // add room for a NULL terminator
  609. dwStrLength = dwEnd*sizeof(WCHAR); // We have unicode chars
  610. pwszAddress = (dwEnd <= ARRAYSIZE(wszTmp)) ? wszTmp :
  611. MALLOC(dwStrLength);
  612. if (pwszAddress==NULL)
  613. {
  614. TspLog(DL_ERROR, "ProviderConfigDetailDlgProc: out of mem");
  615. break;
  616. }
  617. GetWindowTextW(GetDlgItem(hDlg, IDC_ADD_ADDRESS),
  618. pwszAddress, dwEnd);
  619. // Parse the string and create a local list
  620. pwszCrt = pwszAddress;
  621. while (*pwszCrt)
  622. {
  623. PWSTR pwszNext;
  624. WCHAR wch;
  625. // trim leading spaces
  626. while ((*pwszCrt == L' ') || (*pwszCrt == L','))
  627. {
  628. pwszCrt++;
  629. }
  630. // check if trimming the spaces toke us to the end of the string
  631. if (*pwszCrt)
  632. {
  633. // find next space and make it a temporary null
  634. // in the same time verify the address chars
  635. pwszNext = pwszCrt;
  636. while (*pwszNext &&
  637. (*pwszNext != L' ') &&
  638. (*pwszNext != L',') )
  639. {
  640. // All characters allowed
  641. //if (*pszNext>='0' && *pszNext<='9')
  642. pwszNext++;
  643. //else
  644. //{
  645. // dwErrorID = IDS_ERR_BAD_ADDRESS;
  646. // break;
  647. //}
  648. }
  649. if (dwErrorID)
  650. {
  651. break;
  652. }
  653. // save the char and replace with a temporary NULL
  654. wch = *pwszNext;
  655. *pwszNext = L'\0';
  656. // Test 1 - the address must not be already assigned
  657. if (FindAddressInLists(UIContext->pAddressMapListArray,
  658. pwszCrt,
  659. &dwTmp,
  660. &pAddressEntry))
  661. {
  662. dwErrorID = IDS_ERR_ALREADY_ASSIGNED;
  663. break;
  664. }
  665. // Test 2 - the address must be unique in the edit field
  666. if (FindAddressInOneList(pAddressList,
  667. pwszCrt,
  668. &pAddressEntry))
  669. {
  670. dwErrorID = IDS_ERR_DUPLICATE_ADDRESS;
  671. break;
  672. }
  673. // Create cell
  674. pAddress = (PADDRESS_MAP)MALLOC(sizeof(ADDRESS_MAP));
  675. if (pAddress == NULL)
  676. {
  677. dwErrorID = IDS_ERR_OOM;
  678. break;
  679. }
  680. dwLengthW = lstrlenW(pwszCrt);
  681. pAddress -> pwszAddress = MALLOC((dwLengthW + 1)*sizeof(WCHAR));
  682. if (pAddress->pwszAddress == NULL)
  683. {
  684. dwErrorID = IDS_ERR_OOM;
  685. FREE(pAddress);
  686. break;
  687. }
  688. lstrcpynW(pAddress->pwszAddress, pwszCrt, dwLengthW+1);
  689. pAddress->dwAddressLength = dwLengthW;
  690. // insert the entry in the local list
  691. pAddress->pNext = NULL;
  692. pAddress->pPrev = pLastCell;
  693. if (pLastCell)
  694. {
  695. pLastCell->pNext = pAddress;
  696. }
  697. else
  698. {
  699. pAddressList = pAddress;
  700. }
  701. pLastCell = pAddress;
  702. // replace our temporary null with it's previous value
  703. *pwszNext = wch;
  704. // advance the pszCrt point
  705. pwszCrt = pwszNext;
  706. }
  707. }
  708. if (pwszAddress!=wszTmp)
  709. {
  710. FREE(pwszAddress);
  711. }
  712. if (dwErrorID == 0)
  713. {
  714. // no error
  715. PADDRESS_MAP *ppInsertPoint;
  716. if (pAddressList)
  717. {
  718. // add the addresses to the list box
  719. for (pAddress=pAddressList;
  720. pAddress!=NULL;
  721. pAddress = pAddress->pNext)
  722. {
  723. SendMessageW(UIContext->hwndListBox,
  724. LB_ADDSTRING,
  725. 0,
  726. (LPARAM)pAddress->pwszAddress);
  727. }
  728. // glue the local list to the global one
  729. ppInsertPoint = &UIContext->pAddressMapListArray[
  730. UIContext->dwCrtTypeIndex];
  731. pLastCell->pNext = *ppInsertPoint;
  732. if (pLastCell->pNext)
  733. {
  734. pLastCell->pNext->pPrev = pLastCell;
  735. }
  736. *ppInsertPoint = pAddressList;
  737. }
  738. }
  739. else
  740. {
  741. WCHAR wszErrorMsg[0x100];
  742. // load error string
  743. LoadStringW(ghInstance,
  744. dwErrorID,
  745. wszErrorMsg,
  746. ARRAYSIZE(wszErrorMsg));
  747. // pop up error dialog
  748. MessageBoxW(hDlg,wszErrorMsg,NULL,MB_OK | MB_ICONEXCLAMATION);
  749. break;
  750. }
  751. // close dialog
  752. EndDialog(hDlg, 0);
  753. break;
  754. case IDCANCEL:
  755. // close dialog
  756. EndDialog(hDlg, 0);
  757. break;
  758. }
  759. break;
  760. }
  761. // success
  762. return FALSE;
  763. }
  764. LONG
  765. RegistrySaveConfig(
  766. PADDRESS_MAP *pAddressListArray
  767. )
  768. {
  769. HKEY hKey;
  770. HKEY hNotifyKey;
  771. LONG lRes;
  772. DWORD dwDisp;
  773. DWORD dwModeCnt;
  774. PADDRESS_MAP pAddress;
  775. DWORD dwLengthW;
  776. DWORD dwTotalLengthW;
  777. DWORD dwBufferLengthW;
  778. WCHAR wszBuffer[0x100];
  779. PWSTR pwszBuffer;
  780. PWSTR pwszCrt;
  781. // Open/create the key
  782. lRes = RegCreateKeyExW (HKEY_LOCAL_MACHINE,
  783. NDPTSP_REGKEY_ROOT,
  784. 0,
  785. NULL,
  786. REG_OPTION_NON_VOLATILE,
  787. KEY_READ | KEY_WRITE,
  788. NULL,
  789. &hKey,
  790. &dwDisp
  791. );
  792. if (lRes != ERROR_SUCCESS)
  793. {
  794. TspLog(DL_ERROR,
  795. "RegistrySaveConfig: open/create config key failed(%ld)",
  796. lRes);
  797. return lRes;
  798. }
  799. // for speed we use a local buffer. If it is too small, alloc one
  800. pwszBuffer = wszBuffer;
  801. dwBufferLengthW = ARRAYSIZE(wszBuffer);
  802. // for each type
  803. for (dwModeCnt=0; dwModeCnt<NUM_NDP_MODES; dwModeCnt++)
  804. {
  805. pAddress = pAddressListArray[dwModeCnt];
  806. // calculate the length needed for multistring
  807. dwTotalLengthW = 1;
  808. while (pAddress!=NULL)
  809. {
  810. dwTotalLengthW += pAddress->dwAddressLength + 1;
  811. pAddress = pAddress->pNext;
  812. }
  813. if (dwTotalLengthW > dwBufferLengthW)
  814. {
  815. // need a bigger buffer..
  816. if (pwszBuffer!=wszBuffer)
  817. {
  818. FREE(pwszBuffer);
  819. }
  820. pwszBuffer = MALLOC(dwTotalLengthW*sizeof(WCHAR));
  821. if (pwszBuffer == NULL)
  822. {
  823. TspLog(DL_ERROR, "RegistrySaveConfig: out of mem");
  824. RegCloseKey(hKey);
  825. return ERROR_OUTOFMEMORY;
  826. }
  827. dwBufferLengthW = dwTotalLengthW;
  828. }
  829. pAddress = pAddressListArray[dwModeCnt];
  830. pwszCrt = pwszBuffer;
  831. // linear search, hope not too many values...
  832. while (pAddress != NULL)
  833. {
  834. // Add the value to the multi string
  835. lstrcpyW(pwszCrt, pAddress->pwszAddress);
  836. // prepare for next string
  837. pwszCrt += pAddress->dwAddressLength + 1 ;
  838. pAddress = pAddress->pNext;
  839. }
  840. // final NULL
  841. *pwszCrt++ = L'\0';
  842. dwLengthW = (DWORD)(pwszCrt - pwszBuffer);
  843. lRes = RegSetValueExW(hKey,
  844. NdpModeArray[dwModeCnt].pwszRegString,
  845. 0,
  846. REG_MULTI_SZ,
  847. (PVOID)pwszBuffer,
  848. dwLengthW*sizeof(WCHAR));
  849. if (lRes != ERROR_SUCCESS)
  850. {
  851. TspLog(DL_ERROR, "RegistrySaveConfig: failed(%ld) to save value",
  852. lRes);
  853. break;
  854. }
  855. }
  856. // notify the server with a volatile key
  857. if (lRes==ERROR_SUCCESS)
  858. {
  859. lRes = RegCreateKeyExW(hKey,
  860. NDPTSP_NOTIFY_SUBKEY,
  861. 0,
  862. NULL,
  863. REG_OPTION_VOLATILE,
  864. KEY_READ,
  865. NULL,
  866. &hNotifyKey,
  867. &dwDisp);
  868. if (lRes == ERROR_SUCCESS)
  869. {
  870. RegCloseKey(hNotifyKey);
  871. }
  872. else
  873. {
  874. TspLog(DL_ERROR,
  875. "RegistrySaveConfig: failed(%ld) to create notify key",
  876. lRes);
  877. }
  878. }
  879. RegCloseKey(hKey);
  880. if (pwszBuffer != wszBuffer)
  881. {
  882. FREE(pwszBuffer);
  883. }
  884. return lRes;
  885. }
  886. LONG
  887. RegistryLoadConfig(
  888. PADDRESS_MAP *pAddressListArray
  889. )
  890. {
  891. HKEY hKey;
  892. LONG lRes;
  893. DWORD dwDisp;
  894. DWORD dwModeCnt;
  895. PADDRESS_MAP pAddress;
  896. PADDRESS_MAP pPrevCell;
  897. DWORD dwLength;
  898. DWORD dwLengthW;
  899. DWORD dwBufferLength;
  900. DWORD dwType;
  901. WCHAR wszBuffer[0x100];
  902. PWSTR pwszBuffer;
  903. PWSTR pwszCrt;
  904. FreeAllAddressLists(pAddressListArray);
  905. // Open/create the key
  906. lRes = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
  907. NDPTSP_REGKEY_ROOT,
  908. 0,
  909. NULL,
  910. REG_OPTION_NON_VOLATILE,
  911. KEY_READ ,
  912. NULL,
  913. &hKey,
  914. &dwDisp);
  915. if (lRes != ERROR_SUCCESS)
  916. {
  917. TspLog(DL_ERROR,
  918. "RegistryLoadConfig: open/create config key failed(%ld)",
  919. lRes);
  920. return lRes;
  921. }
  922. // for speed we use a local buffer. If it is too small, alloc one
  923. pwszBuffer = wszBuffer;
  924. dwBufferLength = sizeof(wszBuffer); // In bytes !!
  925. // for each type
  926. for (dwModeCnt=0; dwModeCnt<NUM_NDP_MODES; dwModeCnt++)
  927. {
  928. pPrevCell = NULL;
  929. // try to load the value. If the space is a problem, grow the buffer
  930. while (TRUE)
  931. {
  932. dwLength = dwBufferLength;
  933. lRes = RegQueryValueExW(hKey,
  934. NdpModeArray[dwModeCnt].pwszRegString,
  935. NULL,
  936. &dwType,
  937. (PVOID)pwszBuffer,
  938. &dwLength
  939. );
  940. if (lRes == ERROR_MORE_DATA)
  941. {
  942. // need a bigger buffer..
  943. if (pwszBuffer!=wszBuffer)
  944. {
  945. FREE(pwszBuffer);
  946. }
  947. pwszBuffer = MALLOC(dwLength);
  948. if (pwszBuffer == NULL)
  949. {
  950. TspLog(DL_ERROR, "RegistryLoadConfig: out of mem");
  951. RegCloseKey(hKey);
  952. return ERROR_OUTOFMEMORY;
  953. }
  954. dwBufferLength = dwLength;
  955. }
  956. else
  957. {
  958. break;
  959. }
  960. }
  961. if (lRes != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
  962. {
  963. // no values
  964. pwszBuffer[0] = L'\0';
  965. lRes = ERROR_SUCCESS;
  966. }
  967. // parse the multistring and create the list
  968. pwszCrt = pwszBuffer;
  969. while (*pwszCrt != L'\0')
  970. {
  971. // Alloc a cell
  972. pAddress = (PADDRESS_MAP)MALLOC(sizeof(ADDRESS_MAP));
  973. if (pAddress!= NULL)
  974. {
  975. dwLengthW = lstrlenW(pwszCrt);
  976. pAddress->pwszAddress = MALLOC((dwLengthW + 1)*sizeof(WCHAR));
  977. if (pAddress->pwszAddress != NULL)
  978. {
  979. lstrcpynW(pAddress->pwszAddress, pwszCrt, dwLengthW+1);
  980. pAddress->dwAddressLength = dwLengthW;
  981. // Insert in the list. Don't matter where, the lists are not sorted...
  982. pAddress->pNext = NULL;
  983. pAddress->pPrev = pPrevCell;
  984. if (pPrevCell)
  985. pPrevCell->pNext = pAddress;
  986. else
  987. pAddressListArray[dwModeCnt] = pAddress;
  988. pPrevCell = pAddress;
  989. }
  990. else
  991. {
  992. TspLog(DL_ERROR, "RegistryLoadConfig: out of mem");
  993. lRes = ERROR_OUTOFMEMORY;
  994. FREE(pAddress);
  995. break;
  996. }
  997. }
  998. else
  999. {
  1000. TspLog(DL_ERROR, "RegistryLoadConfig: out of mem");
  1001. lRes = ERROR_OUTOFMEMORY;
  1002. break;
  1003. }
  1004. // Next string
  1005. pwszCrt += dwLengthW + 1;
  1006. }
  1007. }
  1008. if (lRes!=ERROR_SUCCESS)
  1009. {
  1010. FreeAllAddressLists(pAddressListArray);
  1011. }
  1012. RegCloseKey(hKey);
  1013. if (pwszBuffer != wszBuffer)
  1014. {
  1015. FREE(pwszBuffer);
  1016. }
  1017. return lRes;
  1018. }
  1019. LONG
  1020. GetMediaModeForAddress(
  1021. PCWSTR pwszAddress,
  1022. DWORD * pdwMediaMode
  1023. )
  1024. {
  1025. LONG lRes;
  1026. DWORD dwModeIndex;
  1027. PADDRESS_MAP pAddressEntry;
  1028. EnterCriticalSection(&gAddressMapCritSec);
  1029. // force a reload:
  1030. // 1. at first call
  1031. // 2. after a change notification
  1032. if (gbAddressMapListLoaded)
  1033. {
  1034. lRes = RegDeleteKeyW(HKEY_LOCAL_MACHINE,
  1035. NDPTSP_NOTIFY_REGKEY_ROOT);
  1036. gbAddressMapListLoaded = (lRes != ERROR_SUCCESS);
  1037. }
  1038. lRes = ERROR_SUCCESS;
  1039. if (!gbAddressMapListLoaded)
  1040. {
  1041. TspLog(DL_TRACE, "GetMediaModeForAddress: reload the reg settings");
  1042. lRes = RegistryLoadConfig(gpAddressMapListArray);
  1043. }
  1044. if (lRes == ERROR_SUCCESS)
  1045. {
  1046. if (FindAddressInLists(gpAddressMapListArray,
  1047. pwszAddress,
  1048. &dwModeIndex,
  1049. &pAddressEntry))
  1050. {
  1051. *pdwMediaMode = NdpModeArray[dwModeIndex].dwMediaMode;
  1052. }
  1053. else
  1054. {
  1055. *pdwMediaMode = LINEMEDIAMODE_UNKNOWN;
  1056. }
  1057. }
  1058. LeaveCriticalSection(&gAddressMapCritSec);
  1059. return lRes;
  1060. }
  1061. void
  1062. UpdateAddressListBox(
  1063. PADDRESS_MAP pAddress,
  1064. HWND hwndListBox
  1065. )
  1066. {
  1067. SendMessageW(hwndListBox, LB_RESETCONTENT, 0, 0);
  1068. for (; pAddress!=NULL; pAddress = pAddress->pNext)
  1069. {
  1070. SendMessageW(hwndListBox,
  1071. LB_ADDSTRING,
  1072. 0,
  1073. (LPARAM)(pAddress->pwszAddress));
  1074. }
  1075. }
  1076. INT_PTR
  1077. CALLBACK
  1078. ProviderConfigDlgProc(
  1079. HWND hDlg,
  1080. UINT uMsg,
  1081. WPARAM wParam,
  1082. LPARAM lParam
  1083. )
  1084. {
  1085. LONG lStatus;
  1086. CONFIG_UI_CTX *UIContext;
  1087. DWORD dwModeIndex;
  1088. LONG lIndex;
  1089. LONG lRes;
  1090. WCHAR wszTmp[0x40];
  1091. // decode
  1092. switch (uMsg) {
  1093. case WM_HELP:
  1094. // F1 key or the "?" button is pressed
  1095. (void) WinHelpW(((LPHELPINFO)lParam)->hItemHandle,
  1096. NDPTSP_HELP_FILE,
  1097. HELP_WM_HELP,
  1098. (DWORD_PTR)(LPVOID)g_aHelpIDs_IDD_MEDIA_MAP);
  1099. break;
  1100. case WM_CONTEXTMENU:
  1101. // Right-mouse click on a dialog control
  1102. (void) WinHelpW((HWND)wParam,
  1103. NDPTSP_HELP_FILE,
  1104. HELP_CONTEXTMENU,
  1105. (DWORD_PTR)(LPVOID)g_aHelpIDs_IDD_MEDIA_MAP);
  1106. break;
  1107. case WM_INITDIALOG:
  1108. SetWindowLongPtr(
  1109. hDlg,
  1110. DWLP_USER,
  1111. lParam);
  1112. UIContext = (CONFIG_UI_CTX *)lParam;
  1113. // Get the registry values
  1114. lRes = RegistryLoadConfig(UIContext->pAddressMapListArray);
  1115. if (lRes != ERROR_SUCCESS)
  1116. {
  1117. WCHAR wszErrorMsg[0x100];
  1118. TspLog(DL_ERROR,
  1119. "ProviderConfigDlgProc: loading reg key failed(0x%08lx)",
  1120. lRes);
  1121. // load error string
  1122. LoadStringW(ghInstance,
  1123. IDS_ERR_REGLOAD,
  1124. wszErrorMsg,
  1125. ARRAYSIZE(wszErrorMsg));
  1126. // pop up error dialog
  1127. MessageBoxW(hDlg, wszErrorMsg, NULL, MB_OK | MB_ICONSTOP);
  1128. // stop dialog
  1129. EndDialog(hDlg, 0);
  1130. break;
  1131. }
  1132. // populate the combo box
  1133. for (dwModeIndex = 0; dwModeIndex < NUM_NDP_MODES; dwModeIndex++)
  1134. {
  1135. LoadStringW(ghInstance,
  1136. NdpModeArray[dwModeIndex].dwResourceID,
  1137. wszTmp,
  1138. ARRAYSIZE(wszTmp));
  1139. lIndex = (LONG)SendDlgItemMessageW(hDlg,
  1140. IDC_MEDIA_TYPE,
  1141. CB_ADDSTRING,
  1142. 0,
  1143. (LPARAM)wszTmp);
  1144. if (lIndex >= 0)
  1145. {
  1146. SendDlgItemMessage(hDlg,
  1147. IDC_MEDIA_TYPE,
  1148. CB_SETITEMDATA,
  1149. (WPARAM)lIndex,
  1150. (LPARAM)dwModeIndex);
  1151. }
  1152. else {
  1153. TspLog(DL_ERROR,
  1154. "ProviderConfigDlgProc: CB_ADDSTRING failed(%ld)",
  1155. lIndex);
  1156. }
  1157. }
  1158. // select the first
  1159. SendDlgItemMessage(hDlg, IDC_MEDIA_TYPE, CB_SETCURSEL, (WPARAM)0, 0);
  1160. dwModeIndex = (DWORD)SendDlgItemMessageW(hDlg,
  1161. IDC_MEDIA_TYPE,
  1162. CB_GETITEMDATA,
  1163. (WPARAM)0,
  1164. 0);
  1165. UIContext->hwndListBox = GetDlgItem(hDlg, IDC_ADDRESS_LIST);
  1166. UIContext->dwCrtTypeIndex = dwModeIndex;
  1167. // update the listbox
  1168. UpdateAddressListBox(UIContext->pAddressMapListArray[dwModeIndex],
  1169. UIContext->hwndListBox);
  1170. // Disable the Delete button
  1171. EnableWindow(GetDlgItem(hDlg, IDC_DELETE_ADDRESS), FALSE);
  1172. break;
  1173. case WM_COMMAND:
  1174. UIContext = (CONFIG_UI_CTX *)GetWindowLongPtr(hDlg, DWLP_USER);
  1175. // decode command
  1176. switch(LOWORD(wParam))
  1177. {
  1178. case IDC_ADD_ADDRESS:
  1179. if (HIWORD(wParam)==BN_CLICKED)
  1180. {
  1181. DialogBoxParamW(ghInstance,
  1182. (LPWSTR)MAKEINTRESOURCE(IDD_MEDIA_ADD),
  1183. hDlg,
  1184. ProviderConfigDetailDlgProc,
  1185. (LPARAM)UIContext);
  1186. }
  1187. break;
  1188. case IDC_DELETE_ADDRESS:
  1189. if (HIWORD(wParam)==BN_CLICKED)
  1190. {
  1191. lIndex = (LONG)SendDlgItemMessageW(hDlg,
  1192. IDC_ADDRESS_LIST,
  1193. LB_GETCURSEL,
  1194. 0,
  1195. 0);
  1196. if (lIndex>=0)
  1197. {
  1198. PWSTR pwszAddress = NULL;
  1199. DWORD dwLengthW;
  1200. DWORD dwMode;
  1201. PADDRESS_MAP pAddress;
  1202. dwLengthW =1 + (DWORD)SendDlgItemMessageW(hDlg,
  1203. IDC_ADDRESS_LIST,
  1204. LB_GETTEXTLEN,
  1205. (WPARAM)lIndex,
  1206. 0);
  1207. pwszAddress = (dwLengthW <= ARRAYSIZE(wszTmp)) ? wszTmp :
  1208. MALLOC(dwLengthW * sizeof(WCHAR));
  1209. if (pwszAddress)
  1210. {
  1211. SendDlgItemMessageW(hDlg,
  1212. IDC_ADDRESS_LIST,
  1213. LB_GETTEXT,
  1214. (WPARAM)lIndex,
  1215. (LPARAM)pwszAddress);
  1216. // Find the address in the lists
  1217. if (FindAddressInLists(UIContext->pAddressMapListArray,
  1218. pwszAddress,
  1219. &dwMode,
  1220. &pAddress))
  1221. {
  1222. // delete from list
  1223. if (pAddress->pNext)
  1224. {
  1225. pAddress->pNext->pPrev = pAddress->pPrev;
  1226. }
  1227. if (pAddress->pPrev)
  1228. {
  1229. pAddress->pPrev->pNext = pAddress->pNext;
  1230. }
  1231. else
  1232. {
  1233. UIContext->pAddressMapListArray[dwMode] =
  1234. pAddress->pNext;
  1235. }
  1236. FREE(pAddress->pwszAddress);
  1237. FREE(pAddress);
  1238. }
  1239. else
  1240. {
  1241. TspLog(DL_ERROR,
  1242. "ProviderConfigDlgProc: "\
  1243. "IDC_DELETE_ADDRESS - cannot find address");
  1244. }
  1245. // delete from list box
  1246. SendDlgItemMessageW(hDlg,
  1247. IDC_ADDRESS_LIST,
  1248. LB_DELETESTRING,
  1249. (WPARAM)lIndex,
  1250. 0);
  1251. // Try to select the previous one
  1252. if (lIndex > 0)
  1253. {
  1254. lIndex--;
  1255. }
  1256. if (LB_ERR == SendDlgItemMessageW(hDlg,
  1257. IDC_ADDRESS_LIST,
  1258. LB_SETCURSEL,
  1259. (WPARAM)lIndex,
  1260. 0))
  1261. {
  1262. // Disable the Delete button
  1263. EnableWindow(GetDlgItem(hDlg, IDC_DELETE_ADDRESS),
  1264. FALSE);
  1265. }
  1266. if (pwszAddress != wszTmp)
  1267. {
  1268. FREE(pwszAddress);
  1269. }
  1270. }
  1271. else
  1272. {
  1273. TspLog(DL_ERROR,
  1274. "ProviderConfigDlgProc: "\
  1275. "IDC_DELETE_ADDRESS - out of memory");
  1276. }
  1277. }
  1278. else
  1279. {
  1280. TspLog(DL_ERROR, "ProviderConfigDlgProc: "\
  1281. "IDC_DELETE_ADDRESS - no item selected");
  1282. }
  1283. }
  1284. break;
  1285. case IDOK:
  1286. RegistrySaveConfig(UIContext->pAddressMapListArray);
  1287. FreeAllAddressLists(UIContext->pAddressMapListArray);
  1288. // close dialog
  1289. EndDialog(hDlg, 0);
  1290. break;
  1291. case IDCANCEL:
  1292. FreeAllAddressLists(UIContext->pAddressMapListArray);
  1293. // close dialog
  1294. EndDialog(hDlg, 0);
  1295. break;
  1296. case IDC_MEDIA_TYPE:
  1297. if (HIWORD(wParam)==CBN_SELCHANGE)
  1298. {
  1299. // Disable the Delete button
  1300. EnableWindow(GetDlgItem(hDlg, IDC_DELETE_ADDRESS), FALSE);
  1301. // refresh the list box
  1302. lIndex = (LONG)SendDlgItemMessageW(hDlg,
  1303. IDC_MEDIA_TYPE,
  1304. CB_GETCURSEL,
  1305. 0,
  1306. 0);
  1307. dwModeIndex = (DWORD)SendDlgItemMessageW(hDlg,
  1308. IDC_MEDIA_TYPE,
  1309. CB_GETITEMDATA,
  1310. (WPARAM)lIndex,
  1311. 0);
  1312. // Update the context structure
  1313. UIContext->dwCrtTypeIndex = dwModeIndex;
  1314. // update the listbox
  1315. UpdateAddressListBox(
  1316. UIContext->pAddressMapListArray[dwModeIndex],
  1317. GetDlgItem(hDlg, IDC_ADDRESS_LIST));
  1318. }
  1319. break;
  1320. case IDC_ADDRESS_LIST:
  1321. if (HIWORD(wParam) == LBN_SELCHANGE)
  1322. {
  1323. // Enable the Delete button
  1324. EnableWindow(GetDlgItem(hDlg, IDC_DELETE_ADDRESS), TRUE);
  1325. }
  1326. break;
  1327. }
  1328. break;
  1329. }
  1330. // success
  1331. return FALSE;
  1332. }
  1333. static char *pszOidNames[] =
  1334. {
  1335. "Accept",
  1336. "Answer",
  1337. "Close",
  1338. "CloseCall",
  1339. "ConditionalMediaDetection",
  1340. "ConfigDialog",
  1341. "DevSpecific",
  1342. "Dial",
  1343. "Drop",
  1344. "GetAddressCaps",
  1345. "GetAddressID",
  1346. "GetAddressStatus",
  1347. "GetCallAddressID",
  1348. "GetCallInfo",
  1349. "GetCallStatus",
  1350. "GetDevCaps",
  1351. "GetDevConfig",
  1352. "GetExtensionID",
  1353. "GetID",
  1354. "GetLineDevStatus",
  1355. "MakeCall",
  1356. "NegotiateExtVersion",
  1357. "Open",
  1358. "ProviderInitialize",
  1359. "ProviderShutdown",
  1360. "SecureCall",
  1361. "SelectExtVersion",
  1362. "SendUserUserInfo",
  1363. "SetAppSpecific",
  1364. "StCallParams",
  1365. "StDefaultMediaDetection",
  1366. "SetDevConfig",
  1367. "SetMediaMode",
  1368. "SetStatusMessages"
  1369. };
  1370. //
  1371. // translates NDIS TAPI status codes into LINEERR_XXX
  1372. //
  1373. LONG
  1374. WINAPI
  1375. TranslateDriverResult(
  1376. ULONG ulRes
  1377. )
  1378. {
  1379. typedef struct _RESULT_LOOKUP
  1380. {
  1381. ULONG NdisTapiResult;
  1382. LONG TapiResult;
  1383. } RESULT_LOOKUP, *PRESULT_LOOKUP;
  1384. typedef ULONG NDIS_STATUS;
  1385. #define NDIS_STATUS_SUCCESS 0x00000000L
  1386. #define NDIS_STATUS_RESOURCES 0xC000009AL
  1387. #define NDIS_STATUS_FAILURE 0xC0000001L
  1388. #define NDIS_STATUS_INVALID_OID 0xC0010017L
  1389. static RESULT_LOOKUP aResults[] =
  1390. {
  1391. //
  1392. // Defined in NDIS.H
  1393. //
  1394. { NDIS_STATUS_SUCCESS ,0 },
  1395. //
  1396. // These errors are defined in NDISTAPI.H
  1397. //
  1398. { NDIS_STATUS_TAPI_ADDRESSBLOCKED ,LINEERR_ADDRESSBLOCKED },
  1399. { NDIS_STATUS_TAPI_BEARERMODEUNAVAIL ,LINEERR_BEARERMODEUNAVAIL },
  1400. { NDIS_STATUS_TAPI_CALLUNAVAIL ,LINEERR_CALLUNAVAIL },
  1401. { NDIS_STATUS_TAPI_DIALBILLING ,LINEERR_DIALBILLING },
  1402. { NDIS_STATUS_TAPI_DIALDIALTONE ,LINEERR_DIALDIALTONE },
  1403. { NDIS_STATUS_TAPI_DIALPROMPT ,LINEERR_DIALPROMPT },
  1404. { NDIS_STATUS_TAPI_DIALQUIET ,LINEERR_DIALQUIET },
  1405. { NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION,LINEERR_INCOMPATIBLEEXTVERSION},
  1406. { NDIS_STATUS_TAPI_INUSE ,LINEERR_INUSE },
  1407. { NDIS_STATUS_TAPI_INVALADDRESS ,LINEERR_INVALADDRESS },
  1408. { NDIS_STATUS_TAPI_INVALADDRESSID ,LINEERR_INVALADDRESSID },
  1409. { NDIS_STATUS_TAPI_INVALADDRESSMODE ,LINEERR_INVALADDRESSMODE },
  1410. { NDIS_STATUS_TAPI_INVALBEARERMODE ,LINEERR_INVALBEARERMODE },
  1411. { NDIS_STATUS_TAPI_INVALCALLHANDLE ,LINEERR_INVALCALLHANDLE },
  1412. { NDIS_STATUS_TAPI_INVALCALLPARAMS ,LINEERR_INVALCALLPARAMS },
  1413. { NDIS_STATUS_TAPI_INVALCALLSTATE ,LINEERR_INVALCALLSTATE },
  1414. { NDIS_STATUS_TAPI_INVALDEVICECLASS ,LINEERR_INVALDEVICECLASS },
  1415. { NDIS_STATUS_TAPI_INVALLINEHANDLE ,LINEERR_INVALLINEHANDLE },
  1416. { NDIS_STATUS_TAPI_INVALLINESTATE ,LINEERR_INVALLINESTATE },
  1417. { NDIS_STATUS_TAPI_INVALMEDIAMODE ,LINEERR_INVALMEDIAMODE },
  1418. { NDIS_STATUS_TAPI_INVALRATE ,LINEERR_INVALRATE },
  1419. { NDIS_STATUS_TAPI_NODRIVER ,LINEERR_NODRIVER },
  1420. { NDIS_STATUS_TAPI_OPERATIONUNAVAIL ,LINEERR_OPERATIONUNAVAIL },
  1421. { NDIS_STATUS_TAPI_RATEUNAVAIL ,LINEERR_RATEUNAVAIL },
  1422. { NDIS_STATUS_TAPI_RESOURCEUNAVAIL ,LINEERR_RESOURCEUNAVAIL },
  1423. { NDIS_STATUS_TAPI_STRUCTURETOOSMALL ,LINEERR_STRUCTURETOOSMALL },
  1424. { NDIS_STATUS_TAPI_USERUSERINFOTOOBIG ,LINEERR_USERUSERINFOTOOBIG },
  1425. { NDIS_STATUS_TAPI_ALLOCATED ,LINEERR_ALLOCATED },
  1426. { NDIS_STATUS_TAPI_INVALADDRESSSTATE ,LINEERR_INVALADDRESSSTATE },
  1427. { NDIS_STATUS_TAPI_INVALPARAM ,LINEERR_INVALPARAM },
  1428. { NDIS_STATUS_TAPI_NODEVICE ,LINEERR_NODEVICE },
  1429. //
  1430. // These errors are defined in NDIS.H
  1431. //
  1432. { NDIS_STATUS_RESOURCES ,LINEERR_NOMEM },
  1433. { NDIS_STATUS_FAILURE ,LINEERR_OPERATIONFAILED },
  1434. { NDIS_STATUS_INVALID_OID ,LINEERR_OPERATIONFAILED },
  1435. //
  1436. //
  1437. //
  1438. { NDISTAPIERR_UNINITIALIZED ,LINEERR_OPERATIONFAILED },
  1439. { NDISTAPIERR_BADDEVICEID ,LINEERR_OPERATIONFAILED },
  1440. { NDISTAPIERR_DEVICEOFFLINE ,LINEERR_OPERATIONFAILED },
  1441. //
  1442. // The terminating fields
  1443. //
  1444. { 0xffffffff, 0xffffffff }
  1445. };
  1446. int i;
  1447. for (i = 0; aResults[i].NdisTapiResult != 0xffffffff; i++)
  1448. {
  1449. if (ulRes == aResults[i].NdisTapiResult)
  1450. {
  1451. return (aResults[i].TapiResult);
  1452. }
  1453. }
  1454. TspLog(DL_WARNING, "TranslateDriverResult: unknown driver result(%x)",
  1455. ulRes);
  1456. return LINEERR_OPERATIONFAILED;
  1457. }
  1458. //
  1459. // NOTE: for functions that need to acquire (read, write) locks for both
  1460. // a line and a call, we enforce the order to be line first, call
  1461. // second to avoid potential DEADLOCK.
  1462. //
  1463. LONG
  1464. GetLineObjWithReadLock(
  1465. IN HDRVLINE hdLine,
  1466. OUT PDRVLINE *ppLine
  1467. )
  1468. {
  1469. LONG lRes;
  1470. PDRVLINE pLine;
  1471. lRes = GetObjWithReadLock((HANDLE)hdLine, &pLine);
  1472. if (lRes != TAPI_SUCCESS)
  1473. {
  1474. return LINEERR_INVALLINEHANDLE;
  1475. }
  1476. ASSERT(pLine != NULL);
  1477. if (pLine->dwKey != LINE_KEY)
  1478. {
  1479. TspLog(DL_WARNING, "GetLineObjWithReadLock: obj(%p) has bad key(%x)",
  1480. hdLine, pLine->dwKey);
  1481. ReleaseObjReadLock((HANDLE)hdLine);
  1482. return LINEERR_INVALLINEHANDLE;
  1483. }
  1484. *ppLine = pLine;
  1485. return lRes;
  1486. }
  1487. LONG
  1488. GetLineObjWithWriteLock(
  1489. IN HDRVLINE hdLine,
  1490. OUT PDRVLINE *ppLine
  1491. )
  1492. {
  1493. LONG lRes;
  1494. PDRVLINE pLine;
  1495. lRes = GetObjWithWriteLock((HANDLE)hdLine, &pLine);
  1496. if (lRes != TAPI_SUCCESS)
  1497. {
  1498. return LINEERR_INVALLINEHANDLE;
  1499. }
  1500. ASSERT(pLine != NULL);
  1501. if (pLine->dwKey != LINE_KEY)
  1502. {
  1503. TspLog(DL_WARNING, "GetLineObjWithWriteLock: obj(%p) has bad key(%x)",
  1504. hdLine, pLine->dwKey);
  1505. ReleaseObjWriteLock((HANDLE)hdLine);
  1506. return LINEERR_INVALLINEHANDLE;
  1507. }
  1508. *ppLine = pLine;
  1509. return lRes;
  1510. }
  1511. LONG
  1512. GetMSPLineObjWithReadLock(
  1513. IN HDRVMSPLINE hdMSPLine,
  1514. OUT PDRVMSPLINE *ppMSPLine
  1515. )
  1516. {
  1517. LONG lRes;
  1518. PDRVMSPLINE pMSPLine;
  1519. lRes = GetObjWithReadLock((HANDLE)hdMSPLine, &pMSPLine);
  1520. if (lRes != TAPI_SUCCESS)
  1521. {
  1522. return LINEERR_INVALLINEHANDLE;
  1523. }
  1524. ASSERT(pMSPLine != NULL);
  1525. if (pMSPLine->dwKey != MSP_KEY)
  1526. {
  1527. TspLog(DL_WARNING, "GetMSPLineObjWithReadLock: obj(%p) has bad key(%x)",
  1528. hdMSPLine, pMSPLine->dwKey);
  1529. ReleaseObjReadLock((HANDLE)hdMSPLine);
  1530. return LINEERR_INVALLINEHANDLE;
  1531. }
  1532. *ppMSPLine = pMSPLine;
  1533. return lRes;
  1534. }
  1535. LONG
  1536. GetMSPLineObjWithWriteLock(
  1537. IN HDRVMSPLINE hdMSPLine,
  1538. OUT PDRVMSPLINE *ppMSPLine
  1539. )
  1540. {
  1541. LONG lRes;
  1542. PDRVMSPLINE pMSPLine;
  1543. lRes = GetObjWithWriteLock((HANDLE)hdMSPLine, &pMSPLine);
  1544. if (lRes != TAPI_SUCCESS)
  1545. {
  1546. return LINEERR_INVALLINEHANDLE;
  1547. }
  1548. ASSERT(pMSPLine != NULL);
  1549. if (pMSPLine->dwKey != MSP_KEY)
  1550. {
  1551. TspLog(DL_WARNING,
  1552. "GetMSPLineObjWithWriteLock: obj(%p) has bad key(%x)",
  1553. hdMSPLine, pMSPLine->dwKey);
  1554. ReleaseObjWriteLock((HANDLE)hdMSPLine);
  1555. return LINEERR_INVALLINEHANDLE;
  1556. }
  1557. *ppMSPLine = pMSPLine;
  1558. return lRes;
  1559. }
  1560. LONG
  1561. GetLineHandleFromMSPLineHandle(
  1562. IN HDRVMSPLINE hdMSPLine,
  1563. OUT HDRVLINE *phdLine
  1564. )
  1565. {
  1566. LONG lRes;
  1567. PDRVMSPLINE pMSPLine;
  1568. lRes = GetObjWithReadLock((HANDLE)hdMSPLine, &pMSPLine);
  1569. if (lRes != TAPI_SUCCESS)
  1570. {
  1571. return LINEERR_INVALLINEHANDLE;
  1572. }
  1573. ASSERT(pMSPLine != NULL);
  1574. if (pMSPLine->dwKey != MSP_KEY)
  1575. {
  1576. TspLog(DL_WARNING,
  1577. "GetLineHandleFromMSPLineHandle: obj(%p) has bad key(%x)",
  1578. hdMSPLine, pMSPLine->dwKey);
  1579. ReleaseObjReadLock((HANDLE)hdMSPLine);
  1580. return LINEERR_INVALLINEHANDLE;
  1581. }
  1582. *phdLine = pMSPLine->hdLine;
  1583. ReleaseObjReadLock((HANDLE)hdMSPLine);
  1584. return lRes;
  1585. }
  1586. LONG
  1587. GetCallObjWithReadLock(
  1588. IN HDRVCALL hdCall,
  1589. OUT PDRVCALL *ppCall
  1590. )
  1591. {
  1592. LONG lRes;
  1593. PDRVCALL pCall;
  1594. lRes = GetObjWithReadLock((HANDLE)hdCall, &pCall);
  1595. if (lRes != TAPI_SUCCESS)
  1596. {
  1597. return LINEERR_INVALCALLHANDLE;
  1598. }
  1599. ASSERT(pCall != NULL);
  1600. if (pCall->dwKey != INBOUND_CALL_KEY &&
  1601. pCall->dwKey != OUTBOUND_CALL_KEY)
  1602. {
  1603. TspLog(DL_WARNING, "GetCallObjWithReadLock: obj(%p) has bad key(%x)",
  1604. hdCall, pCall->dwKey);
  1605. ReleaseObjReadLock((HANDLE)hdCall);
  1606. return LINEERR_INVALCALLHANDLE;
  1607. }
  1608. *ppCall = pCall;
  1609. return lRes;
  1610. }
  1611. LONG
  1612. GetCallObjWithWriteLock(
  1613. IN HDRVCALL hdCall,
  1614. OUT PDRVCALL *ppCall
  1615. )
  1616. {
  1617. LONG lRes;
  1618. PDRVCALL pCall;
  1619. lRes = GetObjWithWriteLock((HANDLE)hdCall, &pCall);
  1620. if (lRes != TAPI_SUCCESS)
  1621. {
  1622. return LINEERR_INVALCALLHANDLE;
  1623. }
  1624. ASSERT(pCall != NULL);
  1625. if (pCall->dwKey != INBOUND_CALL_KEY &&
  1626. pCall->dwKey != OUTBOUND_CALL_KEY)
  1627. {
  1628. TspLog(DL_WARNING, "GetCallObjWithWriteLock: obj(%p) has bad key(%x)",
  1629. hdCall, pCall->dwKey);
  1630. ReleaseObjWriteLock((HANDLE)hdCall);
  1631. return LINEERR_INVALCALLHANDLE;
  1632. }
  1633. *ppCall = pCall;
  1634. return lRes;
  1635. }
  1636. LONG
  1637. GetLineHandleFromCallHandle(
  1638. IN HDRVCALL hdCall,
  1639. OUT HDRVLINE *phdLine
  1640. )
  1641. {
  1642. LONG lRes;
  1643. PDRVCALL pCall;
  1644. lRes = GetObjWithReadLock((HANDLE)hdCall, &pCall);
  1645. if (lRes != TAPI_SUCCESS)
  1646. {
  1647. return LINEERR_INVALCALLHANDLE;
  1648. }
  1649. ASSERT(pCall != NULL);
  1650. if (pCall->dwKey != INBOUND_CALL_KEY &&
  1651. pCall->dwKey != OUTBOUND_CALL_KEY)
  1652. {
  1653. TspLog(DL_WARNING,
  1654. "GetLineHandleFromCallHandle: obj(%p) has bad key(%x)",
  1655. hdCall, pCall->dwKey);
  1656. ReleaseObjReadLock((HANDLE)hdCall);
  1657. return LINEERR_INVALCALLHANDLE;
  1658. }
  1659. *phdLine = pCall->hdLine;
  1660. ReleaseObjReadLock((HANDLE)hdCall);
  1661. return lRes;
  1662. }
  1663. LONG
  1664. GetLineAndCallObjWithReadLock(
  1665. HTAPI_LINE ht_Line,
  1666. HTAPI_CALL ht_Call,
  1667. PDRVLINE *ppLine,
  1668. PDRVCALL *ppCall
  1669. )
  1670. {
  1671. LONG lRes;
  1672. PDRVCALL pCall;
  1673. PDRVLINE pLine;
  1674. lRes = GetLineObjWithReadLock((HDRVLINE)ht_Line, &pLine);
  1675. if (lRes != TAPI_SUCCESS)
  1676. {
  1677. return lRes;
  1678. }
  1679. *ppLine = pLine;
  1680. //
  1681. // figure out whether this is an inbound call or
  1682. // outbound call: for inbound calls, ht_Call is
  1683. // generated by NDPROXY and bit 0 is 1;
  1684. // for outbound calls, ht_Call is a TSP handle
  1685. // and we make sure that bit 0 is 0
  1686. //
  1687. if (ht_Call & 0x1)
  1688. {
  1689. // inbound call: we need to walk the list
  1690. // of inbound calls on this line and
  1691. // find the right one
  1692. if ((pCall = pLine->pInboundCalls) != NULL)
  1693. {
  1694. while (pCall && (pCall->ht_Call != ht_Call))
  1695. {
  1696. pCall = pCall->pNext;
  1697. }
  1698. }
  1699. if (NULL == pCall || pCall->dwKey != INBOUND_CALL_KEY)
  1700. {
  1701. TspLog(DL_WARNING,
  1702. "GetLineAndCallObjWithReadLock: "\
  1703. "inbound ht_call(%p) closed already",
  1704. ht_Call);
  1705. ReleaseObjReadLock((HANDLE)ht_Line);
  1706. return LINEERR_INVALCALLHANDLE;
  1707. }
  1708. // call the following to increase the ref count
  1709. lRes = AcquireObjReadLock((HANDLE)pCall->hdCall);
  1710. if (lRes != TAPI_SUCCESS)
  1711. {
  1712. ReleaseObjReadLock((HANDLE)ht_Line);
  1713. return lRes;
  1714. }
  1715. *ppCall = pCall;
  1716. return TAPI_SUCCESS;
  1717. }
  1718. // ht_Call is a TSP handle and the call is OUTBOUND
  1719. lRes = GetObjWithReadLock((HANDLE)ht_Call, &pCall);
  1720. if (lRes != TAPI_SUCCESS)
  1721. {
  1722. ReleaseObjReadLock((HANDLE)ht_Line);
  1723. return lRes;
  1724. }
  1725. ASSERT(pCall != NULL);
  1726. if (pCall->dwKey != OUTBOUND_CALL_KEY)
  1727. {
  1728. TspLog(DL_WARNING,
  1729. "GetLineAndCallObjWithReadLock: bad call handle(%p, %x)",
  1730. ht_Call, pCall->dwKey);
  1731. ReleaseObjReadLock((HANDLE)ht_Call);
  1732. ReleaseObjReadLock((HANDLE)ht_Line);
  1733. return LINEERR_INVALCALLHANDLE;
  1734. }
  1735. *ppCall = pCall;
  1736. return TAPI_SUCCESS;
  1737. }
  1738. //
  1739. // allocates mem for a NDISTAPI_REQUEST plus some initialization
  1740. //
  1741. LONG
  1742. WINAPI
  1743. PrepareSyncRequest(
  1744. ULONG Oid,
  1745. ULONG ulDeviceID,
  1746. DWORD dwDataSize,
  1747. PNDISTAPI_REQUEST *ppNdisTapiRequest
  1748. )
  1749. {
  1750. PNDISTAPI_REQUEST pNdisTapiRequest =
  1751. (PNDISTAPI_REQUEST)AllocRequest(dwDataSize + sizeof(NDISTAPI_REQUEST));
  1752. if (NULL == pNdisTapiRequest)
  1753. {
  1754. TspLog(DL_ERROR,
  1755. "PrepareSyncRequest: failed to alloc sync req for oid(%x)",
  1756. Oid);
  1757. return LINEERR_NOMEM;
  1758. }
  1759. pNdisTapiRequest->Oid = Oid;
  1760. pNdisTapiRequest->ulDeviceID = ulDeviceID;
  1761. pNdisTapiRequest->ulDataSize = dwDataSize;
  1762. EnterCriticalSection(&gRequestIDCritSec);
  1763. // setting ulRequestId of NDIS_TAPI_xxxx
  1764. if ((*((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
  1765. {
  1766. gdwRequestID = 1;
  1767. }
  1768. LeaveCriticalSection(&gRequestIDCritSec);
  1769. *ppNdisTapiRequest = pNdisTapiRequest;
  1770. return TAPI_SUCCESS;
  1771. }
  1772. //
  1773. // allocates mem for a ASYNC_REQUEST_WRAPPER plus some initialization
  1774. //
  1775. LONG
  1776. WINAPI
  1777. PrepareAsyncRequest(
  1778. ULONG Oid,
  1779. ULONG ulDeviceID,
  1780. DWORD dwRequestID,
  1781. DWORD dwDataSize,
  1782. PASYNC_REQUEST_WRAPPER *ppAsyncReqWrapper
  1783. )
  1784. {
  1785. PNDISTAPI_REQUEST pNdisTapiRequest;
  1786. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  1787. // alloc & init an async request wrapper
  1788. pAsyncReqWrapper = (PASYNC_REQUEST_WRAPPER)
  1789. AllocRequest(dwDataSize + sizeof(ASYNC_REQUEST_WRAPPER));
  1790. if (NULL == pAsyncReqWrapper)
  1791. {
  1792. TspLog(DL_ERROR,
  1793. "PrepareAsyncRequest: failed to alloc async req for oid(%x)",
  1794. Oid);
  1795. return LINEERR_NOMEM;
  1796. }
  1797. // don't need to create an event when using completion ports
  1798. pAsyncReqWrapper->Overlapped.hEvent = (HANDLE)NULL;
  1799. pAsyncReqWrapper->dwKey = ASYNCREQWRAPPER_KEY;
  1800. pAsyncReqWrapper->dwRequestID = dwRequestID;
  1801. pAsyncReqWrapper->pfnPostProcess = (POSTPROCESSPROC)NULL;
  1802. // initialize the critical section, ref the request wrapper.
  1803. // NOTE: this crit sec will be deleted by the last deref.
  1804. InitializeCriticalSection(&pAsyncReqWrapper->CritSec);
  1805. pAsyncReqWrapper->RefCount = 1;
  1806. // safely initialize the driver request
  1807. pNdisTapiRequest = &(pAsyncReqWrapper->NdisTapiRequest);
  1808. pNdisTapiRequest->Oid = Oid;
  1809. pNdisTapiRequest->ulDeviceID = ulDeviceID;
  1810. pNdisTapiRequest->ulDataSize = dwDataSize;
  1811. EnterCriticalSection(&gRequestIDCritSec);
  1812. if ((*((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
  1813. {
  1814. gdwRequestID = 1;
  1815. }
  1816. LeaveCriticalSection(&gRequestIDCritSec);
  1817. *ppAsyncReqWrapper = pAsyncReqWrapper;
  1818. return TAPI_SUCCESS;
  1819. }
  1820. //
  1821. // makes a non-overlapped request to ndproxy.sys
  1822. // so it doesn't return until the req is completed
  1823. //
  1824. LONG
  1825. WINAPI
  1826. SyncDriverRequest(
  1827. DWORD dwIoControlCode,
  1828. PNDISTAPI_REQUEST pNdisTapiRequest
  1829. )
  1830. {
  1831. BOOL bRes;
  1832. DWORD cbReturned;
  1833. TspLog(DL_INFO,
  1834. "SyncDriverRequest: oid(%s), devID(%x), reqID(%x), hdCall(%x)",
  1835. pszOidNames[pNdisTapiRequest->Oid - OID_TAPI_ACCEPT],
  1836. pNdisTapiRequest->ulDeviceID,
  1837. *((ULONG *)pNdisTapiRequest->Data),
  1838. *(((ULONG *)pNdisTapiRequest->Data) + 1));
  1839. // mark the request as being processed by the driver
  1840. MarkRequest(pNdisTapiRequest);
  1841. bRes = DeviceIoControl(ghDriverSync,
  1842. dwIoControlCode,
  1843. pNdisTapiRequest,
  1844. (DWORD)(sizeof(NDISTAPI_REQUEST) +
  1845. pNdisTapiRequest->ulDataSize),
  1846. pNdisTapiRequest,
  1847. (DWORD)(sizeof(NDISTAPI_REQUEST) +
  1848. pNdisTapiRequest->ulDataSize),
  1849. &cbReturned,
  1850. 0);
  1851. // unmark the request now that the ioctl is completed
  1852. UnmarkRequest(pNdisTapiRequest);
  1853. if (bRes != TRUE)
  1854. {
  1855. TspLog(DL_ERROR, "SyncDriverRequest: IoCtl(Oid %x) failed(%d)",
  1856. pNdisTapiRequest->Oid, GetLastError());
  1857. return (LINEERR_OPERATIONFAILED);
  1858. }
  1859. else
  1860. {
  1861. // the errors returned by ndproxy.sys don't match the TAPI
  1862. // LINEERR_'s, so return the translated values (but preserve
  1863. // the original driver return val so it's possible to distinguish
  1864. // between NDISTAPIERR_DEVICEOFFLINE & LINEERR_OPERATIONUNAVAIL,
  1865. // etc.)
  1866. return (TranslateDriverResult(pNdisTapiRequest->ulReturnValue));
  1867. }
  1868. }
  1869. //
  1870. // Routine Description:
  1871. //
  1872. // Sends a message to the MSP telling it the VC handle for a call and
  1873. // instructing it to begin streaming on that call.
  1874. //
  1875. // Arguments:
  1876. // hdLine - Handle to line device
  1877. // hdCall - Handle for call
  1878. //
  1879. // NOTES - must be called while holding the MSP mutex
  1880. //
  1881. VOID
  1882. StartMSPStream(
  1883. HDRVLINE hdLine,
  1884. HDRVCALL hdCall
  1885. )
  1886. {
  1887. LONG lRes;
  1888. DWORD adwMSPMessage[2];
  1889. PDRVLINE pLine;
  1890. PDRVCALL pCall;
  1891. PDRVMSPLINE pMSPLine;
  1892. LPVARSTRING lpDeviceID;
  1893. TspLog(DL_TRACE, "StartMSPStream: enter");
  1894. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  1895. if (lRes != TAPI_SUCCESS)
  1896. {
  1897. return;
  1898. }
  1899. pMSPLine = pLine->pMSPLine;
  1900. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1901. if (lRes != TAPI_SUCCESS)
  1902. {
  1903. ReleaseObjReadLock((HANDLE)hdLine);
  1904. return;
  1905. }
  1906. //
  1907. // allocate a VARSTRING structure with enough space for the DWORD line id.
  1908. // @@@ shouldn't always assume that this will be the right size.
  1909. //
  1910. lpDeviceID = (LPVARSTRING)MALLOC(sizeof(VARSTRING) + sizeof(DWORD));
  1911. if (NULL == lpDeviceID)
  1912. {
  1913. TspLog(DL_ERROR, "StartMSPStream: failed to alloc deviceID");
  1914. ReleaseObjReadLock((HANDLE)hdCall);
  1915. ReleaseObjReadLock((HANDLE)hdLine);
  1916. return;
  1917. }
  1918. lpDeviceID->dwTotalSize = sizeof(VARSTRING) + sizeof(DWORD);
  1919. if ((lRes = TSPI_lineGetID(
  1920. hdLine,
  1921. 0, // @@@ the proxy always makes this 0, so we use 0.
  1922. // Change this if the proxy changes.
  1923. hdCall,
  1924. LINECALLSELECT_CALL,
  1925. lpDeviceID,
  1926. RCA_SAP_STRING,
  1927. 0 // @@@ we don't use this parameter, so I set it 0.
  1928. )) != TAPI_SUCCESS)
  1929. {
  1930. TspLog(DL_ERROR, "StartMSPStream: failed to get the VC handle");
  1931. FREE(lpDeviceID);
  1932. ReleaseObjReadLock((HANDLE)hdCall);
  1933. ReleaseObjReadLock((HANDLE)hdLine);
  1934. return;
  1935. }
  1936. //
  1937. // pass the VC Handle to the MSP.
  1938. //
  1939. adwMSPMessage[0] = 0; // command code for "Here's the VC Handle"
  1940. adwMSPMessage[1] = *((DWORD *)(((PBYTE)lpDeviceID) +
  1941. lpDeviceID->dwStringOffset));
  1942. TspLog(DL_INFO,
  1943. "StartMSPStream: sending VC handle(%x) to htline(%p), htcall(%p)",
  1944. adwMSPMessage[1], pLine->htLine, pCall->htCall);
  1945. (*gpfnLineEvent)(pLine->htLine,
  1946. pCall->htCall,
  1947. LINE_SENDMSPDATA,
  1948. (DWORD_PTR)0,
  1949. (DWORD_PTR)adwMSPMessage,
  1950. (DWORD_PTR)sizeof(DWORD) * 2);
  1951. //
  1952. // tell the MSP to start streaming.
  1953. //
  1954. adwMSPMessage[0] = 1; // command code for "Start Streaming"
  1955. (*gpfnLineEvent)(pLine->htLine,
  1956. pCall->htCall,
  1957. LINE_SENDMSPDATA,
  1958. (DWORD_PTR)0,
  1959. (DWORD_PTR)adwMSPMessage,
  1960. (DWORD_PTR)sizeof(DWORD));
  1961. pMSPLine->bStreamingStarted = TRUE;
  1962. FREE(lpDeviceID);
  1963. ReleaseObjReadLock((HANDLE)hdCall);
  1964. ReleaseObjReadLock((HANDLE)hdLine);
  1965. }
  1966. //
  1967. // Routine Description:
  1968. //
  1969. // Sends a message to the MSP telling it to stop streaming on a
  1970. // particular call.
  1971. //
  1972. // Arguments:
  1973. // hdLine - Handle to line device
  1974. // hdCall - Handle for call
  1975. //
  1976. // NOTES - must be called while holding the MSP mutex
  1977. //
  1978. VOID
  1979. StopMSPStream(
  1980. HDRVLINE hdLine,
  1981. HDRVCALL hdCall
  1982. )
  1983. {
  1984. LONG lRes;
  1985. DWORD adwMSPMessage;
  1986. PDRVLINE pLine;
  1987. PDRVCALL pCall;
  1988. PDRVMSPLINE pMSPLine;
  1989. TspLog(DL_TRACE, "StopMSPStream: enter");
  1990. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  1991. if (lRes != TAPI_SUCCESS)
  1992. {
  1993. return;
  1994. }
  1995. pMSPLine = pLine->pMSPLine;
  1996. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  1997. if (lRes != TAPI_SUCCESS)
  1998. {
  1999. ReleaseObjReadLock((HANDLE)hdLine);
  2000. return;
  2001. }
  2002. //
  2003. // tell the MSP to stop streaming.
  2004. //
  2005. adwMSPMessage = 2; // command code for "Stop Streaming"
  2006. TspLog(DL_INFO,
  2007. "StopMSPStream: sending MSP stop cmd to htline(%p), htcall(%p)",
  2008. pLine->htLine, pCall->htCall);
  2009. (*gpfnLineEvent)(pLine->htLine,
  2010. pCall->htCall,
  2011. LINE_SENDMSPDATA,
  2012. (DWORD_PTR)0,
  2013. (DWORD_PTR)&adwMSPMessage,
  2014. (DWORD_PTR)sizeof(DWORD));
  2015. pMSPLine->bStreamingStarted = FALSE;
  2016. ReleaseObjReadLock((HANDLE)hdCall);
  2017. ReleaseObjReadLock((HANDLE)hdLine);
  2018. }
  2019. //
  2020. // make an overlapped call
  2021. //
  2022. LONG
  2023. WINAPI
  2024. AsyncDriverRequest(
  2025. DWORD dwIoControlCode,
  2026. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper
  2027. )
  2028. {
  2029. BOOL bRes;
  2030. LONG lRes;
  2031. DWORD dwRequestSize, cbReturned, dwLastError;
  2032. TspLog(DL_INFO,
  2033. "AsyncDriverRequest: oid(%s), devID(%x), ReqID(%x), "
  2034. "reqID(%x), hdCall(%x)",
  2035. pszOidNames[pAsyncReqWrapper->NdisTapiRequest.Oid -
  2036. OID_TAPI_ACCEPT],
  2037. pAsyncReqWrapper->NdisTapiRequest.ulDeviceID,
  2038. pAsyncReqWrapper->dwRequestID,
  2039. *((ULONG *)pAsyncReqWrapper->NdisTapiRequest.Data),
  2040. *(((ULONG *)pAsyncReqWrapper->NdisTapiRequest.Data) + 1));
  2041. lRes = (LONG)pAsyncReqWrapper->dwRequestID;
  2042. dwRequestSize = sizeof(NDISTAPI_REQUEST) +
  2043. (pAsyncReqWrapper->NdisTapiRequest.ulDataSize - 1);
  2044. REF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  2045. // mark the request as being processed by the driver
  2046. MarkRequest(pAsyncReqWrapper);
  2047. bRes = DeviceIoControl(
  2048. ghDriverAsync,
  2049. dwIoControlCode,
  2050. &pAsyncReqWrapper->NdisTapiRequest,
  2051. dwRequestSize,
  2052. &pAsyncReqWrapper->NdisTapiRequest,
  2053. dwRequestSize,
  2054. &cbReturned,
  2055. &pAsyncReqWrapper->Overlapped
  2056. );
  2057. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  2058. if (bRes != TRUE) {
  2059. dwLastError = GetLastError();
  2060. if (dwLastError != ERROR_IO_PENDING) {
  2061. TspLog(DL_ERROR, "AsyncDriverRequest: IoCtl(oid %x) failed(%d)",
  2062. pAsyncReqWrapper->NdisTapiRequest.Oid, dwLastError);
  2063. // the ioctl failed and was not pended
  2064. // this does not trigger the completion port
  2065. // so we have to cleanup here.
  2066. (*gpfnCompletionProc)(pAsyncReqWrapper->dwRequestID,
  2067. LINEERR_OPERATIONFAILED);
  2068. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  2069. }
  2070. }
  2071. return lRes;
  2072. }
  2073. //
  2074. // reports to TAPI events that occur on the line or on calls on the line
  2075. //
  2076. VOID
  2077. WINAPI
  2078. ProcessEvent(
  2079. PNDIS_TAPI_EVENT pEvent
  2080. )
  2081. {
  2082. LONG lRes;
  2083. ULONG ulMsg = pEvent->ulMsg;
  2084. HTAPI_LINE ht_Line = (HTAPI_LINE)pEvent->htLine;
  2085. HTAPI_CALL ht_Call = (HTAPI_CALL)pEvent->htCall;
  2086. TspLog(DL_INFO,
  2087. "ProcessEvent: event(%p), msg(%x), ht_line(%p), ht_call(%p), "\
  2088. "p1(%p), p2(%p), p3(%p)",
  2089. pEvent, ulMsg, ht_Line, ht_Call,
  2090. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  2091. switch (ulMsg)
  2092. {
  2093. case LINE_ADDRESSSTATE:
  2094. case LINE_CLOSE:
  2095. case LINE_DEVSPECIFIC:
  2096. case LINE_LINEDEVSTATE:
  2097. {
  2098. PDRVLINE pLine;
  2099. lRes = GetLineObjWithReadLock((HDRVLINE)ht_Line, &pLine);
  2100. if (lRes != TAPI_SUCCESS)
  2101. {
  2102. break;
  2103. }
  2104. TspLog(DL_INFO,
  2105. "PE::fnLineEvent: msg(%x), htline(%p), p1(%p), p2(%p), p3(%p)",
  2106. ulMsg, pLine->htLine,
  2107. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  2108. (*gpfnLineEvent)(pLine->htLine,
  2109. (HTAPICALL)NULL,
  2110. ulMsg,
  2111. (DWORD_PTR)pEvent->ulParam1,
  2112. (DWORD_PTR)pEvent->ulParam2,
  2113. (DWORD_PTR)pEvent->ulParam3);
  2114. ReleaseObjReadLock((HANDLE)ht_Line);
  2115. break;
  2116. }
  2117. case LINE_CALLDEVSPECIFIC:
  2118. case LINE_CALLINFO:
  2119. {
  2120. PDRVLINE pLine;
  2121. PDRVCALL pCall;
  2122. HDRVLINE hdLine;
  2123. lRes = GetLineAndCallObjWithReadLock(ht_Line, ht_Call, &pLine, &pCall);
  2124. if (lRes != TAPI_SUCCESS)
  2125. {
  2126. break;
  2127. }
  2128. hdLine = pCall->hdLine;
  2129. TspLog(DL_INFO,
  2130. "PE::fnLineEvent: msg(%x), htline(%p), htcall(%p), "\
  2131. "p1(%p), p2(%p), p3(%p)",
  2132. ulMsg, pLine->htLine, pCall->htCall,
  2133. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  2134. (*gpfnLineEvent)(pLine->htLine,
  2135. pCall->htCall,
  2136. ulMsg,
  2137. (DWORD_PTR)pEvent->ulParam1,
  2138. (DWORD_PTR)pEvent->ulParam2,
  2139. (DWORD_PTR)pEvent->ulParam3);
  2140. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  2141. ReleaseObjReadLock((HANDLE)hdLine);
  2142. break;
  2143. }
  2144. case LINE_CALLSTATE:
  2145. {
  2146. DWORD dwWaitStatus;
  2147. PDRVLINE pLine;
  2148. PDRVCALL pCall;
  2149. HDRVLINE hdLine;
  2150. lRes = GetLineAndCallObjWithReadLock(ht_Line, ht_Call, &pLine, &pCall);
  2151. // we may still receive a few events
  2152. // for calls that have been closed/dropped
  2153. if (lRes != TAPI_SUCCESS)
  2154. {
  2155. break;
  2156. }
  2157. hdLine = pCall->hdLine;
  2158. //
  2159. // for outbound calls there exists a race condition between
  2160. // receiving the first call state msg(s) and receiving the
  2161. // make call completion notification (if we pass a call state
  2162. // msg on to tapi for a call that hasn't been completed yet
  2163. // tapi will just discard the msg since the htCall really
  2164. // isn't valid at that point). So if htCall references a
  2165. // valid outbound call which hasn't completed yet, we'll save
  2166. // the call state params, and pass them on to tapi after we
  2167. // get & indicate a (successful) completion notification.
  2168. //
  2169. if ((OUTBOUND_CALL_KEY == pCall->dwKey) &&
  2170. (TRUE == pCall->bIncomplete))
  2171. {
  2172. TspLog(DL_INFO,
  2173. "ProcessEvent: incomplete outbound call, saving state");
  2174. pCall->dwPendingCallState = (DWORD)pEvent->ulParam1;
  2175. pCall->dwPendingCallStateMode = (DWORD)pEvent->ulParam2;
  2176. pCall->dwPendingMediaMode = (DWORD)pEvent->ulParam3;
  2177. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  2178. ReleaseObjReadLock((HANDLE)hdLine);
  2179. break;
  2180. }
  2181. //
  2182. // Start or stop the MSP streaming as appropriate. The only states in
  2183. // which this might happen are CONNECTED, DISCONNECTED, or IDLE.
  2184. //
  2185. if ((LINECALLSTATE_CONNECTED == pEvent->ulParam1) ||
  2186. (LINECALLSTATE_DISCONNECTED == pEvent->ulParam1) ||
  2187. (LINECALLSTATE_IDLE == pEvent->ulParam1)) {
  2188. TspLog(DL_TRACE, "ProcessEvent: using MSP");
  2189. if ((dwWaitStatus = WaitForSingleObject(pLine->hMSPMutex, INFINITE))
  2190. == WAIT_OBJECT_0)
  2191. {
  2192. TspLog(DL_TRACE, "ProcessEvent: acquired MSP Mutex");
  2193. if (pLine->pMSPLine)
  2194. {
  2195. TspLog(DL_TRACE, "ProcessEvent: we have an MSP");
  2196. if ((LINECALLSTATE_CONNECTED == pEvent->ulParam1) &&
  2197. (FALSE == pLine->pMSPLine->bStreamingStarted))
  2198. {
  2199. DWORD dwMessage = 3; // Command code for
  2200. // "Are you there?"
  2201. (*gpfnLineEvent)(pLine->htLine,
  2202. pCall->htCall,
  2203. LINE_SENDMSPDATA,
  2204. (DWORD_PTR)0, // Send to all MSPs
  2205. (DWORD_PTR)&dwMessage,
  2206. (DWORD_PTR)sizeof(DWORD));
  2207. TspLog(DL_TRACE,
  2208. "ProcessEvent: sent 'are you there ?' "\
  2209. "message to MSP");
  2210. }
  2211. else if(((LINECALLSTATE_DISCONNECTED == pEvent->ulParam1) ||
  2212. (LINECALLSTATE_IDLE == pEvent->ulParam1)) &&
  2213. (pLine->pMSPLine->bStreamingStarted))
  2214. {
  2215. TspLog(DL_TRACE,
  2216. "ProcessEvent: about to call StopMSPStream");
  2217. StopMSPStream(pCall->hdLine, pCall->hdCall);
  2218. }
  2219. }
  2220. ReleaseMutex(pLine->hMSPMutex);
  2221. TspLog(DL_TRACE, "ProcessEvent: released MSP Mutex");
  2222. }
  2223. else
  2224. {
  2225. TspLog(DL_ERROR,
  2226. "ProcessEvent: wait for MSP Mutex failed(%x)",
  2227. dwWaitStatus);
  2228. }
  2229. }
  2230. if (LINECALLSTATE_OFFERING == pEvent->ulParam1)
  2231. {
  2232. LPLINECALLINFO lpLineCallInfo;
  2233. //
  2234. // We're about to indicate up an offering call. We need
  2235. // to make sure the media mode we're indicating up is
  2236. // correct (we can't rely on what the proxy gave us).
  2237. // So, we call lineGetCallInfo, which will look up the
  2238. // proper value in a table based on the called address.
  2239. //
  2240. lpLineCallInfo = (LPLINECALLINFO)MALLOC(sizeof(LINECALLINFO));
  2241. if (lpLineCallInfo)
  2242. {
  2243. lpLineCallInfo->dwTotalSize = sizeof(LINECALLINFO);
  2244. if (TSPI_lineGetCallInfo(pCall->hdCall, lpLineCallInfo)
  2245. == TAPI_SUCCESS)
  2246. {
  2247. if (lpLineCallInfo->dwNeededSize >
  2248. lpLineCallInfo->dwTotalSize)
  2249. {
  2250. DWORD dwNeededSize = lpLineCallInfo->dwNeededSize;
  2251. FREE(lpLineCallInfo);
  2252. lpLineCallInfo = (LPLINECALLINFO)MALLOC(dwNeededSize);
  2253. if (lpLineCallInfo)
  2254. {
  2255. lpLineCallInfo->dwTotalSize = dwNeededSize;
  2256. if (TSPI_lineGetCallInfo(pCall->hdCall,
  2257. lpLineCallInfo)
  2258. != TAPI_SUCCESS)
  2259. {
  2260. TspLog(DL_ERROR,
  2261. "ProcessEvent: second call to "\
  2262. "TSPI_lineGetCallInfo failed");
  2263. FREE(lpLineCallInfo);
  2264. lpLineCallInfo = NULL;
  2265. }
  2266. }
  2267. else
  2268. {
  2269. TspLog(DL_ERROR,
  2270. "ProcessEvent: failed to allocate line "\
  2271. "call info structure 2nd time");
  2272. }
  2273. }
  2274. if (lpLineCallInfo) {
  2275. pEvent->ulParam3 = lpLineCallInfo->dwMediaMode;
  2276. TspLog(DL_TRACE,
  2277. "ProcessEvent: just set media mode(%x)",
  2278. pEvent->ulParam3);
  2279. }
  2280. }
  2281. else
  2282. {
  2283. TspLog(DL_ERROR,
  2284. "ProcessEvent: first call to "\
  2285. "TSPI_lineGetCallInfo failed");
  2286. }
  2287. if (lpLineCallInfo)
  2288. {
  2289. FREE(lpLineCallInfo);
  2290. lpLineCallInfo = NULL;
  2291. }
  2292. }
  2293. else
  2294. {
  2295. TspLog(DL_ERROR,
  2296. "ProcessEvent: couldn't allocate mem "\
  2297. "for line call info");
  2298. }
  2299. }
  2300. TspLog(DL_INFO,
  2301. "PE::fnLineEvent(CALLSTATE): htline(%p), htcall(%p), "\
  2302. "p1(%p), p2(%p), p3(%p)",
  2303. pLine->htLine, pCall->htCall,
  2304. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  2305. (*gpfnLineEvent)(pLine->htLine,
  2306. pCall->htCall,
  2307. ulMsg,
  2308. (DWORD_PTR)pEvent->ulParam1,
  2309. (DWORD_PTR)pEvent->ulParam2,
  2310. (DWORD_PTR)pEvent->ulParam3);
  2311. //
  2312. // As a perf tweak we want to indicate an IDLE
  2313. // immediately following the disconnected. The proxy
  2314. // will never indicate a callstate_idle.
  2315. //
  2316. if(LINECALLSTATE_DISCONNECTED == pEvent->ulParam1)
  2317. {
  2318. TspLog(DL_INFO,
  2319. "PE::fnLineEvent(CALLSTATE_IDLE): htline(%p), htcall(%p), p3(%p)",
  2320. pLine->htLine, pCall->htCall, pEvent->ulParam3);
  2321. (*gpfnLineEvent)(pLine->htLine,
  2322. pCall->htCall,
  2323. ulMsg,
  2324. (DWORD_PTR)LINECALLSTATE_IDLE,
  2325. (DWORD_PTR)0,
  2326. (DWORD_PTR)pEvent->ulParam3);
  2327. }
  2328. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  2329. ReleaseObjReadLock((HANDLE)hdLine);
  2330. break;
  2331. }
  2332. case LINE_NEWCALL:
  2333. {
  2334. HDRVCALL hdCall;
  2335. PDRVCALL pCall;
  2336. PDRVLINE pLine;
  2337. lRes = GetLineObjWithWriteLock((HDRVLINE)ht_Line, &pLine);
  2338. if (lRes != TAPI_SUCCESS)
  2339. {
  2340. break;
  2341. }
  2342. // alloc & initialize a new DRVCALL object
  2343. if (pCall = AllocCallObj(sizeof(DRVCALL)))
  2344. {
  2345. pCall->dwKey = INBOUND_CALL_KEY;
  2346. pCall->hd_Call = (HDRV_CALL)pEvent->ulParam1;
  2347. pCall->ht_Call = (HTAPI_CALL)pEvent->ulParam2;
  2348. pCall->hdLine = (HDRVLINE)ht_Line;
  2349. pCall->bIncomplete = FALSE;
  2350. }
  2351. //
  2352. // if the new call object allocation failed above then we
  2353. // want to tell the driver to drop & close the call,
  2354. // then just break
  2355. //
  2356. if (NULL == pCall)
  2357. {
  2358. PNDISTAPI_REQUEST pNdisTapiRequestDrop;
  2359. PNDISTAPI_REQUEST pNdisTapiRequestCloseCall;
  2360. PNDIS_TAPI_DROP pNdisTapiDrop;
  2361. PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
  2362. if ((lRes = PrepareSyncRequest(
  2363. OID_TAPI_DROP, // opcode
  2364. pLine->dwDeviceID, // device id
  2365. sizeof(NDIS_TAPI_DROP), // size of drve req data
  2366. &pNdisTapiRequestDrop // ptr to ptr to request buf
  2367. )) != TAPI_SUCCESS)
  2368. {
  2369. ReleaseObjWriteLock((HANDLE)ht_Line);
  2370. break;
  2371. }
  2372. pNdisTapiDrop = (PNDIS_TAPI_DROP)pNdisTapiRequestDrop->Data;
  2373. pNdisTapiDrop->hdCall = (HDRV_CALL) pEvent->ulParam1;
  2374. pNdisTapiDrop->ulUserUserInfoSize = 0;
  2375. SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequestDrop);
  2376. FreeRequest(pNdisTapiRequestDrop);
  2377. if ((lRes = PrepareSyncRequest(
  2378. OID_TAPI_CLOSE_CALL, // opcode
  2379. pLine->dwDeviceID, // device id
  2380. sizeof(NDIS_TAPI_CLOSE_CALL), // size of drve req data
  2381. &pNdisTapiRequestCloseCall // ptr to ptr to request buf
  2382. )) != TAPI_SUCCESS)
  2383. {
  2384. ReleaseObjWriteLock((HANDLE)ht_Line);
  2385. break;
  2386. }
  2387. pNdisTapiCloseCall =
  2388. (PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequestCloseCall->Data;
  2389. pNdisTapiCloseCall->hdCall = (HDRV_CALL) pEvent->ulParam1;
  2390. SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO,
  2391. pNdisTapiRequestCloseCall);
  2392. FreeRequest(pNdisTapiRequestCloseCall);
  2393. ReleaseObjWriteLock((HANDLE)ht_Line);
  2394. break;
  2395. }
  2396. ASSERT(pCall != NULL);
  2397. pCall->dwDeviceID = pLine->dwDeviceID;
  2398. // make sure releasing write lock before calling OpenObjHandle()
  2399. // to avoid deadlock on acquiring write lock for the global mapper
  2400. ReleaseObjWriteLock((HANDLE)ht_Line);
  2401. lRes = OpenObjHandle(pCall, FreeCallObj, (HANDLE *)&hdCall);
  2402. if (lRes != TAPI_SUCCESS)
  2403. {
  2404. TspLog(DL_ERROR,
  2405. "ProcessEvent: failed to map obj(%p) to handle",
  2406. pCall);
  2407. FreeCallObj(pCall);
  2408. break;
  2409. }
  2410. // reacquire the write lock
  2411. lRes = AcquireObjWriteLock((HANDLE)ht_Line);
  2412. if (lRes != TAPI_SUCCESS)
  2413. {
  2414. TspLog(DL_ERROR,
  2415. "ProcessEvent: failed to reacquire write lock for obj(%p)",
  2416. ht_Line);
  2417. CloseObjHandle((HANDLE)hdCall);
  2418. break;
  2419. }
  2420. // save the TSP handle
  2421. pCall->hdCall = hdCall;
  2422. // send the LINE_NEWCALL to TAPI, getting back the TAPI call handle
  2423. TspLog(DL_INFO,
  2424. "PE::fnLineEvent(NEWCALL): htline(%p), call(%p)",
  2425. pLine->htLine, hdCall);
  2426. (*gpfnLineEvent)(pLine->htLine,
  2427. (HTAPICALL)NULL,
  2428. LINE_NEWCALL,
  2429. (DWORD_PTR)hdCall,
  2430. (DWORD_PTR)&pCall->htCall,
  2431. 0);
  2432. //
  2433. // insert the new call into the line's inbound calls list
  2434. // regardless of the result of the LINE_NEWCALL
  2435. // if it failed, we'll destroy the call next, and
  2436. // TSPI_lineCloseCall will expect the call to be
  2437. // in the line's inbound call list
  2438. //
  2439. if ((pCall->pNext = pLine->pInboundCalls) != NULL)
  2440. {
  2441. pCall->pNext->pPrev = pCall;
  2442. }
  2443. pLine->pInboundCalls = pCall;
  2444. ReleaseObjWriteLock((HANDLE)ht_Line);
  2445. //
  2446. // if TAPI didn't create it's own representation of this
  2447. // cal (if pCall->htCall == NULL), then either:
  2448. //
  2449. // 1) the line is in the process of being closed, or
  2450. // 2) TAPI was unable to allocate the necessary resources
  2451. //
  2452. // ...so we'll close the call
  2453. //
  2454. if (NULL == pCall->htCall)
  2455. {
  2456. TspLog(DL_WARNING, "ProcessEvent: TAPI failed to create "
  2457. "its own handle for the new call, so we close the call");
  2458. TSPI_lineCloseCall(hdCall);
  2459. }
  2460. break;
  2461. }
  2462. case LINE_CREATE:
  2463. TspLog(DL_INFO,
  2464. "PE::fnLineEvent(CREATE): ghProvider(%p), p2(%p), p3(%p)",
  2465. ghProvider, pEvent->ulParam2, pEvent->ulParam3);
  2466. (*gpfnLineEvent)((HTAPILINE)NULL,
  2467. (HTAPICALL)NULL,
  2468. ulMsg,
  2469. (DWORD_PTR)ghProvider,
  2470. (DWORD_PTR)pEvent->ulParam2,
  2471. (DWORD_PTR)pEvent->ulParam3);
  2472. break;
  2473. case LINE_MONITORDIGITS:
  2474. {
  2475. PDRVLINE pLine;
  2476. PDRVCALL pCall;
  2477. HDRVLINE hdLine;
  2478. lRes = GetLineAndCallObjWithReadLock(ht_Line, ht_Call, &pLine, &pCall);
  2479. if (lRes != TAPI_SUCCESS)
  2480. {
  2481. break;
  2482. }
  2483. hdLine = pCall->hdLine;
  2484. TspLog(DL_INFO,
  2485. "PE::fnLineEvent(MONITORDIGITS): htline(%p), htcall(%p), "\
  2486. "p1(%p), p2(%p), p3(%p)",
  2487. pLine->htLine, pCall->htCall,
  2488. pEvent->ulParam1, pEvent->ulParam2, pEvent->ulParam3);
  2489. (*gpfnLineEvent)(pLine->htLine,
  2490. pCall->htCall,
  2491. ulMsg,
  2492. (DWORD_PTR)pEvent->ulParam1,
  2493. (DWORD_PTR)pEvent->ulParam2,
  2494. (DWORD_PTR)pEvent->ulParam3);
  2495. ReleaseObjReadLock((HANDLE)pCall->hdCall);
  2496. ReleaseObjReadLock((HANDLE)hdLine);
  2497. break;
  2498. }
  2499. default:
  2500. TspLog(DL_ERROR, "ProcessEvent: unknown msg(%x)", ulMsg);
  2501. break;
  2502. } // switch
  2503. }
  2504. //
  2505. // thread proc that retrieves and processes completed requests
  2506. // and async events
  2507. //
  2508. VOID
  2509. AsyncEventsThread(
  2510. LPVOID lpParams
  2511. )
  2512. {
  2513. OVERLAPPED overlapped;
  2514. DWORD cbReturned;
  2515. //
  2516. // send an IOCTL to retrieve async events
  2517. //
  2518. overlapped.hEvent = NULL; // don't need event when using completion ports
  2519. gpAsyncEventsThreadInfo->pBuf->ulTotalSize =
  2520. gpAsyncEventsThreadInfo->dwBufSize - sizeof(NDISTAPI_EVENT_DATA);
  2521. gpAsyncEventsThreadInfo->pBuf->ulUsedSize = 0;
  2522. if (DeviceIoControl(
  2523. ghDriverAsync,
  2524. IOCTL_NDISTAPI_GET_LINE_EVENTS,
  2525. gpAsyncEventsThreadInfo->pBuf,
  2526. sizeof(NDISTAPI_EVENT_DATA),
  2527. gpAsyncEventsThreadInfo->pBuf,
  2528. gpAsyncEventsThreadInfo->dwBufSize,
  2529. &cbReturned,
  2530. &overlapped
  2531. ) != TRUE)
  2532. {
  2533. DWORD dwLastError = GetLastError();
  2534. if (dwLastError != ERROR_IO_PENDING)
  2535. {
  2536. TspLog(DL_ERROR,
  2537. "AsyncEventsThread: IoCtl(GetEvent) failed(%d)",
  2538. dwLastError);
  2539. }
  2540. ASSERT(ERROR_IO_PENDING == dwLastError);
  2541. }
  2542. // loop waiting for completed requests and retrieving async events
  2543. while (1)
  2544. {
  2545. BOOL bRes;
  2546. LPOVERLAPPED lpOverlapped;
  2547. PNDIS_TAPI_EVENT pEvent;
  2548. // wait for a request to complete
  2549. while (1) {
  2550. DWORD dwNumBytesTransferred;
  2551. DWORD_PTR dwCompletionKey;
  2552. bRes = GetQueuedCompletionStatus(
  2553. ghCompletionPort,
  2554. &dwNumBytesTransferred,
  2555. &dwCompletionKey,
  2556. &lpOverlapped,
  2557. (DWORD)-1); // infinite wait
  2558. if (bRes) {
  2559. //
  2560. // GetQueuedCompletion returned success so if our
  2561. // overlapped field is non-NULL then process the
  2562. // event. If the overlapped field is NULL try
  2563. // to get another event.
  2564. //
  2565. if (lpOverlapped != NULL) {
  2566. break;
  2567. }
  2568. TspLog(DL_WARNING,
  2569. "AsyncEventsThread: GetQueuedCompletionStatus "\
  2570. "lpOverlapped == NULL!");
  2571. } else {
  2572. //
  2573. // Error returned from GetQueuedCompletionStatus so
  2574. // shutdown the thread.
  2575. //
  2576. TspLog(DL_ERROR,
  2577. "AsyncEventsThread: GetQueuedCompletionStatus "\
  2578. "failed(%d)", GetLastError());
  2579. TspLog(DL_WARNING, "AsyncEventsThread: exiting thread");
  2580. ExitThread (0);
  2581. }
  2582. }
  2583. ASSERT(lpOverlapped != NULL);
  2584. //
  2585. // check the returned overlapped struct to determine if
  2586. // we have some events to process or a completed request
  2587. //
  2588. if (lpOverlapped == &overlapped)
  2589. {
  2590. DWORD i;
  2591. TspLog(DL_INFO, "AsyncEventsThread: got a line event");
  2592. // handle the events
  2593. pEvent = (PNDIS_TAPI_EVENT)gpAsyncEventsThreadInfo->pBuf->Data;
  2594. for (i = 0;
  2595. i < (gpAsyncEventsThreadInfo->pBuf->ulUsedSize /
  2596. sizeof(NDIS_TAPI_EVENT));
  2597. i++
  2598. )
  2599. {
  2600. ProcessEvent(pEvent);
  2601. pEvent++;
  2602. }
  2603. //
  2604. // send another IOCTL to retrieve new async events
  2605. //
  2606. overlapped.hEvent = NULL;
  2607. gpAsyncEventsThreadInfo->pBuf->ulTotalSize =
  2608. gpAsyncEventsThreadInfo->dwBufSize -
  2609. sizeof(NDISTAPI_EVENT_DATA) + 1;
  2610. gpAsyncEventsThreadInfo->pBuf->ulUsedSize = 0;
  2611. if (DeviceIoControl(
  2612. ghDriverAsync,
  2613. IOCTL_NDISTAPI_GET_LINE_EVENTS,
  2614. gpAsyncEventsThreadInfo->pBuf,
  2615. sizeof(NDISTAPI_EVENT_DATA),
  2616. gpAsyncEventsThreadInfo->pBuf,
  2617. gpAsyncEventsThreadInfo->dwBufSize,
  2618. &cbReturned,
  2619. &overlapped
  2620. ) != TRUE)
  2621. {
  2622. DWORD dwLastError = GetLastError();
  2623. if (dwLastError != ERROR_IO_PENDING) {
  2624. TspLog(DL_ERROR,
  2625. "AsyncEventsThread: IoCtl(GetEvent) failed(%d)",
  2626. dwLastError);
  2627. TspLog(DL_INFO, "AsyncEventsThread: exiting thread");
  2628. ExitThread (0);
  2629. }
  2630. }
  2631. }
  2632. else
  2633. {
  2634. LONG lRes;
  2635. DWORD dwRequestID, callStateMsgParams[5];
  2636. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper =
  2637. (PASYNC_REQUEST_WRAPPER)lpOverlapped;
  2638. TspLog(DL_INFO, "AsyncEventsThread: got a completed req");
  2639. // verify that pointer is valid
  2640. if (pAsyncReqWrapper->dwKey != ASYNCREQWRAPPER_KEY)
  2641. {
  2642. TspLog(DL_WARNING, "AsyncEventsThread: got a bogus req");
  2643. continue;
  2644. }
  2645. dwRequestID = pAsyncReqWrapper->dwRequestID;
  2646. // unmark the request now that the ioctl is completed
  2647. UnmarkRequest(pAsyncReqWrapper);
  2648. lRes = TranslateDriverResult(
  2649. pAsyncReqWrapper->NdisTapiRequest.ulReturnValue
  2650. );
  2651. TspLog(DL_INFO,
  2652. "AsyncEventsThread: req(%p) with reqID(%x) returned lRes(%x)",
  2653. pAsyncReqWrapper, dwRequestID, lRes);
  2654. // call the post processing proc if appropriate
  2655. callStateMsgParams[0] = 0;
  2656. if (pAsyncReqWrapper->pfnPostProcess)
  2657. {
  2658. (*pAsyncReqWrapper->pfnPostProcess)(
  2659. pAsyncReqWrapper,
  2660. lRes,
  2661. callStateMsgParams
  2662. );
  2663. }
  2664. // call completion proc
  2665. TspLog(DL_TRACE,
  2666. "AsyncEventsThread: call compproc with ReqID(%x), lRes(%x)",
  2667. dwRequestID, lRes);
  2668. // this is a bit ugly. LineGatherDigits is not actually
  2669. // an asynchronous call though conceptually it seems as though it
  2670. // is. The upshot of this is that we're not supposed to call the
  2671. // completion proc for it. If there are more calls like this that
  2672. // we have to support, we should come up with a better mechanism
  2673. // than this "if" statement.
  2674. if (pAsyncReqWrapper->NdisTapiRequest.Oid !=
  2675. OID_TAPI_GATHER_DIGITS)
  2676. {
  2677. (*gpfnCompletionProc)(dwRequestID, lRes);
  2678. }
  2679. // free the async request wrapper
  2680. DEREF_ASYNC_REQUEST_WRAPPER(pAsyncReqWrapper);
  2681. // when outbounding call completes, we need to
  2682. // report back the saved call state
  2683. if (callStateMsgParams[0])
  2684. {
  2685. TspLog(DL_INFO,
  2686. "AsyncEventsThread: report back the saved call state");
  2687. TspLog(DL_INFO,
  2688. "AET::fnLineEvent(CALLSTATE): htline(%p), htcall(%p), "\
  2689. "p1(%p), p2(%p), p3(%p)",
  2690. callStateMsgParams[0], callStateMsgParams[1],
  2691. callStateMsgParams[2], callStateMsgParams[3],
  2692. callStateMsgParams[4]);
  2693. (*gpfnLineEvent)((HTAPILINE)ULongToPtr(callStateMsgParams[0]),
  2694. (HTAPICALL)ULongToPtr(callStateMsgParams[1]),
  2695. LINE_CALLSTATE,
  2696. (DWORD_PTR)callStateMsgParams[2],
  2697. (DWORD_PTR)callStateMsgParams[3],
  2698. (DWORD_PTR)callStateMsgParams[4]);
  2699. }
  2700. }
  2701. } // while
  2702. }
  2703. HDRV_CALL
  2704. GetNdisTapiHandle(
  2705. PDRVCALL pCall,
  2706. LONG *plRes
  2707. )
  2708. {
  2709. HDRVCALL hdCall;
  2710. PDRVCALL pCallLocal = pCall;
  2711. LONG lRes;
  2712. ASSERT(pCall != NULL);
  2713. hdCall = pCall->hdCall;
  2714. if(plRes != NULL)
  2715. {
  2716. *plRes = TAPI_SUCCESS;
  2717. }
  2718. //
  2719. // if the call is outbound, wait until the make call request
  2720. // has completed so we don't send a bad NDPROXY handle down
  2721. // to the driver
  2722. //
  2723. if (OUTBOUND_CALL_KEY == pCall->dwKey)
  2724. {
  2725. if (pCall->bIncomplete)
  2726. {
  2727. TspLog(DL_INFO,
  2728. "GetNdisTapiHandle: wait for the outbound call to complete...");
  2729. do
  2730. {
  2731. ASSERT(plRes != NULL);
  2732. //
  2733. // Release lock before going to sleep, ow we
  2734. // have a deadlock.
  2735. //
  2736. ReleaseObjReadLock((HANDLE) hdCall);
  2737. Sleep(250);
  2738. //
  2739. // ReAcquire Read Lock. Break if we can't
  2740. //
  2741. lRes = GetCallObjWithReadLock(hdCall, &pCallLocal);
  2742. if(lRes != TAPI_SUCCESS)
  2743. {
  2744. *plRes = lRes;
  2745. break;
  2746. }
  2747. } while (pCall->bIncomplete);
  2748. }
  2749. }
  2750. return pCall->hd_Call;
  2751. }
  2752. //
  2753. // TSPI_lineXXX functions
  2754. //
  2755. LONG
  2756. TSPIAPI
  2757. TSPI_lineAccept(
  2758. DRV_REQUESTID dwRequestID,
  2759. HDRVCALL hdCall,
  2760. LPCSTR lpsUserUserInfo,
  2761. DWORD dwSize
  2762. )
  2763. {
  2764. static DWORD dwSum = 0;
  2765. LONG lRes;
  2766. PDRVCALL pCall;
  2767. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  2768. PNDIS_TAPI_ACCEPT pNdisTapiAccept;
  2769. TspLog(DL_TRACE, "lineAccept(%d): reqID(%x), call(%p)",
  2770. ++dwSum, dwRequestID, hdCall);
  2771. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2772. if (lRes != TAPI_SUCCESS)
  2773. {
  2774. return lRes;
  2775. }
  2776. if ((lRes = PrepareAsyncRequest(
  2777. OID_TAPI_ACCEPT, // opcode
  2778. pCall->dwDeviceID, // device id
  2779. dwRequestID, // request id
  2780. sizeof(NDIS_TAPI_ACCEPT) + dwSize, // size of drv request data
  2781. &pAsyncReqWrapper // ptr to ptr to request buf
  2782. )) != TAPI_SUCCESS)
  2783. {
  2784. ReleaseObjReadLock((HANDLE)hdCall);
  2785. return lRes;
  2786. }
  2787. pNdisTapiAccept =
  2788. (PNDIS_TAPI_ACCEPT)pAsyncReqWrapper->NdisTapiRequest.Data;
  2789. pNdisTapiAccept->hdCall = GetNdisTapiHandle(pCall, NULL);
  2790. if ((pNdisTapiAccept->ulUserUserInfoSize = dwSize) != 0)
  2791. {
  2792. CopyMemory(pNdisTapiAccept->UserUserInfo, lpsUserUserInfo, dwSize);
  2793. }
  2794. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  2795. ReleaseObjReadLock((HANDLE)hdCall);
  2796. return lRes;
  2797. }
  2798. LONG
  2799. TSPIAPI
  2800. TSPI_lineAnswer(
  2801. DRV_REQUESTID dwRequestID,
  2802. HDRVCALL hdCall,
  2803. LPCSTR lpsUserUserInfo,
  2804. DWORD dwSize
  2805. )
  2806. {
  2807. static DWORD dwSum = 0;
  2808. LONG lRes;
  2809. PDRVCALL pCall;
  2810. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  2811. PNDIS_TAPI_ANSWER pNdisTapiAnswer;
  2812. TspLog(DL_TRACE, "lineAnswer(%d): reqID(%x), call(%p)",
  2813. ++dwSum, dwRequestID, hdCall);
  2814. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2815. if (lRes != TAPI_SUCCESS)
  2816. {
  2817. return lRes;
  2818. }
  2819. if ((lRes = PrepareAsyncRequest(
  2820. OID_TAPI_ANSWER, // opcode
  2821. pCall->dwDeviceID, // device id
  2822. dwRequestID, // request id
  2823. sizeof(NDIS_TAPI_ANSWER) + dwSize, // size of drv request data
  2824. &pAsyncReqWrapper // ptr to ptr to request buf
  2825. )) != TAPI_SUCCESS)
  2826. {
  2827. ReleaseObjReadLock((HANDLE)hdCall);
  2828. return lRes;
  2829. }
  2830. pNdisTapiAnswer =
  2831. (PNDIS_TAPI_ANSWER)pAsyncReqWrapper->NdisTapiRequest.Data;
  2832. pNdisTapiAnswer->hdCall = GetNdisTapiHandle(pCall, NULL);
  2833. if ((pNdisTapiAnswer->ulUserUserInfoSize = dwSize) != 0)
  2834. {
  2835. CopyMemory(pNdisTapiAnswer->UserUserInfo, lpsUserUserInfo, dwSize);
  2836. }
  2837. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  2838. ReleaseObjReadLock((HANDLE)hdCall);
  2839. return lRes;
  2840. }
  2841. LONG
  2842. TSPIAPI
  2843. TSPI_lineClose(
  2844. HDRVLINE hdLine
  2845. )
  2846. {
  2847. static DWORD dwSum = 0;
  2848. LONG lRes;
  2849. PDRVLINE pLine;
  2850. PNDISTAPI_REQUEST pNdisTapiRequest;
  2851. PNDIS_TAPI_CLOSE pNdisTapiClose;
  2852. TspLog(DL_TRACE, "lineClose(%d): line(%p)", ++dwSum, hdLine);
  2853. lRes = GetLineObjWithWriteLock(hdLine, &pLine);
  2854. if (lRes != TAPI_SUCCESS)
  2855. {
  2856. return lRes;
  2857. }
  2858. if ((lRes = PrepareSyncRequest(
  2859. OID_TAPI_CLOSE, // opcode
  2860. pLine->dwDeviceID, // device id
  2861. sizeof(NDIS_TAPI_CLOSE), // size of drve req data
  2862. &pNdisTapiRequest // ptr to ptr to request buffer
  2863. )) != TAPI_SUCCESS)
  2864. {
  2865. ReleaseObjWriteLock((HANDLE)hdLine);
  2866. return lRes;
  2867. }
  2868. pNdisTapiClose = (PNDIS_TAPI_CLOSE)pNdisTapiRequest->Data;
  2869. // mark line as invalid so any related events that show up
  2870. // will be discarded.
  2871. pLine->dwKey = INVALID_KEY;
  2872. pNdisTapiClose->hdLine = pLine->hd_Line;
  2873. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  2874. FreeRequest(pNdisTapiRequest);
  2875. CloseHandle(pLine->hMSPMutex);
  2876. if (TAPI_SUCCESS == lRes)
  2877. {
  2878. lRes = DecommitNegotiatedTSPIVersion(pLine->dwDeviceID);
  2879. }
  2880. ReleaseObjWriteLock((HANDLE)hdLine);
  2881. // release line resources
  2882. CloseObjHandle((HANDLE)hdLine);
  2883. return lRes;
  2884. }
  2885. LONG
  2886. TSPIAPI
  2887. TSPI_lineCloseCall(
  2888. HDRVCALL hdCall
  2889. )
  2890. {
  2891. static DWORD dwSum = 0;
  2892. LONG lRes;
  2893. HDRVLINE hdLine;
  2894. PDRVLINE pLine;
  2895. PDRVCALL pCall;
  2896. PNDISTAPI_REQUEST pNdisTapiRequestCloseCall;
  2897. PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
  2898. BOOL bInboundCall;
  2899. HDRV_CALL NdisTapiHandle;
  2900. TspLog(DL_TRACE, "lineCloseCall(%d): call(%p)", ++dwSum, hdCall);
  2901. lRes = GetLineHandleFromCallHandle(hdCall, &hdLine);
  2902. if (lRes != TAPI_SUCCESS)
  2903. {
  2904. return lRes;
  2905. }
  2906. //
  2907. // Initially we need to acquire the read lock for the objects.
  2908. // We can't acquire the write lock immediately because we might
  2909. // have to spin-wait in the GetNdisTapiHandle call.
  2910. //
  2911. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  2912. if (lRes != TAPI_SUCCESS)
  2913. {
  2914. return lRes;
  2915. }
  2916. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  2917. if (lRes != TAPI_SUCCESS)
  2918. {
  2919. ReleaseObjReadLock((HANDLE)hdLine);
  2920. return lRes;
  2921. }
  2922. bInboundCall = (INBOUND_CALL_KEY == pCall->dwKey);
  2923. NdisTapiHandle = GetNdisTapiHandle(pCall, &lRes);
  2924. if(lRes != TAPI_SUCCESS)
  2925. {
  2926. ReleaseObjReadLock((HANDLE)hdLine);
  2927. return lRes;
  2928. }
  2929. ReleaseObjReadLock((HANDLE)hdCall);
  2930. ReleaseObjReadLock((HANDLE)hdLine);
  2931. //
  2932. // Now acquire the write locks
  2933. //
  2934. lRes = AcquireObjWriteLock((HANDLE)hdLine);
  2935. if (lRes != TAPI_SUCCESS) {
  2936. return lRes;
  2937. }
  2938. lRes = AcquireObjWriteLock((HANDLE)hdCall);
  2939. if (lRes != TAPI_SUCCESS) {
  2940. ReleaseObjWriteLock((HANDLE)hdLine);
  2941. return lRes;
  2942. }
  2943. if ((lRes = PrepareSyncRequest(
  2944. OID_TAPI_CLOSE_CALL, // opcode
  2945. pCall->dwDeviceID, // device id
  2946. sizeof(NDIS_TAPI_CLOSE_CALL), // size of drve req data
  2947. &pNdisTapiRequestCloseCall // ptr to ptr to request buffer
  2948. )) != TAPI_SUCCESS)
  2949. {
  2950. ReleaseObjWriteLock((HANDLE)hdCall);
  2951. ReleaseObjWriteLock((HANDLE)hdLine);
  2952. return lRes;
  2953. }
  2954. // mark the call as bad so any events get discarded
  2955. pCall->dwKey = INVALID_KEY;
  2956. // set up the params & call the driver
  2957. pNdisTapiCloseCall = (PNDIS_TAPI_CLOSE_CALL)pNdisTapiRequestCloseCall->Data;
  2958. pNdisTapiCloseCall->hdCall = NdisTapiHandle;
  2959. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO,
  2960. pNdisTapiRequestCloseCall);
  2961. FreeRequest(pNdisTapiRequestCloseCall);
  2962. // if inbound call, remove it from the list
  2963. if (bInboundCall)
  2964. {
  2965. if (pCall->pNext)
  2966. {
  2967. pCall->pNext->pPrev = pCall->pPrev;
  2968. }
  2969. if (pCall->pPrev)
  2970. {
  2971. pCall->pPrev->pNext = pCall->pNext;
  2972. }
  2973. else
  2974. {
  2975. pLine->pInboundCalls = pCall->pNext;
  2976. }
  2977. }
  2978. ReleaseObjWriteLock((HANDLE)hdCall);
  2979. ReleaseObjWriteLock((HANDLE)hdLine);
  2980. // free the call struct now that the call is closed
  2981. CloseObjHandle((HANDLE)hdCall);
  2982. return lRes;
  2983. }
  2984. //
  2985. // Routine Description:
  2986. //
  2987. // Called when an instance of our MSP is closed. In this routine we
  2988. // just clean up our structures.
  2989. //
  2990. // Arguments:
  2991. // hdMSPLine - Our MSP handle: we returned this in
  2992. // TSPI_lineCreateMSPInstance()
  2993. //
  2994. // Return value:
  2995. // If the MSP handle is invalid, we return LINEERR_OPERATIONFAILED,
  2996. // otherwise we return NOERROR.
  2997. //
  2998. LONG
  2999. TSPIAPI
  3000. TSPI_lineCloseMSPInstance(
  3001. HDRVMSPLINE hdMSPLine
  3002. )
  3003. {
  3004. static DWORD dwSum = 0;
  3005. LONG lRes;
  3006. PDRVMSPLINE pMSPLine;
  3007. HDRVLINE hdLine;
  3008. PDRVLINE pLine;
  3009. DWORD dwStatus;
  3010. TspLog(DL_TRACE, "lineCloseMSPInstance(%d): MSPline(%p)",
  3011. ++dwSum, hdMSPLine);
  3012. lRes = GetLineHandleFromMSPLineHandle(hdMSPLine, &hdLine);
  3013. if (lRes != TAPI_SUCCESS)
  3014. {
  3015. return lRes;
  3016. }
  3017. lRes = GetLineObjWithWriteLock(hdLine, &pLine);
  3018. if (lRes != TAPI_SUCCESS)
  3019. {
  3020. return lRes;
  3021. }
  3022. lRes = GetMSPLineObjWithWriteLock(hdMSPLine, &pMSPLine);
  3023. if (lRes != TAPI_SUCCESS)
  3024. {
  3025. ReleaseObjWriteLock((HANDLE)hdLine);
  3026. return lRes;
  3027. }
  3028. pMSPLine->dwKey = INVALID_KEY;
  3029. if ((dwStatus = WaitForSingleObject(pLine->hMSPMutex, INFINITE))
  3030. != WAIT_OBJECT_0)
  3031. {
  3032. TspLog(DL_ERROR, "lineCloseMSPInstance: MSP mutex wait failed(%x)",
  3033. dwStatus);
  3034. ReleaseObjWriteLock((HANDLE)hdMSPLine);
  3035. ReleaseObjWriteLock((HANDLE)hdLine);
  3036. return LINEERR_OPERATIONFAILED;
  3037. }
  3038. pLine->pMSPLine = NULL;
  3039. if (!ReleaseMutex(pLine->hMSPMutex))
  3040. {
  3041. TspLog(DL_ERROR, "lineCloseMSPInstance: MSP mutex release failed");
  3042. ReleaseObjWriteLock((HANDLE)hdMSPLine);
  3043. ReleaseObjWriteLock((HANDLE)hdLine);
  3044. return LINEERR_OPERATIONFAILED;
  3045. }
  3046. ReleaseObjWriteLock((HANDLE)hdMSPLine);
  3047. ReleaseObjWriteLock((HANDLE)hdLine);
  3048. CloseObjHandle((HANDLE)hdMSPLine);
  3049. return lRes;
  3050. }
  3051. LONG
  3052. TSPIAPI
  3053. TSPI_lineConditionalMediaDetection(
  3054. HDRVLINE hdLine,
  3055. DWORD dwMediaModes,
  3056. LPLINECALLPARAMS const lpCallParams
  3057. )
  3058. {
  3059. static DWORD dwSum = 0;
  3060. LONG lRes;
  3061. PDRVLINE pLine;
  3062. PNDISTAPI_REQUEST pNdisTapiRequest;
  3063. PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION pNdisTapiConditionalMediaDetection;
  3064. TspLog(DL_TRACE, "lineConditionalMediaDetection(%d): line(%p), mode(%x)",
  3065. ++dwSum, hdLine, dwMediaModes);
  3066. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3067. if (lRes != TAPI_SUCCESS)
  3068. {
  3069. return lRes;
  3070. }
  3071. if ((lRes = PrepareSyncRequest(
  3072. OID_TAPI_CONDITIONAL_MEDIA_DETECTION, // opcode
  3073. pLine->dwDeviceID, // device id
  3074. sizeof(NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) +
  3075. (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)),
  3076. &pNdisTapiRequest // ptr to ptr to
  3077. // req buffer
  3078. )) != TAPI_SUCCESS)
  3079. {
  3080. ReleaseObjReadLock((HANDLE)hdLine);
  3081. return lRes;
  3082. }
  3083. pNdisTapiConditionalMediaDetection =
  3084. (PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) pNdisTapiRequest->Data;
  3085. pNdisTapiConditionalMediaDetection->hdLine = pLine->hd_Line;
  3086. pNdisTapiConditionalMediaDetection->ulMediaModes = dwMediaModes;
  3087. CopyMemory(
  3088. &pNdisTapiConditionalMediaDetection->LineCallParams,
  3089. lpCallParams,
  3090. lpCallParams->dwTotalSize
  3091. );
  3092. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  3093. FreeRequest(pNdisTapiRequest);
  3094. ReleaseObjReadLock((HANDLE)hdLine);
  3095. return lRes;
  3096. }
  3097. //
  3098. // Routine Description:
  3099. //
  3100. // Called when an instance of our MSP is created. In this routine we
  3101. // just set up our structures and save away the TAPI handle to this
  3102. // MSP instance.
  3103. //
  3104. // Arguments:
  3105. // hdLine - Handle to the line on which the MSP is being created
  3106. // dwAddressID - An address on the given open line device
  3107. // htMSPLine - The TAPI handle to the MSP call
  3108. // lphdMSPLine - Pointer to location in which to return our handle
  3109. // to the MSP instance.
  3110. //
  3111. // Return value:
  3112. // If things go well, NOERROR, otherwise LINEERR_NOMEM if we fail to
  3113. // allocate a DRVMSPLINE structure.
  3114. //
  3115. LONG
  3116. TSPIAPI
  3117. TSPI_lineCreateMSPInstance(
  3118. HDRVLINE hdLine,
  3119. DWORD dwAddressID,
  3120. HTAPIMSPLINE htMSPLine,
  3121. LPHDRVMSPLINE lphdMSPLine
  3122. )
  3123. {
  3124. static DWORD dwSum = 0;
  3125. LONG lRes;
  3126. PDRVLINE pLine;
  3127. PDRVMSPLINE pMSPLine;
  3128. DWORD dwStatus;
  3129. TspLog(DL_TRACE, "lineCreateMSPInstance(%d): line(%p), addressID(%x)",
  3130. ++dwSum, hdLine, dwAddressID);
  3131. lRes = GetLineObjWithWriteLock(hdLine, &pLine);
  3132. if (lRes != TAPI_SUCCESS)
  3133. {
  3134. return lRes;
  3135. }
  3136. // allocate and init a DRVMSPLINE struct
  3137. if (!(pMSPLine = AllocMSPLineObj(sizeof(DRVMSPLINE))))
  3138. {
  3139. TspLog(DL_ERROR,
  3140. "lineCreateMSPInstance: failed to create MSP line obj");
  3141. ReleaseObjWriteLock((HANDLE)hdLine);
  3142. return LINEERR_NOMEM;
  3143. }
  3144. pMSPLine->dwKey = MSP_KEY;
  3145. pMSPLine->hdLine = hdLine;
  3146. pMSPLine->dwAddressID = dwAddressID;
  3147. pMSPLine->htMSPLine = htMSPLine;
  3148. if ((dwStatus = WaitForSingleObject(pLine->hMSPMutex, INFINITE))
  3149. != WAIT_OBJECT_0)
  3150. {
  3151. TspLog(DL_ERROR, "lineCreateMSPInstance: MSP mutex wait failed(%x)",
  3152. dwStatus);
  3153. FreeMSPLineObj(pMSPLine);
  3154. ReleaseObjWriteLock((HANDLE)hdLine);
  3155. return LINEERR_OPERATIONFAILED;
  3156. }
  3157. pLine->pMSPLine = pMSPLine;
  3158. if (!ReleaseMutex(pLine->hMSPMutex))
  3159. {
  3160. TspLog(DL_ERROR, "lineCreateMSPInstance: MSP mutex release failed");
  3161. FreeMSPLineObj(pMSPLine);
  3162. ReleaseObjWriteLock((HANDLE)hdLine);
  3163. return LINEERR_OPERATIONFAILED;
  3164. }
  3165. // make sure release read lock before calling OpenObjHandle()
  3166. // to avoid deadlock on acquiring write lock for the global mapper
  3167. ReleaseObjWriteLock((HANDLE)hdLine);
  3168. lRes = OpenObjHandle(pMSPLine, FreeMSPLineObj, (HANDLE *)lphdMSPLine);
  3169. if (lRes != TAPI_SUCCESS)
  3170. {
  3171. TspLog(DL_ERROR,
  3172. "lineCreateMSPInstance: failed to map obj(%p) to handle",
  3173. pMSPLine);
  3174. FreeMSPLineObj(pMSPLine);
  3175. }
  3176. return lRes;
  3177. }
  3178. LONG
  3179. PASCAL
  3180. TSPI_lineDevSpecific_postProcess(
  3181. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  3182. LONG lRes,
  3183. PDWORD_PTR callStateMsgParams
  3184. )
  3185. {
  3186. TspLog(DL_TRACE, "lineDevSpecific_post: lRes(%x)", lRes);
  3187. if (TAPI_SUCCESS == lRes)
  3188. {
  3189. PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =
  3190. (PNDIS_TAPI_DEV_SPECIFIC)pAsyncReqWrapper->NdisTapiRequest.Data;
  3191. CopyMemory(
  3192. (LPVOID) pAsyncReqWrapper->dwRequestSpecific,
  3193. pNdisTapiDevSpecific->Params,
  3194. pNdisTapiDevSpecific->ulParamsSize
  3195. );
  3196. }
  3197. return lRes;
  3198. }
  3199. LONG
  3200. TSPIAPI
  3201. TSPI_lineDevSpecific(
  3202. DRV_REQUESTID dwRequestID,
  3203. HDRVLINE hdLine,
  3204. DWORD dwAddressID,
  3205. HDRVCALL hdCall,
  3206. LPVOID lpParams,
  3207. DWORD dwSize
  3208. )
  3209. {
  3210. static DWORD dwSum = 0;
  3211. LONG lRes;
  3212. PDRVLINE pLine;
  3213. PDRVCALL pCall = NULL;
  3214. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3215. PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific;
  3216. TspLog(DL_TRACE,
  3217. "lineDevSpecific(%d): reqID(%x), line(%p), addressID(%x), call(%p)",
  3218. ++dwSum, dwRequestID, hdLine, dwAddressID, hdCall);
  3219. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3220. if (lRes != TAPI_SUCCESS)
  3221. {
  3222. return lRes;
  3223. }
  3224. if ((lRes = PrepareAsyncRequest(
  3225. OID_TAPI_DEV_SPECIFIC, // opcode
  3226. pLine->dwDeviceID, // device id
  3227. dwRequestID, // request id
  3228. sizeof(NDIS_TAPI_DEV_SPECIFIC) + // size of drv request data
  3229. (dwSize - 1),
  3230. &pAsyncReqWrapper // ptr to ptr to request buffer
  3231. )) != TAPI_SUCCESS)
  3232. {
  3233. ReleaseObjReadLock((HANDLE)hdLine);
  3234. return lRes;
  3235. }
  3236. pNdisTapiDevSpecific =
  3237. (PNDIS_TAPI_DEV_SPECIFIC)pAsyncReqWrapper->NdisTapiRequest.Data;
  3238. pNdisTapiDevSpecific->hdLine = pLine->hd_Line;
  3239. pNdisTapiDevSpecific->ulAddressID = dwAddressID;
  3240. if (hdCall)
  3241. {
  3242. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3243. if (lRes != TAPI_SUCCESS)
  3244. {
  3245. FreeRequest(pAsyncReqWrapper);
  3246. ReleaseObjReadLock((HANDLE)hdLine);
  3247. return lRes;
  3248. }
  3249. pNdisTapiDevSpecific->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3250. if(lRes != TAPI_SUCCESS)
  3251. {
  3252. FreeRequest(pAsyncReqWrapper);
  3253. ReleaseObjReadLock((HANDLE)hdLine);
  3254. return lRes;
  3255. }
  3256. }
  3257. else
  3258. {
  3259. pNdisTapiDevSpecific->hdCall = (HDRV_CALL)NULL;
  3260. }
  3261. pNdisTapiDevSpecific->ulParamsSize = dwSize;
  3262. CopyMemory(pNdisTapiDevSpecific->Params, lpParams, dwSize);
  3263. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)lpParams;
  3264. pAsyncReqWrapper->pfnPostProcess = TSPI_lineDevSpecific_postProcess;
  3265. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pAsyncReqWrapper);
  3266. if (pCall != NULL)
  3267. {
  3268. ReleaseObjReadLock((HANDLE)hdCall);
  3269. }
  3270. ReleaseObjReadLock((HANDLE)hdLine);
  3271. return lRes;
  3272. }
  3273. LONG
  3274. TSPIAPI
  3275. TSPI_lineDial(
  3276. DRV_REQUESTID dwRequestID,
  3277. HDRVCALL hdCall,
  3278. LPCWSTR lpszDestAddress,
  3279. DWORD dwCountryCode
  3280. )
  3281. {
  3282. static DWORD dwSum = 0;
  3283. LONG lRes;
  3284. PDRVCALL pCall;
  3285. DWORD dwLength = lstrlenW (lpszDestAddress) + 1;
  3286. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3287. PNDIS_TAPI_DIAL pNdisTapiDial;
  3288. TspLog(DL_TRACE, "lineDial(%d): reqID(%x), call(%p)",
  3289. ++dwSum, dwRequestID, hdCall);
  3290. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3291. if (lRes != TAPI_SUCCESS)
  3292. {
  3293. return lRes;
  3294. }
  3295. if ((lRes = PrepareAsyncRequest(
  3296. OID_TAPI_DIAL, // opcode
  3297. pCall->dwDeviceID, // device id
  3298. dwRequestID, // request id
  3299. sizeof(NDIS_TAPI_DIAL) + dwLength, // size of driver req buffer
  3300. &pAsyncReqWrapper // ptr to ptr to req buffer
  3301. )) != TAPI_SUCCESS)
  3302. {
  3303. ReleaseObjReadLock((HANDLE)hdCall);
  3304. return lRes;
  3305. }
  3306. pNdisTapiDial =
  3307. (PNDIS_TAPI_DIAL)pAsyncReqWrapper->NdisTapiRequest.Data;
  3308. pNdisTapiDial->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3309. if(lRes != TAPI_SUCCESS)
  3310. {
  3311. FreeRequest(pAsyncReqWrapper);
  3312. return lRes;
  3313. }
  3314. pNdisTapiDial->ulDestAddressSize = dwLength;
  3315. WideCharToMultiByte(CP_ACP, 0, lpszDestAddress,
  3316. -1, (LPSTR)pNdisTapiDial->szDestAddress,
  3317. dwLength, NULL, NULL);
  3318. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  3319. ReleaseObjReadLock((HANDLE)hdCall);
  3320. return lRes;
  3321. }
  3322. LONG
  3323. TSPIAPI
  3324. TSPI_lineDrop(
  3325. DRV_REQUESTID dwRequestID,
  3326. HDRVCALL hdCall,
  3327. LPCSTR lpsUserUserInfo,
  3328. DWORD dwSize
  3329. )
  3330. {
  3331. static DWORD dwSum = 0;
  3332. LONG lRes;
  3333. PDRVCALL pCall;
  3334. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3335. PNDIS_TAPI_DROP pNdisTapiDrop;
  3336. HDRV_CALL NdisTapiHandle;
  3337. TspLog(DL_TRACE, "lineDrop(%d): reqID(%x), call(%p)",
  3338. ++dwSum, dwRequestID, hdCall);
  3339. //
  3340. // Initially we need to acquire the read lock for the object.
  3341. // We can't acquire the write lock immediately because we
  3342. // might have to spin-wait in the GetNdisTapiHandle call.
  3343. //
  3344. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3345. if (lRes != TAPI_SUCCESS)
  3346. {
  3347. return lRes;
  3348. }
  3349. NdisTapiHandle = GetNdisTapiHandle(pCall, &lRes);
  3350. if(lRes != TAPI_SUCCESS)
  3351. {
  3352. return lRes;
  3353. }
  3354. ReleaseObjReadLock((HANDLE)hdCall);
  3355. //
  3356. // Now acquire the write lock
  3357. //
  3358. lRes = AcquireObjWriteLock((HANDLE)hdCall);
  3359. if (lRes) {
  3360. return lRes;
  3361. }
  3362. if ((lRes = PrepareAsyncRequest(
  3363. OID_TAPI_DROP, // opcode
  3364. pCall->dwDeviceID, // device id
  3365. dwRequestID, // request id
  3366. sizeof(NDIS_TAPI_DROP) + dwSize, // size of driver req buffer
  3367. &pAsyncReqWrapper // ptr to ptr to req buffer
  3368. )) != TAPI_SUCCESS)
  3369. {
  3370. ReleaseObjWriteLock((HANDLE)hdCall);
  3371. return lRes;
  3372. }
  3373. pNdisTapiDrop =
  3374. (PNDIS_TAPI_DROP)pAsyncReqWrapper->NdisTapiRequest.Data;
  3375. pNdisTapiDrop->hdCall = NdisTapiHandle;
  3376. //
  3377. // @@@: the following is for legacy NDISWAN ISDN miniports
  3378. //
  3379. // Safely mark the call as dropped so the CloseCall code
  3380. // won't follow up with another "automatic" drop
  3381. //
  3382. pCall->bDropped = TRUE;
  3383. if ((pNdisTapiDrop->ulUserUserInfoSize = dwSize) != 0)
  3384. {
  3385. CopyMemory(pNdisTapiDrop->UserUserInfo, lpsUserUserInfo, dwSize);
  3386. }
  3387. ReleaseObjWriteLock((HANDLE)hdCall);
  3388. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  3389. return lRes;
  3390. }
  3391. LONG
  3392. PASCAL
  3393. TSPI_lineGatherDigits_postProcess(
  3394. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  3395. LONG lRes,
  3396. LPDWORD callStateMsgParams
  3397. )
  3398. {
  3399. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits;
  3400. LPWSTR lpsDigitsBuffer;
  3401. LONG lSuc;
  3402. HDRVLINE hdLine;
  3403. PDRVLINE pLine;
  3404. HDRVCALL hdCall;
  3405. PDRVCALL pCall;
  3406. TspLog(DL_TRACE, "lineGatherDigits_post: lRes(%x)", lRes);
  3407. hdCall = (HDRVCALL)(pAsyncReqWrapper->dwRequestSpecific);
  3408. lSuc = GetLineHandleFromCallHandle(hdCall, &hdLine);
  3409. if (lSuc != TAPI_SUCCESS)
  3410. {
  3411. return lSuc;
  3412. }
  3413. lSuc = GetLineObjWithReadLock(hdLine, &pLine);
  3414. if (lSuc != TAPI_SUCCESS)
  3415. {
  3416. return lSuc;
  3417. }
  3418. lSuc = GetCallObjWithReadLock(hdCall, &pCall);
  3419. if (lSuc != TAPI_SUCCESS)
  3420. {
  3421. ReleaseObjReadLock((HANDLE)hdLine);
  3422. return lSuc;
  3423. }
  3424. if (TAPI_SUCCESS == lRes)
  3425. {
  3426. pNdisTapiGatherDigits =
  3427. (PNDIS_TAPI_GATHER_DIGITS)pAsyncReqWrapper->NdisTapiRequest.Data;
  3428. lpsDigitsBuffer = (LPWSTR)(((LPBYTE)pNdisTapiGatherDigits) +
  3429. pNdisTapiGatherDigits->ulDigitsBufferOffset);
  3430. wcscpy(pNdisTapiGatherDigits->lpsOrigDigitsBuffer, lpsDigitsBuffer);
  3431. // send the LINE_GATHERDIGITS message to TAPI.
  3432. (*gpfnLineEvent)(pLine->htLine,
  3433. pCall->htCall,
  3434. LINE_GATHERDIGITS,
  3435. (DWORD_PTR)pNdisTapiGatherDigits->ulTerminationReason,
  3436. (DWORD_PTR)pNdisTapiGatherDigits->ulEndToEndID,
  3437. (DWORD_PTR)pNdisTapiGatherDigits->ulTickCount);
  3438. }
  3439. ReleaseObjReadLock((HANDLE)hdCall);
  3440. ReleaseObjReadLock((HANDLE)hdLine);
  3441. return lRes;
  3442. }
  3443. // ++ DTMFDigitToOrdinal
  3444. //
  3445. // Turn a DTMF digit into a number between 0 and 15. The digits are assigned
  3446. // numbers in the following order: '0' - '9', 'A' - 'D', '*', '#'.
  3447. //
  3448. // Arguments:
  3449. // wcDigit - The digit, expressed as a UNICODE character.
  3450. //
  3451. // Return value:
  3452. // A number between 0 and 15, or 16 if the digit passed in was not a valid
  3453. // DTMF digit.
  3454. //
  3455. ULONG
  3456. DTMFDigitToOrdinal(
  3457. WCHAR wcDigit
  3458. )
  3459. {
  3460. if ((wcDigit >= L'0') && (wcDigit <= L'9'))
  3461. {
  3462. return (wcDigit - L'0');
  3463. }
  3464. if ((wcDigit >= L'A') && (wcDigit <= L'D'))
  3465. {
  3466. return (10 + (wcDigit - L'A'));
  3467. }
  3468. if (L'*' == wcDigit)
  3469. {
  3470. return 14;
  3471. }
  3472. if (L'#' == wcDigit)
  3473. {
  3474. return 15;
  3475. }
  3476. return 16;
  3477. }
  3478. LONG
  3479. TSPIAPI
  3480. TSPI_lineGatherDigits(
  3481. HDRVCALL hdCall,
  3482. DWORD dwEndToEndID,
  3483. DWORD dwDigitModes,
  3484. LPWSTR lpsDigits,
  3485. DWORD dwNumDigits,
  3486. LPCWSTR lpszTerminationDigits,
  3487. DWORD dwFirstDigitTimeout,
  3488. DWORD dwInterDigitTimeout
  3489. )
  3490. {
  3491. static DWORD dwSum = 0;
  3492. LONG lRes;
  3493. DWORD dwDigitsLength, dwTermDigitsLength;
  3494. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  3495. PDRVCALL pCall;
  3496. WCHAR *pwszTerminationDigit;
  3497. PNDIS_TAPI_GATHER_DIGITS pNdisTapiGatherDigits;
  3498. TspLog(DL_TRACE, "lineGatherDigits(%d): call(%p), EndToEndID(%x)",
  3499. hdCall, dwEndToEndID);
  3500. if (0 == dwNumDigits)
  3501. {
  3502. TspLog(DL_ERROR, "lineGatherDigits: dwNumDigits is 0");
  3503. return LINEERR_INVALPARAM;
  3504. }
  3505. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3506. if (lRes != TAPI_SUCCESS)
  3507. {
  3508. return lRes;
  3509. }
  3510. // calculate the length required to store the digits.
  3511. if (lpsDigits)
  3512. {
  3513. dwDigitsLength = dwNumDigits + 1;
  3514. }
  3515. else
  3516. {
  3517. dwDigitsLength = 0;
  3518. }
  3519. if ((lRes = PrepareAsyncRequest(
  3520. OID_TAPI_GATHER_DIGITS,
  3521. pCall->dwDeviceID,
  3522. dwEndToEndID, // @@@: don't know what to pass in
  3523. sizeof(NDIS_TAPI_GATHER_DIGITS) + (dwDigitsLength * 2),
  3524. &pAsyncReqWrapper
  3525. )) != TAPI_SUCCESS)
  3526. {
  3527. ReleaseObjReadLock((HANDLE)hdCall);
  3528. return lRes;
  3529. }
  3530. pNdisTapiGatherDigits =
  3531. (PNDIS_TAPI_GATHER_DIGITS) pAsyncReqWrapper->NdisTapiRequest.Data;
  3532. // store the pointer to the pCall because we'll need it
  3533. // in our postprocess function.
  3534. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)hdCall;
  3535. //
  3536. // Set up the parameters in our structure.
  3537. //
  3538. pNdisTapiGatherDigits->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3539. if(lRes != TAPI_SUCCESS)
  3540. {
  3541. FreeRequest(pAsyncReqWrapper);
  3542. return lRes;
  3543. }
  3544. pNdisTapiGatherDigits->ulEndToEndID = dwEndToEndID;
  3545. pNdisTapiGatherDigits->ulDigitModes = dwDigitModes;
  3546. pNdisTapiGatherDigits->lpsOrigDigitsBuffer = lpsDigits;
  3547. pNdisTapiGatherDigits->ulDigitsBufferOffset =
  3548. (lpsDigits ? sizeof(NDIS_TAPI_GATHER_DIGITS) : 0);
  3549. pNdisTapiGatherDigits->ulNumDigitsNeeded = dwNumDigits;
  3550. pNdisTapiGatherDigits->ulNumDigitsRead = 0;
  3551. pNdisTapiGatherDigits->ulFirstDigitTimeout = dwFirstDigitTimeout;
  3552. pNdisTapiGatherDigits->ulInterDigitTimeout = dwInterDigitTimeout;
  3553. //
  3554. // Turn the termination digits into a bit mask. There are 16 DTMF digits
  3555. // and I assign each one a bit in a word. If the digit is present in the
  3556. // termination digit string we were passed, we set the bit to 1 in the
  3557. // mask, otherwise it's set to zero. This makes it easier for the proxy
  3558. // to determine if it's read a termination digit: just turn the read digit
  3559. // into it's assigned bit number between 0 and 15 (I use the order '0' -
  3560. // '9', 'A' - 'D', '*', '#') and bitwise AND the mask with a word
  3561. // containing a 1 in the bit belonging to the digit. This makes it an O(1)
  3562. // operation.
  3563. //
  3564. pNdisTapiGatherDigits->ulTerminationDigitsMask = 0;
  3565. pwszTerminationDigit = (LPWSTR)lpszTerminationDigits;
  3566. while (*pwszTerminationDigit != UNICODE_NULL)
  3567. {
  3568. ULONG ulBitNum = DTMFDigitToOrdinal(*pwszTerminationDigit);
  3569. if (ulBitNum < 16) {
  3570. pNdisTapiGatherDigits->ulTerminationDigitsMask |= (1 << ulBitNum);
  3571. }
  3572. pwszTerminationDigit++;
  3573. }
  3574. pAsyncReqWrapper->pfnPostProcess = TSPI_lineGatherDigits_postProcess;
  3575. //
  3576. // I'm not setting lRes to the return value from here. This is because
  3577. // TAPI requires this function to return zero in the success case. This
  3578. // is a bit of a hokey situation - will need further discussion.
  3579. //
  3580. AsyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pAsyncReqWrapper);
  3581. ReleaseObjReadLock((HANDLE)hdCall);
  3582. return lRes;
  3583. }
  3584. LONG
  3585. TSPIAPI
  3586. TSPI_lineGetAddressCaps(
  3587. DWORD dwDeviceID,
  3588. DWORD dwAddressID,
  3589. DWORD dwTSPIVersion,
  3590. DWORD dwExtVersion,
  3591. LPLINEADDRESSCAPS lpAddressCaps
  3592. )
  3593. {
  3594. static DWORD dwSum = 0;
  3595. LONG lRes;
  3596. PNDISTAPI_REQUEST pNdisTapiRequest;
  3597. PLINE_ADDRESS_CAPS pCaps;
  3598. PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps;
  3599. TspLog(DL_TRACE,
  3600. "lineGetAddressCaps(%d): deviceID(%x), addressID(%x), "\
  3601. "TSPIV(%x), ExtV(%x)",
  3602. ++dwSum, dwDeviceID, dwAddressID);
  3603. if ((lRes = PrepareSyncRequest(
  3604. OID_TAPI_GET_ADDRESS_CAPS, // opcode
  3605. dwDeviceID, // device id
  3606. sizeof(NDIS_TAPI_GET_ADDRESS_CAPS) + // size of req data
  3607. (lpAddressCaps->dwTotalSize - sizeof(LINE_ADDRESS_CAPS)),
  3608. &pNdisTapiRequest // ptr to ptr to req buf
  3609. )) != TAPI_SUCCESS)
  3610. {
  3611. return lRes;
  3612. }
  3613. pNdisTapiGetAddressCaps =
  3614. (PNDIS_TAPI_GET_ADDRESS_CAPS)pNdisTapiRequest->Data;
  3615. pNdisTapiGetAddressCaps->ulDeviceID = dwDeviceID;
  3616. pNdisTapiGetAddressCaps->ulAddressID = dwAddressID;
  3617. pNdisTapiGetAddressCaps->ulExtVersion = dwExtVersion;
  3618. pCaps = &pNdisTapiGetAddressCaps->LineAddressCaps;
  3619. pCaps->ulTotalSize = lpAddressCaps->dwTotalSize;
  3620. pCaps->ulNeededSize = pCaps->ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
  3621. ZeroMemory(
  3622. &pCaps->ulLineDeviceID,
  3623. sizeof(LINE_ADDRESS_CAPS) - 3 * sizeof(ULONG)
  3624. );
  3625. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3626. if (lRes != TAPI_SUCCESS)
  3627. {
  3628. FreeRequest(pNdisTapiRequest);
  3629. return lRes;
  3630. }
  3631. //
  3632. // Do some post processing to the returned data structure
  3633. // before passing it back to tapi:
  3634. // 1. Pad the area between the fixed 1.0 structure and the
  3635. // var data that the miniports pass back with 0's so a
  3636. // bad app that disregards the 1.0 version negotiation &
  3637. // references new 1.4 or 2.0 structure fields won't blow up
  3638. // 2. Convert ascii strings to unicode, & rebase all var data
  3639. //
  3640. //
  3641. // The real needed size is the sum of that requested by the
  3642. // underlying driver, plus padding for the new TAPI 1.4/2.0
  3643. // structure fields, plus the size of the var data returned
  3644. // by the driver to account for the ascii->unicode conversion.
  3645. // @@@ Granted, we are very liberal in computing the value for
  3646. // this last part, but at least this way it's fast & we'll
  3647. // never have too little buffer space.
  3648. //
  3649. lpAddressCaps->dwNeededSize =
  3650. pCaps->ulNeededSize +
  3651. (sizeof(LINEADDRESSCAPS) - // v2.0 struct
  3652. sizeof(LINE_ADDRESS_CAPS)) + // v1.0 struct
  3653. (pCaps->ulNeededSize - sizeof(LINE_ADDRESS_CAPS));
  3654. //
  3655. // Copy over the fixed fields that don't need changing, i.e.
  3656. // everything from dwAddressSharing to dwCallCompletionModes
  3657. //
  3658. lpAddressCaps->dwLineDeviceID = dwDeviceID;
  3659. CopyMemory(
  3660. &lpAddressCaps->dwAddressSharing,
  3661. &pCaps->ulAddressSharing,
  3662. sizeof(LINE_ADDRESS_CAPS) - (12 * sizeof(DWORD))
  3663. );
  3664. if (lpAddressCaps->dwNeededSize > lpAddressCaps->dwTotalSize)
  3665. {
  3666. lpAddressCaps->dwUsedSize =
  3667. (lpAddressCaps->dwTotalSize < sizeof(LINEADDRESSCAPS) ?
  3668. lpAddressCaps->dwTotalSize : sizeof(LINEADDRESSCAPS));
  3669. }
  3670. else
  3671. {
  3672. lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS); // v2.0 struct
  3673. //
  3674. // Supported device classes
  3675. //
  3676. INSERTVARDATA(
  3677. pCaps,
  3678. &pCaps->ulDeviceClassesSize,
  3679. lpAddressCaps,
  3680. &lpAddressCaps->dwDeviceClassesSize,
  3681. sizeof(LINE_ADDRESS_CAPS),
  3682. "LINE_ADDRESS_CAPS.DeviceClasses"
  3683. );
  3684. INSERTVARDATA(
  3685. pCaps,
  3686. &pCaps->ulAddressSize,
  3687. lpAddressCaps,
  3688. &lpAddressCaps->dwAddressSize,
  3689. sizeof(LINE_ADDRESS_CAPS),
  3690. "LINE_ADDRESS_CAPS.Address"
  3691. );
  3692. INSERTVARDATA(
  3693. pCaps,
  3694. &pCaps->ulDevSpecificSize,
  3695. lpAddressCaps,
  3696. &lpAddressCaps->dwDevSpecificSize,
  3697. sizeof(LINE_ADDRESS_CAPS),
  3698. "LINE_ADDRESS_CAPS.DevSpecific"
  3699. );
  3700. if (pCaps->ulCompletionMsgTextSize != 0)
  3701. {
  3702. // @@@ convert ComplMsgText to unicode???
  3703. INSERTVARDATA(
  3704. pCaps,
  3705. &pCaps->ulCompletionMsgTextSize,
  3706. lpAddressCaps,
  3707. &lpAddressCaps->dwCompletionMsgTextSize,
  3708. sizeof(LINE_ADDRESS_CAPS),
  3709. "LINE_ADDRESS_CAPS.CompletionMsgText"
  3710. );
  3711. lpAddressCaps->dwNumCompletionMessages =
  3712. pCaps->ulNumCompletionMessages;
  3713. lpAddressCaps->dwCompletionMsgTextEntrySize =
  3714. pCaps->ulCompletionMsgTextEntrySize;
  3715. }
  3716. // make sure dwNeededSize == dwUsedSize
  3717. lpAddressCaps->dwNeededSize = lpAddressCaps->dwUsedSize;
  3718. }
  3719. FreeRequest(pNdisTapiRequest);
  3720. return lRes;
  3721. }
  3722. LONG
  3723. TSPIAPI
  3724. TSPI_lineGetAddressID(
  3725. HDRVLINE hdLine,
  3726. LPDWORD lpdwAddressID,
  3727. DWORD dwAddressMode,
  3728. LPCWSTR lpsAddress,
  3729. DWORD dwSize
  3730. )
  3731. {
  3732. static DWORD dwSum = 0;
  3733. LONG lRes;
  3734. PDRVLINE pLine;
  3735. PNDISTAPI_REQUEST pNdisTapiRequest;
  3736. PNDIS_TAPI_GET_ADDRESS_ID pNdisTapiGetAddressID;
  3737. TspLog(DL_TRACE, "lineGetAddressID(%d): line(%p), addressMode(%x)",
  3738. ++dwSum, hdLine, dwAddressMode);
  3739. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3740. if (lRes != TAPI_SUCCESS)
  3741. {
  3742. return lRes;
  3743. }
  3744. if ((lRes = PrepareSyncRequest(
  3745. OID_TAPI_GET_ADDRESS_ID, // opcode
  3746. pLine->dwDeviceID, // device id
  3747. sizeof(NDIS_TAPI_GET_ADDRESS_ID) + // size of req data
  3748. dwSize / 2 - 1,
  3749. &pNdisTapiRequest // ptr to ptr to req buf
  3750. )) != TAPI_SUCCESS)
  3751. {
  3752. ReleaseObjReadLock((HANDLE)hdLine);
  3753. return lRes;
  3754. }
  3755. pNdisTapiGetAddressID = (PNDIS_TAPI_GET_ADDRESS_ID)pNdisTapiRequest->Data;
  3756. pNdisTapiGetAddressID->hdLine = pLine->hd_Line;
  3757. pNdisTapiGetAddressID->ulAddressMode = dwAddressMode;
  3758. pNdisTapiGetAddressID->ulAddressSize = dwSize / 2;
  3759. WideCharToMultiByte(CP_ACP, 0, lpsAddress, dwSize,
  3760. (LPSTR)pNdisTapiGetAddressID->szAddress, dwSize / 2, NULL, NULL);
  3761. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3762. if (TAPI_SUCCESS == lRes)
  3763. {
  3764. *lpdwAddressID = pNdisTapiGetAddressID->ulAddressID;
  3765. TspLog(DL_INFO, "lineGetAddressID: addressID(%x)", *lpdwAddressID);
  3766. }
  3767. FreeRequest(pNdisTapiRequest);
  3768. ReleaseObjReadLock((HANDLE)hdLine);
  3769. return lRes;
  3770. }
  3771. LONG
  3772. TSPIAPI
  3773. TSPI_lineGetAddressStatus(
  3774. HDRVLINE hdLine,
  3775. DWORD dwAddressID,
  3776. LPLINEADDRESSSTATUS lpAddressStatus
  3777. )
  3778. {
  3779. static DWORD dwSum = 0;
  3780. LONG lRes;
  3781. PDRVLINE pLine;
  3782. PNDISTAPI_REQUEST pNdisTapiRequest;
  3783. PLINE_ADDRESS_STATUS pStatus;
  3784. PNDIS_TAPI_GET_ADDRESS_STATUS pNdisTapiGetAddressStatus;
  3785. TspLog(DL_TRACE, "lineGetAddressStatus(%d): line(%p), addressID(%x)",
  3786. ++dwSum, hdLine, dwAddressID);
  3787. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  3788. if (lRes != TAPI_SUCCESS)
  3789. {
  3790. return lRes;
  3791. }
  3792. if ((lRes = PrepareSyncRequest(
  3793. OID_TAPI_GET_ADDRESS_STATUS, // opcode
  3794. pLine->dwDeviceID, // device id
  3795. sizeof(NDIS_TAPI_GET_ADDRESS_STATUS) + // size of req data
  3796. (lpAddressStatus->dwTotalSize - sizeof(LINE_ADDRESS_STATUS)),
  3797. &pNdisTapiRequest // ptr to ptr to req buf
  3798. )) != TAPI_SUCCESS)
  3799. {
  3800. ReleaseObjReadLock((HANDLE)hdLine);
  3801. return lRes;
  3802. }
  3803. pNdisTapiGetAddressStatus =
  3804. (PNDIS_TAPI_GET_ADDRESS_STATUS)pNdisTapiRequest->Data;
  3805. pNdisTapiGetAddressStatus->hdLine = pLine->hd_Line;
  3806. pNdisTapiGetAddressStatus->ulAddressID = dwAddressID;
  3807. pStatus = &pNdisTapiGetAddressStatus->LineAddressStatus;
  3808. pStatus->ulTotalSize = lpAddressStatus->dwTotalSize;
  3809. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_ADDRESS_STATUS);
  3810. ZeroMemory(&pStatus->ulNumInUse,
  3811. sizeof(LINE_ADDRESS_STATUS) - 3 * sizeof(ULONG));
  3812. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3813. if (TAPI_SUCCESS == lRes)
  3814. {
  3815. CopyMemory(
  3816. lpAddressStatus,
  3817. &pNdisTapiGetAddressStatus->LineAddressStatus,
  3818. pNdisTapiGetAddressStatus->LineAddressStatus.ulUsedSize
  3819. );
  3820. }
  3821. FreeRequest(pNdisTapiRequest);
  3822. ReleaseObjReadLock((HANDLE)hdLine);
  3823. return lRes;
  3824. }
  3825. LONG
  3826. TSPIAPI
  3827. TSPI_lineGetCallAddressID(
  3828. HDRVCALL hdCall,
  3829. LPDWORD lpdwAddressID
  3830. )
  3831. {
  3832. static DWORD dwSum = 0;
  3833. LONG lRes;
  3834. PDRVCALL pCall;
  3835. PNDISTAPI_REQUEST pNdisTapiRequest;
  3836. PNDIS_TAPI_GET_CALL_ADDRESS_ID pNdisTapiGetCallAddressID;
  3837. TspLog(DL_TRACE, "lineGetCallAddressID(%d): call(%p)", ++dwSum, hdCall);
  3838. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3839. if (lRes != TAPI_SUCCESS)
  3840. {
  3841. return lRes;
  3842. }
  3843. if ((lRes = PrepareSyncRequest(
  3844. OID_TAPI_GET_CALL_ADDRESS_ID, // opcode
  3845. pCall->dwDeviceID, // device id
  3846. sizeof(NDIS_TAPI_GET_CALL_ADDRESS_ID), // size of req data
  3847. &pNdisTapiRequest // ptr to ptr to req buf
  3848. )) != TAPI_SUCCESS)
  3849. {
  3850. ReleaseObjReadLock((HANDLE)hdCall);
  3851. return lRes;
  3852. }
  3853. pNdisTapiGetCallAddressID =
  3854. (PNDIS_TAPI_GET_CALL_ADDRESS_ID)pNdisTapiRequest->Data;
  3855. pNdisTapiGetCallAddressID->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3856. if(lRes != TAPI_SUCCESS)
  3857. {
  3858. FreeRequest(pNdisTapiRequest);
  3859. return lRes;
  3860. }
  3861. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3862. if (TAPI_SUCCESS == lRes)
  3863. {
  3864. *lpdwAddressID = pNdisTapiGetCallAddressID->ulAddressID;
  3865. TspLog(DL_INFO, "lineGetCallAddressID: addressID(%x)", *lpdwAddressID);
  3866. }
  3867. FreeRequest(pNdisTapiRequest);
  3868. ReleaseObjReadLock((HANDLE)hdCall);
  3869. return lRes;
  3870. }
  3871. LONG
  3872. TSPIAPI
  3873. TSPI_lineGetCallInfo(
  3874. HDRVCALL hdCall,
  3875. LPLINECALLINFO lpCallInfo
  3876. )
  3877. {
  3878. static DWORD dwSum = 0;
  3879. LONG lRes;
  3880. PDRVCALL pCall;
  3881. PNDISTAPI_REQUEST pNdisTapiRequest;
  3882. PLINE_CALL_INFO pInfo;
  3883. PNDIS_TAPI_GET_CALL_INFO pNdisTapiGetCallInfo;
  3884. TspLog(DL_TRACE, "lineGetCallInfo(%d): call(%p)", ++dwSum, hdCall);
  3885. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  3886. if (lRes != TAPI_SUCCESS)
  3887. {
  3888. return lRes;
  3889. }
  3890. if ((lRes = PrepareSyncRequest(
  3891. OID_TAPI_GET_CALL_INFO, // opcode
  3892. pCall->dwDeviceID, // device id
  3893. sizeof(NDIS_TAPI_GET_CALL_INFO) + // size of req data
  3894. (lpCallInfo->dwTotalSize - sizeof(LINE_CALL_INFO)),
  3895. &pNdisTapiRequest // ptr to ptr to req buf
  3896. )) != TAPI_SUCCESS)
  3897. {
  3898. ReleaseObjReadLock((HANDLE)hdCall);
  3899. return lRes;
  3900. }
  3901. pNdisTapiGetCallInfo = (PNDIS_TAPI_GET_CALL_INFO)pNdisTapiRequest->Data;
  3902. pNdisTapiGetCallInfo->hdCall = GetNdisTapiHandle(pCall, &lRes);
  3903. if(lRes != TAPI_SUCCESS)
  3904. {
  3905. FreeRequest(pNdisTapiRequest);
  3906. return lRes;
  3907. }
  3908. pInfo = &pNdisTapiGetCallInfo->LineCallInfo;
  3909. pInfo->ulTotalSize = lpCallInfo->dwTotalSize;
  3910. pInfo->ulNeededSize = pInfo->ulUsedSize = sizeof(LINE_CALL_INFO);
  3911. ZeroMemory(&pInfo->hLine, sizeof(LINE_CALL_INFO) - 3 * sizeof(ULONG));
  3912. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  3913. if (lRes != TAPI_SUCCESS)
  3914. {
  3915. FreeRequest(pNdisTapiRequest);
  3916. ReleaseObjReadLock((HANDLE)hdCall);
  3917. return lRes;
  3918. }
  3919. //
  3920. // Do some post processing to the returned data structure
  3921. // before passing it back to tapi:
  3922. // 1. Pad the area between the fixed 1.0 structure and the
  3923. // var data that the miniports pass back with 0's so a
  3924. // bad app that disregards the 1.0 version negotiation &
  3925. // references new 1.4 or 2.0 structure fields won't blow up
  3926. // 2. Convert ascii strings to unicode, & rebase all var data
  3927. //
  3928. //
  3929. // The real needed size is the sum of that requested by the
  3930. // underlying driver, plus padding for the new TAPI 1.4/2.0
  3931. // structure fields, plus the size of the var data returned
  3932. // by the driver to account for the ascii->unicode conversion.
  3933. // @@@ Granted, we are very liberal in computing the value for
  3934. // this last part, but at least this way it's fast & we'll
  3935. // never have too little buffer space.
  3936. //
  3937. lpCallInfo->dwNeededSize =
  3938. pInfo->ulNeededSize +
  3939. (sizeof(LINECALLINFO) - // v2.0 struct
  3940. sizeof(LINE_CALL_INFO)) + // v1.0 struct
  3941. (pInfo->ulNeededSize - sizeof(LINE_CALL_INFO));
  3942. //
  3943. // Copy over the fixed fields that don't need changing,
  3944. // i.e. everything from dwLineDeviceID to dwTrunk
  3945. //
  3946. CopyMemory(
  3947. &lpCallInfo->dwLineDeviceID,
  3948. &pInfo->ulLineDeviceID,
  3949. 23 * sizeof(DWORD)
  3950. );
  3951. if (lpCallInfo->dwNeededSize > lpCallInfo->dwTotalSize)
  3952. {
  3953. lpCallInfo->dwUsedSize =
  3954. (lpCallInfo->dwTotalSize < sizeof(LINECALLINFO) ?
  3955. lpCallInfo->dwTotalSize : sizeof(LINECALLINFO));
  3956. }
  3957. else
  3958. {
  3959. PWSTR pwszCalledAddress;
  3960. DWORD dwAlteredMediaModes;
  3961. lpCallInfo->dwUsedSize = sizeof(LINECALLINFO); // v2.0 struct
  3962. lpCallInfo->dwCallerIDFlags = pInfo->ulCallerIDFlags;
  3963. INSERTVARDATA(
  3964. pInfo,
  3965. &pInfo->ulCallerIDSize,
  3966. lpCallInfo,
  3967. &lpCallInfo->dwCallerIDSize,
  3968. sizeof(LINE_CALL_INFO),
  3969. "LINE_CALL_INFO.CallerID"
  3970. );
  3971. lpCallInfo->dwCallerIDAddressType = pInfo->ulCallerIDAddressType;
  3972. INSERTVARDATA(
  3973. pInfo,
  3974. &pInfo->ulCallerIDNameSize,
  3975. lpCallInfo,
  3976. &lpCallInfo->dwCallerIDNameSize,
  3977. sizeof(LINE_CALL_INFO),
  3978. "LINE_CALL_INFO.CallerIDName"
  3979. );
  3980. lpCallInfo->dwCalledIDFlags = pInfo->ulCalledIDFlags;
  3981. INSERTVARDATA(
  3982. pInfo,
  3983. &pInfo->ulCalledIDSize,
  3984. lpCallInfo,
  3985. &lpCallInfo->dwCalledIDSize,
  3986. sizeof(LINE_CALL_INFO),
  3987. "LINE_CALL_INFO.CalledID"
  3988. );
  3989. lpCallInfo->dwCalledIDAddressType = pInfo->ulCalledIDAddressType;
  3990. INSERTVARDATA(
  3991. pInfo,
  3992. &pInfo->ulCalledIDNameSize,
  3993. lpCallInfo,
  3994. &lpCallInfo->dwCalledIDNameSize,
  3995. sizeof(LINE_CALL_INFO),
  3996. "LINE_CALL_INFO.CalledIDName"
  3997. );
  3998. lpCallInfo->dwConnectedIDFlags = pInfo->ulConnectedIDFlags;
  3999. INSERTVARDATA(
  4000. pInfo,
  4001. &pInfo->ulConnectedIDSize,
  4002. lpCallInfo,
  4003. &lpCallInfo->dwConnectedIDSize,
  4004. sizeof(LINE_CALL_INFO),
  4005. "LINE_CALL_INFO.ConnectID"
  4006. );
  4007. lpCallInfo->dwConnectedIDAddressType = pInfo->ulConnectedIDAddressType;
  4008. INSERTVARDATA(
  4009. pInfo,
  4010. &pInfo->ulConnectedIDNameSize,
  4011. lpCallInfo,
  4012. &lpCallInfo->dwConnectedIDNameSize,
  4013. sizeof(LINE_CALL_INFO),
  4014. "LINE_CALL_INFO.ConnectIDName"
  4015. );
  4016. lpCallInfo->dwRedirectionIDFlags = pInfo->ulRedirectionIDFlags;
  4017. INSERTVARDATA(
  4018. pInfo,
  4019. &pInfo->ulRedirectionIDSize,
  4020. lpCallInfo,
  4021. &lpCallInfo->dwRedirectionIDSize,
  4022. sizeof(LINE_CALL_INFO),
  4023. "LINE_CALL_INFO.RedirectionID"
  4024. );
  4025. lpCallInfo->dwRedirectionIDAddressType =
  4026. pInfo->ulRedirectionIDAddressType;
  4027. INSERTVARDATA(
  4028. pInfo,
  4029. &pInfo->ulRedirectionIDNameSize,
  4030. lpCallInfo,
  4031. &lpCallInfo->dwRedirectionIDNameSize,
  4032. sizeof(LINE_CALL_INFO),
  4033. "LINE_CALL_INFO.RedirectionIDName"
  4034. );
  4035. lpCallInfo->dwRedirectingIDFlags = pInfo->ulRedirectingIDFlags;
  4036. INSERTVARDATA(
  4037. pInfo,
  4038. &pInfo->ulRedirectingIDSize,
  4039. lpCallInfo,
  4040. &lpCallInfo->dwRedirectingIDSize,
  4041. sizeof(LINE_CALL_INFO),
  4042. "LINE_CALL_INFO.RedirectingID"
  4043. );
  4044. lpCallInfo->dwRedirectingIDAddressType =
  4045. pInfo->ulRedirectingIDAddressType;
  4046. INSERTVARDATA(
  4047. pInfo,
  4048. &pInfo->ulRedirectingIDNameSize,
  4049. lpCallInfo,
  4050. &lpCallInfo->dwRedirectingIDNameSize,
  4051. sizeof(LINE_CALL_INFO),
  4052. "LINE_CALL_INFO.RedirectingIDName"
  4053. );
  4054. INSERTVARDATA(
  4055. pInfo,
  4056. &pInfo->ulDisplaySize,
  4057. lpCallInfo,
  4058. &lpCallInfo->dwDisplaySize,
  4059. sizeof(LINE_CALL_INFO),
  4060. "LINE_CALL_INFO.Display"
  4061. );
  4062. INSERTVARDATA(
  4063. pInfo,
  4064. &pInfo->ulUserUserInfoSize,
  4065. lpCallInfo,
  4066. &lpCallInfo->dwUserUserInfoSize,
  4067. sizeof(LINE_CALL_INFO),
  4068. "LINE_CALL_INFO.UserUserInfo"
  4069. );
  4070. INSERTVARDATA(
  4071. pInfo,
  4072. &pInfo->ulHighLevelCompSize,
  4073. lpCallInfo,
  4074. &lpCallInfo->dwHighLevelCompSize,
  4075. sizeof(LINE_CALL_INFO),
  4076. "LINE_CALL_INFO.HighLevelComp"
  4077. );
  4078. INSERTVARDATA(
  4079. pInfo,
  4080. &pInfo->ulLowLevelCompSize,
  4081. lpCallInfo,
  4082. &lpCallInfo->dwLowLevelCompSize,
  4083. sizeof(LINE_CALL_INFO),
  4084. "LINE_CALL_INFO.LowLevelComp"
  4085. );
  4086. INSERTVARDATA(
  4087. pInfo,
  4088. &pInfo->ulChargingInfoSize,
  4089. lpCallInfo,
  4090. &lpCallInfo->dwChargingInfoSize,
  4091. sizeof(LINE_CALL_INFO),
  4092. "LINE_CALL_INFO.ChargingInfo"
  4093. );
  4094. INSERTVARDATA(
  4095. pInfo,
  4096. &pInfo->ulTerminalModesSize,
  4097. lpCallInfo,
  4098. &lpCallInfo->dwTerminalModesSize,
  4099. sizeof(LINE_CALL_INFO),
  4100. "LINE_CALL_INFO.TerminalModes"
  4101. );
  4102. INSERTVARDATA(
  4103. pInfo,
  4104. &pInfo->ulDevSpecificSize,
  4105. lpCallInfo,
  4106. &lpCallInfo->dwDevSpecificSize,
  4107. sizeof(LINE_CALL_INFO),
  4108. "LINE_CALL_INFO.DevSpecific"
  4109. );
  4110. // make sure that dwNeededSize == dwUsedSize
  4111. lpCallInfo->dwNeededSize = lpCallInfo->dwUsedSize;
  4112. //
  4113. // we now have the called address, look up the
  4114. // proper associated media mode in TAPI's table
  4115. //
  4116. if (lpCallInfo->dwCalledIDFlags & LINECALLPARTYID_UNAVAIL)
  4117. {
  4118. TspLog(DL_INFO,
  4119. "lineGetCallInfo: dwCalledIDFlags contained "\
  4120. "LINECALLPARTYID_UNAVAIL");
  4121. goto get_call_info_end;
  4122. }
  4123. if (lpCallInfo->dwCalledIDSize == 0)
  4124. {
  4125. TspLog(DL_INFO, "lineGetCallInfo: dwCalledIDSize was 0");
  4126. goto get_call_info_end;
  4127. }
  4128. // we've got a called address that we need to look up.
  4129. // we have to copy it and make it null-terminated.
  4130. pwszCalledAddress = (PWSTR)MALLOC(lpCallInfo->dwCalledIDSize +
  4131. sizeof(UNICODE_NULL));
  4132. if (NULL == pwszCalledAddress)
  4133. {
  4134. TspLog(DL_ERROR,
  4135. "lineGetCallInfo: failed to alloc mem for called address");
  4136. lRes = LINEERR_NOMEM;
  4137. goto get_call_info_end;
  4138. }
  4139. CopyMemory((PUCHAR)pwszCalledAddress,
  4140. (((PUCHAR)lpCallInfo) + lpCallInfo->dwCalledIDOffset),
  4141. lpCallInfo->dwCalledIDSize);
  4142. *((PWSTR)(((PUCHAR)pwszCalledAddress) + lpCallInfo->dwCalledIDSize))
  4143. = UNICODE_NULL;
  4144. lRes = GetMediaModeForAddress(pwszCalledAddress,
  4145. &dwAlteredMediaModes);
  4146. FREE(pwszCalledAddress);
  4147. pwszCalledAddress = NULL;
  4148. if (lRes != TAPI_SUCCESS)
  4149. {
  4150. goto get_call_info_end;
  4151. }
  4152. if (dwAlteredMediaModes == LINEMEDIAMODE_UNKNOWN)
  4153. {
  4154. TspLog(DL_INFO, "lineGetCallInfo: got unknown media mode");
  4155. goto get_call_info_end;
  4156. }
  4157. TspLog(DL_INFO, "lineGetCallInfo: got media mode(%x)",
  4158. dwAlteredMediaModes);
  4159. lpCallInfo->dwMediaMode = dwAlteredMediaModes;
  4160. }
  4161. get_call_info_end:
  4162. FreeRequest(pNdisTapiRequest);
  4163. ReleaseObjReadLock((HANDLE)hdCall);
  4164. return lRes;
  4165. }
  4166. LONG
  4167. TSPIAPI
  4168. TSPI_lineGetCallStatus(
  4169. HDRVCALL hdCall,
  4170. LPLINECALLSTATUS lpCallStatus
  4171. )
  4172. {
  4173. static DWORD dwSum = 0;
  4174. LONG lRes;
  4175. PDRVCALL pCall;
  4176. PNDISTAPI_REQUEST pNdisTapiRequest;
  4177. PLINE_CALL_STATUS pStatus;
  4178. PNDIS_TAPI_GET_CALL_STATUS pNdisTapiGetCallStatus;
  4179. TspLog(DL_TRACE, "lineGetCallStatus(%d): call(%p)", ++dwSum, hdCall);
  4180. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  4181. if (lRes != TAPI_SUCCESS)
  4182. {
  4183. return lRes;
  4184. }
  4185. if ((lRes = PrepareSyncRequest(
  4186. OID_TAPI_GET_CALL_STATUS, // opcode
  4187. pCall->dwDeviceID, // device id
  4188. sizeof(NDIS_TAPI_GET_CALL_STATUS) + // size of req data
  4189. (lpCallStatus->dwTotalSize - sizeof(LINE_CALL_STATUS)),
  4190. &pNdisTapiRequest // ptr to ptr to req buf
  4191. )) != TAPI_SUCCESS)
  4192. {
  4193. ReleaseObjReadLock((HANDLE)hdCall);
  4194. return lRes;
  4195. }
  4196. pNdisTapiGetCallStatus = (PNDIS_TAPI_GET_CALL_STATUS)pNdisTapiRequest->Data;
  4197. pNdisTapiGetCallStatus->hdCall = GetNdisTapiHandle(pCall, &lRes);
  4198. if(lRes != TAPI_SUCCESS)
  4199. {
  4200. FreeRequest(pNdisTapiRequest);
  4201. return lRes;
  4202. }
  4203. pStatus = &pNdisTapiGetCallStatus->LineCallStatus;
  4204. pStatus->ulTotalSize = lpCallStatus->dwTotalSize;
  4205. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_CALL_STATUS);
  4206. ZeroMemory(&pStatus->ulCallState,
  4207. sizeof(LINE_CALL_STATUS) - 3 * sizeof(ULONG));
  4208. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4209. if (lRes != TAPI_SUCCESS)
  4210. {
  4211. FreeRequest(pNdisTapiRequest);
  4212. ReleaseObjReadLock((HANDLE)hdCall);
  4213. return lRes;
  4214. }
  4215. //
  4216. // Do some post processing to the returned data structure
  4217. // before passing it back to tapi:
  4218. // 1. Pad the area between the fixed 1.0 structure and the
  4219. // var data that the miniports pass back with 0's so a
  4220. // bad app that disregards the 1.0 version negotiation &
  4221. // references new 1.4 or 2.0 structure fields won't blow up
  4222. // (no embedded ascii strings to convert to unicode)
  4223. //
  4224. //
  4225. // The real needed size is the sum of that requested by the
  4226. // underlying driver, plus padding for the new TAPI 1.4/2.0
  4227. // structure fields. (There are no embedded ascii strings to
  4228. // convert to unicode, so no extra space needed for that.)
  4229. //
  4230. lpCallStatus->dwNeededSize =
  4231. pStatus->ulNeededSize +
  4232. (sizeof(LINECALLSTATUS) - // v2.0 struct
  4233. sizeof(LINE_CALL_STATUS)); // v1.0 struct
  4234. //
  4235. // Copy over the fixed fields that don't need changing,
  4236. // i.e. everything from dwLineDeviceID to dwCallCompletionModes
  4237. //
  4238. CopyMemory(
  4239. &lpCallStatus->dwCallState,
  4240. &pStatus->ulCallState,
  4241. 4 * sizeof(DWORD)
  4242. );
  4243. if (lpCallStatus->dwNeededSize > lpCallStatus->dwTotalSize)
  4244. {
  4245. lpCallStatus->dwUsedSize =
  4246. (lpCallStatus->dwTotalSize < sizeof(LINECALLSTATUS) ?
  4247. lpCallStatus->dwTotalSize : sizeof(LINECALLSTATUS));
  4248. }
  4249. else
  4250. {
  4251. lpCallStatus->dwUsedSize = sizeof(LINECALLSTATUS);
  4252. // v2.0 struct
  4253. INSERTVARDATA(
  4254. pStatus,
  4255. &pStatus->ulDevSpecificSize,
  4256. lpCallStatus,
  4257. &lpCallStatus->dwDevSpecificSize,
  4258. sizeof(LINE_CALL_STATUS),
  4259. "LINE_CALL_STATUS.DevSpecific"
  4260. );
  4261. }
  4262. FreeRequest(pNdisTapiRequest);
  4263. ReleaseObjReadLock((HANDLE)hdCall);
  4264. return lRes;
  4265. }
  4266. LINEDEVCAPS *
  4267. GetLineDevCaps(
  4268. IN DWORD dwDeviceID,
  4269. IN DWORD dwExtVersion
  4270. )
  4271. {
  4272. LONG lRes;
  4273. PNDISTAPI_REQUEST pNdisTapiRequest;
  4274. PLINE_DEV_CAPS pCaps;
  4275. PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps;
  4276. DWORD dwNeededSize;
  4277. LINEDEVCAPS *pLineDevCaps;
  4278. DWORD dwTotalSize = sizeof(LINEDEVCAPS) + 0x80;
  4279. get_caps:
  4280. pLineDevCaps = (LINEDEVCAPS *)MALLOC(dwTotalSize);
  4281. if (NULL == pLineDevCaps)
  4282. {
  4283. TspLog(DL_ERROR, "GetLineDevCaps: failed to alloc mem of size(%x)",
  4284. dwTotalSize);
  4285. return NULL;
  4286. }
  4287. pLineDevCaps->dwTotalSize = dwTotalSize;
  4288. if ((lRes = PrepareSyncRequest(
  4289. OID_TAPI_GET_DEV_CAPS, // opcode
  4290. dwDeviceID, // device id
  4291. sizeof(NDIS_TAPI_GET_DEV_CAPS) + // size of req data
  4292. (dwTotalSize - sizeof(LINE_DEV_CAPS)),
  4293. &pNdisTapiRequest // ptr to ptr to req buf
  4294. )) != TAPI_SUCCESS)
  4295. {
  4296. return NULL;
  4297. }
  4298. pNdisTapiGetDevCaps = (PNDIS_TAPI_GET_DEV_CAPS)pNdisTapiRequest->Data;
  4299. pNdisTapiGetDevCaps->ulDeviceID = dwDeviceID;
  4300. pNdisTapiGetDevCaps->ulExtVersion = dwExtVersion;
  4301. pCaps = &pNdisTapiGetDevCaps->LineDevCaps;
  4302. pCaps->ulTotalSize = dwTotalSize;
  4303. pCaps->ulNeededSize = pCaps->ulUsedSize = sizeof(LINE_DEV_CAPS);
  4304. ZeroMemory(&pCaps->ulProviderInfoSize,
  4305. sizeof(LINE_DEV_CAPS) - 3 * sizeof(ULONG));
  4306. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4307. if (lRes != TAPI_SUCCESS)
  4308. {
  4309. FreeRequest(pNdisTapiRequest);
  4310. return NULL;
  4311. }
  4312. //
  4313. // The real needed size is the sum of that requested by the
  4314. // underlying driver, plus padding for the new TAPI 1.4/2.0
  4315. // structure fields, plus the size of the var data returned
  4316. // by the driver to account for the ascii->unicode conversion.
  4317. // @@@ Granted, we are very liberal in computing the value for
  4318. // this last part, but at least this way it's fast & we'll
  4319. // never have too little buffer space.
  4320. //
  4321. TspLog(DL_TRACE,
  4322. "GetLineDevCaps: ulNeeded(%x), LINEDEVCAPS(%x), LINE_DEV_CAPS(%x)",
  4323. pCaps->ulNeededSize, sizeof(LINEDEVCAPS), sizeof(LINE_DEV_CAPS));
  4324. dwNeededSize =
  4325. pCaps->ulNeededSize +
  4326. (sizeof(LINEDEVCAPS) - // v2.0 struct
  4327. sizeof(LINE_DEV_CAPS)) + // v1.0 struct
  4328. (pCaps->ulNeededSize - sizeof(LINE_DEV_CAPS));
  4329. TspLog(DL_TRACE, "GetLineDevCaps: dwNeededSize(%x), dwTotalSize(%x)",
  4330. dwNeededSize, dwTotalSize);
  4331. if (dwNeededSize > dwTotalSize)
  4332. {
  4333. // free up the old req
  4334. FreeRequest(pNdisTapiRequest);
  4335. // free the old buffer
  4336. FREE(pLineDevCaps);
  4337. // try again with a larger buffer
  4338. dwTotalSize = dwNeededSize;
  4339. goto get_caps;
  4340. }
  4341. ASSERT(dwNeededSize <= dwTotalSize);
  4342. //
  4343. // Copy over the fixed fields that don't need changing,
  4344. // i.e. everything from dwPermanentLineID to dwNumTerminals
  4345. //
  4346. CopyMemory(
  4347. &pLineDevCaps->dwPermanentLineID,
  4348. &pCaps->ulPermanentLineID,
  4349. sizeof(LINE_DEV_CAPS) - (7 * sizeof(DWORD))
  4350. );
  4351. // @@@ not sure if this is the right place to do this
  4352. pLineDevCaps->dwDevCapFlags |= LINEDEVCAPFLAGS_MSP;
  4353. // set the local flag to indicate that
  4354. // the line can't be used from remote machine
  4355. pLineDevCaps->dwDevCapFlags |= LINEDEVCAPFLAGS_LOCAL;
  4356. //
  4357. // Do some post processing to the returned data structure
  4358. // before passing it back to tapi:
  4359. // 1. Pad the area between the fixed 1.0 structure and the
  4360. // var data that the miniports pass back with 0's so a
  4361. // bad app that disregards the 1.0 version negotiation &
  4362. // references new 1.4 or 2.0 structure fields won't blow up
  4363. // 2. Convert ascii strings to unicode, & rebase all var data
  4364. //
  4365. pLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS); // v2.0 struct
  4366. INSERTVARDATA(
  4367. pCaps,
  4368. &pCaps->ulDeviceClassesSize,
  4369. pLineDevCaps,
  4370. &pLineDevCaps->dwDeviceClassesSize,
  4371. sizeof (LINE_DEV_CAPS),
  4372. "LINE_DEV_CAPS.DeviceClasses"
  4373. );
  4374. INSERTVARDATA(
  4375. pCaps,
  4376. &pCaps->ulProviderInfoSize,
  4377. pLineDevCaps,
  4378. &pLineDevCaps->dwProviderInfoSize,
  4379. sizeof(LINE_DEV_CAPS),
  4380. "LINE_DEV_CAPS.ProviderInfo"
  4381. );
  4382. INSERTVARDATA(
  4383. pCaps,
  4384. &pCaps->ulSwitchInfoSize,
  4385. pLineDevCaps,
  4386. &pLineDevCaps->dwSwitchInfoSize,
  4387. sizeof(LINE_DEV_CAPS),
  4388. "LINE_DEV_CAPS.SwitchInfo"
  4389. );
  4390. INSERTVARDATA(
  4391. pCaps,
  4392. &pCaps->ulLineNameSize,
  4393. pLineDevCaps,
  4394. &pLineDevCaps->dwLineNameSize,
  4395. sizeof(LINE_DEV_CAPS),
  4396. "LINE_DEV_CAPS.LineName"
  4397. );
  4398. INSERTVARDATA(
  4399. pCaps,
  4400. &pCaps->ulTerminalCapsSize,
  4401. pLineDevCaps,
  4402. &pLineDevCaps->dwTerminalCapsSize,
  4403. sizeof(LINE_DEV_CAPS),
  4404. "LINE_DEV_CAPS.TerminalCaps"
  4405. );
  4406. // @@@ convert DevCaps.TermText to unicode???
  4407. pLineDevCaps->dwTerminalTextEntrySize =
  4408. pCaps->ulTerminalTextEntrySize;
  4409. INSERTVARDATA(
  4410. pCaps,
  4411. &pCaps->ulTerminalTextSize,
  4412. pLineDevCaps,
  4413. &pLineDevCaps->dwTerminalTextSize,
  4414. sizeof(LINE_DEV_CAPS),
  4415. "LINE_DEV_CAPS.TerminalText"
  4416. );
  4417. INSERTVARDATA(
  4418. pCaps,
  4419. &pCaps->ulDevSpecificSize,
  4420. pLineDevCaps,
  4421. &pLineDevCaps->dwDevSpecificSize,
  4422. sizeof(LINE_DEV_CAPS),
  4423. "LINE_DEV_CAPS.DevSpecific"
  4424. );
  4425. // make sure dwNeededSize == dwUsedSize
  4426. pLineDevCaps->dwNeededSize = pLineDevCaps->dwUsedSize;
  4427. FreeRequest(pNdisTapiRequest);
  4428. return pLineDevCaps;
  4429. }
  4430. LONG
  4431. TSPIAPI
  4432. TSPI_lineGetDevCaps(
  4433. DWORD dwDeviceID,
  4434. DWORD dwTSPIVersion,
  4435. DWORD dwExtVersion,
  4436. LPLINEDEVCAPS lpLineDevCaps
  4437. )
  4438. {
  4439. static DWORD dwSum = 0;
  4440. LONG lRes;
  4441. TspLog(DL_TRACE, "lineGetDevCaps(%d): deviceID(%x), TSPIV(%x), ExtV(%x)",
  4442. ++dwSum, dwDeviceID, dwTSPIVersion, dwExtVersion);
  4443. lRes = GetDevCaps(dwDeviceID, dwTSPIVersion, dwExtVersion, lpLineDevCaps);
  4444. return lRes;
  4445. }
  4446. LONG
  4447. TSPIAPI
  4448. TSPI_lineGetDevConfig(
  4449. DWORD dwDeviceID,
  4450. LPVARSTRING lpDeviceConfig,
  4451. LPCWSTR lpszDeviceClass
  4452. )
  4453. {
  4454. static DWORD dwSum = 0;
  4455. LONG lRes;
  4456. DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
  4457. PNDISTAPI_REQUEST pNdisTapiRequest;
  4458. PVAR_STRING pConfig;
  4459. PNDIS_TAPI_GET_DEV_CONFIG pNdisTapiGetDevConfig;
  4460. TspLog(DL_TRACE, "lineGetDevConfig(%d): deviceID(%x)", ++dwSum, dwDeviceID);
  4461. if ((lRes = PrepareSyncRequest(
  4462. OID_TAPI_GET_DEV_CONFIG, // opcode
  4463. dwDeviceID, // device id
  4464. sizeof(NDIS_TAPI_GET_DEV_CONFIG) + // size of req data
  4465. (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING)) + dwLength,
  4466. &pNdisTapiRequest // ptr to ptr to req buf
  4467. )) != TAPI_SUCCESS)
  4468. {
  4469. return lRes;
  4470. }
  4471. pNdisTapiGetDevConfig = (PNDIS_TAPI_GET_DEV_CONFIG)pNdisTapiRequest->Data;
  4472. pNdisTapiGetDevConfig->ulDeviceID = dwDeviceID;
  4473. pNdisTapiGetDevConfig->ulDeviceClassSize = dwLength;
  4474. pNdisTapiGetDevConfig->ulDeviceClassOffset =
  4475. sizeof(NDIS_TAPI_GET_DEV_CONFIG) +
  4476. (lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING));
  4477. pConfig = &pNdisTapiGetDevConfig->DeviceConfig;
  4478. pConfig->ulTotalSize = lpDeviceConfig->dwTotalSize;
  4479. pConfig->ulNeededSize = pConfig->ulUsedSize = sizeof(VAR_STRING);
  4480. pConfig->ulStringFormat =
  4481. pConfig->ulStringSize =
  4482. pConfig->ulStringOffset = 0;
  4483. // NOTE: old miniports expect strings to be ascii
  4484. WideCharToMultiByte(CP_ACP, 0, lpszDeviceClass, -1,
  4485. (LPSTR) (((LPBYTE) pNdisTapiGetDevConfig) +
  4486. pNdisTapiGetDevConfig->ulDeviceClassOffset),
  4487. dwLength, NULL, NULL);
  4488. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4489. if (TAPI_SUCCESS == lRes)
  4490. {
  4491. CopyMemory(
  4492. lpDeviceConfig,
  4493. &pNdisTapiGetDevConfig->DeviceConfig,
  4494. pNdisTapiGetDevConfig->DeviceConfig.ulUsedSize
  4495. );
  4496. }
  4497. FreeRequest(pNdisTapiRequest);
  4498. return lRes;
  4499. }
  4500. LONG
  4501. TSPIAPI
  4502. TSPI_lineGetExtensionID(
  4503. DWORD dwDeviceID,
  4504. DWORD dwTSPIVersion,
  4505. LPLINEEXTENSIONID lpExtensionID
  4506. )
  4507. {
  4508. static DWORD dwSum = 0;
  4509. LONG lRes;
  4510. PNDISTAPI_REQUEST pNdisTapiRequest;
  4511. PNDIS_TAPI_GET_EXTENSION_ID pNdisTapiGetExtensionID;
  4512. TspLog(DL_TRACE, "lineGetExtensionID(%d): deviceID(%x), TSPIV(%x)",
  4513. ++dwSum, dwDeviceID, dwTSPIVersion);
  4514. if ((lRes = PrepareSyncRequest(
  4515. OID_TAPI_GET_EXTENSION_ID, // opcode
  4516. dwDeviceID, // device id
  4517. sizeof(NDIS_TAPI_GET_EXTENSION_ID), // size of req data
  4518. &pNdisTapiRequest // ptr to ptr to req buf
  4519. )) != TAPI_SUCCESS)
  4520. {
  4521. return lRes;
  4522. }
  4523. pNdisTapiGetExtensionID =
  4524. (PNDIS_TAPI_GET_EXTENSION_ID)pNdisTapiRequest->Data;
  4525. pNdisTapiGetExtensionID->ulDeviceID = dwDeviceID;
  4526. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4527. if (TAPI_SUCCESS == lRes)
  4528. {
  4529. CopyMemory(
  4530. lpExtensionID,
  4531. &pNdisTapiGetExtensionID->LineExtensionID,
  4532. sizeof(LINE_EXTENSION_ID)
  4533. );
  4534. }
  4535. else
  4536. {
  4537. //
  4538. // Rather than indicating a failure, we'll just zero out the
  4539. // ext id (implying driver doesn't support extensions) and
  4540. // return success to tapisrv so it'll complete the open ok
  4541. //
  4542. ZeroMemory(lpExtensionID, sizeof(LINE_EXTENSION_ID));
  4543. lRes = TAPI_SUCCESS;
  4544. }
  4545. FreeRequest(pNdisTapiRequest);
  4546. return lRes;
  4547. }
  4548. LONG
  4549. TSPIAPI
  4550. TSPI_lineGetID(
  4551. HDRVLINE hdLine,
  4552. DWORD dwAddressID,
  4553. HDRVCALL hdCall,
  4554. DWORD dwSelect,
  4555. LPVARSTRING lpDeviceID,
  4556. LPCWSTR lpszDeviceClass,
  4557. HANDLE hTargetProcess
  4558. )
  4559. {
  4560. static DWORD dwSum = 0;
  4561. LONG lRes;
  4562. PDRVLINE pLine = NULL;
  4563. PDRVCALL pCall = NULL;
  4564. PNDISTAPI_REQUEST pNdisTapiRequest;
  4565. DWORD dwLength = lstrlenW(lpszDeviceClass) + 1;
  4566. DWORD dwDeviceID;
  4567. PUCHAR pchDest;
  4568. PVAR_STRING pID;
  4569. PNDIS_TAPI_GET_ID pNdisTapiGetID;
  4570. TspLog(DL_TRACE,
  4571. "lineGetID(%d): line(%p), call(%p), addressID(%x), select(%x)",
  4572. ++dwSum, hdLine, hdCall, dwAddressID, dwSelect);
  4573. ASSERT(LINECALLSELECT_LINE == dwSelect ||
  4574. LINECALLSELECT_ADDRESS == dwSelect ||
  4575. LINECALLSELECT_CALL == dwSelect);
  4576. if (LINECALLSELECT_LINE == dwSelect ||
  4577. LINECALLSELECT_ADDRESS == dwSelect)
  4578. {
  4579. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  4580. if (lRes != TAPI_SUCCESS)
  4581. {
  4582. return lRes;
  4583. }
  4584. }
  4585. if (LINECALLSELECT_CALL == dwSelect)
  4586. {
  4587. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  4588. if (lRes != TAPI_SUCCESS)
  4589. {
  4590. return lRes;
  4591. }
  4592. }
  4593. //
  4594. // Ndptsp will field this specific call on behalf of the
  4595. // wan miniports. It returns the guid and media string
  4596. // of the adapter that this line lives on
  4597. //
  4598. if (LINECALLSELECT_LINE == dwSelect &&
  4599. !wcscmp(lpszDeviceClass, L"LineGuid"))
  4600. {
  4601. lpDeviceID->dwNeededSize =
  4602. sizeof(VARSTRING) + sizeof(GUID) +
  4603. sizeof(pLine->MediaType) + sizeof('\0');
  4604. if (lpDeviceID->dwTotalSize < lpDeviceID->dwNeededSize)
  4605. {
  4606. if (pCall != NULL)
  4607. {
  4608. ReleaseObjReadLock((HANDLE)hdCall);
  4609. }
  4610. if (pLine != NULL)
  4611. {
  4612. ReleaseObjReadLock((HANDLE)hdLine);
  4613. }
  4614. return LINEERR_STRUCTURETOOSMALL;
  4615. }
  4616. lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
  4617. lpDeviceID->dwStringFormat = STRINGFORMAT_ASCII;
  4618. pchDest = (PUCHAR)lpDeviceID + sizeof(*lpDeviceID);
  4619. lpDeviceID->dwStringOffset = (DWORD)(pchDest - (PUCHAR)lpDeviceID);
  4620. lpDeviceID->dwStringSize =
  4621. sizeof(GUID) + sizeof(pLine->MediaType) +sizeof('\0');
  4622. MoveMemory(
  4623. pchDest,
  4624. (PUCHAR)&pLine->Guid,
  4625. sizeof(pLine->Guid)
  4626. );
  4627. pchDest += sizeof(pLine->Guid);
  4628. MoveMemory(
  4629. pchDest,
  4630. &pLine->MediaType,
  4631. sizeof(pLine->MediaType)
  4632. );
  4633. pchDest += sizeof(pLine->MediaType);
  4634. *pchDest = '\0';
  4635. TspLog(DL_INFO, "lineGetID: obj(%p)", hdLine);
  4636. TspLog(
  4637. DL_INFO,
  4638. "Guid %4.4x-%2.2x-%2.2x-%1.1x%1.1x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x",
  4639. pLine->Guid.Data1, pLine->Guid.Data2,
  4640. pLine->Guid.Data3, pLine->Guid.Data4[0],
  4641. pLine->Guid.Data4[1], pLine->Guid.Data4[2],
  4642. pLine->Guid.Data4[3], pLine->Guid.Data4[4],
  4643. pLine->Guid.Data4[5], pLine->Guid.Data4[6],
  4644. pLine->Guid.Data4[7]
  4645. );
  4646. TspLog(DL_INFO, "MediaType: %d", pLine->MediaType);
  4647. if (pCall != NULL)
  4648. {
  4649. ReleaseObjReadLock((HANDLE)hdCall);
  4650. }
  4651. if (pLine != NULL)
  4652. {
  4653. ReleaseObjReadLock((HANDLE)hdLine);
  4654. }
  4655. return TAPI_SUCCESS;
  4656. }
  4657. else if (LINECALLSELECT_CALL == dwSelect)
  4658. {
  4659. lpDeviceID->dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
  4660. if (lpDeviceID->dwTotalSize < lpDeviceID->dwNeededSize)
  4661. {
  4662. if (pCall != NULL)
  4663. {
  4664. ReleaseObjReadLock((HANDLE)hdCall);
  4665. }
  4666. if (pLine != NULL)
  4667. {
  4668. ReleaseObjReadLock((HANDLE)hdLine);
  4669. }
  4670. return LINEERR_STRUCTURETOOSMALL;
  4671. }
  4672. }
  4673. else
  4674. {
  4675. if (pCall != NULL)
  4676. {
  4677. ReleaseObjReadLock((HANDLE)hdCall);
  4678. }
  4679. if (pLine != NULL)
  4680. {
  4681. ReleaseObjReadLock((HANDLE)hdLine);
  4682. }
  4683. return LINEERR_OPERATIONUNAVAIL;
  4684. }
  4685. dwDeviceID = (LINECALLSELECT_CALL == dwSelect) ?
  4686. pCall->dwDeviceID : pLine->dwDeviceID;
  4687. if ((lRes = PrepareSyncRequest(
  4688. OID_TAPI_GET_ID, // opcode
  4689. dwDeviceID, // device id
  4690. sizeof(NDIS_TAPI_GET_ID) + // size of req data
  4691. (lpDeviceID->dwTotalSize - sizeof(VAR_STRING)) + 2 * dwLength + 4,
  4692. // 4 for returned ID
  4693. &pNdisTapiRequest // ptr to ptr to req buf
  4694. )) != TAPI_SUCCESS)
  4695. {
  4696. if (pCall != NULL)
  4697. {
  4698. ReleaseObjReadLock((HANDLE)hdCall);
  4699. }
  4700. if (pLine != NULL)
  4701. {
  4702. ReleaseObjReadLock((HANDLE)hdLine);
  4703. }
  4704. return lRes;
  4705. }
  4706. pNdisTapiGetID = (PNDIS_TAPI_GET_ID)pNdisTapiRequest->Data;
  4707. if (LINECALLSELECT_LINE == dwSelect ||
  4708. LINECALLSELECT_ADDRESS == dwSelect)
  4709. {
  4710. pNdisTapiGetID->hdLine = pLine->hd_Line;
  4711. }
  4712. pNdisTapiGetID->ulAddressID = dwAddressID;
  4713. if (LINECALLSELECT_CALL == dwSelect)
  4714. {
  4715. pNdisTapiGetID->hdCall = GetNdisTapiHandle(pCall, &lRes);
  4716. if(lRes != TAPI_SUCCESS)
  4717. {
  4718. if(pLine != NULL)
  4719. {
  4720. ReleaseObjReadLock((HANDLE)hdLine);
  4721. }
  4722. return lRes;
  4723. }
  4724. }
  4725. pNdisTapiGetID->ulSelect = dwSelect;
  4726. pNdisTapiGetID->ulDeviceClassSize = dwLength;
  4727. pNdisTapiGetID->ulDeviceClassOffset = sizeof(NDIS_TAPI_GET_ID) +
  4728. (lpDeviceID->dwTotalSize - sizeof(VAR_STRING));
  4729. pID = &pNdisTapiGetID->DeviceID;
  4730. pID->ulTotalSize = lpDeviceID->dwTotalSize;
  4731. pID->ulNeededSize = pID->ulUsedSize = sizeof(VAR_STRING);
  4732. pID->ulStringFormat = pID->ulStringSize = pID->ulStringOffset = 0;
  4733. // we use wide strings in the proxy
  4734. wcsncpy ((LPWSTR)(((LPBYTE)pNdisTapiGetID) +
  4735. pNdisTapiGetID->ulDeviceClassOffset),
  4736. lpszDeviceClass,
  4737. dwLength);
  4738. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4739. if (TAPI_SUCCESS == lRes)
  4740. {
  4741. CopyMemory(
  4742. lpDeviceID,
  4743. &pNdisTapiGetID->DeviceID,
  4744. pNdisTapiGetID->DeviceID.ulUsedSize
  4745. );
  4746. }
  4747. FreeRequest(pNdisTapiRequest);
  4748. if (pCall != NULL)
  4749. {
  4750. ReleaseObjReadLock((HANDLE)hdCall);
  4751. }
  4752. if (pLine != NULL)
  4753. {
  4754. ReleaseObjReadLock((HANDLE)hdLine);
  4755. }
  4756. return lRes;
  4757. }
  4758. LONG
  4759. TSPIAPI
  4760. TSPI_lineGetLineDevStatus(
  4761. HDRVLINE hdLine,
  4762. LPLINEDEVSTATUS lpLineDevStatus
  4763. )
  4764. {
  4765. static DWORD dwSum = 0;
  4766. LONG lRes;
  4767. PDRVLINE pLine;
  4768. PNDISTAPI_REQUEST pNdisTapiRequest;
  4769. PLINE_DEV_STATUS pStatus;
  4770. PNDIS_TAPI_GET_LINE_DEV_STATUS pNdisTapiGetLineDevStatus;
  4771. TspLog(DL_TRACE, "lineGetLineDevStatus(%d): line(%p)", ++dwSum, hdLine);
  4772. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  4773. if (lRes != TAPI_SUCCESS)
  4774. {
  4775. return lRes;
  4776. }
  4777. if ((lRes = PrepareSyncRequest(
  4778. OID_TAPI_GET_LINE_DEV_STATUS, // opcode
  4779. pLine->dwDeviceID, // device id
  4780. sizeof(NDIS_TAPI_GET_LINE_DEV_STATUS) + // size of req data
  4781. (lpLineDevStatus->dwTotalSize - sizeof(LINE_DEV_STATUS)),
  4782. &pNdisTapiRequest // ptr to ptr to req buf
  4783. )) != TAPI_SUCCESS)
  4784. {
  4785. ReleaseObjReadLock((HANDLE)hdLine);
  4786. return lRes;
  4787. }
  4788. pNdisTapiGetLineDevStatus =
  4789. (PNDIS_TAPI_GET_LINE_DEV_STATUS)pNdisTapiRequest->Data;
  4790. pNdisTapiGetLineDevStatus->hdLine = pLine->hd_Line;
  4791. pStatus = &pNdisTapiGetLineDevStatus->LineDevStatus;
  4792. pStatus->ulTotalSize = lpLineDevStatus->dwTotalSize;
  4793. pStatus->ulNeededSize = pStatus->ulUsedSize = sizeof(LINE_DEV_STATUS);
  4794. ZeroMemory(&pStatus->ulNumOpens,
  4795. sizeof(LINE_DEV_STATUS) - 3 * sizeof(ULONG));
  4796. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  4797. if (lRes != TAPI_SUCCESS)
  4798. {
  4799. FreeRequest(pNdisTapiRequest);
  4800. ReleaseObjReadLock((HANDLE)hdLine);
  4801. return lRes;
  4802. }
  4803. //
  4804. // Do some post processing to the returned data structure
  4805. // before passing it back to tapi:
  4806. // 1. Pad the area between the fixed 1.0 structure and the
  4807. // var data that the miniports pass back with 0's so a
  4808. // bad app that disregards the 1.0 version negotiation &
  4809. // references new 1.4 or 2.0 structure fields won't blow up
  4810. // (no embedded ascii strings to convert to unicode)
  4811. //
  4812. //
  4813. // The real needed size is the sum of that requested by the
  4814. // underlying driver, plus padding for the new TAPI 1.4/2.0
  4815. // structure fields. (There are no embedded ascii strings to
  4816. // convert to unicode, so no extra space needed for that.)
  4817. //
  4818. lpLineDevStatus->dwNeededSize =
  4819. pStatus->ulNeededSize +
  4820. (sizeof(LINEDEVSTATUS) - // v2.0 struct
  4821. sizeof(LINE_DEV_STATUS)); // v1.0 struct
  4822. //
  4823. // Copy over the fixed fields that don't need changing,
  4824. // i.e. everything from dwNumActiveCalls to dwDevStatusFlags
  4825. //
  4826. CopyMemory(
  4827. &lpLineDevStatus->dwNumActiveCalls,
  4828. &pStatus->ulNumActiveCalls,
  4829. sizeof(LINE_DEV_STATUS) - (9 * sizeof(DWORD))
  4830. );
  4831. if (lpLineDevStatus->dwNeededSize > lpLineDevStatus->dwTotalSize)
  4832. {
  4833. lpLineDevStatus->dwUsedSize =
  4834. (lpLineDevStatus->dwTotalSize < sizeof(LINEDEVSTATUS) ?
  4835. lpLineDevStatus->dwTotalSize : sizeof(LINEDEVSTATUS));
  4836. }
  4837. else
  4838. {
  4839. lpLineDevStatus->dwUsedSize = sizeof(LINEDEVSTATUS);
  4840. // v2.0 struct
  4841. INSERTVARDATA(
  4842. pStatus,
  4843. &pStatus->ulTerminalModesSize,
  4844. lpLineDevStatus,
  4845. &lpLineDevStatus->dwTerminalModesSize,
  4846. sizeof(LINE_DEV_STATUS),
  4847. "LINE_DEV_STATUS.TerminalModes"
  4848. );
  4849. INSERTVARDATA(
  4850. pStatus,
  4851. &pStatus->ulDevSpecificSize,
  4852. lpLineDevStatus,
  4853. &lpLineDevStatus->dwDevSpecificSize,
  4854. sizeof(LINE_DEV_STATUS),
  4855. "LINE_DEV_STATUS.DevSpecific"
  4856. );
  4857. }
  4858. FreeRequest(pNdisTapiRequest);
  4859. ReleaseObjReadLock((HANDLE)hdLine);
  4860. return lRes;
  4861. }
  4862. LONG
  4863. TSPIAPI
  4864. TSPI_lineGetNumAddressIDs(
  4865. HDRVLINE hdLine,
  4866. LPDWORD lpdwNumAddressIDs
  4867. )
  4868. {
  4869. static DWORD dwSum = 0;
  4870. LONG lRes;
  4871. PDRVLINE pLine;
  4872. TspLog(DL_TRACE, "lineGetNumAddressIDs(%d): line(%p)", ++dwSum, hdLine);
  4873. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  4874. if (lRes != TAPI_SUCCESS)
  4875. {
  4876. return lRes;
  4877. }
  4878. lRes = GetNumAddressIDs(pLine->dwDeviceID, lpdwNumAddressIDs);
  4879. if (TAPI_SUCCESS == lRes)
  4880. {
  4881. TspLog(DL_INFO, "lineGetNumAddressIDs: numAddressIDs(%x)",
  4882. *lpdwNumAddressIDs);
  4883. }
  4884. ReleaseObjReadLock((HANDLE)hdLine);
  4885. return lRes;
  4886. }
  4887. LONG
  4888. PASCAL
  4889. TSPI_lineMakeCall_postProcess(
  4890. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper,
  4891. LONG lRes,
  4892. PDWORD_PTR callStateMsgParams
  4893. )
  4894. {
  4895. LONG lSuc;
  4896. HDRVLINE hdLine;
  4897. PDRVLINE pLine;
  4898. HDRVCALL hdCall;
  4899. PDRVCALL pCall;
  4900. TspLog(DL_TRACE, "lineMakeCall_post: lRes(%x)", lRes);
  4901. hdCall = (HDRVCALL)(pAsyncReqWrapper->dwRequestSpecific);
  4902. lSuc = GetLineHandleFromCallHandle(hdCall, &hdLine);
  4903. if (lSuc != TAPI_SUCCESS)
  4904. {
  4905. return lSuc;
  4906. }
  4907. lSuc = GetLineObjWithReadLock(hdLine, &pLine);
  4908. if (lSuc != TAPI_SUCCESS)
  4909. {
  4910. return lSuc;
  4911. }
  4912. lSuc = GetCallObjWithWriteLock(hdCall, &pCall);
  4913. if (lSuc != TAPI_SUCCESS)
  4914. {
  4915. ReleaseObjReadLock((HANDLE)hdLine);
  4916. return lSuc;
  4917. }
  4918. if (TAPI_SUCCESS == lRes)
  4919. {
  4920. PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
  4921. pAsyncReqWrapper->NdisTapiRequest.Data;
  4922. // check to see if a call state msg was received before we had
  4923. // the chance to process the completion notification, & if so
  4924. // fill in the msg params
  4925. if (pCall->dwPendingCallState)
  4926. {
  4927. callStateMsgParams[0] = (DWORD_PTR)pLine->htLine;
  4928. callStateMsgParams[1] = (DWORD_PTR)pCall->htCall;
  4929. callStateMsgParams[2] = pCall->dwPendingCallState;
  4930. callStateMsgParams[3] = pCall->dwPendingCallStateMode;
  4931. callStateMsgParams[4] = pCall->dwPendingMediaMode;
  4932. }
  4933. pCall->hd_Call = pNdisTapiMakeCall->hdCall;
  4934. pCall->bIncomplete = FALSE;
  4935. ReleaseObjWriteLock((HANDLE)hdCall);
  4936. ReleaseObjReadLock((HANDLE)hdLine);
  4937. }
  4938. else
  4939. {
  4940. pCall->dwKey = INVALID_KEY;
  4941. ReleaseObjWriteLock((HANDLE)hdCall);
  4942. ReleaseObjReadLock((HANDLE)hdLine);
  4943. CloseObjHandle((HANDLE)hdCall);
  4944. }
  4945. return lRes;
  4946. }
  4947. LONG
  4948. TSPIAPI
  4949. TSPI_lineMakeCall(
  4950. DRV_REQUESTID dwRequestID,
  4951. HDRVLINE hdLine,
  4952. HTAPICALL htCall,
  4953. LPHDRVCALL lphdCall,
  4954. LPCWSTR lpszDestAddress,
  4955. DWORD dwCountryCode,
  4956. LPLINECALLPARAMS const lpCallParams
  4957. )
  4958. {
  4959. static DWORD dwSum = 0;
  4960. LONG lRes;
  4961. PDRVLINE pLine;
  4962. PDRVCALL pCall;
  4963. HDRVCALL hdCall;
  4964. DWORD dwDALength, dwCPLength;
  4965. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  4966. PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall;
  4967. TspLog(DL_TRACE, "lineMakeCall(%d): reqID(%x), line(%p)",
  4968. ++dwSum, dwRequestID, hdLine);
  4969. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  4970. if (lRes != TAPI_SUCCESS)
  4971. {
  4972. return lRes;
  4973. }
  4974. // alloc & init a DRVCALL
  4975. if (!(pCall = AllocCallObj(sizeof(DRVCALL))))
  4976. {
  4977. TspLog(DL_ERROR, "lineMakeCall: failed to create call obj");
  4978. ReleaseObjReadLock((HANDLE)hdLine);
  4979. return LINEERR_NOMEM;
  4980. }
  4981. pCall->dwKey = OUTBOUND_CALL_KEY;
  4982. pCall->dwDeviceID = pLine->dwDeviceID;
  4983. pCall->htCall = htCall;
  4984. pCall->hdLine = hdLine;
  4985. pCall->bIncomplete = TRUE;
  4986. // init the request
  4987. dwDALength = (lpszDestAddress ? (lstrlenW (lpszDestAddress) + 1) : 0);
  4988. dwCPLength = (lpCallParams ?
  4989. (lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)) : 0);
  4990. if ((lRes = PrepareAsyncRequest(
  4991. OID_TAPI_MAKE_CALL, // opcode
  4992. pLine->dwDeviceID, // device id
  4993. dwRequestID, // request id
  4994. sizeof(NDIS_TAPI_MAKE_CALL) +
  4995. 2 * dwDALength + dwCPLength +
  4996. sizeof(PVOID), // size
  4997. &pAsyncReqWrapper // ptr to ptr to request buffer
  4998. )) != TAPI_SUCCESS)
  4999. {
  5000. FreeCallObj(pCall);
  5001. ReleaseObjReadLock((HANDLE)hdLine);
  5002. return lRes;
  5003. }
  5004. pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
  5005. pAsyncReqWrapper->NdisTapiRequest.Data;
  5006. // make sure releasing read lock before calling OpenObjHandle()
  5007. // to avoid deadlock on acquiring write lock for the global mapper
  5008. ReleaseObjReadLock((HANDLE)hdLine);
  5009. lRes = OpenObjHandle(pCall, FreeCallObj, (HANDLE *)&hdCall);
  5010. if (lRes != TAPI_SUCCESS)
  5011. {
  5012. TspLog(DL_ERROR,
  5013. "lineMakeCall: failed to map obj(%p) to handle",
  5014. pCall);
  5015. FreeRequest(pAsyncReqWrapper);
  5016. FreeCallObj(pCall);
  5017. return lRes;
  5018. }
  5019. // reacquire the read lock
  5020. lRes = AcquireObjReadLock((HANDLE)hdLine);
  5021. if (lRes != TAPI_SUCCESS)
  5022. {
  5023. TspLog(DL_ERROR,
  5024. "lineMakeCall: failed to reacquire read lock for obj(%p)",
  5025. hdLine);
  5026. FreeRequest(pAsyncReqWrapper);
  5027. CloseObjHandle((HANDLE)hdCall);
  5028. return lRes;
  5029. }
  5030. // save the TSP handle
  5031. pCall->hdCall = hdCall;
  5032. pNdisTapiMakeCall->hdLine = pLine->hd_Line;
  5033. pNdisTapiMakeCall->htCall = (HTAPI_CALL)hdCall;
  5034. pNdisTapiMakeCall->ulDestAddressSize = dwDALength;
  5035. if (lpszDestAddress)
  5036. {
  5037. UCHAR *pDest;
  5038. // end of pNdisTapiMakeCall
  5039. pDest = (UCHAR *)(pNdisTapiMakeCall + 1);
  5040. // add room for lpCallParams
  5041. (ULONG_PTR)pDest += dwCPLength;
  5042. // align
  5043. (ULONG_PTR)pDest += sizeof(PVOID);
  5044. (ULONG_PTR)pDest &= ~((ULONG_PTR)sizeof(PVOID) - 1);
  5045. pNdisTapiMakeCall->ulDestAddressOffset =
  5046. (ULONG)(pDest - (UCHAR*)pNdisTapiMakeCall);
  5047. // use wide strings in NDPROXY
  5048. wcsncpy ((LPWSTR)pDest, lpszDestAddress, dwDALength);
  5049. }
  5050. else
  5051. {
  5052. pNdisTapiMakeCall->ulDestAddressOffset = 0;
  5053. }
  5054. if (lpCallParams)
  5055. {
  5056. pNdisTapiMakeCall->bUseDefaultLineCallParams = FALSE;
  5057. CopyMemory(
  5058. &pNdisTapiMakeCall->LineCallParams,
  5059. lpCallParams,
  5060. lpCallParams->dwTotalSize
  5061. );
  5062. if (lpCallParams->dwOrigAddressSize != 0)
  5063. {
  5064. WideCharToMultiByte(
  5065. CP_ACP,
  5066. 0,
  5067. (LPCWSTR) (((LPBYTE) lpCallParams) +
  5068. lpCallParams->dwOrigAddressOffset),
  5069. lpCallParams->dwOrigAddressSize / sizeof(WCHAR),
  5070. (LPSTR) (((LPBYTE) &pNdisTapiMakeCall->LineCallParams) +
  5071. lpCallParams->dwOrigAddressOffset),
  5072. lpCallParams->dwOrigAddressSize,
  5073. NULL,
  5074. NULL
  5075. );
  5076. pNdisTapiMakeCall->LineCallParams.ulOrigAddressSize /= 2;
  5077. }
  5078. }
  5079. else
  5080. {
  5081. pNdisTapiMakeCall->bUseDefaultLineCallParams = TRUE;
  5082. }
  5083. pAsyncReqWrapper->dwRequestSpecific = (DWORD_PTR)hdCall;
  5084. pAsyncReqWrapper->pfnPostProcess = TSPI_lineMakeCall_postProcess;
  5085. *lphdCall = hdCall;
  5086. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pAsyncReqWrapper);
  5087. ReleaseObjReadLock((HANDLE)hdLine);
  5088. return lRes;
  5089. }
  5090. LONG
  5091. TSPIAPI
  5092. TSPI_lineMonitorDigits(
  5093. HDRVCALL hdCall,
  5094. DWORD dwDigitModes
  5095. )
  5096. {
  5097. static DWORD dwSum = 0;
  5098. LONG lRes;
  5099. PDRVCALL pCall;
  5100. PNDISTAPI_REQUEST pNdisTapiRequest;
  5101. PNDIS_TAPI_MONITOR_DIGITS pNdisTapiMonitorDigits;
  5102. TspLog(DL_TRACE, "lineMonitorDigits(%d): call(%p), DigitModes(%x)",
  5103. ++dwSum, hdCall, dwDigitModes);
  5104. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5105. if (lRes != TAPI_SUCCESS)
  5106. {
  5107. return lRes;
  5108. }
  5109. if ((lRes = PrepareSyncRequest(
  5110. OID_TAPI_MONITOR_DIGITS, // opcode
  5111. pCall->dwDeviceID, // device ID
  5112. sizeof(NDIS_TAPI_MONITOR_DIGITS), // size of req data
  5113. &pNdisTapiRequest // ptr to ptr to req buf
  5114. )) != TAPI_SUCCESS)
  5115. {
  5116. ReleaseObjReadLock((HANDLE)hdCall);
  5117. return lRes;
  5118. }
  5119. pNdisTapiMonitorDigits = (PNDIS_TAPI_MONITOR_DIGITS)pNdisTapiRequest->Data;
  5120. // set up the parameters in our structure.
  5121. pNdisTapiMonitorDigits->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5122. if(lRes != TAPI_SUCCESS)
  5123. {
  5124. FreeRequest(pNdisTapiRequest);
  5125. return lRes;
  5126. }
  5127. pNdisTapiMonitorDigits->ulDigitModes = dwDigitModes;
  5128. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  5129. FreeRequest(pNdisTapiRequest);
  5130. ReleaseObjReadLock((HANDLE)hdCall);
  5131. return lRes;
  5132. }
  5133. //
  5134. // Routine Description:
  5135. //
  5136. // Identifies the MSP to use for a particular line device. In our case,
  5137. // this is always the RCA MSP for all devices that support audio.
  5138. //
  5139. // Arguments:
  5140. // dwDeviceID - The line device whose MSP identifier is being requested
  5141. // pCLSID - Pointer to location at which to store the MSP CLSID
  5142. //
  5143. // Return value:
  5144. // For devices that support TAPIMEDIAMODE_AUDIO, returns NOERROR, otherwise
  5145. // LINEERR_OPERATIONUNAVAIL.
  5146. //
  5147. LONG
  5148. TSPIAPI
  5149. TSPI_lineMSPIdentify(
  5150. DWORD dwDeviceID,
  5151. GUID *pCLSID
  5152. )
  5153. {
  5154. static DWORD dwSum = 0;
  5155. LONG lRes;
  5156. LINEDEVCAPS DevCaps;
  5157. TspLog(DL_TRACE, "lineMSPIdentify(%d): deviceID(%x)", ++dwSum, dwDeviceID);
  5158. //
  5159. // ugly, but we have to do it. We need to get the dev caps so we can see
  5160. // if the line supports audio. If it does, then we return the CLSID of
  5161. // the RCA MSP, otherwise return a null GUID
  5162. // (@@@ check if a null guid is the right thing to return)
  5163. //
  5164. ZeroMemory(&DevCaps, sizeof(LINEDEVCAPS));
  5165. DevCaps.dwTotalSize = sizeof(LINEDEVCAPS);
  5166. if ((lRes = TSPI_lineGetDevCaps(dwDeviceID, 0, 0, &DevCaps))
  5167. == TAPI_SUCCESS) {
  5168. //
  5169. // NOTE: LINEMEDIAMODE_AUTOMATEDVOICE == TAPIMEDIAMODE_AUDIO
  5170. //
  5171. if (DevCaps.dwMediaModes & LINEMEDIAMODE_AUTOMATEDVOICE) {
  5172. //
  5173. // The RCA MSP handles all lines that support AUDIO,
  5174. // so send this there.
  5175. //
  5176. *pCLSID = CLSID_RCAMSP;
  5177. }
  5178. }
  5179. return lRes;
  5180. }
  5181. LONG
  5182. TSPIAPI
  5183. TSPI_lineNegotiateExtVersion(
  5184. DWORD dwDeviceID,
  5185. DWORD dwTSPIVersion,
  5186. DWORD dwLowVersion,
  5187. DWORD dwHighVersion,
  5188. LPDWORD lpdwExtVersion
  5189. )
  5190. {
  5191. static DWORD dwSum = 0;
  5192. LONG lRes;
  5193. PNDISTAPI_REQUEST pNdisTapiRequest;
  5194. PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion;
  5195. TspLog(DL_TRACE,
  5196. "lineNegotiateExtVersion(%d): deviceID(%x), TSPIV(%x), "\
  5197. "LowV(%x), HighV(%x)",
  5198. ++dwSum, dwDeviceID, dwTSPIVersion, dwLowVersion, dwHighVersion);
  5199. if ((lRes = PrepareSyncRequest(
  5200. OID_TAPI_NEGOTIATE_EXT_VERSION, // opcode
  5201. dwDeviceID, // device id
  5202. sizeof(NDIS_TAPI_NEGOTIATE_EXT_VERSION), // size of req data
  5203. &pNdisTapiRequest // ptr to ptr to req buf
  5204. )) != TAPI_SUCCESS)
  5205. {
  5206. return lRes;
  5207. }
  5208. pNdisTapiNegotiateExtVersion =
  5209. (PNDIS_TAPI_NEGOTIATE_EXT_VERSION)pNdisTapiRequest->Data;
  5210. pNdisTapiNegotiateExtVersion->ulDeviceID = dwDeviceID;
  5211. pNdisTapiNegotiateExtVersion->ulLowVersion = dwLowVersion;
  5212. pNdisTapiNegotiateExtVersion->ulHighVersion = dwHighVersion;
  5213. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  5214. if (TAPI_SUCCESS == lRes)
  5215. {
  5216. *lpdwExtVersion = pNdisTapiNegotiateExtVersion->ulExtVersion;
  5217. // save version for future verification
  5218. lRes = SetNegotiatedExtVersion(dwDeviceID, *lpdwExtVersion);
  5219. }
  5220. else
  5221. {
  5222. TspLog(DL_WARNING, "lineNegotiateExtVersion: syncRequest returned(%x)",
  5223. lRes);
  5224. }
  5225. FreeRequest(pNdisTapiRequest);
  5226. return lRes;
  5227. }
  5228. LONG
  5229. TSPIAPI
  5230. TSPI_lineNegotiateTSPIVersion(
  5231. DWORD dwDeviceID,
  5232. DWORD dwLowVersion,
  5233. DWORD dwHighVersion,
  5234. LPDWORD lpdwTSPIVersion
  5235. )
  5236. {
  5237. static DWORD dwSum = 0;
  5238. LONG lRes;
  5239. TspLog(DL_TRACE, "lineNegotiateTSPIVersion(%d): deviceID(%x)",
  5240. ++dwSum, dwDeviceID);
  5241. *lpdwTSPIVersion = 0x00030000;
  5242. // save version for future verification
  5243. lRes = SetNegotiatedTSPIVersion(dwDeviceID, 0x00030000);
  5244. if (TAPI_SUCCESS == lRes)
  5245. {
  5246. TspLog(DL_INFO, "lineNegotiateTSPIVersion: TSPIVersion(%x)",
  5247. *lpdwTSPIVersion);
  5248. }
  5249. return lRes;
  5250. }
  5251. LONG
  5252. TSPIAPI
  5253. TSPI_lineOpen(
  5254. DWORD dwDeviceID,
  5255. HTAPILINE htLine,
  5256. LPHDRVLINE lphdLine,
  5257. DWORD dwTSPIVersion,
  5258. LINEEVENT lpfnEventProc
  5259. )
  5260. {
  5261. static DWORD dwSum = 0;
  5262. LONG lRes;
  5263. PDRVLINE pLine;
  5264. HDRVLINE hdLine;
  5265. PNDISTAPI_REQUEST pNdisTapiRequest;
  5266. PNDIS_TAPI_OPEN pNdisTapiOpen;
  5267. GUID Guid;
  5268. NDIS_WAN_MEDIUM_SUBTYPE MediaType;
  5269. PNDISTAPI_OPENDATA OpenData;
  5270. TspLog(DL_TRACE, "lineOpen(%d): deviceID(%x), htLine(%p)",
  5271. ++dwSum, dwDeviceID, htLine);
  5272. // alloc & init a DRVLINE
  5273. if (!(pLine = AllocLineObj(sizeof(DRVLINE))))
  5274. {
  5275. TspLog(DL_ERROR, "lineOpen: failed to create line obj");
  5276. return LINEERR_NOMEM;
  5277. }
  5278. pLine->dwKey = LINE_KEY;
  5279. pLine->dwDeviceID = dwDeviceID;
  5280. pLine->htLine = htLine;
  5281. pLine->hMSPMutex = CreateMutex(NULL, FALSE, "MSPMutex");
  5282. if (NULL == pLine->hMSPMutex)
  5283. {
  5284. TspLog(DL_ERROR, "lineOpen: failed to create mutex");
  5285. FreeLineObj(pLine);
  5286. return LINEERR_NOMEM;
  5287. }
  5288. if ((lRes = PrepareSyncRequest(
  5289. OID_TAPI_OPEN, // opcode
  5290. dwDeviceID, // device id
  5291. sizeof(NDIS_TAPI_OPEN) +
  5292. sizeof(NDISTAPI_OPENDATA), // size
  5293. &pNdisTapiRequest // ptr to ptr to request buffer
  5294. )) != TAPI_SUCCESS)
  5295. {
  5296. CloseHandle(pLine->hMSPMutex);
  5297. FreeLineObj(pLine);
  5298. return lRes;
  5299. }
  5300. pNdisTapiOpen = (PNDIS_TAPI_OPEN)pNdisTapiRequest->Data;
  5301. pNdisTapiOpen->ulDeviceID = dwDeviceID;
  5302. lRes = OpenObjHandle(pLine, FreeLineObj, (HANDLE *)&hdLine);
  5303. if (lRes != TAPI_SUCCESS)
  5304. {
  5305. TspLog(DL_ERROR, "lineOpen: failed to map obj(%p) to handle", pLine);
  5306. CloseHandle(pLine->hMSPMutex);
  5307. FreeLineObj(pLine);
  5308. FreeRequest(pNdisTapiRequest);
  5309. return lRes;
  5310. }
  5311. pNdisTapiOpen->htLine = (HTAPI_LINE)hdLine;
  5312. lRes = SyncDriverRequest(IOCTL_NDISTAPI_QUERY_INFO, pNdisTapiRequest);
  5313. if (lRes != TAPI_SUCCESS)
  5314. {
  5315. CloseHandle(pLine->hMSPMutex);
  5316. CloseObjHandle((HANDLE)hdLine);
  5317. FreeRequest(pNdisTapiRequest);
  5318. return lRes;
  5319. }
  5320. OpenData = (PNDISTAPI_OPENDATA)
  5321. ((PUCHAR)pNdisTapiOpen + sizeof(NDIS_TAPI_OPEN));
  5322. MoveMemory(&pLine->Guid,&OpenData->Guid, sizeof(pLine->Guid));
  5323. pLine->MediaType = OpenData->MediaType;
  5324. TspLog(DL_INFO, "lineOpen: obj(%p)", hdLine);
  5325. TspLog(
  5326. DL_INFO,
  5327. "Guid: %4.4x-%4.4x-%2.2x%2.2x-%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x%1.1x",
  5328. pLine->Guid.Data1, pLine->Guid.Data2,
  5329. pLine->Guid.Data3, pLine->Guid.Data4[0],
  5330. pLine->Guid.Data4[1], pLine->Guid.Data4[2],
  5331. pLine->Guid.Data4[3], pLine->Guid.Data4[4],
  5332. pLine->Guid.Data4[5], pLine->Guid.Data4[6],
  5333. pLine->Guid.Data4[7]
  5334. );
  5335. TspLog(DL_INFO, "MediaType(%ld)", pLine->MediaType);
  5336. pLine->hd_Line = pNdisTapiOpen->hdLine;
  5337. *lphdLine = hdLine;
  5338. lRes = CommitNegotiatedTSPIVersion(dwDeviceID);
  5339. FreeRequest(pNdisTapiRequest);
  5340. return lRes;
  5341. }
  5342. //
  5343. // Routine Description:
  5344. //
  5345. // Called when an MSP wants to send us data. Right now we have not
  5346. // defined any TSP / MSP communication, so this function does nothing.
  5347. //
  5348. // Arguments:
  5349. // hdLine - Handle to line device
  5350. // hdCall - Handle for call
  5351. // hdMSPLine - MSP handle for the call
  5352. // pBuffer - Pointer to buffer containing MSP data
  5353. // dwSize - Size of MSP data buffer
  5354. //
  5355. // Return value:
  5356. // LINEERR_OPERATIONFAILED - if data size is too small
  5357. // LINEERR_OPERATIONUNAVAIL - if the message contains an unrecognized command
  5358. // NOERROR - if everything went OK
  5359. //
  5360. LONG
  5361. TSPIAPI
  5362. TSPI_lineReceiveMSPData(
  5363. HDRVLINE hdLine,
  5364. HDRVCALL hdCall,
  5365. HDRVMSPLINE hdMSPLine,
  5366. LPVOID pBuffer,
  5367. DWORD dwSize
  5368. )
  5369. {
  5370. static DWORD dwSum = 0;
  5371. LONG lRes;
  5372. PDRVLINE pLine;
  5373. DWORD dwMsg;
  5374. DWORD dwStatus;
  5375. TspLog(DL_TRACE, "lineReceiveMSPData(%d): line(%p), call(%p), MSPline(%p)",
  5376. ++dwSum, hdLine, hdCall, hdMSPLine);
  5377. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  5378. if (lRes != TAPI_SUCCESS)
  5379. {
  5380. return lRes;
  5381. }
  5382. if (dwSize < sizeof(DWORD))
  5383. {
  5384. TspLog(DL_ERROR,
  5385. "lineReceiveMSPData: data buf smaller than dword size");
  5386. ReleaseObjReadLock((HANDLE)hdLine);
  5387. return LINEERR_OPERATIONFAILED;
  5388. }
  5389. dwMsg = *((DWORD *)pBuffer);
  5390. if (dwMsg != 0)
  5391. {
  5392. TspLog(DL_ERROR, "lineReceiveMSPData: unrecognized msg(%x)", dwMsg);
  5393. ReleaseObjReadLock((HANDLE)hdLine);
  5394. return LINEERR_OPERATIONUNAVAIL;
  5395. }
  5396. //
  5397. // have to call StartMSPStream with the MSP mutex held
  5398. //
  5399. if ((dwStatus = WaitForSingleObject(pLine->hMSPMutex, INFINITE))
  5400. != WAIT_OBJECT_0)
  5401. {
  5402. TspLog(DL_ERROR, "lineReceiveMSPData: MSP mutex wait failed(%x)",
  5403. dwStatus);
  5404. ReleaseObjReadLock((HANDLE)hdLine);
  5405. return LINEERR_OPERATIONFAILED;
  5406. }
  5407. StartMSPStream(hdLine, hdCall);
  5408. if (!ReleaseMutex(pLine->hMSPMutex))
  5409. {
  5410. TspLog(DL_ERROR, "lineReceiveMSPData: MSP mutex release failed");
  5411. ReleaseObjReadLock((HANDLE)hdLine);
  5412. return LINEERR_OPERATIONFAILED;
  5413. }
  5414. ReleaseObjReadLock((HANDLE)hdLine);
  5415. return lRes;
  5416. }
  5417. LONG
  5418. TSPIAPI
  5419. TSPI_lineSecureCall(
  5420. DRV_REQUESTID dwRequestID,
  5421. HDRVCALL hdCall
  5422. )
  5423. {
  5424. static DWORD dwSum = 0;
  5425. LONG lRes;
  5426. PDRVCALL pCall;
  5427. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  5428. PNDIS_TAPI_SECURE_CALL pNdisTapiSecureCall;
  5429. TspLog(DL_TRACE, "lineSecureCall(%d): reqID(%x), call(%p)",
  5430. ++dwSum, dwRequestID, hdCall);
  5431. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5432. if (lRes != TAPI_SUCCESS)
  5433. {
  5434. return lRes;
  5435. }
  5436. if ((lRes = PrepareAsyncRequest(
  5437. OID_TAPI_SECURE_CALL, // opcode
  5438. pCall->dwDeviceID, // device id
  5439. dwRequestID, // req id
  5440. sizeof(NDIS_TAPI_SECURE_CALL), // size
  5441. &pAsyncReqWrapper // ptr to ptr to request buf
  5442. )) != TAPI_SUCCESS)
  5443. {
  5444. ReleaseObjReadLock((HANDLE)hdCall);
  5445. return lRes;
  5446. }
  5447. pNdisTapiSecureCall =
  5448. (PNDIS_TAPI_SECURE_CALL)pAsyncReqWrapper->NdisTapiRequest.Data;
  5449. pNdisTapiSecureCall->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5450. if(lRes != TAPI_SUCCESS)
  5451. {
  5452. FreeRequest(pAsyncReqWrapper);
  5453. return lRes;
  5454. }
  5455. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  5456. ReleaseObjReadLock((HANDLE)hdCall);
  5457. return lRes;
  5458. }
  5459. LONG
  5460. TSPIAPI
  5461. TSPI_lineSelectExtVersion(
  5462. HDRVLINE hdLine,
  5463. DWORD dwExtVersion
  5464. )
  5465. {
  5466. static DWORD dwSum = 0;
  5467. LONG lRes;
  5468. PDRVLINE pLine;
  5469. PNDISTAPI_REQUEST pNdisTapiRequest;
  5470. PNDIS_TAPI_SELECT_EXT_VERSION pNdisTapiSelectExtVersion;
  5471. TspLog(DL_TRACE, "lineSelectExtVersion(%d): line(%p), ExtV(%x)",
  5472. ++dwSum, hdLine, dwExtVersion);
  5473. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  5474. if (lRes != TAPI_SUCCESS)
  5475. {
  5476. return lRes;
  5477. }
  5478. if ((lRes = PrepareSyncRequest(
  5479. OID_TAPI_SELECT_EXT_VERSION, // opcode
  5480. pLine->dwDeviceID, // device id
  5481. sizeof(NDIS_TAPI_SELECT_EXT_VERSION), // size
  5482. &pNdisTapiRequest // ptr to ptr to req buf
  5483. )) != TAPI_SUCCESS)
  5484. {
  5485. ReleaseObjReadLock((HANDLE)hdLine);
  5486. return lRes;
  5487. }
  5488. pNdisTapiSelectExtVersion =
  5489. (PNDIS_TAPI_SELECT_EXT_VERSION)pNdisTapiRequest->Data;
  5490. pNdisTapiSelectExtVersion->hdLine = pLine->hd_Line;
  5491. pNdisTapiSelectExtVersion->ulExtVersion = dwExtVersion;
  5492. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5493. if (TAPI_SUCCESS == lRes)
  5494. {
  5495. lRes = SetSelectedExtVersion(pLine->dwDeviceID, dwExtVersion);
  5496. }
  5497. FreeRequest(pNdisTapiRequest);
  5498. ReleaseObjReadLock((HANDLE)hdLine);
  5499. return lRes;
  5500. }
  5501. LONG
  5502. TSPIAPI
  5503. TSPI_lineSendUserUserInfo(
  5504. DRV_REQUESTID dwRequestID,
  5505. HDRVCALL hdCall,
  5506. LPCSTR lpsUserUserInfo,
  5507. DWORD dwSize
  5508. )
  5509. {
  5510. static DWORD dwSum = 0;
  5511. LONG lRes;
  5512. PDRVCALL pCall;
  5513. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  5514. PNDIS_TAPI_SEND_USER_USER_INFO pNdisTapiSendUserUserInfo;
  5515. TspLog(DL_TRACE, "lineSendUserUserInfo(%d): reqID(%x), call(%p)",
  5516. ++dwSum, dwRequestID, hdCall);
  5517. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5518. if (lRes != TAPI_SUCCESS)
  5519. {
  5520. return lRes;
  5521. }
  5522. if ((lRes = PrepareAsyncRequest(
  5523. OID_TAPI_SEND_USER_USER_INFO, // opcode
  5524. pCall->dwDeviceID, // device id
  5525. dwRequestID, // request id
  5526. sizeof(NDIS_TAPI_SEND_USER_USER_INFO) + dwSize,
  5527. &pAsyncReqWrapper // ptr to ptr to req buf
  5528. )) != TAPI_SUCCESS)
  5529. {
  5530. ReleaseObjReadLock((HANDLE)hdCall);
  5531. return lRes;
  5532. }
  5533. pNdisTapiSendUserUserInfo = (PNDIS_TAPI_SEND_USER_USER_INFO)
  5534. pAsyncReqWrapper->NdisTapiRequest.Data;
  5535. pNdisTapiSendUserUserInfo->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5536. if(lRes != TAPI_SUCCESS)
  5537. {
  5538. FreeRequest(pAsyncReqWrapper);
  5539. return lRes;
  5540. }
  5541. if (pNdisTapiSendUserUserInfo->ulUserUserInfoSize = dwSize)
  5542. {
  5543. CopyMemory(
  5544. pNdisTapiSendUserUserInfo->UserUserInfo,
  5545. lpsUserUserInfo,
  5546. dwSize
  5547. );
  5548. }
  5549. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  5550. ReleaseObjReadLock((HANDLE)hdCall);
  5551. return lRes;
  5552. }
  5553. LONG
  5554. TSPIAPI
  5555. TSPI_lineSetAppSpecific(
  5556. HDRVCALL hdCall,
  5557. DWORD dwAppSpecific
  5558. )
  5559. {
  5560. static DWORD dwSum = 0;
  5561. LONG lRes;
  5562. PDRVCALL pCall;
  5563. PNDISTAPI_REQUEST pNdisTapiRequest;
  5564. PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific;
  5565. TspLog(DL_TRACE, "lineSetAppSpecific(%d): call(%p)", ++dwSum, hdCall);
  5566. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5567. if (lRes != TAPI_SUCCESS)
  5568. {
  5569. return lRes;
  5570. }
  5571. if ((lRes = PrepareSyncRequest(
  5572. OID_TAPI_SET_APP_SPECIFIC, // opcode
  5573. pCall->dwDeviceID, // device id
  5574. sizeof(NDIS_TAPI_SET_APP_SPECIFIC), // size
  5575. &pNdisTapiRequest // ptr to ptr to req buf
  5576. )) != TAPI_SUCCESS)
  5577. {
  5578. ReleaseObjReadLock((HANDLE)hdCall);
  5579. return lRes;
  5580. }
  5581. pNdisTapiSetAppSpecific =
  5582. (PNDIS_TAPI_SET_APP_SPECIFIC)pNdisTapiRequest->Data;
  5583. pNdisTapiSetAppSpecific->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5584. if(lRes != TAPI_SUCCESS)
  5585. {
  5586. FreeRequest(pNdisTapiRequest);
  5587. return lRes;
  5588. }
  5589. pNdisTapiSetAppSpecific->ulAppSpecific = dwAppSpecific;
  5590. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5591. FreeRequest(pNdisTapiRequest);
  5592. ReleaseObjReadLock((HANDLE)hdCall);
  5593. return lRes;
  5594. }
  5595. LONG
  5596. TSPIAPI
  5597. TSPI_lineSetCallParams(
  5598. DRV_REQUESTID dwRequestID,
  5599. HDRVCALL hdCall,
  5600. DWORD dwBearerMode,
  5601. DWORD dwMinRate,
  5602. DWORD dwMaxRate,
  5603. LPLINEDIALPARAMS const lpDialParams
  5604. )
  5605. {
  5606. static DWORD dwSum = 0;
  5607. LONG lRes;
  5608. PDRVCALL pCall;
  5609. PASYNC_REQUEST_WRAPPER pAsyncReqWrapper;
  5610. PNDIS_TAPI_SET_CALL_PARAMS pNdisTapiSetCallParams;
  5611. TspLog(DL_TRACE, "lineSetCallParams(%d): reqID(%x), call(%p)",
  5612. ++dwSum, dwRequestID, hdCall);
  5613. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5614. if (lRes != TAPI_SUCCESS)
  5615. {
  5616. return lRes;
  5617. }
  5618. if ((lRes = PrepareAsyncRequest(
  5619. OID_TAPI_SET_CALL_PARAMS, // opcode
  5620. pCall->dwDeviceID, // device id
  5621. dwRequestID, // request id
  5622. sizeof(NDIS_TAPI_SET_CALL_PARAMS), // size
  5623. &pAsyncReqWrapper // ptr to ptr to request buf
  5624. )) != TAPI_SUCCESS)
  5625. {
  5626. ReleaseObjReadLock((HANDLE)hdCall);
  5627. return lRes;
  5628. }
  5629. pNdisTapiSetCallParams =
  5630. (PNDIS_TAPI_SET_CALL_PARAMS)pAsyncReqWrapper->NdisTapiRequest.Data;
  5631. pNdisTapiSetCallParams->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5632. if(lRes != TAPI_SUCCESS)
  5633. {
  5634. FreeRequest(pAsyncReqWrapper);
  5635. return lRes;
  5636. }
  5637. pNdisTapiSetCallParams->ulBearerMode = dwBearerMode;
  5638. pNdisTapiSetCallParams->ulMinRate = dwMinRate;
  5639. pNdisTapiSetCallParams->ulMaxRate = dwMaxRate;
  5640. if (lpDialParams)
  5641. {
  5642. pNdisTapiSetCallParams->bSetLineDialParams = TRUE;
  5643. CopyMemory(
  5644. &pNdisTapiSetCallParams->LineDialParams,
  5645. lpDialParams,
  5646. sizeof(LINE_DIAL_PARAMS)
  5647. );
  5648. }
  5649. else
  5650. {
  5651. pNdisTapiSetCallParams->bSetLineDialParams = FALSE;
  5652. }
  5653. lRes = AsyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pAsyncReqWrapper);
  5654. ReleaseObjReadLock((HANDLE)hdCall);
  5655. return lRes;
  5656. }
  5657. LONG
  5658. TSPIAPI
  5659. TSPI_lineSetDefaultMediaDetection(
  5660. HDRVLINE hdLine,
  5661. DWORD dwMediaModes
  5662. )
  5663. {
  5664. static DWORD dwSum = 0;
  5665. LONG lRes;
  5666. PDRVLINE pLine;
  5667. PNDISTAPI_REQUEST pNdisTapiRequest;
  5668. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pNdisTapiSetDefaultMediaDetection;
  5669. TspLog(DL_TRACE, "lineSetDefaultMediaDetection(%d): line(%p), mode(%x)",
  5670. ++dwSum, hdLine, dwMediaModes);
  5671. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  5672. if (lRes != TAPI_SUCCESS)
  5673. {
  5674. return lRes;
  5675. }
  5676. if ((lRes = PrepareSyncRequest(
  5677. OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, // opcode
  5678. pLine->dwDeviceID, // device id
  5679. sizeof(NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION), // size
  5680. &pNdisTapiRequest // ptr to ptr to req buf
  5681. )) != TAPI_SUCCESS)
  5682. {
  5683. ReleaseObjReadLock((HANDLE)hdLine);
  5684. return lRes;
  5685. }
  5686. pNdisTapiSetDefaultMediaDetection =
  5687. (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) pNdisTapiRequest->Data;
  5688. pNdisTapiSetDefaultMediaDetection->hdLine = pLine->hd_Line;
  5689. pNdisTapiSetDefaultMediaDetection->ulMediaModes = dwMediaModes;
  5690. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5691. FreeRequest(pNdisTapiRequest);
  5692. ReleaseObjReadLock((HANDLE)hdLine);
  5693. return lRes;
  5694. }
  5695. LONG
  5696. TSPIAPI
  5697. TSPI_lineSetDevConfig(
  5698. DWORD dwDeviceID,
  5699. LPVOID const lpDeviceConfig,
  5700. DWORD dwSize,
  5701. LPCWSTR lpszDeviceClass
  5702. )
  5703. {
  5704. static DWORD dwSum = 0;
  5705. LONG lRes;
  5706. DWORD dwLength = lstrlenW(lpszDeviceClass) + 1;
  5707. PNDISTAPI_REQUEST pNdisTapiRequest;
  5708. PNDIS_TAPI_SET_DEV_CONFIG pNdisTapiSetDevConfig;
  5709. TspLog(DL_TRACE, "lineSetDevConfig(%d): deviceID(%x)", ++dwSum, dwDeviceID);
  5710. if ((lRes = PrepareSyncRequest(
  5711. OID_TAPI_SET_DEV_CONFIG, // opcode
  5712. dwDeviceID, // device id
  5713. sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwLength + dwSize,
  5714. &pNdisTapiRequest // ptr to ptr to req buf
  5715. )) != TAPI_SUCCESS)
  5716. {
  5717. return lRes;
  5718. }
  5719. pNdisTapiSetDevConfig = (PNDIS_TAPI_SET_DEV_CONFIG)pNdisTapiRequest->Data;
  5720. pNdisTapiSetDevConfig->ulDeviceID = dwDeviceID;
  5721. pNdisTapiSetDevConfig->ulDeviceClassSize = dwLength;
  5722. pNdisTapiSetDevConfig->ulDeviceClassOffset =
  5723. sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwSize - 1;
  5724. pNdisTapiSetDevConfig->ulDeviceConfigSize = dwSize;
  5725. CopyMemory(
  5726. pNdisTapiSetDevConfig->DeviceConfig,
  5727. lpDeviceConfig,
  5728. dwSize
  5729. );
  5730. // NOTE: old miniports expect strings to be ascii
  5731. WideCharToMultiByte(CP_ACP, 0, lpszDeviceClass, -1,
  5732. (LPSTR) (((LPBYTE) pNdisTapiSetDevConfig) +
  5733. pNdisTapiSetDevConfig->ulDeviceClassOffset),
  5734. dwLength, NULL, NULL);
  5735. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5736. FreeRequest(pNdisTapiRequest);
  5737. return lRes;
  5738. }
  5739. LONG
  5740. TSPIAPI
  5741. TSPI_lineSetMediaMode(
  5742. HDRVCALL hdCall,
  5743. DWORD dwMediaMode
  5744. )
  5745. {
  5746. static DWORD dwSum = 0;
  5747. LONG lRes;
  5748. PDRVCALL pCall;
  5749. PNDISTAPI_REQUEST pNdisTapiRequest;
  5750. PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode;
  5751. TspLog(DL_TRACE, "lineSetMediaMode(%d): call(%p), mode(%x)",
  5752. ++dwSum, hdCall, dwMediaMode);
  5753. lRes = GetCallObjWithReadLock(hdCall, &pCall);
  5754. if (lRes != TAPI_SUCCESS)
  5755. {
  5756. return lRes;
  5757. }
  5758. if ((lRes = PrepareSyncRequest(
  5759. OID_TAPI_SET_MEDIA_MODE, // opcode
  5760. pCall->dwDeviceID, // device id
  5761. sizeof(NDIS_TAPI_SET_MEDIA_MODE), // size
  5762. &pNdisTapiRequest // ptr to ptr to req buf
  5763. )) != TAPI_SUCCESS)
  5764. {
  5765. ReleaseObjReadLock((HANDLE)hdCall);
  5766. return lRes;
  5767. }
  5768. pNdisTapiSetMediaMode = (PNDIS_TAPI_SET_MEDIA_MODE)pNdisTapiRequest->Data;
  5769. pNdisTapiSetMediaMode->hdCall = GetNdisTapiHandle(pCall, &lRes);
  5770. if(lRes != TAPI_SUCCESS)
  5771. {
  5772. FreeRequest(pNdisTapiRequest);
  5773. return lRes;
  5774. }
  5775. pNdisTapiSetMediaMode->ulMediaMode = dwMediaMode;
  5776. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5777. FreeRequest(pNdisTapiRequest);
  5778. ReleaseObjReadLock((HANDLE)hdCall);
  5779. return lRes;
  5780. }
  5781. LONG
  5782. TSPIAPI
  5783. TSPI_lineSetStatusMessages(
  5784. HDRVLINE hdLine,
  5785. DWORD dwLineStates,
  5786. DWORD dwAddressStates
  5787. )
  5788. {
  5789. static DWORD dwSum = 0;
  5790. LONG lRes;
  5791. PDRVLINE pLine;
  5792. PNDISTAPI_REQUEST pNdisTapiRequest;
  5793. PNDIS_TAPI_SET_STATUS_MESSAGES pNdisTapiSetStatusMessages;
  5794. TspLog(DL_TRACE, "lineSetStatusMessages(%d): line(%p)", ++dwSum, hdLine);
  5795. lRes = GetLineObjWithReadLock(hdLine, &pLine);
  5796. if (lRes != TAPI_SUCCESS)
  5797. {
  5798. return lRes;
  5799. }
  5800. if ((lRes = PrepareSyncRequest(
  5801. OID_TAPI_SET_STATUS_MESSAGES, // opcode
  5802. pLine->dwDeviceID, // device id
  5803. sizeof(NDIS_TAPI_SET_STATUS_MESSAGES), // size
  5804. &pNdisTapiRequest // ptr to ptr to req buf
  5805. )) != TAPI_SUCCESS)
  5806. {
  5807. ReleaseObjReadLock((HANDLE)hdLine);
  5808. return lRes;
  5809. }
  5810. pNdisTapiSetStatusMessages =
  5811. (PNDIS_TAPI_SET_STATUS_MESSAGES)pNdisTapiRequest->Data;
  5812. pNdisTapiSetStatusMessages->hdLine = pLine->hd_Line;
  5813. pNdisTapiSetStatusMessages->ulLineStates = dwLineStates;
  5814. pNdisTapiSetStatusMessages->ulAddressStates = dwAddressStates;
  5815. lRes = SyncDriverRequest(IOCTL_NDISTAPI_SET_INFO, pNdisTapiRequest);
  5816. FreeRequest(pNdisTapiRequest);
  5817. ReleaseObjReadLock((HANDLE)hdLine);
  5818. return lRes;
  5819. }
  5820. //
  5821. // TAPI_providerXxx funcs
  5822. //
  5823. LONG
  5824. TSPIAPI
  5825. TSPI_providerEnumDevices(
  5826. DWORD dwPermanentProviderID,
  5827. LPDWORD lpdwNumLines,
  5828. LPDWORD lpdwNumPhones,
  5829. HPROVIDER hProvider,
  5830. LINEEVENT lpfnLineCreateProc,
  5831. PHONEEVENT lpfnPhoneCreateProc
  5832. )
  5833. {
  5834. char szDeviceName[] = "NDProxy";
  5835. char szTargetPath[] = "\\Device\\NDProxy";
  5836. char szCompleteDeviceName[] = "\\\\.\\NDProxy";
  5837. DWORD cbReturned, dwNumLines;
  5838. DWORD adwConnectInfo[2] = {1, 1};
  5839. TspLog(DL_TRACE, "providerEnumDevices: permProvID(%x)",
  5840. dwPermanentProviderID);
  5841. gpfnLineEvent = lpfnLineCreateProc;
  5842. ghProvider = hProvider;
  5843. gInitResult= LINEERR_OPERATIONFAILED;
  5844. // create symbolic link to the kernel-mode driver
  5845. DefineDosDevice (DDD_RAW_TARGET_PATH, szDeviceName, szTargetPath);
  5846. //
  5847. // open driver handles
  5848. //
  5849. if ((ghDriverSync = CreateFileA(
  5850. szCompleteDeviceName,
  5851. GENERIC_READ | GENERIC_WRITE,
  5852. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5853. NULL, // no security attrs
  5854. OPEN_EXISTING,
  5855. FILE_ATTRIBUTE_NORMAL,
  5856. NULL // no template file
  5857. )) == INVALID_HANDLE_VALUE)
  5858. {
  5859. TspLog(DL_ERROR,
  5860. "providerEnumDevices: CreateFile(%s, sync) failed(%ld)",
  5861. szCompleteDeviceName, GetLastError());
  5862. goto enumdevs_error0;
  5863. }
  5864. if ((ghDriverAsync = CreateFileA(
  5865. szCompleteDeviceName,
  5866. GENERIC_READ | GENERIC_WRITE,
  5867. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5868. NULL, // no security attrs
  5869. OPEN_EXISTING,
  5870. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  5871. NULL // no template file
  5872. )) == INVALID_HANDLE_VALUE)
  5873. {
  5874. TspLog(DL_ERROR,
  5875. "providerEnumDevices: CreateFile(%s, async) failed(%ld)",
  5876. szCompleteDeviceName, GetLastError());
  5877. goto enumdevs_error1;
  5878. }
  5879. // create io completion port
  5880. if ((ghCompletionPort = CreateIoCompletionPort(ghDriverAsync, NULL, 0, 0))
  5881. == INVALID_HANDLE_VALUE)
  5882. {
  5883. TspLog(DL_ERROR,
  5884. "providerEnumDevices: CreateIoCompletionPort failed(%ld)",
  5885. GetLastError());
  5886. goto enumdevs_error2;
  5887. }
  5888. // connect to driver: sending a device ID base
  5889. // and it will return the number of devices it supports
  5890. if (!DeviceIoControl(ghDriverSync,
  5891. (DWORD) IOCTL_NDISTAPI_CONNECT,
  5892. adwConnectInfo,
  5893. 2*sizeof(DWORD),
  5894. &dwNumLines,
  5895. sizeof(DWORD),
  5896. &cbReturned,
  5897. (LPOVERLAPPED) NULL
  5898. ) || (cbReturned < sizeof(DWORD)))
  5899. {
  5900. TspLog(DL_ERROR,
  5901. "providerEnumDevices: CONNECT failed(%ld)",
  5902. GetLastError());
  5903. goto enumdevs_error3;
  5904. }
  5905. // init the req id
  5906. gdwRequestID = 1;
  5907. // set the number of devices
  5908. *((LPDWORD)lpdwNumLines) = dwNumLines;
  5909. // if here, success
  5910. gInitResult = TAPI_SUCCESS;
  5911. goto enumdevs_return;
  5912. // clean up resources if an error occurred
  5913. enumdevs_error3:
  5914. CloseHandle (ghCompletionPort);
  5915. enumdevs_error2:
  5916. CloseHandle (ghDriverAsync);
  5917. enumdevs_error1:
  5918. CloseHandle (ghDriverSync);
  5919. enumdevs_error0:
  5920. DefineDosDevice (DDD_REMOVE_DEFINITION, szDeviceName, NULL);
  5921. enumdevs_return:
  5922. TspLog(DL_INFO, "providerEnumDevices: gInitResult(%x)", gInitResult);
  5923. return gInitResult;
  5924. }
  5925. LONG
  5926. TSPIAPI
  5927. TSPI_providerConfig(
  5928. HWND hwndOwner,
  5929. DWORD dwPermanentProviderID
  5930. )
  5931. {
  5932. UNREFERENCED_PARAMETER(hwndOwner); // no dialog here
  5933. UNREFERENCED_PARAMETER(dwPermanentProviderID); // not needed anymore
  5934. // success
  5935. return TAPI_SUCCESS;
  5936. }
  5937. LONG
  5938. TSPIAPI
  5939. TSPI_providerInit(
  5940. DWORD dwTSPIVersion,
  5941. DWORD dwPermanentProviderID,
  5942. DWORD dwLineDeviceIDBase,
  5943. DWORD dwPhoneDeviceIDBase,
  5944. DWORD_PTR dwNumLines,
  5945. DWORD_PTR dwNumPhones,
  5946. ASYNC_COMPLETION lpfnCompletionProc,
  5947. LPDWORD lpdwTSPIOptions
  5948. )
  5949. {
  5950. LONG lRes = LINEERR_OPERATIONFAILED;
  5951. DWORD cbReturned, dwThreadID;
  5952. TspLog(DL_TRACE, "providerInit: perfProvID(%x), lineDevIDBase(%x)",
  5953. dwPermanentProviderID, dwLineDeviceIDBase);
  5954. gpfnCompletionProc = lpfnCompletionProc;
  5955. // inform tapisrv that we support multiple simultaneous requests
  5956. // (the WAN wrapper handles request serialization for miniports)
  5957. *lpdwTSPIOptions = 0;
  5958. // check for successful init in EnumDevs
  5959. if (gInitResult != TAPI_SUCCESS)
  5960. {
  5961. goto providerInit_return;
  5962. }
  5963. // send the base ID to the proxy
  5964. if (!DeviceIoControl(ghDriverSync,
  5965. (DWORD) IOCTL_NDISTAPI_SET_DEVICEID_BASE,
  5966. &dwLineDeviceIDBase,
  5967. sizeof(DWORD),
  5968. NULL,
  5969. 0,
  5970. &cbReturned,
  5971. (LPOVERLAPPED)NULL))
  5972. {
  5973. TspLog(DL_ERROR, "providerInit: SET_DEVICEID_BASE failed(%ld)",
  5974. GetLastError());
  5975. goto providerInit_return;
  5976. }
  5977. //
  5978. // init mapper and allocator
  5979. //
  5980. if (InitializeMapper() != TAPI_SUCCESS)
  5981. {
  5982. goto providerInit_return;
  5983. }
  5984. InitAllocator();
  5985. //
  5986. // alloc the resources needed by the AsyncEventThread,
  5987. // and then create the thread
  5988. //
  5989. if ((gpAsyncEventsThreadInfo = (PASYNC_EVENTS_THREAD_INFO)
  5990. MALLOC(sizeof(ASYNC_EVENTS_THREAD_INFO))) == NULL)
  5991. {
  5992. TspLog(DL_ERROR, "providerInit: failed to alloc thread info");
  5993. goto providerInit_error4;
  5994. }
  5995. gpAsyncEventsThreadInfo->dwBufSize = EVENT_BUFFER_SIZE;
  5996. if ((gpAsyncEventsThreadInfo->pBuf = (PNDISTAPI_EVENT_DATA)
  5997. MALLOC(EVENT_BUFFER_SIZE)) == NULL)
  5998. {
  5999. TspLog(DL_ERROR, "providerInit: failed to alloc event buf");
  6000. goto providerInit_error5;
  6001. }
  6002. if ((gpAsyncEventsThreadInfo->hThread = CreateThread(
  6003. (LPSECURITY_ATTRIBUTES)NULL, // no security attrs
  6004. 0, // default stack size
  6005. (LPTHREAD_START_ROUTINE) // func addr
  6006. AsyncEventsThread,
  6007. (LPVOID)NULL, // thread param
  6008. 0, // create flags
  6009. &dwThreadID // thread id
  6010. )) == NULL)
  6011. {
  6012. TspLog(DL_ERROR, "providerInit: CreateThread failed(%ld)",
  6013. GetLastError());
  6014. goto providerInit_error7;
  6015. }
  6016. //
  6017. // If here success
  6018. //
  6019. lRes = TAPI_SUCCESS;
  6020. goto providerInit_return;
  6021. //
  6022. // clean up resources if an error occured & then return
  6023. //
  6024. providerInit_error7:
  6025. FREE(gpAsyncEventsThreadInfo->pBuf);
  6026. providerInit_error5:
  6027. FREE(gpAsyncEventsThreadInfo);
  6028. providerInit_error4:
  6029. UninitAllocator();
  6030. UninitializeMapper();
  6031. providerInit_return:
  6032. TspLog(DL_INFO, "providerInit: lRes(%x)", lRes);
  6033. return lRes;
  6034. }
  6035. LONG
  6036. TSPIAPI
  6037. TSPI_providerCreateLineDevice(
  6038. DWORD_PTR dwTempID,
  6039. DWORD dwDeviceID
  6040. )
  6041. {
  6042. DWORD cbReturned;
  6043. NDISTAPI_CREATE_INFO CreateInfo;
  6044. CreateInfo.TempID = (DWORD)dwTempID;
  6045. CreateInfo.DeviceID = dwDeviceID;
  6046. TspLog(DL_TRACE, "providerCreateLineDevice: tempID(%x), deviceID(%x)",
  6047. dwTempID, dwDeviceID);
  6048. if (!DeviceIoControl(
  6049. ghDriverSync,
  6050. IOCTL_NDISTAPI_CREATE,
  6051. &CreateInfo,
  6052. sizeof(CreateInfo),
  6053. &CreateInfo,
  6054. sizeof(CreateInfo),
  6055. &cbReturned,
  6056. (LPOVERLAPPED)NULL
  6057. ))
  6058. {
  6059. TspLog(DL_ERROR, "providerCreateLineDevice: failed(%ld) to create",
  6060. GetLastError());
  6061. return LINEERR_OPERATIONFAILED;
  6062. }
  6063. return TAPI_SUCCESS;
  6064. }
  6065. LONG
  6066. TSPIAPI
  6067. TSPI_providerShutdown(
  6068. DWORD dwTSPIVersion,
  6069. DWORD dwPermanentProviderID
  6070. )
  6071. {
  6072. char deviceName[] = "NDPROXY";
  6073. ASYNC_REQUEST_WRAPPER asyncRequestWrapper;
  6074. DWORD cbReturned;
  6075. TspLog(DL_TRACE, "providerShutdown: perfProvID(%x)", dwPermanentProviderID);
  6076. // disconnect with the driver
  6077. if (!DeviceIoControl(ghDriverSync,
  6078. (DWORD) IOCTL_NDISTAPI_DISCONNECT,
  6079. NULL,
  6080. 0,
  6081. NULL,
  6082. 0,
  6083. &cbReturned,
  6084. (LPOVERLAPPED) NULL
  6085. ))
  6086. {
  6087. TspLog(DL_ERROR, "providerShutdown: DISCONNECT failed(%ld)",
  6088. GetLastError());
  6089. }
  6090. //
  6091. // Close the driver & remove the symbolic link
  6092. //
  6093. CancelIo(ghDriverSync);
  6094. CancelIo(ghDriverAsync);
  6095. CloseHandle (ghDriverSync);
  6096. CloseHandle (ghDriverAsync);
  6097. CloseHandle (ghCompletionPort);
  6098. DefineDosDevice (DDD_REMOVE_DEFINITION, deviceName, NULL);
  6099. WaitForSingleObject(gpAsyncEventsThreadInfo->hThread, INFINITE);
  6100. CloseHandle(gpAsyncEventsThreadInfo->hThread);
  6101. FREE(gpAsyncEventsThreadInfo->pBuf);
  6102. FREE(gpAsyncEventsThreadInfo);
  6103. UninitAllocator();
  6104. UninitializeMapper();
  6105. return TAPI_SUCCESS;
  6106. }
  6107. LONG
  6108. TSPIAPI
  6109. TSPI_providerUIIdentify(
  6110. LPWSTR pwszUIDLLName
  6111. )
  6112. {
  6113. // copy name of our dll as ui dll
  6114. lstrcpyW(pwszUIDLLName, NDPTSP_UIDLL);
  6115. // success
  6116. return TAPI_SUCCESS;
  6117. }
  6118. LONG
  6119. TSPIAPI
  6120. TUISPI_providerConfig(
  6121. TUISPIDLLCALLBACK pfnUIDLLCallback,
  6122. HWND hwndOwner,
  6123. DWORD dwPermanentProviderID
  6124. )
  6125. {
  6126. INT_PTR nResult;
  6127. CONFIG_UI_CTX Ctx;
  6128. UNREFERENCED_PARAMETER(pfnUIDLLCallback);
  6129. UNREFERENCED_PARAMETER(dwPermanentProviderID);
  6130. ZeroMemory(&Ctx, sizeof(Ctx));
  6131. // invoke dialog box
  6132. nResult = DialogBoxParamW(
  6133. ghInstance,
  6134. (LPWSTR)MAKEINTRESOURCE(IDD_MEDIA_MAP),
  6135. hwndOwner,
  6136. ProviderConfigDlgProc,
  6137. (LPARAM)&Ctx
  6138. );
  6139. // status based on whether dialog executed properly
  6140. return ((DWORD)nResult == 0) ? TAPI_SUCCESS : LINEERR_OPERATIONFAILED;
  6141. }
  6142. BOOL
  6143. WINAPI
  6144. DllMain(
  6145. HANDLE hDLL,
  6146. DWORD dwReason,
  6147. LPVOID lpReserved
  6148. )
  6149. {
  6150. switch (dwReason)
  6151. {
  6152. case DLL_PROCESS_ATTACH:
  6153. {
  6154. #if DBG
  6155. {
  6156. HKEY hKey;
  6157. DWORD dwDataSize, dwDataType;
  6158. TCHAR szTelephonyKey[] =
  6159. "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
  6160. TCHAR szNdptspDebugLevel[] = "NdptspDebugLevel";
  6161. RegOpenKeyEx(
  6162. HKEY_LOCAL_MACHINE,
  6163. szTelephonyKey,
  6164. 0,
  6165. KEY_ALL_ACCESS,
  6166. &hKey
  6167. );
  6168. dwDataSize = sizeof(DWORD);
  6169. gdwDebugLevel = DL_WARNING;
  6170. RegQueryValueEx(
  6171. hKey,
  6172. szNdptspDebugLevel,
  6173. 0,
  6174. &dwDataType,
  6175. (LPBYTE)&gdwDebugLevel,
  6176. &dwDataSize
  6177. );
  6178. RegCloseKey(hKey);
  6179. }
  6180. #endif
  6181. gdwTraceID = TraceRegisterA("NDPTSP");
  6182. ASSERT(gdwTraceID != INVALID_TRACEID);
  6183. TspLog(DL_TRACE, "DLL_PROCESS_ATTACH");
  6184. // save the handle for the UI
  6185. ghInstance = hDLL;
  6186. ZeroMemory(&gpAddressMapListArray, sizeof(gpAddressMapListArray));
  6187. gbAddressMapListLoaded = FALSE;
  6188. //
  6189. // Init global sync objects
  6190. //
  6191. InitializeCriticalSection(&gRequestIDCritSec);
  6192. InitializeCriticalSection(&gAddressMapCritSec);
  6193. InitLineDevList();
  6194. break;
  6195. }
  6196. case DLL_PROCESS_DETACH:
  6197. {
  6198. TspLog(DL_TRACE, "DLL_PROCESS_DETACH");
  6199. UninitLineDevList();
  6200. // free address list
  6201. FreeAllAddressLists(gpAddressMapListArray);
  6202. DeleteCriticalSection(&gRequestIDCritSec);
  6203. DeleteCriticalSection(&gAddressMapCritSec);
  6204. TraceDeregisterA(gdwTraceID);
  6205. break;
  6206. }
  6207. } // switch
  6208. return TRUE;
  6209. }