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.

1628 lines
43 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. (ULONG_PTR)(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. (ULONG_PTR)(&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_PTR &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. DisableThreadLibraryCalls(hDLL);
  321. g_hInstance = hDLL;
  322. #if 0 // we dont' need the user name anymore.
  323. // switch in user's context
  324. RpcImpersonateClient(0);
  325. // determine name of current user
  326. GetUserNameA(gszUserName, &dwUserNameLen);
  327. // switch back
  328. RpcRevertToSelf();
  329. #endif
  330. // Initialize critical sections.
  331. __try
  332. {
  333. InitializeCriticalSection(&gCritSec);
  334. }
  335. __except (EXCEPTION_EXECUTE_HANDLER)
  336. {
  337. return FALSE;
  338. }
  339. break;
  340. case DLL_PROCESS_DETACH:
  341. DeleteCriticalSection(&gCritSec);
  342. break;
  343. } // switch
  344. return TRUE;
  345. }
  346. //
  347. // We get a slough of C4047 (different levels of indrection) warnings down
  348. // below in the initialization of FUNC_PARAM structs as a result of the
  349. // real func prototypes having params that are types other than DWORDs,
  350. // so since these are known non-interesting warnings just turn them off
  351. //
  352. #pragma warning (disable:4047)
  353. ///////////////////////////////////////////////////////////////////////////////
  354. // //
  355. // TSPI_lineXxx functions //
  356. // //
  357. ///////////////////////////////////////////////////////////////////////////////
  358. LONG
  359. TSPIAPI
  360. TSPI_lineClose(
  361. HDRVLINE hdLine
  362. )
  363. {
  364. DBGOUT((TRCE, "TSPI_lineClose, hdLine %p", hdLine));
  365. DWORD dwLine = HandleToUlong(hdLine);
  366. if (dwLine != IPCONF_LINE_HANDLE)
  367. {
  368. DBGOUT((FAIL, "invalide line handle, hdLine %p", hdLine));
  369. return LINEERR_INVALLINEHANDLE;
  370. }
  371. EnterCriticalSection(&gCritSec);
  372. // Clean up all the open calls when this line is closed.
  373. for (DWORD i = 0; i < gpCallList.size(); i++)
  374. {
  375. if ((gpCallList[i] != NULL))
  376. {
  377. FreeCall(i);
  378. }
  379. }
  380. gLine.bOpened = FALSE;
  381. LeaveCriticalSection(&gCritSec);
  382. DBGOUT((TRCE, "TSPI_lineClose succeeded."));
  383. return NOERROR;
  384. }
  385. LONG
  386. TSPIAPI
  387. TSPI_lineCloseCall(
  388. HDRVCALL hdCall
  389. )
  390. {
  391. DBGOUT((TRCE, "TSPI_lineCloseCall, hdCall %p", hdCall));
  392. DWORD dwCall = HandleToUlong(hdCall);
  393. EnterCriticalSection(&gCritSec);
  394. if (dwCall >= gpCallList.size())
  395. {
  396. LeaveCriticalSection(&gCritSec);
  397. DBGOUT((FAIL, "TSPI_lineCloseCall invalid call handle: %p", hdCall));
  398. return LINEERR_INVALCALLHANDLE;
  399. }
  400. FreeCall(dwCall);
  401. LeaveCriticalSection(&gCritSec);
  402. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  403. return NOERROR;
  404. }
  405. LONG
  406. TSPIAPI
  407. TSPI_lineCreateMSPInstance(
  408. HDRVLINE hdLine,
  409. DWORD dwAddressID,
  410. HTAPIMSPLINE htMSPLine,
  411. LPHDRVMSPLINE phdMSPLine
  412. )
  413. {
  414. DBGOUT((TRCE, "TSPI_lineCreateMSPInstance"));
  415. if (IsBadWritePtr(phdMSPLine, sizeof (HDRVMSPLINE)))
  416. {
  417. DBGOUT((FAIL, "TSPI_lineCreateMSPInstance bad pointer"));
  418. return LINEERR_INVALPOINTER;
  419. }
  420. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  421. {
  422. DBGOUT((FAIL, "TSPI_lineCreateMSPInstance, bad line handle:%p", hdLine));
  423. return LINEERR_INVALLINEHANDLE;
  424. }
  425. EnterCriticalSection(&gCritSec);
  426. // We are not keeping the msp handles. Just fake a handle here.
  427. *phdMSPLine = (HDRVMSPLINE)(gLine.dwNextMSPHandle ++);
  428. LeaveCriticalSection(&gCritSec);
  429. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  430. return (NOERROR);
  431. }
  432. LONG
  433. TSPIAPI
  434. TSPI_lineCloseMSPInstance(
  435. HDRVMSPLINE hdMSPLine
  436. )
  437. {
  438. DBGOUT((TRCE, "TSPI_lineCloseMSPInstance, hdMSPLine %p", hdMSPLine));
  439. DBGOUT((TRCE, "TSPI_lineCloseCall succeeded"));
  440. return NOERROR;
  441. }
  442. LONG
  443. TSPIAPI
  444. TSPI_lineDrop(
  445. DRV_REQUESTID dwRequestID,
  446. HDRVCALL hdCall,
  447. LPCSTR lpsUserUserInfo,
  448. DWORD dwSize
  449. )
  450. {
  451. DBGOUT((TRCE, "TSPI_lineDrop, hdCall %p", hdCall));
  452. DWORD dwCall = HandleToUlong(hdCall);
  453. EnterCriticalSection(&gCritSec);
  454. // check the call handle.
  455. if (dwCall >= gpCallList.size())
  456. {
  457. LeaveCriticalSection(&gCritSec);
  458. (*glpfnCompletionProc)(dwRequestID, LINEERR_INVALCALLHANDLE);
  459. DBGOUT((FAIL, "TSPI_lineDrop invalid call handle %p", hdCall));
  460. return dwRequestID;
  461. }
  462. CALL *pCall = gpCallList[dwCall];
  463. if (pCall != NULL)
  464. {
  465. pCall->SetCallState(LINECALLSTATE_IDLE, 0);
  466. pCall->SendMSPStopMessage();
  467. DBGOUT((INFO, "call %d state changed to idle", dwCall));
  468. }
  469. LeaveCriticalSection(&gCritSec);
  470. (*glpfnCompletionProc)(dwRequestID, 0);
  471. DBGOUT((TRCE, "TSPI_lineDrop succeeded"));
  472. return dwRequestID;
  473. }
  474. LONG
  475. TSPIAPI
  476. TSPI_lineGetAddressCaps(
  477. DWORD dwDeviceID,
  478. DWORD dwAddressID,
  479. DWORD dwTSPIVersion,
  480. DWORD dwExtVersion,
  481. LPLINEADDRESSCAPS lpAddressCaps
  482. )
  483. {
  484. DBGOUT((TRCE, "TSPI_lineGetAddressCaps"));
  485. if (dwDeviceID != gdwLineDeviceIDBase)
  486. {
  487. DBGOUT((TRCE, "TSPI_lineGetAddressCaps bad device id: %d", dwDeviceID));
  488. return LINEERR_BADDEVICEID;
  489. }
  490. // Check the address ID.
  491. if (dwAddressID != 0)
  492. {
  493. DBGOUT((TRCE, "TSPI_lineGetAddressCaps bad address id: %d", dwAddressID));
  494. return LINEERR_INVALADDRESSID;
  495. }
  496. // load the address name from the string table.
  497. WCHAR szAddressName[IPCONF_BUFSIZE + 1];
  498. if (0 == LoadStringW(g_hInstance, IDS_IPCONFADDRESSNAME, szAddressName, IPCONF_BUFSIZE))
  499. {
  500. szAddressName[0] = L'\0';
  501. }
  502. DWORD dwAddressSize = (lstrlenW(szAddressName) + 1) * (sizeof WCHAR);
  503. lpAddressCaps->dwNeededSize = sizeof(LINEADDRESSCAPS) + dwAddressSize;
  504. if (lpAddressCaps->dwTotalSize >= lpAddressCaps->dwNeededSize)
  505. {
  506. // Copy the IP address to the end of the structure.
  507. lpAddressCaps->dwUsedSize = lpAddressCaps->dwNeededSize;
  508. lpAddressCaps->dwAddressSize = dwAddressSize;
  509. lpAddressCaps->dwAddressOffset = sizeof(LINEADDRESSCAPS);
  510. lstrcpyW ((WCHAR *)(lpAddressCaps + 1), szAddressName);
  511. }
  512. else
  513. {
  514. lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS);
  515. }
  516. lpAddressCaps->dwLineDeviceID = dwDeviceID;
  517. lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
  518. lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_MEDIAMODE;
  519. lpAddressCaps->dwCallerIDFlags =
  520. lpAddressCaps->dwCalledIDFlags =
  521. lpAddressCaps->dwConnectedIDFlags =
  522. lpAddressCaps->dwRedirectionIDFlags =
  523. lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  524. lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
  525. LINECALLSTATE_DIALING |
  526. LINECALLSTATE_CONNECTED;
  527. lpAddressCaps->dwDialToneModes = 0;
  528. lpAddressCaps->dwBusyModes = 0;
  529. lpAddressCaps->dwSpecialInfo = 0;
  530. lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_NORMAL |
  531. LINEDISCONNECTMODE_UNAVAIL;
  532. lpAddressCaps->dwMaxNumActiveCalls = MAXCALLSPERADDRESS;
  533. lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_DIALED |
  534. LINEADDRCAPFLAGS_ORIGOFFHOOK;
  535. lpAddressCaps->dwCallFeatures = LINECALLFEATURE_DROP |
  536. LINECALLFEATURE_SETQOS;
  537. lpAddressCaps->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
  538. DBGOUT((TRCE, "TSPI_lineGetAddressCaps succeeded."));
  539. return NOERROR;
  540. }
  541. LONG
  542. TSPIAPI
  543. TSPI_lineGetAddressID(
  544. HDRVLINE hdLine,
  545. LPDWORD lpdwAddressID,
  546. DWORD dwAddressMode,
  547. LPCWSTR lpsAddress,
  548. DWORD dwSize
  549. )
  550. {
  551. DBGOUT((TRCE, "TSPI_lineGetAddressID htLine:%p", hdLine));
  552. *lpdwAddressID = 0;
  553. DBGOUT((TRCE, "TSPI_lineGetAddressID succeeded."));
  554. return NOERROR;
  555. }
  556. LONG
  557. TSPIAPI
  558. TSPI_lineGetAddressStatus(
  559. HDRVLINE hdLine,
  560. DWORD dwAddressID,
  561. LPLINEADDRESSSTATUS lpAddressStatus
  562. )
  563. {
  564. DBGOUT((TRCE, "TSPI_lineGetAddressStatus htLine:%p", hdLine));
  565. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  566. {
  567. DBGOUT((FAIL, "TSPI_lineGetAddressStatus htLine:%p", hdLine));
  568. return LINEERR_INVALLINEHANDLE;
  569. }
  570. lpAddressStatus->dwNeededSize =
  571. lpAddressStatus->dwUsedSize = sizeof(LINEADDRESSSTATUS);
  572. EnterCriticalSection(&gCritSec);
  573. lpAddressStatus->dwNumActiveCalls = gLine.dwNumCalls;
  574. LeaveCriticalSection(&gCritSec);
  575. lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
  576. DBGOUT((TRCE, "TSPI_lineGetAddressStatus succeeded."));
  577. return NOERROR;
  578. }
  579. LONG
  580. TSPIAPI
  581. TSPI_lineGetCallAddressID(
  582. HDRVCALL hdCall,
  583. LPDWORD lpdwAddressID
  584. )
  585. {
  586. DBGOUT((TRCE, "TSPI_lineGetCallAddressID hdCall %p", hdCall));
  587. //
  588. // We only support 1 address (id=0) per line
  589. //
  590. *lpdwAddressID = 0;
  591. DBGOUT((TRCE, "TSPI_lineGetCallAddressID succeeded."));
  592. return NOERROR;
  593. }
  594. LONG
  595. TSPIAPI
  596. TSPI_lineGetCallInfo(
  597. HDRVCALL hdCall,
  598. LPLINECALLINFO lpLineInfo
  599. )
  600. {
  601. DBGOUT((TRCE, "TSPI_lineGetCallInfo hdCall %p", hdCall));
  602. DWORD dwCall = HandleToUlong(hdCall);
  603. EnterCriticalSection(&gCritSec);
  604. if (dwCall >= gpCallList.size())
  605. {
  606. LeaveCriticalSection(&gCritSec);
  607. DBGOUT((FAIL, "TSPI_lineGetCallInfo bad call handle %p", hdCall));
  608. return LINEERR_INVALCALLHANDLE;
  609. }
  610. // get the call object.
  611. CALL *pCall = gpCallList[dwCall];
  612. if (pCall == NULL)
  613. {
  614. LeaveCriticalSection(&gCritSec);
  615. DBGOUT((FAIL, "TSPI_lineGetCallInfo bad call handle %p", hdCall));
  616. return LINEERR_INVALCALLHANDLE;
  617. }
  618. lpLineInfo->dwMediaMode = pCall->dwMediaMode();
  619. LeaveCriticalSection(&gCritSec);
  620. lpLineInfo->dwLineDeviceID = gLine.dwDeviceID;
  621. lpLineInfo->dwAddressID = 0; // There is only on address per line.
  622. lpLineInfo->dwBearerMode = IPCONF_BEARERMODES;
  623. lpLineInfo->dwCallStates = LINECALLSTATE_IDLE |
  624. LINECALLSTATE_DIALING |
  625. LINECALLSTATE_CONNECTED;
  626. lpLineInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
  627. lpLineInfo->dwReason = LINECALLREASON_DIRECT;
  628. lpLineInfo->dwCallerIDFlags =
  629. lpLineInfo->dwCalledIDFlags =
  630. lpLineInfo->dwConnectedIDFlags =
  631. lpLineInfo->dwRedirectionIDFlags =
  632. lpLineInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  633. DBGOUT((TRCE, "TSPI_lineGetCallInfo succeeded."));
  634. return NOERROR;
  635. }
  636. LONG
  637. TSPIAPI
  638. TSPI_lineGetCallStatus(
  639. HDRVCALL hdCall,
  640. LPLINECALLSTATUS lpLineStatus
  641. )
  642. {
  643. DBGOUT((TRCE, "TSPI_lineGetCallStatus hdCall %p", hdCall));
  644. DWORD dwCall = HandleToUlong(hdCall);
  645. EnterCriticalSection(&gCritSec);
  646. // check the call handle.
  647. if (dwCall >= gpCallList.size())
  648. {
  649. LeaveCriticalSection(&gCritSec);
  650. DBGOUT((TRCE, "TSPI_lineGetCallStatus bad call handle %p", hdCall));
  651. return LINEERR_INVALCALLHANDLE;
  652. }
  653. lpLineStatus->dwNeededSize =
  654. lpLineStatus->dwUsedSize = sizeof(LINECALLSTATUS);
  655. lpLineStatus->dwCallState = gpCallList[dwCall]->dwState();
  656. if (lpLineStatus->dwCallState != LINECALLSTATE_IDLE)
  657. {
  658. lpLineStatus->dwCallFeatures = LINECALLFEATURE_DROP |
  659. LINECALLFEATURE_SETQOS;
  660. }
  661. LeaveCriticalSection(&gCritSec);
  662. DBGOUT((TRCE, "TSPI_lineGetCallStatus succeeded."));
  663. return NOERROR;
  664. }
  665. LONG
  666. TSPIAPI
  667. TSPI_lineGetDevCaps(
  668. DWORD dwDeviceID,
  669. DWORD dwTSPIVersion,
  670. DWORD dwExtVersion,
  671. LPLINEDEVCAPS lpLineDevCaps
  672. )
  673. {
  674. DBGOUT((TRCE, "TSPI_lineGetDevCaps"));
  675. if (dwDeviceID != gdwLineDeviceIDBase)
  676. {
  677. DBGOUT((FAIL, "TSPI_lineGetDevCaps bad device id %d", dwDeviceID));
  678. return LINEERR_BADDEVICEID;
  679. }
  680. DWORD dwProviderInfoSize;
  681. DWORD dwLineNameSize;
  682. DWORD dwDevSpecificSize;
  683. DWORD dwOffset;
  684. // load the name of the service provider from the string table.
  685. WCHAR szProviderInfo[IPCONF_BUFSIZE + 1];
  686. if (0 == LoadStringW(g_hInstance, IDS_IPCONFPROVIDERNAME, szProviderInfo, IPCONF_BUFSIZE))
  687. {
  688. szProviderInfo[0] = L'\0';
  689. }
  690. dwProviderInfoSize = (lstrlenW(szProviderInfo) + 1) * sizeof(WCHAR);
  691. // load the line name format from the string table and print the line name.
  692. WCHAR szLineName[IPCONF_BUFSIZE + 1];
  693. if (0 == LoadStringW(g_hInstance, IDS_IPCONFLINENAME, szLineName, IPCONF_BUFSIZE))
  694. {
  695. szLineName[0] = L'\0';
  696. }
  697. dwLineNameSize = (lstrlenW(szLineName) + 1) * (sizeof WCHAR);
  698. lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS)
  699. + dwProviderInfoSize
  700. + dwLineNameSize;
  701. if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwNeededSize)
  702. {
  703. lpLineDevCaps->dwUsedSize = lpLineDevCaps->dwNeededSize;
  704. CHAR *pChar;
  705. pChar = (CHAR *)(lpLineDevCaps + 1);
  706. dwOffset = sizeof(LINEDEVCAPS);
  707. // fill in the provider info.
  708. lpLineDevCaps->dwProviderInfoSize = dwProviderInfoSize;
  709. lpLineDevCaps->dwProviderInfoOffset = dwOffset;
  710. lstrcpyW ((WCHAR *)pChar, szProviderInfo);
  711. pChar += dwProviderInfoSize;
  712. dwOffset += dwProviderInfoSize;
  713. // fill in the name of the line.
  714. lpLineDevCaps->dwLineNameSize = dwLineNameSize;
  715. lpLineDevCaps->dwLineNameOffset = dwOffset;
  716. lstrcpyW ((WCHAR *)pChar, szLineName);
  717. }
  718. else
  719. {
  720. lpLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS);
  721. }
  722. // We don't have really "Permanent" line ids. So just fake one here.
  723. lpLineDevCaps->dwPermanentLineID =
  724. ((gdwPermanentProviderID & 0xffff) << 16) |
  725. ((dwDeviceID - gdwLineDeviceIDBase) & 0xffff);
  726. CopyMemory(
  727. &(lpLineDevCaps->PermanentLineGuid),
  728. &GUID_LINE,
  729. sizeof(GUID)
  730. );
  731. lpLineDevCaps->PermanentLineGuid.Data1 += dwDeviceID - gdwLineDeviceIDBase;
  732. lpLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
  733. lpLineDevCaps->dwAddressModes = IPCONF_ADDRESSMODES;
  734. lpLineDevCaps->dwNumAddresses = IPCONF_NUMADDRESSESPERLINE;
  735. lpLineDevCaps->dwBearerModes = IPCONF_BEARERMODES;
  736. lpLineDevCaps->dwMediaModes = IPCONF_MEDIAMODES;
  737. lpLineDevCaps->dwMaxRate = (1 << 20);
  738. lpLineDevCaps->dwAddressTypes = LINEADDRESSTYPE_SDP;
  739. lpLineDevCaps->dwDevCapFlags =
  740. LINEDEVCAPFLAGS_CLOSEDROP
  741. | LINEDEVCAPFLAGS_MSP
  742. | LINEDEVCAPFLAGS_LOCAL;
  743. lpLineDevCaps->dwMaxNumActiveCalls =
  744. MAXCALLSPERADDRESS * IPCONF_NUMADDRESSESPERLINE;
  745. lpLineDevCaps->dwRingModes = 0;
  746. lpLineDevCaps->dwLineFeatures = LINEFEATURE_MAKECALL;
  747. CopyMemory(
  748. &(lpLineDevCaps->ProtocolGuid),
  749. &TAPIPROTOCOL_Multicast,
  750. sizeof(GUID)
  751. );
  752. DBGOUT((TRCE, "TSPI_lineGetDevCaps succeeded."));
  753. return NOERROR;
  754. }
  755. LONG
  756. TSPIAPI
  757. TSPI_lineGetIcon(
  758. DWORD dwDeviceID,
  759. LPCWSTR lpgszDeviceClass,
  760. LPHICON lphIcon
  761. )
  762. {
  763. DBGOUT((TRCE, "TSPI_lineGetIcon:"));
  764. return LINEERR_OPERATIONUNAVAIL;
  765. }
  766. LONG
  767. TSPIAPI
  768. TSPI_lineGetID(
  769. HDRVLINE hdLine,
  770. DWORD dwAddressID,
  771. HDRVCALL hdCall,
  772. DWORD dwSelect,
  773. LPVARSTRING lpDeviceID,
  774. LPCWSTR lpgszDeviceClass,
  775. HANDLE hTargetProcess
  776. )
  777. {
  778. DBGOUT((TRCE, "TSPI_lineGetID:"));
  779. return LINEERR_OPERATIONUNAVAIL;
  780. }
  781. LONG
  782. TSPIAPI
  783. TSPI_lineGetLineDevStatus(
  784. HDRVLINE hdLine,
  785. LPLINEDEVSTATUS lpLineDevStatus
  786. )
  787. {
  788. DBGOUT((TRCE, "TSPI_lineGetLineDevStatus %p", hdLine));
  789. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  790. {
  791. DBGOUT((FAIL, "TSPI_lineGetLineDevStatus bad line handle %p", hdLine));
  792. return LINEERR_INVALLINEHANDLE;
  793. }
  794. lpLineDevStatus->dwUsedSize =
  795. lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
  796. EnterCriticalSection(&gCritSec);
  797. lpLineDevStatus->dwNumActiveCalls = gLine.dwNumCalls;
  798. LeaveCriticalSection(&gCritSec);
  799. lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL;
  800. lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
  801. LINEDEVSTATUSFLAGS_INSERVICE;
  802. DBGOUT((TRCE, "TSPI_lineGetLineDevStatus succeeded"));
  803. return NOERROR;
  804. }
  805. LONG
  806. TSPIAPI
  807. TSPI_lineGetNumAddressIDs(
  808. HDRVLINE hdLine,
  809. LPDWORD lpdwNumAddressIDs
  810. )
  811. {
  812. DBGOUT((TRCE, "TSPI_lineGetNumAddressIDs"));
  813. *lpdwNumAddressIDs = IPCONF_NUMADDRESSESPERLINE;
  814. DBGOUT((TRCE, "TSPI_lineGetNumAddressIDs succeeded."));
  815. return NOERROR;
  816. }
  817. LONG
  818. TSPIAPI
  819. TSPI_lineMakeCall(
  820. DRV_REQUESTID dwRequestID,
  821. HDRVLINE hdLine,
  822. HTAPICALL htCall,
  823. LPHDRVCALL lphdCall,
  824. LPCWSTR lpszDestAddress,
  825. DWORD dwCountryCode,
  826. LPLINECALLPARAMS const lpCallParams
  827. )
  828. {
  829. DBGOUT((TRCE, "TSPI_lineMakeCall hdLine %p, htCall %p",
  830. hdLine, htCall));
  831. // check the line handle.
  832. if (HandleToUlong(hdLine) != IPCONF_LINE_HANDLE)
  833. {
  834. DBGOUT((FAIL, "TSPI_lineMakeCall Bad line handle %p", hdLine));
  835. return LINEERR_INVALLINEHANDLE;
  836. }
  837. LONG lResult;
  838. if ((lResult = CheckCallParams(lpCallParams)) != NOERROR)
  839. {
  840. DBGOUT((FAIL, "TSPI_lineMakeCall Bad call params"));
  841. return lResult;
  842. }
  843. // check the destination address.
  844. if (lpszDestAddress == NULL || lstrlenW(lpszDestAddress) == 0)
  845. {
  846. DBGOUT((FAIL, "TSPI_lineMakeCall invalid address."));
  847. return LINEERR_INVALADDRESS;
  848. }
  849. DBGOUT((TRCE, "TSPI_lineMakeCall making call to %ws", lpszDestAddress));
  850. // check the line handle.
  851. EnterCriticalSection(&gCritSec);
  852. // create a call object.
  853. CALL * pCall = (CALL *)MemAlloc(sizeof(CALL));
  854. if (pCall == NULL)
  855. {
  856. LeaveCriticalSection(&gCritSec);
  857. DBGOUT((FAIL, "out of memory for a new call"));
  858. return LINEERR_NOMEM;
  859. }
  860. if (pCall->Init(
  861. htCall,
  862. lpCallParams
  863. ) != NOERROR)
  864. {
  865. MemFree(pCall);
  866. LeaveCriticalSection(&gCritSec);
  867. DBGOUT((FAIL, "out of memory in init a new call"));
  868. return LINEERR_NOMEM;
  869. }
  870. // add the call into the call list.
  871. DWORD_PTR hdCall;
  872. if (!FindFreeCallSlot(hdCall))
  873. {
  874. LeaveCriticalSection(&gCritSec);
  875. MemFree(pCall);
  876. DBGOUT((FAIL, "out of memory finding a new slot"));
  877. return LINEERR_NOMEM;
  878. }
  879. gpCallList[(ULONG)hdCall] = pCall;
  880. // Increament the call count for the line and the provider.
  881. gLine.dwNumCalls ++;
  882. gdwNumCallsInUse ++;
  883. // Complete the request and set the initial call state.
  884. (*glpfnCompletionProc)(dwRequestID, lResult);
  885. *lphdCall = (HDRVCALL)(hdCall);
  886. // Send the MSP a message about this call. It has the SDP in it.
  887. lResult = pCall->SendMSPStartMessage(lpszDestAddress);
  888. if (lResult == NOERROR)
  889. {
  890. // Set the call state to dialing.
  891. pCall->SetCallState(
  892. LINECALLSTATE_DIALING,
  893. 0
  894. );
  895. DBGOUT((INFO, "call %d state changed to dialing", hdCall));
  896. }
  897. else
  898. {
  899. DBGOUT((FAIL, "send MSP message failed, err:%x", lResult));
  900. // Set the call state to idel.
  901. pCall->SetCallState(
  902. LINECALLSTATE_DISCONNECTED,
  903. LINEDISCONNECTMODE_UNREACHABLE
  904. );
  905. DBGOUT((INFO, "call %d state changed to disconnected", hdCall));
  906. }
  907. LeaveCriticalSection(&gCritSec);
  908. DBGOUT((TRCE, "TSPI_lineMakeCall succeeded."));
  909. return dwRequestID;
  910. }
  911. LONG
  912. TSPIAPI
  913. TSPI_lineMSPIdentify(
  914. DWORD dwDeviceID,
  915. GUID * pCLSID
  916. )
  917. {
  918. DBGOUT((TRCE, "TSPI_lineMSPIdentify dwDeviceID %d", dwDeviceID));
  919. *pCLSID = CLSID_CONFMSP;
  920. DBGOUT((TRCE, "TSPI_lineMSPIdentify succeeded."));
  921. return NOERROR;
  922. }
  923. LONG
  924. TSPIAPI
  925. TSPI_lineNegotiateTSPIVersion(
  926. DWORD dwDeviceID,
  927. DWORD dwLowVersion,
  928. DWORD dwHighVersion,
  929. LPDWORD lpdwTSPIVersion
  930. )
  931. {
  932. DBGOUT((TRCE, "TSPI_lineNegotiateTSPIVersion dwDeviceID %d", dwDeviceID));
  933. LONG lResult = 0;
  934. if (TAPI_CURRENT_VERSION <= dwHighVersion
  935. && TAPI_CURRENT_VERSION >= dwLowVersion)
  936. {
  937. *lpdwTSPIVersion = TAPI_CURRENT_VERSION;
  938. }
  939. else
  940. {
  941. DBGOUT((FAIL, "TSPI_lineNegotiateTSPIVersion failed."));
  942. return LINEERR_INCOMPATIBLEAPIVERSION;
  943. }
  944. DBGOUT((TRCE, "TSPI_lineNegotiateTSPIVersion succeeded. version %x",
  945. TAPI_CURRENT_VERSION));
  946. return NOERROR;
  947. }
  948. LONG
  949. TSPIAPI
  950. TSPI_lineOpen(
  951. DWORD dwDeviceID,
  952. HTAPILINE htLine,
  953. LPHDRVLINE lphdLine,
  954. DWORD dwTSPIVersion,
  955. LINEEVENT lpfnEventProc
  956. )
  957. {
  958. DBGOUT((TRCE, "TSPI_lineOpen dwDiviceID %d", dwDeviceID));
  959. LONG lResult;
  960. if (dwDeviceID != gdwLineDeviceIDBase)
  961. {
  962. DBGOUT((FAIL, "TSPI_lineOpen bad DiviceID %d", dwDeviceID));
  963. return LINEERR_BADDEVICEID;
  964. }
  965. EnterCriticalSection(&gCritSec);
  966. lResult = LINEERR_RESOURCEUNAVAIL;
  967. if (!gLine.bOpened)
  968. {
  969. *lphdLine = (HDRVLINE)IPCONF_LINE_HANDLE;
  970. gLine.bOpened = TRUE;
  971. gLine.htLine = htLine;
  972. gLine.dwNumCalls = 0;
  973. lResult = 0;
  974. }
  975. LeaveCriticalSection(&gCritSec);
  976. DBGOUT((TRCE, "TSPI_lineOpen returns:%d", lResult));
  977. return lResult;
  978. }
  979. LONG
  980. TSPIAPI
  981. TSPI_lineReceiveMSPData(
  982. HDRVLINE hdLine,
  983. HDRVCALL hdCall, // can be NULL
  984. HDRVMSPLINE hdMSPLine, // from lineCreateMSPInstance
  985. LPBYTE pBuffer,
  986. DWORD dwSize
  987. )
  988. {
  989. DBGOUT((TRCE, "TSPI_lineReceiveMSPData hdLine %p", hdLine));
  990. if ((dwSize == 0) || IsBadReadPtr(pBuffer, dwSize))
  991. {
  992. DBGOUT((FAIL, "TSPI_lineReceiveMSPData bad puffer"));
  993. return LINEERR_INVALPOINTER;
  994. }
  995. DWORD dwCall = HandleToUlong(hdCall);
  996. EnterCriticalSection(&gCritSec);
  997. // check the call handle.
  998. if (dwCall >= gpCallList.size() || gpCallList[dwCall] == NULL)
  999. {
  1000. LeaveCriticalSection(&gCritSec);
  1001. DBGOUT((FAIL, "TSPI_lineReceiveMSPData invalide call handle: %x",
  1002. dwCall));
  1003. return LINEERR_INVALCALLHANDLE;
  1004. }
  1005. MSG_TSPMSPDATA *pData = (MSG_TSPMSPDATA *)pBuffer;
  1006. long lResult = NOERROR;
  1007. switch (pData->command)
  1008. {
  1009. case CALL_CONNECTED:
  1010. // Set the call state to connected.
  1011. gpCallList[dwCall]->SetCallState(
  1012. LINECALLSTATE_CONNECTED,
  1013. LINECONNECTEDMODE_ACTIVE
  1014. );
  1015. DBGOUT((INFO, "call %d state changed to connected", dwCall));
  1016. break;
  1017. case CALL_DISCONNECTED:
  1018. // Set the call state to idel.
  1019. gpCallList[dwCall]->SetCallState(
  1020. LINECALLSTATE_DISCONNECTED,
  1021. LINEDISCONNECTMODE_UNREACHABLE
  1022. );
  1023. DBGOUT((INFO, "call %d state changed to disconnected", dwCall));
  1024. break;
  1025. case CALL_QOS_EVENT:
  1026. (*glpfnLineEventProc)(
  1027. gLine.htLine,
  1028. gpCallList[dwCall]->htCall(),
  1029. LINE_QOSINFO,
  1030. pData->QosEvent.dwEvent,
  1031. pData->QosEvent.dwMediaMode,
  1032. 0
  1033. );
  1034. break;
  1035. default:
  1036. DBGOUT((FAIL, "invalide command: %x", pData->command));
  1037. lResult = LINEERR_OPERATIONFAILED;
  1038. }
  1039. LeaveCriticalSection(&gCritSec);
  1040. DBGOUT((TRCE, "TSPI_lineReceiveMSPData returns:%d", lResult));
  1041. return lResult;
  1042. }
  1043. LONG
  1044. TSPIAPI
  1045. TSPI_lineSetDefaultMediaDetection(
  1046. HDRVLINE hdLine,
  1047. DWORD dwMediaModes
  1048. )
  1049. {
  1050. DBGOUT((TRCE, "TSPI_lineSetDefaultMediaDetection:"));
  1051. return LINEERR_OPERATIONUNAVAIL;
  1052. }
  1053. LONG
  1054. TSPIAPI
  1055. TSPI_lineSetMediaMode(
  1056. HDRVCALL hdCall,
  1057. DWORD dwMediaMode
  1058. )
  1059. {
  1060. DBGOUT((TRCE, "TSPI_lineSetMediaMode:"));
  1061. return LINEERR_OPERATIONUNAVAIL;
  1062. }
  1063. ///////////////////////////////////////////////////////////////////////////////
  1064. // //
  1065. // TSPI_providerXxx functions //
  1066. // //
  1067. ///////////////////////////////////////////////////////////////////////////////
  1068. #if 0 // we dont' need the user name anymore.
  1069. LONG
  1070. TSPIAPI
  1071. TSPI_providerCheckForNewUser(
  1072. IN DWORD dwPermanentProviderID
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. Once a line is opened, it will never be opened twice, even when the user
  1077. logs off and logs on. So we need a way to find out when the user changes.
  1078. That's why this function is added. It only work for single user.
  1079. Everytime a new app starts using tapi, tapisrv will call this function.
  1080. We need to check to see if the user has changed and register the new user
  1081. in the ILS server.
  1082. Arguments:
  1083. NONE.
  1084. Return Values:
  1085. NOERROR always.
  1086. --*/
  1087. {
  1088. DBGOUT((TRCE, "TSPI_providerCheckForNewUser"));
  1089. DWORD dwUserNameLen = MAXUSERNAMELEN;
  1090. CHAR szNewUserName[MAXUSERNAMELEN + 1];
  1091. UNREFERENCED_PARAMETER(dwPermanentProviderID ); // It is me.
  1092. // switch in user's context
  1093. RpcImpersonateClient(0);
  1094. // determine name of current user
  1095. GetUserNameA(szNewUserName, &dwUserNameLen);
  1096. // switch back
  1097. RpcRevertToSelf();
  1098. EnterCriticalSection(&gCritSec);
  1099. lstrcpy(gszUserName, szNewUserName);
  1100. LeaveCriticalSection(&gCritSec);
  1101. DBGOUT((TRCE, "TSPI_providerCheckForNewUser succeeded, new user :%ws",
  1102. gszUserName ));
  1103. return NOERROR;
  1104. }
  1105. #endif
  1106. LONG
  1107. TSPIAPI
  1108. TSPI_providerEnumDevices(
  1109. DWORD dwPermanentProviderID,
  1110. LPDWORD lpdwNumLines,
  1111. LPDWORD lpdwNumPhones,
  1112. HPROVIDER hProvider,
  1113. LINEEVENT lpfnLineCreateProc,
  1114. PHONEEVENT lpfnPhoneCreateProc
  1115. )
  1116. {
  1117. DBGOUT((TRCE, "TSPI_providerEnumDevices"));
  1118. EnterCriticalSection(&gCritSec);
  1119. *lpdwNumLines = IPCONF_NUMLINES;
  1120. *lpdwNumPhones = IPCONF_NUMPHONES;
  1121. // save provider handle
  1122. ghProvider = hProvider;
  1123. // save the callback used in creating new lines.
  1124. glpfnLineEventProc = lpfnLineCreateProc;
  1125. LeaveCriticalSection(&gCritSec);
  1126. DBGOUT((TRCE, "TSPI_providerEnumDevices succeeded."));
  1127. return NOERROR;
  1128. }
  1129. LONG
  1130. TSPIAPI
  1131. TSPI_providerInit(
  1132. DWORD dwTSPIVersion,
  1133. DWORD dwPermanentProviderID,
  1134. DWORD dwLineDeviceIDBase,
  1135. DWORD dwPhoneDeviceIDBase,
  1136. DWORD dwNumLines,
  1137. DWORD dwNumPhones,
  1138. ASYNC_COMPLETION lpfnCompletionProc,
  1139. LPDWORD lpdwTSPIOptions
  1140. )
  1141. {
  1142. EnterCriticalSection(&gCritSec);
  1143. DBGREGISTER (("conftsp"));
  1144. DBGOUT((TRCE, "TSPI_providerInit"));
  1145. LONG hr = LINEERR_OPERATIONFAILED;
  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. EnterCriticalSection(&gCritSec);
  1195. DBGOUT((TRCE, "TSPI_providerShutdown."));
  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. DBGOUT((TRCE, "TSPI_providerShutdown succeeded."));
  1202. DBGDEREGISTER ();
  1203. LeaveCriticalSection(&gCritSec);
  1204. return NOERROR;
  1205. }
  1206. LONG
  1207. TSPIAPI
  1208. TSPI_providerUIIdentify(
  1209. LPWSTR lpszUIDLLName
  1210. )
  1211. {
  1212. lstrcpyW(lpszUIDLLName, gszUIDLLName);
  1213. return NOERROR;
  1214. }
  1215. LONG
  1216. TSPIAPI
  1217. TUISPI_providerRemove(
  1218. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  1219. HWND hwndOwner,
  1220. DWORD dwPermanentProviderID
  1221. )
  1222. {
  1223. DBGOUT((TRCE, "TUISPI_providerInstall"));
  1224. return NOERROR;
  1225. }
  1226. LONG
  1227. TSPIAPI
  1228. TUISPI_providerInstall(
  1229. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  1230. HWND hwndOwner,
  1231. DWORD dwPermanentProviderID
  1232. )
  1233. {
  1234. DBGOUT((TRCE, "TUISPI_providerInstall"));
  1235. const CHAR szKey[] =
  1236. "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers";
  1237. HKEY hKey;
  1238. DWORD dwDataSize, dwDataType;
  1239. DWORD dwNumProviders;
  1240. CHAR szName[IPCONF_BUFSIZE + 1], szPath[IPCONF_BUFSIZE + 1];
  1241. // open the providers key
  1242. if (RegOpenKeyEx(
  1243. HKEY_LOCAL_MACHINE,
  1244. szKey,
  1245. 0,
  1246. KEY_READ,
  1247. &hKey
  1248. ) == ERROR_SUCCESS)
  1249. {
  1250. // first get the number of providers installed.
  1251. dwDataSize = sizeof(DWORD);
  1252. if (RegQueryValueEx(
  1253. hKey,
  1254. "NumProviders",
  1255. 0,
  1256. &dwDataType,
  1257. (LPBYTE) &dwNumProviders,
  1258. &dwDataSize
  1259. ) != ERROR_SUCCESS)
  1260. {
  1261. RegCloseKey (hKey);
  1262. return LINEERR_UNINITIALIZED;
  1263. }
  1264. // then go through the list of providers to see if
  1265. // we are already installed.
  1266. for (DWORD i = 0; i < dwNumProviders; i ++)
  1267. {
  1268. wsprintf (szName, "ProviderFileName%d", i);
  1269. dwDataSize = sizeof(szPath);
  1270. if (RegQueryValueEx(
  1271. hKey,
  1272. szName,
  1273. 0,
  1274. &dwDataType,
  1275. (LPBYTE) &szPath,
  1276. &dwDataSize
  1277. ) != ERROR_SUCCESS)
  1278. {
  1279. RegCloseKey (hKey);
  1280. return LINEERR_UNINITIALIZED;
  1281. }
  1282. _strupr(szPath);
  1283. if (strstr(szPath, "IPCONF") != NULL)
  1284. {
  1285. RegCloseKey (hKey);
  1286. // found, we don't want to be installed twice.
  1287. return LINEERR_NOMULTIPLEINSTANCE;
  1288. }
  1289. }
  1290. RegCloseKey (hKey);
  1291. return NOERROR;
  1292. }
  1293. return LINEERR_UNINITIALIZED;
  1294. }