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

1624 lines
41 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. sdpsp.cpp
  5. Abstract:
  6. This module contains a multicast conference service provider for TAPI3.0.
  7. It is first designed and implemented in c. Later, in order to use the SDP
  8. parser, which is written in C++, this file is changed to cpp. It still
  9. uses only c features except the lines that uses the parser.
  10. Author:
  11. Mu Han (muhan) 26-March-1997
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "stdafx.h"
  19. #include <initguid.h>
  20. #include <confpdu.h>
  21. #include "resource.h"
  22. #include "conftsp.h"
  23. #include "confdbg.h"
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // //
  26. // Global Variables //
  27. // //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. static WCHAR gszUIDLLName[] = L"IPCONF.TSP";
  30. //
  31. // Some data used in talking with TAPI.
  32. //
  33. HPROVIDER ghProvider;
  34. DWORD gdwPermanentProviderID;
  35. DWORD gdwLineDeviceIDBase;
  36. // The handle of this dll.
  37. extern "C"
  38. {
  39. HINSTANCE g_hInstance;
  40. }
  41. //
  42. // This function is called if the completion of the process will be sent
  43. // as an asynchrous event. Set in TSPI_ProviderInit.
  44. //
  45. ASYNC_COMPLETION glpfnCompletionProc;
  46. //
  47. // Notify tapi about events in the provider. Set in TSPI_LineOpen.
  48. //
  49. LINEEVENT glpfnLineEventProc;
  50. // This service provider has only one line.
  51. LINE gLine;
  52. // Calls are stored in an array of structures. The array will grow as needed.
  53. CCallList gpCallList;
  54. DWORD gdwNumCallsInUse = 0;
  55. // The critical section the protects the global variables.
  56. CRITICAL_SECTION gCritSec;
  57. #if 0 // we dont' need the user name anymore.
  58. // The name of the user.
  59. CHAR gszUserName[MAXUSERNAMELEN + 1];
  60. #endif
  61. ///////////////////////////////////////////////////////////////////////////////
  62. // //
  63. // Functiion definitions for the call object. //
  64. // //
  65. ///////////////////////////////////////////////////////////////////////////////
  66. DWORD CALL::Init(
  67. HTAPICALL htCall,
  68. LPLINECALLPARAMS const lpCallParams
  69. )
  70. {
  71. m_htCall = htCall;
  72. m_dwState = LINECALLSTATE_IDLE;
  73. m_dwStateMode = 0;
  74. m_dwMediaMode = IPCONF_MEDIAMODES;
  75. m_dwAudioQOSLevel = LINEQOSSERVICELEVEL_IFAVAILABLE;
  76. m_dwVideoQOSLevel = LINEQOSSERVICELEVEL_IFAVAILABLE;
  77. // m_dwAudioQOSLevel = LINEQOSSERVICELEVEL_BESTEFFORT;
  78. // m_dwVideoQOSLevel = LINEQOSSERVICELEVEL_BESTEFFORT;
  79. if (!lpCallParams)
  80. {
  81. return NOERROR;
  82. }
  83. // set my media modes.
  84. m_dwMediaMode = lpCallParams->dwMediaMode;
  85. if (lpCallParams->dwReceivingFlowspecOffset == 0)
  86. {
  87. // No QOS policy specified.
  88. DBGOUT((WARN, "no qos level request."));
  89. return NOERROR;
  90. }
  91. // get the QOS policy requirements.
  92. LPLINECALLQOSINFO pQOSInfo = (LPLINECALLQOSINFO)
  93. (((LPBYTE)lpCallParams) + lpCallParams->dwReceivingFlowspecOffset);
  94. ASSERT(pQOSInfo->dwKey == LINEQOSSTRUCT_KEY);
  95. // find out if this is a QOS level request.
  96. if (pQOSInfo->dwQOSRequestType != LINEQOSREQUESTTYPE_SERVICELEVEL)
  97. {
  98. // It is not a request for qos service level.
  99. DBGOUT((WARN, "wrong qos request type."));
  100. return NOERROR;
  101. }
  102. DWORD dwCount = pQOSInfo->SetQOSServiceLevel.dwNumServiceLevelEntries;
  103. for (DWORD i = 0; i < dwCount; i ++)
  104. {
  105. LINEQOSSERVICELEVEL &QOSLevel =
  106. pQOSInfo->SetQOSServiceLevel.LineQOSServiceLevel[i];
  107. switch (QOSLevel.dwMediaMode)
  108. {
  109. case LINEMEDIAMODE_VIDEO:
  110. m_dwVideoQOSLevel = QOSLevel.dwQOSServiceLevel;
  111. break;
  112. case LINEMEDIAMODE_INTERACTIVEVOICE:
  113. case LINEMEDIAMODE_AUTOMATEDVOICE:
  114. m_dwAudioQOSLevel = QOSLevel.dwQOSServiceLevel;
  115. break;
  116. default:
  117. DBGOUT((WARN, "Unknown mediamode for QOS, %x", dwMediaMode));
  118. break;
  119. }
  120. }
  121. return NOERROR;
  122. }
  123. void CALL::SetCallState(
  124. DWORD dwCallState,
  125. DWORD dwCallStateMode
  126. )
  127. {
  128. if (m_dwState != dwCallState)
  129. {
  130. m_dwState = dwCallState;
  131. m_dwStateMode = dwCallStateMode;
  132. (*glpfnLineEventProc)(
  133. gLine.htLine,
  134. m_htCall,
  135. LINE_CALLSTATE,
  136. m_dwState,
  137. m_dwStateMode,
  138. m_dwMediaMode
  139. );
  140. DBGOUT((INFO, "sending event to htCall: %x", m_htCall));
  141. }
  142. }
  143. DWORD CALL::SendMSPStartMessage(LPCWSTR lpszDestAddress)
  144. {
  145. DWORD dwStrLen = lstrlenW(lpszDestAddress);
  146. DWORD dwSize = sizeof(MSG_TSPMSPDATA) + dwStrLen * sizeof(WCHAR);
  147. MSG_TSPMSPDATA *pData = (MSG_TSPMSPDATA *)MemAlloc(dwSize);
  148. if (pData == NULL)
  149. {
  150. DBGOUT((FAIL, "No memory for the TSPMSP data, size: %d", dwSize));
  151. return LINEERR_NOMEM;
  152. }
  153. pData->command = CALL_START;
  154. pData->CallStart.dwAudioQOSLevel = m_dwAudioQOSLevel;
  155. pData->CallStart.dwVideoQOSLevel = m_dwVideoQOSLevel;
  156. pData->CallStart.dwSDPLen = dwStrLen;
  157. lstrcpyW(pData->CallStart.szSDP, lpszDestAddress);
  158. DBGOUT((INFO, "Send MSP call Start message"));
  159. (*glpfnLineEventProc)(
  160. gLine.htLine,
  161. m_htCall,
  162. LINE_SENDMSPDATA,
  163. 0,
  164. PtrToUlong(pData),
  165. dwSize
  166. );
  167. MemFree(pData);
  168. return NOERROR;
  169. }
  170. DWORD CALL::SendMSPStopMessage()
  171. {
  172. MSG_TSPMSPDATA Data;
  173. Data.command = CALL_STOP;
  174. DBGOUT((INFO, "Send MSP call Stop message"));
  175. (*glpfnLineEventProc)(
  176. gLine.htLine,
  177. m_htCall,
  178. LINE_SENDMSPDATA,
  179. 0,
  180. PtrToUlong(&Data),
  181. sizeof(MSG_TSPMSPDATA)
  182. );
  183. return NOERROR;
  184. }
  185. ///////////////////////////////////////////////////////////////////////////////
  186. // //
  187. // Private Functiion definitions //
  188. // //
  189. // Note: none of these functions uses critical sections operations inside. //
  190. // The caller is responsible for critical sections. //
  191. ///////////////////////////////////////////////////////////////////////////////
  192. LONG
  193. CheckCallParams(
  194. LPLINECALLPARAMS const lpCallParams
  195. )
  196. {
  197. // validate pointer
  198. if (lpCallParams == NULL)
  199. {
  200. return NOERROR;
  201. }
  202. // see if the address type is right
  203. if (lpCallParams->dwAddressType != LINEADDRESSTYPE_SDP)
  204. {
  205. DBGOUT((FAIL,
  206. "wrong address type 0x%08lx.\n", lpCallParams->dwAddressType
  207. ));
  208. return LINEERR_INVALADDRESSTYPE;
  209. }
  210. // see if we support call parameters
  211. if (lpCallParams->dwCallParamFlags != 0)
  212. {
  213. DBGOUT((FAIL,
  214. "do not support call parameters 0x%08lx.\n",
  215. lpCallParams->dwCallParamFlags
  216. ));
  217. return LINEERR_INVALCALLPARAMS;
  218. }
  219. // see if we support media modes specified
  220. if (lpCallParams->dwMediaMode & ~IPCONF_MEDIAMODES)
  221. {
  222. DBGOUT((FAIL,
  223. "do not support media modes 0x%08lx.\n",
  224. lpCallParams->dwMediaMode
  225. ));
  226. return LINEERR_INVALMEDIAMODE;
  227. }
  228. // see if we support bearer modes
  229. if (lpCallParams->dwBearerMode & ~IPCONF_BEARERMODES)
  230. {
  231. DBGOUT((FAIL,
  232. "do not support bearer mode 0x%08lx.\n",
  233. lpCallParams->dwBearerMode
  234. ));
  235. return LINEERR_INVALBEARERMODE;
  236. }
  237. // see if we support address modes
  238. if (lpCallParams->dwAddressMode & ~IPCONF_ADDRESSMODES)
  239. {
  240. DBGOUT((FAIL,
  241. "do not support address mode 0x%08lx.\n",
  242. lpCallParams->dwAddressMode
  243. ));
  244. return LINEERR_INVALADDRESSMODE;
  245. }
  246. // validate address id specified There is only one address per line
  247. if (lpCallParams->dwAddressID != 0)
  248. {
  249. DBGOUT((FAIL,
  250. "address id 0x%08lx invalid.\n",
  251. lpCallParams->dwAddressID
  252. ));
  253. return LINEERR_INVALADDRESSID;
  254. }
  255. return NOERROR;
  256. }
  257. DWORD
  258. FreeCall(DWORD hdCall)
  259. /*++
  260. Routine Description:
  261. Decrement the ref count on the call and release the call if the ref
  262. count gets 0.
  263. Arguments:
  264. hdCall - The handle of the call.
  265. Return Value:
  266. NOERROR
  267. --*/
  268. {
  269. if (gpCallList[hdCall] == NULL)
  270. {
  271. return NOERROR;
  272. }
  273. DWORD dwLine = (DWORD)gpCallList[hdCall]->hdLine();
  274. MemFree(gpCallList[hdCall]);
  275. gpCallList[hdCall] = NULL;
  276. gdwNumCallsInUse --;
  277. gLine.dwNumCalls --;
  278. DBGOUT((INFO, "No.%d call was deleted.", hdCall));
  279. return NOERROR;
  280. }
  281. long FindFreeCallSlot(DWORD &hdCall)
  282. {
  283. if (gdwNumCallsInUse < gpCallList.size())
  284. {
  285. for (DWORD i = 0; i < gpCallList.size(); i++)
  286. {
  287. if (gpCallList[i] == NULL)
  288. {
  289. hdCall = i;
  290. return TRUE;;
  291. }
  292. }
  293. }
  294. if (!gpCallList.add())
  295. {
  296. return FALSE;
  297. }
  298. hdCall = gpCallList.size() - 1;
  299. return TRUE;
  300. }
  301. ///////////////////////////////////////////////////////////////////////////////
  302. // //
  303. // DllMain definition //
  304. // //
  305. ///////////////////////////////////////////////////////////////////////////////
  306. BOOL
  307. WINAPI
  308. DllMain(
  309. HINSTANCE hDLL,
  310. DWORD dwReason,
  311. LPVOID lpReserved
  312. )
  313. {
  314. DWORD i;
  315. DWORD dwUserNameLen = MAXUSERNAMELEN;
  316. HRESULT hr;
  317. switch (dwReason)
  318. {
  319. case DLL_PROCESS_ATTACH:
  320. DBGOUT((TRCE, "DLL_PROCESS_ATTACH"));
  321. DisableThreadLibraryCalls(hDLL);
  322. g_hInstance = hDLL;
  323. #if 0 // we dont' need the user name anymore.
  324. // switch in user's context
  325. RpcImpersonateClient(0);
  326. // determine name of current user
  327. GetUserNameA(gszUserName, &dwUserNameLen);
  328. // switch back
  329. RpcRevertToSelf();
  330. #endif
  331. // Initialize critical sections.
  332. __try
  333. {
  334. InitializeCriticalSection(&gCritSec);
  335. }
  336. __except (EXCEPTION_EXECUTE_HANDLER)
  337. {
  338. return FALSE;
  339. }
  340. break;
  341. case DLL_PROCESS_DETACH:
  342. DBGOUT((TRCE, "DLL_PROCESS_DETACH"));
  343. DeleteCriticalSection(&gCritSec);
  344. break;
  345. } // switch
  346. return TRUE;
  347. }
  348. //
  349. // We get a slough of C4047 (different levels of indrection) warnings down
  350. // below in the initialization of FUNC_PARAM structs as a result of the
  351. // real func prototypes having params that are types other than DWORDs,
  352. // so since these are known non-interesting warnings just turn them off
  353. //
  354. #pragma warning (disable:4047)
  355. ///////////////////////////////////////////////////////////////////////////////
  356. // //
  357. // TSPI_lineXxx functions //
  358. // //
  359. ///////////////////////////////////////////////////////////////////////////////
  360. LONG
  361. TSPIAPI
  362. TSPI_lineClose(
  363. HDRVLINE hdLine
  364. )
  365. {
  366. DBGOUT((TRCE, "TSPI_lineClose, hdLine %p", hdLine));
  367. DWORD dwLine = HandleToUlong(hdLine);
  368. if (dwLine != IPCONF_LINE_HANDLE)
  369. {
  370. DBGOUT((FAIL, "invalide line handle, hdLine %p", hdLine));
  371. return LINEERR_INVALLINEHANDLE;
  372. }
  373. EnterCriticalSection(&gCritSec);
  374. // Clean up all the open calls when this line is closed.
  375. for (DWORD i = 0; i < gpCallList.size(); i++)
  376. {
  377. if ((gpCallList[i] != NULL))
  378. {
  379. FreeCall(i);
  380. }
  381. }
  382. gLine.bOpened = FALSE;
  383. LeaveCriticalSection(&gCritSec);
  384. DBGOUT((TRCE, "TSPI_lineClose succeeded."));
  385. return NOERROR;
  386. }
  387. LONG
  388. TSPIAPI
  389. TSPI_lineCloseCall(
  390. HDRVCALL hdCall
  391. )
  392. {
  393. DBGOUT((TRCE, "TSPI_lineCloseCall, hdCall %p", hdCall));
  394. DWORD dwCall = HandleToUlong(hdCall);
  395. EnterCriticalSection(&gCritSec);
  396. if (dwCall >= gpCallList.size())
  397. {
  398. LeaveCriticalSection(&gCritSec);
  399. DBGOUT((FAIL, "TSPI_lineCloseCall invalid call handle: %p", hdCall));
  400. return LINEERR_INVALCALLHANDLE;
  401. }
  402. FreeCall(dwCall);
  403. LeaveCriticalSection(&gCritSec);
  404. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  405. return NOERROR;
  406. }
  407. LONG
  408. TSPIAPI
  409. TSPI_lineCreateMSPInstance(
  410. HDRVLINE hdLine,
  411. DWORD dwAddressID,
  412. HTAPIMSPLINE htMSPLine,
  413. LPHDRVMSPLINE phdMSPLine
  414. )
  415. {
  416. DBGOUT((TRCE, "TSPI_lineCreateMSPInstance"));
  417. if (IsBadWritePtr(phdMSPLine, sizeof (HDRVMSPLINE)))
  418. {
  419. DBGOUT((FAIL, "TSPI_lineCreateMSPInstance bad pointer"));
  420. return LINEERR_INVALPOINTER;
  421. }
  422. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  423. {
  424. DBGOUT((FAIL, "TSPI_lineCreateMSPInstance, bad line handle:%p", hdLine));
  425. return LINEERR_INVALLINEHANDLE;
  426. }
  427. EnterCriticalSection(&gCritSec);
  428. // We are not keeping the msp handles. Just fake a handle here.
  429. *phdMSPLine = (HDRVMSPLINE)(gLine.dwNextMSPHandle ++);
  430. LeaveCriticalSection(&gCritSec);
  431. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  432. return (NOERROR);
  433. }
  434. LONG
  435. TSPIAPI
  436. TSPI_lineCloseMSPInstance(
  437. HDRVMSPLINE hdMSPLine
  438. )
  439. {
  440. DBGOUT((TRCE, "TSPI_lineCloseMSPInstance, hdMSPLine %p", hdMSPLine));
  441. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  442. return NOERROR;
  443. }
  444. LONG
  445. TSPIAPI
  446. TSPI_lineDrop(
  447. DRV_REQUESTID dwRequestID,
  448. HDRVCALL hdCall,
  449. LPCSTR lpsUserUserInfo,
  450. DWORD dwSize
  451. )
  452. {
  453. DBGOUT((TRCE, "TSPI_lineDrop, hdCall %p", hdCall));
  454. DWORD dwCall = HandleToUlong(hdCall);
  455. EnterCriticalSection(&gCritSec);
  456. // check the call handle.
  457. if (dwCall >= gpCallList.size())
  458. {
  459. LeaveCriticalSection(&gCritSec);
  460. (*glpfnCompletionProc)(dwRequestID, LINEERR_INVALCALLHANDLE);
  461. DBGOUT((FAIL, "TSPI_lineDrop invalid call handle %p", hdCall));
  462. return dwRequestID;
  463. }
  464. CALL *pCall = gpCallList[dwCall];
  465. if (pCall != NULL)
  466. {
  467. pCall->SetCallState(LINECALLSTATE_IDLE, 0);
  468. pCall->SendMSPStopMessage();
  469. DBGOUT((INFO, "call %d state changed to idle", dwCall));
  470. }
  471. LeaveCriticalSection(&gCritSec);
  472. (*glpfnCompletionProc)(dwRequestID, 0);
  473. DBGOUT((TRCE, "TSPI_lineDrop succeeded"));
  474. return dwRequestID;
  475. }
  476. LONG
  477. TSPIAPI
  478. TSPI_lineGetAddressCaps(
  479. DWORD dwDeviceID,
  480. DWORD dwAddressID,
  481. DWORD dwTSPIVersion,
  482. DWORD dwExtVersion,
  483. LPLINEADDRESSCAPS lpAddressCaps
  484. )
  485. {
  486. DBGOUT((TRCE, "TSPI_lineGetAddressCaps"));
  487. if (dwDeviceID != gdwLineDeviceIDBase)
  488. {
  489. DBGOUT((TRCE, "TSPI_lineGetAddressCaps bad device id: %d", dwDeviceID));
  490. return LINEERR_BADDEVICEID;
  491. }
  492. // Check the address ID.
  493. if (dwAddressID != 0)
  494. {
  495. DBGOUT((TRCE, "TSPI_lineGetAddressCaps bad address id: %d", dwAddressID));
  496. return LINEERR_INVALADDRESSID;
  497. }
  498. // load the address name from the string table.
  499. WCHAR szAddressName[IPCONF_BUFSIZE + 1];
  500. if (0 == LoadStringW(g_hInstance, IDS_IPCONFADDRESSNAME, szAddressName, IPCONF_BUFSIZE))
  501. {
  502. szAddressName[0] = L'\0';
  503. }
  504. DWORD dwAddressSize = (lstrlenW(szAddressName) + 1) * (sizeof WCHAR);
  505. lpAddressCaps->dwNeededSize = sizeof(LINEADDRESSCAPS) + dwAddressSize;
  506. if (lpAddressCaps->dwTotalSize >= lpAddressCaps->dwNeededSize)
  507. {
  508. // Copy the IP address to the end of the structure.
  509. lpAddressCaps->dwUsedSize = lpAddressCaps->dwNeededSize;
  510. lpAddressCaps->dwAddressSize = dwAddressSize;
  511. lpAddressCaps->dwAddressOffset = sizeof(LINEADDRESSCAPS);
  512. lstrcpyW ((WCHAR *)(lpAddressCaps + 1), szAddressName);
  513. }
  514. else
  515. {
  516. lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS);
  517. }
  518. lpAddressCaps->dwLineDeviceID = dwDeviceID;
  519. lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
  520. lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_MEDIAMODE;
  521. lpAddressCaps->dwCallerIDFlags =
  522. lpAddressCaps->dwCalledIDFlags =
  523. lpAddressCaps->dwConnectedIDFlags =
  524. lpAddressCaps->dwRedirectionIDFlags =
  525. lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  526. lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
  527. LINECALLSTATE_DIALING |
  528. LINECALLSTATE_CONNECTED;
  529. lpAddressCaps->dwDialToneModes = 0;
  530. lpAddressCaps->dwBusyModes = 0;
  531. lpAddressCaps->dwSpecialInfo = 0;
  532. lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_NORMAL |
  533. LINEDISCONNECTMODE_UNAVAIL;
  534. lpAddressCaps->dwMaxNumActiveCalls = MAXCALLSPERADDRESS;
  535. lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_DIALED |
  536. LINEADDRCAPFLAGS_ORIGOFFHOOK;
  537. lpAddressCaps->dwCallFeatures = LINECALLFEATURE_DROP |
  538. LINECALLFEATURE_SETQOS;
  539. lpAddressCaps->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
  540. DBGOUT((TRCE, "TSPI_lineGetAddressCaps succeeded."));
  541. return NOERROR;
  542. }
  543. LONG
  544. TSPIAPI
  545. TSPI_lineGetAddressID(
  546. HDRVLINE hdLine,
  547. LPDWORD lpdwAddressID,
  548. DWORD dwAddressMode,
  549. LPCWSTR lpsAddress,
  550. DWORD dwSize
  551. )
  552. {
  553. DBGOUT((TRCE, "TSPI_lineGetAddressID htLine:%p", hdLine));
  554. *lpdwAddressID = 0;
  555. DBGOUT((TRCE, "TSPI_lineGetAddressID succeeded."));
  556. return NOERROR;
  557. }
  558. LONG
  559. TSPIAPI
  560. TSPI_lineGetAddressStatus(
  561. HDRVLINE hdLine,
  562. DWORD dwAddressID,
  563. LPLINEADDRESSSTATUS lpAddressStatus
  564. )
  565. {
  566. DBGOUT((TRCE, "TSPI_lineGetAddressStatus htLine:%p", hdLine));
  567. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  568. {
  569. DBGOUT((FAIL, "TSPI_lineGetAddressStatus htLine:%p", hdLine));
  570. return LINEERR_INVALLINEHANDLE;
  571. }
  572. lpAddressStatus->dwNeededSize =
  573. lpAddressStatus->dwUsedSize = sizeof(LINEADDRESSSTATUS);
  574. EnterCriticalSection(&gCritSec);
  575. lpAddressStatus->dwNumActiveCalls = gLine.dwNumCalls;
  576. LeaveCriticalSection(&gCritSec);
  577. lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
  578. DBGOUT((TRCE, "TSPI_lineGetAddressStatus succeeded."));
  579. return NOERROR;
  580. }
  581. LONG
  582. TSPIAPI
  583. TSPI_lineGetCallAddressID(
  584. HDRVCALL hdCall,
  585. LPDWORD lpdwAddressID
  586. )
  587. {
  588. DBGOUT((TRCE, "TSPI_lineGetCallAddressID hdCall %p", hdCall));
  589. //
  590. // We only support 1 address (id=0) per line
  591. //
  592. *lpdwAddressID = 0;
  593. DBGOUT((TRCE, "TSPI_lineGetCallAddressID succeeded."));
  594. return NOERROR;
  595. }
  596. LONG
  597. TSPIAPI
  598. TSPI_lineGetCallInfo(
  599. HDRVCALL hdCall,
  600. LPLINECALLINFO lpLineInfo
  601. )
  602. {
  603. DBGOUT((TRCE, "TSPI_lineGetCallInfo hdCall %p", hdCall));
  604. DWORD dwCall = HandleToUlong(hdCall);
  605. EnterCriticalSection(&gCritSec);
  606. if (dwCall >= gpCallList.size())
  607. {
  608. LeaveCriticalSection(&gCritSec);
  609. DBGOUT((FAIL, "TSPI_lineGetCallInfo bad call handle %p", hdCall));
  610. return LINEERR_INVALCALLHANDLE;
  611. }
  612. // get the call object.
  613. CALL *pCall = gpCallList[dwCall];
  614. if (pCall == NULL)
  615. {
  616. LeaveCriticalSection(&gCritSec);
  617. DBGOUT((FAIL, "TSPI_lineGetCallInfo bad call handle %p", hdCall));
  618. return LINEERR_INVALCALLHANDLE;
  619. }
  620. lpLineInfo->dwMediaMode = pCall->dwMediaMode();
  621. LeaveCriticalSection(&gCritSec);
  622. lpLineInfo->dwLineDeviceID = gLine.dwDeviceID;
  623. lpLineInfo->dwAddressID = 0; // There is only on address per line.
  624. lpLineInfo->dwBearerMode = IPCONF_BEARERMODES;
  625. lpLineInfo->dwCallStates = LINECALLSTATE_IDLE |
  626. LINECALLSTATE_DIALING |
  627. LINECALLSTATE_CONNECTED;
  628. lpLineInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
  629. lpLineInfo->dwReason = LINECALLREASON_DIRECT;
  630. lpLineInfo->dwCallerIDFlags =
  631. lpLineInfo->dwCalledIDFlags =
  632. lpLineInfo->dwConnectedIDFlags =
  633. lpLineInfo->dwRedirectionIDFlags =
  634. lpLineInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  635. DBGOUT((TRCE, "TSPI_lineGetCallInfo succeeded."));
  636. return NOERROR;
  637. }
  638. LONG
  639. TSPIAPI
  640. TSPI_lineGetCallStatus(
  641. HDRVCALL hdCall,
  642. LPLINECALLSTATUS lpLineStatus
  643. )
  644. {
  645. DBGOUT((TRCE, "TSPI_lineGetCallStatus hdCall %p", hdCall));
  646. DWORD dwCall = HandleToUlong(hdCall);
  647. EnterCriticalSection(&gCritSec);
  648. // check the call handle.
  649. if (dwCall >= gpCallList.size())
  650. {
  651. LeaveCriticalSection(&gCritSec);
  652. DBGOUT((TRCE, "TSPI_lineGetCallStatus bad call handle %p", hdCall));
  653. return LINEERR_INVALCALLHANDLE;
  654. }
  655. lpLineStatus->dwNeededSize =
  656. lpLineStatus->dwUsedSize = sizeof(LINECALLSTATUS);
  657. lpLineStatus->dwCallState = gpCallList[dwCall]->dwState();
  658. if (lpLineStatus->dwCallState != LINECALLSTATE_IDLE)
  659. {
  660. lpLineStatus->dwCallFeatures = LINECALLFEATURE_DROP |
  661. LINECALLFEATURE_SETQOS;
  662. }
  663. LeaveCriticalSection(&gCritSec);
  664. DBGOUT((TRCE, "TSPI_lineGetCallStatus succeeded."));
  665. return NOERROR;
  666. }
  667. LONG
  668. TSPIAPI
  669. TSPI_lineGetDevCaps(
  670. DWORD dwDeviceID,
  671. DWORD dwTSPIVersion,
  672. DWORD dwExtVersion,
  673. LPLINEDEVCAPS lpLineDevCaps
  674. )
  675. {
  676. DBGOUT((TRCE, "TSPI_lineGetDevCaps"));
  677. if (dwDeviceID != gdwLineDeviceIDBase)
  678. {
  679. DBGOUT((FAIL, "TSPI_lineGetDevCaps bad device id %d", dwDeviceID));
  680. return LINEERR_BADDEVICEID;
  681. }
  682. DWORD dwProviderInfoSize;
  683. DWORD dwLineNameSize;
  684. DWORD dwDevSpecificSize;
  685. DWORD dwOffset;
  686. // load the name of the service provider from the string table.
  687. WCHAR szProviderInfo[IPCONF_BUFSIZE + 1];
  688. if (0 == LoadStringW(g_hInstance, IDS_IPCONFPROVIDERNAME, szProviderInfo, IPCONF_BUFSIZE))
  689. {
  690. szProviderInfo[0] = L'\0';
  691. }
  692. dwProviderInfoSize = (lstrlenW(szProviderInfo) + 1) * sizeof(WCHAR);
  693. // load the line name format from the string table and print the line name.
  694. WCHAR szLineName[IPCONF_BUFSIZE + 1];
  695. if (0 == LoadStringW(g_hInstance, IDS_IPCONFLINENAME, szLineName, IPCONF_BUFSIZE))
  696. {
  697. szLineName[0] = L'\0';
  698. }
  699. dwLineNameSize = (lstrlenW(szLineName) + 1) * (sizeof WCHAR);
  700. lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS)
  701. + dwProviderInfoSize
  702. + dwLineNameSize;
  703. if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwNeededSize)
  704. {
  705. lpLineDevCaps->dwUsedSize = lpLineDevCaps->dwNeededSize;
  706. CHAR *pChar;
  707. pChar = (CHAR *)(lpLineDevCaps + 1);
  708. dwOffset = sizeof(LINEDEVCAPS);
  709. // fill in the provider info.
  710. lpLineDevCaps->dwProviderInfoSize = dwProviderInfoSize;
  711. lpLineDevCaps->dwProviderInfoOffset = dwOffset;
  712. lstrcpyW ((WCHAR *)pChar, szProviderInfo);
  713. pChar += dwProviderInfoSize;
  714. dwOffset += dwProviderInfoSize;
  715. // fill in the name of the line.
  716. lpLineDevCaps->dwLineNameSize = dwLineNameSize;
  717. lpLineDevCaps->dwLineNameOffset = dwOffset;
  718. lstrcpyW ((WCHAR *)pChar, szLineName);
  719. }
  720. else
  721. {
  722. lpLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS);
  723. }
  724. // We don't have really "Permanent" line ids. So just fake one here.
  725. lpLineDevCaps->dwPermanentLineID =
  726. ((gdwPermanentProviderID & 0xffff) << 16) |
  727. ((dwDeviceID - gdwLineDeviceIDBase) & 0xffff);
  728. CopyMemory(
  729. &(lpLineDevCaps->PermanentLineGuid),
  730. &GUID_LINE,
  731. sizeof(GUID)
  732. );
  733. lpLineDevCaps->PermanentLineGuid.Data1 += dwDeviceID - gdwLineDeviceIDBase;
  734. lpLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
  735. lpLineDevCaps->dwAddressModes = IPCONF_ADDRESSMODES;
  736. lpLineDevCaps->dwNumAddresses = IPCONF_NUMADDRESSESPERLINE;
  737. lpLineDevCaps->dwBearerModes = IPCONF_BEARERMODES;
  738. lpLineDevCaps->dwMediaModes = IPCONF_MEDIAMODES;
  739. lpLineDevCaps->dwMaxRate = (1 << 20);
  740. lpLineDevCaps->dwAddressTypes = LINEADDRESSTYPE_SDP;
  741. lpLineDevCaps->dwDevCapFlags =
  742. LINEDEVCAPFLAGS_CLOSEDROP
  743. | LINEDEVCAPFLAGS_MSP;
  744. lpLineDevCaps->dwMaxNumActiveCalls =
  745. MAXCALLSPERADDRESS * IPCONF_NUMADDRESSESPERLINE;
  746. lpLineDevCaps->dwRingModes = 0;
  747. lpLineDevCaps->dwLineFeatures = LINEFEATURE_MAKECALL;
  748. CopyMemory(
  749. &(lpLineDevCaps->ProtocolGuid),
  750. &TAPIPROTOCOL_Multicast,
  751. sizeof(GUID)
  752. );
  753. DBGOUT((TRCE, "TSPI_lineGetDevCaps succeeded."));
  754. return NOERROR;
  755. }
  756. LONG
  757. TSPIAPI
  758. TSPI_lineGetIcon(
  759. DWORD dwDeviceID,
  760. LPCWSTR lpgszDeviceClass,
  761. LPHICON lphIcon
  762. )
  763. {
  764. DBGOUT((TRCE, "TSPI_lineGetIcon:"));
  765. return LINEERR_OPERATIONUNAVAIL;
  766. }
  767. LONG
  768. TSPIAPI
  769. TSPI_lineGetID(
  770. HDRVLINE hdLine,
  771. DWORD dwAddressID,
  772. HDRVCALL hdCall,
  773. DWORD dwSelect,
  774. LPVARSTRING lpDeviceID,
  775. LPCWSTR lpgszDeviceClass,
  776. HANDLE hTargetProcess
  777. )
  778. {
  779. DBGOUT((TRCE, "TSPI_lineGetID:"));
  780. return LINEERR_OPERATIONUNAVAIL;
  781. }
  782. LONG
  783. TSPIAPI
  784. TSPI_lineGetLineDevStatus(
  785. HDRVLINE hdLine,
  786. LPLINEDEVSTATUS lpLineDevStatus
  787. )
  788. {
  789. DBGOUT((TRCE, "TSPI_lineGetLineDevStatus %p", hdLine));
  790. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  791. {
  792. DBGOUT((FAIL, "TSPI_lineGetLineDevStatus bad line handle %p", hdLine));
  793. return LINEERR_INVALLINEHANDLE;
  794. }
  795. lpLineDevStatus->dwUsedSize =
  796. lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
  797. EnterCriticalSection(&gCritSec);
  798. lpLineDevStatus->dwNumActiveCalls = gLine.dwNumCalls;
  799. LeaveCriticalSection(&gCritSec);
  800. lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL;
  801. lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
  802. LINEDEVSTATUSFLAGS_INSERVICE;
  803. DBGOUT((TRCE, "TSPI_lineGetLineDevStatus succeeded"));
  804. return NOERROR;
  805. }
  806. LONG
  807. TSPIAPI
  808. TSPI_lineGetNumAddressIDs(
  809. HDRVLINE hdLine,
  810. LPDWORD lpdwNumAddressIDs
  811. )
  812. {
  813. DBGOUT((TRCE, "TSPI_lineGetNumAddressIDs"));
  814. *lpdwNumAddressIDs = IPCONF_NUMADDRESSESPERLINE;
  815. DBGOUT((TRCE, "TSPI_lineGetNumAddressIDs succeeded."));
  816. return NOERROR;
  817. }
  818. LONG
  819. TSPIAPI
  820. TSPI_lineMakeCall(
  821. DRV_REQUESTID dwRequestID,
  822. HDRVLINE hdLine,
  823. HTAPICALL htCall,
  824. LPHDRVCALL lphdCall,
  825. LPCWSTR lpszDestAddress,
  826. DWORD dwCountryCode,
  827. LPLINECALLPARAMS const lpCallParams
  828. )
  829. {
  830. DBGOUT((TRCE, "TSPI_lineMakeCall hdLine %p, htCall %p",
  831. hdLine, htCall));
  832. // check the line handle.
  833. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  834. {
  835. DBGOUT((FAIL, "TSPI_lineMakeCall Bad line handle %p", hdLine));
  836. return LINEERR_INVALLINEHANDLE;
  837. }
  838. LONG lResult;
  839. if ((lResult = CheckCallParams(lpCallParams)) != NOERROR)
  840. {
  841. DBGOUT((FAIL, "TSPI_lineMakeCall Bad call params"));
  842. return lResult;
  843. }
  844. // check the destination address.
  845. if (lpszDestAddress == NULL || lstrlenW(lpszDestAddress) == 0)
  846. {
  847. DBGOUT((FAIL, "TSPI_lineMakeCall invalid address."));
  848. return LINEERR_INVALADDRESS;
  849. }
  850. DBGOUT((TRCE, "TSPI_lineMakeCall making call to %ws", lpszDestAddress));
  851. // check the line handle.
  852. EnterCriticalSection(&gCritSec);
  853. // create a call object.
  854. CALL * pCall = (CALL *)MemAlloc(sizeof(CALL));
  855. if (pCall == NULL)
  856. {
  857. LeaveCriticalSection(&gCritSec);
  858. DBGOUT((FAIL, "out of memory for a new call"));
  859. return LINEERR_NOMEM;
  860. }
  861. if (pCall->Init(
  862. htCall,
  863. lpCallParams
  864. ) != NOERROR)
  865. {
  866. MemFree(pCall);
  867. LeaveCriticalSection(&gCritSec);
  868. DBGOUT((FAIL, "out of memory in init a new call"));
  869. return LINEERR_NOMEM;
  870. }
  871. // add the call into the call list.
  872. DWORD hdCall;
  873. if (!FindFreeCallSlot(hdCall))
  874. {
  875. LeaveCriticalSection(&gCritSec);
  876. MemFree(pCall);
  877. DBGOUT((FAIL, "out of memory finding a new slot"));
  878. return LINEERR_NOMEM;
  879. }
  880. gpCallList[hdCall] = pCall;
  881. // Increament the call count for the line and the provider.
  882. gLine.dwNumCalls ++;
  883. gdwNumCallsInUse ++;
  884. // Complete the request and set the initial call state.
  885. (*glpfnCompletionProc)(dwRequestID, lResult);
  886. *lphdCall = (HDRVCALL)(hdCall);
  887. // Send the MSP a message about this call. It has the SDP in it.
  888. lResult = pCall->SendMSPStartMessage(lpszDestAddress);
  889. if (lResult == NOERROR)
  890. {
  891. // Set the call state to dialing.
  892. pCall->SetCallState(
  893. LINECALLSTATE_DIALING,
  894. 0
  895. );
  896. DBGOUT((INFO, "call %d state changed to dialing", hdCall));
  897. }
  898. else
  899. {
  900. DBGOUT((FAIL, "send MSP message failed, err:%x", lResult));
  901. // Set the call state to idel.
  902. pCall->SetCallState(
  903. LINECALLSTATE_DISCONNECTED,
  904. LINEDISCONNECTMODE_UNREACHABLE
  905. );
  906. DBGOUT((INFO, "call %d state changed to disconnected", hdCall));
  907. }
  908. LeaveCriticalSection(&gCritSec);
  909. DBGOUT((TRCE, "TSPI_lineMakeCall succeeded."));
  910. return dwRequestID;
  911. }
  912. LONG
  913. TSPIAPI
  914. TSPI_lineMSPIdentify(
  915. DWORD dwDeviceID,
  916. GUID * pCLSID
  917. )
  918. {
  919. DBGOUT((TRCE, "TSPI_lineMSPIdentify dwDeviceID %d", dwDeviceID));
  920. *pCLSID = CLSID_CONFMSP;
  921. DBGOUT((TRCE, "TSPI_lineMSPIdentify succeeded."));
  922. return NOERROR;
  923. }
  924. LONG
  925. TSPIAPI
  926. TSPI_lineNegotiateTSPIVersion(
  927. DWORD dwDeviceID,
  928. DWORD dwLowVersion,
  929. DWORD dwHighVersion,
  930. LPDWORD lpdwTSPIVersion
  931. )
  932. {
  933. DBGOUT((TRCE, "TSPI_lineNegotiateTSPIVersion dwDeviceID %d", dwDeviceID));
  934. LONG lResult = 0;
  935. if (TAPI_CURRENT_VERSION <= dwHighVersion
  936. && TAPI_CURRENT_VERSION >= dwLowVersion)
  937. {
  938. *lpdwTSPIVersion = TAPI_CURRENT_VERSION;
  939. }
  940. else
  941. {
  942. DBGOUT((FAIL, "TSPI_lineNegotiateTSPIVersion failed."));
  943. return LINEERR_INCOMPATIBLEAPIVERSION;
  944. }
  945. DBGOUT((TRCE, "TSPI_lineNegotiateTSPIVersion succeeded. version %x",
  946. TAPI_CURRENT_VERSION));
  947. return NOERROR;
  948. }
  949. LONG
  950. TSPIAPI
  951. TSPI_lineOpen(
  952. DWORD dwDeviceID,
  953. HTAPILINE htLine,
  954. LPHDRVLINE lphdLine,
  955. DWORD dwTSPIVersion,
  956. LINEEVENT lpfnEventProc
  957. )
  958. {
  959. DBGOUT((TRCE, "TSPI_lineOpen dwDiviceID %d", dwDeviceID));
  960. LONG lResult;
  961. if (dwDeviceID != gdwLineDeviceIDBase)
  962. {
  963. DBGOUT((FAIL, "TSPI_lineOpen bad DiviceID %d", dwDeviceID));
  964. return LINEERR_BADDEVICEID;
  965. }
  966. EnterCriticalSection(&gCritSec);
  967. lResult = LINEERR_RESOURCEUNAVAIL;
  968. if (!gLine.bOpened)
  969. {
  970. *lphdLine = (HDRVLINE)IPCONF_LINE_HANDLE;
  971. gLine.bOpened = TRUE;
  972. gLine.htLine = htLine;
  973. gLine.dwNumCalls = 0;
  974. lResult = 0;
  975. }
  976. LeaveCriticalSection(&gCritSec);
  977. DBGOUT((TRCE, "TSPI_lineOpen returns:%d", lResult));
  978. return lResult;
  979. }
  980. LONG
  981. TSPIAPI
  982. TSPI_lineReceiveMSPData(
  983. HDRVLINE hdLine,
  984. HDRVCALL hdCall, // can be NULL
  985. HDRVMSPLINE hdMSPLine, // from lineCreateMSPInstance
  986. LPBYTE pBuffer,
  987. DWORD dwSize
  988. )
  989. {
  990. DBGOUT((TRCE, "TSPI_lineReceiveMSPData hdLine %p", hdLine));
  991. if ((dwSize == 0) || IsBadReadPtr(pBuffer, dwSize))
  992. {
  993. DBGOUT((FAIL, "TSPI_lineReceiveMSPData bad puffer"));
  994. return LINEERR_INVALPOINTER;
  995. }
  996. DWORD dwCall = HandleToUlong(hdCall);
  997. EnterCriticalSection(&gCritSec);
  998. // check the call handle.
  999. if (dwCall >= gpCallList.size() || gpCallList[dwCall] == NULL)
  1000. {
  1001. LeaveCriticalSection(&gCritSec);
  1002. DBGOUT((FAIL, "TSPI_lineReceiveMSPData invalide call handle: %x",
  1003. dwCall));
  1004. return LINEERR_INVALCALLHANDLE;
  1005. }
  1006. MSG_TSPMSPDATA *pData = (MSG_TSPMSPDATA *)pBuffer;
  1007. long lResult = NOERROR;
  1008. switch (pData->command)
  1009. {
  1010. case CALL_CONNECTED:
  1011. // Set the call state to connected.
  1012. gpCallList[dwCall]->SetCallState(
  1013. LINECALLSTATE_CONNECTED,
  1014. LINECONNECTEDMODE_ACTIVE
  1015. );
  1016. DBGOUT((INFO, "call %d state changed to connected", dwCall));
  1017. break;
  1018. case CALL_DISCONNECTED:
  1019. // Set the call state to idel.
  1020. gpCallList[dwCall]->SetCallState(
  1021. LINECALLSTATE_DISCONNECTED,
  1022. LINEDISCONNECTMODE_UNREACHABLE
  1023. );
  1024. DBGOUT((INFO, "call %d state changed to disconnected", dwCall));
  1025. break;
  1026. case CALL_QOS_EVENT:
  1027. (*glpfnLineEventProc)(
  1028. gLine.htLine,
  1029. gpCallList[dwCall]->htCall(),
  1030. LINE_QOSINFO,
  1031. pData->QosEvent.dwEvent,
  1032. pData->QosEvent.dwMediaMode,
  1033. 0
  1034. );
  1035. break;
  1036. default:
  1037. DBGOUT((FAIL, "invalide command: %x", pData->command));
  1038. lResult = LINEERR_OPERATIONFAILED;
  1039. }
  1040. LeaveCriticalSection(&gCritSec);
  1041. DBGOUT((TRCE, "TSPI_lineReceiveMSPData returns:%d", lResult));
  1042. return lResult;
  1043. }
  1044. LONG
  1045. TSPIAPI
  1046. TSPI_lineSetDefaultMediaDetection(
  1047. HDRVLINE hdLine,
  1048. DWORD dwMediaModes
  1049. )
  1050. {
  1051. DBGOUT((TRCE, "TSPI_lineSetDefaultMediaDetection:"));
  1052. return LINEERR_OPERATIONUNAVAIL;
  1053. }
  1054. LONG
  1055. TSPIAPI
  1056. TSPI_lineSetMediaMode(
  1057. HDRVCALL hdCall,
  1058. DWORD dwMediaMode
  1059. )
  1060. {
  1061. DBGOUT((TRCE, "TSPI_lineSetMediaMode:"));
  1062. return LINEERR_OPERATIONUNAVAIL;
  1063. }
  1064. ///////////////////////////////////////////////////////////////////////////////
  1065. // //
  1066. // TSPI_providerXxx functions //
  1067. // //
  1068. ///////////////////////////////////////////////////////////////////////////////
  1069. #if 0 // we dont' need the user name anymore.
  1070. LONG
  1071. TSPIAPI
  1072. TSPI_providerCheckForNewUser(
  1073. IN DWORD dwPermanentProviderID
  1074. )
  1075. /*++
  1076. Routine Description:
  1077. Once a line is opened, it will never be opened twice, even when the user
  1078. logs off and logs on. So we need a way to find out when the user changes.
  1079. That's why this function is added. It only work for single user.
  1080. Everytime a new app starts using tapi, tapisrv will call this function.
  1081. We need to check to see if the user has changed and register the new user
  1082. in the ILS server.
  1083. Arguments:
  1084. NONE.
  1085. Return Values:
  1086. NOERROR always.
  1087. --*/
  1088. {
  1089. DBGOUT((TRCE, "TSPI_providerCheckForNewUser"));
  1090. DWORD dwUserNameLen = MAXUSERNAMELEN;
  1091. CHAR szNewUserName[MAXUSERNAMELEN + 1];
  1092. UNREFERENCED_PARAMETER(dwPermanentProviderID ); // It is me.
  1093. // switch in user's context
  1094. RpcImpersonateClient(0);
  1095. // determine name of current user
  1096. GetUserNameA(szNewUserName, &dwUserNameLen);
  1097. // switch back
  1098. RpcRevertToSelf();
  1099. EnterCriticalSection(&gCritSec);
  1100. lstrcpy(gszUserName, szNewUserName);
  1101. LeaveCriticalSection(&gCritSec);
  1102. DBGOUT((TRCE, "TSPI_providerCheckForNewUser succeeded, new user :%ws",
  1103. gszUserName ));
  1104. return NOERROR;
  1105. }
  1106. #endif
  1107. LONG
  1108. TSPIAPI
  1109. TSPI_providerEnumDevices(
  1110. DWORD dwPermanentProviderID,
  1111. LPDWORD lpdwNumLines,
  1112. LPDWORD lpdwNumPhones,
  1113. HPROVIDER hProvider,
  1114. LINEEVENT lpfnLineCreateProc,
  1115. PHONEEVENT lpfnPhoneCreateProc
  1116. )
  1117. {
  1118. DBGOUT((TRCE, "TSPI_providerEnumDevices"));
  1119. EnterCriticalSection(&gCritSec);
  1120. *lpdwNumLines = IPCONF_NUMLINES;
  1121. *lpdwNumPhones = IPCONF_NUMPHONES;
  1122. // save provider handle
  1123. ghProvider = hProvider;
  1124. // save the callback used in creating new lines.
  1125. glpfnLineEventProc = lpfnLineCreateProc;
  1126. LeaveCriticalSection(&gCritSec);
  1127. DBGOUT((TRCE, "TSPI_providerEnumDevices succeeded."));
  1128. return NOERROR;
  1129. }
  1130. LONG
  1131. TSPIAPI
  1132. TSPI_providerInit(
  1133. DWORD dwTSPIVersion,
  1134. DWORD dwPermanentProviderID,
  1135. DWORD dwLineDeviceIDBase,
  1136. DWORD dwPhoneDeviceIDBase,
  1137. DWORD dwNumLines,
  1138. DWORD dwNumPhones,
  1139. ASYNC_COMPLETION lpfnCompletionProc,
  1140. LPDWORD lpdwTSPIOptions
  1141. )
  1142. {
  1143. DBGOUT((TRCE, "TSPI_providerInit"));
  1144. LONG hr = LINEERR_OPERATIONFAILED;
  1145. EnterCriticalSection(&gCritSec);
  1146. glpfnCompletionProc = lpfnCompletionProc;
  1147. gdwLineDeviceIDBase = dwLineDeviceIDBase;
  1148. gdwPermanentProviderID = dwPermanentProviderID;
  1149. gLine.dwDeviceID = gdwLineDeviceIDBase;
  1150. gLine.bOpened = FALSE;
  1151. LeaveCriticalSection(&gCritSec);
  1152. DBGOUT((TRCE, "TSPI_providerInit succeeded."));
  1153. return NOERROR;
  1154. }
  1155. LONG
  1156. TSPIAPI
  1157. TSPI_providerInstall(
  1158. HWND hwndOwner,
  1159. DWORD dwPermanentProviderID
  1160. )
  1161. {
  1162. DBGOUT((TRCE, "TSPI_providerInstall:"));
  1163. //
  1164. // Although this func is never called by TAPI v2.0, we export
  1165. // it so that the Telephony Control Panel Applet knows that it
  1166. // can add this provider via lineAddProvider(), otherwise
  1167. // Telephon.cpl will not consider it installable
  1168. //
  1169. //
  1170. return NOERROR;
  1171. }
  1172. LONG
  1173. TSPIAPI
  1174. TSPI_providerRemove(
  1175. HWND hwndOwner,
  1176. DWORD dwPermanentProviderID
  1177. )
  1178. {
  1179. //
  1180. // Although this func is never called by TAPI v2.0, we export
  1181. // it so that the Telephony Control Panel Applet knows that it
  1182. // can configure this provider via lineConfigProvider(),
  1183. // otherwise Telephon.cpl will not consider it configurable
  1184. //
  1185. return NOERROR;
  1186. }
  1187. LONG
  1188. TSPIAPI
  1189. TSPI_providerShutdown(
  1190. DWORD dwTSPIVersion,
  1191. DWORD dwPermanentProviderID
  1192. )
  1193. {
  1194. DBGOUT((TRCE, "TSPI_providerShutdown."));
  1195. EnterCriticalSection(&gCritSec);
  1196. // Clean up all the open calls when this provider is shutted down.
  1197. for (DWORD i = 0; i < gpCallList.size(); i++)
  1198. {
  1199. FreeCall(i);
  1200. }
  1201. LeaveCriticalSection(&gCritSec);
  1202. DBGOUT((TRCE, "TSPI_providerShutdown succeeded."));
  1203. return NOERROR;
  1204. }
  1205. LONG
  1206. TSPIAPI
  1207. TSPI_providerUIIdentify(
  1208. LPWSTR lpszUIDLLName
  1209. )
  1210. {
  1211. lstrcpyW(lpszUIDLLName, gszUIDLLName);
  1212. return NOERROR;
  1213. }
  1214. LONG
  1215. TSPIAPI
  1216. TUISPI_providerRemove(
  1217. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  1218. HWND hwndOwner,
  1219. DWORD dwPermanentProviderID
  1220. )
  1221. {
  1222. DBGOUT((TRCE, "TUISPI_providerInstall"));
  1223. return NOERROR;
  1224. }
  1225. LONG
  1226. TSPIAPI
  1227. TUISPI_providerInstall(
  1228. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  1229. HWND hwndOwner,
  1230. DWORD dwPermanentProviderID
  1231. )
  1232. {
  1233. DBGOUT((TRCE, "TUISPI_providerInstall"));
  1234. const CHAR szKey[] =
  1235. "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers";
  1236. HKEY hKey;
  1237. DWORD dwDataSize, dwDataType;
  1238. DWORD dwNumProviders;
  1239. CHAR szName[IPCONF_BUFSIZE + 1], szPath[IPCONF_BUFSIZE + 1];
  1240. // open the providers key
  1241. if (RegOpenKeyEx(
  1242. HKEY_LOCAL_MACHINE,
  1243. szKey,
  1244. 0,
  1245. KEY_READ,
  1246. &hKey
  1247. ) == ERROR_SUCCESS)
  1248. {
  1249. // first get the number of providers installed.
  1250. dwDataSize = sizeof(DWORD);
  1251. if (RegQueryValueEx(
  1252. hKey,
  1253. "NumProviders",
  1254. 0,
  1255. &dwDataType,
  1256. (LPBYTE) &dwNumProviders,
  1257. &dwDataSize
  1258. ) != ERROR_SUCCESS)
  1259. {
  1260. RegCloseKey (hKey);
  1261. return LINEERR_UNINITIALIZED;
  1262. }
  1263. // then go through the list of providers to see if
  1264. // we are already installed.
  1265. for (DWORD i = 0; i < dwNumProviders; i ++)
  1266. {
  1267. wsprintf(szName, "ProviderFileName%d", i);
  1268. dwDataSize = sizeof(szPath);
  1269. if (RegQueryValueEx(
  1270. hKey,
  1271. szName,
  1272. 0,
  1273. &dwDataType,
  1274. (LPBYTE) &szPath,
  1275. &dwDataSize
  1276. ) != ERROR_SUCCESS)
  1277. {
  1278. RegCloseKey (hKey);
  1279. return LINEERR_UNINITIALIZED;
  1280. }
  1281. _strupr(szPath);
  1282. if (strstr(szPath, "IPCONF") != NULL)
  1283. {
  1284. RegCloseKey (hKey);
  1285. // found, we don't want to be installed twice.
  1286. return LINEERR_NOMULTIPLEINSTANCE;
  1287. }
  1288. }
  1289. RegCloseKey (hKey);
  1290. return NOERROR;
  1291. }
  1292. return LINEERR_UNINITIALIZED;
  1293. }