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

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