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.

13029 lines
330 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. esp.c
  5. Abstract:
  6. This module contains
  7. Author:
  8. Dan Knudson (DanKn) 18-Sep-1995
  9. Revision History:
  10. Notes:
  11. 1. Regarding the SP filling in structures with variable length fields
  12. (dwXxxSize/dwXxxOffset) : "The SP's variable size fields start
  13. immediately after the fixed part of the data structure. The order
  14. of filling of the variable size fields owned by the SP is not
  15. specified. The SP can fill them in any order it desires. Filling
  16. should be contiguous, starting at the beginning of the variable
  17. part." (Taken from Chapter 2 of the SPI Programmer's Guide.)
  18. --*/
  19. #include "stdarg.h"
  20. #include "stdio.h"
  21. #include "stdlib.h"
  22. //#include "malloc.h"
  23. #include "string.h"
  24. #include "esp.h"
  25. #include "devspec.h"
  26. #include "vars.h"
  27. #define MAX_NUM_PARKED_CALLS 16
  28. LONG glNextRequestResult = 0;
  29. DWORD gdwNextRequestCompletionType;
  30. DWORD gdwDevSpecificRequestID;
  31. DWORD gdwCallID = 0;
  32. BOOL gbExitPBXThread;
  33. BOOL gbDisableUI;
  34. BOOL gbAutoGatherGenerateMsgs;
  35. BOOL gbManualResults = FALSE;
  36. BOOL gbInteractWithDesktop = FALSE;
  37. DWORD gdwCallInstance = 0;
  38. DWORD gdwDrvLineSize;
  39. WCHAR gszProviderInfo[] = L"ESP v2.0";
  40. HANDLE ghPBXThread = NULL;
  41. PDRVCALL gaParkedCalls[MAX_NUM_PARKED_CALLS];
  42. HANDLE ghESPHeap;
  43. static WCHAR *aszDeviceClasses[] =
  44. {
  45. L"tapi/line",
  46. L"tapi/phone",
  47. L"wave",
  48. L"wave/in",
  49. L"wave/out",
  50. L"comm",
  51. L"comm/datamodem",
  52. (WCHAR *) NULL
  53. };
  54. BOOL
  55. PASCAL
  56. IsValidDrvCall(
  57. PDRVCALL pCall,
  58. LPDWORD pdwCallInstance
  59. );
  60. INT_PTR
  61. CALLBACK
  62. ValuesDlgProc(
  63. HWND hwnd,
  64. UINT msg,
  65. WPARAM wParam,
  66. LPARAM lParam
  67. );
  68. LONG
  69. PASCAL
  70. CreateIncomingCall(
  71. LPCWSTR lpszDestAddress,
  72. LPLINECALLPARAMS lpCallParams,
  73. PDRVCALL pOutgoingCall,
  74. BOOL *pbValidESPAddress,
  75. PDRVLINE *ppIncomingLine,
  76. PDRVCALL *ppIncomingCall
  77. );
  78. LONG
  79. PASCAL
  80. TransferCall(
  81. PFUNC_INFO pInfo,
  82. PDRVCALL pCall,
  83. DWORD dwValidCurrentCallStates,
  84. DWORD dwNewCallState,
  85. LPCWSTR lpszDestAddress
  86. );
  87. int
  88. PASCAL
  89. My_lstrcmpiW(
  90. WCHAR *pwsz1,
  91. WCHAR *pwsz2
  92. )
  93. {
  94. if (!pwsz1 || !pwsz2)
  95. {
  96. return 1;
  97. }
  98. for(
  99. ;
  100. *pwsz1 && (*pwsz1 == *pwsz2 || *pwsz1 == (*pwsz2 ^ 0x0020));
  101. pwsz1++, pwsz2++
  102. );
  103. return (*pwsz1 == *pwsz2 ? 0 : 1);
  104. }
  105. BOOL
  106. WINAPI
  107. DllMain(
  108. HANDLE hDLL,
  109. DWORD dwReason,
  110. LPVOID lpReserved
  111. )
  112. {
  113. static BOOL bLoadedByTapisrv;
  114. static HANDLE hInitEvent;
  115. switch (dwReason)
  116. {
  117. case DLL_PROCESS_ATTACH:
  118. {
  119. UINT uiResult;
  120. if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  121. {
  122. OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
  123. }
  124. ghInstance = hDLL;
  125. //
  126. // Allocate a private heap (use process heap if that fails)
  127. //
  128. if (!(ghESPHeap = HeapCreate(
  129. 0, // return NULL on failure, serialize access
  130. 0x1000, // initial heap size
  131. 0 // max heap size (0 == growable)
  132. )))
  133. {
  134. ghESPHeap = GetProcessHeap();
  135. }
  136. //
  137. // Grab ini file settings
  138. //
  139. #if DBG
  140. {
  141. HKEY hKey;
  142. DWORD dwDataSize, dwDataType;
  143. TCHAR szTelephonyKey[] =
  144. "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony",
  145. szEsp32DebugLevel[] = "Esp32DebugLevel";
  146. RegOpenKeyEx(
  147. HKEY_LOCAL_MACHINE,
  148. szTelephonyKey,
  149. 0,
  150. KEY_ALL_ACCESS,
  151. &hKey
  152. );
  153. dwDataSize = sizeof (DWORD);
  154. gdwDebugLevel=0;
  155. RegQueryValueEx(
  156. hKey,
  157. szEsp32DebugLevel,
  158. 0,
  159. &dwDataType,
  160. (LPBYTE) &gdwDebugLevel,
  161. &dwDataSize
  162. );
  163. RegCloseKey (hKey);
  164. }
  165. #endif
  166. //
  167. // Determine whether we're being loaded by tapisrv or some
  168. // other process (i.e. telephony ctrl panel)- this will tell
  169. // us whether we need to go thru all the necessary init or not
  170. //
  171. if (!(GetVersion() & 0x80000000)) // Win NT
  172. {
  173. char *pszProcessName;
  174. STARTUPINFO si;
  175. GetStartupInfoA (&si);
  176. pszProcessName = si.lpTitle + (lstrlenA (si.lpTitle) - 1);
  177. for (; pszProcessName != si.lpTitle; pszProcessName--)
  178. {
  179. if (*pszProcessName == '\\')
  180. {
  181. pszProcessName++;
  182. break;
  183. }
  184. }
  185. if (lstrcmpiA (pszProcessName, "tapisrv.exe") == 0 ||
  186. lstrcmpiA (pszProcessName, "svchost.exe") == 0)
  187. {
  188. bLoadedByTapisrv = TRUE;
  189. }
  190. else
  191. {
  192. bLoadedByTapisrv = FALSE;
  193. }
  194. }
  195. else
  196. {
  197. // For some reason the above blows up on Win9x
  198. char buf[MAX_PATH] = "";
  199. DWORD i;
  200. GetModuleFileName (NULL, buf, MAX_PATH);
  201. for (i = 0; buf[i]; i++)
  202. {
  203. if (isalpha (buf[i]))
  204. {
  205. buf[i] |= 0x20;
  206. }
  207. }
  208. bLoadedByTapisrv = (strstr (buf, "tapisrv.exe") ? TRUE : FALSE);
  209. }
  210. if (bLoadedByTapisrv)
  211. {
  212. {
  213. typedef struct _XXX
  214. {
  215. DWORD dwDefValue;
  216. LPCSTR pszValueName;
  217. LPDWORD pdwValue;
  218. } XXX, *PXXX;
  219. XXX axxx[] =
  220. {
  221. { DEF_SPI_VERSION,
  222. "TSPIVersion",
  223. &gESPGlobals.dwSPIVersion },
  224. { DEF_NUM_LINES,
  225. "NumLines",
  226. &gESPGlobals.dwNumLines },
  227. { DEF_NUM_ADDRS_PER_LINE,
  228. "NumAddrsPerLine",
  229. &gESPGlobals.dwNumAddressesPerLine },
  230. { DEF_NUM_CALLS_PER_ADDR,
  231. "NumCallsPerAddr",
  232. &gESPGlobals.dwNumCallsPerAddress },
  233. { DEF_NUM_PHONES,
  234. "NumPhones",
  235. &gESPGlobals.dwNumPhones },
  236. { DEF_DEBUG_OPTIONS,
  237. "DebugOutput",
  238. &gESPGlobals.dwDebugOptions },
  239. { DEF_COMPLETION_MODE,
  240. "Completion",
  241. &gESPGlobals.dwCompletionMode },
  242. { 0,
  243. "DisableUI",
  244. &gbDisableUI },
  245. { 1,
  246. "AutoGatherGenerateMsgs",
  247. &gbAutoGatherGenerateMsgs },
  248. { 0,
  249. NULL,
  250. NULL },
  251. };
  252. DWORD i;
  253. for (i = 0; axxx[i].pszValueName; i++)
  254. {
  255. *(axxx[i].pdwValue) = (DWORD) GetProfileInt(
  256. "ESP32",
  257. axxx[i].pszValueName,
  258. (int) axxx[i].dwDefValue
  259. );
  260. }
  261. }
  262. //
  263. //
  264. //
  265. InitializeCriticalSection (&gESPGlobals.CallListCritSec);
  266. InitializeCriticalSection (&gESPGlobals.PhoneCritSec);
  267. InitializeCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  268. if (gbDisableUI)
  269. {
  270. //
  271. // Don't bother doing all the stuff to sync/start up espexe.
  272. // However, we do want to make sure that we're not wasting
  273. // time spewing dbg output nor completing async requests in
  274. // any way other than inline (synchronously), since we're
  275. // not real smart about cleaning up pending async requests
  276. // when a call or line is closed/destroyed.
  277. //
  278. gESPGlobals.dwDebugOptions = 0;
  279. gESPGlobals.dwCompletionMode =
  280. COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY;
  281. gbAutoGatherGenerateMsgs = FALSE; //TRUE;
  282. }
  283. else
  284. {
  285. //
  286. // Check to see if tapisrv has the "interact with
  287. // desktop" privilege enabled
  288. //
  289. {
  290. SC_HANDLE hSCManager, hTapisrvSvc;
  291. if ((hSCManager = OpenSCManager(
  292. NULL,
  293. NULL,
  294. GENERIC_READ
  295. )))
  296. {
  297. if ((hTapisrvSvc = OpenService(
  298. hSCManager,
  299. "tapisrv",
  300. SERVICE_QUERY_CONFIG
  301. )))
  302. {
  303. DWORD dwNeededSize;
  304. QUERY_SERVICE_CONFIG config;
  305. if (!QueryServiceConfig(
  306. hTapisrvSvc,
  307. &config,
  308. sizeof (QUERY_SERVICE_CONFIG),
  309. &dwNeededSize
  310. ))
  311. {
  312. QUERY_SERVICE_CONFIG *pConfig;
  313. config.dwServiceType = 0;
  314. if (GetLastError() ==
  315. ERROR_INSUFFICIENT_BUFFER)
  316. {
  317. if ((pConfig = DrvAlloc (dwNeededSize)))
  318. {
  319. if (QueryServiceConfig(
  320. hTapisrvSvc,
  321. pConfig,
  322. dwNeededSize,
  323. &dwNeededSize
  324. ))
  325. {
  326. config.dwServiceType =
  327. pConfig->dwServiceType;
  328. }
  329. DrvFree (pConfig);
  330. }
  331. }
  332. }
  333. gbInteractWithDesktop = (BOOL)
  334. (config.dwServiceType &
  335. SERVICE_INTERACTIVE_PROCESS);
  336. CloseServiceHandle (hTapisrvSvc);
  337. }
  338. CloseServiceHandle (hSCManager);
  339. }
  340. }
  341. if (!gbInteractWithDesktop)
  342. {
  343. gESPGlobals.dwDebugOptions &= ~MANUAL_RESULTS;
  344. }
  345. //
  346. //
  347. //
  348. InitializeCriticalSection (&gESPGlobals.DebugBufferCritSec);
  349. InitializeCriticalSection (&gESPGlobals.EventBufferCritSec);
  350. gESPGlobals.dwDebugBufferTotalSize = 2048;
  351. gESPGlobals.dwDebugBufferUsedSize = 0;
  352. gESPGlobals.pDebugBuffer =
  353. gESPGlobals.pDebugBufferIn =
  354. gESPGlobals.pDebugBufferOut = DrvAlloc(
  355. gESPGlobals.dwDebugBufferTotalSize
  356. );
  357. gESPGlobals.dwEventBufferTotalSize = 40 * sizeof (WIDGETEVENT);
  358. gESPGlobals.dwEventBufferUsedSize = 0;
  359. gESPGlobals.pEventBuffer =
  360. gESPGlobals.pEventBufferIn =
  361. gESPGlobals.pEventBufferOut = DrvAlloc(
  362. gESPGlobals.dwEventBufferTotalSize
  363. );
  364. //
  365. // Create the events used to sync up w/ espexe, and
  366. // start espexe if it's not already running
  367. //
  368. ghDebugOutputEvent = CreateEvent(
  369. (LPSECURITY_ATTRIBUTES) NULL,
  370. TRUE, // manual reset
  371. FALSE, // non-signaled
  372. NULL // unnamed
  373. );
  374. ghWidgetEventsEvent = CreateEvent(
  375. (LPSECURITY_ATTRIBUTES) NULL,
  376. TRUE, // manual reset
  377. FALSE, // non-signaled
  378. NULL // unnamed
  379. );
  380. ghShutdownEvent = CreateEvent(
  381. (LPSECURITY_ATTRIBUTES) NULL,
  382. FALSE, // auto reset
  383. FALSE, // non-signaled
  384. NULL // unnamed
  385. );
  386. //
  387. // Enable rpc server interface
  388. //
  389. {
  390. RPC_STATUS status;
  391. unsigned char * pszSecurity = NULL;
  392. unsigned int cMaxCalls = 20;
  393. status = RpcServerUseProtseqEp(
  394. "ncalrpc",
  395. cMaxCalls,
  396. "esplpc",
  397. pszSecurity // Security descriptor
  398. );
  399. DBGOUT((3, "RpcServerUseProtseqEp(lrpc) ret'd %d", status));
  400. if (status)
  401. {
  402. }
  403. status = RpcServerRegisterIf(
  404. esp_ServerIfHandle, // interface to register
  405. NULL, // MgrTypeUuid
  406. NULL // MgrEpv; null means use default
  407. );
  408. DBGOUT((3, "RpcServerRegisterIf ret'd %d", status));
  409. if (status)
  410. {
  411. }
  412. }
  413. if ((hInitEvent = OpenEvent(
  414. EVENT_ALL_ACCESS,
  415. FALSE, "ESPevent"
  416. )))
  417. {
  418. SetEvent (hInitEvent);
  419. }
  420. else
  421. {
  422. hInitEvent = CreateEvent(
  423. (LPSECURITY_ATTRIBUTES) NULL,
  424. FALSE, // auto reset
  425. TRUE, // signaled
  426. "ESPevent"
  427. );
  428. DBGOUT((3, "Starting espexe..."));
  429. if ((uiResult = WinExec ("espexe.exe", SW_SHOW)) < 32)
  430. {
  431. DBGOUT((
  432. 1,
  433. "WinExec(espexe.exe) failed, err=%d",
  434. uiResult
  435. ));
  436. gESPGlobals.dwDebugOptions = 0;
  437. gESPGlobals.dwCompletionMode =
  438. COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY;
  439. }
  440. #if DBG
  441. else
  442. {
  443. DBGOUT((3, "started espexe"));
  444. }
  445. #endif
  446. }
  447. }
  448. }
  449. break;
  450. }
  451. case DLL_PROCESS_DETACH:
  452. if (bLoadedByTapisrv)
  453. {
  454. if (gbDisableUI == FALSE)
  455. {
  456. SetEvent (ghShutdownEvent);
  457. //
  458. // Unregister out rpc server interface
  459. //
  460. {
  461. RPC_STATUS status;
  462. status = RpcServerUnregisterIf(
  463. esp_ServerIfHandle, // interface to register
  464. NULL, // MgrTypeUuid
  465. 0 // wait for calls to complete
  466. );
  467. DBGOUT((3, "RpcServerUntegisterIf ret'd %d", status));
  468. }
  469. CloseHandle (ghDebugOutputEvent);
  470. CloseHandle (ghWidgetEventsEvent);
  471. CloseHandle (ghShutdownEvent);
  472. CloseHandle (hInitEvent);
  473. DeleteCriticalSection (&gESPGlobals.DebugBufferCritSec);
  474. DeleteCriticalSection (&gESPGlobals.EventBufferCritSec);
  475. DrvFree (gESPGlobals.pDebugBuffer);
  476. DrvFree (gESPGlobals.pEventBuffer);
  477. }
  478. DeleteCriticalSection (&gESPGlobals.CallListCritSec);
  479. DeleteCriticalSection (&gESPGlobals.PhoneCritSec);
  480. DeleteCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  481. }
  482. if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  483. {
  484. OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
  485. }
  486. if (ghESPHeap != GetProcessHeap())
  487. {
  488. HeapDestroy (ghESPHeap);
  489. }
  490. break;
  491. default:
  492. if (!_CRT_INIT (hDLL, dwReason, lpReserved))
  493. {
  494. OutputDebugString ("ESP: DllMain: _CRT_INIT() failed\n\r");
  495. }
  496. break;
  497. }
  498. return TRUE;
  499. }
  500. void
  501. AsyncEventQueueServiceThread(
  502. LPVOID pParams
  503. )
  504. {
  505. while (1)
  506. {
  507. WaitForSingleObject (gESPGlobals.hAsyncEventsPendingEvent, INFINITE);
  508. while (1)
  509. {
  510. PASYNC_REQUEST_INFO pAsyncReqInfo;
  511. EnterCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  512. if (gESPGlobals.dwNumUsedQueueEntries == 0)
  513. {
  514. ResetEvent (gESPGlobals.hAsyncEventsPendingEvent);
  515. LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  516. break;
  517. }
  518. pAsyncReqInfo = *gESPGlobals.pAsyncRequestQueueOut;
  519. gESPGlobals.pAsyncRequestQueueOut++;
  520. if (gESPGlobals.pAsyncRequestQueueOut ==
  521. (gESPGlobals.pAsyncRequestQueue +
  522. gESPGlobals.dwNumTotalQueueEntries))
  523. {
  524. gESPGlobals.pAsyncRequestQueueOut =
  525. gESPGlobals.pAsyncRequestQueue;
  526. }
  527. gESPGlobals.dwNumUsedQueueEntries--;
  528. LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  529. if (pAsyncReqInfo->pfnPostProcessProc)
  530. {
  531. (*(pAsyncReqInfo->pfnPostProcessProc))(
  532. pAsyncReqInfo,
  533. ASYNC
  534. );
  535. }
  536. else
  537. {
  538. DoCompletion (pAsyncReqInfo, ASYNC);
  539. }
  540. DrvFree (pAsyncReqInfo);
  541. }
  542. if (gESPGlobals.bProviderShutdown)
  543. {
  544. break;
  545. }
  546. }
  547. ExitThread (0);
  548. }
  549. void
  550. PBXThread(
  551. LPVOID pParams
  552. )
  553. {
  554. DWORD *pPBXSettings = (LPDWORD) pParams,
  555. dwTickCount, dwElapsedTime,
  556. dwTimePerNewCall = pPBXSettings[0], dwLastNewCallTickCount,
  557. dwTimePerDisconnect = pPBXSettings[1], dwLastDisconnectTickCount;
  558. /*
  559. DWORD dwTickCount, dwElapsedTime,
  560. dwLastNewCallTickCount, dwLastDisconnectTickCount,
  561. dwTimePerNewCall = (gPBXSettings[0].dwNumber ?
  562. gPBXSettings[0].dwTime / gPBXSettings[0].dwNumber : 0),
  563. dwTimePerDisconnect = (gPBXSettings[1].dwNumber ?
  564. gPBXSettings[1].dwTime / gPBXSettings[1].dwNumber : 0);
  565. */
  566. ShowStr (TRUE, "PBXThread: enter");
  567. dwTickCount =
  568. dwLastNewCallTickCount =
  569. dwLastDisconnectTickCount = GetTickCount();
  570. ShowStr(
  571. TRUE,
  572. "dwTimePerNewCall = %d, dwTimePerDisconnect = %d",
  573. dwTimePerNewCall,
  574. dwTimePerDisconnect
  575. );
  576. while (1)
  577. {
  578. Sleep (1000);
  579. if (gbExitPBXThread)
  580. {
  581. break;
  582. }
  583. dwTickCount += 1000; // will automatically wrap around to 0 after it reaches 0xffffffff
  584. if (dwTimePerNewCall)
  585. {
  586. dwElapsedTime = (dwLastNewCallTickCount<=dwTickCount) ? (dwTickCount-dwLastNewCallTickCount) : (dwTickCount+(MAXDWORD-dwLastNewCallTickCount));
  587. while (dwElapsedTime >= dwTimePerNewCall)
  588. {
  589. //
  590. // Generate new call (random line, random media mode)
  591. //
  592. DWORD i = rand(), j;
  593. for (j = 0; j < gESPGlobals.dwInitialNumLines; j++)
  594. {
  595. PDRVLINE pLine = GetLineFromID(
  596. i % gESPGlobals.dwInitialNumLines +
  597. gESPGlobals.dwLineDeviceIDBase
  598. );
  599. if (pLine && pLine->dwMediaModes)
  600. {
  601. DWORD dwMediaMode;
  602. PDRVCALL pCall;
  603. for(
  604. dwMediaMode =
  605. (LINEMEDIAMODE_INTERACTIVEVOICE << i % 13);
  606. dwMediaMode <= LAST_LINEMEDIAMODE;
  607. dwMediaMode <<= 1
  608. )
  609. {
  610. if (pLine->dwMediaModes & dwMediaMode)
  611. {
  612. goto PBXThread_allocCall;
  613. }
  614. }
  615. for(
  616. dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
  617. dwMediaMode <= LAST_LINEMEDIAMODE;
  618. dwMediaMode <<= 1
  619. )
  620. {
  621. if (pLine->dwMediaModes & dwMediaMode)
  622. {
  623. break;
  624. }
  625. }
  626. PBXThread_allocCall:
  627. if (AllocCall (pLine, NULL, NULL, &pCall) == 0)
  628. {
  629. pCall->dwMediaMode = dwMediaMode;
  630. SendLineEvent(
  631. pLine,
  632. NULL,
  633. LINE_NEWCALL,
  634. (ULONG_PTR) pCall,
  635. (ULONG_PTR) &pCall->htCall,
  636. 0
  637. );
  638. if (!pCall->htCall)
  639. {
  640. FreeCall (pCall, pCall->dwCallInstance);
  641. continue;
  642. }
  643. SetCallState(
  644. pCall,
  645. pCall->dwCallInstance,
  646. 0xffffffff,
  647. LINECALLSTATE_OFFERING,
  648. 0,
  649. FALSE
  650. );
  651. break;
  652. }
  653. }
  654. i++;
  655. }
  656. dwElapsedTime -= dwTimePerNewCall;
  657. dwLastNewCallTickCount = dwTickCount;
  658. }
  659. }
  660. if (dwTimePerDisconnect)
  661. {
  662. dwElapsedTime = (dwLastDisconnectTickCount<=dwTickCount) ? (dwTickCount-dwLastDisconnectTickCount) : (dwTickCount+(MAXDWORD-dwLastDisconnectTickCount));
  663. while (dwElapsedTime >= dwTimePerDisconnect)
  664. {
  665. //
  666. // Disconnect a random (non-idle) call (random disconnect mode)
  667. //
  668. DWORD i = rand(), j, k;
  669. for (j = 0; j < gESPGlobals.dwInitialNumLines; j++)
  670. {
  671. DWORD dwInitialAddrID =
  672. i % gESPGlobals.dwNumAddressesPerLine,
  673. dwLastAddrID =
  674. gESPGlobals.dwNumAddressesPerLine;
  675. PDRVLINE pLine = GetLineFromID(
  676. i % gESPGlobals.dwInitialNumLines +
  677. gESPGlobals.dwLineDeviceIDBase
  678. );
  679. PBXThread_findCallToDisconnect:
  680. for (
  681. k = dwInitialAddrID;
  682. k < dwLastAddrID;
  683. k++
  684. )
  685. {
  686. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  687. if (pLine->aAddrs[k].dwNumCalls)
  688. {
  689. PDRVCALL pCall = pLine->aAddrs[k].pCalls;
  690. while (pCall &&
  691. pCall->dwCallState == LINECALLSTATE_IDLE)
  692. {
  693. pCall = pCall->pNext;
  694. }
  695. if (pCall)
  696. {
  697. DWORD dwDisconnectMode =
  698. LINEDISCONNECTMODE_NORMAL;
  699. // BUGBUG disconnectMode depends on curr state
  700. SetCallState(
  701. pCall,
  702. pCall->dwCallInstance,
  703. 0xffffffff,
  704. LINECALLSTATE_DISCONNECTED,
  705. dwDisconnectMode,
  706. FALSE
  707. );
  708. SetCallState(
  709. pCall,
  710. pCall->dwCallInstance,
  711. 0xffffffff,
  712. LINECALLSTATE_IDLE,
  713. 0,
  714. FALSE
  715. );
  716. LeaveCriticalSection(
  717. &gESPGlobals.CallListCritSec
  718. );
  719. goto PBXThread_droppedCall;
  720. }
  721. }
  722. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  723. }
  724. if (dwInitialAddrID != 0)
  725. {
  726. dwLastAddrID = dwInitialAddrID;
  727. dwInitialAddrID = 0;
  728. goto PBXThread_findCallToDisconnect;
  729. }
  730. i++;
  731. }
  732. PBXThread_droppedCall:
  733. dwElapsedTime -= dwTimePerDisconnect;
  734. dwLastDisconnectTickCount = dwTickCount;
  735. }
  736. }
  737. }
  738. DrvFree (pPBXSettings);
  739. ShowStr (TRUE, "PBXThread: exit");
  740. ExitThread (0);
  741. }
  742. void
  743. PASCAL
  744. InsertVarData(
  745. LPVOID lpXxx,
  746. LPDWORD pdwXxxSize,
  747. LPVOID pData,
  748. DWORD dwDataSize
  749. )
  750. {
  751. DWORD dwAlignedSize, dwUsedSize;
  752. LPVARSTRING lpVarString = (LPVARSTRING) lpXxx;
  753. if (dwDataSize != 0)
  754. {
  755. //
  756. // Align var data on 64-bit boundaries
  757. //
  758. if ((dwAlignedSize = dwDataSize) & 7)
  759. {
  760. dwAlignedSize += 8;
  761. dwAlignedSize &= 0xfffffff8;
  762. }
  763. //
  764. // The following if statement should only be TRUE the first time
  765. // we're inserting data into a given structure that does not have
  766. // an even number of DWORD fields
  767. //
  768. if ((dwUsedSize = lpVarString->dwUsedSize) & 7)
  769. {
  770. dwUsedSize += 8;
  771. dwUsedSize &= 0xfffffff8;
  772. lpVarString->dwNeededSize += dwUsedSize - lpVarString->dwUsedSize;
  773. }
  774. lpVarString->dwNeededSize += dwAlignedSize;
  775. if ((dwUsedSize + dwAlignedSize) <= lpVarString->dwTotalSize)
  776. {
  777. CopyMemory(
  778. ((LPBYTE) lpVarString) + dwUsedSize,
  779. pData,
  780. dwDataSize
  781. );
  782. *pdwXxxSize = dwDataSize;
  783. pdwXxxSize++; // pdwXxxSize = pdwXxxOffset
  784. *pdwXxxSize = dwUsedSize;
  785. lpVarString->dwUsedSize = dwUsedSize + dwAlignedSize;
  786. }
  787. }
  788. }
  789. void
  790. PASCAL
  791. InsertVarDataString(
  792. LPVOID lpXxx,
  793. LPDWORD pdwXxxSize,
  794. WCHAR *psz
  795. )
  796. {
  797. DWORD dwRealSize = (lstrlenW (psz) + 1) * sizeof (WCHAR),
  798. dwAlignedSize;
  799. LPVARSTRING lpVarString = (LPVARSTRING) lpXxx;
  800. if (dwRealSize % 4)
  801. {
  802. dwAlignedSize = dwRealSize - (dwRealSize % 4) + 4;
  803. }
  804. else
  805. {
  806. dwAlignedSize = dwRealSize;
  807. }
  808. lpVarString->dwNeededSize += dwAlignedSize;
  809. if ((lpVarString->dwUsedSize + dwAlignedSize) <= lpVarString->dwTotalSize)
  810. {
  811. CopyMemory(
  812. ((LPBYTE) lpVarString) + lpVarString->dwUsedSize,
  813. psz,
  814. dwRealSize
  815. );
  816. *pdwXxxSize = dwRealSize;
  817. pdwXxxSize++;
  818. *pdwXxxSize = lpVarString->dwUsedSize;
  819. lpVarString->dwUsedSize += dwAlignedSize;
  820. }
  821. }
  822. //
  823. // We get a slough of C4047 (different levels of indrection) warnings down
  824. // below in the initialization of FUNC_PARAM structs as a result of the
  825. // real func prototypes having params that are types other than DWORDs,
  826. // so since these are known non-interesting warnings just turn them off
  827. //
  828. #pragma warning (disable:4047)
  829. //
  830. // --------------------------- TSPI_lineXxx funcs -----------------------------
  831. //
  832. void
  833. FAR
  834. PASCAL
  835. TSPI_lineAccept_postProcess(
  836. PASYNC_REQUEST_INFO pAsyncReqInfo,
  837. BOOL bAsync
  838. )
  839. {
  840. if (pAsyncReqInfo->lResult == 0)
  841. {
  842. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  843. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  844. pAsyncReqInfo->lResult = SetCallState(
  845. pCall,
  846. dwCallInstThen,
  847. LINECALLSTATE_OFFERING,
  848. LINECALLSTATE_ACCEPTED,
  849. 0,
  850. TRUE
  851. );
  852. }
  853. DoCompletion (pAsyncReqInfo, bAsync);
  854. }
  855. LONG
  856. TSPIAPI
  857. TSPI_lineAccept(
  858. DRV_REQUESTID dwRequestID,
  859. HDRVCALL hdCall,
  860. LPCSTR lpsUserUserInfo,
  861. DWORD dwSize
  862. )
  863. {
  864. static char szFuncName[] = "lineAccept";
  865. FUNC_PARAM params[] =
  866. {
  867. { szdwRequestID, dwRequestID },
  868. { szhdCall, hdCall },
  869. { "lpsUserUserInfo", lpsUserUserInfo },
  870. { szdwSize, dwSize }
  871. };
  872. FUNC_INFO info =
  873. {
  874. szFuncName,
  875. ASYNC,
  876. 4,
  877. params,
  878. TSPI_lineAccept_postProcess
  879. };
  880. if (Prolog (&info))
  881. {
  882. DWORD dwCallInstance;
  883. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  884. {
  885. info.pAsyncReqInfo->dwParam2 = dwCallInstance;
  886. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  887. }
  888. else
  889. {
  890. info.lResult = LINEERR_INVALCALLHANDLE;
  891. }
  892. }
  893. return (Epilog (&info));
  894. }
  895. void
  896. FAR
  897. PASCAL
  898. TSPI_lineAddToConference_postProcess(
  899. PASYNC_REQUEST_INFO pAsyncReqInfo,
  900. BOOL bAsync
  901. )
  902. {
  903. if (pAsyncReqInfo->lResult == 0)
  904. {
  905. DWORD dwConfCallInstThen = (DWORD) pAsyncReqInfo->dwParam3,
  906. dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam4,
  907. dwConfCallInstNow;
  908. PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  909. PDRVCALL pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  910. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  911. if (IsValidDrvCall (pConfCall, &dwConfCallInstNow) &&
  912. dwConfCallInstNow == dwConfCallInstThen)
  913. {
  914. //
  915. // Note - indecision on the validity of ONHOLD -> CONNECTED transition
  916. // SDK allows it, internal TAPI documents by NoelA do not.
  917. //
  918. if (SetCallState(
  919. pConfCall,
  920. dwConfCallInstThen,
  921. LINECALLSTATE_ONHOLDPENDCONF | LINECALLSTATE_ONHOLD,
  922. LINECALLSTATE_CONNECTED,
  923. 0,
  924. TRUE
  925. ) == 0)
  926. {
  927. if ((pAsyncReqInfo->lResult = SetCallState(
  928. pConsultCall,
  929. dwConsultCallInstThen,
  930. LINECALLSTATE_PROCEEDING | LINECALLSTATE_RINGBACK | LINECALLSTATE_ONHOLD | LINECALLSTATE_CONNECTED,
  931. LINECALLSTATE_CONFERENCED,
  932. 0,
  933. TRUE
  934. )) == 0)
  935. {
  936. pConsultCall->pConfParent = pConfCall;
  937. pConsultCall->pNextConfChild = pConfCall->pNextConfChild;
  938. pConfCall->pNextConfChild = pConsultCall;
  939. /*
  940. pConsultCall->dwRelatedCallID = pConfCall->dwRelatedCallID;
  941. SendLineEvent(
  942. pConsultCall->pLine,
  943. pConsultCall,
  944. LINE_CALLINFO,
  945. LINECALLINFOSTATE_RELATEDCALLID,
  946. 0,
  947. 0
  948. );
  949. */
  950. // give the consult call the same callid as the conf controller
  951. // this puts it into the same call hub
  952. pConsultCall->dwCallID = pConfCall->dwCallID;
  953. SendLineEvent(
  954. pConsultCall->pLine,
  955. pConsultCall,
  956. LINE_CALLINFO,
  957. LINECALLINFOSTATE_CALLID,
  958. 0,
  959. 0
  960. );
  961. if (pConsultCall->pDestCall)
  962. {
  963. // BUGBUG chg buddy's call hub id, and check to see if
  964. // buddy is in a conf (if so will need to munge
  965. // the conf too (?)
  966. // give the consult call's buddy the same callid as the conf
  967. // controller, this puts it into the same call hub
  968. pConsultCall->pDestCall->dwCallID = pConfCall->dwCallID;
  969. SendLineEvent(
  970. pConsultCall->pDestCall->pLine,
  971. pConsultCall->pDestCall,
  972. LINE_CALLINFO,
  973. LINECALLINFOSTATE_CALLID,
  974. 0,
  975. 0
  976. );
  977. }
  978. }
  979. }
  980. }
  981. else
  982. {
  983. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  984. }
  985. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  986. }
  987. DoCompletion (pAsyncReqInfo, bAsync);
  988. }
  989. LONG
  990. TSPIAPI
  991. TSPI_lineAddToConference(
  992. DRV_REQUESTID dwRequestID,
  993. HDRVCALL hdConfCall,
  994. HDRVCALL hdConsultCall
  995. )
  996. {
  997. static char szFuncName[] = "lineAddToConference";
  998. FUNC_PARAM params[] =
  999. {
  1000. { szdwRequestID, dwRequestID },
  1001. { "hdConfCall", hdConfCall },
  1002. { "hdConsultCall", hdConsultCall }
  1003. };
  1004. FUNC_INFO info =
  1005. {
  1006. szFuncName,
  1007. ASYNC,
  1008. 3,
  1009. params,
  1010. TSPI_lineAddToConference_postProcess
  1011. };
  1012. PDRVCALL pConfCall = (PDRVCALL) hdConfCall;
  1013. PDRVCALL pConsultCall = (PDRVCALL) hdConsultCall;
  1014. if (Prolog (&info))
  1015. {
  1016. DWORD dwConfCallInstance, dwConsultCallInstance;
  1017. if (IsValidDrvCall ((PDRVCALL) hdConfCall, &dwConfCallInstance) &&
  1018. IsValidDrvCall ((PDRVCALL) hdConsultCall, &dwConsultCallInstance))
  1019. {
  1020. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdConfCall;
  1021. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdConsultCall;
  1022. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwConfCallInstance;
  1023. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) dwConsultCallInstance;
  1024. }
  1025. else
  1026. {
  1027. info.lResult = LINEERR_INVALCALLHANDLE;
  1028. }
  1029. }
  1030. return (Epilog (&info));
  1031. }
  1032. void
  1033. FAR
  1034. PASCAL
  1035. TSPI_lineAnswer_postProcess(
  1036. PASYNC_REQUEST_INFO pAsyncReqInfo,
  1037. BOOL bAsync
  1038. )
  1039. {
  1040. if (pAsyncReqInfo->lResult == 0)
  1041. {
  1042. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  1043. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  1044. pAsyncReqInfo->lResult = SetCallState(
  1045. pCall,
  1046. dwCallInstThen,
  1047. LINECALLSTATE_OFFERING | LINECALLSTATE_ACCEPTED,
  1048. LINECALLSTATE_CONNECTED,
  1049. 0,
  1050. TRUE
  1051. );
  1052. }
  1053. DoCompletion (pAsyncReqInfo, bAsync);
  1054. }
  1055. LONG
  1056. TSPIAPI
  1057. TSPI_lineAnswer(
  1058. DRV_REQUESTID dwRequestID,
  1059. HDRVCALL hdCall,
  1060. LPCSTR lpsUserUserInfo,
  1061. DWORD dwSize
  1062. )
  1063. {
  1064. static char szFuncName[] = "lineAnswer";
  1065. FUNC_PARAM params[] =
  1066. {
  1067. { szdwRequestID, dwRequestID },
  1068. { szhdCall, hdCall },
  1069. { "lpsUserUserInfo", lpsUserUserInfo },
  1070. { szdwSize, dwSize }
  1071. };
  1072. FUNC_INFO info =
  1073. {
  1074. szFuncName,
  1075. ASYNC,
  1076. 4,
  1077. params,
  1078. TSPI_lineAnswer_postProcess
  1079. };
  1080. if (Prolog (&info))
  1081. {
  1082. DWORD dwCallInstance;
  1083. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  1084. {
  1085. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  1086. info.pAsyncReqInfo->dwParam2 = dwCallInstance;
  1087. }
  1088. else
  1089. {
  1090. info.lResult = LINEERR_INVALCALLHANDLE;
  1091. }
  1092. }
  1093. return (Epilog (&info));
  1094. }
  1095. LONG
  1096. TSPIAPI
  1097. TSPI_lineBlindTransfer(
  1098. DRV_REQUESTID dwRequestID,
  1099. HDRVCALL hdCall,
  1100. LPCWSTR lpszDestAddress,
  1101. DWORD dwCountryCode
  1102. )
  1103. {
  1104. static char szFuncName[] = "lineBlindTransfer";
  1105. FUNC_PARAM params[] =
  1106. {
  1107. { szdwRequestID, dwRequestID },
  1108. { szhdCall, hdCall },
  1109. { "lpszDestAddress", lpszDestAddress },
  1110. { "dwCountryCode", dwCountryCode }
  1111. };
  1112. FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
  1113. if (Prolog (&info))
  1114. {
  1115. info.lResult = TransferCall(
  1116. &info,
  1117. (PDRVCALL) hdCall,
  1118. LINECALLSTATE_CONNECTED,
  1119. LINECALLSTATE_OFFERING,
  1120. lpszDestAddress
  1121. );
  1122. }
  1123. return (Epilog (&info));
  1124. }
  1125. LONG
  1126. TSPIAPI
  1127. TSPI_lineClose(
  1128. HDRVLINE hdLine
  1129. )
  1130. {
  1131. static char szFuncName[] = "lineClose";
  1132. FUNC_PARAM params[] =
  1133. {
  1134. { szhdLine, hdLine }
  1135. };
  1136. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  1137. PDRVLINE pLine = (PDRVLINE) hdLine;
  1138. //
  1139. // This is more of a "command" than a request, in that TAPI.DLL is
  1140. // going to consider the line closed whether we like it or not.
  1141. // Therefore we want to free up the line even if the user chooses
  1142. // to return an error.
  1143. //
  1144. Prolog (&info);
  1145. pLine->htLine = (HTAPILINE) NULL;
  1146. pLine->dwMediaModes = 0;
  1147. // pLine->dwMSGWAITFlag = 0; //smarandb #23974 winseqfe: don't reset this on lineClose!!
  1148. //this value should not be reset on lineClose,
  1149. //instead it should reflect the hardware status (should be dictated by the switch).
  1150. WriteEventBuffer (pLine->dwDeviceID, WIDGETTYPE_LINE, 0, 0, 0, 0);
  1151. return (Epilog (&info));
  1152. }
  1153. LONG
  1154. TSPIAPI
  1155. TSPI_lineCloseCall(
  1156. HDRVCALL hdCall
  1157. )
  1158. {
  1159. DWORD dwCallInst;
  1160. static char szFuncName[] = "lineCloseCall";
  1161. FUNC_PARAM params[] =
  1162. {
  1163. { szhdCall, hdCall }
  1164. };
  1165. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  1166. PDRVCALL pCall = (PDRVCALL) hdCall;
  1167. //
  1168. // This is more of a "command" than a request, in that TAPI.DLL is
  1169. // going to consider the call closed whether we like it or not.
  1170. // Therefore we want to free up the call even if the user chooses
  1171. // to return an error.
  1172. //
  1173. Prolog (&info);
  1174. if (IsValidDrvCall (pCall, &dwCallInst))
  1175. {
  1176. if (pCall && pCall->pLine)
  1177. WriteEventBuffer(
  1178. ((PDRVLINE) pCall->pLine)->dwDeviceID,
  1179. WIDGETTYPE_CALL,
  1180. (ULONG_PTR) pCall,
  1181. 0,
  1182. 0,
  1183. 0
  1184. );
  1185. FreeCall (pCall, dwCallInst);
  1186. }
  1187. return (Epilog (&info));
  1188. }
  1189. LONG
  1190. TSPIAPI
  1191. TSPI_lineCompleteCall(
  1192. DRV_REQUESTID dwRequestID,
  1193. HDRVCALL hdCall,
  1194. LPDWORD lpdwCompletionID,
  1195. DWORD dwCompletionMode,
  1196. DWORD dwMessageID
  1197. )
  1198. {
  1199. static char szFuncName[] = "lineCompleteCall";
  1200. FUNC_PARAM params[] =
  1201. {
  1202. { szdwRequestID, dwRequestID },
  1203. { szhdCall, hdCall },
  1204. { "lpdwCompletionID", lpdwCompletionID },
  1205. { "dwCompletionMode", dwCompletionMode },
  1206. { "dwMessageID", dwMessageID }
  1207. };
  1208. FUNC_INFO info = { szFuncName, ASYNC, 5, params, NULL };
  1209. if (Prolog (&info))
  1210. {
  1211. if (dwMessageID >= MAX_NUM_COMPLETION_MESSAGES)
  1212. {
  1213. info.lResult = LINEERR_INVALMESSAGEID;
  1214. }
  1215. }
  1216. return (Epilog (&info));
  1217. }
  1218. void
  1219. FAR
  1220. PASCAL
  1221. TSPI_lineCompleteTransfer_postProcess(
  1222. PASYNC_REQUEST_INFO pAsyncReqInfo,
  1223. BOOL bAsync
  1224. )
  1225. {
  1226. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  1227. dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam2,
  1228. dwConfCallInstThen = (DWORD) pAsyncReqInfo->dwParam6,
  1229. dwCallInstNow, dwConsultCallInstNow, dwConfCallInstNow;
  1230. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
  1231. pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam4,
  1232. pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam5;
  1233. if (pAsyncReqInfo->lResult == 0)
  1234. {
  1235. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  1236. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  1237. dwCallInstNow == dwCallInstThen &&
  1238. IsValidDrvCall (pConsultCall, &dwConsultCallInstNow) &&
  1239. dwConsultCallInstNow == dwConsultCallInstThen)
  1240. {
  1241. if (pConfCall)
  1242. {
  1243. if (IsValidDrvCall (pConfCall, &dwConfCallInstNow) &&
  1244. dwConfCallInstNow == dwConfCallInstThen)
  1245. {
  1246. pConfCall->pNextConfChild = pCall;
  1247. pCall->pNextConfChild = pConsultCall;
  1248. pCall->pConfParent = pConfCall;
  1249. pConsultCall->pConfParent = pConfCall;
  1250. }
  1251. else
  1252. {
  1253. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  1254. }
  1255. }
  1256. }
  1257. else
  1258. {
  1259. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  1260. if (pConfCall)
  1261. {
  1262. FreeCall (pConfCall, dwConfCallInstThen);
  1263. }
  1264. }
  1265. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  1266. }
  1267. DoCompletion (pAsyncReqInfo, bAsync);
  1268. if (pAsyncReqInfo->lResult == 0)
  1269. {
  1270. if (pConfCall)
  1271. {
  1272. if (SetCallState(
  1273. pConfCall,
  1274. dwConfCallInstNow,
  1275. 0xffffffff, // we just created this conf call, any state is fine
  1276. LINECALLSTATE_CONNECTED,
  1277. 0,
  1278. TRUE
  1279. ) == 0)
  1280. {
  1281. //
  1282. // Note - indecision on the validity of ONHOLD -> CONFERENCED transition
  1283. // SDK allows it, internal TAPI documents by NoelA do not.
  1284. //
  1285. SetCallState(
  1286. pCall,
  1287. dwCallInstNow,
  1288. LINECALLSTATE_ONHOLDPENDTRANSFER | LINECALLSTATE_ONHOLD,
  1289. LINECALLSTATE_CONFERENCED,
  1290. 0,
  1291. TRUE
  1292. );
  1293. //
  1294. // Note - indecision on the validity of these transitions
  1295. // SDK allows them, internal TAPI documents by NoelA do not.
  1296. //
  1297. SetCallState(
  1298. pConsultCall,
  1299. dwConsultCallInstNow,
  1300. LINECALLSTATE_PROCEEDING | LINECALLSTATE_RINGBACK | LINECALLSTATE_BUSY | LINECALLSTATE_CONNECTED,
  1301. LINECALLSTATE_CONFERENCED,
  1302. 0,
  1303. TRUE
  1304. );
  1305. }
  1306. pConsultCall->dwCallID = pConfCall->dwCallID;
  1307. SendLineEvent(
  1308. pConsultCall->pLine,
  1309. pConsultCall,
  1310. LINE_CALLINFO,
  1311. LINECALLINFOSTATE_CALLID,
  1312. 0,
  1313. 0
  1314. );
  1315. if (pConsultCall->pDestCall)
  1316. {
  1317. pConsultCall->pDestCall->dwCallID = pConfCall->dwCallID;
  1318. SendLineEvent(
  1319. pConsultCall->pDestCall->pLine,
  1320. pConsultCall->pDestCall,
  1321. LINE_CALLINFO,
  1322. LINECALLINFOSTATE_CALLID,
  1323. 0,
  1324. 0
  1325. );
  1326. }
  1327. }
  1328. else
  1329. {
  1330. PDRVCALL pCallOtherEnd = pCall->pDestCall;
  1331. PDRVCALL pConsultCallOtherEnd = pConsultCall->pDestCall;
  1332. pCall->pDestCall = NULL;
  1333. pConsultCall->pDestCall = NULL;
  1334. // create a new callid for the transfered call
  1335. // this create a new call hub
  1336. if (pConsultCallOtherEnd)
  1337. {
  1338. pConsultCallOtherEnd->pDestCall = pCallOtherEnd;
  1339. pConsultCallOtherEnd->dwCallID = (++gdwCallID ? gdwCallID : ++gdwCallID);
  1340. SendLineEvent(
  1341. pConsultCallOtherEnd->pLine,
  1342. pConsultCallOtherEnd,
  1343. LINE_CALLINFO,
  1344. LINECALLINFOSTATE_CALLID,
  1345. 0,
  1346. 0
  1347. );
  1348. }
  1349. if (pCallOtherEnd)
  1350. {
  1351. pCallOtherEnd->pDestCall = pConsultCallOtherEnd;
  1352. pCallOtherEnd->dwCallID = pConsultCallOtherEnd->dwCallID;
  1353. SendLineEvent(
  1354. pCallOtherEnd->pLine,
  1355. pCallOtherEnd,
  1356. LINE_CALLINFO,
  1357. LINECALLINFOSTATE_CALLID,
  1358. 0,
  1359. 0
  1360. );
  1361. }
  1362. SetCallState(
  1363. pCall,
  1364. dwCallInstNow,
  1365. LINECALLSTATE_ONHOLDPENDTRANSFER | LINECALLSTATE_ONHOLD,
  1366. LINECALLSTATE_IDLE,
  1367. 0,
  1368. TRUE
  1369. );
  1370. //
  1371. // Note - indecision on the validity of BUSY->IDLE transition
  1372. // SDK allows it, internal TAPI documents by NoelA do not.
  1373. //
  1374. SetCallState(
  1375. pConsultCall,
  1376. dwConsultCallInstNow,
  1377. LINECALLSTATE_RINGBACK | LINECALLSTATE_PROCEEDING | LINECALLSTATE_CONNECTED | LINECALLSTATE_BUSY,
  1378. LINECALLSTATE_IDLE,
  1379. 0,
  1380. TRUE
  1381. );
  1382. }
  1383. }
  1384. }
  1385. LONG
  1386. TSPIAPI
  1387. TSPI_lineCompleteTransfer(
  1388. DRV_REQUESTID dwRequestID,
  1389. HDRVCALL hdCall,
  1390. HDRVCALL hdConsultCall,
  1391. HTAPICALL htConfCall,
  1392. LPHDRVCALL lphdConfCall,
  1393. DWORD dwTransferMode
  1394. )
  1395. {
  1396. static char szFuncName[] = "lineCompleteTransfer";
  1397. FUNC_PARAM params[] =
  1398. {
  1399. { szdwRequestID, dwRequestID },
  1400. { szhdCall, hdCall },
  1401. { "hdConsultCall", hdConsultCall },
  1402. { "htConfCall", htConfCall },
  1403. { "lphdConfCall", lphdConfCall },
  1404. { "dwTransferMode", dwTransferMode, aTransferModes }
  1405. };
  1406. FUNC_INFO info =
  1407. {
  1408. szFuncName,
  1409. ASYNC,
  1410. 6,
  1411. params,
  1412. TSPI_lineCompleteTransfer_postProcess
  1413. };
  1414. if (Prolog (&info))
  1415. {
  1416. DWORD dwCallInstance, dwConsultCallInstance;
  1417. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance) &&
  1418. IsValidDrvCall((PDRVCALL) hdConsultCall, &dwConsultCallInstance))
  1419. {
  1420. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  1421. info.pAsyncReqInfo->dwParam2 = dwConsultCallInstance;
  1422. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) hdCall;
  1423. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) hdConsultCall;
  1424. if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
  1425. {
  1426. LONG lResult;
  1427. PDRVCALL pConfCall;
  1428. PDRVLINE pLine = ((PDRVCALL) hdCall)->pLine;
  1429. if ((lResult = AllocCall(
  1430. pLine,
  1431. htConfCall,
  1432. NULL,
  1433. &pConfCall
  1434. )) == 0)
  1435. {
  1436. *lphdConfCall = (HDRVCALL) pConfCall;
  1437. pConfCall->dwCallID = ((PDRVCALL) hdCall)->dwCallID;
  1438. info.pAsyncReqInfo->dwParam5 = (ULONG_PTR) pConfCall;
  1439. info.pAsyncReqInfo->dwParam6 = pConfCall->dwCallInstance;
  1440. }
  1441. else
  1442. {
  1443. info.lResult = lResult;
  1444. }
  1445. }
  1446. }
  1447. else
  1448. {
  1449. info.lResult = LINEERR_INVALCALLHANDLE;
  1450. }
  1451. }
  1452. return (Epilog (&info));
  1453. }
  1454. LONG
  1455. TSPIAPI
  1456. TSPI_lineConditionalMediaDetection(
  1457. HDRVLINE hdLine,
  1458. DWORD dwMediaModes,
  1459. LPLINECALLPARAMS const lpCallParams
  1460. )
  1461. {
  1462. static char szFuncName[] = "lineConditionalMediaDetection";
  1463. FUNC_PARAM params[] =
  1464. {
  1465. { szhdLine, hdLine },
  1466. { "dwMediaModes", dwMediaModes, aMediaModes },
  1467. { szlpCallParams, lpCallParams }
  1468. };
  1469. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  1470. PDRVLINE pLine = (PDRVLINE) hdLine;
  1471. if (Prolog (&info))
  1472. {
  1473. }
  1474. return (Epilog (&info));
  1475. }
  1476. void
  1477. FAR
  1478. PASCAL
  1479. TSPI_lineDevSpecific_postProcess(
  1480. PASYNC_REQUEST_INFO pAsyncReqInfo,
  1481. BOOL bAsync
  1482. )
  1483. {
  1484. LPBYTE lpParams = pAsyncReqInfo->dwParam1;
  1485. DWORD dwSize = (DWORD) pAsyncReqInfo->dwParam2, i;
  1486. if (pAsyncReqInfo->lResult == 0)
  1487. {
  1488. for (i = 0; i < dwSize; i++)
  1489. {
  1490. *lpParams++ = (BYTE) i;
  1491. }
  1492. }
  1493. DoCompletion (pAsyncReqInfo, bAsync);
  1494. }
  1495. LONG
  1496. TSPIAPI
  1497. TSPI_lineDevSpecific(
  1498. DRV_REQUESTID dwRequestID,
  1499. HDRVLINE hdLine,
  1500. DWORD dwAddressID,
  1501. HDRVCALL hdCall,
  1502. LPVOID lpParams,
  1503. DWORD dwSize
  1504. )
  1505. {
  1506. static char szFuncName[] = "lineDevSpecific";
  1507. FUNC_PARAM params[] =
  1508. {
  1509. { szdwRequestID, dwRequestID },
  1510. { szhdLine, hdLine },
  1511. { "dwAddressID", dwAddressID },
  1512. { szhdCall, hdCall },
  1513. { "lpParams", lpParams },
  1514. { szdwSize, dwSize }
  1515. };
  1516. FUNC_INFO info =
  1517. {
  1518. szFuncName,
  1519. ASYNC,
  1520. 6,
  1521. params
  1522. };
  1523. PESPDEVSPECIFICINFO pInfo = (PESPDEVSPECIFICINFO) lpParams;
  1524. if (Prolog (&info))
  1525. {
  1526. if (dwSize >= sizeof (ESPDEVSPECIFICINFO) &&
  1527. pInfo->dwKey == ESPDEVSPECIFIC_KEY)
  1528. {
  1529. switch (pInfo->dwType)
  1530. {
  1531. case ESP_DEVSPEC_MSG:
  1532. switch (pInfo->u.EspMsg.dwMsg)
  1533. {
  1534. case LINE_ADDRESSSTATE:
  1535. case LINE_CLOSE:
  1536. case LINE_DEVSPECIFIC:
  1537. case LINE_DEVSPECIFICFEATURE:
  1538. case LINE_LINEDEVSTATE:
  1539. SendLineEvent(
  1540. (PDRVLINE) hdLine,
  1541. NULL,
  1542. pInfo->u.EspMsg.dwMsg,
  1543. pInfo->u.EspMsg.dwParam1,
  1544. pInfo->u.EspMsg.dwParam2,
  1545. pInfo->u.EspMsg.dwParam3
  1546. );
  1547. break;
  1548. case LINE_CALLDEVSPECIFIC:
  1549. case LINE_CALLDEVSPECIFICFEATURE:
  1550. case LINE_CALLINFO:
  1551. case LINE_MONITORDIGITS:
  1552. case LINE_MONITORMEDIA:
  1553. if (hdCall)
  1554. {
  1555. SendLineEvent(
  1556. (PDRVLINE) hdLine,
  1557. (PDRVCALL) hdCall,
  1558. pInfo->u.EspMsg.dwMsg,
  1559. pInfo->u.EspMsg.dwParam1,
  1560. pInfo->u.EspMsg.dwParam2,
  1561. pInfo->u.EspMsg.dwParam3
  1562. );
  1563. }
  1564. else
  1565. {
  1566. info.lResult = LINEERR_OPERATIONFAILED;
  1567. }
  1568. break;
  1569. case LINE_GATHERDIGITS:
  1570. if (hdCall)
  1571. {
  1572. DWORD dwEndToEndID = 0;
  1573. PDRVCALL pCall = (PDRVCALL) hdCall;
  1574. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  1575. if (IsValidDrvCall (pCall, NULL))
  1576. {
  1577. if ((dwEndToEndID =
  1578. pCall->dwGatherDigitsEndToEndID))
  1579. {
  1580. pCall->dwGatherDigitsEndToEndID = 0;
  1581. }
  1582. else
  1583. {
  1584. info.lResult = LINEERR_OPERATIONFAILED;
  1585. }
  1586. }
  1587. else
  1588. {
  1589. info.lResult = LINEERR_INVALCALLHANDLE;
  1590. }
  1591. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  1592. if (dwEndToEndID)
  1593. {
  1594. SendLineEvent(
  1595. (PDRVLINE) hdLine,
  1596. (PDRVCALL) hdCall,
  1597. LINE_GATHERDIGITS,
  1598. pInfo->u.EspMsg.dwParam1,
  1599. dwEndToEndID,
  1600. 0
  1601. );
  1602. }
  1603. else if (info.lResult == LINEERR_OPERATIONFAILED)
  1604. {
  1605. ShowStr(
  1606. TRUE,
  1607. "ERROR: TSPI_lineDevSpecific: attempt to " \
  1608. "send GATHERDIGITS msg with no " \
  1609. "lineGatherDigits request pending"
  1610. );
  1611. }
  1612. }
  1613. else
  1614. {
  1615. info.lResult = LINEERR_OPERATIONFAILED;
  1616. }
  1617. break;
  1618. case LINE_GENERATE:
  1619. if (hdCall)
  1620. {
  1621. DWORD dwEndToEndID = 0, *pdwXxxEndToEndID;
  1622. PDRVCALL pCall = (PDRVCALL) hdCall;
  1623. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  1624. if (IsValidDrvCall (pCall, NULL))
  1625. {
  1626. pdwXxxEndToEndID = (pInfo->u.EspMsg.dwParam3 ?
  1627. &pCall->dwGenerateToneEndToEndID :
  1628. &pCall->dwGenerateDigitsEndToEndID
  1629. );
  1630. if ((dwEndToEndID = *pdwXxxEndToEndID))
  1631. {
  1632. *pdwXxxEndToEndID = 0;
  1633. }
  1634. else
  1635. {
  1636. info.lResult = LINEERR_OPERATIONFAILED;
  1637. }
  1638. }
  1639. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  1640. if (dwEndToEndID)
  1641. {
  1642. SendLineEvent(
  1643. (PDRVLINE) hdLine,
  1644. (PDRVCALL) hdCall,
  1645. LINE_GENERATE,
  1646. pInfo->u.EspMsg.dwParam1,
  1647. dwEndToEndID,
  1648. 0
  1649. );
  1650. }
  1651. else if (info.lResult == LINEERR_OPERATIONFAILED)
  1652. {
  1653. ShowStr(
  1654. TRUE,
  1655. "ERROR: TSPI_lineDevSpecific: attempt to " \
  1656. "send GENERATE msg with no " \
  1657. "lineGenerateXxx request pending"
  1658. );
  1659. }
  1660. }
  1661. else
  1662. {
  1663. info.lResult = LINEERR_OPERATIONFAILED;
  1664. }
  1665. break;
  1666. case LINE_MONITORTONE:
  1667. if (hdCall)
  1668. {
  1669. DWORD dwToneListID = 0;
  1670. PDRVCALL pCall = (PDRVCALL) hdCall;
  1671. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  1672. if (IsValidDrvCall (pCall, NULL))
  1673. {
  1674. if ((dwToneListID =
  1675. pCall->dwMonitorToneListID))
  1676. {
  1677. pCall->dwMonitorToneListID = 0;
  1678. }
  1679. else
  1680. {
  1681. info.lResult = LINEERR_OPERATIONFAILED;
  1682. }
  1683. }
  1684. else
  1685. {
  1686. info.lResult = LINEERR_INVALCALLHANDLE;
  1687. }
  1688. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  1689. if (dwToneListID)
  1690. {
  1691. SendLineEvent(
  1692. (PDRVLINE) hdLine,
  1693. (PDRVCALL) hdCall,
  1694. LINE_MONITORTONE,
  1695. pInfo->u.EspMsg.dwParam1,
  1696. dwToneListID,
  1697. 0
  1698. );
  1699. }
  1700. else if (info.lResult == LINEERR_OPERATIONFAILED)
  1701. {
  1702. ShowStr(
  1703. TRUE,
  1704. "ERROR: TSPI_lineDevSpecific: attempt to " \
  1705. "send MONITORTONE msg with no " \
  1706. "lineMonitorTone request pending"
  1707. );
  1708. }
  1709. }
  1710. else
  1711. {
  1712. info.lResult = LINEERR_OPERATIONFAILED;
  1713. }
  1714. break;
  1715. case LINE_CALLSTATE:
  1716. {
  1717. DWORD dwCallInst;
  1718. if (hdCall &&
  1719. IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInst))
  1720. {
  1721. LONG lResult;
  1722. ULONG_PTR param2 = pInfo->u.EspMsg.dwParam2;
  1723. // BUGBUG changing to/from conf state cause ptr probs?
  1724. // BUGBUG check for bad call state vals
  1725. if (pInfo->u.EspMsg.dwParam1 ==
  1726. LINECALLSTATE_CONFERENCED &&
  1727. pInfo->u.EspMsg.dwParam2 != 0)
  1728. {
  1729. //
  1730. // App wants us to do a provider-initiated
  1731. // conference.
  1732. //
  1733. // Try to find the call on this line whose
  1734. // dwAppSpecific field matches the value in
  1735. // pInfo->u.EspMsg.dwParam2. This will be
  1736. // the conference parent.
  1737. //
  1738. DWORD i;
  1739. PDRVLINE pLine;
  1740. PDRVCALL pConfCall = NULL, pCall;
  1741. EnterCriticalSection(
  1742. &gESPGlobals.CallListCritSec
  1743. );
  1744. if (IsValidDrvCall ((PDRVCALL)hdCall, &dwCallInst))
  1745. {
  1746. pLine = (PDRVLINE) ((PDRVCALL) hdCall)->pLine;
  1747. for(
  1748. i = 0;
  1749. i < gESPGlobals.dwNumAddressesPerLine &&
  1750. pConfCall == NULL;
  1751. i++
  1752. )
  1753. {
  1754. pCall = pLine->aAddrs[i].pCalls;
  1755. while (pCall)
  1756. {
  1757. if (pCall->dwAppSpecific ==
  1758. pInfo->u.EspMsg.dwParam2)
  1759. {
  1760. pConfCall = pCall;
  1761. break;
  1762. }
  1763. pCall = pCall->pNext;
  1764. }
  1765. }
  1766. if (pConfCall)
  1767. {
  1768. if (pConfCall->pConfParent == NULL)
  1769. {
  1770. pCall = (PDRVCALL) hdCall;
  1771. pCall->pConfParent = pConfCall;
  1772. pCall->pNextConfChild =
  1773. pConfCall->pNextConfChild;
  1774. pConfCall->pNextConfChild = pCall;
  1775. param2 = (ULONG_PTR) pConfCall->htCall;
  1776. }
  1777. else
  1778. {
  1779. ShowStr(
  1780. TRUE,
  1781. "ERROR: TSPI_lineDevSpecific: " \
  1782. "attempt to initiate conference " \
  1783. "when specifed conf parent " \
  1784. "already a conf child."
  1785. );
  1786. }
  1787. }
  1788. else
  1789. {
  1790. ShowStr(
  1791. TRUE,
  1792. "ERROR: TSPI_lineDevSpecific: " \
  1793. "attempted to initiate conference " \
  1794. "but could not find conf parent " \
  1795. "with specified dwAppSpecific value."
  1796. );
  1797. }
  1798. }
  1799. LeaveCriticalSection(
  1800. &gESPGlobals.CallListCritSec
  1801. );
  1802. }
  1803. if ((lResult = SetCallState(
  1804. (PDRVCALL) hdCall,
  1805. dwCallInst,
  1806. 0xffffffff,
  1807. pInfo->u.EspMsg.dwParam1, //LINECALLSTATE_CONFERENCED
  1808. param2,
  1809. TRUE
  1810. )) != 0)
  1811. {
  1812. info.lResult = lResult;
  1813. }
  1814. }
  1815. else
  1816. {
  1817. info.lResult = LINEERR_OPERATIONFAILED;
  1818. }
  1819. break;
  1820. }
  1821. case LINE_CREATE:
  1822. if (gESPGlobals.pLines->dwNumUsedEntries <
  1823. gESPGlobals.pLines->dwNumTotalEntries)
  1824. {
  1825. (*gESPGlobals.pfnLineEvent)(
  1826. (HTAPILINE) NULL,
  1827. (HTAPICALL) NULL,
  1828. LINE_CREATE,
  1829. (ULONG_PTR) gESPGlobals.hProvider,
  1830. gESPGlobals.pLines->dwNumUsedEntries++,
  1831. 0
  1832. );
  1833. }
  1834. else
  1835. {
  1836. ShowStr(
  1837. TRUE,
  1838. "ERROR: TSPI_lineDevSpecific: attempt " \
  1839. "to send LINE_CREATE - can't create " \
  1840. "any more devices on the fly"
  1841. );
  1842. info.lResult = LINEERR_OPERATIONFAILED;
  1843. }
  1844. break;
  1845. case LINE_NEWCALL: // BUGBUG
  1846. ShowStr(
  1847. TRUE,
  1848. "ERROR: TSPI_lineDevSpecific: no support " \
  1849. "for indicating LINE_NEWCALL yet"
  1850. );
  1851. info.lResult = LINEERR_OPERATIONFAILED;
  1852. break;
  1853. default:
  1854. ShowStr(
  1855. TRUE,
  1856. "ERROR: TSPI_lineDevSpecific: unrecognized " \
  1857. "ESPDEVSPECIFICINFO.u.EspMsg.dwMsg (=x%x)",
  1858. pInfo->u.EspMsg.dwMsg
  1859. );
  1860. info.lResult = LINEERR_OPERATIONFAILED;
  1861. break;
  1862. }
  1863. break;
  1864. case ESP_DEVSPEC_RESULT:
  1865. {
  1866. DWORD dwResult = pInfo->u.EspResult.lResult;
  1867. if (dwResult != 0 &&
  1868. (dwResult < LINEERR_ALLOCATED ||
  1869. dwResult > PHONEERR_REINIT ||
  1870. (dwResult > LINEERR_DIALVOICEDETECT &&
  1871. dwResult < PHONEERR_ALLOCATED)))
  1872. {
  1873. ShowStr(
  1874. TRUE,
  1875. "ERROR: TSPI_lineDevSpecific: invalid request" \
  1876. "result value (x%x)",
  1877. dwResult
  1878. );
  1879. info.lResult = LINEERR_OPERATIONFAILED;
  1880. }
  1881. else if (pInfo->u.EspResult.dwCompletionType >
  1882. ESP_RESULT_CALLCOMPLPROCASYNC)
  1883. {
  1884. ShowStr(
  1885. TRUE,
  1886. "ERROR: TSPI_lineDevSpecific: invalid request" \
  1887. "completion type (x%x)",
  1888. pInfo->u.EspResult.dwCompletionType
  1889. );
  1890. info.lResult = LINEERR_OPERATIONFAILED;
  1891. }
  1892. else
  1893. {
  1894. glNextRequestResult = (LONG) dwResult;
  1895. gdwNextRequestCompletionType =
  1896. pInfo->u.EspResult.dwCompletionType;
  1897. gdwDevSpecificRequestID = dwRequestID;
  1898. }
  1899. break;
  1900. }
  1901. default:
  1902. ShowStr(
  1903. TRUE,
  1904. "ERROR: TSPI_lineDevSpecific: unrecognized " \
  1905. "ESPDEVSPECIFICINFO.dwType (=x%x)",
  1906. pInfo->dwType
  1907. );
  1908. info.lResult = LINEERR_OPERATIONFAILED;
  1909. break;
  1910. }
  1911. }
  1912. else
  1913. {
  1914. info.pAsyncReqInfo->dwParam1 = lpParams;
  1915. info.pAsyncReqInfo->dwParam2 = dwSize;
  1916. info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  1917. TSPI_lineDevSpecific_postProcess;
  1918. }
  1919. }
  1920. return (Epilog (&info));
  1921. }
  1922. LONG
  1923. TSPIAPI
  1924. TSPI_lineDevSpecificFeature(
  1925. DRV_REQUESTID dwRequestID,
  1926. HDRVLINE hdLine,
  1927. DWORD dwFeature,
  1928. LPVOID lpParams,
  1929. DWORD dwSize
  1930. )
  1931. {
  1932. static char szFuncName[] = "lineDevSpecificFeature";
  1933. FUNC_PARAM params[] =
  1934. {
  1935. { szdwRequestID, dwRequestID },
  1936. { szhdLine, hdLine },
  1937. { "dwFeature", dwFeature },
  1938. { "lpParams", lpParams },
  1939. { szdwSize, dwSize }
  1940. };
  1941. FUNC_INFO info =
  1942. {
  1943. szFuncName,
  1944. ASYNC,
  1945. 5,
  1946. params,
  1947. TSPI_lineDevSpecific_postProcess
  1948. };
  1949. if (Prolog (&info))
  1950. {
  1951. info.pAsyncReqInfo->dwParam1 = lpParams;
  1952. info.pAsyncReqInfo->dwParam2 = dwSize;
  1953. }
  1954. return (Epilog (&info));
  1955. }
  1956. void
  1957. FAR
  1958. PASCAL
  1959. TSPI_lineDial_postProcess(
  1960. PASYNC_REQUEST_INFO pAsyncReqInfo,
  1961. BOOL bAsync
  1962. )
  1963. {
  1964. DWORD bDestAddress = (DWORD) pAsyncReqInfo->dwParam3,
  1965. bValidLineID = (DWORD) pAsyncReqInfo->dwParam4,
  1966. dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam6,
  1967. dwCallInstNow;
  1968. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
  1969. pDestCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  1970. PDRVLINE pDestLine = (PDRVLINE) pAsyncReqInfo->dwParam5;
  1971. DoCompletion (pAsyncReqInfo, bAsync);
  1972. if (pAsyncReqInfo->lResult == 0)
  1973. {
  1974. if (bDestAddress)
  1975. {
  1976. if (bValidLineID && !pDestCall)
  1977. {
  1978. SetCallState(
  1979. pCall,
  1980. dwCallInstThen,
  1981. 0xffffffff,
  1982. LINECALLSTATE_BUSY,
  1983. LINEBUSYMODE_UNAVAIL,
  1984. TRUE
  1985. );
  1986. }
  1987. else
  1988. {
  1989. SetCallState(
  1990. pCall,
  1991. dwCallInstThen,
  1992. LINECALLSTATE_DIALTONE,
  1993. LINECALLSTATE_DIALING,
  1994. 0,
  1995. FALSE
  1996. );
  1997. SetCallState(
  1998. pCall,
  1999. dwCallInstThen,
  2000. 0xffffffff,
  2001. LINECALLSTATE_RINGBACK,
  2002. 0,
  2003. TRUE
  2004. );
  2005. }
  2006. if (pDestCall)
  2007. {
  2008. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2009. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  2010. dwCallInstNow == dwCallInstThen)
  2011. {
  2012. SendLineEvent(
  2013. pDestLine,
  2014. NULL,
  2015. LINE_NEWCALL,
  2016. (ULONG_PTR) pDestCall,
  2017. (ULONG_PTR) &pDestCall->htCall,
  2018. 0
  2019. );
  2020. if (pDestCall->htCall != NULL)
  2021. {
  2022. SetCallState(
  2023. pDestCall,
  2024. pDestCall->dwCallInstance,
  2025. 0xffffffff,
  2026. LINECALLSTATE_OFFERING,
  2027. 0,
  2028. TRUE
  2029. );
  2030. }
  2031. else
  2032. {
  2033. FreeCall (pDestCall, pDestCall->dwCallInstance);
  2034. }
  2035. }
  2036. else
  2037. {
  2038. FreeCall (pDestCall, pDestCall->dwCallInstance);
  2039. }
  2040. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2041. }
  2042. }
  2043. else
  2044. {
  2045. SetCallState(
  2046. pCall,
  2047. dwCallInstThen,
  2048. 0xffffffff,
  2049. LINECALLSTATE_DIALTONE,
  2050. 0,
  2051. TRUE
  2052. );
  2053. }
  2054. }
  2055. else
  2056. {
  2057. FreeCall (pCall, dwCallInstThen);
  2058. if (pDestCall)
  2059. {
  2060. FreeCall (pDestCall, pDestCall->dwCallInstance);
  2061. }
  2062. }
  2063. }
  2064. LONG
  2065. TSPIAPI
  2066. TSPI_lineDial(
  2067. DRV_REQUESTID dwRequestID,
  2068. HDRVCALL hdCall,
  2069. LPCWSTR lpszDestAddress,
  2070. DWORD dwCountryCode
  2071. )
  2072. {
  2073. static char szFuncName[] = "lineDial";
  2074. FUNC_PARAM params[] =
  2075. {
  2076. { szdwRequestID, dwRequestID },
  2077. { szhdCall, hdCall },
  2078. { "lpszDestAddress", lpszDestAddress },
  2079. { "dwCountryCode", dwCountryCode }
  2080. };
  2081. FUNC_INFO info = { szFuncName, ASYNC, 4, params, TSPI_lineDial_postProcess };
  2082. if (Prolog (&info))
  2083. {
  2084. BOOL bValidLineID = FALSE;
  2085. LONG lResult;
  2086. PDRVCALL pCall = (PDRVCALL) hdCall, pDestCall;
  2087. PDRVLINE pDestLine;
  2088. LPLINECALLPARAMS const lpCallParams = NULL;
  2089. DWORD dwCallInstance;
  2090. if (IsValidDrvCall (pCall, &dwCallInstance))
  2091. {
  2092. CreateIncomingCall(
  2093. lpszDestAddress,
  2094. lpCallParams,
  2095. pCall,
  2096. &bValidLineID,
  2097. &pDestLine,
  2098. &pDestCall
  2099. );
  2100. info.pAsyncReqInfo->dwParam1 = pCall;
  2101. info.pAsyncReqInfo->dwParam2 = pDestCall;
  2102. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) lpszDestAddress;
  2103. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) bValidLineID;
  2104. info.pAsyncReqInfo->dwParam5 = pDestLine;
  2105. info.pAsyncReqInfo->dwParam6 = pCall->dwCallInstance;
  2106. }
  2107. else
  2108. {
  2109. info.lResult = LINEERR_INVALCALLHANDLE;
  2110. }
  2111. }
  2112. return (Epilog (&info));
  2113. }
  2114. void
  2115. FAR
  2116. PASCAL
  2117. TSPI_lineDrop_postProcess(
  2118. PASYNC_REQUEST_INFO pAsyncReqInfo,
  2119. BOOL bAsync
  2120. )
  2121. {
  2122. if ((pAsyncReqInfo->lResult == 0))
  2123. {
  2124. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  2125. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  2126. //
  2127. // We need to make sure pCall is pointing at a valid call
  2128. // structure because it's possible that tapi immediately
  2129. // followed the drop request with a closeCall request
  2130. // (without waiting for the result from the drop)
  2131. //
  2132. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2133. if (SetCallState(
  2134. pCall,
  2135. dwCallInstThen,
  2136. 0xffffffff,
  2137. LINECALLSTATE_IDLE,
  2138. 0,
  2139. TRUE
  2140. ) == 0)
  2141. {
  2142. if (pCall->pConfParent)
  2143. {
  2144. //
  2145. // Call is a conf child, so remove from conf list
  2146. //
  2147. PDRVCALL pCall2 = pCall->pConfParent;
  2148. while (pCall2 && (pCall2->pNextConfChild != pCall))
  2149. {
  2150. pCall2 = pCall2->pNextConfChild;
  2151. }
  2152. if (pCall2)
  2153. {
  2154. pCall2->pNextConfChild = pCall->pNextConfChild;
  2155. }
  2156. pCall->pConfParent = NULL;
  2157. }
  2158. else if (pCall->pNextConfChild)
  2159. {
  2160. //
  2161. // Call is a conf parent, so IDLE-ize all children &
  2162. // remove them from list
  2163. //
  2164. PDRVCALL pConfChild = pCall->pNextConfChild;
  2165. pCall->pNextConfChild = NULL;
  2166. while (pConfChild)
  2167. {
  2168. PDRVCALL pNextConfChild = pConfChild->pNextConfChild;
  2169. pConfChild->pConfParent =
  2170. pConfChild->pNextConfChild = NULL;
  2171. SetCallState(
  2172. pConfChild,
  2173. pConfChild->dwCallInstance,
  2174. 0xffffffff,
  2175. LINECALLSTATE_IDLE,
  2176. 0,
  2177. TRUE
  2178. );
  2179. pConfChild = pNextConfChild;
  2180. }
  2181. }
  2182. }
  2183. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2184. }
  2185. DoCompletion (pAsyncReqInfo, bAsync);
  2186. }
  2187. LONG
  2188. TSPIAPI
  2189. TSPI_lineDrop(
  2190. DRV_REQUESTID dwRequestID,
  2191. HDRVCALL hdCall,
  2192. LPCSTR lpsUserUserInfo,
  2193. DWORD dwSize
  2194. )
  2195. {
  2196. static char szFuncName[] = "lineDrop";
  2197. FUNC_PARAM params[] =
  2198. {
  2199. { szdwRequestID, dwRequestID },
  2200. { szhdCall, hdCall },
  2201. { "lpsUserUserInfo", lpsUserUserInfo },
  2202. { szdwSize, dwSize }
  2203. };
  2204. FUNC_INFO info =
  2205. {
  2206. szFuncName,
  2207. ASYNC,
  2208. 4,
  2209. params,
  2210. TSPI_lineDrop_postProcess
  2211. };
  2212. if (Prolog (&info))
  2213. {
  2214. DWORD dwCallInstance;
  2215. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  2216. {
  2217. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  2218. info.pAsyncReqInfo->dwParam2 = dwCallInstance;
  2219. }
  2220. else
  2221. {
  2222. info.lResult = LINEERR_INVALCALLHANDLE;
  2223. }
  2224. }
  2225. return (Epilog (&info));
  2226. }
  2227. void
  2228. FAR
  2229. PASCAL
  2230. TSPI_lineForward_postProcess(
  2231. PASYNC_REQUEST_INFO pAsyncReqInfo,
  2232. BOOL bAsync
  2233. )
  2234. {
  2235. DWORD dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  2236. PDRVCALL pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  2237. DoCompletion (pAsyncReqInfo, bAsync);
  2238. if (pAsyncReqInfo->lResult == 0)
  2239. {
  2240. SetCallState(
  2241. pConsultCall,
  2242. dwConsultCallInstThen,
  2243. 0xffffffff, // BUGBUG specify valid call states
  2244. LINECALLSTATE_CONNECTED,
  2245. 0,
  2246. TRUE
  2247. );
  2248. }
  2249. else
  2250. {
  2251. FreeCall (pConsultCall, dwConsultCallInstThen);
  2252. }
  2253. }
  2254. LONG
  2255. TSPIAPI
  2256. TSPI_lineForward(
  2257. DRV_REQUESTID dwRequestID,
  2258. HDRVLINE hdLine,
  2259. DWORD bAllAddresses,
  2260. DWORD dwAddressID,
  2261. LPLINEFORWARDLIST const lpForwardList,
  2262. DWORD dwNumRingsNoAnswer,
  2263. HTAPICALL htConsultCall,
  2264. LPHDRVCALL lphdConsultCall,
  2265. LPLINECALLPARAMS const lpCallParams
  2266. )
  2267. {
  2268. static char szFuncName[] = "lineForward";
  2269. FUNC_PARAM params[] =
  2270. {
  2271. { szdwRequestID, dwRequestID },
  2272. { szhdLine, hdLine },
  2273. { "bAllAddresses", bAllAddresses },
  2274. { "dwAddressID", dwAddressID },
  2275. { "lpForwardList", lpForwardList },
  2276. { "dwNumRingsNoAnswer", dwNumRingsNoAnswer },
  2277. { "htConsultCall", htConsultCall },
  2278. { "lphdConsultCall", lphdConsultCall },
  2279. { szlpCallParams, lpCallParams }
  2280. };
  2281. FUNC_INFO info =
  2282. {
  2283. szFuncName,
  2284. ASYNC,
  2285. 9,
  2286. params,
  2287. TSPI_lineForward_postProcess
  2288. };
  2289. if (Prolog (&info))
  2290. {
  2291. if (bAllAddresses ||
  2292. dwAddressID < gESPGlobals.dwNumAddressesPerLine)
  2293. {
  2294. if (lpForwardList)
  2295. {
  2296. LONG lResult;
  2297. PDRVCALL pConsultCall;
  2298. if ((lResult = AllocCall(
  2299. (PDRVLINE) hdLine,
  2300. htConsultCall,
  2301. lpCallParams,
  2302. &pConsultCall
  2303. )) == 0)
  2304. {
  2305. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) pConsultCall;
  2306. info.pAsyncReqInfo->dwParam2 = pConsultCall->dwCallInstance;
  2307. *lphdConsultCall = (HDRVCALL) pConsultCall;
  2308. }
  2309. else
  2310. {
  2311. info.lResult = lResult;
  2312. }
  2313. }
  2314. else
  2315. {
  2316. info.pAsyncReqInfo->pfnPostProcessProc = NULL;
  2317. *lphdConsultCall = (HDRVCALL) NULL;
  2318. }
  2319. }
  2320. else
  2321. {
  2322. info.lResult = LINEERR_INVALADDRESSID;
  2323. }
  2324. }
  2325. return (Epilog (&info));
  2326. }
  2327. LONG
  2328. TSPIAPI
  2329. TSPI_lineGatherDigits(
  2330. HDRVCALL hdCall,
  2331. DWORD dwEndToEndID,
  2332. DWORD dwDigitModes,
  2333. LPWSTR lpsDigits,
  2334. DWORD dwNumDigits,
  2335. LPCWSTR lpszTerminationDigits,
  2336. DWORD dwFirstDigitTimeout,
  2337. DWORD dwInterDigitTimeout
  2338. )
  2339. {
  2340. static char szFuncName[] = "lineGatherDigits";
  2341. FUNC_PARAM params[] =
  2342. {
  2343. { szhdCall, hdCall },
  2344. { "dwEndToEndID", dwEndToEndID },
  2345. { "dwDigitModes", dwDigitModes, aDigitModes },
  2346. { "lpsDigits", lpsDigits },
  2347. { "dwNumDigits", dwNumDigits },
  2348. { "lpszTerminationDigits", lpszTerminationDigits },
  2349. { "dwFirstDigitTimeout", dwFirstDigitTimeout },
  2350. { "dwInterDigitTimeout", dwInterDigitTimeout }
  2351. };
  2352. FUNC_INFO info = { szFuncName, SYNC, 8, params };
  2353. PDRVCALL pCall = (PDRVCALL) hdCall;
  2354. DWORD dwReason = 0;
  2355. HTAPILINE htLine;
  2356. HTAPICALL htCall;
  2357. if (Prolog (&info))
  2358. {
  2359. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2360. if (IsValidDrvCall (pCall, NULL))
  2361. {
  2362. htLine = ((PDRVLINE) pCall->pLine)->htLine;
  2363. htCall = pCall->htCall;
  2364. if (lpsDigits)
  2365. {
  2366. lstrcpynW (lpsDigits, L"1234567890", dwNumDigits);
  2367. if (dwNumDigits == 10)
  2368. {
  2369. lpsDigits[9] = L'0';
  2370. }
  2371. }
  2372. if (gbAutoGatherGenerateMsgs)
  2373. {
  2374. if (lpsDigits)
  2375. {
  2376. dwReason = (dwNumDigits > 10 ? LINEGATHERTERM_INTERTIMEOUT
  2377. : LINEGATHERTERM_BUFFERFULL);
  2378. }
  2379. }
  2380. else
  2381. {
  2382. DWORD dwEndToEndIDTmp = dwEndToEndID;
  2383. if ((dwEndToEndID = pCall->dwGatherDigitsEndToEndID))
  2384. {
  2385. dwReason = LINEGATHERTERM_CANCEL;
  2386. }
  2387. pCall->dwGatherDigitsEndToEndID = (lpsDigits ?
  2388. dwEndToEndIDTmp : 0);
  2389. }
  2390. }
  2391. else
  2392. {
  2393. htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
  2394. dwReason = (lpsDigits ? LINEGATHERTERM_CANCEL : 0);
  2395. }
  2396. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2397. if (dwReason)
  2398. {
  2399. (gESPGlobals.pfnLineEvent)(
  2400. htLine,
  2401. htCall,
  2402. LINE_GATHERDIGITS,
  2403. dwReason,
  2404. dwEndToEndID,
  2405. 0
  2406. );
  2407. }
  2408. }
  2409. return (Epilog (&info));
  2410. }
  2411. LONG
  2412. TSPIAPI
  2413. TSPI_lineGenerateDigits(
  2414. HDRVCALL hdCall,
  2415. DWORD dwEndToEndID,
  2416. DWORD dwDigitMode,
  2417. LPCWSTR lpszDigits,
  2418. DWORD dwDuration
  2419. )
  2420. {
  2421. static char szFuncName[] = "lineGenerateDigits";
  2422. FUNC_PARAM params[] =
  2423. {
  2424. { szhdCall, hdCall },
  2425. { "dwEndToEndID", dwEndToEndID },
  2426. { "dwDigitMode", dwDigitMode, aDigitModes },
  2427. { "lpszDigits", lpszDigits },
  2428. { "dwDuration", dwDuration }
  2429. };
  2430. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  2431. PDRVCALL pCall = (PDRVCALL) hdCall;
  2432. HTAPILINE htLine, htDestLine = NULL;
  2433. HTAPICALL htCall, htDestCall;
  2434. DWORD dwReason = 0, i;
  2435. if (Prolog (&info))
  2436. {
  2437. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2438. if (IsValidDrvCall (pCall, NULL))
  2439. {
  2440. htLine = ((PDRVLINE) pCall->pLine)->htLine;
  2441. htCall = pCall->htCall;
  2442. if (gbAutoGatherGenerateMsgs)
  2443. {
  2444. dwReason = (lpszDigits ? LINEGENERATETERM_DONE : 0);
  2445. }
  2446. else
  2447. {
  2448. DWORD dwEndToEndIDTmp = dwEndToEndID;
  2449. if ((dwEndToEndID = pCall->dwGenerateDigitsEndToEndID))
  2450. {
  2451. dwReason = LINEGENERATETERM_CANCEL;
  2452. }
  2453. pCall->dwGenerateDigitsEndToEndID = (lpszDigits ?
  2454. dwEndToEndIDTmp : 0);
  2455. }
  2456. if (lpszDigits && IsValidDrvCall (pCall->pDestCall, NULL))
  2457. {
  2458. htDestCall = pCall->pDestCall->htCall;
  2459. htDestLine = ((PDRVLINE) pCall->pDestCall->pLine)->htLine;
  2460. }
  2461. }
  2462. else
  2463. {
  2464. htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
  2465. dwReason = (lpszDigits ? LINEGENERATETERM_CANCEL : 0);
  2466. }
  2467. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2468. if (dwReason)
  2469. {
  2470. (gESPGlobals.pfnLineEvent)(
  2471. htLine,
  2472. htCall,
  2473. LINE_GENERATE,
  2474. dwReason,
  2475. dwEndToEndID,
  2476. 0
  2477. );
  2478. }
  2479. if (htDestLine)
  2480. {
  2481. DWORD dwTickCount = GetTickCount();
  2482. for (i = 0; lpszDigits[i]; i++)
  2483. {
  2484. (gESPGlobals.pfnLineEvent)(
  2485. htDestLine,
  2486. htDestCall,
  2487. LINE_MONITORDIGITS,
  2488. lpszDigits[i],
  2489. dwDigitMode,
  2490. dwTickCount + (2 * i * dwDuration)
  2491. );
  2492. if (dwDigitMode == LINEDIGITMODE_DTMF)
  2493. {
  2494. (gESPGlobals.pfnLineEvent)(
  2495. htDestLine,
  2496. htDestCall,
  2497. LINE_MONITORDIGITS,
  2498. lpszDigits[i],
  2499. LINEDIGITMODE_DTMFEND,
  2500. dwTickCount + (((2 * i) + 1) * dwDuration)
  2501. );
  2502. }
  2503. }
  2504. }
  2505. }
  2506. return (Epilog (&info));
  2507. }
  2508. LONG
  2509. TSPIAPI
  2510. TSPI_lineGenerateTone(
  2511. HDRVCALL hdCall,
  2512. DWORD dwEndToEndID,
  2513. DWORD dwToneMode,
  2514. DWORD dwDuration,
  2515. DWORD dwNumTones,
  2516. LPLINEGENERATETONE const lpTones
  2517. )
  2518. {
  2519. static char szFuncName[] = "lineGenerateTone";
  2520. FUNC_PARAM params[] =
  2521. {
  2522. { szhdCall, hdCall },
  2523. { "dwEndToEndID", dwEndToEndID },
  2524. { "dwToneMode", dwToneMode, aToneModes },
  2525. { "dwDuration", dwDuration },
  2526. { "dwNumTones", dwNumTones },
  2527. { "lpTones", lpTones }
  2528. };
  2529. FUNC_INFO info = { szFuncName, SYNC, 6, params };
  2530. PDRVCALL pCall = (PDRVCALL) hdCall;
  2531. HTAPILINE htLine;
  2532. HTAPICALL htCall;
  2533. DWORD dwReason = 0;
  2534. if (Prolog (&info))
  2535. {
  2536. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2537. if (IsValidDrvCall (pCall, NULL))
  2538. {
  2539. htLine = ((PDRVLINE) pCall->pLine)->htLine;
  2540. htCall = pCall->htCall;
  2541. if (gbAutoGatherGenerateMsgs)
  2542. {
  2543. dwReason = (dwToneMode ? LINEGENERATETERM_DONE : 0);
  2544. }
  2545. else
  2546. {
  2547. DWORD dwEndToEndIDTmp = dwEndToEndID;
  2548. if ((dwEndToEndID = pCall->dwGenerateToneEndToEndID))
  2549. {
  2550. dwReason = LINEGENERATETERM_CANCEL;
  2551. }
  2552. pCall->dwGenerateToneEndToEndID = (dwToneMode ?
  2553. dwEndToEndIDTmp : 0);
  2554. }
  2555. }
  2556. else
  2557. {
  2558. htLine = (HTAPILINE) (htCall = (HTAPICALL) NULL);
  2559. dwReason = (dwToneMode ? LINEGENERATETERM_CANCEL : 0);
  2560. }
  2561. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2562. if (dwReason)
  2563. {
  2564. (gESPGlobals.pfnLineEvent)(
  2565. htLine,
  2566. htCall,
  2567. LINE_GENERATE,
  2568. dwReason,
  2569. dwEndToEndID,
  2570. 0
  2571. );
  2572. }
  2573. }
  2574. return (Epilog (&info));
  2575. }
  2576. LONG
  2577. TSPIAPI
  2578. TSPI_lineGetAddressCaps(
  2579. DWORD dwDeviceID,
  2580. DWORD dwAddressID,
  2581. DWORD dwTSPIVersion,
  2582. DWORD dwExtVersion,
  2583. LPLINEADDRESSCAPS lpAddressCaps
  2584. )
  2585. {
  2586. static char szFuncName[] = "lineGetAddressCaps";
  2587. FUNC_PARAM params[] =
  2588. {
  2589. { szdwDeviceID, dwDeviceID },
  2590. { "dwAddressID", dwAddressID },
  2591. { "dwTSPIVersion", dwTSPIVersion },
  2592. { "dwExtVersion", dwExtVersion },
  2593. { "lpAddressCaps", lpAddressCaps }
  2594. };
  2595. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  2596. DWORD dwUsedSize;
  2597. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  2598. if (!Prolog (&info))
  2599. {
  2600. return (Epilog (&info));
  2601. }
  2602. if (dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
  2603. {
  2604. info.lResult = LINEERR_INVALADDRESSID;
  2605. return (Epilog (&info));
  2606. }
  2607. //lpAddressCaps->dwTotalSize
  2608. //lpAddressCaps->dwNeededSize
  2609. //lpAddressCaps->dwUsedSize
  2610. //lpAddressCaps->dwLineDeviceID
  2611. //
  2612. //lpAddressCaps->dwAddressOffset
  2613. {
  2614. char buf[20];
  2615. WCHAR wbuf[20];
  2616. // NOTE: win9x doesn't support wsprintfW
  2617. wsprintfA (buf, "%d#%d", dwDeviceID, dwAddressID);
  2618. MultiByteToWideChar(
  2619. GetACP(),
  2620. MB_PRECOMPOSED,
  2621. buf,
  2622. lstrlen (buf) + 1,
  2623. wbuf,
  2624. 20
  2625. );
  2626. InsertVarDataString(
  2627. lpAddressCaps,
  2628. &lpAddressCaps->dwAddressSize,
  2629. wbuf
  2630. );
  2631. }
  2632. //lpAddressCaps->dwDevSpecificSize
  2633. //lpAddressCaps->dwDevSpecificOffset
  2634. //lpAddressCaps->dwAddressSharing
  2635. //lpAddressCaps->dwAddressStates
  2636. //lpAddressCaps->dwCallInfoStates
  2637. //lpAddressCaps->dwCallerIDFlags
  2638. //lpAddressCaps->dwCalledIDFlags
  2639. //lpAddressCaps->dwConnectedIDFlags
  2640. //lpAddressCaps->dwRedirectionIDFlags
  2641. //lpAddressCaps->dwRedirectingIDFlags
  2642. //lpAddressCaps->dwCallStates
  2643. //lpAddressCaps->dwDialToneModes
  2644. //lpAddressCaps->dwBusyModes
  2645. //lpAddressCaps->dwSpecialInfo
  2646. //lpAddressCaps->dwDisconnectModes
  2647. lpAddressCaps->dwMaxNumActiveCalls = gESPGlobals.dwNumCallsPerAddress;
  2648. //lpAddressCaps->dwMaxNumOnHoldCalls
  2649. //lpAddressCaps->dwMaxNumOnHoldPendingCalls
  2650. //lpAddressCaps->dwMaxNumConference
  2651. //lpAddressCaps->dwMaxNumTransConf
  2652. lpAddressCaps->dwAddrCapFlags = AllAddrCaps1_0;
  2653. lpAddressCaps->dwCallFeatures = AllCallFeatures1_0;
  2654. //lpAddressCaps->dwRemoveFromConfCaps
  2655. //lpAddressCaps->dwRemoveFromConfState
  2656. //lpAddressCaps->dwTransferModes
  2657. //lpAddressCaps->dwParkModes
  2658. //lpAddressCaps->dwForwardModes
  2659. //lpAddressCaps->dwMaxForwardEntries
  2660. //lpAddressCaps->dwMaxSpecificEntries
  2661. //lpAddressCaps->dwMinFwdNumRings
  2662. //lpAddressCaps->dwMaxFwdNumRings
  2663. //lpAddressCaps->dwMaxCallCompletions
  2664. //lpAddressCaps->dwCallCompletionConds
  2665. //lpAddressCaps->dwCallCompletionModes
  2666. lpAddressCaps->dwNumCompletionMessages = MAX_NUM_COMPLETION_MESSAGES;
  2667. //lpAddressCaps->dwCompletionMsgTextEntrySize
  2668. //lpAddressCaps->dwCompletionMsgTextSize
  2669. //lpAddressCaps->dwCompletionMsgTextOffset
  2670. if (dwTSPIVersion >= 0x00010004)
  2671. {
  2672. lpAddressCaps->dwCallFeatures = AllCallFeatures1_4;
  2673. lpAddressCaps->dwAddressFeatures = AllAddrFeatures1_0;
  2674. if (dwTSPIVersion >= 0x00020000)
  2675. {
  2676. lpAddressCaps->dwAddrCapFlags = AllAddrCaps2_0;
  2677. lpAddressCaps->dwCallFeatures = AllCallFeatures2_0;
  2678. lpAddressCaps->dwAddressFeatures = AllAddrFeatures2_0;
  2679. //lpAddressCaps->dwPredictiveAutoTransferStates
  2680. //lpAddressCaps->dwNumCallTreatments
  2681. //lpAddressCaps->dwCallTreatmentListSize
  2682. //lpAddressCaps->dwCallTreatmentListOffset
  2683. //lpAddressCaps->dwDeviceClassesSize
  2684. //lpAddressCaps->dwDeviceClassesOffset
  2685. //lpAddressCaps->dwMaxCallDataSize
  2686. lpAddressCaps->dwCallFeatures2 = AllCallFeaturesTwo;
  2687. //lpAddressCaps->dwMaxNoAnswerTimeout
  2688. //lpAddressCaps->dwConnectedModes
  2689. //lpAddressCaps->dwOfferingModes
  2690. lpAddressCaps->dwAvailableMediaModes = AllMediaModes1_4;
  2691. if (dwTSPIVersion >= 0x00020001)
  2692. {
  2693. lpAddressCaps->dwAvailableMediaModes = AllMediaModes2_1;
  2694. }
  2695. }
  2696. }
  2697. return (Epilog (&info));
  2698. }
  2699. LONG
  2700. TSPIAPI
  2701. TSPI_lineGetAddressID(
  2702. HDRVLINE hdLine,
  2703. LPDWORD lpdwAddressID,
  2704. DWORD dwAddressMode,
  2705. LPCWSTR lpsAddress,
  2706. DWORD dwSize
  2707. )
  2708. {
  2709. static char szFuncName[] = "lineGetAddressID";
  2710. FUNC_PARAM params[] =
  2711. {
  2712. { szhdLine, hdLine },
  2713. { "lpdwAddressID", lpdwAddressID },
  2714. { "dwAddressMode", dwAddressMode },
  2715. { "lpsAddress", lpsAddress },
  2716. { szdwSize, dwSize }
  2717. };
  2718. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  2719. PDRVLINE pLine = (PDRVLINE) hdLine;
  2720. if (Prolog (&info))
  2721. {
  2722. }
  2723. return (Epilog (&info));
  2724. }
  2725. LONG
  2726. TSPIAPI
  2727. TSPI_lineGetAddressStatus(
  2728. HDRVLINE hdLine,
  2729. DWORD dwAddressID,
  2730. LPLINEADDRESSSTATUS lpAddressStatus
  2731. )
  2732. {
  2733. static char szFuncName[] = "lineGetAddressStatus";
  2734. FUNC_PARAM params[] =
  2735. {
  2736. { szhdLine, hdLine },
  2737. { "dwAddressID", dwAddressID },
  2738. { "lpAddressStatus", lpAddressStatus }
  2739. };
  2740. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  2741. PDRVLINE pLine = (PDRVLINE) hdLine;
  2742. if (!Prolog (&info))
  2743. {
  2744. return (Epilog (&info));
  2745. }
  2746. if (dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
  2747. {
  2748. info.lResult = LINEERR_INVALADDRESSID;
  2749. return (Epilog (&info));
  2750. }
  2751. //lpAddressStatus->dwNeededSize
  2752. //lpAddressStatus->dwUsedSize
  2753. //lpAddressStatus->dwNumInUse
  2754. if (pLine->aAddrs[dwAddressID].dwNumCalls != 0)
  2755. {
  2756. PDRVCALL pCall;
  2757. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2758. for(
  2759. pCall = pLine->aAddrs[dwAddressID].pCalls;
  2760. pCall != NULL;
  2761. pCall = pCall->pNext
  2762. )
  2763. {
  2764. switch (pCall->dwCallState)
  2765. {
  2766. case LINECALLSTATE_IDLE:
  2767. continue;
  2768. case LINECALLSTATE_ONHOLD:
  2769. lpAddressStatus->dwNumOnHoldCalls++;
  2770. continue;
  2771. case LINECALLSTATE_ONHOLDPENDCONF:
  2772. case LINECALLSTATE_ONHOLDPENDTRANSFER:
  2773. lpAddressStatus->dwNumOnHoldPendCalls++;
  2774. continue;
  2775. default:
  2776. lpAddressStatus->dwNumActiveCalls++;
  2777. continue;
  2778. }
  2779. }
  2780. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2781. }
  2782. lpAddressStatus->dwAddressFeatures = (gESPGlobals.dwSPIVersion > 0x10004 ?
  2783. AllAddrFeatures1_0 : AllAddrFeatures2_0);
  2784. //lpAddressStatus->dwNumRingsNoAnswer
  2785. //lpAddressStatus->dwForwardNumEntries
  2786. //lpAddressStatus->dwForwardSize
  2787. //lpAddressStatus->dwForwardOffset
  2788. //lpAddressStatus->dwTerminalModesSize
  2789. //lpAddressStatus->dwTerminalModesOffset
  2790. //lpAddressStatus->dwDevSpecificSize
  2791. //lpAddressStatus->dwDevSpecificOffset
  2792. return (Epilog (&info));
  2793. }
  2794. LONG
  2795. TSPIAPI
  2796. TSPI_lineGetCallAddressID(
  2797. HDRVCALL hdCall,
  2798. LPDWORD lpdwAddressID
  2799. )
  2800. {
  2801. static char szFuncName[] = "lineGetCallAddressID";
  2802. FUNC_PARAM params[] =
  2803. {
  2804. { szhdCall, hdCall },
  2805. { "lpdwAddressID", lpdwAddressID }
  2806. };
  2807. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  2808. if (Prolog (&info))
  2809. {
  2810. *lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
  2811. }
  2812. return (Epilog (&info));
  2813. }
  2814. LONG
  2815. TSPIAPI
  2816. TSPI_lineGetCallHubTracking(
  2817. HDRVLINE hdLine,
  2818. LPLINECALLHUBTRACKINGINFO lpTrackingInfo
  2819. )
  2820. {
  2821. static char szFuncName[] = "lineGetCallHubTracking";
  2822. FUNC_PARAM params[] =
  2823. {
  2824. { szhdLine, hdLine },
  2825. { "lpTrackingInfo", lpTrackingInfo }
  2826. };
  2827. FUNC_INFO info = { szFuncName, SYNC, 2, params, NULL };
  2828. if (Prolog (&info))
  2829. {
  2830. lpTrackingInfo->dwAvailableTracking =
  2831. LINECALLHUBTRACKING_PROVIDERLEVEL | LINECALLHUBTRACKING_ALLCALLS;
  2832. }
  2833. return (Epilog (&info));
  2834. }
  2835. LONG
  2836. TSPIAPI
  2837. TSPI_lineGetCallIDs(
  2838. HDRVCALL hdCall,
  2839. LPDWORD lpdwAddressID,
  2840. LPDWORD lpdwCallID,
  2841. LPDWORD lpdwRelatedCallID
  2842. )
  2843. {
  2844. static char szFuncName[] = "lineGetCallIDs";
  2845. FUNC_PARAM params[] =
  2846. {
  2847. { szhdCall, hdCall },
  2848. { "lpdwAddressID", lpdwAddressID },
  2849. { "lpdwCallID", lpdwCallID },
  2850. { "lpdwRelatedCallID", lpdwRelatedCallID }
  2851. };
  2852. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  2853. if (Prolog (&info))
  2854. {
  2855. try
  2856. {
  2857. *lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
  2858. *lpdwCallID = ((PDRVCALL) hdCall)->dwCallID;
  2859. *lpdwRelatedCallID = ((PDRVCALL) hdCall)->dwRelatedCallID;
  2860. if (((PDRVCALL) hdCall)->dwKey != DRVCALL_KEY)
  2861. {
  2862. info.lResult = LINEERR_INVALCALLHANDLE;
  2863. }
  2864. }
  2865. except (EXCEPTION_EXECUTE_HANDLER)
  2866. {
  2867. info.lResult = LINEERR_INVALCALLHANDLE;
  2868. }
  2869. }
  2870. return (Epilog (&info));
  2871. }
  2872. LONG
  2873. TSPIAPI
  2874. TSPI_lineGetCallInfo(
  2875. HDRVCALL hdCall,
  2876. LPLINECALLINFO lpCallInfo
  2877. )
  2878. {
  2879. static char szFuncName[] = "lineGetCallInfo";
  2880. FUNC_PARAM params[] =
  2881. {
  2882. { szhdCall, hdCall },
  2883. { "lpCallInfo", lpCallInfo }
  2884. };
  2885. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  2886. PDRVCALL pCall = (PDRVCALL) hdCall;
  2887. DWORD dwUsedSize;
  2888. if (Prolog (&info))
  2889. {
  2890. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  2891. if (IsValidDrvCall (pCall, NULL))
  2892. {
  2893. //lpCallInfo->dwNeededSize
  2894. //lpCallInfo->dwUsedSize
  2895. lpCallInfo->dwLineDeviceID = ((PDRVLINE)pCall->pLine)->dwDeviceID;
  2896. lpCallInfo->dwAddressID = pCall->dwAddressID;
  2897. lpCallInfo->dwBearerMode = pCall->dwBearerMode;
  2898. //lpCallInfo->dwRate
  2899. lpCallInfo->dwMediaMode = pCall->dwMediaMode;
  2900. lpCallInfo->dwAppSpecific = pCall->dwAppSpecific;
  2901. lpCallInfo->dwCallID = pCall->dwCallID;
  2902. lpCallInfo->dwRelatedCallID = pCall->dwRelatedCallID;
  2903. //lpCallInfo->dwCallParamFlags
  2904. //lpCallInfo->dwCallStates
  2905. CopyMemory(
  2906. &lpCallInfo->DialParams,
  2907. &pCall->DialParams,
  2908. sizeof(LINEDIALPARAMS)
  2909. );
  2910. //lpCallInfo->dwOrigin
  2911. //lpCallInfo->dwReason
  2912. //lpCallInfo->dwCompletionID
  2913. //lpCallInfo->dwCountryCode
  2914. //lpCallInfo->dwTrunk
  2915. //lpCallInfo->dwCallerIDFlags
  2916. //lpCallInfo->dwCallerIDSize
  2917. //lpCallInfo->dwCallerIDOffset
  2918. //lpCallInfo->dwCallerIDNameSize
  2919. //lpCallInfo->dwCallerIDNameOffset
  2920. //lpCallInfo->dwCalledIDFlags
  2921. //lpCallInfo->dwCalledIDSize
  2922. //lpCallInfo->dwCalledIDOffset
  2923. //lpCallInfo->dwCalledIDNameSize
  2924. //lpCallInfo->dwCalledIDNameOffset
  2925. //lpCallInfo->dwConnectedIDFlags
  2926. //lpCallInfo->dwConnectedIDSize
  2927. //lpCallInfo->dwConnectedIDOffset
  2928. //lpCallInfo->dwConnectedIDNameSize
  2929. //lpCallInfo->dwConnectedIDNameOffset
  2930. //lpCallInfo->dwRedirectionIDFlags
  2931. //lpCallInfo->dwRedirectionIDSize
  2932. //lpCallInfo->dwRedirectionIDOffset
  2933. //lpCallInfo->dwRedirectionIDNameSize
  2934. //lpCallInfo->dwRedirectionIDNameOffset
  2935. //lpCallInfo->dwRedirectingIDFlags
  2936. //lpCallInfo->dwRedirectingIDSize
  2937. //lpCallInfo->dwRedirectingIDOffset
  2938. //lpCallInfo->dwRedirectingIDNameSize
  2939. //lpCallInfo->dwRedirectingIDNameOffset
  2940. //lpCallInfo->dwDisplaySize
  2941. //lpCallInfo->dwDisplayOffset
  2942. //lpCallInfo->dwUserUserInfoSize
  2943. //lpCallInfo->dwUserUserInfoOffset
  2944. //lpCallInfo->dwHighLevelCompSize
  2945. //lpCallInfo->dwHighLevelCompOffset
  2946. //lpCallInfo->dwLowLevelCompSize
  2947. //lpCallInfo->dwLowLevelCompOffset
  2948. //lpCallInfo->dwChargingInfoSize
  2949. //lpCallInfo->dwChargingInfoOffset
  2950. //lpCallInfo->dwTerminalModesSize
  2951. //lpCallInfo->dwTerminalModesOffset
  2952. //lpCallInfo->dwDevSpecificSize
  2953. //lpCallInfo->dwDevSpecificOffset
  2954. if (gESPGlobals.dwSPIVersion >= 0x00020000)
  2955. {
  2956. lpCallInfo->dwCallTreatment = pCall->dwTreatment;
  2957. InsertVarData(
  2958. lpCallInfo,
  2959. &lpCallInfo->dwCallDataSize,
  2960. pCall->pCallData,
  2961. pCall->dwCallDataSize
  2962. );
  2963. InsertVarData(
  2964. lpCallInfo,
  2965. &lpCallInfo->dwSendingFlowspecSize,
  2966. pCall->pSendingFlowspec,
  2967. pCall->dwSendingFlowspecSize
  2968. );
  2969. InsertVarData(
  2970. lpCallInfo,
  2971. &lpCallInfo->dwReceivingFlowspecSize,
  2972. pCall->pReceivingFlowspec,
  2973. pCall->dwReceivingFlowspecSize
  2974. );
  2975. if (gESPGlobals.dwSPIVersion >= 0x00030000)
  2976. {
  2977. // no addresstypes now
  2978. }
  2979. }
  2980. }
  2981. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  2982. }
  2983. return (Epilog (&info));
  2984. }
  2985. LONG
  2986. TSPIAPI
  2987. TSPI_lineGetCallStatus(
  2988. HDRVCALL hdCall,
  2989. LPLINECALLSTATUS lpCallStatus
  2990. )
  2991. {
  2992. DWORD dwCallState, dwCallStateMode;
  2993. static char szFuncName[] = "lineGetCallStatus";
  2994. FUNC_PARAM params[] =
  2995. {
  2996. { szhdCall, hdCall },
  2997. { "lpCallStatus", lpCallStatus }
  2998. };
  2999. PDRVCALL pCall = (PDRVCALL) hdCall;
  3000. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  3001. if (!Prolog (&info))
  3002. {
  3003. return (Epilog (&info));
  3004. }
  3005. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3006. if (IsValidDrvCall (pCall, NULL))
  3007. {
  3008. dwCallState = pCall->dwCallState;
  3009. dwCallStateMode = pCall->dwCallStateMode;
  3010. }
  3011. else
  3012. {
  3013. info.lResult = LINEERR_INVALCALLHANDLE;
  3014. }
  3015. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3016. if (info.lResult == 0)
  3017. {
  3018. //lpCallStatus->dwNeededSize
  3019. //lpCallStatus->dwUsedSize
  3020. lpCallStatus->dwCallState = dwCallState;
  3021. lpCallStatus->dwCallStateMode = dwCallStateMode;
  3022. //
  3023. // If the call is IDLE we won't let apps do anything with it,
  3024. // otherwise they can do anything they want to (all valid
  3025. // 1.0/1.4 LINECALLFEATURE_XXX flags)
  3026. //
  3027. switch (dwCallState)
  3028. {
  3029. case LINECALLSTATE_IDLE:
  3030. lpCallStatus->dwCallFeatures = 0;
  3031. break;
  3032. default:
  3033. lpCallStatus->dwCallFeatures =
  3034. (gESPGlobals.dwSPIVersion == 0x10003 ?
  3035. AllCallFeatures1_0 : AllCallFeatures1_4);
  3036. break;
  3037. }
  3038. //lpCallStatus->dwDevSpecificSize
  3039. //lpCallStatus->dwDevSpecificOffset
  3040. if (gESPGlobals.dwSPIVersion >= 0x00020000)
  3041. {
  3042. switch (dwCallState)
  3043. {
  3044. case LINECALLSTATE_IDLE:
  3045. lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLDATA;
  3046. break;
  3047. default:
  3048. lpCallStatus->dwCallFeatures = AllCallFeatures2_0;
  3049. lpCallStatus->dwCallFeatures2 = AllCallFeaturesTwo;
  3050. break;
  3051. }
  3052. //lpCallStatus->dwCallFeatures2
  3053. //lpCallStatus->tStateEntryTime
  3054. }
  3055. }
  3056. return (Epilog (&info));
  3057. }
  3058. LONG
  3059. TSPIAPI
  3060. TSPI_lineGetDevCaps(
  3061. DWORD dwDeviceID,
  3062. DWORD dwTSPIVersion,
  3063. DWORD dwExtVersion,
  3064. LPLINEDEVCAPS lpLineDevCaps
  3065. )
  3066. {
  3067. static char szFuncName[] = "lineGetDevCaps";
  3068. FUNC_PARAM params[] =
  3069. {
  3070. { szdwDeviceID, dwDeviceID },
  3071. { "dwTSPIVersion", dwTSPIVersion },
  3072. { "dwExtVersion", dwExtVersion },
  3073. { "lpLineDevCaps", lpLineDevCaps }
  3074. };
  3075. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  3076. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  3077. char buf[32];
  3078. WCHAR wbuf[32];
  3079. if (!Prolog (&info))
  3080. {
  3081. return (Epilog (&info));
  3082. }
  3083. InsertVarDataString(
  3084. lpLineDevCaps,
  3085. &lpLineDevCaps->dwProviderInfoSize,
  3086. gszProviderInfo
  3087. );
  3088. InsertVarDataString(
  3089. lpLineDevCaps,
  3090. &lpLineDevCaps->dwSwitchInfoSize,
  3091. L"ESP switch info"
  3092. );
  3093. //smarandb - adding "linedevice specific info", as a Null terminated string ----------
  3094. InsertVarDataString(
  3095. lpLineDevCaps,
  3096. &lpLineDevCaps->dwDevSpecificSize,
  3097. L"123"
  3098. );
  3099. //------------------------------------------------------------------------------------
  3100. lpLineDevCaps->dwPermanentLineID =
  3101. (gESPGlobals.dwPermanentProviderID << 16) |
  3102. (dwDeviceID - gESPGlobals.dwLineDeviceIDBase);
  3103. // NOTE: win9x doesn't support wsprintfW
  3104. wsprintfA (buf, "ESP Line %d", dwDeviceID);
  3105. MultiByteToWideChar(
  3106. GetACP(),
  3107. MB_PRECOMPOSED,
  3108. buf,
  3109. lstrlen (buf) + 1,
  3110. wbuf,
  3111. 20
  3112. );
  3113. InsertVarDataString(
  3114. lpLineDevCaps,
  3115. &lpLineDevCaps->dwLineNameSize,
  3116. wbuf
  3117. );
  3118. lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
  3119. lpLineDevCaps->dwAddressModes = LINEADDRESSMODE_ADDRESSID |
  3120. LINEADDRESSMODE_DIALABLEADDR;
  3121. lpLineDevCaps->dwNumAddresses = gESPGlobals.dwNumAddressesPerLine;
  3122. lpLineDevCaps->dwBearerModes = AllBearerModes1_0;
  3123. lpLineDevCaps->dwMaxRate = 0x00100000;
  3124. lpLineDevCaps->dwMediaModes = AllMediaModes1_0;
  3125. //lpLineDevCaps->dwGenerateToneModes
  3126. //lpLineDevCaps->dwGenerateToneMaxNumFreq
  3127. //lpLineDevCaps->dwGenerateDigitModes
  3128. //lpLineDevCaps->dwMonitorToneMaxNumFreq
  3129. //lpLineDevCaps->dwMonitorToneMaxNumEntries
  3130. //lpLineDevCaps->dwMonitorDigitModes
  3131. //lpLineDevCaps->dwGatherDigitsMinTimeout
  3132. //lpLineDevCaps->dwGatherDigitsMaxTimeout
  3133. //lpLineDevCaps->dwMedCtlDigitMaxListSize
  3134. //lpLineDevCaps->dwMedCtlMediaMaxListSize
  3135. //lpLineDevCaps->dwMedCtlToneMaxListSize;
  3136. //lpLineDevCaps->dwMedCtlCallStateMaxListSize
  3137. //lpLineDevCaps->dwDevCapFlags
  3138. lpLineDevCaps->dwMaxNumActiveCalls = gESPGlobals.dwNumAddressesPerLine *
  3139. gESPGlobals.dwNumCallsPerAddress;
  3140. //lpLineDevCaps->dwAnswerMode
  3141. //lpLineDevCaps->dwRingModes
  3142. //lpLineDevCaps->dwLineStates
  3143. //lpLineDevCaps->dwUUIAcceptSize
  3144. //lpLineDevCaps->dwUUIAnswerSize
  3145. //lpLineDevCaps->dwUUIMakeCallSize
  3146. //lpLineDevCaps->dwUUIDropSize
  3147. //lpLineDevCaps->dwUUISendUserUserInfoSize
  3148. //lpLineDevCaps->dwUUICallInfoSize
  3149. //lpLineDevCaps->MinDialParams
  3150. //lpLineDevCaps->MaxDialParams
  3151. //lpLineDevCaps->DefaultDialParams
  3152. //lpLineDevCaps->dwNumTerminals
  3153. //lpLineDevCaps->dwTerminalCapsSize
  3154. //lpLineDevCaps->dwTerminalCapsOffset
  3155. //lpLineDevCaps->dwTerminalTextEntrySize
  3156. //lpLineDevCaps->dwTerminalTextSize;
  3157. //lpLineDevCaps->dwTerminalTextOffset
  3158. //lpLineDevCaps->dwDevSpecificSize
  3159. //lpLineDevCaps->dwDevSpecificOffset
  3160. if (dwTSPIVersion >= 0x00010004)
  3161. {
  3162. lpLineDevCaps->dwBearerModes = AllBearerModes1_4;
  3163. lpLineDevCaps->dwMediaModes = AllMediaModes1_4;
  3164. lpLineDevCaps->dwLineFeatures = AllLineFeatures1_0;
  3165. if (dwTSPIVersion >= 0x00020000)
  3166. {
  3167. lpLineDevCaps->dwBearerModes = AllBearerModes2_0;
  3168. lpLineDevCaps->dwLineFeatures = AllLineFeatures2_0;
  3169. //lpLineDevCaps->dwSettableDevStatus
  3170. //lpLineDevCaps->dwDeviceClassesSize
  3171. //lpLineDevCaps->dwDeviceClassesOffset
  3172. if (dwTSPIVersion >= 0x00020001)
  3173. {
  3174. lpLineDevCaps->dwMediaModes = AllMediaModes2_1;
  3175. if (dwTSPIVersion >= 0x00020002)
  3176. {
  3177. *((LPDWORD) &lpLineDevCaps->PermanentLineGuid.Data2) =
  3178. *((LPDWORD) &lpLineDevCaps->PermanentLineGuid.Data4[0]) =
  3179. *((LPDWORD) &lpLineDevCaps->PermanentLineGuid.Data4[4]) =
  3180. DRVLINE_KEY;
  3181. if (dwTSPIVersion >= 0x00030000)
  3182. {
  3183. lpLineDevCaps->dwAddressTypes =
  3184. LINEADDRESSTYPE_PHONENUMBER |
  3185. LINEADDRESSTYPE_SDP |
  3186. LINEADDRESSTYPE_EMAILNAME |
  3187. LINEADDRESSTYPE_DOMAINNAME |
  3188. LINEADDRESSTYPE_IPADDRESS;
  3189. lpLineDevCaps->dwAvailableTracking =
  3190. LINECALLHUBTRACKING_ALLCALLS;
  3191. lpLineDevCaps->PermanentLineGuid.Data1 = (long)
  3192. (dwDeviceID - gESPGlobals.dwLineDeviceIDBase);
  3193. }
  3194. }
  3195. }
  3196. }
  3197. }
  3198. return (Epilog (&info));
  3199. }
  3200. LONG
  3201. TSPIAPI
  3202. TSPI_lineGetDevConfig(
  3203. DWORD dwDeviceID,
  3204. LPVARSTRING lpDeviceConfig,
  3205. LPCWSTR lpszDeviceClass
  3206. )
  3207. {
  3208. static char szFuncName[] = "lineGetDevConfig";
  3209. FUNC_PARAM params[] =
  3210. {
  3211. { szdwDeviceID, dwDeviceID },
  3212. { "lpDeviceConfig", lpDeviceConfig },
  3213. { "lpszDeviceClass", lpszDeviceClass }
  3214. };
  3215. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  3216. if (Prolog (&info))
  3217. {
  3218. // BUGBUG TSPI_lineGetDevConfig: fill in dev config
  3219. }
  3220. return (Epilog (&info));
  3221. }
  3222. LONG
  3223. TSPIAPI
  3224. TSPI_lineGetExtensionID(
  3225. DWORD dwDeviceID,
  3226. DWORD dwTSPIVersion,
  3227. LPLINEEXTENSIONID lpExtensionID
  3228. )
  3229. {
  3230. static char szFuncName[] = "lineGetExtensionID";
  3231. FUNC_PARAM params[] =
  3232. {
  3233. { szdwDeviceID, dwDeviceID },
  3234. { "dwTSPIVersion", dwTSPIVersion },
  3235. { "lpExtensionID", lpExtensionID }
  3236. };
  3237. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  3238. if (Prolog (&info))
  3239. {
  3240. // BUGBUG TSPI_lineGetExtensionID: fill in ext id
  3241. }
  3242. return (Epilog (&info));
  3243. }
  3244. LONG
  3245. TSPIAPI
  3246. TSPI_lineGetIcon(
  3247. DWORD dwDeviceID,
  3248. LPCWSTR lpszDeviceClass,
  3249. LPHICON lphIcon
  3250. )
  3251. {
  3252. static char szFuncName[] = "lineGetIcon";
  3253. FUNC_PARAM params[] =
  3254. {
  3255. { szdwDeviceID, dwDeviceID },
  3256. { "lpszDeviceClass", lpszDeviceClass },
  3257. { "lphIcon", lphIcon }
  3258. };
  3259. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  3260. if (Prolog (&info))
  3261. {
  3262. if (lpszDeviceClass &&
  3263. My_lstrcmpiW (
  3264. (WCHAR *) lpszDeviceClass,
  3265. (WCHAR *) (L"tapi/InvalidDeviceClass")
  3266. ) == 0)
  3267. {
  3268. info.lResult = LINEERR_INVALDEVICECLASS;
  3269. }
  3270. else
  3271. {
  3272. *lphIcon = gESPGlobals.hIconLine;
  3273. }
  3274. }
  3275. return (Epilog (&info));
  3276. }
  3277. LONG
  3278. TSPIAPI
  3279. TSPI_lineGetID(
  3280. HDRVLINE hdLine,
  3281. DWORD dwAddressID,
  3282. HDRVCALL hdCall,
  3283. DWORD dwSelect,
  3284. LPVARSTRING lpDeviceID,
  3285. LPCWSTR lpszDeviceClass,
  3286. HANDLE hTargetProcess
  3287. )
  3288. {
  3289. static char szFuncName[] = "lineGetID";
  3290. FUNC_PARAM params[] =
  3291. {
  3292. { szhdLine, hdLine },
  3293. { "dwAddressID", dwAddressID },
  3294. { szhdCall, hdCall },
  3295. { "dwSelect", dwSelect, aCallSelects },
  3296. { "lpDeviceID", lpDeviceID },
  3297. { "lpszDeviceClass", lpszDeviceClass },
  3298. { "hTargetProcess", hTargetProcess }
  3299. };
  3300. FUNC_INFO info = { szFuncName, SYNC, 7, params };
  3301. PDRVLINE pLine = (PDRVLINE) hdLine;
  3302. PDRVCALL pCall = (PDRVCALL) hdCall;
  3303. DWORD i, dwDeviceID, dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
  3304. if (!Prolog (&info))
  3305. {
  3306. return (Epilog (&info));
  3307. }
  3308. for (i = 0; aszDeviceClasses[i]; i++)
  3309. {
  3310. if (My_lstrcmpiW(
  3311. (WCHAR *) lpszDeviceClass,
  3312. (WCHAR *) aszDeviceClasses[i]
  3313. ) == 0)
  3314. {
  3315. break;
  3316. }
  3317. }
  3318. if (!aszDeviceClasses[i])
  3319. {
  3320. info.lResult = LINEERR_NODEVICE;
  3321. return (Epilog (&info));
  3322. }
  3323. if (dwSelect == LINECALLSELECT_ADDRESS &&
  3324. dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
  3325. {
  3326. info.lResult = LINEERR_INVALADDRESSID;
  3327. return (Epilog (&info));
  3328. }
  3329. if (lpDeviceID->dwTotalSize < dwNeededSize)
  3330. {
  3331. lpDeviceID->dwNeededSize = dwNeededSize;
  3332. lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
  3333. return (Epilog (&info));
  3334. }
  3335. switch (i)
  3336. {
  3337. case 0:
  3338. // tapi/line
  3339. if (dwSelect == LINECALLSELECT_CALL)
  3340. {
  3341. dwDeviceID = ((PDRVLINE) pCall->pLine)->dwDeviceID;
  3342. }
  3343. else
  3344. {
  3345. dwDeviceID = pLine->dwDeviceID;
  3346. }
  3347. break;
  3348. case 1:
  3349. // tapi/phone
  3350. dwDeviceID = gESPGlobals.dwPhoneDeviceIDBase;
  3351. break;
  3352. default:
  3353. dwDeviceID = 0;
  3354. break;
  3355. }
  3356. lpDeviceID->dwNeededSize =
  3357. lpDeviceID->dwUsedSize = dwNeededSize;
  3358. lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
  3359. lpDeviceID->dwStringSize = sizeof(DWORD);
  3360. lpDeviceID->dwStringOffset = sizeof(VARSTRING);
  3361. *((LPDWORD)(lpDeviceID + 1)) = dwDeviceID;
  3362. return (Epilog (&info));
  3363. }
  3364. LONG
  3365. TSPIAPI
  3366. TSPI_lineGetLineDevStatus(
  3367. HDRVLINE hdLine,
  3368. LPLINEDEVSTATUS lpLineDevStatus
  3369. )
  3370. {
  3371. static char szFuncName[] = "lineGetLineDevStatus";
  3372. FUNC_PARAM params[] =
  3373. {
  3374. { szhdLine, hdLine },
  3375. { "lpLineDevStatus", lpLineDevStatus }
  3376. };
  3377. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  3378. PDRVLINE pLine = (PDRVLINE) hdLine;
  3379. DWORD dwTotalSize, dwNeededSize;
  3380. if (!Prolog (&info))
  3381. {
  3382. return (Epilog (&info));
  3383. }
  3384. //lpLineDevStatus->dwNeededSize
  3385. //lpLineDevStatus->dwUsedSize
  3386. //lpLineDevStatus->dwNumOpens tapi fills this in
  3387. //lpLineDevStatus->dwOpenMediaModes tapi fills this in
  3388. //
  3389. // Safely determine the # of active, on hold, & onhold pending
  3390. // conference/transfer calls on this line
  3391. //
  3392. {
  3393. DWORD i;
  3394. PDRVCALL pCall;
  3395. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3396. for (i = 0; i < gESPGlobals.dwNumAddressesPerLine; i++)
  3397. {
  3398. for(
  3399. pCall = pLine->aAddrs[i].pCalls;
  3400. pCall != NULL;
  3401. pCall = pCall->pNext
  3402. )
  3403. {
  3404. switch (pCall->dwCallState)
  3405. {
  3406. case LINECALLSTATE_IDLE:
  3407. continue;
  3408. case LINECALLSTATE_ONHOLD:
  3409. lpLineDevStatus->dwNumOnHoldCalls++;
  3410. continue;
  3411. case LINECALLSTATE_ONHOLDPENDCONF:
  3412. case LINECALLSTATE_ONHOLDPENDTRANSFER:
  3413. lpLineDevStatus->dwNumOnHoldPendCalls++;
  3414. continue;
  3415. default:
  3416. lpLineDevStatus->dwNumActiveCalls++;
  3417. continue;
  3418. }
  3419. }
  3420. }
  3421. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3422. }
  3423. lpLineDevStatus->dwLineFeatures = AllLineFeatures1_0;
  3424. //lpLineDevStatus->dwNumCallCompletions
  3425. //lpLineDevStatus->dwRingMode
  3426. //lpLineDevStatus->dwSignalLevel
  3427. //lpLineDevStatus->dwBatteryLevel
  3428. //lpLineDevStatus->dwRoamMode
  3429. lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
  3430. LINEDEVSTATUSFLAGS_INSERVICE |
  3431. pLine->dwMSGWAITFlag; //smarandb #23974 winseqfe
  3432. //lpLineDevStatus->dwTerminalModesSize
  3433. //lpLineDevStatus->dwTerminalModesOffset
  3434. //lpLineDevStatus->dwDevSpecificSize
  3435. //lpLineDevStatus->dwDevSpecificOffset
  3436. if (gESPGlobals.dwSPIVersion >= 0x20000)
  3437. {
  3438. lpLineDevStatus->dwLineFeatures = AllLineFeatures2_0;
  3439. lpLineDevStatus->dwAvailableMediaModes = AllMediaModes1_4;
  3440. //lpLineDevStatus->dwAppInfoSize; tapi fills this in
  3441. //lpLineDevStatus->dwAppInfoOffset; tapi fills this in
  3442. if (gESPGlobals.dwSPIVersion >= 0x20001)
  3443. {
  3444. lpLineDevStatus->dwAvailableMediaModes = AllMediaModes2_1;
  3445. }
  3446. }
  3447. return (Epilog (&info));
  3448. }
  3449. LONG
  3450. TSPIAPI
  3451. TSPI_lineGetNumAddressIDs(
  3452. HDRVLINE hdLine,
  3453. LPDWORD lpdwNumAddressIDs
  3454. )
  3455. {
  3456. static char szFuncName[] = "lineGetNumAddressIDs";
  3457. FUNC_PARAM params[] =
  3458. {
  3459. { szhdLine, hdLine },
  3460. { "lpdwNumAddressIDs", lpdwNumAddressIDs }
  3461. };
  3462. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  3463. PDRVLINE pLine = (PDRVLINE) hdLine;
  3464. if (Prolog (&info))
  3465. {
  3466. *lpdwNumAddressIDs = gESPGlobals.dwNumAddressesPerLine;
  3467. }
  3468. return (Epilog (&info));
  3469. }
  3470. void
  3471. FAR
  3472. PASCAL
  3473. TSPI_lineHold_postProcess(
  3474. PASYNC_REQUEST_INFO pAsyncReqInfo,
  3475. BOOL bAsync
  3476. )
  3477. {
  3478. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  3479. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  3480. if (pAsyncReqInfo->lResult == 0)
  3481. {
  3482. pAsyncReqInfo->lResult = SetCallState(
  3483. pCall,
  3484. dwCallInstThen,
  3485. LINECALLSTATE_CONNECTED,
  3486. LINECALLSTATE_ONHOLD,
  3487. 0,
  3488. TRUE
  3489. );
  3490. }
  3491. DoCompletion (pAsyncReqInfo, bAsync);
  3492. }
  3493. LONG
  3494. TSPIAPI
  3495. TSPI_lineHold(
  3496. DRV_REQUESTID dwRequestID,
  3497. HDRVCALL hdCall
  3498. )
  3499. {
  3500. static char szFuncName[] = "lineHold";
  3501. FUNC_PARAM params[] =
  3502. {
  3503. { szdwRequestID, dwRequestID },
  3504. { szhdCall, hdCall }
  3505. };
  3506. FUNC_INFO info =
  3507. {
  3508. szFuncName,
  3509. ASYNC,
  3510. 2,
  3511. params,
  3512. TSPI_lineHold_postProcess
  3513. };
  3514. if (Prolog (&info))
  3515. {
  3516. DWORD dwCallInstance;
  3517. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  3518. {
  3519. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  3520. info.pAsyncReqInfo->dwParam2 = dwCallInstance;
  3521. }
  3522. else
  3523. {
  3524. info.lResult = LINEERR_INVALCALLHANDLE;
  3525. }
  3526. }
  3527. return (Epilog (&info));
  3528. }
  3529. void
  3530. FAR
  3531. PASCAL
  3532. TSPI_lineMakeCall_postProcess(
  3533. PASYNC_REQUEST_INFO pAsyncReqInfo,
  3534. BOOL bAsync
  3535. )
  3536. {
  3537. DWORD bDestAddress = (DWORD) pAsyncReqInfo->dwParam3,
  3538. bValidLineID = (DWORD) pAsyncReqInfo->dwParam4,
  3539. dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam6,
  3540. dwCallInstNow;
  3541. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
  3542. pDestCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  3543. PDRVLINE pDestLine = (PDRVLINE) pAsyncReqInfo->dwParam5;
  3544. DoCompletion (pAsyncReqInfo, bAsync);
  3545. if (pAsyncReqInfo->lResult == 0)
  3546. {
  3547. if (bDestAddress)
  3548. {
  3549. if (bValidLineID && !pDestCall)
  3550. {
  3551. SetCallState(
  3552. pCall,
  3553. dwCallInstThen,
  3554. 0xffffffff,
  3555. LINECALLSTATE_BUSY,
  3556. LINEBUSYMODE_UNAVAIL,
  3557. TRUE
  3558. );
  3559. }
  3560. else
  3561. {
  3562. SetCallState(
  3563. pCall,
  3564. dwCallInstThen,
  3565. 0xffffffff,
  3566. LINECALLSTATE_DIALING,
  3567. 0,
  3568. FALSE
  3569. );
  3570. SetCallState(
  3571. pCall,
  3572. dwCallInstThen,
  3573. 0xffffffff,
  3574. LINECALLSTATE_RINGBACK,
  3575. 0,
  3576. TRUE
  3577. );
  3578. }
  3579. if (pDestCall)
  3580. {
  3581. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3582. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  3583. dwCallInstNow == dwCallInstThen)
  3584. {
  3585. SendLineEvent(
  3586. pDestLine,
  3587. NULL,
  3588. LINE_NEWCALL,
  3589. (ULONG_PTR) pDestCall,
  3590. (ULONG_PTR) &pDestCall->htCall,
  3591. 0
  3592. );
  3593. if (pDestCall->htCall != NULL)
  3594. {
  3595. SetCallState(
  3596. pDestCall,
  3597. pDestCall->dwCallInstance,
  3598. 0xffffffff,
  3599. LINECALLSTATE_OFFERING,
  3600. 0,
  3601. TRUE
  3602. );
  3603. }
  3604. else
  3605. {
  3606. FreeCall (pDestCall, pDestCall->dwCallInstance);
  3607. }
  3608. }
  3609. else
  3610. {
  3611. FreeCall (pDestCall, pDestCall->dwCallInstance);
  3612. }
  3613. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3614. }
  3615. }
  3616. else
  3617. {
  3618. SetCallState(
  3619. pCall,
  3620. dwCallInstThen,
  3621. 0xffffffff,
  3622. LINECALLSTATE_DIALTONE,
  3623. 0,
  3624. TRUE
  3625. );
  3626. }
  3627. }
  3628. else
  3629. {
  3630. FreeCall (pCall, dwCallInstThen);
  3631. if (pDestCall)
  3632. {
  3633. FreeCall (pDestCall, pDestCall->dwCallInstance);
  3634. }
  3635. }
  3636. }
  3637. LONG
  3638. TSPIAPI
  3639. TSPI_lineMakeCall(
  3640. DRV_REQUESTID dwRequestID,
  3641. HDRVLINE hdLine,
  3642. HTAPICALL htCall,
  3643. LPHDRVCALL lphdCall,
  3644. LPCWSTR lpszDestAddress,
  3645. DWORD dwCountryCode,
  3646. LPLINECALLPARAMS const lpCallParams
  3647. )
  3648. {
  3649. static char szFuncName[] = "lineMakeCall";
  3650. FUNC_PARAM params[] =
  3651. {
  3652. { szdwRequestID, dwRequestID },
  3653. { szhdLine, hdLine },
  3654. { "htCall", htCall },
  3655. { "lphdCall", lphdCall },
  3656. { "lpszDestAddress", lpszDestAddress },
  3657. { "dwCountryCode", dwCountryCode },
  3658. { szlpCallParams, lpCallParams }
  3659. };
  3660. FUNC_INFO info =
  3661. {
  3662. szFuncName,
  3663. ASYNC,
  3664. 7,
  3665. params,
  3666. TSPI_lineMakeCall_postProcess
  3667. };
  3668. if (Prolog (&info))
  3669. {
  3670. BOOL bValidLineID = FALSE;
  3671. LONG lResult;
  3672. PDRVCALL pCall, pDestCall;
  3673. PDRVLINE pLine = (PDRVLINE) hdLine, pDestLine;
  3674. if ((lResult = AllocCall (pLine, htCall, lpCallParams, &pCall)) == 0)
  3675. {
  3676. *lphdCall = (HDRVCALL) pCall;
  3677. CreateIncomingCall(
  3678. lpszDestAddress,
  3679. lpCallParams,
  3680. pCall,
  3681. &bValidLineID,
  3682. &pDestLine,
  3683. &pDestCall
  3684. );
  3685. info.pAsyncReqInfo->dwParam1 = pCall;
  3686. info.pAsyncReqInfo->dwParam2 = pDestCall;
  3687. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) lpszDestAddress;
  3688. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) bValidLineID;
  3689. info.pAsyncReqInfo->dwParam5 = pDestLine;
  3690. info.pAsyncReqInfo->dwParam6 = pCall->dwCallInstance;
  3691. }
  3692. else
  3693. {
  3694. info.lResult = lResult;
  3695. }
  3696. }
  3697. return (Epilog (&info));
  3698. }
  3699. LONG
  3700. TSPIAPI
  3701. TSPI_lineMonitorDigits(
  3702. HDRVCALL hdCall,
  3703. DWORD dwDigitModes
  3704. )
  3705. {
  3706. static char szFuncName[] = "lineMonitorDigits";
  3707. FUNC_PARAM params[] =
  3708. {
  3709. { szhdCall, hdCall },
  3710. { "dwDigitModes", dwDigitModes, aDigitModes }
  3711. };
  3712. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  3713. PDRVCALL pCall = (PDRVCALL) hdCall;
  3714. if (Prolog (&info))
  3715. {
  3716. }
  3717. return (Epilog (&info));
  3718. }
  3719. LONG
  3720. TSPIAPI
  3721. TSPI_lineMonitorMedia(
  3722. HDRVCALL hdCall,
  3723. DWORD dwMediaModes
  3724. )
  3725. {
  3726. static char szFuncName[] = "lineMonitorMedia";
  3727. FUNC_PARAM params[] =
  3728. {
  3729. { szhdCall, hdCall },
  3730. { "dwMediaModes", dwMediaModes, aMediaModes }
  3731. };
  3732. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  3733. PDRVCALL pCall = (PDRVCALL) hdCall;
  3734. if (Prolog (&info))
  3735. {
  3736. }
  3737. return (Epilog (&info));
  3738. }
  3739. LONG
  3740. TSPIAPI
  3741. TSPI_lineMonitorTones(
  3742. HDRVCALL hdCall,
  3743. DWORD dwToneListID,
  3744. LPLINEMONITORTONE const lpToneList,
  3745. DWORD dwNumEntries
  3746. )
  3747. {
  3748. static char szFuncName[] = "lineMonitorTones";
  3749. FUNC_PARAM params[] =
  3750. {
  3751. { szhdCall, hdCall },
  3752. { "dwToneListID", dwToneListID },
  3753. { "lpToneList", lpToneList },
  3754. { "dwNumEntries", dwNumEntries }
  3755. };
  3756. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  3757. PDRVCALL pCall = (PDRVCALL) hdCall;
  3758. if (Prolog (&info))
  3759. {
  3760. DWORD dwLastToneListID = 0;
  3761. HTAPICALL htCall;
  3762. HTAPILINE htLine;
  3763. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3764. if (IsValidDrvCall (pCall, NULL))
  3765. {
  3766. htLine = ((PDRVLINE) pCall->pLine)->htLine;
  3767. htCall = pCall->htCall;
  3768. if (gbAutoGatherGenerateMsgs)
  3769. {
  3770. dwLastToneListID = dwToneListID;
  3771. }
  3772. else
  3773. {
  3774. dwLastToneListID = pCall->dwMonitorToneListID;
  3775. pCall->dwMonitorToneListID = dwToneListID;
  3776. }
  3777. }
  3778. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3779. if (dwLastToneListID)
  3780. {
  3781. (gESPGlobals.pfnLineEvent)(
  3782. htLine,
  3783. htCall,
  3784. LINE_MONITORTONE,
  3785. 0,
  3786. dwLastToneListID,
  3787. 0
  3788. );
  3789. }
  3790. }
  3791. return (Epilog (&info));
  3792. }
  3793. LONG
  3794. TSPIAPI
  3795. TSPI_lineNegotiateExtVersion(
  3796. DWORD dwDeviceID,
  3797. DWORD dwTSPIVersion,
  3798. DWORD dwLowVersion,
  3799. DWORD dwHighVersion,
  3800. LPDWORD lpdwExtVersion
  3801. )
  3802. {
  3803. static char szFuncName[] = "lineNegotiateExtVersion";
  3804. FUNC_PARAM params[] =
  3805. {
  3806. { szdwDeviceID, dwDeviceID },
  3807. { "dwTSPIVersion", dwTSPIVersion },
  3808. { "dwLowVersion", dwLowVersion },
  3809. { "dwHighVersion", dwHighVersion },
  3810. { "lpdwExtVersion", lpdwExtVersion }
  3811. };
  3812. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  3813. if (Prolog (&info))
  3814. {
  3815. if (dwLowVersion == 0 ||
  3816. dwHighVersion == 0xffffffff ||
  3817. dwLowVersion > dwHighVersion)
  3818. {
  3819. info.lResult = LINEERR_INCOMPATIBLEEXTVERSION;
  3820. }
  3821. else
  3822. {
  3823. *lpdwExtVersion = dwHighVersion;
  3824. }
  3825. }
  3826. return (Epilog (&info));
  3827. }
  3828. LONG
  3829. TSPIAPI
  3830. TSPI_lineNegotiateTSPIVersion(
  3831. DWORD dwDeviceID,
  3832. DWORD dwLowVersion,
  3833. DWORD dwHighVersion,
  3834. LPDWORD lpdwTSPIVersion
  3835. )
  3836. {
  3837. static char szFuncName[] = "lineNegotiateTSPIVersion";
  3838. FUNC_PARAM params[] =
  3839. {
  3840. { szdwDeviceID, dwDeviceID },
  3841. { "dwLowVersion", dwLowVersion },
  3842. { "dwHighVersion", dwHighVersion },
  3843. { "lpdwTSPIVersion", lpdwTSPIVersion }
  3844. };
  3845. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  3846. if (Prolog (&info))
  3847. {
  3848. *lpdwTSPIVersion = gESPGlobals.dwSPIVersion;
  3849. }
  3850. return (Epilog (&info));
  3851. }
  3852. LONG
  3853. TSPIAPI
  3854. TSPI_lineOpen(
  3855. DWORD dwDeviceID,
  3856. HTAPILINE htLine,
  3857. LPHDRVLINE lphdLine,
  3858. DWORD dwTSPIVersion,
  3859. LINEEVENT lpfnEventProc
  3860. )
  3861. {
  3862. static char szFuncName[] = "lineOpen";
  3863. FUNC_PARAM params[] =
  3864. {
  3865. { szdwDeviceID, dwDeviceID },
  3866. { "htLine", htLine },
  3867. { "lphdLine", lphdLine },
  3868. { "dwTSPIVersion", dwTSPIVersion },
  3869. { "lpfnEventProc", lpfnEventProc }
  3870. };
  3871. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  3872. PDRVLINE pLine;
  3873. if (Prolog (&info))
  3874. {
  3875. if ((pLine = GetLineFromID (dwDeviceID)))
  3876. {
  3877. pLine->htLine = htLine;
  3878. *lphdLine = (HDRVLINE) pLine;
  3879. WriteEventBuffer(
  3880. pLine->dwDeviceID,
  3881. WIDGETTYPE_LINE,
  3882. (ULONG_PTR) pLine,
  3883. (ULONG_PTR) htLine,
  3884. 0,
  3885. 0
  3886. );
  3887. }
  3888. else
  3889. {
  3890. info.lResult = LINEERR_OPERATIONFAILED;
  3891. }
  3892. }
  3893. return (Epilog (&info));
  3894. }
  3895. void
  3896. FAR
  3897. PASCAL
  3898. TSPI_linePark_postProcess(
  3899. PASYNC_REQUEST_INFO pAsyncReqInfo,
  3900. BOOL bAsync
  3901. )
  3902. {
  3903. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2,
  3904. dwParkIndex = (DWORD) pAsyncReqInfo->dwParam4;
  3905. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
  3906. pParkedCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
  3907. pDestCall;
  3908. if (pAsyncReqInfo->lResult == 0)
  3909. {
  3910. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3911. pDestCall = pCall->pDestCall;
  3912. pCall->pDestCall = NULL;
  3913. pParkedCall->bConnectedToDestCall =
  3914. pCall->bConnectedToDestCall;
  3915. pAsyncReqInfo->lResult = SetCallState(
  3916. pCall,
  3917. dwCallInstThen,
  3918. LINECALLSTATE_CONNECTED,
  3919. LINECALLSTATE_IDLE,
  3920. 0,
  3921. TRUE
  3922. );
  3923. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3924. }
  3925. DoCompletion (pAsyncReqInfo, bAsync);
  3926. if (pAsyncReqInfo->lResult == 0)
  3927. {
  3928. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  3929. if (IsValidDrvCall (pDestCall, NULL))
  3930. {
  3931. pDestCall->pDestCall = pParkedCall;
  3932. pParkedCall->pDestCall = pDestCall;
  3933. }
  3934. // BUGBUG TSPI_linePark: what if dest call state chg while buddy parked???
  3935. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  3936. }
  3937. else
  3938. {
  3939. //
  3940. // Clean up parked call
  3941. //
  3942. if (pParkedCall->pSendingFlowspec)
  3943. {
  3944. DrvFree (pParkedCall->pSendingFlowspec);
  3945. }
  3946. if (pParkedCall->pReceivingFlowspec)
  3947. {
  3948. DrvFree (pParkedCall->pReceivingFlowspec);
  3949. }
  3950. if (pParkedCall->pCallData)
  3951. {
  3952. DrvFree (pParkedCall->pCallData);
  3953. }
  3954. DrvFree (pParkedCall);
  3955. gaParkedCalls[dwParkIndex] = NULL;
  3956. }
  3957. }
  3958. LONG
  3959. TSPIAPI
  3960. TSPI_linePark(
  3961. DRV_REQUESTID dwRequestID,
  3962. HDRVCALL hdCall,
  3963. DWORD dwParkMode,
  3964. LPCWSTR lpszDirAddress,
  3965. LPVARSTRING lpNonDirAddress
  3966. )
  3967. {
  3968. static char szFuncName[] = "linePark";
  3969. FUNC_PARAM params[] =
  3970. {
  3971. { szdwRequestID, dwRequestID },
  3972. { szhdCall, hdCall },
  3973. { "dwParkMode", dwParkMode },
  3974. { "lpszDirAddress", lpszDirAddress },
  3975. { "lpNonDirAddress", lpNonDirAddress }
  3976. };
  3977. FUNC_INFO info = { szFuncName, ASYNC, 5, params, NULL };
  3978. PDRVCALL pCall = (PDRVCALL) hdCall;
  3979. if (Prolog (&info))
  3980. {
  3981. if (dwParkMode == LINEPARKMODE_DIRECTED)
  3982. {
  3983. info.lResult = TransferCall(
  3984. &info,
  3985. pCall,
  3986. LINECALLSTATE_CONNECTED | LINECALLSTATE_ONHOLD,
  3987. LINECALLSTATE_ONHOLD,
  3988. lpszDirAddress
  3989. );
  3990. }
  3991. else
  3992. {
  3993. //
  3994. // First check to see if buf is big enough to return parked addr
  3995. //
  3996. if (lpNonDirAddress->dwTotalSize <
  3997. (sizeof (VARSTRING) + 9 * sizeof(WCHAR))) // L"9999#123"
  3998. {
  3999. lpNonDirAddress->dwNeededSize = sizeof (VARSTRING) +
  4000. 9 * sizeof(WCHAR);
  4001. info.lResult = LINEERR_STRUCTURETOOSMALL;
  4002. return (Epilog (&info));
  4003. }
  4004. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4005. if (IsValidDrvCall (pCall, NULL) == FALSE)
  4006. {
  4007. info.lResult = LINEERR_INVALCALLHANDLE;
  4008. }
  4009. else if (pCall->dwCallState != LINECALLSTATE_CONNECTED &&
  4010. pCall->dwCallState != LINECALLSTATE_ONHOLD)
  4011. {
  4012. info.lResult = LINEERR_INVALCALLSTATE;
  4013. }
  4014. else
  4015. {
  4016. DWORD i;
  4017. for (i = 0; i < MAX_NUM_PARKED_CALLS; i++)
  4018. {
  4019. if (gaParkedCalls[i] == NULL)
  4020. {
  4021. break;
  4022. }
  4023. }
  4024. if (i < MAX_NUM_PARKED_CALLS)
  4025. {
  4026. //
  4027. // Create a new call struct, dup-ing all the info of
  4028. // the existing call, & stick it in the parking place
  4029. //
  4030. DWORD dwStringSize;
  4031. PDRVCALL pParkedCall;
  4032. if ((pParkedCall = DrvAlloc (sizeof (DRVCALL))))
  4033. {
  4034. char buf[16];
  4035. CopyMemory(
  4036. &pParkedCall->dwMediaMode,
  4037. &pCall->dwMediaMode,
  4038. 8 * sizeof (DWORD) + sizeof (LINEDIALPARAMS)
  4039. );
  4040. if (pCall->pSendingFlowspec &&
  4041. (pParkedCall->pSendingFlowspec =
  4042. DrvAlloc (pCall->dwSendingFlowspecSize)))
  4043. {
  4044. pParkedCall->dwSendingFlowspecSize =
  4045. pCall->dwSendingFlowspecSize;
  4046. }
  4047. if (pCall->pReceivingFlowspec &&
  4048. (pParkedCall->pReceivingFlowspec =
  4049. DrvAlloc (pCall->dwReceivingFlowspecSize)))
  4050. {
  4051. pParkedCall->dwReceivingFlowspecSize =
  4052. pCall->dwReceivingFlowspecSize;
  4053. }
  4054. if (pCall->pCallData &&
  4055. (pParkedCall->pCallData =
  4056. DrvAlloc (pCall->dwCallDataSize)))
  4057. {
  4058. pParkedCall->dwCallDataSize =
  4059. pCall->dwCallDataSize;
  4060. }
  4061. pParkedCall->dwCallInstance = gdwCallInstance++;
  4062. pParkedCall->dwCallID = pCall->dwCallID;
  4063. pParkedCall->dwRelatedCallID = pCall->dwRelatedCallID;
  4064. pParkedCall->dwAddressType = pCall->dwAddressType;
  4065. gaParkedCalls[i] = pParkedCall;
  4066. wsprintfA (buf, "9999#%d", i);
  4067. dwStringSize = (DWORD) MultiByteToWideChar(
  4068. GetACP(),
  4069. MB_PRECOMPOSED,
  4070. (LPCSTR) buf,
  4071. lstrlenA (buf) + 1,
  4072. (LPWSTR) (lpNonDirAddress + 1),
  4073. 9
  4074. ) * sizeof (WCHAR);
  4075. lpNonDirAddress->dwNeededSize += dwStringSize;
  4076. lpNonDirAddress->dwUsedSize += dwStringSize;
  4077. lpNonDirAddress->dwStringFormat = STRINGFORMAT_UNICODE;
  4078. lpNonDirAddress->dwStringSize = dwStringSize;
  4079. lpNonDirAddress->dwStringOffset = sizeof (VARSTRING);
  4080. info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  4081. TSPI_linePark_postProcess;
  4082. info.pAsyncReqInfo->dwParam1 = pCall;
  4083. info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
  4084. info.pAsyncReqInfo->dwParam3 = pParkedCall;
  4085. info.pAsyncReqInfo->dwParam4 = i;
  4086. }
  4087. else
  4088. {
  4089. info.lResult = LINEERR_NOMEM;
  4090. }
  4091. }
  4092. else
  4093. {
  4094. ShowStr(
  4095. TRUE,
  4096. "TSPI_linePark (undirected): no available " \
  4097. "parking spaces"
  4098. );
  4099. info.lResult = LINEERR_OPERATIONFAILED;
  4100. }
  4101. }
  4102. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4103. }
  4104. }
  4105. return (Epilog (&info));
  4106. }
  4107. void
  4108. FAR
  4109. PASCAL
  4110. TSPI_linePickup_postProcess(
  4111. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4112. BOOL bAsync
  4113. )
  4114. {
  4115. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  4116. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  4117. DoCompletion (pAsyncReqInfo, bAsync);
  4118. if (pAsyncReqInfo->lResult == 0)
  4119. {
  4120. SetCallState(
  4121. pCall,
  4122. dwCallInstThen,
  4123. 0xffffffff,
  4124. LINECALLSTATE_OFFERING,
  4125. 0,
  4126. TRUE
  4127. );
  4128. }
  4129. else
  4130. {
  4131. FreeCall (pCall, dwCallInstThen);
  4132. }
  4133. }
  4134. LONG
  4135. TSPIAPI
  4136. TSPI_linePickup(
  4137. DRV_REQUESTID dwRequestID,
  4138. HDRVLINE hdLine,
  4139. DWORD dwAddressID,
  4140. HTAPICALL htCall,
  4141. LPHDRVCALL lphdCall,
  4142. LPCWSTR lpszDestAddress,
  4143. LPCWSTR lpszGroupID
  4144. )
  4145. {
  4146. static char szFuncName[] = "linePickup";
  4147. FUNC_PARAM params[] =
  4148. {
  4149. { szdwRequestID, dwRequestID },
  4150. { szhdLine, hdLine },
  4151. { "dwAddressID", dwAddressID },
  4152. { "htCall", htCall },
  4153. { "lphdCall", lphdCall },
  4154. { "lpszDestAddress", lpszDestAddress },
  4155. { "lpszGroupID", lpszGroupID }
  4156. };
  4157. FUNC_INFO info =
  4158. {
  4159. szFuncName,
  4160. ASYNC,
  4161. 7,
  4162. params,
  4163. TSPI_linePickup_postProcess
  4164. };
  4165. if (Prolog (&info))
  4166. {
  4167. LONG lResult;
  4168. PDRVCALL pCall;
  4169. if ((lResult = AllocCall(
  4170. (PDRVLINE) hdLine,
  4171. htCall,
  4172. NULL,
  4173. &pCall
  4174. )) == 0)
  4175. {
  4176. // BUGBUG deal w/ addr id
  4177. *lphdCall = (HDRVCALL) pCall;
  4178. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) pCall;
  4179. info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
  4180. }
  4181. else
  4182. {
  4183. info.lResult = lResult;
  4184. }
  4185. }
  4186. return (Epilog (&info));
  4187. }
  4188. void
  4189. FAR
  4190. PASCAL
  4191. TSPI_linePrepareAddToConference_postProcess(
  4192. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4193. BOOL bAsync
  4194. )
  4195. {
  4196. DWORD dwConfCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  4197. dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam4;
  4198. PDRVCALL pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
  4199. pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam3;
  4200. DoCompletion (pAsyncReqInfo, bAsync);
  4201. if (pAsyncReqInfo->lResult == 0)
  4202. {
  4203. SetCallState(
  4204. pConfCall,
  4205. dwConfCallInstThen,
  4206. LINECALLSTATE_CONNECTED,
  4207. LINECALLSTATE_ONHOLDPENDCONF,
  4208. 0,
  4209. TRUE
  4210. );
  4211. SetCallState(
  4212. pConsultCall,
  4213. dwConsultCallInstThen,
  4214. 0xffffffff,
  4215. LINECALLSTATE_DIALTONE,
  4216. 0,
  4217. TRUE
  4218. );
  4219. }
  4220. else
  4221. {
  4222. FreeCall (pConsultCall, dwConsultCallInstThen);
  4223. }
  4224. }
  4225. LONG
  4226. TSPIAPI
  4227. TSPI_linePrepareAddToConference(
  4228. DRV_REQUESTID dwRequestID,
  4229. HDRVCALL hdConfCall,
  4230. HTAPICALL htConsultCall,
  4231. LPHDRVCALL lphdConsultCall,
  4232. LPLINECALLPARAMS const lpCallParams
  4233. )
  4234. {
  4235. LONG lResult;
  4236. PDRVCALL pConsultCall;
  4237. static char szFuncName[] = "linePrepareAddToConference";
  4238. FUNC_PARAM params[] =
  4239. {
  4240. { szdwRequestID, dwRequestID },
  4241. { "hdConfCall", hdConfCall },
  4242. { "htConsultCall", htConsultCall },
  4243. { "lphdConsultCall", lphdConsultCall },
  4244. { szlpCallParams, lpCallParams }
  4245. };
  4246. FUNC_INFO info =
  4247. {
  4248. szFuncName,
  4249. ASYNC,
  4250. 5,
  4251. params,
  4252. TSPI_linePrepareAddToConference_postProcess
  4253. };
  4254. if (Prolog (&info))
  4255. {
  4256. DWORD dwCallInstance;
  4257. if (IsValidDrvCall ((PDRVCALL) hdConfCall, &dwCallInstance))
  4258. {
  4259. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  4260. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdConfCall;
  4261. if ((lResult = AllocCall(
  4262. ((PDRVCALL) hdConfCall)->pLine,
  4263. htConsultCall,
  4264. lpCallParams,
  4265. &pConsultCall
  4266. )) == 0)
  4267. {
  4268. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) pConsultCall;
  4269. info.pAsyncReqInfo->dwParam4 = pConsultCall->dwCallInstance;
  4270. *lphdConsultCall = (HDRVCALL) pConsultCall;
  4271. }
  4272. else
  4273. {
  4274. info.lResult = lResult;
  4275. }
  4276. }
  4277. }
  4278. return (Epilog (&info));
  4279. }
  4280. LONG
  4281. TSPIAPI
  4282. TSPI_lineRedirect(
  4283. DRV_REQUESTID dwRequestID,
  4284. HDRVCALL hdCall,
  4285. LPCWSTR lpszDestAddress,
  4286. DWORD dwCountryCode
  4287. )
  4288. {
  4289. static char szFuncName[] = "lineRedirect";
  4290. FUNC_PARAM params[] =
  4291. {
  4292. { szdwRequestID, dwRequestID },
  4293. { szhdCall, hdCall },
  4294. { "lpszDestAddress", lpszDestAddress },
  4295. { "dwCountryCode", dwCountryCode }
  4296. };
  4297. FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
  4298. PDRVCALL pCall = (PDRVCALL) hdCall;
  4299. if (Prolog (&info))
  4300. {
  4301. info.lResult = TransferCall(
  4302. &info,
  4303. (PDRVCALL) hdCall,
  4304. LINECALLSTATE_OFFERING,
  4305. LINECALLSTATE_OFFERING,
  4306. lpszDestAddress
  4307. );
  4308. }
  4309. return (Epilog (&info));
  4310. }
  4311. LONG
  4312. TSPIAPI
  4313. TSPI_lineReleaseUserUserInfo(
  4314. DRV_REQUESTID dwRequestID,
  4315. HDRVCALL hdCall
  4316. )
  4317. {
  4318. static char szFuncName[] = "lineReleaseUserUserInfo";
  4319. FUNC_PARAM params[] =
  4320. {
  4321. { szdwRequestID, dwRequestID },
  4322. { szhdCall, hdCall }
  4323. };
  4324. FUNC_INFO info = { szFuncName, ASYNC, 2, params, NULL };
  4325. if (Prolog (&info))
  4326. {
  4327. }
  4328. return (Epilog (&info));
  4329. }
  4330. void
  4331. FAR
  4332. PASCAL
  4333. TSPI_lineRemoveFromConference_postProcess(
  4334. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4335. BOOL bAsync
  4336. )
  4337. {
  4338. if (pAsyncReqInfo->lResult == 0)
  4339. {
  4340. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2;
  4341. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  4342. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4343. if ((pAsyncReqInfo->lResult = SetCallState(
  4344. pCall,
  4345. dwCallInstThen,
  4346. LINECALLSTATE_CONFERENCED,
  4347. LINECALLSTATE_CONNECTED,
  4348. 0,
  4349. TRUE
  4350. )) == 0)
  4351. {
  4352. PDRVCALL pCall2 = (PDRVCALL) pCall->pConfParent;
  4353. while (pCall2 && (pCall2->pNextConfChild != pCall))
  4354. {
  4355. pCall2 = pCall2->pNextConfChild;
  4356. }
  4357. if (pCall2)
  4358. {
  4359. pCall2->pNextConfChild = pCall->pNextConfChild;
  4360. }
  4361. pCall->pConfParent = NULL;
  4362. /*
  4363. pCall->dwRelatedCallID = 0;
  4364. SendLineEvent(
  4365. pCall->pLine,
  4366. pCall,
  4367. LINE_CALLINFO,
  4368. LINECALLINFOSTATE_RELATEDCALLID,
  4369. 0,
  4370. 0
  4371. );
  4372. */
  4373. // create a new callid for the break away conf leg
  4374. // this create a new call hub
  4375. pCall->dwCallID = (++gdwCallID ? gdwCallID : ++gdwCallID);
  4376. SendLineEvent(
  4377. pCall->pLine,
  4378. pCall,
  4379. LINE_CALLINFO,
  4380. LINECALLINFOSTATE_CALLID,
  4381. 0,
  4382. 0
  4383. );
  4384. if (pCall->pDestCall)
  4385. {
  4386. // BUGBUG chg buddy's call hub id, and check to see if
  4387. // buddy is in a conf (if so will need to munge
  4388. // the conf too (?)
  4389. // give the call's buddy the same callid, this puts it
  4390. // into the same call hub
  4391. pCall->pDestCall->dwCallID = pCall->dwCallID;
  4392. SendLineEvent(
  4393. pCall->pDestCall->pLine,
  4394. pCall->pDestCall,
  4395. LINE_CALLINFO,
  4396. LINECALLINFOSTATE_CALLID,
  4397. 0,
  4398. 0
  4399. );
  4400. }
  4401. }
  4402. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4403. }
  4404. DoCompletion (pAsyncReqInfo, bAsync);
  4405. }
  4406. LONG
  4407. TSPIAPI
  4408. TSPI_lineRemoveFromConference(
  4409. DRV_REQUESTID dwRequestID,
  4410. HDRVCALL hdCall
  4411. )
  4412. {
  4413. static char szFuncName[] = "lineRemoveFromConference";
  4414. FUNC_PARAM params[] =
  4415. {
  4416. { szdwRequestID, dwRequestID },
  4417. { szhdCall, hdCall }
  4418. };
  4419. FUNC_INFO info =
  4420. {
  4421. szFuncName,
  4422. ASYNC,
  4423. 2,
  4424. params,
  4425. TSPI_lineRemoveFromConference_postProcess
  4426. };
  4427. if (Prolog (&info))
  4428. {
  4429. DWORD dwCallInstance;
  4430. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  4431. {
  4432. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  4433. info.pAsyncReqInfo->dwParam2 = dwCallInstance;
  4434. }
  4435. else
  4436. {
  4437. info.lResult = LINEERR_INVALCALLHANDLE;
  4438. }
  4439. }
  4440. return (Epilog (&info));
  4441. }
  4442. LONG
  4443. TSPIAPI
  4444. TSPI_lineSecureCall(
  4445. DRV_REQUESTID dwRequestID,
  4446. HDRVCALL hdCall
  4447. )
  4448. {
  4449. static char szFuncName[] = "lineSecureCall";
  4450. FUNC_PARAM params[] =
  4451. {
  4452. { szdwRequestID, dwRequestID },
  4453. { szhdCall, hdCall }
  4454. };
  4455. FUNC_INFO info = { szFuncName, ASYNC, 2, params, NULL };
  4456. if (Prolog (&info))
  4457. {
  4458. }
  4459. return (Epilog (&info));
  4460. }
  4461. LONG
  4462. TSPIAPI
  4463. TSPI_lineSelectExtVersion(
  4464. HDRVLINE hdLine,
  4465. DWORD dwExtVersion
  4466. )
  4467. {
  4468. static char szFuncName[] = "lineSelectExtVersion";
  4469. FUNC_PARAM params[] =
  4470. {
  4471. { szhdLine, hdLine },
  4472. { "dwExtVersion", dwExtVersion }
  4473. };
  4474. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  4475. if (Prolog (&info))
  4476. {
  4477. }
  4478. return (Epilog (&info));
  4479. }
  4480. LONG
  4481. TSPIAPI
  4482. TSPI_lineSendUserUserInfo(
  4483. DRV_REQUESTID dwRequestID,
  4484. HDRVCALL hdCall,
  4485. LPCSTR lpsUserUserInfo,
  4486. DWORD dwSize
  4487. )
  4488. {
  4489. static char szFuncName[] = "lineSendUserUserInfo";
  4490. FUNC_PARAM params[] =
  4491. {
  4492. { szdwRequestID, dwRequestID },
  4493. { szhdCall, hdCall },
  4494. { "lpsUserUserInfo", lpsUserUserInfo },
  4495. { szdwSize, dwSize }
  4496. };
  4497. FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
  4498. if (Prolog (&info))
  4499. {
  4500. }
  4501. return (Epilog (&info));
  4502. }
  4503. LONG
  4504. TSPIAPI
  4505. TSPI_lineSetAppSpecific(
  4506. HDRVCALL hdCall,
  4507. DWORD dwAppSpecific
  4508. )
  4509. {
  4510. static char szFuncName[] = "lineSetAppSpecific";
  4511. FUNC_PARAM params[] =
  4512. {
  4513. { szhdCall, hdCall },
  4514. { "dwAppSpecific", dwAppSpecific }
  4515. };
  4516. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  4517. if (Prolog (&info))
  4518. {
  4519. PDRVCALL pCall = (PDRVCALL) hdCall;
  4520. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4521. if (IsValidDrvCall (pCall, NULL))
  4522. {
  4523. if (pCall->dwAppSpecific != dwAppSpecific)
  4524. {
  4525. pCall->dwAppSpecific = dwAppSpecific;
  4526. SendLineEvent(
  4527. pCall->pLine,
  4528. pCall,
  4529. LINE_CALLINFO,
  4530. LINECALLINFOSTATE_APPSPECIFIC,
  4531. 0,
  4532. 0
  4533. );
  4534. }
  4535. }
  4536. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4537. }
  4538. return (Epilog (&info));
  4539. }
  4540. void
  4541. FAR
  4542. PASCAL
  4543. TSPI_lineSetCallData_postProcess(
  4544. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4545. BOOL bAsync
  4546. )
  4547. {
  4548. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  4549. dwCallInstNow,
  4550. dwCallDataSize = (DWORD) pAsyncReqInfo->dwParam4;
  4551. LPVOID pCallData = (LPVOID) pAsyncReqInfo->dwParam3, pToFree;
  4552. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  4553. if (pAsyncReqInfo->lResult == 0)
  4554. {
  4555. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4556. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  4557. dwCallInstNow == dwCallInstThen)
  4558. {
  4559. pToFree = pCall->pCallData;
  4560. pCall->pCallData = pCallData;
  4561. pCall->dwCallDataSize = dwCallDataSize;
  4562. SendLineEvent(
  4563. pCall->pLine,
  4564. pCall,
  4565. LINE_CALLINFO,
  4566. LINECALLINFOSTATE_CALLDATA,
  4567. 0,
  4568. 0
  4569. );
  4570. }
  4571. else
  4572. {
  4573. pToFree = NULL;
  4574. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  4575. }
  4576. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4577. DrvFree (pToFree);
  4578. }
  4579. DoCompletion (pAsyncReqInfo, bAsync);
  4580. if (pAsyncReqInfo->lResult != 0)
  4581. {
  4582. DrvFree (pCallData);
  4583. }
  4584. }
  4585. LONG
  4586. TSPIAPI
  4587. TSPI_lineSetCallData(
  4588. DRV_REQUESTID dwRequestID,
  4589. HDRVCALL hdCall,
  4590. LPVOID lpCallData,
  4591. DWORD dwSize
  4592. )
  4593. {
  4594. static char szFuncName[] = "lineSetCallData";
  4595. FUNC_PARAM params[] =
  4596. {
  4597. { szdwRequestID, dwRequestID },
  4598. { szhdCall, hdCall },
  4599. { "lpCallData", lpCallData },
  4600. { szdwSize, dwSize }
  4601. };
  4602. FUNC_INFO info =
  4603. {
  4604. szFuncName,
  4605. ASYNC,
  4606. 4,
  4607. params,
  4608. TSPI_lineSetCallData_postProcess
  4609. };
  4610. if (Prolog (&info))
  4611. {
  4612. DWORD dwCallInstance;
  4613. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  4614. {
  4615. LPVOID pCallData;
  4616. if (dwSize)
  4617. {
  4618. if ((pCallData = DrvAlloc (dwSize)))
  4619. {
  4620. CopyMemory (pCallData, lpCallData, dwSize);
  4621. }
  4622. else
  4623. {
  4624. info.lResult = LINEERR_NOMEM;
  4625. }
  4626. }
  4627. else
  4628. {
  4629. pCallData = NULL;
  4630. }
  4631. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  4632. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  4633. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) pCallData;
  4634. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) dwSize;
  4635. }
  4636. else
  4637. {
  4638. info.lResult = LINEERR_INVALCALLHANDLE;
  4639. }
  4640. }
  4641. return (Epilog (&info));
  4642. }
  4643. LONG
  4644. TSPIAPI
  4645. TSPI_lineSetCallHubTracking(
  4646. HDRVLINE hdLine,
  4647. LPLINECALLHUBTRACKINGINFO lpTrackingInfo
  4648. )
  4649. {
  4650. static char szFuncName[] = "lineSetCallHubTracking";
  4651. FUNC_PARAM params[] =
  4652. {
  4653. { szhdLine, hdLine },
  4654. { "lpTrackingInfo", lpTrackingInfo }
  4655. };
  4656. FUNC_INFO info = { szFuncName, SYNC, 2, params, NULL };
  4657. if (Prolog (&info))
  4658. {
  4659. // BUGBUG
  4660. }
  4661. return (Epilog (&info));
  4662. }
  4663. void
  4664. FAR
  4665. PASCAL
  4666. TSPI_lineSetCallParams_postProcess(
  4667. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4668. BOOL bAsync
  4669. )
  4670. {
  4671. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  4672. dwCallInstNow,
  4673. dwBearerMode = (DWORD) pAsyncReqInfo->dwParam3,
  4674. dwMinRate = (DWORD) pAsyncReqInfo->dwParam4,
  4675. dwMaxRate = (DWORD) pAsyncReqInfo->dwParam5;
  4676. PDRVCALL pCall = pAsyncReqInfo->dwParam2;
  4677. LPLINEDIALPARAMS pDialParams = pAsyncReqInfo->dwParam6;
  4678. if (pAsyncReqInfo->lResult == 0)
  4679. {
  4680. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4681. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  4682. dwCallInstNow == dwCallInstThen)
  4683. {
  4684. DWORD dwCallInfoStates = 0;
  4685. if (pCall->dwBearerMode != dwBearerMode)
  4686. {
  4687. pCall->dwBearerMode = dwBearerMode;
  4688. dwCallInfoStates |= LINECALLINFOSTATE_BEARERMODE;
  4689. }
  4690. if (pCall->dwMinRate != dwMinRate ||
  4691. pCall->dwMaxRate != dwMaxRate)
  4692. {
  4693. pCall->dwMinRate = dwMinRate;
  4694. pCall->dwMaxRate = dwMaxRate;
  4695. dwCallInfoStates |= LINECALLINFOSTATE_RATE;
  4696. }
  4697. if (pDialParams &&
  4698. (pCall->DialParams.dwDialPause != pDialParams->dwDialPause ||
  4699. pCall->DialParams.dwDialSpeed != pDialParams->dwDialSpeed ||
  4700. pCall->DialParams.dwDigitDuration !=
  4701. pDialParams->dwDigitDuration ||
  4702. pCall->DialParams.dwWaitForDialtone !=
  4703. pDialParams->dwWaitForDialtone))
  4704. {
  4705. pCall->DialParams.dwDialPause = pDialParams->dwDialPause;
  4706. pCall->DialParams.dwDialSpeed = pDialParams->dwDialSpeed;
  4707. pCall->DialParams.dwDigitDuration =
  4708. pDialParams->dwDigitDuration;
  4709. pCall->DialParams.dwWaitForDialtone =
  4710. pDialParams->dwWaitForDialtone;
  4711. dwCallInfoStates |= LINECALLINFOSTATE_DIALPARAMS;
  4712. }
  4713. if (dwCallInfoStates)
  4714. {
  4715. SendLineEvent(
  4716. pCall->pLine,
  4717. pCall,
  4718. LINE_CALLINFO,
  4719. dwCallInfoStates,
  4720. 0,
  4721. 0
  4722. );
  4723. }
  4724. }
  4725. else
  4726. {
  4727. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  4728. }
  4729. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4730. }
  4731. DoCompletion (pAsyncReqInfo, bAsync);
  4732. if (pDialParams)
  4733. {
  4734. DrvFree (pDialParams);
  4735. }
  4736. }
  4737. LONG
  4738. TSPIAPI
  4739. TSPI_lineSetCallParams(
  4740. DRV_REQUESTID dwRequestID,
  4741. HDRVCALL hdCall,
  4742. DWORD dwBearerMode,
  4743. DWORD dwMinRate,
  4744. DWORD dwMaxRate,
  4745. LPLINEDIALPARAMS const lpDialParams
  4746. )
  4747. {
  4748. static char szFuncName[] = "lineSetCallParams";
  4749. FUNC_PARAM params[] =
  4750. {
  4751. { szdwRequestID, dwRequestID },
  4752. { szhdCall, hdCall },
  4753. { "dwBearerMode", dwBearerMode, aBearerModes },
  4754. { "dwMinRate", dwMinRate },
  4755. { "dwMaxRate", dwMaxRate },
  4756. { "lpDialParams", lpDialParams }
  4757. };
  4758. FUNC_INFO info =
  4759. {
  4760. szFuncName,
  4761. ASYNC,
  4762. 6,
  4763. params,
  4764. TSPI_lineSetCallParams_postProcess
  4765. };
  4766. if (Prolog (&info))
  4767. {
  4768. DWORD dwCallInstance;
  4769. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  4770. {
  4771. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  4772. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  4773. info.pAsyncReqInfo->dwParam3 = dwBearerMode;
  4774. info.pAsyncReqInfo->dwParam4 = dwMinRate;
  4775. info.pAsyncReqInfo->dwParam5 = dwMaxRate;
  4776. if (lpDialParams)
  4777. {
  4778. LPLINEDIALPARAMS pDialParams;
  4779. if ((pDialParams = DrvAlloc (sizeof (LINEDIALPARAMS))))
  4780. {
  4781. CopyMemory(
  4782. pDialParams,
  4783. lpDialParams,
  4784. sizeof (LINEDIALPARAMS)
  4785. );
  4786. info.pAsyncReqInfo->dwParam8 = (ULONG_PTR) pDialParams;
  4787. }
  4788. else
  4789. {
  4790. info.lResult = LINEERR_NOMEM;
  4791. }
  4792. }
  4793. }
  4794. else
  4795. {
  4796. info.lResult = LINEERR_INVALCALLHANDLE;
  4797. }
  4798. }
  4799. return (Epilog (&info));
  4800. }
  4801. void
  4802. FAR
  4803. PASCAL
  4804. TSPI_lineSetCallQualityOfService_postProcess(
  4805. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4806. BOOL bAsync
  4807. )
  4808. {
  4809. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  4810. dwCallInstNow,
  4811. dwSendingFlowspecSize = (DWORD) pAsyncReqInfo->dwParam4,
  4812. dwReceivingFlowspecSize = (DWORD) pAsyncReqInfo->dwParam6;
  4813. LPVOID pSendingFlowspec = (LPVOID) pAsyncReqInfo->dwParam3,
  4814. pReceivingFlowspec = (LPVOID) pAsyncReqInfo->dwParam5,
  4815. pToFree, pToFree2;
  4816. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  4817. if (pAsyncReqInfo->lResult == 0)
  4818. {
  4819. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4820. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  4821. dwCallInstNow == dwCallInstThen)
  4822. {
  4823. pToFree = pCall->pSendingFlowspec;
  4824. pCall->pSendingFlowspec = pSendingFlowspec;
  4825. pCall->dwSendingFlowspecSize = dwSendingFlowspecSize;
  4826. pToFree2 = pCall->pReceivingFlowspec;
  4827. pCall->pReceivingFlowspec = pReceivingFlowspec;
  4828. pCall->dwReceivingFlowspecSize = dwReceivingFlowspecSize;
  4829. SendLineEvent(
  4830. pCall->pLine,
  4831. pCall,
  4832. LINE_CALLINFO,
  4833. LINECALLINFOSTATE_QOS,
  4834. 0,
  4835. 0
  4836. );
  4837. }
  4838. else
  4839. {
  4840. pToFree = pToFree2 = NULL;
  4841. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  4842. }
  4843. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4844. DrvFree (pToFree);
  4845. DrvFree (pToFree2);
  4846. }
  4847. DoCompletion (pAsyncReqInfo, bAsync);
  4848. if (pAsyncReqInfo->lResult != 0)
  4849. {
  4850. DrvFree (pSendingFlowspec);
  4851. DrvFree (pReceivingFlowspec);
  4852. }
  4853. }
  4854. LONG
  4855. TSPIAPI
  4856. TSPI_lineSetCallQualityOfService(
  4857. DRV_REQUESTID dwRequestID,
  4858. HDRVCALL hdCall,
  4859. LPVOID lpSendingFlowspec,
  4860. DWORD dwSendingFlowspecSize,
  4861. LPVOID lpReceivingFlowspec,
  4862. DWORD dwReceivingFlowspecSize
  4863. )
  4864. {
  4865. static char szFuncName[] = "lineSetCallQualityOfService";
  4866. FUNC_PARAM params[] =
  4867. {
  4868. { szdwRequestID, dwRequestID },
  4869. { szhdCall, hdCall },
  4870. { "lpSendingFlowspec", lpSendingFlowspec },
  4871. { "dwSendingFlowspecSize", dwSendingFlowspecSize },
  4872. { "lpReceivingFlowspec", lpReceivingFlowspec },
  4873. { "dwReceivingFlowspecSize", dwReceivingFlowspecSize }
  4874. };
  4875. FUNC_INFO info =
  4876. {
  4877. szFuncName,
  4878. ASYNC,
  4879. 6,
  4880. params,
  4881. TSPI_lineSetCallQualityOfService_postProcess
  4882. };
  4883. if (Prolog (&info))
  4884. {
  4885. DWORD dwCallInstance;
  4886. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  4887. {
  4888. LPVOID pSendingFlowspec, pReceivingFlowspec;
  4889. if (dwSendingFlowspecSize)
  4890. {
  4891. if ((pSendingFlowspec = DrvAlloc (dwSendingFlowspecSize)))
  4892. {
  4893. CopyMemory(
  4894. pSendingFlowspec,
  4895. lpSendingFlowspec,
  4896. dwSendingFlowspecSize
  4897. );
  4898. }
  4899. else
  4900. {
  4901. info.lResult = LINEERR_NOMEM;
  4902. goto TSPI_lineSetCallQualityOfService_epilog;
  4903. }
  4904. }
  4905. else
  4906. {
  4907. pSendingFlowspec = NULL;
  4908. }
  4909. if (dwReceivingFlowspecSize)
  4910. {
  4911. if ((pReceivingFlowspec = DrvAlloc (dwReceivingFlowspecSize)))
  4912. {
  4913. CopyMemory(
  4914. pReceivingFlowspec,
  4915. lpReceivingFlowspec,
  4916. dwReceivingFlowspecSize
  4917. );
  4918. }
  4919. else
  4920. {
  4921. info.lResult = LINEERR_NOMEM;
  4922. if (pSendingFlowspec)
  4923. {
  4924. DrvFree (pSendingFlowspec);
  4925. }
  4926. goto TSPI_lineSetCallQualityOfService_epilog;
  4927. }
  4928. }
  4929. else
  4930. {
  4931. pReceivingFlowspec = NULL;
  4932. }
  4933. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  4934. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  4935. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) pSendingFlowspec;
  4936. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) dwSendingFlowspecSize;
  4937. info.pAsyncReqInfo->dwParam5 = (ULONG_PTR) pReceivingFlowspec;
  4938. info.pAsyncReqInfo->dwParam6 = (ULONG_PTR) dwReceivingFlowspecSize;
  4939. }
  4940. else
  4941. {
  4942. info.lResult = LINEERR_INVALCALLHANDLE;
  4943. }
  4944. }
  4945. TSPI_lineSetCallQualityOfService_epilog:
  4946. return (Epilog (&info));
  4947. }
  4948. void
  4949. FAR
  4950. PASCAL
  4951. TSPI_lineSetCallTreatment_postProcess(
  4952. PASYNC_REQUEST_INFO pAsyncReqInfo,
  4953. BOOL bAsync
  4954. )
  4955. {
  4956. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  4957. dwCallInstNow,
  4958. dwTreatment = (DWORD) pAsyncReqInfo->dwParam3;
  4959. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  4960. if (pAsyncReqInfo->lResult == 0)
  4961. {
  4962. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  4963. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  4964. dwCallInstNow == dwCallInstThen)
  4965. {
  4966. if (pCall->dwTreatment != dwTreatment)
  4967. {
  4968. pCall->dwTreatment = dwTreatment;
  4969. SendLineEvent(
  4970. pCall->pLine,
  4971. pCall,
  4972. LINE_CALLINFO,
  4973. LINECALLINFOSTATE_TREATMENT,
  4974. 0,
  4975. 0
  4976. );
  4977. }
  4978. }
  4979. else
  4980. {
  4981. pAsyncReqInfo->lResult = LINEERR_INVALCALLHANDLE;
  4982. }
  4983. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  4984. }
  4985. DoCompletion (pAsyncReqInfo, bAsync);
  4986. }
  4987. LONG
  4988. TSPIAPI
  4989. TSPI_lineSetCallTreatment(
  4990. DRV_REQUESTID dwRequestID,
  4991. HDRVCALL hdCall,
  4992. DWORD dwTreatment
  4993. )
  4994. {
  4995. static char szFuncName[] = "lineSetCallTreatment";
  4996. FUNC_PARAM params[] =
  4997. {
  4998. { szdwRequestID, dwRequestID },
  4999. { szhdCall, hdCall },
  5000. { "dwTreatment", dwTreatment }
  5001. };
  5002. FUNC_INFO info =
  5003. {
  5004. szFuncName,
  5005. ASYNC,
  5006. 3,
  5007. params,
  5008. TSPI_lineSetCallTreatment_postProcess
  5009. };
  5010. if (Prolog (&info))
  5011. {
  5012. DWORD dwCallInstance;
  5013. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  5014. {
  5015. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  5016. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  5017. info.pAsyncReqInfo->dwParam3 = dwTreatment;
  5018. }
  5019. else
  5020. {
  5021. info.lResult = LINEERR_INVALCALLHANDLE;
  5022. }
  5023. }
  5024. return (Epilog (&info));
  5025. }
  5026. LONG
  5027. TSPIAPI
  5028. TSPI_lineSetCurrentLocation(
  5029. DWORD dwLocation
  5030. )
  5031. {
  5032. static char szFuncName[] = "lineSetCurrentLocation";
  5033. FUNC_PARAM params[] =
  5034. {
  5035. { "dwLocation", dwLocation }
  5036. };
  5037. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  5038. if (Prolog (&info))
  5039. {
  5040. }
  5041. return (Epilog (&info));
  5042. }
  5043. LONG
  5044. TSPIAPI
  5045. TSPI_lineSetDefaultMediaDetection(
  5046. HDRVLINE hdLine,
  5047. DWORD dwMediaModes
  5048. )
  5049. {
  5050. static char szFuncName[] = "lineSetDefaultMediaDetection";
  5051. FUNC_PARAM params[] =
  5052. {
  5053. { szhdLine, hdLine },
  5054. { "dwMediaModes", dwMediaModes, aMediaModes }
  5055. };
  5056. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  5057. PDRVLINE pLine = (PDRVLINE) hdLine;
  5058. if (Prolog (&info))
  5059. {
  5060. pLine->dwMediaModes = dwMediaModes;
  5061. }
  5062. return (Epilog (&info));
  5063. }
  5064. LONG
  5065. TSPIAPI
  5066. TSPI_lineSetDevConfig(
  5067. DWORD dwDeviceID,
  5068. LPVOID const lpDeviceConfig,
  5069. DWORD dwSize,
  5070. LPCWSTR lpszDeviceClass
  5071. )
  5072. {
  5073. static char szFuncName[] = "lineSetDevConfig";
  5074. FUNC_PARAM params[] =
  5075. {
  5076. { szdwDeviceID, dwDeviceID },
  5077. { "lpDeviceConfig", lpDeviceConfig },
  5078. { szdwSize, dwSize },
  5079. { "lpszDeviceClass", lpszDeviceClass }
  5080. };
  5081. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  5082. if (Prolog (&info))
  5083. {
  5084. }
  5085. return (Epilog (&info));
  5086. }
  5087. LONG
  5088. TSPIAPI
  5089. TSPI_lineSetLineDevStatus(
  5090. DRV_REQUESTID dwRequestID,
  5091. HDRVLINE hdLine,
  5092. DWORD dwStatusToChange,
  5093. DWORD fStatus
  5094. )
  5095. {
  5096. static char szFuncName[] = "lineSetLineDevStatus";
  5097. FUNC_PARAM params[] =
  5098. {
  5099. { szdwRequestID, dwRequestID },
  5100. { szhdLine, hdLine },
  5101. { "dwStatusToChange", dwStatusToChange },
  5102. { "fStatus", fStatus }
  5103. };
  5104. FUNC_INFO info = { szFuncName, ASYNC, 4, params, NULL };
  5105. PDRVLINE pLine = (PDRVLINE) hdLine;
  5106. if (Prolog (&info))
  5107. {
  5108. //
  5109. // smarandb #23974 winseqfe:
  5110. //
  5111. if (dwStatusToChange == LINEDEVSTATUSFLAGS_MSGWAIT)
  5112. {
  5113. // save new MSGWAIT value
  5114. pLine->dwMSGWAITFlag = fStatus?LINEDEVSTATUSFLAGS_MSGWAIT:0;
  5115. // send event to notify that value has changed;
  5116. // Note: real TSP-s should send the event only if the MSGWAIT value has really changed
  5117. // (in other words don't send the event if the same MSGWAIT value is set twice in a row)
  5118. // Here, we will send the event even if the value didn't change,
  5119. // because we want to help testing winseqfe bug #23974 (tapi3.dll possible infinite loop)
  5120. SendLineEvent(
  5121. pLine,
  5122. NULL,
  5123. LINE_LINEDEVSTATE,
  5124. fStatus?LINEDEVSTATE_MSGWAITON:LINEDEVSTATE_MSGWAITOFF,
  5125. 0,
  5126. 0
  5127. );
  5128. }
  5129. }
  5130. return (Epilog (&info));
  5131. }
  5132. LONG
  5133. TSPIAPI
  5134. TSPI_lineSetMediaControl(
  5135. HDRVLINE hdLine,
  5136. DWORD dwAddressID,
  5137. HDRVCALL hdCall,
  5138. DWORD dwSelect,
  5139. LPLINEMEDIACONTROLDIGIT const lpDigitList,
  5140. DWORD dwDigitNumEntries,
  5141. LPLINEMEDIACONTROLMEDIA const lpMediaList,
  5142. DWORD dwMediaNumEntries,
  5143. LPLINEMEDIACONTROLTONE const lpToneList,
  5144. DWORD dwToneNumEntries,
  5145. LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
  5146. DWORD dwCallStateNumEntries
  5147. )
  5148. {
  5149. static char szFuncName[] = "lineSetMediaControl";
  5150. FUNC_PARAM params[] =
  5151. {
  5152. { szhdLine, hdLine },
  5153. { "dwAddressID", dwAddressID },
  5154. { szhdCall, hdCall },
  5155. { "dwSelect", dwSelect, aCallSelects },
  5156. { "lpDigitList", lpDigitList },
  5157. { "dwDigitNumEntries", dwDigitNumEntries },
  5158. { "lpMediaList", lpMediaList },
  5159. { "dwMediaNumEntries", dwMediaNumEntries },
  5160. { "lpToneList", lpToneList },
  5161. { "dwToneNumEntries", dwToneNumEntries },
  5162. { "lpCallStateList", lpCallStateList },
  5163. { "dwCallStateNumEntries", dwCallStateNumEntries }
  5164. };
  5165. FUNC_INFO info = { szFuncName, SYNC, 12, params };
  5166. if (Prolog (&info))
  5167. {
  5168. }
  5169. return (Epilog (&info));
  5170. }
  5171. LONG
  5172. TSPIAPI
  5173. TSPI_lineSetMediaMode(
  5174. HDRVCALL hdCall,
  5175. DWORD dwMediaMode
  5176. )
  5177. {
  5178. static char szFuncName[] = "lineSetMediaMode";
  5179. FUNC_PARAM params[] =
  5180. {
  5181. { szhdCall, szhdCall },
  5182. { "dwMediaMode", dwMediaMode, aMediaModes }
  5183. };
  5184. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  5185. if (Prolog (&info))
  5186. {
  5187. PDRVCALL pCall = (PDRVCALL) hdCall;
  5188. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  5189. if (IsValidDrvCall (pCall, NULL))
  5190. {
  5191. if (pCall->dwMediaMode != dwMediaMode)
  5192. {
  5193. pCall->dwMediaMode = dwMediaMode;
  5194. SendLineEvent(
  5195. pCall->pLine,
  5196. pCall,
  5197. LINE_CALLINFO,
  5198. LINECALLINFOSTATE_MEDIAMODE,
  5199. 0,
  5200. 0
  5201. );
  5202. }
  5203. }
  5204. else
  5205. {
  5206. info.lResult = LINEERR_INVALCALLHANDLE;
  5207. }
  5208. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  5209. }
  5210. return (Epilog (&info));
  5211. }
  5212. LONG
  5213. TSPIAPI
  5214. TSPI_lineSetStatusMessages(
  5215. HDRVLINE hdLine,
  5216. DWORD dwLineStates,
  5217. DWORD dwAddressStates
  5218. )
  5219. {
  5220. static char szFuncName[] = "lineSetStatusMessages";
  5221. FUNC_PARAM params[] =
  5222. {
  5223. { szhdLine, hdLine },
  5224. { "dwLineStates", dwLineStates, aLineStates },
  5225. { "dwAddressStates", dwAddressStates, aAddressStates }
  5226. };
  5227. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  5228. if (Prolog (&info))
  5229. {
  5230. }
  5231. return (Epilog (&info));
  5232. }
  5233. LONG
  5234. TSPIAPI
  5235. TSPI_lineSetTerminal(
  5236. DRV_REQUESTID dwRequestID,
  5237. HDRVLINE hdLine,
  5238. DWORD dwAddressID,
  5239. HDRVCALL hdCall,
  5240. DWORD dwSelect,
  5241. DWORD dwTerminalModes,
  5242. DWORD dwTerminalID,
  5243. DWORD bEnable
  5244. )
  5245. {
  5246. static char szFuncName[] = "lineSetTerminal";
  5247. FUNC_PARAM params[] =
  5248. {
  5249. { szdwRequestID, dwRequestID },
  5250. { szhdLine, hdLine },
  5251. { "dwAddressID", dwAddressID },
  5252. { szhdCall, hdCall },
  5253. { "dwSelect", dwSelect, aCallSelects },
  5254. { "dwTerminalModes", dwTerminalModes, aTerminalModes },
  5255. { "dwTerminalID", dwTerminalID },
  5256. { "bEnable", bEnable }
  5257. };
  5258. FUNC_INFO info = { szFuncName, ASYNC, 8, params, NULL };
  5259. if (Prolog (&info))
  5260. {
  5261. }
  5262. return (Epilog (&info));
  5263. }
  5264. void
  5265. FAR
  5266. PASCAL
  5267. TSPI_lineSetupConference_postProcess(
  5268. PASYNC_REQUEST_INFO pAsyncReqInfo,
  5269. BOOL bAsync
  5270. )
  5271. {
  5272. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  5273. dwConfCallInstThen = (DWORD) pAsyncReqInfo->dwParam4,
  5274. dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam6;
  5275. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
  5276. pConfCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
  5277. pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam5;
  5278. DoCompletion (pAsyncReqInfo, bAsync);
  5279. if (pAsyncReqInfo->lResult == 0)
  5280. {
  5281. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  5282. if (SetCallState(
  5283. pConfCall,
  5284. dwConfCallInstThen,
  5285. 0xffffffff, // we created this call right now - no initial state reqs.
  5286. LINECALLSTATE_ONHOLDPENDCONF,
  5287. 0,
  5288. TRUE
  5289. ) == 0)
  5290. {
  5291. /*
  5292. pConfCall->dwCallID = pCall->dwCallID;
  5293. SendLineEvent(
  5294. pConfCall->pLine,
  5295. pConfCall,
  5296. LINE_CALLINFO,
  5297. LINECALLINFOSTATE_CALLID,
  5298. 0,
  5299. 0
  5300. );
  5301. */
  5302. if (pCall &&
  5303. SetCallState(
  5304. pCall,
  5305. dwCallInstThen,
  5306. LINECALLSTATE_CONNECTED,
  5307. LINECALLSTATE_CONFERENCED,
  5308. 0,
  5309. TRUE
  5310. ) == 0)
  5311. {
  5312. pCall->pConfParent = pConfCall;
  5313. pConfCall->pNextConfChild = pCall;
  5314. }
  5315. // The consult call isn't in the conf initially
  5316. //
  5317. // Note - indecision on the validity of this transition
  5318. // SDK allows it, internal TAPI documents by NoelA do not.
  5319. //
  5320. SetCallState(
  5321. pConsultCall,
  5322. dwConsultCallInstThen,
  5323. 0xffffffff, // we created this call right now - no initial state reqs.
  5324. LINECALLSTATE_DIALTONE,
  5325. 0,
  5326. TRUE
  5327. );
  5328. }
  5329. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  5330. }
  5331. else
  5332. {
  5333. FreeCall (pConfCall, dwConfCallInstThen);
  5334. FreeCall (pConsultCall, dwConsultCallInstThen);
  5335. }
  5336. }
  5337. LONG
  5338. TSPIAPI
  5339. TSPI_lineSetupConference(
  5340. DRV_REQUESTID dwRequestID,
  5341. HDRVCALL hdCall,
  5342. HDRVLINE hdLine,
  5343. HTAPICALL htConfCall,
  5344. LPHDRVCALL lphdConfCall,
  5345. HTAPICALL htConsultCall,
  5346. LPHDRVCALL lphdConsultCall,
  5347. DWORD dwNumParties,
  5348. LPLINECALLPARAMS const lpCallParams
  5349. )
  5350. {
  5351. static char szFuncName[] = "lineSetupConference";
  5352. FUNC_PARAM params[] =
  5353. {
  5354. { szdwRequestID, dwRequestID },
  5355. { szhdCall, hdCall },
  5356. { szhdLine, hdLine },
  5357. { "htConfCall", htConfCall },
  5358. { "lphdConfCall", lphdConfCall },
  5359. { "htConsultCall", htConsultCall },
  5360. { "lphdConsultCall", lphdConsultCall },
  5361. { "dwNumParties", dwNumParties },
  5362. { szlpCallParams, lpCallParams }
  5363. };
  5364. FUNC_INFO info =
  5365. {
  5366. szFuncName,
  5367. ASYNC,
  5368. 9,
  5369. params,
  5370. TSPI_lineSetupConference_postProcess
  5371. };
  5372. if (Prolog (&info))
  5373. {
  5374. LONG lResult;
  5375. DWORD dwCallInstance;
  5376. PDRVCALL pConfCall, pConsultCall;
  5377. PDRVLINE pLine;
  5378. //info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdCall;
  5379. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  5380. if (hdCall && !IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  5381. {
  5382. info.lResult = LINEERR_INVALCALLHANDLE;
  5383. goto TSPI_lineSetupConference_leaveCritSec;
  5384. }
  5385. pLine = (hdCall ? (PDRVLINE) ((PDRVCALL) hdCall)->pLine :
  5386. (PDRVLINE) hdLine);
  5387. if ((lResult = AllocCall(
  5388. pLine,
  5389. htConfCall,
  5390. lpCallParams,
  5391. &pConfCall
  5392. )) == 0)
  5393. {
  5394. if (hdCall)
  5395. {
  5396. pConfCall->dwCallID = ((PDRVCALL) hdCall)->dwCallID;
  5397. }
  5398. if ((lResult = AllocCall(
  5399. pLine,
  5400. htConsultCall,
  5401. lpCallParams,
  5402. &pConsultCall
  5403. )) == 0)
  5404. {
  5405. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  5406. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  5407. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) pConfCall;
  5408. info.pAsyncReqInfo->dwParam4 = pConfCall->dwCallInstance;
  5409. info.pAsyncReqInfo->dwParam5 = (ULONG_PTR) pConsultCall;
  5410. info.pAsyncReqInfo->dwParam6 = pConsultCall->dwCallInstance;
  5411. *lphdConfCall = (HDRVCALL) pConfCall;
  5412. *lphdConsultCall = (HDRVCALL) pConsultCall;
  5413. }
  5414. else
  5415. {
  5416. FreeCall (pConfCall, pConfCall->dwCallInstance);
  5417. info.lResult = lResult;
  5418. }
  5419. }
  5420. else
  5421. {
  5422. info.lResult = lResult;
  5423. }
  5424. TSPI_lineSetupConference_leaveCritSec:
  5425. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  5426. }
  5427. return (Epilog (&info));
  5428. }
  5429. void
  5430. FAR
  5431. PASCAL
  5432. TSPI_lineSetupTransfer_postProcess(
  5433. PASYNC_REQUEST_INFO pAsyncReqInfo,
  5434. BOOL bAsync
  5435. )
  5436. {
  5437. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  5438. dwConsultCallInstThen = (DWORD) pAsyncReqInfo->dwParam4;
  5439. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2,
  5440. pConsultCall = (PDRVCALL) pAsyncReqInfo->dwParam3;
  5441. DoCompletion (pAsyncReqInfo, bAsync);
  5442. if (pAsyncReqInfo->lResult == 0)
  5443. {
  5444. if (SetCallState(
  5445. pConsultCall,
  5446. dwConsultCallInstThen,
  5447. 0xffffffff, // we created this call right now - no initial state reqs.
  5448. LINECALLSTATE_DIALTONE,
  5449. 0,
  5450. TRUE
  5451. ) == 0)
  5452. {
  5453. SetCallState(
  5454. pCall,
  5455. dwCallInstThen,
  5456. LINECALLSTATE_CONNECTED,
  5457. LINECALLSTATE_ONHOLDPENDTRANSFER,
  5458. 0,
  5459. TRUE
  5460. );
  5461. }
  5462. }
  5463. else
  5464. {
  5465. FreeCall (pConsultCall, dwConsultCallInstThen);
  5466. }
  5467. }
  5468. LONG
  5469. TSPIAPI
  5470. TSPI_lineSetupTransfer(
  5471. DRV_REQUESTID dwRequestID,
  5472. HDRVCALL hdCall,
  5473. HTAPICALL htConsultCall,
  5474. LPHDRVCALL lphdConsultCall,
  5475. LPLINECALLPARAMS const lpCallParams
  5476. )
  5477. {
  5478. static char szFuncName[] = "lineSetupTransfer";
  5479. FUNC_PARAM params[] =
  5480. {
  5481. { szdwRequestID, dwRequestID },
  5482. { szhdCall, hdCall },
  5483. { "htConsultCall", htConsultCall },
  5484. { "lphdConsultCall", lphdConsultCall },
  5485. { szlpCallParams, lpCallParams }
  5486. };
  5487. FUNC_INFO info =
  5488. {
  5489. szFuncName,
  5490. ASYNC,
  5491. 5,
  5492. params,
  5493. TSPI_lineSetupTransfer_postProcess
  5494. };
  5495. if (Prolog (&info))
  5496. {
  5497. DWORD dwCallInstance;
  5498. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  5499. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  5500. {
  5501. LONG lResult;
  5502. PDRVCALL pConsultCall;
  5503. if ((lResult = AllocCall(
  5504. ((PDRVCALL) hdCall)->pLine,
  5505. htConsultCall,
  5506. lpCallParams,
  5507. &pConsultCall
  5508. )) == 0)
  5509. {
  5510. *lphdConsultCall = (HDRVCALL) pConsultCall;
  5511. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  5512. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  5513. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) pConsultCall;
  5514. info.pAsyncReqInfo->dwParam4 = pConsultCall->dwCallInstance;
  5515. }
  5516. else
  5517. {
  5518. info.lResult = lResult;
  5519. }
  5520. }
  5521. else
  5522. {
  5523. info.lResult = LINEERR_INVALCALLHANDLE;
  5524. }
  5525. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  5526. }
  5527. return (Epilog (&info));
  5528. }
  5529. void
  5530. FAR
  5531. PASCAL
  5532. TSPI_lineSwapHold_postProcess(
  5533. PASYNC_REQUEST_INFO pAsyncReqInfo,
  5534. BOOL bAsync
  5535. )
  5536. {
  5537. DWORD dwActiveCallInstThen = (DWORD) pAsyncReqInfo->dwParam1,
  5538. dwHeldCallInstThen = (DWORD) pAsyncReqInfo->dwParam2,
  5539. dwActiveCallInstNow, dwHeldCallInstNow;
  5540. PDRVCALL pActiveCall = (PDRVCALL) pAsyncReqInfo->dwParam3,
  5541. pHeldCall = (PDRVCALL) pAsyncReqInfo->dwParam4;
  5542. if ((pAsyncReqInfo->lResult == 0))
  5543. {
  5544. //
  5545. // Note - indecision on the final state of the ActiveCall after lineSwapHold()
  5546. // SDK says ONHOLD, internal TAPI documents by NoelA allow several other.
  5547. //
  5548. if (SetCallState(
  5549. pActiveCall,
  5550. dwActiveCallInstThen,
  5551. LINECALLSTATE_CONNECTED,
  5552. LINECALLSTATE_ONHOLD,
  5553. 0,
  5554. TRUE
  5555. ) == 0)
  5556. {
  5557. //
  5558. // Note - indecision on the validity of ONHOLD->CONNECTED transition
  5559. // SDK allows it, internal TAPI documents by NoelA do not.
  5560. //
  5561. SetCallState(
  5562. pHeldCall,
  5563. dwHeldCallInstThen,
  5564. LINECALLSTATE_ONHOLD | LINECALLSTATE_ONHOLDPENDTRANSFER | LINECALLSTATE_ONHOLDPENDCONF,
  5565. LINECALLSTATE_CONNECTED,
  5566. 0,
  5567. TRUE
  5568. );
  5569. }
  5570. }
  5571. DoCompletion (pAsyncReqInfo, bAsync);
  5572. }
  5573. LONG
  5574. TSPIAPI
  5575. TSPI_lineSwapHold(
  5576. DRV_REQUESTID dwRequestID,
  5577. HDRVCALL hdActiveCall,
  5578. HDRVCALL hdHeldCall
  5579. )
  5580. {
  5581. static char szFuncName[] = "lineSwapHold";
  5582. FUNC_PARAM params[] =
  5583. {
  5584. { szdwRequestID, dwRequestID },
  5585. { "hdActiveCall", hdActiveCall },
  5586. { "hdHeldCall", hdHeldCall }
  5587. };
  5588. FUNC_INFO info =
  5589. {
  5590. szFuncName,
  5591. ASYNC,
  5592. 3,
  5593. params,
  5594. TSPI_lineSwapHold_postProcess
  5595. };
  5596. if (Prolog (&info))
  5597. {
  5598. DWORD dwActiveCallInstance, dwHeldCallInstance;
  5599. if (IsValidDrvCall(
  5600. (PDRVCALL) hdActiveCall,
  5601. &dwActiveCallInstance
  5602. ) &&
  5603. IsValidDrvCall(
  5604. (PDRVCALL) hdHeldCall,
  5605. &dwHeldCallInstance
  5606. ))
  5607. {
  5608. info.pAsyncReqInfo->dwParam1 = dwActiveCallInstance;
  5609. info.pAsyncReqInfo->dwParam2 = dwHeldCallInstance;
  5610. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) hdActiveCall;
  5611. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) hdHeldCall;
  5612. }
  5613. else
  5614. {
  5615. info.lResult = LINEERR_INVALCALLHANDLE;
  5616. }
  5617. }
  5618. return (Epilog (&info));
  5619. }
  5620. LONG
  5621. TSPIAPI
  5622. TSPI_lineUncompleteCall(
  5623. DRV_REQUESTID dwRequestID,
  5624. HDRVLINE hdLine,
  5625. DWORD dwCompletionID
  5626. )
  5627. {
  5628. static char szFuncName[] = "lineUncompleteCall";
  5629. FUNC_PARAM params[] =
  5630. {
  5631. { szdwRequestID, dwRequestID },
  5632. { szhdLine, hdLine },
  5633. { "dwCompletionID", dwCompletionID }
  5634. };
  5635. FUNC_INFO info = { szFuncName, ASYNC, 3, params, NULL };
  5636. if (Prolog (&info))
  5637. {
  5638. if (dwCompletionID == 0xffffffff)
  5639. {
  5640. info.lResult = LINEERR_INVALCOMPLETIONID;
  5641. }
  5642. }
  5643. return (Epilog (&info));
  5644. }
  5645. void
  5646. FAR
  5647. PASCAL
  5648. TSPI_lineUnhold_postProcess(
  5649. PASYNC_REQUEST_INFO pAsyncReqInfo,
  5650. BOOL bAsync
  5651. )
  5652. {
  5653. if (pAsyncReqInfo->lResult == 0)
  5654. {
  5655. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam1;
  5656. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam2;
  5657. pAsyncReqInfo->lResult = SetCallState(
  5658. pCall,
  5659. dwCallInstThen,
  5660. LINECALLSTATE_ONHOLD,
  5661. LINECALLSTATE_CONNECTED,
  5662. 0,
  5663. TRUE
  5664. );
  5665. }
  5666. DoCompletion (pAsyncReqInfo, bAsync);
  5667. }
  5668. LONG
  5669. TSPIAPI
  5670. TSPI_lineUnhold(
  5671. DRV_REQUESTID dwRequestID,
  5672. HDRVCALL hdCall
  5673. )
  5674. {
  5675. static char szFuncName[] = "lineUnhold";
  5676. FUNC_PARAM params[] =
  5677. {
  5678. { szdwRequestID, dwRequestID },
  5679. { szhdCall, hdCall },
  5680. };
  5681. FUNC_INFO info =
  5682. {
  5683. szFuncName,
  5684. ASYNC,
  5685. 2,
  5686. params,
  5687. TSPI_lineUnhold_postProcess
  5688. };
  5689. if (Prolog (&info))
  5690. {
  5691. DWORD dwCallInstance;
  5692. if (IsValidDrvCall ((PDRVCALL) hdCall, &dwCallInstance))
  5693. {
  5694. info.pAsyncReqInfo->dwParam1 = dwCallInstance;
  5695. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) hdCall;
  5696. }
  5697. else
  5698. {
  5699. info.lResult = LINEERR_INVALCALLHANDLE;
  5700. }
  5701. }
  5702. return (Epilog (&info));
  5703. }
  5704. void
  5705. FAR
  5706. PASCAL
  5707. TSPI_lineUnpark_postProcess(
  5708. PASYNC_REQUEST_INFO pAsyncReqInfo,
  5709. BOOL bAsync
  5710. )
  5711. {
  5712. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2,
  5713. dwParkIndex = (DWORD) pAsyncReqInfo->dwParam3,
  5714. dwCallInstNow;
  5715. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1;
  5716. if (pAsyncReqInfo->lResult == 0)
  5717. {
  5718. //
  5719. // Make sure there's still a call there to unpark
  5720. //
  5721. if (gaParkedCalls[dwParkIndex] == NULL)
  5722. {
  5723. pAsyncReqInfo->lResult = LINEERR_OPERATIONFAILED;
  5724. }
  5725. }
  5726. DoCompletion (pAsyncReqInfo, bAsync);
  5727. if (pAsyncReqInfo->lResult == 0)
  5728. {
  5729. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  5730. if (gaParkedCalls[dwParkIndex] != NULL &&
  5731. IsValidDrvCall (pCall, &dwCallInstNow) &&
  5732. dwCallInstNow == dwCallInstThen)
  5733. {
  5734. //
  5735. // Copy all the data from the parked call to the new call,
  5736. // then free the parked call
  5737. //
  5738. PDRVCALL pParkedCall = gaParkedCalls[dwParkIndex];
  5739. gaParkedCalls[dwParkIndex] = NULL;
  5740. CopyMemory(
  5741. &pCall->dwMediaMode,
  5742. &pParkedCall->dwMediaMode,
  5743. 14 * sizeof (DWORD) + sizeof (LINEDIALPARAMS)
  5744. );
  5745. if ((pCall->pDestCall = pParkedCall->pDestCall))
  5746. {
  5747. pCall->pDestCall->pDestCall = pCall;
  5748. pCall->bConnectedToDestCall =
  5749. pParkedCall->bConnectedToDestCall;
  5750. }
  5751. CopyMemory(
  5752. &pCall->dwGatherDigitsEndToEndID,
  5753. &pParkedCall->dwGatherDigitsEndToEndID,
  5754. 5 * sizeof (DWORD)
  5755. );
  5756. pCall->dwCallID = pParkedCall->dwCallID;
  5757. //
  5758. // Reset call state to 0 so SetCallState will do the indication
  5759. //
  5760. {
  5761. DWORD dwCallState = pCall->dwCallState;
  5762. pCall->dwCallState = 0;
  5763. SetCallState(
  5764. pCall,
  5765. dwCallInstThen,
  5766. 0xffffffff, // no reqs. we set the current state to 0 just above!
  5767. dwCallState,
  5768. 0,
  5769. TRUE
  5770. );
  5771. }
  5772. SendLineEvent(
  5773. pCall->pLine,
  5774. pCall,
  5775. LINE_CALLINFO,
  5776. LINECALLINFOSTATE_CALLID,
  5777. 0,
  5778. 0
  5779. );
  5780. pParkedCall->dwKey = INVAL_KEY;
  5781. DrvFree (pParkedCall);
  5782. }
  5783. else
  5784. {
  5785. SetCallState(
  5786. pCall,
  5787. dwCallInstThen,
  5788. 0xffffffff, // all states are valid
  5789. LINECALLSTATE_IDLE,
  5790. 0,
  5791. TRUE
  5792. );
  5793. }
  5794. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  5795. }
  5796. else
  5797. {
  5798. FreeCall (pCall, dwCallInstThen);
  5799. }
  5800. }
  5801. LONG
  5802. TSPIAPI
  5803. TSPI_lineUnpark(
  5804. DRV_REQUESTID dwRequestID,
  5805. HDRVLINE hdLine,
  5806. DWORD dwAddressID,
  5807. HTAPICALL htCall,
  5808. LPHDRVCALL lphdCall,
  5809. LPCWSTR lpszDestAddress
  5810. )
  5811. {
  5812. static char szFuncName[] = "lineUnpark";
  5813. FUNC_PARAM params[] =
  5814. {
  5815. { szdwRequestID, dwRequestID },
  5816. { szhdLine, hdLine },
  5817. { "dwAddressID", dwAddressID },
  5818. { "htCall", htCall },
  5819. { "lphdCall", lphdCall },
  5820. { "lpszDestAddress", lpszDestAddress }
  5821. };
  5822. FUNC_INFO info =
  5823. {
  5824. szFuncName,
  5825. ASYNC,
  5826. 6,
  5827. params,
  5828. NULL
  5829. };
  5830. if (Prolog (&info))
  5831. {
  5832. //
  5833. // See if the park addr is valid, & if there's actually a
  5834. // call parked there now
  5835. //
  5836. char *pszDestAddress, *p, c;
  5837. DWORD length, dwParkIndex;
  5838. //
  5839. // Convert dest addr from unicode to ascii
  5840. //
  5841. length = (lstrlenW (lpszDestAddress) + 1) * sizeof (WCHAR);
  5842. if (!(pszDestAddress = DrvAlloc (length)))
  5843. {
  5844. info.lResult = LINEERR_NOMEM;
  5845. return (Epilog (&info));
  5846. }
  5847. WideCharToMultiByte(
  5848. CP_ACP,
  5849. 0,
  5850. lpszDestAddress,
  5851. -1,
  5852. pszDestAddress,
  5853. length,
  5854. NULL,
  5855. NULL
  5856. );
  5857. p = pszDestAddress;
  5858. //
  5859. // See if destination address is in the format of "9999#<addr id>"
  5860. //
  5861. if (*p++ != '9' ||
  5862. *p++ != '9' ||
  5863. *p++ != '9' ||
  5864. *p++ != '9' ||
  5865. *p++ != '#' ||
  5866. *p < '0' ||
  5867. *p > '9')
  5868. {
  5869. info.lResult = LINEERR_INVALADDRESS;
  5870. goto TSPI_lineUnpark_freeDestAddress;
  5871. }
  5872. for (dwParkIndex = 0; (c = *p); p++)
  5873. {
  5874. if (c >= '0' && c <= '9')
  5875. {
  5876. dwParkIndex *= 10;
  5877. dwParkIndex += ((DWORD)(c - '0'));
  5878. }
  5879. else
  5880. {
  5881. break;
  5882. }
  5883. }
  5884. if (c != '\0' || dwParkIndex >= MAX_NUM_PARKED_CALLS)
  5885. {
  5886. info.lResult = LINEERR_INVALADDRESS;
  5887. goto TSPI_lineUnpark_freeDestAddress;
  5888. }
  5889. if (gaParkedCalls[dwParkIndex] != NULL)
  5890. {
  5891. PDRVCALL pCall;
  5892. LINECALLPARAMS callParams;
  5893. ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
  5894. callParams.dwTotalSize = sizeof (LINECALLPARAMS);
  5895. callParams.dwAddressID = dwAddressID;
  5896. callParams.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  5897. if ((info.lResult = AllocCall(
  5898. (PDRVLINE) hdLine,
  5899. htCall,
  5900. &callParams,
  5901. &pCall
  5902. )) == 0)
  5903. {
  5904. pCall->dwCallID = gaParkedCalls[dwParkIndex]->dwCallID;
  5905. pCall->dwRelatedCallID = gaParkedCalls[dwParkIndex]->dwRelatedCallID;
  5906. pCall->dwAddressType = gaParkedCalls[dwParkIndex]->dwAddressType;
  5907. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) pCall;
  5908. info.pAsyncReqInfo->dwParam2 = pCall->dwCallInstance;
  5909. info.pAsyncReqInfo->dwParam3 = dwParkIndex;
  5910. *lphdCall = (HDRVCALL) pCall;
  5911. info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  5912. TSPI_lineUnpark_postProcess;
  5913. }
  5914. }
  5915. else
  5916. {
  5917. info.lResult = LINEERR_OPERATIONFAILED;
  5918. }
  5919. TSPI_lineUnpark_freeDestAddress:
  5920. DrvFree (pszDestAddress);
  5921. }
  5922. return (Epilog (&info));
  5923. }
  5924. //
  5925. // -------------------------- TSPI_phoneXxx funcs -----------------------------
  5926. //
  5927. LONG
  5928. TSPIAPI
  5929. TSPI_phoneClose(
  5930. HDRVPHONE hdPhone
  5931. )
  5932. {
  5933. static char szFuncName[] = "phoneClose";
  5934. FUNC_PARAM params[] =
  5935. {
  5936. { szhdPhone, hdPhone }
  5937. };
  5938. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  5939. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  5940. //
  5941. // This is more of a "command" than a request, in that TAPI.DLL is
  5942. // going to consider the phone closed whether we like it or not.
  5943. // Therefore we want to free up the phone even if the user chooses
  5944. // to return an error.
  5945. //
  5946. Prolog (&info);
  5947. pPhone->htPhone = (HTAPIPHONE) NULL;
  5948. WriteEventBuffer (pPhone->dwDeviceID, WIDGETTYPE_PHONE, 0, 0, 0, 0);
  5949. return (Epilog (&info));
  5950. }
  5951. LONG
  5952. TSPIAPI
  5953. TSPI_phoneDevSpecific(
  5954. DRV_REQUESTID dwRequestID,
  5955. HDRVPHONE hdPhone,
  5956. LPVOID lpParams,
  5957. DWORD dwSize
  5958. )
  5959. {
  5960. static char szFuncName[] = "phoneDevSpecific";
  5961. FUNC_PARAM params[] =
  5962. {
  5963. { szdwRequestID, dwRequestID },
  5964. { szhdPhone, hdPhone },
  5965. { "lpParams", lpParams },
  5966. { szdwSize, dwSize }
  5967. };
  5968. FUNC_INFO info =
  5969. {
  5970. szFuncName,
  5971. ASYNC,
  5972. 4,
  5973. params
  5974. };
  5975. if (Prolog (&info))
  5976. {
  5977. PESPDEVSPECIFICINFO pInfo = (PESPDEVSPECIFICINFO) lpParams;
  5978. if (dwSize >= sizeof (ESPDEVSPECIFICINFO) &&
  5979. pInfo->dwKey == ESPDEVSPECIFIC_KEY)
  5980. {
  5981. switch (pInfo->dwType)
  5982. {
  5983. case ESP_DEVSPEC_MSG:
  5984. switch (pInfo->u.EspMsg.dwMsg)
  5985. {
  5986. case PHONE_BUTTON:
  5987. case PHONE_CLOSE:
  5988. case PHONE_DEVSPECIFIC:
  5989. case PHONE_STATE:
  5990. SendPhoneEvent(
  5991. (PDRVPHONE) hdPhone,
  5992. pInfo->u.EspMsg.dwMsg,
  5993. pInfo->u.EspMsg.dwParam1,
  5994. pInfo->u.EspMsg.dwParam2,
  5995. pInfo->u.EspMsg.dwParam3
  5996. );
  5997. break;
  5998. case PHONE_CREATE:
  5999. if (gESPGlobals.pPhones->dwNumUsedEntries <
  6000. gESPGlobals.pPhones->dwNumTotalEntries)
  6001. {
  6002. (*gESPGlobals.pfnPhoneEvent)(
  6003. (HTAPIPHONE) NULL,
  6004. PHONE_CREATE,
  6005. (ULONG_PTR) gESPGlobals.hProvider,
  6006. gESPGlobals.pPhones->dwNumUsedEntries++,
  6007. 0
  6008. );
  6009. }
  6010. else
  6011. {
  6012. ShowStr(
  6013. TRUE,
  6014. "ERROR: TSPI_phoneDevSpecific: attempt " \
  6015. "to send PHONE_CREATE - can't create " \
  6016. "any more devices on the fly"
  6017. );
  6018. info.lResult = PHONEERR_OPERATIONFAILED;
  6019. }
  6020. break;
  6021. default:
  6022. ShowStr(
  6023. TRUE,
  6024. "ERROR: TSPI_phoneDevSpecific: unrecognized " \
  6025. "ESPDEVSPECIFICINFO.u.EspMsg.dwMsg (=x%x)",
  6026. pInfo->u.EspMsg.dwMsg
  6027. );
  6028. info.lResult = PHONEERR_OPERATIONFAILED;
  6029. break;
  6030. }
  6031. break;
  6032. case ESP_DEVSPEC_RESULT:
  6033. {
  6034. DWORD dwResult = pInfo->u.EspResult.lResult;
  6035. if (dwResult != 0 &&
  6036. (dwResult < LINEERR_ALLOCATED ||
  6037. dwResult > PHONEERR_REINIT ||
  6038. (dwResult > LINEERR_DIALVOICEDETECT &&
  6039. dwResult < PHONEERR_ALLOCATED)))
  6040. {
  6041. ShowStr(
  6042. TRUE,
  6043. "ERROR: TSPI_phoneDevSpecific: invalid request" \
  6044. "result value (x%x)",
  6045. dwResult
  6046. );
  6047. info.lResult = PHONEERR_OPERATIONFAILED;
  6048. }
  6049. else if (pInfo->u.EspResult.dwCompletionType >
  6050. ESP_RESULT_CALLCOMPLPROCASYNC)
  6051. {
  6052. ShowStr(
  6053. TRUE,
  6054. "ERROR: TSPI_phoneDevSpecific: invalid request" \
  6055. "completion type (x%x)",
  6056. pInfo->u.EspResult.dwCompletionType
  6057. );
  6058. info.lResult = PHONEERR_OPERATIONFAILED;
  6059. }
  6060. else
  6061. {
  6062. glNextRequestResult = (LONG) dwResult;
  6063. gdwNextRequestCompletionType =
  6064. pInfo->u.EspResult.dwCompletionType;
  6065. gdwDevSpecificRequestID = dwRequestID;
  6066. }
  6067. break;
  6068. }
  6069. default:
  6070. ShowStr(
  6071. TRUE,
  6072. "ERROR: TSPI_phoneDevSpecific: unrecognized " \
  6073. "ESPDEVSPECIFICINFO.dwType (=x%x)",
  6074. pInfo->dwType
  6075. );
  6076. info.lResult = PHONEERR_OPERATIONFAILED;
  6077. break;
  6078. }
  6079. }
  6080. else
  6081. {
  6082. info.pAsyncReqInfo->dwParam1 = lpParams;
  6083. info.pAsyncReqInfo->dwParam2 = dwSize;
  6084. info.pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  6085. TSPI_lineDevSpecific_postProcess;
  6086. }
  6087. }
  6088. return (Epilog (&info));
  6089. }
  6090. LONG
  6091. TSPIAPI
  6092. TSPI_phoneGetButtonInfo(
  6093. HDRVPHONE hdPhone,
  6094. DWORD dwButtonLampID,
  6095. LPPHONEBUTTONINFO lpButtonInfo
  6096. )
  6097. {
  6098. static char szFuncName[] = "phoneGetButtonInfo";
  6099. FUNC_PARAM params[] =
  6100. {
  6101. { szhdPhone, hdPhone },
  6102. { "dwButtonLampID", dwButtonLampID },
  6103. { "lpButtonInfo", lpButtonInfo }
  6104. };
  6105. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6106. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6107. if (Prolog (&info))
  6108. {
  6109. if (dwButtonLampID == 0)
  6110. {
  6111. if (pPhone->pButtonInfo)
  6112. {
  6113. if (pPhone->pButtonInfo->dwUsedSize <=
  6114. lpButtonInfo->dwTotalSize)
  6115. {
  6116. CopyMemory(
  6117. (LPBYTE) &lpButtonInfo->dwNeededSize,
  6118. (LPBYTE) &pPhone->pButtonInfo->dwNeededSize,
  6119. pPhone->pButtonInfo->dwUsedSize - sizeof (DWORD)
  6120. );
  6121. }
  6122. else
  6123. {
  6124. lpButtonInfo->dwNeededSize =
  6125. pPhone->pButtonInfo->dwUsedSize;
  6126. }
  6127. }
  6128. }
  6129. else
  6130. {
  6131. info.lResult = PHONEERR_INVALBUTTONLAMPID;
  6132. }
  6133. }
  6134. return (Epilog (&info));
  6135. }
  6136. LONG
  6137. TSPIAPI
  6138. TSPI_phoneGetData(
  6139. HDRVPHONE hdPhone,
  6140. DWORD dwDataID,
  6141. LPVOID lpData,
  6142. DWORD dwSize
  6143. )
  6144. {
  6145. static char szFuncName[] = "phoneGetData";
  6146. FUNC_PARAM params[] =
  6147. {
  6148. { szhdPhone, hdPhone },
  6149. { "dwDataID", dwDataID },
  6150. { "lpData", lpData },
  6151. { szdwSize, dwSize }
  6152. };
  6153. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  6154. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6155. if (Prolog (&info))
  6156. {
  6157. if (dwDataID != 0)
  6158. {
  6159. info.lResult = PHONEERR_INVALDATAID;
  6160. }
  6161. else if (pPhone->pData)
  6162. {
  6163. CopyMemory(
  6164. lpData,
  6165. pPhone->pData,
  6166. (dwSize > pPhone->dwDataSize ? pPhone->dwDataSize : dwSize)
  6167. );
  6168. }
  6169. }
  6170. return (Epilog (&info));
  6171. }
  6172. LONG
  6173. TSPIAPI
  6174. TSPI_phoneGetDevCaps(
  6175. DWORD dwDeviceID,
  6176. DWORD dwTSPIVersion,
  6177. DWORD dwExtVersion,
  6178. LPPHONECAPS lpPhoneCaps
  6179. )
  6180. {
  6181. static char szFuncName[] = "phoneGetDevCaps";
  6182. FUNC_PARAM params[] =
  6183. {
  6184. { szdwDeviceID, dwDeviceID },
  6185. { "dwTSPIVersion", dwTSPIVersion },
  6186. { "dwExtVersion", dwExtVersion },
  6187. { "lpPhoneCaps", lpPhoneCaps }
  6188. };
  6189. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  6190. char buf[32];
  6191. WCHAR wbuf[32];
  6192. DWORD dwDummy;
  6193. PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
  6194. if (Prolog (&info))
  6195. {
  6196. //lpPhoneCaps->dwNeededSize
  6197. //lpPhoneCaps->dwUsedSize
  6198. InsertVarDataString(
  6199. lpPhoneCaps,
  6200. &lpPhoneCaps->dwProviderInfoSize,
  6201. gszProviderInfo
  6202. );
  6203. //lpPhoneCaps->dwPhoneInfoSize
  6204. //lpPhoneCaps->dwPhoneInfoOffset
  6205. lpPhoneCaps->dwPermanentPhoneID =
  6206. (gESPGlobals.dwPermanentProviderID << 16) |
  6207. (dwDeviceID - gESPGlobals.dwPhoneDeviceIDBase);
  6208. // NOTE: win9x doesn't support wsprintfW
  6209. wsprintfA (buf, "ESP Phone %d", dwDeviceID);
  6210. MultiByteToWideChar(
  6211. GetACP(),
  6212. MB_PRECOMPOSED,
  6213. buf,
  6214. lstrlen (buf) + 1,
  6215. wbuf,
  6216. 20
  6217. );
  6218. InsertVarDataString(
  6219. lpPhoneCaps,
  6220. &lpPhoneCaps->dwPhoneNameSize,
  6221. wbuf
  6222. );
  6223. lpPhoneCaps->dwStringFormat = STRINGFORMAT_ASCII;
  6224. //lpPhoneCaps->dwPhoneStates
  6225. lpPhoneCaps->dwHookSwitchDevs = AllHookSwitchDevs;
  6226. lpPhoneCaps->dwHandsetHookSwitchModes =
  6227. lpPhoneCaps->dwSpeakerHookSwitchModes =
  6228. lpPhoneCaps->dwHeadsetHookSwitchModes = AllHookSwitchModes;
  6229. lpPhoneCaps->dwVolumeFlags = AllHookSwitchDevs;
  6230. lpPhoneCaps->dwGainFlags = AllHookSwitchDevs;
  6231. lpPhoneCaps->dwDisplayNumRows = 1;
  6232. lpPhoneCaps->dwDisplayNumColumns = PHONE_DISPLAY_SIZE_IN_CHARS;
  6233. lpPhoneCaps->dwNumRingModes = 0xffffffff;
  6234. lpPhoneCaps->dwNumButtonLamps = 1;
  6235. dwDummy = PHONEBUTTONMODE_FEATURE;
  6236. InsertVarData(
  6237. lpPhoneCaps,
  6238. &lpPhoneCaps->dwButtonModesSize,
  6239. (LPVOID) &dwDummy,
  6240. sizeof (DWORD)
  6241. );
  6242. dwDummy = PHONEBUTTONFUNCTION_UNKNOWN;
  6243. InsertVarData(
  6244. lpPhoneCaps,
  6245. &lpPhoneCaps->dwButtonFunctionsSize,
  6246. (LPVOID) &dwDummy,
  6247. sizeof (DWORD)
  6248. );
  6249. dwDummy = PHONELAMPMODE_OFF;
  6250. InsertVarData(
  6251. lpPhoneCaps,
  6252. &lpPhoneCaps->dwLampModesSize,
  6253. (LPVOID) &dwDummy,
  6254. sizeof (DWORD)
  6255. );
  6256. lpPhoneCaps->dwNumSetData = 1;
  6257. dwDummy = MAX_VAR_DATA_SIZE;
  6258. InsertVarData(
  6259. lpPhoneCaps,
  6260. &lpPhoneCaps->dwSetDataSize,
  6261. (LPVOID) &dwDummy,
  6262. sizeof (DWORD)
  6263. );
  6264. lpPhoneCaps->dwNumGetData = 1;
  6265. InsertVarData(
  6266. lpPhoneCaps,
  6267. &lpPhoneCaps->dwGetDataSize,
  6268. (LPVOID) &dwDummy,
  6269. sizeof (DWORD)
  6270. );
  6271. //lpPhoneCaps->dwDevSpecificSize
  6272. //lpPhoneCaps->dwDevSpecificOffset
  6273. if (gESPGlobals.dwSPIVersion >= 0x00020000)
  6274. {
  6275. //lpPhoneCaps->dwDeviceClassesSize
  6276. //lpPhoneCaps->dwDeviceClassesOffset
  6277. lpPhoneCaps->dwPhoneFeatures = AllPhoneFeatures;
  6278. lpPhoneCaps->dwSettableHandsetHookSwitchModes =
  6279. lpPhoneCaps->dwSettableSpeakerHookSwitchModes =
  6280. lpPhoneCaps->dwSettableHeadsetHookSwitchModes = AllHookSwitchModes;
  6281. //lpPhoneCaps->dwMonitoredHandsetHookSwitchModes
  6282. //lpPhoneCaps->dwMonitoredSpeakerHookSwitchModes
  6283. //lpPhoneCaps->dwMonitoredHeadsetHookSwitchModes
  6284. if (gESPGlobals.dwSPIVersion >= 0x00020002)
  6285. {
  6286. lpPhoneCaps->PermanentPhoneGuid.Data1 = (long)
  6287. (dwDeviceID - gESPGlobals.dwPhoneDeviceIDBase);
  6288. *((LPDWORD) &lpPhoneCaps->PermanentPhoneGuid.Data2) =
  6289. *((LPDWORD) &lpPhoneCaps->PermanentPhoneGuid.Data4[0]) =
  6290. *((LPDWORD) &lpPhoneCaps->PermanentPhoneGuid.Data4[4]) =
  6291. DRVPHONE_KEY;
  6292. }
  6293. }
  6294. }
  6295. return (Epilog (&info));
  6296. }
  6297. LONG
  6298. TSPIAPI
  6299. TSPI_phoneGetDisplay(
  6300. HDRVPHONE hdPhone,
  6301. LPVARSTRING lpDisplay
  6302. )
  6303. {
  6304. static char szFuncName[] = "phoneGetDisplay";
  6305. FUNC_PARAM params[] =
  6306. {
  6307. { szhdPhone, hdPhone },
  6308. { "lpDisplay", lpDisplay }
  6309. };
  6310. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  6311. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6312. if (Prolog (&info))
  6313. {
  6314. static DWORD dwNeededSize = sizeof(VARSTRING) +
  6315. PHONE_DISPLAY_SIZE_IN_BYTES;
  6316. if (lpDisplay->dwTotalSize >= dwNeededSize)
  6317. {
  6318. if (pPhone->pDisplay)
  6319. {
  6320. CopyMemory(
  6321. lpDisplay + 1,
  6322. pPhone->pDisplay,
  6323. PHONE_DISPLAY_SIZE_IN_BYTES
  6324. );
  6325. }
  6326. else
  6327. {
  6328. ZeroMemory (lpDisplay + 1, PHONE_DISPLAY_SIZE_IN_BYTES);
  6329. }
  6330. lpDisplay->dwUsedSize = dwNeededSize;
  6331. lpDisplay->dwStringFormat = STRINGFORMAT_ASCII;
  6332. lpDisplay->dwStringSize = PHONE_DISPLAY_SIZE_IN_BYTES;
  6333. lpDisplay->dwStringOffset = sizeof (VARSTRING);
  6334. }
  6335. lpDisplay->dwNeededSize = dwNeededSize;
  6336. }
  6337. return (Epilog (&info));
  6338. }
  6339. LONG
  6340. TSPIAPI
  6341. TSPI_phoneGetExtensionID(
  6342. DWORD dwDeviceID,
  6343. DWORD dwTSPIVersion,
  6344. LPPHONEEXTENSIONID lpExtensionID
  6345. )
  6346. {
  6347. static char szFuncName[] = "phoneGetExtensionID";
  6348. FUNC_PARAM params[] =
  6349. {
  6350. { szdwDeviceID, dwDeviceID },
  6351. { "dwTSPIVersion", dwTSPIVersion },
  6352. { "lpExtensionID", lpExtensionID }
  6353. };
  6354. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6355. if (Prolog (&info))
  6356. {
  6357. // BUGBUG TSPI_phoneGetExtensionID:
  6358. }
  6359. return (Epilog (&info));
  6360. }
  6361. LONG
  6362. TSPIAPI
  6363. TSPI_phoneGetGain(
  6364. HDRVPHONE hdPhone,
  6365. DWORD dwHookSwitchDev,
  6366. LPDWORD lpdwGain
  6367. )
  6368. {
  6369. static char szFuncName[] = "phoneGetGain";
  6370. FUNC_PARAM params[] =
  6371. {
  6372. { szhdPhone, hdPhone },
  6373. { "dwHookSwitchDev", dwHookSwitchDev },
  6374. { "lpdwGain", lpdwGain }
  6375. };
  6376. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6377. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6378. if (Prolog (&info))
  6379. {
  6380. switch (dwHookSwitchDev)
  6381. {
  6382. case PHONEHOOKSWITCHDEV_HANDSET:
  6383. *lpdwGain = pPhone->dwHandsetGain;
  6384. break;
  6385. case PHONEHOOKSWITCHDEV_SPEAKER:
  6386. *lpdwGain = pPhone->dwSpeakerGain;
  6387. break;
  6388. case PHONEHOOKSWITCHDEV_HEADSET:
  6389. *lpdwGain = pPhone->dwHeadsetGain;
  6390. break;
  6391. }
  6392. }
  6393. return (Epilog (&info));
  6394. }
  6395. LONG
  6396. TSPIAPI
  6397. TSPI_phoneGetHookSwitch(
  6398. HDRVPHONE hdPhone,
  6399. LPDWORD lpdwHookSwitchDevs
  6400. )
  6401. {
  6402. static char szFuncName[] = "phoneGetHookSwitch";
  6403. FUNC_PARAM params[] =
  6404. {
  6405. { szhdPhone, hdPhone },
  6406. { "lpdwHookSwitchDevs", lpdwHookSwitchDevs }
  6407. };
  6408. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  6409. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6410. if (Prolog (&info))
  6411. {
  6412. *lpdwHookSwitchDevs = 0;
  6413. if (!(pPhone->dwHandsetHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
  6414. {
  6415. *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_HANDSET;
  6416. }
  6417. if (!(pPhone->dwSpeakerHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
  6418. {
  6419. *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_SPEAKER;
  6420. }
  6421. if (!(pPhone->dwHeadsetHookSwitchMode & PHONEHOOKSWITCHMODE_ONHOOK))
  6422. {
  6423. *lpdwHookSwitchDevs |= PHONEHOOKSWITCHDEV_HEADSET;
  6424. }
  6425. }
  6426. return (Epilog (&info));
  6427. }
  6428. LONG
  6429. TSPIAPI
  6430. TSPI_phoneGetIcon(
  6431. DWORD dwDeviceID,
  6432. LPCWSTR lpszDeviceClass,
  6433. LPHICON lphIcon
  6434. )
  6435. {
  6436. static char szFuncName[] = "phoneGetIcon";
  6437. FUNC_PARAM params[] =
  6438. {
  6439. { szdwDeviceID, dwDeviceID },
  6440. { "lpszDeviceClass", lpszDeviceClass },
  6441. { "lphIcon", lphIcon }
  6442. };
  6443. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6444. if (Prolog (&info))
  6445. {
  6446. if (lpszDeviceClass &&
  6447. My_lstrcmpiW(
  6448. (WCHAR *) lpszDeviceClass,
  6449. (WCHAR *) (L"tapi/InvalidDeviceClass")
  6450. ) == 0)
  6451. {
  6452. info.lResult = PHONEERR_INVALDEVICECLASS;
  6453. }
  6454. else
  6455. {
  6456. *lphIcon = gESPGlobals.hIconPhone;
  6457. }
  6458. }
  6459. return (Epilog (&info));
  6460. }
  6461. LONG
  6462. TSPIAPI
  6463. TSPI_phoneGetID(
  6464. HDRVPHONE hdPhone,
  6465. LPVARSTRING lpDeviceID,
  6466. LPCWSTR lpszDeviceClass,
  6467. HANDLE hTargetProcess
  6468. )
  6469. {
  6470. static char szFuncName[] = "phoneGetID";
  6471. FUNC_PARAM params[] =
  6472. {
  6473. { szhdPhone, hdPhone },
  6474. { "lpDeviceID", lpDeviceID },
  6475. { "lpszDeviceClass", lpszDeviceClass }
  6476. ,{ "hTargetProcess", hTargetProcess }
  6477. };
  6478. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  6479. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6480. DWORD i, j, dwDeviceID, dwNeededSize, dwNumDeviceIDs = 1;
  6481. DWORD *lpdwDeviceIDs;
  6482. if (!Prolog (&info))
  6483. {
  6484. return (Epilog (&info));
  6485. }
  6486. for (i = 0; aszDeviceClasses[i]; i++)
  6487. {
  6488. if (My_lstrcmpiW(
  6489. (WCHAR *) lpszDeviceClass,
  6490. (WCHAR *) aszDeviceClasses[i]
  6491. ) == 0)
  6492. {
  6493. break;
  6494. }
  6495. }
  6496. if (!aszDeviceClasses[i])
  6497. {
  6498. info.lResult = PHONEERR_NODEVICE;
  6499. return (Epilog (&info));
  6500. }
  6501. if (i == 1) //tapi/phone
  6502. {
  6503. dwNumDeviceIDs = 1;
  6504. dwNeededSize = sizeof(VARSTRING) + (dwNumDeviceIDs * sizeof(DWORD));
  6505. if (lpDeviceID->dwTotalSize < dwNeededSize)
  6506. {
  6507. lpDeviceID->dwNeededSize = dwNeededSize;
  6508. lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
  6509. return (Epilog (&info));
  6510. }
  6511. if (! (lpdwDeviceIDs = DrvAlloc(dwNumDeviceIDs * sizeof(DWORD)) ) )
  6512. {
  6513. info.lResult = PHONEERR_NOMEM;
  6514. return (Epilog (&info));
  6515. }
  6516. lpdwDeviceIDs[0] = pPhone->dwDeviceID;
  6517. }
  6518. else if (i == 0) //tapi/line
  6519. {
  6520. PDRVLINE pLine;
  6521. // create a list of all the ESP deviceIDs
  6522. dwNumDeviceIDs = gESPGlobals.dwInitialNumLines + gESPGlobals.pLines->dwNumUsedEntries;
  6523. dwNeededSize = sizeof(VARSTRING) + (dwNumDeviceIDs * sizeof(DWORD));
  6524. if (lpDeviceID->dwTotalSize < dwNeededSize)
  6525. {
  6526. lpDeviceID->dwNeededSize = dwNeededSize;
  6527. lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
  6528. return (Epilog (&info));
  6529. }
  6530. if (! (lpdwDeviceIDs = DrvAlloc(dwNumDeviceIDs * sizeof(DWORD))))
  6531. {
  6532. info.lResult = PHONEERR_NOMEM;
  6533. return (Epilog (&info));
  6534. }
  6535. for (j = 0;
  6536. j < gESPGlobals.dwInitialNumLines;
  6537. j++)
  6538. {
  6539. lpdwDeviceIDs[j] = gESPGlobals.dwLineDeviceIDBase + j;
  6540. }
  6541. pLine = (PDRVLINE) (((LPBYTE) gESPGlobals.pLines->aLines) +
  6542. (gESPGlobals.dwInitialNumLines * gdwDrvLineSize));
  6543. for( j = gESPGlobals.dwInitialNumLines;
  6544. j < gESPGlobals.pLines->dwNumUsedEntries;
  6545. j++
  6546. )
  6547. {
  6548. lpdwDeviceIDs[j] = pLine->dwDeviceID;
  6549. pLine = (PDRVLINE) (((LPBYTE) pLine) + gdwDrvLineSize);
  6550. }
  6551. }
  6552. else
  6553. {
  6554. dwNumDeviceIDs = 1;
  6555. dwNeededSize = sizeof(VARSTRING) + (dwNumDeviceIDs * sizeof(DWORD));
  6556. if (lpDeviceID->dwTotalSize < dwNeededSize)
  6557. {
  6558. lpDeviceID->dwNeededSize = dwNeededSize;
  6559. lpDeviceID->dwUsedSize = 3 * sizeof(DWORD);
  6560. return (Epilog (&info));
  6561. }
  6562. if (! (lpdwDeviceIDs = DrvAlloc(dwNumDeviceIDs * sizeof(DWORD))))
  6563. {
  6564. info.lResult = PHONEERR_NOMEM;
  6565. return (Epilog (&info));
  6566. }
  6567. lpdwDeviceIDs[0] = 0;
  6568. // needs to be modified according to the previous two cases before uncommenting
  6569. /* BUGBUG TSPI_phoneGetID: if (gbShowLineGetIDDlg)
  6570. {
  6571. char szDlgTitle[64];
  6572. EVENT_PARAM params[] =
  6573. {
  6574. { "dwDeviceID", PT_DWORD, gdwDefLineGetIDID, 0 }
  6575. };
  6576. EVENT_PARAM_HEADER paramsHeader =
  6577. { 1, szDlgTitle, 0, params };
  6578. HWND hwnd;
  6579. if (strlen (lpszDeviceClass) > 20)
  6580. {
  6581. ((char far *)lpszDeviceClass)[19] = 0;
  6582. }
  6583. wsprintfA(
  6584. szDlgTitle,
  6585. "TSPI_phoneGetID: select ID for class '%s'",
  6586. lpszDeviceClass
  6587. );
  6588. hwnd = CreateDialogParam(
  6589. ghInstance,
  6590. (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG3),
  6591. (HWND) NULL,
  6592. (DLGPROC) CallDlgProc,
  6593. (LPARAM) &paramsHeader
  6594. );
  6595. MsgLoopInTAPIClientContext (hwnd);
  6596. dwDeviceID = params[0].dwValue;
  6597. }
  6598. else
  6599. {
  6600. dwDeviceID = 0;
  6601. }
  6602. */
  6603. }
  6604. lpDeviceID->dwNeededSize =
  6605. lpDeviceID->dwUsedSize = dwNeededSize;
  6606. lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
  6607. lpDeviceID->dwStringSize = sizeof(DWORD) * dwNumDeviceIDs;
  6608. lpDeviceID->dwStringOffset = sizeof(VARSTRING);
  6609. for (j = 0; j < dwNumDeviceIDs; j++)
  6610. {
  6611. *( ((LPDWORD)(lpDeviceID + 1)) + j) = lpdwDeviceIDs[j];
  6612. }
  6613. DrvFree(lpdwDeviceIDs);
  6614. return (Epilog (&info));
  6615. }
  6616. LONG
  6617. TSPIAPI
  6618. TSPI_phoneGetLamp(
  6619. HDRVPHONE hdPhone,
  6620. DWORD dwButtonLampID,
  6621. LPDWORD lpdwLampMode
  6622. )
  6623. {
  6624. static char szFuncName[] = "phoneGetLamp";
  6625. FUNC_PARAM params[] =
  6626. {
  6627. { szhdPhone, hdPhone },
  6628. { "dwButtonLampID", dwButtonLampID },
  6629. { "lpdwLampMode", lpdwLampMode }
  6630. };
  6631. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6632. if (Prolog (&info))
  6633. {
  6634. *lpdwLampMode = ((PDRVPHONE) hdPhone)->dwLampMode;
  6635. }
  6636. return (Epilog (&info));
  6637. }
  6638. LONG
  6639. TSPIAPI
  6640. TSPI_phoneGetRing(
  6641. HDRVPHONE hdPhone,
  6642. LPDWORD lpdwRingMode,
  6643. LPDWORD lpdwVolume
  6644. )
  6645. {
  6646. static char szFuncName[] = "phoneGetRing";
  6647. FUNC_PARAM params[] =
  6648. {
  6649. { szhdPhone, hdPhone },
  6650. { "lpdwRingMode", lpdwRingMode },
  6651. { "lpdwVolume", lpdwVolume }
  6652. };
  6653. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6654. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6655. if (Prolog (&info))
  6656. {
  6657. *lpdwRingMode = pPhone->dwRingMode;
  6658. *lpdwVolume = pPhone->dwRingVolume;
  6659. }
  6660. return (Epilog (&info));
  6661. }
  6662. LONG
  6663. TSPIAPI
  6664. TSPI_phoneGetStatus(
  6665. HDRVPHONE hdPhone,
  6666. LPPHONESTATUS lpPhoneStatus
  6667. )
  6668. {
  6669. static char szFuncName[] = "phoneGetStatus";
  6670. FUNC_PARAM params[] =
  6671. {
  6672. { szhdPhone, hdPhone },
  6673. { "lpPhoneStatus", lpPhoneStatus }
  6674. };
  6675. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  6676. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6677. if (Prolog (&info))
  6678. {
  6679. //lpPhoneStatus->dwStatusFlags;
  6680. lpPhoneStatus->dwRingMode = pPhone->dwRingMode;
  6681. lpPhoneStatus->dwRingVolume = pPhone->dwRingVolume;
  6682. lpPhoneStatus->dwHandsetHookSwitchMode =
  6683. pPhone->dwHandsetHookSwitchMode;
  6684. lpPhoneStatus->dwHandsetVolume = pPhone->dwHandsetVolume;
  6685. lpPhoneStatus->dwHandsetGain = pPhone->dwHandsetGain;
  6686. lpPhoneStatus->dwSpeakerHookSwitchMode =
  6687. pPhone->dwSpeakerHookSwitchMode;
  6688. lpPhoneStatus->dwSpeakerVolume = pPhone->dwSpeakerVolume;
  6689. lpPhoneStatus->dwSpeakerGain = pPhone->dwSpeakerGain;
  6690. lpPhoneStatus->dwHeadsetHookSwitchMode =
  6691. pPhone->dwHeadsetHookSwitchMode;
  6692. lpPhoneStatus->dwHeadsetVolume = pPhone->dwHeadsetVolume;
  6693. lpPhoneStatus->dwHeadsetGain = pPhone->dwHeadsetGain;
  6694. // BUGBUG TSPI_phoneGetStatus: copy 0's to display buf if !pDisplay
  6695. InsertVarData(
  6696. lpPhoneStatus,
  6697. &lpPhoneStatus->dwDisplaySize,
  6698. (LPVOID) pPhone->pDisplay,
  6699. (pPhone->pDisplay ? PHONE_DISPLAY_SIZE_IN_BYTES : 0)
  6700. );
  6701. InsertVarData(
  6702. lpPhoneStatus,
  6703. &lpPhoneStatus->dwLampModesSize,
  6704. (LPVOID) &pPhone->dwLampMode,
  6705. sizeof (DWORD)
  6706. );
  6707. //lpPhoneStatus->dwDevSpecificSize;
  6708. //lpPhoneStatus->dwDevSpecificOffset;
  6709. if (gESPGlobals.dwSPIVersion >= 0x00020000)
  6710. {
  6711. //lpPhoneStatus->
  6712. }
  6713. }
  6714. return (Epilog (&info));
  6715. }
  6716. LONG
  6717. TSPIAPI
  6718. TSPI_phoneGetVolume(
  6719. HDRVPHONE hdPhone,
  6720. DWORD dwHookSwitchDev,
  6721. LPDWORD lpdwVolume
  6722. )
  6723. {
  6724. static char szFuncName[] = "phoneGetVolume";
  6725. FUNC_PARAM params[] =
  6726. {
  6727. { szhdPhone, hdPhone },
  6728. { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
  6729. { "lpdwVolume", lpdwVolume }
  6730. };
  6731. FUNC_INFO info = { szFuncName, SYNC, 3, params };
  6732. PDRVPHONE pPhone = (PDRVPHONE) hdPhone;
  6733. if (Prolog (&info))
  6734. {
  6735. switch (dwHookSwitchDev)
  6736. {
  6737. case PHONEHOOKSWITCHDEV_HANDSET:
  6738. *lpdwVolume = pPhone->dwHandsetVolume;
  6739. break;
  6740. case PHONEHOOKSWITCHDEV_SPEAKER:
  6741. *lpdwVolume = pPhone->dwSpeakerVolume;
  6742. break;
  6743. case PHONEHOOKSWITCHDEV_HEADSET:
  6744. *lpdwVolume = pPhone->dwHeadsetVolume;
  6745. break;
  6746. }
  6747. }
  6748. return (Epilog (&info));
  6749. }
  6750. LONG
  6751. TSPIAPI
  6752. TSPI_phoneNegotiateExtVersion(
  6753. DWORD dwDeviceID,
  6754. DWORD dwTSPIVersion,
  6755. DWORD dwLowVersion,
  6756. DWORD dwHighVersion,
  6757. LPDWORD lpdwExtVersion
  6758. )
  6759. {
  6760. static char szFuncName[] = "phoneNegotiateExtVersion";
  6761. FUNC_PARAM params[] =
  6762. {
  6763. { szdwDeviceID, dwDeviceID },
  6764. { "dwTSPIVersion", dwTSPIVersion },
  6765. { "dwLowVersion", dwLowVersion },
  6766. { "dwHighVersion", dwHighVersion },
  6767. { "lpdwExtVersion", lpdwExtVersion }
  6768. };
  6769. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  6770. if (Prolog (&info))
  6771. {
  6772. if (dwLowVersion == 0 ||
  6773. dwHighVersion == 0xffffffff ||
  6774. dwLowVersion > dwHighVersion)
  6775. {
  6776. info.lResult = PHONEERR_INCOMPATIBLEEXTVERSION;
  6777. }
  6778. else
  6779. {
  6780. *lpdwExtVersion = dwHighVersion;
  6781. }
  6782. }
  6783. return (Epilog (&info));
  6784. }
  6785. LONG
  6786. TSPIAPI
  6787. TSPI_phoneNegotiateTSPIVersion(
  6788. DWORD dwDeviceID,
  6789. DWORD dwLowVersion,
  6790. DWORD dwHighVersion,
  6791. LPDWORD lpdwTSPIVersion
  6792. )
  6793. {
  6794. static char szFuncName[] = "phoneNegotiateTSPIVersion";
  6795. FUNC_PARAM params[] =
  6796. {
  6797. { szdwDeviceID, dwDeviceID },
  6798. { "dwLowVersion", dwLowVersion },
  6799. { "dwHighVersion", dwHighVersion },
  6800. { "lpdwTSPIVersion", lpdwTSPIVersion }
  6801. };
  6802. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  6803. if (Prolog (&info))
  6804. {
  6805. *lpdwTSPIVersion = gESPGlobals.dwSPIVersion;
  6806. }
  6807. return (Epilog (&info));
  6808. }
  6809. LONG
  6810. TSPIAPI
  6811. TSPI_phoneOpen(
  6812. DWORD dwDeviceID,
  6813. HTAPIPHONE htPhone,
  6814. LPHDRVPHONE lphdPhone,
  6815. DWORD dwTSPIVersion,
  6816. PHONEEVENT lpfnEventProc
  6817. )
  6818. {
  6819. static char szFuncName[] = "phoneOpen";
  6820. FUNC_PARAM params[] =
  6821. {
  6822. { szdwDeviceID, dwDeviceID },
  6823. { "htPhone", htPhone },
  6824. { "lphdPhone", lphdPhone },
  6825. { "dwTSPIVersion", dwTSPIVersion },
  6826. { "lpfnEventProc", lpfnEventProc }
  6827. };
  6828. FUNC_INFO info = { szFuncName, SYNC, 5, params };
  6829. if (Prolog (&info))
  6830. {
  6831. PDRVPHONE pPhone;
  6832. if (pPhone = GetPhoneFromID (dwDeviceID))
  6833. {
  6834. pPhone->htPhone = htPhone;
  6835. *lphdPhone = (HDRVPHONE) pPhone;
  6836. WriteEventBuffer(
  6837. pPhone->dwDeviceID,
  6838. WIDGETTYPE_PHONE,
  6839. (ULONG_PTR) pPhone,
  6840. (ULONG_PTR) htPhone,
  6841. 0,
  6842. 0
  6843. );
  6844. }
  6845. else
  6846. {
  6847. info.lResult = PHONEERR_BADDEVICEID;
  6848. }
  6849. }
  6850. return (Epilog (&info));
  6851. }
  6852. LONG
  6853. TSPIAPI
  6854. TSPI_phoneSelectExtVersion(
  6855. HDRVPHONE hdPhone,
  6856. DWORD dwExtVersion
  6857. )
  6858. {
  6859. static char szFuncName[] = "phoneSelectExtVersion";
  6860. FUNC_PARAM params[] =
  6861. {
  6862. { szhdPhone, hdPhone },
  6863. { "dwExtVersion", dwExtVersion }
  6864. };
  6865. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  6866. if (Prolog (&info))
  6867. {
  6868. }
  6869. return (Epilog (&info));
  6870. }
  6871. void
  6872. FAR
  6873. PASCAL
  6874. TSPI_phoneSetButtonInfo_postProcess(
  6875. PASYNC_REQUEST_INFO pAsyncReqInfo,
  6876. BOOL bAsync
  6877. )
  6878. {
  6879. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  6880. LPPHONEBUTTONINFO pButtonInfo = (LPPHONEBUTTONINFO)
  6881. pAsyncReqInfo->dwParam2, pToFree;
  6882. DoCompletion (pAsyncReqInfo, bAsync);
  6883. if (pAsyncReqInfo->lResult == 0)
  6884. {
  6885. EnterCriticalSection (&gESPGlobals.PhoneCritSec);
  6886. pToFree = pPhone->pButtonInfo;
  6887. pPhone->pButtonInfo = pButtonInfo;
  6888. LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
  6889. DrvFree (pToFree);
  6890. // no msg to send for this one?
  6891. }
  6892. else
  6893. {
  6894. DrvFree (pButtonInfo);
  6895. }
  6896. }
  6897. LONG
  6898. TSPIAPI
  6899. TSPI_phoneSetButtonInfo(
  6900. DRV_REQUESTID dwRequestID,
  6901. HDRVPHONE hdPhone,
  6902. DWORD dwButtonLampID,
  6903. LPPHONEBUTTONINFO const lpButtonInfo
  6904. )
  6905. {
  6906. static char szFuncName[] = "phoneSetButtonInfo";
  6907. FUNC_PARAM params[] =
  6908. {
  6909. { szdwRequestID, dwRequestID },
  6910. { szhdPhone, hdPhone },
  6911. { "dwButtonLampID", dwButtonLampID },
  6912. { "lpButtonInfo", lpButtonInfo }
  6913. };
  6914. FUNC_INFO info =
  6915. {
  6916. szFuncName,
  6917. ASYNC,
  6918. 4,
  6919. params,
  6920. TSPI_phoneSetButtonInfo_postProcess
  6921. };
  6922. if (Prolog (&info))
  6923. {
  6924. if (dwButtonLampID == 0)
  6925. {
  6926. DWORD dwNeededSize;
  6927. LPPHONEBUTTONINFO pMyButtonInfo;
  6928. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  6929. dwNeededSize = sizeof (PHONEBUTTONINFO) +
  6930. lpButtonInfo->dwButtonTextSize +
  6931. lpButtonInfo->dwDevSpecificSize +
  6932. 16; // 64-bit align var fields
  6933. if ((pMyButtonInfo = (LPPHONEBUTTONINFO) DrvAlloc (dwNeededSize)))
  6934. {
  6935. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) pMyButtonInfo;
  6936. CopyMemory(
  6937. pMyButtonInfo,
  6938. lpButtonInfo,
  6939. (gESPGlobals.dwSPIVersion > 0x00010003 ?
  6940. sizeof (PHONEBUTTONINFO) : 9 * sizeof (DWORD))
  6941. );
  6942. pMyButtonInfo->dwTotalSize = dwNeededSize;
  6943. pMyButtonInfo->dwNeededSize =
  6944. pMyButtonInfo->dwUsedSize = sizeof (PHONEBUTTONINFO);
  6945. InsertVarData(
  6946. pMyButtonInfo,
  6947. &pMyButtonInfo->dwButtonTextSize,
  6948. ((LPBYTE) lpButtonInfo) +
  6949. lpButtonInfo->dwButtonTextOffset,
  6950. lpButtonInfo->dwButtonTextSize
  6951. );
  6952. InsertVarData(
  6953. pMyButtonInfo,
  6954. &pMyButtonInfo->dwDevSpecificSize,
  6955. ((LPBYTE) lpButtonInfo) +
  6956. lpButtonInfo->dwDevSpecificOffset,
  6957. lpButtonInfo->dwDevSpecificSize
  6958. );
  6959. }
  6960. else
  6961. {
  6962. info.lResult = PHONEERR_NOMEM;
  6963. }
  6964. }
  6965. else
  6966. {
  6967. info.lResult = PHONEERR_INVALBUTTONLAMPID;
  6968. }
  6969. }
  6970. return (Epilog (&info));
  6971. }
  6972. void
  6973. FAR
  6974. PASCAL
  6975. TSPI_phoneSetData_postProcess(
  6976. PASYNC_REQUEST_INFO pAsyncReqInfo,
  6977. BOOL bAsync
  6978. )
  6979. {
  6980. DWORD dwNewDataSize = (DWORD) pAsyncReqInfo->dwParam3;
  6981. LPVOID pNewData = (LPVOID) pAsyncReqInfo->dwParam2, pToFree;
  6982. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  6983. DoCompletion (pAsyncReqInfo, bAsync);
  6984. if (pAsyncReqInfo->lResult == 0)
  6985. {
  6986. EnterCriticalSection (&gESPGlobals.PhoneCritSec);
  6987. pToFree = pPhone->pData;
  6988. pPhone->pData = pNewData;
  6989. pPhone->dwDataSize = dwNewDataSize;
  6990. LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
  6991. DrvFree (pToFree);
  6992. // no msg to send for this one?
  6993. }
  6994. else
  6995. {
  6996. DrvFree (pNewData);
  6997. }
  6998. }
  6999. LONG
  7000. TSPIAPI
  7001. TSPI_phoneSetData(
  7002. DRV_REQUESTID dwRequestID,
  7003. HDRVPHONE hdPhone,
  7004. DWORD dwDataID,
  7005. LPVOID const lpData,
  7006. DWORD dwSize
  7007. )
  7008. {
  7009. static char szFuncName[] = "phoneSetData";
  7010. FUNC_PARAM params[] =
  7011. {
  7012. { szdwRequestID, dwRequestID },
  7013. { szhdPhone, hdPhone },
  7014. { "dwDataID", dwDataID },
  7015. { "lpData", lpData },
  7016. { szdwSize, dwSize }
  7017. };
  7018. FUNC_INFO info =
  7019. {
  7020. szFuncName,
  7021. ASYNC,
  7022. 5,
  7023. params,
  7024. TSPI_phoneSetData_postProcess
  7025. };
  7026. if (Prolog (&info))
  7027. {
  7028. if (dwDataID != 0)
  7029. {
  7030. info.lResult = PHONEERR_INVALDATAID;
  7031. }
  7032. else
  7033. {
  7034. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7035. if (dwSize)
  7036. {
  7037. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) DrvAlloc (dwSize);
  7038. if (info.pAsyncReqInfo->dwParam2 == 0)
  7039. {
  7040. info.lResult = PHONEERR_NOMEM;
  7041. return (Epilog (&info));
  7042. }
  7043. CopyMemory(
  7044. (LPVOID) info.pAsyncReqInfo->dwParam2,
  7045. lpData,
  7046. dwSize
  7047. );
  7048. }
  7049. else
  7050. {
  7051. info.pAsyncReqInfo->dwParam2 = 0;
  7052. }
  7053. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwSize;
  7054. }
  7055. }
  7056. return (Epilog (&info));
  7057. }
  7058. void
  7059. FAR
  7060. PASCAL
  7061. TSPI_phoneSetDisplay_postProcess(
  7062. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7063. BOOL bAsync
  7064. )
  7065. {
  7066. DWORD dwColumn = (DWORD) pAsyncReqInfo->dwParam2,
  7067. dwSize = (DWORD) pAsyncReqInfo->dwParam4;
  7068. WCHAR *pDisplay = (LPVOID) pAsyncReqInfo->dwParam3;
  7069. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7070. if (pAsyncReqInfo->lResult == 0)
  7071. {
  7072. EnterCriticalSection (&gESPGlobals.PhoneCritSec);
  7073. if (pPhone->pDisplay ||
  7074. (pPhone->pDisplay = DrvAlloc (PHONE_DISPLAY_SIZE_IN_BYTES)))
  7075. {
  7076. CopyMemory(
  7077. pPhone->pDisplay + dwColumn,
  7078. pDisplay,
  7079. dwSize
  7080. );
  7081. SendPhoneEvent (pPhone, PHONE_STATE, PHONESTATE_DISPLAY, 0, 0);
  7082. }
  7083. else
  7084. {
  7085. pAsyncReqInfo->lResult = PHONEERR_NOMEM;
  7086. }
  7087. LeaveCriticalSection (&gESPGlobals.PhoneCritSec);
  7088. }
  7089. DoCompletion (pAsyncReqInfo, bAsync);
  7090. DrvFree (pDisplay);
  7091. }
  7092. LONG
  7093. TSPIAPI
  7094. TSPI_phoneSetDisplay(
  7095. DRV_REQUESTID dwRequestID,
  7096. HDRVPHONE hdPhone,
  7097. DWORD dwRow,
  7098. DWORD dwColumn,
  7099. LPCWSTR lpsDisplay,
  7100. DWORD dwSize
  7101. )
  7102. {
  7103. static char szFuncName[] = "phoneSetDisplay";
  7104. FUNC_PARAM params[] =
  7105. {
  7106. { szdwRequestID, dwRequestID },
  7107. { szhdPhone, hdPhone },
  7108. { "dwRow", dwRow },
  7109. { "dwColumn", dwColumn },
  7110. { "lpsDisplay", lpsDisplay },
  7111. { szdwSize, dwSize }
  7112. };
  7113. FUNC_INFO info =
  7114. {
  7115. szFuncName,
  7116. ASYNC,
  7117. 6,
  7118. params,
  7119. TSPI_phoneSetDisplay_postProcess
  7120. };
  7121. if (Prolog (&info))
  7122. {
  7123. if (dwRow == 0 &&
  7124. dwColumn < PHONE_DISPLAY_SIZE_IN_CHARS &&
  7125. dwSize <= PHONE_DISPLAY_SIZE_IN_BYTES &&
  7126. (dwColumn * sizeof (WCHAR) + dwSize - sizeof (WCHAR)) <
  7127. PHONE_DISPLAY_SIZE_IN_BYTES)
  7128. {
  7129. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7130. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwColumn;
  7131. if (dwSize)
  7132. {
  7133. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) DrvAlloc (dwSize);
  7134. if (info.pAsyncReqInfo->dwParam3 == 0)
  7135. {
  7136. info.lResult = PHONEERR_NOMEM;
  7137. return (Epilog (&info));
  7138. }
  7139. CopyMemory(
  7140. (LPVOID) info.pAsyncReqInfo->dwParam3,
  7141. lpsDisplay,
  7142. dwSize
  7143. );
  7144. }
  7145. else
  7146. {
  7147. info.pAsyncReqInfo->dwParam3 = 0;
  7148. }
  7149. info.pAsyncReqInfo->dwParam4 = (ULONG_PTR) dwSize;
  7150. }
  7151. else
  7152. {
  7153. info.lResult = PHONEERR_INVALPARAM;
  7154. }
  7155. }
  7156. return (Epilog (&info));
  7157. }
  7158. void
  7159. FAR
  7160. PASCAL
  7161. TSPI_phoneSetGain_postProcess(
  7162. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7163. BOOL bAsync
  7164. )
  7165. {
  7166. DoCompletion (pAsyncReqInfo, bAsync);
  7167. if (pAsyncReqInfo->lResult == 0)
  7168. {
  7169. DWORD dwHookSwitchDev = (DWORD) pAsyncReqInfo->dwParam2,
  7170. dwGain = (DWORD) pAsyncReqInfo->dwParam3,
  7171. *pdwXxxGain, dwPhoneState;
  7172. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7173. switch (dwHookSwitchDev)
  7174. {
  7175. case PHONEHOOKSWITCHDEV_HANDSET:
  7176. pdwXxxGain = &pPhone->dwHandsetGain;
  7177. dwPhoneState = PHONESTATE_HANDSETGAIN;
  7178. break;
  7179. case PHONEHOOKSWITCHDEV_SPEAKER:
  7180. pdwXxxGain = &pPhone->dwSpeakerGain;
  7181. dwPhoneState = PHONESTATE_SPEAKERGAIN;
  7182. break;
  7183. default: // case PHONEHOOKSWITCHDEV_HEADSET:
  7184. pdwXxxGain = &pPhone->dwHeadsetGain;
  7185. dwPhoneState = PHONESTATE_HEADSETGAIN;
  7186. break;
  7187. }
  7188. if (*pdwXxxGain != dwGain)
  7189. {
  7190. *pdwXxxGain = dwGain;
  7191. SendPhoneEvent (pPhone, PHONE_STATE, dwPhoneState, 0, 0);
  7192. }
  7193. }
  7194. }
  7195. LONG
  7196. TSPIAPI
  7197. TSPI_phoneSetGain(
  7198. DRV_REQUESTID dwRequestID,
  7199. HDRVPHONE hdPhone,
  7200. DWORD dwHookSwitchDev,
  7201. DWORD dwGain
  7202. )
  7203. {
  7204. static char szFuncName[] = "phoneSetGain";
  7205. FUNC_PARAM params[] =
  7206. {
  7207. { szdwRequestID, dwRequestID },
  7208. { szhdPhone, hdPhone },
  7209. { "dwHookSwitchDev", dwHookSwitchDev, aHookSwitchDevs },
  7210. { "dwGain", dwGain }
  7211. };
  7212. FUNC_INFO info =
  7213. {
  7214. szFuncName,
  7215. ASYNC,
  7216. 4,
  7217. params,
  7218. TSPI_phoneSetGain_postProcess
  7219. };
  7220. if (Prolog (&info))
  7221. {
  7222. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7223. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwHookSwitchDev;
  7224. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwGain;
  7225. }
  7226. return (Epilog (&info));
  7227. }
  7228. void
  7229. FAR
  7230. PASCAL
  7231. TSPI_phoneSetHookSwitch_postProcess(
  7232. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7233. BOOL bAsync
  7234. )
  7235. {
  7236. DoCompletion (pAsyncReqInfo, bAsync);
  7237. if (pAsyncReqInfo->lResult == 0)
  7238. {
  7239. DWORD dwHookSwitchDevs = (DWORD) pAsyncReqInfo->dwParam2,
  7240. dwHookSwitchMode = (DWORD) pAsyncReqInfo->dwParam3,
  7241. dwPhoneStates = 0;
  7242. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7243. if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HANDSET &&
  7244. pPhone->dwHandsetHookSwitchMode != dwHookSwitchMode)
  7245. {
  7246. pPhone->dwHandsetHookSwitchMode = dwHookSwitchMode;
  7247. dwPhoneStates |= PHONESTATE_HANDSETHOOKSWITCH;
  7248. }
  7249. if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_SPEAKER &&
  7250. pPhone->dwSpeakerHookSwitchMode != dwHookSwitchMode)
  7251. {
  7252. pPhone->dwSpeakerHookSwitchMode = dwHookSwitchMode;
  7253. dwPhoneStates |= PHONESTATE_SPEAKERHOOKSWITCH;
  7254. }
  7255. if (dwHookSwitchDevs & PHONEHOOKSWITCHDEV_HEADSET &&
  7256. pPhone->dwHeadsetHookSwitchMode != dwHookSwitchMode)
  7257. {
  7258. pPhone->dwHeadsetHookSwitchMode = dwHookSwitchMode;
  7259. dwPhoneStates |= PHONESTATE_HEADSETHOOKSWITCH;
  7260. }
  7261. if (dwPhoneStates)
  7262. {
  7263. SendPhoneEvent(
  7264. pPhone,
  7265. PHONE_STATE,
  7266. dwPhoneStates,
  7267. dwHookSwitchMode,
  7268. 0
  7269. );
  7270. }
  7271. }
  7272. }
  7273. LONG
  7274. TSPIAPI
  7275. TSPI_phoneSetHookSwitch(
  7276. DRV_REQUESTID dwRequestID,
  7277. HDRVPHONE hdPhone,
  7278. DWORD dwHookSwitchDevs,
  7279. DWORD dwHookSwitchMode
  7280. )
  7281. {
  7282. static char szFuncName[] = "phoneSetHookSwitch";
  7283. FUNC_PARAM params[] =
  7284. {
  7285. { szdwRequestID, dwRequestID },
  7286. { szhdPhone, hdPhone },
  7287. { "dwHookSwitchDevs", dwHookSwitchDevs, aHookSwitchDevs },
  7288. { "dwHookSwitchMode", dwHookSwitchMode, aHookSwitchModes }
  7289. };
  7290. FUNC_INFO info =
  7291. {
  7292. szFuncName,
  7293. ASYNC,
  7294. 4,
  7295. params,
  7296. TSPI_phoneSetHookSwitch_postProcess
  7297. };
  7298. if (Prolog (&info))
  7299. {
  7300. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7301. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwHookSwitchDevs;
  7302. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwHookSwitchMode;
  7303. }
  7304. return (Epilog (&info));
  7305. }
  7306. void
  7307. FAR
  7308. PASCAL
  7309. TSPI_phoneSetLamp_postProcess(
  7310. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7311. BOOL bAsync
  7312. )
  7313. {
  7314. DoCompletion (pAsyncReqInfo, bAsync);
  7315. if (pAsyncReqInfo->lResult == 0)
  7316. {
  7317. DWORD dwLampMode = (DWORD) pAsyncReqInfo->dwParam2;
  7318. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7319. if (pPhone->dwLampMode != dwLampMode)
  7320. {
  7321. pPhone->dwLampMode = dwLampMode;
  7322. SendPhoneEvent (pPhone, PHONE_STATE, PHONESTATE_LAMP, 0, 0);
  7323. }
  7324. }
  7325. }
  7326. LONG
  7327. TSPIAPI
  7328. TSPI_phoneSetLamp(
  7329. DRV_REQUESTID dwRequestID,
  7330. HDRVPHONE hdPhone,
  7331. DWORD dwButtonLampID,
  7332. DWORD dwLampMode
  7333. )
  7334. {
  7335. static char szFuncName[] = "phoneSetLamp";
  7336. FUNC_PARAM params[] =
  7337. {
  7338. { szdwRequestID, dwRequestID },
  7339. { szhdPhone, hdPhone },
  7340. { "dwButtonLampID", dwButtonLampID },
  7341. { "dwLampMode", dwLampMode, aLampModes }
  7342. };
  7343. FUNC_INFO info =
  7344. {
  7345. szFuncName,
  7346. ASYNC,
  7347. 4,
  7348. params,
  7349. TSPI_phoneSetLamp_postProcess
  7350. };
  7351. if (Prolog (&info))
  7352. {
  7353. if (dwButtonLampID == 0)
  7354. {
  7355. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7356. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwLampMode;
  7357. }
  7358. else
  7359. {
  7360. info.lResult = PHONEERR_INVALBUTTONLAMPID;
  7361. }
  7362. }
  7363. return (Epilog (&info));
  7364. }
  7365. void
  7366. FAR
  7367. PASCAL
  7368. TSPI_phoneSetRing_postProcess(
  7369. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7370. BOOL bAsync
  7371. )
  7372. {
  7373. DoCompletion (pAsyncReqInfo, bAsync);
  7374. if (pAsyncReqInfo->lResult == 0)
  7375. {
  7376. DWORD dwRingMode = (DWORD) pAsyncReqInfo->dwParam2,
  7377. dwRingVolume = (DWORD) pAsyncReqInfo->dwParam3,
  7378. dwPhoneStates = 0;
  7379. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7380. if (pPhone->dwRingMode != dwRingMode)
  7381. {
  7382. pPhone->dwRingMode = dwRingMode;
  7383. dwPhoneStates |= PHONESTATE_RINGMODE;
  7384. }
  7385. if (pPhone->dwRingVolume != dwRingVolume)
  7386. {
  7387. pPhone->dwRingVolume = dwRingVolume;
  7388. dwPhoneStates |= PHONESTATE_RINGVOLUME;
  7389. }
  7390. if (dwPhoneStates)
  7391. {
  7392. SendPhoneEvent(
  7393. pPhone,
  7394. PHONE_STATE,
  7395. dwPhoneStates,
  7396. (dwPhoneStates & PHONESTATE_RINGMODE) ? dwRingMode : 0,
  7397. 0
  7398. );
  7399. }
  7400. }
  7401. }
  7402. LONG
  7403. TSPIAPI
  7404. TSPI_phoneSetRing(
  7405. DRV_REQUESTID dwRequestID,
  7406. HDRVPHONE hdPhone,
  7407. DWORD dwRingMode,
  7408. DWORD dwVolume
  7409. )
  7410. {
  7411. static char szFuncName[] = "phoneSetRing";
  7412. FUNC_PARAM params[] =
  7413. {
  7414. { szdwRequestID, dwRequestID },
  7415. { szhdPhone, hdPhone },
  7416. { "dwRingMode", dwRingMode },
  7417. { "dwVolume", dwVolume }
  7418. };
  7419. FUNC_INFO info =
  7420. {
  7421. szFuncName,
  7422. ASYNC,
  7423. 4,
  7424. params,
  7425. TSPI_phoneSetRing_postProcess
  7426. };
  7427. if (Prolog (&info))
  7428. {
  7429. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7430. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwRingMode;
  7431. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwVolume;
  7432. }
  7433. return (Epilog (&info));
  7434. }
  7435. LONG
  7436. TSPIAPI
  7437. TSPI_phoneSetStatusMessages(
  7438. HDRVPHONE hdPhone,
  7439. DWORD dwPhoneStates,
  7440. DWORD dwButtonModes,
  7441. DWORD dwButtonStates
  7442. )
  7443. {
  7444. static char szFuncName[] = "phoneSetStatusMessages";
  7445. FUNC_PARAM params[] =
  7446. {
  7447. { szhdPhone, hdPhone },
  7448. { "dwPhoneStates", dwPhoneStates, aPhoneStates },
  7449. { "dwButtonModes", dwButtonModes, aButtonModes },
  7450. { "dwButtonStates", dwButtonStates, aButtonStates }
  7451. };
  7452. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  7453. if (Prolog (&info))
  7454. {
  7455. }
  7456. return (Epilog (&info));
  7457. }
  7458. void
  7459. FAR
  7460. PASCAL
  7461. TSPI_phoneSetVolume_postProcess(
  7462. PASYNC_REQUEST_INFO pAsyncReqInfo,
  7463. BOOL bAsync
  7464. )
  7465. {
  7466. DoCompletion (pAsyncReqInfo, bAsync);
  7467. if (pAsyncReqInfo->lResult == 0)
  7468. {
  7469. DWORD dwHookSwitchDev = (DWORD) pAsyncReqInfo->dwParam2,
  7470. dwVolume = (DWORD) pAsyncReqInfo->dwParam3,
  7471. *pdwXxxVolume, dwPhoneState;
  7472. PDRVPHONE pPhone = (PDRVPHONE) pAsyncReqInfo->dwParam1;
  7473. switch (dwHookSwitchDev)
  7474. {
  7475. case PHONEHOOKSWITCHDEV_HANDSET:
  7476. pdwXxxVolume = &pPhone->dwHandsetVolume;
  7477. dwPhoneState = PHONESTATE_HANDSETVOLUME;
  7478. break;
  7479. case PHONEHOOKSWITCHDEV_SPEAKER:
  7480. pdwXxxVolume = &pPhone->dwSpeakerVolume;
  7481. dwPhoneState = PHONESTATE_SPEAKERVOLUME;
  7482. break;
  7483. default: // case PHONEHOOKSWITCHDEV_HEADSET:
  7484. pdwXxxVolume = &pPhone->dwHeadsetVolume;
  7485. dwPhoneState = PHONESTATE_HEADSETVOLUME;
  7486. break;
  7487. }
  7488. if (*pdwXxxVolume != dwVolume)
  7489. {
  7490. *pdwXxxVolume = dwVolume;
  7491. SendPhoneEvent (pPhone, PHONE_STATE, dwPhoneState, 0, 0);
  7492. }
  7493. }
  7494. }
  7495. LONG
  7496. TSPIAPI
  7497. TSPI_phoneSetVolume(
  7498. DRV_REQUESTID dwRequestID,
  7499. HDRVPHONE hdPhone,
  7500. DWORD dwHookSwitchDev,
  7501. DWORD dwVolume
  7502. )
  7503. {
  7504. static char szFuncName[] = "phoneSetVolume";
  7505. FUNC_PARAM params[] =
  7506. {
  7507. { szdwRequestID, dwRequestID },
  7508. { szhdPhone, hdPhone },
  7509. { "dwHookSwitchDev", dwHookSwitchDev }, // BUGBUG lookup
  7510. { "dwVolume", dwVolume }
  7511. };
  7512. FUNC_INFO info =
  7513. {
  7514. szFuncName,
  7515. ASYNC,
  7516. 4,
  7517. params,
  7518. TSPI_phoneSetVolume_postProcess
  7519. };
  7520. if (Prolog (&info))
  7521. {
  7522. info.pAsyncReqInfo->dwParam1 = (ULONG_PTR) hdPhone;
  7523. info.pAsyncReqInfo->dwParam2 = (ULONG_PTR) dwHookSwitchDev;
  7524. info.pAsyncReqInfo->dwParam3 = (ULONG_PTR) dwVolume;
  7525. }
  7526. return (Epilog (&info));
  7527. }
  7528. //
  7529. // ------------------------- TSPI_providerXxx funcs ---------------------------
  7530. //
  7531. LONG
  7532. TSPIAPI
  7533. TSPI_providerConfig(
  7534. HWND hwndOwner,
  7535. DWORD dwPermanentProviderID
  7536. )
  7537. {
  7538. //
  7539. // 32-bit TAPI never actually calls this function (the corresponding
  7540. // TUISPI_ func has taken it's place), but the Telephony control
  7541. // panel applet does look to see if this function is exported to
  7542. // determine whether or not the provider is configurable
  7543. //
  7544. return 0;
  7545. }
  7546. LONG
  7547. TSPIAPI
  7548. TSPI_providerCreateLineDevice(
  7549. ULONG_PTR dwTempID,
  7550. DWORD dwDeviceID
  7551. )
  7552. {
  7553. static char szFuncName[] = "providerCreateLineDevice";
  7554. FUNC_PARAM params[] =
  7555. {
  7556. { "dwTempID", dwTempID },
  7557. { szdwDeviceID, dwDeviceID }
  7558. };
  7559. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  7560. if (Prolog (&info))
  7561. {
  7562. PDRVLINE pLine = (PDRVLINE) (((LPBYTE) gESPGlobals.pLines->aLines) +
  7563. (dwTempID * gdwDrvLineSize));
  7564. pLine->dwDeviceID = dwDeviceID;
  7565. WriteEventBuffer (pLine->dwDeviceID, WIDGETTYPE_LINE, 0, 0, 0, 0);
  7566. }
  7567. return (Epilog (&info));
  7568. }
  7569. LONG
  7570. TSPIAPI
  7571. TSPI_providerCreatePhoneDevice(
  7572. ULONG_PTR dwTempID,
  7573. DWORD dwDeviceID
  7574. )
  7575. {
  7576. static char szFuncName[] = "providerCreatePhoneDevice";
  7577. FUNC_PARAM params[] =
  7578. {
  7579. { "dwTempID", dwTempID },
  7580. { szdwDeviceID, dwDeviceID }
  7581. };
  7582. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  7583. if (Prolog (&info))
  7584. {
  7585. PDRVPHONE pPhone = gESPGlobals.pPhones->aPhones + dwTempID;
  7586. pPhone->dwDeviceID = dwDeviceID;
  7587. WriteEventBuffer (pPhone->dwDeviceID, WIDGETTYPE_PHONE, 0, 0, 0, 0);
  7588. }
  7589. return (Epilog (&info));
  7590. }
  7591. LONG
  7592. TSPIAPI
  7593. TSPI_providerEnumDevices(
  7594. DWORD dwPermanentProviderID,
  7595. LPDWORD lpdwNumLines,
  7596. LPDWORD lpdwNumPhones,
  7597. HPROVIDER hProvider,
  7598. LINEEVENT lpfnLineCreateProc,
  7599. PHONEEVENT lpfnPhoneCreateProc
  7600. )
  7601. {
  7602. static char szFuncName[] = "providerEnumDevices";
  7603. FUNC_PARAM params[] =
  7604. {
  7605. { szdwPermanentProviderID, dwPermanentProviderID },
  7606. { "lpdwNumLines", lpdwNumLines },
  7607. { "lpdwNumPhones", lpdwNumPhones },
  7608. { "hProvider", hProvider },
  7609. { "lpfnLineCreateProc", lpfnLineCreateProc },
  7610. { "lpfnPhoneCreateProc", lpfnPhoneCreateProc }
  7611. };
  7612. FUNC_INFO info = { szFuncName, SYNC, 6, params };
  7613. if (Prolog (&info))
  7614. {
  7615. *lpdwNumLines = gESPGlobals.dwNumLines;
  7616. *lpdwNumPhones = gESPGlobals.dwNumPhones;
  7617. gESPGlobals.pfnLineEvent = lpfnLineCreateProc;
  7618. gESPGlobals.pfnPhoneEvent = lpfnPhoneCreateProc;
  7619. gESPGlobals.hProvider = hProvider;
  7620. }
  7621. return (Epilog (&info));
  7622. }
  7623. LONG
  7624. TSPIAPI
  7625. TSPI_providerFreeDialogInstance(
  7626. HDRVDIALOGINSTANCE hdDlgInst
  7627. )
  7628. {
  7629. static char szFuncName[] = "providerFreeDialogInstance";
  7630. FUNC_PARAM params[] =
  7631. {
  7632. { "hdDlgInst", hdDlgInst }
  7633. };
  7634. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  7635. Prolog (&info);
  7636. return (Epilog (&info));
  7637. }
  7638. LONG
  7639. TSPIAPI
  7640. TSPI_providerGenericDialogData(
  7641. ULONG_PTR dwObjectID,
  7642. DWORD dwObjectType,
  7643. LPVOID lpParams,
  7644. DWORD dwSize
  7645. )
  7646. {
  7647. static char szFuncName[] = "providerGenericDialogData";
  7648. FUNC_PARAM params[] =
  7649. {
  7650. { "dwObjectID", dwObjectID },
  7651. { "dwObjectType", dwObjectType },
  7652. { "lpszParams", lpParams },
  7653. { "dwSize", dwSize }
  7654. };
  7655. FUNC_INFO info = { szFuncName, SYNC, 4, params };
  7656. Prolog (&info);
  7657. lstrcpyA (lpParams, "espDlgData");
  7658. return (Epilog (&info));
  7659. }
  7660. LONG
  7661. TSPIAPI
  7662. TSPI_providerInit(
  7663. DWORD dwTSPIVersion,
  7664. DWORD dwPermanentProviderID,
  7665. DWORD dwLineDeviceIDBase,
  7666. DWORD dwPhoneDeviceIDBase,
  7667. DWORD_PTR dwNumLines,
  7668. DWORD_PTR dwNumPhones,
  7669. ASYNC_COMPLETION lpfnCompletionProc,
  7670. LPDWORD lpdwTSPIOptions
  7671. )
  7672. {
  7673. static char szFuncName[] = "providerInit";
  7674. FUNC_PARAM params[] =
  7675. {
  7676. { "dwTSPIVersion", dwTSPIVersion },
  7677. { szdwPermanentProviderID, dwPermanentProviderID },
  7678. { "dwLineDeviceIDBase", dwLineDeviceIDBase },
  7679. { "dwPhoneDeviceIDBase", dwPhoneDeviceIDBase },
  7680. { "dwNumLines", dwNumLines },
  7681. { "dwNumPhones", dwNumPhones },
  7682. { "lpfnCompletionProc", lpfnCompletionProc }
  7683. };
  7684. FUNC_INFO info = { szFuncName, SYNC, 7, params };
  7685. DWORD i, dwNumTotalEntries;
  7686. PDRVLINE pLine;
  7687. PDRVPHONE pPhone;
  7688. if (!Prolog (&info))
  7689. {
  7690. return (Epilog (&info));
  7691. }
  7692. //
  7693. //
  7694. //
  7695. // BUGBUG zero out he approp gESPGlobals stuff
  7696. gESPGlobals.bProviderShutdown = FALSE;
  7697. ZeroMemory (gaParkedCalls, MAX_NUM_PARKED_CALLS * sizeof (PDRVCALL));
  7698. //
  7699. // Alloc a queue for storing async requests for async completion,
  7700. // and start a thread to service that queue
  7701. //
  7702. // if (gbDisableUI == FALSE) IF THIS IS UNCOMMENTED MUST MUNGE ERROR CLEANUP
  7703. {
  7704. gESPGlobals.dwNumTotalQueueEntries = DEF_NUM_ASYNC_REQUESTS_IN_QUEUE;
  7705. if (!(gESPGlobals.pAsyncRequestQueue = DrvAlloc(
  7706. gESPGlobals.dwNumTotalQueueEntries * sizeof (DWORD)
  7707. )))
  7708. {
  7709. goto TSPI_providerInit_error0;
  7710. }
  7711. gESPGlobals.pAsyncRequestQueueIn =
  7712. gESPGlobals.pAsyncRequestQueueOut = gESPGlobals.pAsyncRequestQueue;
  7713. if (!(gESPGlobals.hAsyncEventsPendingEvent = CreateEvent(
  7714. (LPSECURITY_ATTRIBUTES) NULL,
  7715. TRUE, // manual reset
  7716. FALSE, // non-signaled
  7717. NULL // unnamed
  7718. )))
  7719. {
  7720. goto TSPI_providerInit_error1;
  7721. }
  7722. if (!(gESPGlobals.hAsyncEventQueueServiceThread = CreateThread(
  7723. (LPSECURITY_ATTRIBUTES) NULL,
  7724. 0, // def stack size
  7725. (LPTHREAD_START_ROUTINE) AsyncEventQueueServiceThread,
  7726. NULL, // thread param
  7727. 0, // creation flags
  7728. &i // &dwThreadID
  7729. )))
  7730. {
  7731. goto TSPI_providerInit_error2;
  7732. }
  7733. }
  7734. //
  7735. // Init sundry globals
  7736. //
  7737. gESPGlobals.dwPermanentProviderID = dwPermanentProviderID;
  7738. gESPGlobals.dwLineDeviceIDBase = dwLineDeviceIDBase;
  7739. gESPGlobals.dwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
  7740. gESPGlobals.dwInitialNumLines = (DWORD)dwNumLines;
  7741. gESPGlobals.dwInitialNumPhones = (DWORD)dwNumPhones;
  7742. gESPGlobals.pfnCompletion = lpfnCompletionProc;
  7743. gESPGlobals.hIconLine = LoadIcon(
  7744. ghInstance,
  7745. (LPCSTR)MAKEINTRESOURCE(PHONE_ICON) // the id's are reversed
  7746. );
  7747. gESPGlobals.hIconPhone = LoadIcon(
  7748. ghInstance,
  7749. (LPCSTR)MAKEINTRESOURCE(LINE_ICON)
  7750. );
  7751. //
  7752. // Init the line lookup table & crit sec for accessing call lists
  7753. //
  7754. dwNumTotalEntries = (DWORD)dwNumLines + DEF_NUM_EXTRA_LOOKUP_ENTRIES;
  7755. gdwDrvLineSize = sizeof (DRVLINE) +
  7756. ((gESPGlobals.dwNumAddressesPerLine - 1) * sizeof (DRVADDRESS));
  7757. if (!(gESPGlobals.pLines = DrvAlloc(
  7758. sizeof (DRVLINETABLE) +
  7759. (dwNumTotalEntries * gdwDrvLineSize)
  7760. )))
  7761. {
  7762. goto TSPI_providerInit_error3;
  7763. }
  7764. gESPGlobals.pLines->dwNumTotalEntries = dwNumTotalEntries;
  7765. gESPGlobals.pLines->dwNumUsedEntries = (DWORD)dwNumLines;
  7766. for (
  7767. i = dwLineDeviceIDBase, pLine = gESPGlobals.pLines->aLines;
  7768. i < (dwLineDeviceIDBase + dwNumTotalEntries);
  7769. i++
  7770. )
  7771. {
  7772. pLine->dwDeviceID =
  7773. (i < (dwLineDeviceIDBase + dwNumLines) ? i : 0xffffffff);
  7774. pLine = (PDRVLINE) (((LPBYTE) pLine) + gdwDrvLineSize);
  7775. }
  7776. //
  7777. // Init the phone lookup table
  7778. //
  7779. dwNumTotalEntries = (DWORD)dwNumPhones + DEF_NUM_EXTRA_LOOKUP_ENTRIES;
  7780. if (!(gESPGlobals.pPhones = DrvAlloc(
  7781. sizeof (DRVPHONETABLE) + dwNumTotalEntries * sizeof(DRVPHONE)
  7782. )))
  7783. {
  7784. goto TSPI_providerInit_error4;
  7785. }
  7786. gESPGlobals.pPhones->dwNumTotalEntries = dwNumTotalEntries;
  7787. gESPGlobals.pPhones->dwNumUsedEntries = (DWORD)dwNumPhones;
  7788. for (
  7789. i = dwPhoneDeviceIDBase, pPhone = gESPGlobals.pPhones->aPhones;
  7790. i < (dwPhoneDeviceIDBase + dwNumTotalEntries);
  7791. i++, pPhone++
  7792. )
  7793. {
  7794. pPhone->dwDeviceID =
  7795. (i < (dwPhoneDeviceIDBase + dwNumPhones) ? i : 0xffffffff);
  7796. }
  7797. if (gbDisableUI == FALSE)
  7798. {
  7799. WriteEventBuffer(
  7800. 0,
  7801. WIDGETTYPE_STARTUP,
  7802. dwNumLines,
  7803. dwNumPhones,
  7804. dwLineDeviceIDBase,
  7805. dwPhoneDeviceIDBase
  7806. );
  7807. }
  7808. goto TSPI_providerInit_return;
  7809. TSPI_providerInit_error4:
  7810. DrvFree (gESPGlobals.pLines);
  7811. TSPI_providerInit_error3:
  7812. gESPGlobals.bProviderShutdown = TRUE;
  7813. if (gESPGlobals.hAsyncEventQueueServiceThread)
  7814. {
  7815. // wait for the thread to terminate
  7816. while (WaitForSingleObject(
  7817. gESPGlobals.hAsyncEventQueueServiceThread,
  7818. 0
  7819. ) != WAIT_OBJECT_0)
  7820. {
  7821. SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
  7822. Sleep (0);
  7823. }
  7824. CloseHandle (gESPGlobals.hAsyncEventQueueServiceThread);
  7825. gESPGlobals.hAsyncEventQueueServiceThread = 0;
  7826. }
  7827. TSPI_providerInit_error2:
  7828. CloseHandle (gESPGlobals.hAsyncEventsPendingEvent);
  7829. gESPGlobals.hAsyncEventsPendingEvent = 0;
  7830. TSPI_providerInit_error1:
  7831. DrvFree (gESPGlobals.pAsyncRequestQueue);
  7832. TSPI_providerInit_error0:
  7833. info.lResult = LINEERR_NOMEM;
  7834. TSPI_providerInit_return:
  7835. return (Epilog (&info)); // BUGBUG TSPI_providerInit: return 0 by default
  7836. }
  7837. LONG
  7838. TSPIAPI
  7839. TSPI_providerInstall(
  7840. HWND hwndOwner,
  7841. DWORD dwPermanentProviderID
  7842. )
  7843. {
  7844. //
  7845. // 32-bit TAPI never actually calls this function (the corresponding
  7846. // TUISPI_ func has taken it's place), but the Telephony control
  7847. // panel applet does look to see if this function is exported to
  7848. // determine whether or not the provider is installable
  7849. //
  7850. return 0;
  7851. }
  7852. LONG
  7853. TSPIAPI
  7854. TSPI_providerRemove(
  7855. HWND hwndOwner,
  7856. DWORD dwPermanentProviderID
  7857. )
  7858. {
  7859. //
  7860. // 32-bit TAPI never actually calls this function (the corresponding
  7861. // TUISPI_ func has taken it's place), but the Telephony control
  7862. // panel applet does look to see if this function is exported to
  7863. // determine whether or not the provider is removeable
  7864. //
  7865. return 0;
  7866. }
  7867. LONG
  7868. TSPIAPI
  7869. TSPI_providerShutdown(
  7870. DWORD dwTSPIVersion,
  7871. DWORD dwPermanentProviderID
  7872. )
  7873. {
  7874. static char szFuncName[] = "providerShutdown";
  7875. FUNC_PARAM params[] =
  7876. {
  7877. { "dwTSPIVersion", dwTSPIVersion },
  7878. { szdwPermanentProviderID, dwPermanentProviderID }
  7879. };
  7880. FUNC_INFO info = { szFuncName, SYNC, 2, params };
  7881. LONG lResult;
  7882. DWORD i;
  7883. Prolog (&info);
  7884. DestroyIcon (gESPGlobals.hIconLine);
  7885. DestroyIcon (gESPGlobals.hIconPhone);
  7886. //
  7887. //
  7888. //
  7889. // if (gbDisableUI == FALSE)
  7890. // {
  7891. gESPGlobals.bProviderShutdown = TRUE;
  7892. if (gESPGlobals.hAsyncEventQueueServiceThread)
  7893. {
  7894. // wait for the thread to terminate
  7895. while (WaitForSingleObject(
  7896. gESPGlobals.hAsyncEventQueueServiceThread,
  7897. 0
  7898. ) != WAIT_OBJECT_0)
  7899. {
  7900. SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
  7901. Sleep (0);
  7902. }
  7903. CloseHandle (gESPGlobals.hAsyncEventQueueServiceThread);
  7904. gESPGlobals.hAsyncEventQueueServiceThread = 0;
  7905. }
  7906. CloseHandle (gESPGlobals.hAsyncEventsPendingEvent);
  7907. gESPGlobals.hAsyncEventsPendingEvent = 0;
  7908. DrvFree (gESPGlobals.pAsyncRequestQueue);
  7909. // }
  7910. //
  7911. // Free the device tables & call list crit sec
  7912. //
  7913. {
  7914. PDRVLINETABLE pTable = gESPGlobals.pLines;
  7915. while (pTable)
  7916. {
  7917. PDRVLINETABLE pNextTable = pTable->pNext;
  7918. DrvFree (pTable);
  7919. pTable = pNextTable;
  7920. }
  7921. }
  7922. {
  7923. PDRVPHONETABLE pTable = gESPGlobals.pPhones;
  7924. while (pTable)
  7925. {
  7926. PDRVPHONE pPhone = pTable->aPhones;
  7927. PDRVPHONETABLE pNextTable = pTable->pNext;
  7928. for (i = 0; i < pTable->dwNumUsedEntries; i++, pPhone++)
  7929. {
  7930. if (pPhone->pData)
  7931. {
  7932. DrvFree (pPhone->pData);
  7933. }
  7934. if (pPhone->pButtonInfo)
  7935. {
  7936. DrvFree (pPhone->pButtonInfo);
  7937. }
  7938. if (pPhone->pDisplay)
  7939. {
  7940. DrvFree (pPhone->pDisplay);
  7941. }
  7942. }
  7943. DrvFree (pTable);
  7944. pTable = pNextTable;
  7945. }
  7946. }
  7947. //
  7948. //
  7949. //
  7950. if (ghPBXThread)
  7951. {
  7952. ESPStopPBXThread (0);
  7953. }
  7954. //
  7955. // Clean up any parked calls
  7956. //
  7957. for (i = 0; i < MAX_NUM_PARKED_CALLS; i++)
  7958. {
  7959. if (gaParkedCalls[i])
  7960. {
  7961. if (gaParkedCalls[i]->pSendingFlowspec)
  7962. {
  7963. DrvFree (gaParkedCalls[i]->pSendingFlowspec);
  7964. }
  7965. if (gaParkedCalls[i]->pReceivingFlowspec)
  7966. {
  7967. DrvFree (gaParkedCalls[i]->pReceivingFlowspec);
  7968. }
  7969. if (gaParkedCalls[i]->pCallData)
  7970. {
  7971. DrvFree (gaParkedCalls[i]->pCallData);
  7972. }
  7973. DrvFree (gaParkedCalls[i]);
  7974. }
  7975. }
  7976. return (Epilog (&info));
  7977. }
  7978. LONG
  7979. TSPIAPI
  7980. TSPI_providerUIIdentify(
  7981. LPWSTR lpszUIDLLName
  7982. )
  7983. {
  7984. static char szFuncName[] = "providerUIIdentify";
  7985. FUNC_PARAM params[] =
  7986. {
  7987. { "pszUIDLLName", lpszUIDLLName }
  7988. };
  7989. FUNC_INFO info = { szFuncName, SYNC, 1, params };
  7990. Prolog (&info);
  7991. wcscpy (lpszUIDLLName, szESPUIDLL);
  7992. return (Epilog (&info));
  7993. }
  7994. #pragma warning (default:4047)
  7995. //
  7996. // ------------------------ Private support routines --------------------------
  7997. //
  7998. BOOL
  7999. PASCAL
  8000. IsValidDrvCall(
  8001. PDRVCALL pCall,
  8002. LPDWORD pdwCallInstance
  8003. )
  8004. {
  8005. try
  8006. {
  8007. if (pdwCallInstance)
  8008. {
  8009. *pdwCallInstance = pCall->dwCallInstance;
  8010. }
  8011. if (pCall->dwKey != DRVCALL_KEY)
  8012. {
  8013. return FALSE;
  8014. }
  8015. }
  8016. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  8017. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  8018. {
  8019. return FALSE;
  8020. }
  8021. return TRUE;
  8022. }
  8023. VOID
  8024. ShowStr(
  8025. BOOL bAlertApp,
  8026. char *format,
  8027. ...
  8028. )
  8029. {
  8030. char buf[256];
  8031. DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped = 0;
  8032. va_list ap;
  8033. if (gbDisableUI == TRUE)
  8034. {
  8035. return;
  8036. }
  8037. va_start(ap, format);
  8038. dwTotalSize = wvsprintf (buf, format, ap);
  8039. buf[dwTotalSize++] = '\r';
  8040. buf[dwTotalSize++] = '\n';
  8041. dwMoveSize = dwTotalSize;
  8042. EnterCriticalSection (&gESPGlobals.DebugBufferCritSec);
  8043. //
  8044. // Check to see if there's enough room in the the buffer for the new
  8045. // data, alloc more if not
  8046. //
  8047. if (dwMoveSize > (gESPGlobals.dwDebugBufferTotalSize -
  8048. gESPGlobals.dwDebugBufferUsedSize))
  8049. {
  8050. char *pNewDebugBuffer;
  8051. DWORD dwMoveSize2, dwMoveSizeWrapped2;
  8052. if (!(pNewDebugBuffer = DrvAlloc(
  8053. 2 * gESPGlobals.dwDebugBufferTotalSize
  8054. )))
  8055. {
  8056. LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
  8057. return;
  8058. }
  8059. if (gESPGlobals.pDebugBufferIn > gESPGlobals.pDebugBufferOut)
  8060. {
  8061. dwMoveSize2 = (DWORD) (gESPGlobals.pDebugBufferIn -
  8062. gESPGlobals.pDebugBufferOut);
  8063. dwMoveSizeWrapped2 = 0;
  8064. }
  8065. else
  8066. {
  8067. dwMoveSize2 = (DWORD) ((gESPGlobals.pDebugBuffer +
  8068. gESPGlobals.dwDebugBufferTotalSize) -
  8069. gESPGlobals.pDebugBufferOut);
  8070. dwMoveSizeWrapped2 = (DWORD) (gESPGlobals.pDebugBufferIn -
  8071. gESPGlobals.pDebugBuffer);
  8072. }
  8073. CopyMemory(
  8074. pNewDebugBuffer,
  8075. gESPGlobals.pDebugBufferOut,
  8076. dwMoveSize2
  8077. );
  8078. if (dwMoveSizeWrapped2)
  8079. {
  8080. CopyMemory(
  8081. pNewDebugBuffer + dwMoveSize2,
  8082. gESPGlobals.pDebugBuffer,
  8083. dwMoveSizeWrapped2
  8084. );
  8085. }
  8086. DrvFree (gESPGlobals.pDebugBuffer);
  8087. gESPGlobals.pDebugBufferIn = pNewDebugBuffer + dwMoveSize2 +
  8088. dwMoveSizeWrapped2;
  8089. gESPGlobals.pDebugBuffer =
  8090. gESPGlobals.pDebugBufferOut = pNewDebugBuffer;
  8091. gESPGlobals.dwDebugBufferTotalSize *= 2;
  8092. }
  8093. if (gESPGlobals.pDebugBufferIn >= gESPGlobals.pDebugBufferOut)
  8094. {
  8095. DWORD dwFreeSize = gESPGlobals.dwDebugBufferTotalSize -
  8096. (DWORD)(gESPGlobals.pDebugBufferIn - gESPGlobals.pDebugBuffer);
  8097. if (dwMoveSize > dwFreeSize)
  8098. {
  8099. dwMoveSizeWrapped = dwMoveSize - dwFreeSize;
  8100. dwMoveSize = dwFreeSize;
  8101. }
  8102. }
  8103. CopyMemory (gESPGlobals.pDebugBufferIn, buf, dwMoveSize);
  8104. if (dwMoveSizeWrapped != 0)
  8105. {
  8106. CopyMemory(
  8107. gESPGlobals.pDebugBuffer,
  8108. buf + dwMoveSize,
  8109. dwMoveSizeWrapped
  8110. );
  8111. gESPGlobals.pDebugBufferIn = gESPGlobals.pDebugBuffer +
  8112. dwMoveSizeWrapped;
  8113. }
  8114. else
  8115. {
  8116. gESPGlobals.pDebugBufferIn += dwMoveSize;
  8117. }
  8118. gESPGlobals.dwDebugBufferUsedSize += dwTotalSize;
  8119. LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
  8120. if (bAlertApp)
  8121. {
  8122. SetEvent (ghDebugOutputEvent);
  8123. }
  8124. va_end(ap);
  8125. }
  8126. char far *
  8127. GetFlags(
  8128. ULONG_PTR Flags,
  8129. PLOOKUP pLookup
  8130. )
  8131. {
  8132. int i;
  8133. static char buf[256];
  8134. char far *p = (char far *) NULL;
  8135. if (gbDisableUI == TRUE)
  8136. {
  8137. return NULL;
  8138. }
  8139. buf[0] = 0;
  8140. for (i = 0; (Flags && (pLookup[i].dwVal != 0xffffffff)); i++)
  8141. {
  8142. if (Flags & pLookup[i].dwVal)
  8143. {
  8144. lstrcatA (buf, pLookup[i].lpszVal);
  8145. lstrcatA (buf, " ");
  8146. Flags = Flags & (~ ((ULONG_PTR) pLookup[i].dwVal));
  8147. }
  8148. }
  8149. if (buf[0])
  8150. {
  8151. if ((p = (char far *) DrvAlloc (lstrlenA (buf) + 1)))
  8152. {
  8153. lstrcpyA (p, buf);
  8154. }
  8155. }
  8156. return p;
  8157. }
  8158. void
  8159. ShowLineEvent(
  8160. HTAPILINE htLine,
  8161. HTAPICALL htCall,
  8162. DWORD dwMsg,
  8163. ULONG_PTR Param1,
  8164. ULONG_PTR Param2,
  8165. ULONG_PTR Param3
  8166. )
  8167. {
  8168. if (gESPGlobals.dwDebugOptions & SHOW_EVENT_NOTIFICATIONS)
  8169. {
  8170. static DWORD adwLineMsgs[] =
  8171. {
  8172. LINE_ADDRESSSTATE,
  8173. LINE_CALLINFO,
  8174. LINE_CALLSTATE,
  8175. LINE_CLOSE,
  8176. LINE_DEVSPECIFIC,
  8177. LINE_DEVSPECIFICFEATURE,
  8178. LINE_GATHERDIGITS,
  8179. LINE_GENERATE,
  8180. LINE_LINEDEVSTATE,
  8181. LINE_MONITORDIGITS,
  8182. LINE_MONITORMEDIA,
  8183. LINE_MONITORTONE,
  8184. LINE_CREATE,
  8185. LINE_NEWCALL,
  8186. LINE_CALLDEVSPECIFIC,
  8187. LINE_CALLDEVSPECIFICFEATURE,
  8188. LINE_REMOVE,
  8189. 0xffffffff
  8190. };
  8191. static char *aszLineMsgs[] =
  8192. {
  8193. "LINE_ADDRESSSTATE",
  8194. "LINE_CALLINFO",
  8195. "LINE_CALLSTATE",
  8196. "LINE_CLOSE",
  8197. "LINE_DEVSPECIFIC",
  8198. "LINE_DEVSPECIFICFEATURE",
  8199. "LINE_GATHERDIGITS",
  8200. "LINE_GENERATE",
  8201. "LINE_LINEDEVSTATE",
  8202. "LINE_MONITORDIGITS",
  8203. "LINE_MONITORMEDIA",
  8204. "LINE_MONITORTONE",
  8205. "LINE_CREATE",
  8206. "LINE_NEWCALL",
  8207. "LINE_CALLDEVSPECIFIC",
  8208. "LINE_CALLDEVSPECIFICFEATURE",
  8209. "LINE_REMOVE"
  8210. };
  8211. int i;
  8212. char far *lpszParam1 = (char far *) NULL;
  8213. char far *lpszParam2 = (char far *) NULL;
  8214. char far *lpszParam3 = (char far *) NULL;
  8215. for (i = 0; adwLineMsgs[i] != 0xffffffff; i++)
  8216. {
  8217. if (dwMsg == adwLineMsgs[i])
  8218. {
  8219. ShowStr(
  8220. FALSE,
  8221. "%ssent %s : htLine=x%x, htCall=x%x",
  8222. szCallUp,
  8223. aszLineMsgs[i],
  8224. htLine,
  8225. htCall
  8226. );
  8227. break;
  8228. }
  8229. }
  8230. if (adwLineMsgs[i] == 0xffffffff)
  8231. {
  8232. ShowStr(
  8233. FALSE,
  8234. "%ssent <unknown msg id, x%x> : htLine=x%x, htCall=x%x",
  8235. szCallUp,
  8236. dwMsg,
  8237. htLine,
  8238. htCall
  8239. );
  8240. }
  8241. switch (dwMsg)
  8242. {
  8243. case LINE_ADDRESSSTATE:
  8244. lpszParam2 = GetFlags (Param2, aAddressStates);
  8245. break;
  8246. case LINE_CALLINFO:
  8247. lpszParam1 = GetFlags (Param1, aCallInfoStates);
  8248. break;
  8249. case LINE_CALLSTATE:
  8250. lpszParam1 = GetFlags (Param1, aCallStates);
  8251. break;
  8252. case LINE_LINEDEVSTATE:
  8253. lpszParam1 = GetFlags (Param1, aLineStates);
  8254. break;
  8255. } // switch
  8256. ShowStr(
  8257. FALSE,
  8258. "%s%sParam1=x%x, %s",
  8259. szCallUp,
  8260. szTab,
  8261. Param1,
  8262. (lpszParam1 ? lpszParam1 : "")
  8263. );
  8264. ShowStr(
  8265. FALSE,
  8266. "%s%sParam2=x%x, %s",
  8267. szCallUp,
  8268. szTab,
  8269. Param2,
  8270. (lpszParam2 ? lpszParam2 : "")
  8271. );
  8272. ShowStr(
  8273. TRUE,
  8274. "%s%sParam3=x%x, %s",
  8275. szCallUp,
  8276. szTab,
  8277. Param3,
  8278. (lpszParam3 ? lpszParam3 : "")
  8279. );
  8280. if (lpszParam1)
  8281. {
  8282. DrvFree (lpszParam1);
  8283. }
  8284. if (lpszParam2)
  8285. {
  8286. DrvFree (lpszParam2);
  8287. }
  8288. if (lpszParam3)
  8289. {
  8290. DrvFree (lpszParam3);
  8291. }
  8292. }
  8293. }
  8294. void
  8295. ShowPhoneEvent(
  8296. HTAPIPHONE htPhone,
  8297. DWORD dwMsg,
  8298. ULONG_PTR Param1,
  8299. ULONG_PTR Param2,
  8300. ULONG_PTR Param3
  8301. )
  8302. {
  8303. if (gESPGlobals.dwDebugOptions & SHOW_EVENT_NOTIFICATIONS)
  8304. {
  8305. static DWORD adwPhoneMsgs[] =
  8306. {
  8307. PHONE_BUTTON,
  8308. PHONE_CLOSE,
  8309. PHONE_DEVSPECIFIC,
  8310. PHONE_STATE,
  8311. PHONE_CREATE,
  8312. PHONE_REMOVE,
  8313. 0xffffffff
  8314. };
  8315. static char *aszPhoneMsgs[] =
  8316. {
  8317. "PHONE_BUTTON",
  8318. "PHONE_CLOSE",
  8319. "PHONE_DEVSPECIFIC",
  8320. "PHONE_STATE",
  8321. "PHONE_CREATE",
  8322. "PHONE_REMOVE"
  8323. };
  8324. char far *lpszParam1 = (char far *) NULL;
  8325. char far *lpszParam2 = (char far *) NULL;
  8326. char far *lpszParam3 = (char far *) NULL;
  8327. DWORD i;
  8328. for (i = 0; adwPhoneMsgs[i] != 0xffffffff; i++)
  8329. {
  8330. if (dwMsg == adwPhoneMsgs[i])
  8331. {
  8332. ShowStr(
  8333. FALSE,
  8334. "%ssent %s : htPhone=x%x",
  8335. szCallUp,
  8336. aszPhoneMsgs[i],
  8337. htPhone
  8338. );
  8339. break;
  8340. }
  8341. }
  8342. if (adwPhoneMsgs[i] == 0xffffffff)
  8343. {
  8344. ShowStr(
  8345. FALSE,
  8346. "%ssent <unknown msg id, x%x> : htPhone=x%x",
  8347. szCallUp,
  8348. dwMsg,
  8349. htPhone
  8350. );
  8351. }
  8352. switch (dwMsg)
  8353. {
  8354. case PHONE_BUTTON:
  8355. lpszParam2 = GetFlags (Param2, aButtonModes);
  8356. lpszParam3 = GetFlags (Param3, aButtonStates);
  8357. break;
  8358. case PHONE_STATE:
  8359. lpszParam1 = GetFlags (Param1, aPhoneStates);
  8360. break;
  8361. } // switch
  8362. ShowStr(
  8363. FALSE,
  8364. "%s%sParam1=x%x, %s",
  8365. szCallUp,
  8366. szTab,
  8367. Param1,
  8368. (lpszParam1 ? lpszParam1 : "")
  8369. );
  8370. ShowStr(
  8371. FALSE,
  8372. "%s%sParam2=x%x, %s",
  8373. szCallUp,
  8374. szTab,
  8375. Param2,
  8376. (lpszParam2 ? lpszParam2 : "")
  8377. );
  8378. ShowStr(
  8379. TRUE,
  8380. "%s%sParam3=x%x, %s",
  8381. szCallUp,
  8382. szTab,
  8383. Param3,
  8384. (lpszParam3 ? lpszParam3 : "")
  8385. );
  8386. if (lpszParam1)
  8387. {
  8388. DrvFree (lpszParam1);
  8389. }
  8390. if (lpszParam2)
  8391. {
  8392. DrvFree (lpszParam2);
  8393. }
  8394. if (lpszParam3)
  8395. {
  8396. DrvFree (lpszParam3);
  8397. }
  8398. }
  8399. }
  8400. BOOL
  8401. Prolog(
  8402. PFUNC_INFO pInfo
  8403. )
  8404. {
  8405. BOOL bLineFunc = (pInfo->pszFuncName[1] != 'h');
  8406. DWORD i, j;
  8407. if (gESPGlobals.dwDebugOptions & SHOW_FUNC_ENTRY)
  8408. {
  8409. ShowStr (FALSE, "TSPI_%s: enter", pInfo->pszFuncName);
  8410. }
  8411. if (gESPGlobals.dwDebugOptions & SHOW_PARAMETERS)
  8412. {
  8413. for (i = 0; i < pInfo->dwNumParams; i++)
  8414. {
  8415. if (pInfo->aParams[i].dwVal &&
  8416. pInfo->aParams[i].lpszVal[3] == 'z') // "lpszXxx"
  8417. {
  8418. ShowStr(
  8419. FALSE,
  8420. "%s%s=x%x, '%ws'",
  8421. szTab,
  8422. pInfo->aParams[i].lpszVal,
  8423. pInfo->aParams[i].dwVal,
  8424. pInfo->aParams[i].dwVal
  8425. );
  8426. }
  8427. else if (pInfo->aParams[i].pLookup)
  8428. {
  8429. char buf[90];
  8430. PLOOKUP pLookup = pInfo->aParams[i].pLookup;
  8431. wsprintfA(
  8432. buf,
  8433. "%s%s=x%x, ",
  8434. szTab,
  8435. pInfo->aParams[i].lpszVal,
  8436. pInfo->aParams[i].dwVal
  8437. );
  8438. for (j = 0; pLookup[j].dwVal != 0xffffffff; j++)
  8439. {
  8440. if (pInfo->aParams[i].dwVal & pLookup[j].dwVal)
  8441. {
  8442. lstrcatA (buf, pLookup[j].lpszVal);
  8443. lstrcatA (buf, " ");
  8444. if (lstrlenA (buf) > 60)
  8445. {
  8446. ShowStr (FALSE, buf);
  8447. wsprintfA (buf, "%s%s", szTab, szTab);
  8448. }
  8449. }
  8450. }
  8451. ShowStr (FALSE, buf);
  8452. }
  8453. else
  8454. {
  8455. ShowStr(
  8456. FALSE,
  8457. "%s%s=x%x",
  8458. szTab,
  8459. pInfo->aParams[i].lpszVal,
  8460. pInfo->aParams[i].dwVal
  8461. );
  8462. }
  8463. }
  8464. }
  8465. if (gESPGlobals.dwDebugOptions & (SHOW_PARAMETERS | SHOW_FUNC_ENTRY))
  8466. {
  8467. SetEvent (ghDebugOutputEvent);
  8468. }
  8469. //
  8470. //
  8471. //
  8472. if (gdwDevSpecificRequestID &&
  8473. glNextRequestResult != 0 &&
  8474. (pInfo->bAsync == FALSE ||
  8475. gdwNextRequestCompletionType == ESP_RESULT_RETURNRESULT)
  8476. )
  8477. {
  8478. gdwDevSpecificRequestID = 0;
  8479. pInfo->lResult = glNextRequestResult;
  8480. return FALSE;
  8481. }
  8482. if (gESPGlobals.dwDebugOptions & MANUAL_RESULTS)
  8483. {
  8484. char szDlgTitle[64];
  8485. EVENT_PARAM params[] =
  8486. {
  8487. { "lResult", PT_ORDINAL, 0, (bLineFunc ? aLineErrs : aPhoneErrs) }
  8488. };
  8489. EVENT_PARAM_HEADER paramsHeader =
  8490. { 1, szDlgTitle, 0, params };
  8491. HWND hwnd;
  8492. wsprintfA (szDlgTitle, "TSPI_%s request result", pInfo->pszFuncName);
  8493. DialogBoxParamA(
  8494. ghInstance,
  8495. (LPCSTR)MAKEINTRESOURCE(IDD_DIALOG1),
  8496. (HWND) NULL,
  8497. (DLGPROC) ValuesDlgProc,
  8498. (LPARAM) &paramsHeader
  8499. );
  8500. //
  8501. // If user selected to synchronously return an error we'll save
  8502. // the error & return FALSE to indicate to caller that it should
  8503. // return immediately.
  8504. //
  8505. if (params[0].dwValue)
  8506. {
  8507. pInfo->lResult = (LONG) params[0].dwValue;
  8508. return FALSE;
  8509. }
  8510. }
  8511. if (pInfo->bAsync)
  8512. {
  8513. //
  8514. // Alloc & init an async request info structure
  8515. //
  8516. PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO)
  8517. DrvAlloc (sizeof(ASYNC_REQUEST_INFO));
  8518. if ((pInfo->pAsyncReqInfo = pAsyncReqInfo))
  8519. {
  8520. pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  8521. pInfo->pfnPostProcessProc;
  8522. pAsyncReqInfo->dwRequestID = (DWORD)pInfo->aParams[0].dwVal;
  8523. pAsyncReqInfo->pszFuncName = pInfo->pszFuncName;
  8524. }
  8525. else
  8526. {
  8527. pInfo->lResult = (bLineFunc ?
  8528. LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
  8529. return FALSE;
  8530. }
  8531. }
  8532. return TRUE;
  8533. }
  8534. LONG
  8535. Epilog(
  8536. PFUNC_INFO pInfo
  8537. )
  8538. {
  8539. if (pInfo->bAsync)
  8540. {
  8541. PASYNC_REQUEST_INFO pAsyncReqInfo = pInfo->pAsyncReqInfo;
  8542. if (pInfo->lResult == 0)
  8543. {
  8544. //
  8545. //
  8546. //
  8547. if (gdwDevSpecificRequestID &&
  8548. pInfo->aParams[0].dwVal != gdwDevSpecificRequestID)
  8549. {
  8550. gdwDevSpecificRequestID = 0;
  8551. if (glNextRequestResult != 0)
  8552. {
  8553. pAsyncReqInfo->lResult = glNextRequestResult;
  8554. }
  8555. if (gdwNextRequestCompletionType ==
  8556. ESP_RESULT_CALLCOMPLPROCASYNC)
  8557. {
  8558. goto complete_event_async;
  8559. }
  8560. else
  8561. {
  8562. goto complete_event_sync;
  8563. }
  8564. }
  8565. switch (gESPGlobals.dwCompletionMode)
  8566. {
  8567. case COMPLETE_ASYNC_EVENTS_SYNCHRONOUSLY:
  8568. //
  8569. // We're completing this async request synchronously, so call
  8570. // the post processing proc (if there is one) or call the
  8571. // completion routine directly
  8572. //
  8573. complete_event_sync:
  8574. if (pInfo->pAsyncReqInfo->pfnPostProcessProc)
  8575. {
  8576. (*((POSTPROCESSPROC) pAsyncReqInfo->pfnPostProcessProc))(
  8577. pInfo->pAsyncReqInfo,
  8578. SYNC
  8579. );
  8580. }
  8581. else
  8582. {
  8583. DoCompletion (pAsyncReqInfo, SYNC);
  8584. }
  8585. DrvFree (pAsyncReqInfo);
  8586. break;
  8587. case COMPLETE_ASYNC_EVENTS_ASYNCHRONOUSLY:
  8588. //
  8589. // Safely add the async request to the queue (careful to
  8590. // reset pDataIn when we reach the end of the buffer)
  8591. //
  8592. complete_event_async:
  8593. EnterCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  8594. if (gESPGlobals.dwNumUsedQueueEntries ==
  8595. gESPGlobals.dwNumTotalQueueEntries)
  8596. {
  8597. //
  8598. // We've max'd out our ring buf, so try to grow it
  8599. //
  8600. DWORD dwMoveSize;
  8601. PASYNC_REQUEST_INFO *pNewAsyncRequestQueue;
  8602. if (!(pNewAsyncRequestQueue = DrvAlloc(
  8603. 2 * gESPGlobals.dwNumTotalQueueEntries *
  8604. sizeof (DWORD)
  8605. )))
  8606. {
  8607. LeaveCriticalSection(
  8608. &gESPGlobals.AsyncEventQueueCritSec
  8609. );
  8610. goto complete_event_sync;
  8611. }
  8612. dwMoveSize = (DWORD) ((gESPGlobals.pAsyncRequestQueue +
  8613. gESPGlobals.dwNumTotalQueueEntries) -
  8614. gESPGlobals.pAsyncRequestQueueOut) * sizeof (DWORD);
  8615. CopyMemory(
  8616. pNewAsyncRequestQueue,
  8617. gESPGlobals.pAsyncRequestQueueOut,
  8618. dwMoveSize
  8619. );
  8620. CopyMemory(
  8621. ((LPBYTE) pNewAsyncRequestQueue) + dwMoveSize,
  8622. gESPGlobals.pAsyncRequestQueue,
  8623. (gESPGlobals.pAsyncRequestQueueOut -
  8624. gESPGlobals.pAsyncRequestQueue) * sizeof (DWORD)
  8625. );
  8626. DrvFree (gESPGlobals.pAsyncRequestQueue);
  8627. gESPGlobals.pAsyncRequestQueue =
  8628. gESPGlobals.pAsyncRequestQueueOut = pNewAsyncRequestQueue;
  8629. gESPGlobals.pAsyncRequestQueueIn = pNewAsyncRequestQueue +
  8630. gESPGlobals.dwNumTotalQueueEntries;
  8631. gESPGlobals.dwNumTotalQueueEntries *= 2;
  8632. }
  8633. *(gESPGlobals.pAsyncRequestQueueIn) = pAsyncReqInfo;
  8634. gESPGlobals.pAsyncRequestQueueIn++;
  8635. if (gESPGlobals.pAsyncRequestQueueIn ==
  8636. (gESPGlobals.pAsyncRequestQueue +
  8637. gESPGlobals.dwNumTotalQueueEntries))
  8638. {
  8639. gESPGlobals.pAsyncRequestQueueIn =
  8640. gESPGlobals.pAsyncRequestQueue;
  8641. }
  8642. gESPGlobals.dwNumUsedQueueEntries++;
  8643. if (gESPGlobals.dwNumUsedQueueEntries == 1)
  8644. {
  8645. SetEvent (gESPGlobals.hAsyncEventsPendingEvent);
  8646. }
  8647. LeaveCriticalSection (&gESPGlobals.AsyncEventQueueCritSec);
  8648. break;
  8649. case COMPLETE_ASYNC_EVENTS_SYNC_AND_ASYNC:
  8650. {
  8651. //
  8652. // Decide whether to complete this request sync or async,
  8653. // then jump to the right place
  8654. //
  8655. static i = 0;
  8656. if (i++ % 2)
  8657. {
  8658. goto complete_event_sync;
  8659. }
  8660. else
  8661. {
  8662. goto complete_event_async;
  8663. }
  8664. break;
  8665. }
  8666. case COMPLETE_ASYNC_EVENTS_MANUALLY:
  8667. WriteEventBuffer(
  8668. (ULONG_PTR) pAsyncReqInfo->dwRequestID,
  8669. WIDGETTYPE_ASYNCREQUEST,
  8670. (ULONG_PTR) pAsyncReqInfo,
  8671. 0,
  8672. 0,
  8673. 0
  8674. );
  8675. break;
  8676. }
  8677. //
  8678. // Finally, return the request ID
  8679. //
  8680. pInfo->lResult = (DWORD) pInfo->aParams[0].dwVal;
  8681. }
  8682. else if (pAsyncReqInfo)
  8683. {
  8684. DrvFree (pAsyncReqInfo);
  8685. }
  8686. }
  8687. if (gESPGlobals.dwDebugOptions & SHOW_FUNC_EXIT)
  8688. {
  8689. ShowStr(
  8690. TRUE,
  8691. "TSPI_%s: exit, returning x%x",
  8692. pInfo->pszFuncName,
  8693. pInfo->lResult
  8694. );
  8695. }
  8696. return (pInfo->lResult);
  8697. }
  8698. void
  8699. PASCAL
  8700. SendLineEvent(
  8701. PDRVLINE pLine,
  8702. PDRVCALL pCall,
  8703. DWORD dwMsg,
  8704. ULONG_PTR Param1,
  8705. ULONG_PTR Param2,
  8706. ULONG_PTR Param3
  8707. )
  8708. {
  8709. //
  8710. //
  8711. //
  8712. (*(gESPGlobals.pfnLineEvent))(
  8713. pLine->htLine,
  8714. (pCall ? pCall->htCall : (HTAPICALL) NULL),
  8715. dwMsg,
  8716. Param1,
  8717. Param2,
  8718. Param3
  8719. );
  8720. if (dwMsg == LINE_CALLSTATE)
  8721. {
  8722. //PostUpdateWidgetListMsg();
  8723. }
  8724. ShowLineEvent(
  8725. pLine->htLine,
  8726. (pCall ? pCall->htCall : (HTAPICALL) NULL),
  8727. dwMsg,
  8728. Param1,
  8729. Param2,
  8730. Param3
  8731. );
  8732. }
  8733. void
  8734. PASCAL
  8735. SendPhoneEvent(
  8736. PDRVPHONE pPhone,
  8737. DWORD dwMsg,
  8738. ULONG_PTR Param1,
  8739. ULONG_PTR Param2,
  8740. ULONG_PTR Param3
  8741. )
  8742. {
  8743. //
  8744. //
  8745. //
  8746. (*(gESPGlobals.pfnPhoneEvent))(
  8747. pPhone->htPhone,
  8748. dwMsg,
  8749. Param1,
  8750. Param2,
  8751. Param3
  8752. );
  8753. ShowPhoneEvent(
  8754. pPhone->htPhone,
  8755. dwMsg,
  8756. Param1,
  8757. Param2,
  8758. Param3
  8759. );
  8760. }
  8761. void
  8762. PASCAL
  8763. DoCompletion(
  8764. PASYNC_REQUEST_INFO pAsyncRequestInfo,
  8765. BOOL bAsync
  8766. )
  8767. {
  8768. (*(gESPGlobals.pfnCompletion))(
  8769. pAsyncRequestInfo->dwRequestID,
  8770. pAsyncRequestInfo->lResult
  8771. );
  8772. if (gESPGlobals.dwDebugOptions & SHOW_COMPLETION_NOTIFICATIONS)
  8773. {
  8774. ShowStr(
  8775. TRUE,
  8776. "%sTSPI_%s: calling compl proc (%ssync), dwReqID=x%x, lResult = x%x",
  8777. szCallUp,
  8778. pAsyncRequestInfo->pszFuncName,
  8779. (bAsync ? "a" : ""),
  8780. pAsyncRequestInfo->dwRequestID,
  8781. pAsyncRequestInfo->lResult
  8782. );
  8783. }
  8784. }
  8785. LONG
  8786. PASCAL
  8787. SetCallState(
  8788. PDRVCALL pCall,
  8789. DWORD dwExpectedCallInstance,
  8790. DWORD dwValidCurrentStates,
  8791. DWORD dwNewCallState,
  8792. ULONG_PTR dwNewCallStateMode,
  8793. BOOL bSendStateMsgToExe
  8794. )
  8795. {
  8796. LONG lResult = 0;
  8797. DWORD dwActualCallInstance;
  8798. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  8799. if (!IsValidDrvCall (pCall, &dwActualCallInstance) ||
  8800. dwActualCallInstance != dwExpectedCallInstance)
  8801. {
  8802. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  8803. return LINEERR_INVALCALLHANDLE;
  8804. }
  8805. if (lResult == 0)
  8806. {
  8807. //
  8808. // Check to see that the call is in a valid (expected) state.
  8809. // If dwValidCurrentStates == 0xffffffff then we want to chg the
  8810. // state regardless of the current state.
  8811. //
  8812. if ((dwValidCurrentStates != 0xffffffff) &&
  8813. !(dwValidCurrentStates & pCall->dwCallState))
  8814. {
  8815. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  8816. return LINEERR_INVALCALLSTATE;
  8817. }
  8818. //
  8819. // Only chg the call state if it differs from the existing one
  8820. //
  8821. if (dwNewCallState != pCall->dwCallState)
  8822. {
  8823. pCall->dwCallState = dwNewCallState;
  8824. pCall->dwCallStateMode = (DWORD) dwNewCallStateMode;
  8825. SendLineEvent(
  8826. pCall->pLine,
  8827. pCall,
  8828. LINE_CALLSTATE,
  8829. dwNewCallState,
  8830. dwNewCallStateMode,
  8831. pCall->dwMediaMode
  8832. );
  8833. if (bSendStateMsgToExe)
  8834. {
  8835. WriteEventBuffer(
  8836. ((PDRVLINE) pCall->pLine)->dwDeviceID,
  8837. WIDGETTYPE_CALL,
  8838. (ULONG_PTR) pCall,
  8839. (ULONG_PTR) pCall->htCall,
  8840. dwNewCallState,
  8841. pCall->dwAddressID
  8842. );
  8843. }
  8844. //
  8845. // If this call has an associated call/endpoint then pass
  8846. // connected (1st time only) or disconnected msgs to that
  8847. // call so they know if we've answered or hung up
  8848. //
  8849. if (pCall->pDestCall)
  8850. {
  8851. if (dwNewCallState == LINECALLSTATE_CONNECTED)
  8852. {
  8853. if (!pCall->bConnectedToDestCall)
  8854. {
  8855. if (IsValidDrvCall (pCall->pDestCall, NULL))
  8856. {
  8857. if (SetCallState(
  8858. pCall->pDestCall,
  8859. pCall->pDestCall->dwCallInstance,
  8860. 0xffffffff,
  8861. LINECALLSTATE_CONNECTED,
  8862. 0,
  8863. TRUE
  8864. ) == 0)
  8865. {
  8866. // NOTE: use 0x55 to aid in debugging
  8867. // wild writes
  8868. pCall->bConnectedToDestCall =
  8869. pCall->pDestCall->bConnectedToDestCall = 0x55;
  8870. }
  8871. }
  8872. else
  8873. {
  8874. pCall->pDestCall = NULL;
  8875. }
  8876. }
  8877. }
  8878. else if (dwNewCallState == LINECALLSTATE_IDLE ||
  8879. dwNewCallState == LINECALLSTATE_DISCONNECTED)
  8880. {
  8881. pCall->pDestCall->pDestCall = NULL;
  8882. SetCallState(
  8883. pCall->pDestCall,
  8884. pCall->pDestCall->dwCallInstance,
  8885. 0xffffffff,
  8886. LINECALLSTATE_DISCONNECTED,
  8887. (dwNewCallState == LINECALLSTATE_DISCONNECTED ?
  8888. dwNewCallStateMode : LINEDISCONNECTMODE_NORMAL),
  8889. TRUE
  8890. );
  8891. pCall->pDestCall = NULL;
  8892. }
  8893. }
  8894. }
  8895. }
  8896. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  8897. return lResult;
  8898. }
  8899. void
  8900. PASCAL
  8901. WriteEventBuffer(
  8902. ULONG_PTR Param1,
  8903. ULONG_PTR Param2,
  8904. ULONG_PTR Param3,
  8905. ULONG_PTR Param4,
  8906. ULONG_PTR Param5,
  8907. ULONG_PTR Param6
  8908. )
  8909. {
  8910. WIDGETEVENT event ={ Param1, Param2, Param3, Param4, Param5, Param6 };
  8911. if (gbDisableUI == TRUE)
  8912. {
  8913. return;
  8914. }
  8915. EnterCriticalSection (&gESPGlobals.EventBufferCritSec);
  8916. if ((gESPGlobals.dwEventBufferUsedSize + sizeof (WIDGETEVENT)) >
  8917. gESPGlobals.dwEventBufferTotalSize)
  8918. {
  8919. //
  8920. // We've max'd out our ring buf, so try to grow it
  8921. //
  8922. char *pNewEventBuffer;
  8923. DWORD dwMoveSize;
  8924. if (!(pNewEventBuffer = DrvAlloc (
  8925. 2 * gESPGlobals.dwEventBufferTotalSize
  8926. )))
  8927. {
  8928. LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
  8929. // log some sort of error
  8930. return;
  8931. }
  8932. dwMoveSize = (DWORD) (gESPGlobals.pEventBuffer +
  8933. gESPGlobals.dwEventBufferTotalSize - gESPGlobals.pEventBufferOut);
  8934. CopyMemory (pNewEventBuffer, gESPGlobals.pEventBufferOut, dwMoveSize);
  8935. CopyMemory(
  8936. pNewEventBuffer + dwMoveSize,
  8937. gESPGlobals.pEventBuffer,
  8938. gESPGlobals.pEventBufferOut - gESPGlobals.pEventBuffer
  8939. );
  8940. DrvFree (gESPGlobals.pEventBuffer);
  8941. gESPGlobals.pEventBuffer =
  8942. gESPGlobals.pEventBufferOut = pNewEventBuffer;
  8943. gESPGlobals.pEventBufferIn = pNewEventBuffer +
  8944. gESPGlobals.dwEventBufferTotalSize;
  8945. gESPGlobals.dwEventBufferTotalSize *= 2;
  8946. }
  8947. CopyMemory (gESPGlobals.pEventBufferIn, &event, sizeof (WIDGETEVENT));
  8948. gESPGlobals.dwEventBufferUsedSize += sizeof (WIDGETEVENT);
  8949. if ((gESPGlobals.pEventBufferIn += sizeof (WIDGETEVENT)) >=
  8950. (gESPGlobals.pEventBuffer + gESPGlobals.dwEventBufferTotalSize))
  8951. {
  8952. gESPGlobals.pEventBufferIn = gESPGlobals.pEventBuffer;
  8953. }
  8954. SetEvent (ghWidgetEventsEvent);
  8955. LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
  8956. }
  8957. LPVOID
  8958. DrvAlloc(
  8959. size_t numBytes
  8960. )
  8961. {
  8962. LPVOID p = HeapAlloc (ghESPHeap, HEAP_ZERO_MEMORY, numBytes);
  8963. if (!p)
  8964. {
  8965. ShowStr (TRUE, "Error: DrvAlloc (x%x) failed", (DWORD) numBytes);
  8966. }
  8967. return p;
  8968. }
  8969. void
  8970. DrvFree(
  8971. LPVOID p
  8972. )
  8973. {
  8974. if (p)
  8975. {
  8976. #if DBG
  8977. //
  8978. // Fill the buf to free with 0xa5's to facilitate debugging
  8979. //
  8980. FillMemory (p, HeapSize (ghESPHeap, 0, p), 0xa5);
  8981. #endif
  8982. HeapFree (ghESPHeap, 0, p);
  8983. }
  8984. }
  8985. PDRVADDRESS
  8986. PASCAL
  8987. FindFreeAddress(
  8988. PDRVLINE pLine
  8989. )
  8990. {
  8991. DWORD i;
  8992. PDRVADDRESS pAddr = pLine->aAddrs;
  8993. for (i = 0; i < gESPGlobals.dwNumAddressesPerLine; i++)
  8994. {
  8995. if (pAddr->dwNumCalls < gESPGlobals.dwNumCallsPerAddress)
  8996. {
  8997. return pAddr;
  8998. }
  8999. pAddr++;
  9000. }
  9001. return NULL;
  9002. }
  9003. LONG
  9004. PASCAL
  9005. AllocCall(
  9006. PDRVLINE pLine,
  9007. HTAPICALL htCall,
  9008. LPLINECALLPARAMS pCallParams,
  9009. PDRVCALL *ppCall
  9010. )
  9011. {
  9012. LONG lResult = 0;
  9013. DWORD i;
  9014. PDRVCALL pCall;
  9015. PDRVADDRESS pAddr;
  9016. if (!(pCall = (PDRVCALL) DrvAlloc (sizeof (DRVCALL))))
  9017. {
  9018. return LINEERR_NOMEM;
  9019. }
  9020. pCall->pLine = pLine;
  9021. pCall->htCall = htCall;
  9022. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  9023. if (!pCallParams)
  9024. {
  9025. if (!(pAddr = FindFreeAddress (pLine)))
  9026. {
  9027. lResult = LINEERR_CALLUNAVAIL;
  9028. goto AllocCall_cleanup;
  9029. }
  9030. pCall->dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
  9031. pCall->dwBearerMode = LINEBEARERMODE_VOICE;
  9032. pCall->dwAddressType = LINEADDRESSTYPE_PHONENUMBER;
  9033. }
  9034. else
  9035. {
  9036. AllocCall_findTheAddr:
  9037. if (pCallParams->dwAddressMode == LINEADDRESSMODE_ADDRESSID)
  9038. {
  9039. if (pCallParams->dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
  9040. {
  9041. lResult = LINEERR_INVALADDRESSID;
  9042. goto AllocCall_cleanup;
  9043. }
  9044. if (pCallParams->dwAddressID == 0)
  9045. {
  9046. //
  9047. // App doesn't care which addr to make call on
  9048. //
  9049. if (!(pAddr = FindFreeAddress (pLine)))
  9050. {
  9051. lResult = LINEERR_CALLUNAVAIL;
  9052. goto AllocCall_cleanup;
  9053. }
  9054. }
  9055. else
  9056. {
  9057. //
  9058. // App wants call on a particular addr
  9059. //
  9060. pAddr = pLine->aAddrs + pCallParams->dwAddressID;
  9061. if (pAddr->dwNumCalls > gESPGlobals.dwNumCallsPerAddress)
  9062. {
  9063. lResult = LINEERR_CALLUNAVAIL;
  9064. goto AllocCall_cleanup;
  9065. }
  9066. }
  9067. }
  9068. else // (pCallParams->dwAddressMode == LINEADDRESSMODE_DIALABLEADDR)
  9069. {
  9070. // BUGBUG AllocCall: handle dialable addr
  9071. pCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  9072. pCallParams->dwAddressID = 0;
  9073. goto AllocCall_findTheAddr;
  9074. }
  9075. pCall->dwMediaMode = pCallParams->dwMediaMode;
  9076. pCall->dwBearerMode = pCallParams->dwBearerMode;
  9077. if (gESPGlobals.dwSPIVersion >= 0x00030000)
  9078. {
  9079. pCall->dwAddressType = pCallParams->dwAddressType;
  9080. }
  9081. }
  9082. //
  9083. // Call was successfully "made", so do all the common stuff like
  9084. // adding it to the addr's list, setting the attributes, etc...
  9085. //
  9086. if ((pCall->pNext = pAddr->pCalls))
  9087. {
  9088. pCall->pNext->pPrev = pCall;
  9089. }
  9090. pAddr->pCalls = pCall;
  9091. pAddr->dwNumCalls++;
  9092. pCall->dwKey = DRVCALL_KEY;
  9093. pCall->pLine = pLine;
  9094. pCall->dwAddressID = (DWORD) (pAddr - pLine->aAddrs);
  9095. pCall->dwCallInstance = gdwCallInstance++;
  9096. pCall->dwCallID = (++gdwCallID ? gdwCallID : ++gdwCallID);
  9097. pCall->dwRelatedCallID = 0;
  9098. AllocCall_cleanup:
  9099. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  9100. if (lResult == 0)
  9101. {
  9102. *ppCall = pCall;
  9103. }
  9104. else
  9105. {
  9106. DrvFree (pCall);
  9107. }
  9108. return lResult;
  9109. }
  9110. void
  9111. PASCAL
  9112. FreeCall(
  9113. PDRVCALL pCall,
  9114. DWORD dwExpectedCallInstance
  9115. )
  9116. {
  9117. DWORD dwActualCallInstance;
  9118. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  9119. if (IsValidDrvCall (pCall, &dwActualCallInstance) &&
  9120. dwActualCallInstance == dwExpectedCallInstance)
  9121. {
  9122. PDRVADDRESS pAddr;
  9123. pCall->dwKey = INVAL_KEY;
  9124. pAddr = ((PDRVLINE) pCall->pLine)->aAddrs + pCall->dwAddressID;
  9125. if (pCall->pNext)
  9126. {
  9127. pCall->pNext->pPrev = pCall->pPrev;
  9128. }
  9129. if (pCall->pPrev)
  9130. {
  9131. pCall->pPrev->pNext = pCall->pNext;
  9132. }
  9133. else
  9134. {
  9135. pAddr->pCalls = pCall->pNext;
  9136. }
  9137. if (pCall->pDestCall)
  9138. {
  9139. pCall->pDestCall->pDestCall = NULL;
  9140. SetCallState(
  9141. pCall->pDestCall,
  9142. pCall->pDestCall->dwCallInstance,
  9143. 0xffffffff,
  9144. LINECALLSTATE_DISCONNECTED,
  9145. LINEDISCONNECTMODE_NORMAL,
  9146. TRUE
  9147. );
  9148. pCall->pDestCall = NULL;
  9149. }
  9150. pAddr->dwNumCalls--;
  9151. }
  9152. else
  9153. {
  9154. pCall = NULL;
  9155. }
  9156. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  9157. if (pCall)
  9158. {
  9159. if (pCall->pSendingFlowspec)
  9160. {
  9161. DrvFree (pCall->pSendingFlowspec);
  9162. }
  9163. if (pCall->pReceivingFlowspec)
  9164. {
  9165. DrvFree (pCall->pReceivingFlowspec);
  9166. }
  9167. if (pCall->pCallData)
  9168. {
  9169. DrvFree (pCall->pCallData);
  9170. }
  9171. if (pCall->dwGatherDigitsEndToEndID)
  9172. {
  9173. (gESPGlobals.pfnLineEvent)(
  9174. ((PDRVLINE) pCall->pLine)->htLine,
  9175. pCall->htCall,
  9176. LINE_GATHERDIGITS,
  9177. LINEGATHERTERM_CANCEL,
  9178. pCall->dwGatherDigitsEndToEndID,
  9179. 0
  9180. );
  9181. }
  9182. if (pCall->dwGenerateDigitsEndToEndID)
  9183. {
  9184. (gESPGlobals.pfnLineEvent)(
  9185. ((PDRVLINE) pCall->pLine)->htLine,
  9186. pCall->htCall,
  9187. LINE_GENERATE,
  9188. LINEGENERATETERM_CANCEL,
  9189. pCall->dwGenerateDigitsEndToEndID,
  9190. 0
  9191. );
  9192. }
  9193. if (pCall->dwGenerateToneEndToEndID)
  9194. {
  9195. (gESPGlobals.pfnLineEvent)(
  9196. ((PDRVLINE) pCall->pLine)->htLine,
  9197. pCall->htCall,
  9198. LINE_GENERATE,
  9199. LINEGENERATETERM_CANCEL,
  9200. pCall->dwGenerateToneEndToEndID,
  9201. 0
  9202. );
  9203. }
  9204. if (pCall->dwMonitorToneListID)
  9205. {
  9206. (gESPGlobals.pfnLineEvent)(
  9207. ((PDRVLINE) pCall->pLine)->htLine,
  9208. pCall->htCall,
  9209. LINE_MONITORTONE,
  9210. 0,
  9211. pCall->dwMonitorToneListID,
  9212. 0
  9213. );
  9214. }
  9215. DrvFree (pCall);
  9216. }
  9217. }
  9218. PDRVLINE
  9219. PASCAL
  9220. GetLineFromID(
  9221. DWORD dwDeviceID
  9222. )
  9223. {
  9224. DWORD i;
  9225. PDRVLINE pLine;
  9226. if (dwDeviceID < gESPGlobals.dwLineDeviceIDBase)
  9227. {
  9228. pLine = (PDRVLINE) NULL;
  9229. }
  9230. else if (dwDeviceID < (gESPGlobals.dwLineDeviceIDBase +
  9231. gESPGlobals.dwInitialNumLines))
  9232. {
  9233. pLine = (PDRVLINE) (((LPBYTE) gESPGlobals.pLines->aLines) +
  9234. ((dwDeviceID - gESPGlobals.dwLineDeviceIDBase) * gdwDrvLineSize));
  9235. }
  9236. else
  9237. {
  9238. pLine = (PDRVLINE) (((LPBYTE) gESPGlobals.pLines->aLines) +
  9239. (gESPGlobals.dwInitialNumLines * gdwDrvLineSize));
  9240. for(
  9241. i = gESPGlobals.dwInitialNumLines;
  9242. i < gESPGlobals.pLines->dwNumUsedEntries;
  9243. i++
  9244. )
  9245. {
  9246. if (pLine->dwDeviceID == dwDeviceID)
  9247. {
  9248. return pLine;
  9249. }
  9250. pLine = (PDRVLINE) (((LPBYTE) pLine) + gdwDrvLineSize);
  9251. }
  9252. pLine = (PDRVLINE) NULL;
  9253. }
  9254. return pLine;
  9255. }
  9256. PDRVPHONE
  9257. PASCAL
  9258. GetPhoneFromID(
  9259. DWORD dwDeviceID
  9260. )
  9261. {
  9262. DWORD i;
  9263. PDRVPHONE pPhone;
  9264. if (dwDeviceID < gESPGlobals.dwPhoneDeviceIDBase)
  9265. {
  9266. pPhone = (PDRVPHONE) NULL;
  9267. }
  9268. else if (dwDeviceID < (gESPGlobals.dwPhoneDeviceIDBase +
  9269. gESPGlobals.dwInitialNumPhones))
  9270. {
  9271. pPhone = gESPGlobals.pPhones->aPhones +
  9272. (dwDeviceID - gESPGlobals.dwPhoneDeviceIDBase);
  9273. }
  9274. else
  9275. {
  9276. pPhone = gESPGlobals.pPhones->aPhones + gESPGlobals.dwInitialNumPhones;
  9277. for(
  9278. i = gESPGlobals.dwInitialNumPhones;
  9279. i < gESPGlobals.pPhones->dwNumUsedEntries;
  9280. i++, pPhone++
  9281. )
  9282. {
  9283. if (pPhone->dwDeviceID == dwDeviceID)
  9284. {
  9285. return pPhone;
  9286. }
  9287. }
  9288. pPhone = (PDRVPHONE) NULL;
  9289. }
  9290. return pPhone;
  9291. }
  9292. long
  9293. ESPAttach(
  9294. long lProcessID,
  9295. ULONG_PTR *phShutdownEvent,
  9296. ULONG_PTR *phDebugOutputEvent,
  9297. ULONG_PTR *phWidgetEventsEvent
  9298. )
  9299. {
  9300. HANDLE hMyProcess, hEspExeProcess;
  9301. hMyProcess = GetCurrentProcess();
  9302. hEspExeProcess = OpenProcess(
  9303. PROCESS_DUP_HANDLE,
  9304. TRUE,
  9305. (DWORD) lProcessID
  9306. );
  9307. if (!DuplicateHandle(
  9308. hMyProcess,
  9309. ghDebugOutputEvent,
  9310. hEspExeProcess,
  9311. (HANDLE *) phDebugOutputEvent,
  9312. 0,
  9313. FALSE,
  9314. DUPLICATE_SAME_ACCESS
  9315. ) ||
  9316. !DuplicateHandle(
  9317. hMyProcess,
  9318. ghShutdownEvent,
  9319. hEspExeProcess,
  9320. (HANDLE *) phShutdownEvent,
  9321. 0,
  9322. FALSE,
  9323. DUPLICATE_SAME_ACCESS
  9324. ) ||
  9325. !DuplicateHandle(
  9326. hMyProcess,
  9327. ghWidgetEventsEvent,
  9328. hEspExeProcess,
  9329. (HANDLE *) phWidgetEventsEvent,
  9330. 0,
  9331. FALSE,
  9332. DUPLICATE_SAME_ACCESS
  9333. ))
  9334. {
  9335. DBGOUT((1, "ESPAttach: DupHandle failed, err=%d", GetLastError()));
  9336. CloseHandle(hEspExeProcess); /* bug 49690 */
  9337. return -1;
  9338. }
  9339. return 0;
  9340. }
  9341. void
  9342. ESPSetOptions(
  9343. long lDebugOptions,
  9344. long lCompletionMode
  9345. )
  9346. {
  9347. gESPGlobals.dwDebugOptions = (DWORD) lDebugOptions;
  9348. gESPGlobals.dwCompletionMode = (DWORD) lCompletionMode;
  9349. if (!gbInteractWithDesktop)
  9350. {
  9351. gESPGlobals.dwDebugOptions &= ~MANUAL_RESULTS;
  9352. }
  9353. }
  9354. void
  9355. ESPCompleteRequest(
  9356. ULONG_PTR lAsyncReqInfo,
  9357. long lResult
  9358. )
  9359. {
  9360. PASYNC_REQUEST_INFO pAsyncReqInfo = (PASYNC_REQUEST_INFO) lAsyncReqInfo;
  9361. pAsyncReqInfo->lResult = lResult;
  9362. if (pAsyncReqInfo->pfnPostProcessProc)
  9363. {
  9364. (*((POSTPROCESSPROC) pAsyncReqInfo->pfnPostProcessProc))(
  9365. pAsyncReqInfo,
  9366. ASYNC
  9367. );
  9368. }
  9369. else
  9370. {
  9371. DoCompletion (pAsyncReqInfo, ASYNC);
  9372. }
  9373. DrvFree (pAsyncReqInfo);
  9374. }
  9375. long
  9376. ESPEvent(
  9377. ULONG_PTR htDevice,
  9378. ULONG_PTR htCall,
  9379. ULONG_PTR Msg,
  9380. ULONG_PTR Param1,
  9381. ULONG_PTR Param2,
  9382. ULONG_PTR Param3
  9383. )
  9384. {
  9385. switch (Msg)
  9386. {
  9387. case LINE_CALLSTATE:
  9388. {
  9389. DWORD dwCallInst;
  9390. // BUGBUG when state == conf or prevState == conf need to add/rem conf list
  9391. try
  9392. {
  9393. dwCallInst = ((PDRVCALL) htCall)->dwCallInstance;
  9394. }
  9395. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  9396. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  9397. {
  9398. break;
  9399. }
  9400. SetCallState(
  9401. (PDRVCALL) htCall,
  9402. dwCallInst,
  9403. 0xffffffff,
  9404. (DWORD) Param1,
  9405. (DWORD) Param2,
  9406. TRUE
  9407. );
  9408. break;
  9409. }
  9410. case LINE_REMOVE:
  9411. //
  9412. // Ignore invalid device ID
  9413. //
  9414. if (!GetLineFromID((DWORD)Param1))
  9415. break;
  9416. case LINE_ADDRESSSTATE:
  9417. case LINE_CALLDEVSPECIFIC:
  9418. case LINE_CALLDEVSPECIFICFEATURE:
  9419. case LINE_CALLINFO:
  9420. case LINE_CLOSE:
  9421. case LINE_DEVSPECIFIC:
  9422. case LINE_DEVSPECIFICFEATURE:
  9423. case LINE_GATHERDIGITS:
  9424. case LINE_GENERATE:
  9425. case LINE_LINEDEVSTATE:
  9426. case LINE_MONITORDIGITS:
  9427. case LINE_MONITORMEDIA:
  9428. case LINE_MONITORTONE:
  9429. (*gESPGlobals.pfnLineEvent)(
  9430. (HTAPILINE) htDevice,
  9431. (HTAPICALL) htCall,
  9432. (DWORD) Msg,
  9433. Param1,
  9434. Param2,
  9435. Param3
  9436. );
  9437. ShowLineEvent(
  9438. (HTAPILINE) htDevice,
  9439. (HTAPICALL) htCall,
  9440. (DWORD) Msg,
  9441. Param1,
  9442. Param2,
  9443. Param3
  9444. );
  9445. break;
  9446. case LINE_CREATEDIALOGINSTANCE:
  9447. {
  9448. TUISPICREATEDIALOGINSTANCEPARAMS createDlgParams;
  9449. ZeroMemory(
  9450. &createDlgParams,
  9451. sizeof (TUISPICREATEDIALOGINSTANCEPARAMS)
  9452. );
  9453. createDlgParams.dwRequestID = (DWORD) Param1;
  9454. createDlgParams.hdDlgInst = (HDRVDIALOGINSTANCE) 0x55;
  9455. createDlgParams.lpszUIDLLName = szESPUIDLL;
  9456. createDlgParams.lpParams = "genDlg params";
  9457. createDlgParams.dwSize = 14;
  9458. (*gESPGlobals.pfnLineEvent)(
  9459. (HTAPILINE) gESPGlobals.hProvider,
  9460. (HTAPICALL) NULL,
  9461. LINE_CREATEDIALOGINSTANCE,
  9462. (ULONG_PTR) &createDlgParams,
  9463. 0,
  9464. 0
  9465. );
  9466. ShowLineEvent(
  9467. (HTAPILINE) gESPGlobals.hProvider,
  9468. NULL,
  9469. LINE_CREATEDIALOGINSTANCE,
  9470. (ULONG_PTR) &createDlgParams,
  9471. 0,
  9472. 0
  9473. );
  9474. break;
  9475. }
  9476. case LINE_SENDDIALOGINSTANCEDATA:
  9477. {
  9478. char data[] = "dlgInstData";
  9479. (*gESPGlobals.pfnLineEvent)(
  9480. (HTAPILINE) Param1,
  9481. (HTAPICALL) NULL,
  9482. LINE_SENDDIALOGINSTANCEDATA,
  9483. (ULONG_PTR) data,
  9484. 12,
  9485. 0
  9486. );
  9487. ShowLineEvent(
  9488. (HTAPILINE) Param1,
  9489. NULL,
  9490. LINE_CREATEDIALOGINSTANCE,
  9491. (ULONG_PTR) data,
  9492. 12,
  9493. 0
  9494. );
  9495. break;
  9496. }
  9497. case PHONE_BUTTON:
  9498. case PHONE_CLOSE:
  9499. case PHONE_DEVSPECIFIC:
  9500. case PHONE_STATE:
  9501. case PHONE_REMOVE:
  9502. (*gESPGlobals.pfnPhoneEvent)(
  9503. (HTAPIPHONE) htDevice,
  9504. (DWORD) Msg,
  9505. Param1,
  9506. Param2,
  9507. Param3
  9508. );
  9509. ShowPhoneEvent(
  9510. (HTAPIPHONE) htDevice,
  9511. (DWORD) Msg,
  9512. Param1,
  9513. Param2,
  9514. Param3
  9515. );
  9516. break;
  9517. case LINE_CREATE:
  9518. if (gESPGlobals.pLines->dwNumUsedEntries <
  9519. gESPGlobals.pLines->dwNumTotalEntries)
  9520. {
  9521. (*gESPGlobals.pfnLineEvent)(
  9522. (HTAPILINE) NULL,
  9523. (HTAPICALL) NULL,
  9524. LINE_CREATE,
  9525. (ULONG_PTR) gESPGlobals.hProvider,
  9526. (ULONG_PTR) gESPGlobals.pLines->dwNumUsedEntries,
  9527. (ULONG_PTR) 0
  9528. );
  9529. ShowLineEvent(
  9530. (HTAPILINE) NULL,
  9531. (HTAPICALL) NULL,
  9532. LINE_CREATE,
  9533. (ULONG_PTR) gESPGlobals.hProvider,
  9534. (ULONG_PTR) gESPGlobals.pLines->dwNumUsedEntries++,
  9535. (ULONG_PTR) 0
  9536. );
  9537. }
  9538. else
  9539. {
  9540. ShowStr(
  9541. TRUE,
  9542. "ERROR: attempt to send LINE_CREATE - can't create " \
  9543. "any more devices on the fly"
  9544. );
  9545. }
  9546. break;
  9547. case PHONE_CREATE:
  9548. if (gESPGlobals.pPhones->dwNumUsedEntries <
  9549. gESPGlobals.pPhones->dwNumTotalEntries)
  9550. {
  9551. (*gESPGlobals.pfnPhoneEvent)(
  9552. (HTAPIPHONE) NULL,
  9553. PHONE_CREATE,
  9554. (ULONG_PTR) gESPGlobals.hProvider,
  9555. (ULONG_PTR) gESPGlobals.pPhones->dwNumUsedEntries,
  9556. (ULONG_PTR) 0
  9557. );
  9558. ShowPhoneEvent(
  9559. (HTAPIPHONE) NULL,
  9560. PHONE_CREATE,
  9561. (ULONG_PTR) gESPGlobals.hProvider,
  9562. gESPGlobals.pPhones->dwNumUsedEntries++,
  9563. 0
  9564. );
  9565. }
  9566. else
  9567. {
  9568. ShowStr(
  9569. TRUE,
  9570. "ERROR: attempt to send PHONE_CREATE - can't create " \
  9571. "any more devices on the fly"
  9572. );
  9573. }
  9574. break;
  9575. }
  9576. return 0;
  9577. }
  9578. void
  9579. ESPGetDebugOutput(
  9580. unsigned char *pBuffer,
  9581. long *plSize
  9582. )
  9583. {
  9584. DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped;
  9585. if (IsBadWritePtr (plSize, sizeof(long)) ||
  9586. IsBadWritePtr (pBuffer, *plSize))
  9587. {
  9588. return;
  9589. }
  9590. EnterCriticalSection (&gESPGlobals.DebugBufferCritSec);
  9591. dwMoveSize =
  9592. dwTotalSize = ((DWORD) *plSize < gESPGlobals.dwDebugBufferUsedSize ?
  9593. (DWORD)*plSize : gESPGlobals.dwDebugBufferUsedSize);
  9594. if ((DWORD) (gESPGlobals.pDebugBuffer + gESPGlobals.dwDebugBufferTotalSize
  9595. - gESPGlobals.pDebugBufferOut) > dwTotalSize)
  9596. {
  9597. dwMoveSizeWrapped = 0;
  9598. }
  9599. else
  9600. {
  9601. dwMoveSize = (DWORD) (gESPGlobals.pDebugBuffer +
  9602. gESPGlobals.dwDebugBufferTotalSize - gESPGlobals.pDebugBufferOut);
  9603. dwMoveSizeWrapped = dwTotalSize - dwMoveSize;
  9604. }
  9605. CopyMemory(
  9606. pBuffer,
  9607. gESPGlobals.pDebugBufferOut,
  9608. dwMoveSize
  9609. );
  9610. if (dwMoveSizeWrapped)
  9611. {
  9612. CopyMemory(
  9613. pBuffer + dwMoveSize,
  9614. gESPGlobals.pDebugBuffer,
  9615. dwMoveSizeWrapped
  9616. );
  9617. gESPGlobals.pDebugBufferOut = gESPGlobals.pDebugBuffer +
  9618. dwMoveSizeWrapped;
  9619. }
  9620. else
  9621. {
  9622. gESPGlobals.pDebugBufferOut += dwTotalSize;
  9623. }
  9624. gESPGlobals.dwDebugBufferUsedSize -= dwTotalSize;
  9625. LeaveCriticalSection (&gESPGlobals.DebugBufferCritSec);
  9626. ResetEvent (ghDebugOutputEvent);
  9627. *plSize = (long) dwTotalSize;
  9628. }
  9629. void
  9630. ESPGetWidgetEvents(
  9631. unsigned char *pBuffer,
  9632. long *plSize
  9633. )
  9634. {
  9635. DWORD dwTotalSize, dwMoveSize, dwMoveSizeWrapped;
  9636. if (IsBadWritePtr (plSize, sizeof(long)) ||
  9637. IsBadWritePtr (pBuffer, *plSize))
  9638. {
  9639. return;
  9640. }
  9641. EnterCriticalSection (&gESPGlobals.EventBufferCritSec);
  9642. dwMoveSize =
  9643. dwTotalSize = ((DWORD) *plSize < gESPGlobals.dwEventBufferUsedSize ?
  9644. (DWORD)*plSize : gESPGlobals.dwEventBufferUsedSize);
  9645. if ((DWORD) (gESPGlobals.pEventBuffer + gESPGlobals.dwEventBufferTotalSize
  9646. - gESPGlobals.pEventBufferOut) > dwTotalSize)
  9647. {
  9648. dwMoveSizeWrapped = 0;
  9649. }
  9650. else
  9651. {
  9652. dwMoveSize = (DWORD) (gESPGlobals.pEventBuffer +
  9653. gESPGlobals.dwEventBufferTotalSize - gESPGlobals.pEventBufferOut);
  9654. dwMoveSizeWrapped = dwTotalSize - dwMoveSize;
  9655. }
  9656. CopyMemory(
  9657. pBuffer,
  9658. gESPGlobals.pEventBufferOut,
  9659. dwMoveSize
  9660. );
  9661. if (dwMoveSizeWrapped)
  9662. {
  9663. CopyMemory(
  9664. pBuffer + dwMoveSize,
  9665. gESPGlobals.pEventBuffer,
  9666. dwMoveSizeWrapped
  9667. );
  9668. gESPGlobals.pEventBufferOut = gESPGlobals.pEventBuffer +
  9669. dwMoveSizeWrapped;
  9670. }
  9671. else
  9672. {
  9673. gESPGlobals.pEventBufferOut += dwTotalSize;
  9674. }
  9675. gESPGlobals.dwEventBufferUsedSize -= dwTotalSize;
  9676. LeaveCriticalSection (&gESPGlobals.EventBufferCritSec);
  9677. ResetEvent (ghWidgetEventsEvent);
  9678. *plSize = (long) dwTotalSize;
  9679. }
  9680. long
  9681. ESPStartPBXThread(
  9682. unsigned char *pBuffer,
  9683. long lSize
  9684. )
  9685. {
  9686. long *pPBXSettings;
  9687. DWORD dwThreadID;
  9688. if ((pPBXSettings = DrvAlloc (lSize)))
  9689. {
  9690. CopyMemory (pPBXSettings, pBuffer, lSize);
  9691. gbExitPBXThread = FALSE;
  9692. if ((ghPBXThread = CreateThread(
  9693. (LPSECURITY_ATTRIBUTES) NULL,
  9694. 0,
  9695. (LPTHREAD_START_ROUTINE) PBXThread,
  9696. (LPVOID) pPBXSettings,
  9697. 0,
  9698. &dwThreadID
  9699. )))
  9700. {
  9701. return 0;
  9702. }
  9703. DrvFree (pPBXSettings);
  9704. }
  9705. return -1;
  9706. }
  9707. long
  9708. ESPStopPBXThread(
  9709. long lDummy
  9710. )
  9711. {
  9712. gbExitPBXThread = TRUE;
  9713. WaitForSingleObject (ghPBXThread, INFINITE);
  9714. CloseHandle (ghPBXThread);
  9715. ghPBXThread = NULL;
  9716. return 0;
  9717. }
  9718. void
  9719. __RPC_FAR *
  9720. __RPC_API
  9721. midl_user_allocate(
  9722. size_t len
  9723. )
  9724. {
  9725. return (DrvAlloc (len));
  9726. }
  9727. void
  9728. __RPC_API
  9729. midl_user_free(
  9730. void __RPC_FAR * ptr
  9731. )
  9732. {
  9733. DrvFree (ptr);
  9734. }
  9735. #if DBG
  9736. VOID
  9737. DbgPrt(
  9738. IN DWORD dwDbgLevel,
  9739. IN PUCHAR lpszFormat,
  9740. IN ...
  9741. )
  9742. /*++
  9743. Routine Description:
  9744. Formats the incoming debug message & calls DbgPrint
  9745. Arguments:
  9746. DbgLevel - level of message verboseness
  9747. DbgMessage - printf-style format string, followed by appropriate
  9748. list of arguments
  9749. Return Value:
  9750. --*/
  9751. {
  9752. if (dwDbgLevel <= gdwDebugLevel)
  9753. {
  9754. char buf[128] = "ESP32: ";
  9755. va_list ap;
  9756. va_start(ap, lpszFormat);
  9757. wvsprintf (&buf[7], lpszFormat, ap);
  9758. lstrcatA (buf, "\n");
  9759. OutputDebugStringA (buf);
  9760. va_end(ap);
  9761. }
  9762. }
  9763. #endif
  9764. BOOL
  9765. ScanForDWORD(
  9766. char far *pBuf,
  9767. ULONG_PTR *lpdw
  9768. )
  9769. {
  9770. char c;
  9771. BOOL bValid = FALSE;
  9772. ULONG_PTR d = 0;
  9773. while ((c = *pBuf))
  9774. {
  9775. if ((c >= '0') && (c <= '9'))
  9776. {
  9777. c -= '0';
  9778. }
  9779. else if ((c >= 'a') && (c <= 'f'))
  9780. {
  9781. c -= ('a' - 10);
  9782. }
  9783. else if ((c >= 'A') && (c <= 'F'))
  9784. {
  9785. c -= ('A' - 10);
  9786. }
  9787. else
  9788. {
  9789. break;
  9790. }
  9791. bValid = TRUE;
  9792. d *= 16;
  9793. d += (DWORD) c;
  9794. pBuf++;
  9795. }
  9796. if (bValid)
  9797. {
  9798. *lpdw = d;
  9799. }
  9800. return bValid;
  9801. }
  9802. INT_PTR
  9803. CALLBACK
  9804. ValuesDlgProc(
  9805. HWND hwnd,
  9806. UINT msg,
  9807. WPARAM wParam,
  9808. LPARAM lParam
  9809. )
  9810. {
  9811. DWORD i;
  9812. static HWND hwndCombo, hwndList1, hwndList2;
  9813. static LRESULT lLastSel;
  9814. static char szComboText[MAX_STRING_PARAM_SIZE];
  9815. static PEVENT_PARAM_HEADER pParamsHeader;
  9816. switch (msg)
  9817. {
  9818. case WM_INITDIALOG:
  9819. {
  9820. hwndList1 = GetDlgItem (hwnd, IDC_LIST1);
  9821. hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
  9822. hwndCombo = GetDlgItem (hwnd, IDC_COMBO1);
  9823. lLastSel = -1;
  9824. pParamsHeader = (PEVENT_PARAM_HEADER) lParam;
  9825. //
  9826. // Limit the max text length for the combobox's edit field
  9827. // (NOTE: A combobox ctrl actually has two child windows: a
  9828. // edit ctrl & a listbox. We need to get the hwnd of the
  9829. // child edit ctrl & send it the LIMITTEXT msg.)
  9830. //
  9831. {
  9832. HWND hwndChild = GetWindow (hwndCombo, GW_CHILD);
  9833. while (hwndChild)
  9834. {
  9835. char buf[8];
  9836. GetClassName (hwndChild, buf, 7);
  9837. if (_stricmp (buf, "edit") == 0)
  9838. {
  9839. break;
  9840. }
  9841. hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
  9842. }
  9843. SendMessage(
  9844. hwndChild,
  9845. EM_LIMITTEXT,
  9846. (WPARAM) MAX_STRING_PARAM_SIZE - 1,
  9847. 0
  9848. );
  9849. }
  9850. //
  9851. // Misc other init
  9852. //
  9853. SetWindowText (hwnd, pParamsHeader->pszDlgTitle);
  9854. for (i = 0; i < pParamsHeader->dwNumParams; i++)
  9855. {
  9856. SendMessage(
  9857. hwndList1,
  9858. LB_INSERTSTRING,
  9859. (WPARAM) -1,
  9860. (LPARAM) pParamsHeader->aParams[i].szName
  9861. );
  9862. }
  9863. break;
  9864. }
  9865. case WM_COMMAND:
  9866. {
  9867. switch (LOWORD(wParam))
  9868. {
  9869. case IDOK:
  9870. if (lLastSel != -1)
  9871. {
  9872. char buf[MAX_STRING_PARAM_SIZE];
  9873. //
  9874. // Save val of currently selected param
  9875. //
  9876. i = GetDlgItemText(
  9877. hwnd,
  9878. IDC_COMBO1,
  9879. buf,
  9880. MAX_STRING_PARAM_SIZE - 1
  9881. );
  9882. switch (pParamsHeader->aParams[lLastSel].dwType)
  9883. {
  9884. case PT_STRING:
  9885. {
  9886. LRESULT lComboSel;
  9887. lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
  9888. if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
  9889. {
  9890. pParamsHeader->aParams[lLastSel].dwValue = 0;
  9891. }
  9892. else // "Valid string"
  9893. {
  9894. strncpy(
  9895. pParamsHeader->aParams[lLastSel].buf,
  9896. buf,
  9897. MAX_STRING_PARAM_SIZE - 1
  9898. );
  9899. pParamsHeader->aParams[lLastSel].buf[MAX_STRING_PARAM_SIZE-1] = 0;
  9900. pParamsHeader->aParams[lLastSel].dwValue = (ULONG_PTR)
  9901. pParamsHeader->aParams[lLastSel].buf;
  9902. }
  9903. break;
  9904. }
  9905. case PT_DWORD:
  9906. case PT_FLAGS:
  9907. case PT_ORDINAL:
  9908. {
  9909. if (!ScanForDWORD(
  9910. buf,
  9911. &pParamsHeader->aParams[lLastSel].dwValue
  9912. ))
  9913. {
  9914. //
  9915. // Default to 0
  9916. //
  9917. pParamsHeader->aParams[lLastSel].dwValue = 0;
  9918. }
  9919. break;
  9920. }
  9921. } // switch
  9922. }
  9923. // Drop thru to IDCANCEL cleanup code
  9924. case IDCANCEL:
  9925. EndDialog (hwnd, (int)LOWORD(wParam));
  9926. break;
  9927. case IDC_LIST1:
  9928. if (HIWORD(wParam) == LBN_SELCHANGE)
  9929. {
  9930. char buf[MAX_STRING_PARAM_SIZE] = "";
  9931. LPCSTR lpstr = buf;
  9932. LRESULT lSel = SendMessage (hwndList1, LB_GETCURSEL, 0, 0);
  9933. if (lLastSel != -1)
  9934. {
  9935. //
  9936. // Save the old param value
  9937. //
  9938. i = GetWindowText(
  9939. hwndCombo,
  9940. buf,
  9941. MAX_STRING_PARAM_SIZE - 1
  9942. );
  9943. switch (pParamsHeader->aParams[lLastSel].dwType)
  9944. {
  9945. case PT_STRING:
  9946. {
  9947. LRESULT lComboSel;
  9948. lComboSel = SendMessage (hwndCombo, CB_GETCURSEL, 0,0);
  9949. if (lComboSel == 0) // "NULL string (dwXxxSize = 0)"
  9950. {
  9951. pParamsHeader->aParams[lLastSel].dwValue = 0;
  9952. }
  9953. else // "Valid string" or no sel
  9954. {
  9955. strncpy(
  9956. pParamsHeader->aParams[lLastSel].buf,
  9957. buf,
  9958. MAX_STRING_PARAM_SIZE - 1
  9959. );
  9960. pParamsHeader->aParams[lLastSel].buf
  9961. [MAX_STRING_PARAM_SIZE - 1] = 0;
  9962. pParamsHeader->aParams[lLastSel].dwValue =
  9963. (ULONG_PTR)
  9964. pParamsHeader->aParams[lLastSel].buf;
  9965. }
  9966. break;
  9967. }
  9968. case PT_DWORD:
  9969. case PT_FLAGS:
  9970. case PT_ORDINAL:
  9971. {
  9972. if (!ScanForDWORD(
  9973. buf,
  9974. &pParamsHeader->aParams[lLastSel].dwValue
  9975. ))
  9976. {
  9977. //
  9978. // Default to 0
  9979. //
  9980. pParamsHeader->aParams[lLastSel].dwValue = 0;
  9981. }
  9982. break;
  9983. }
  9984. } // switch
  9985. }
  9986. SendMessage (hwndList2, LB_RESETCONTENT, 0, 0);
  9987. SendMessage (hwndCombo, CB_RESETCONTENT, 0, 0);
  9988. switch (pParamsHeader->aParams[lSel].dwType)
  9989. {
  9990. case PT_STRING:
  9991. {
  9992. char * aszOptions[] =
  9993. {
  9994. "NUL (dwXxxSize=0)",
  9995. "Valid string"
  9996. };
  9997. for (i = 0; i < 2; i++)
  9998. {
  9999. SendMessage(
  10000. hwndCombo,
  10001. CB_INSERTSTRING,
  10002. (WPARAM) -1,
  10003. (LPARAM) aszOptions[i]
  10004. );
  10005. }
  10006. if (pParamsHeader->aParams[lSel].dwValue == 0)
  10007. {
  10008. i = 0;
  10009. buf[0] = 0;
  10010. }
  10011. else
  10012. {
  10013. i = 1;
  10014. lpstr = (LPCSTR) pParamsHeader->aParams[lSel].dwValue;
  10015. }
  10016. SendMessage (hwndCombo, CB_SETCURSEL, (WPARAM) i, 0);
  10017. break;
  10018. }
  10019. case PT_DWORD:
  10020. {
  10021. SendMessage(
  10022. hwndCombo,
  10023. CB_INSERTSTRING,
  10024. (WPARAM) -1,
  10025. (LPARAM) (char far *) "0000000"
  10026. );
  10027. if (pParamsHeader->aParams[lSel].dwDefValue)
  10028. {
  10029. //
  10030. // Add the default val string to the combo
  10031. //
  10032. wsprintfA(
  10033. buf,
  10034. "%08lx",
  10035. pParamsHeader->aParams[lSel].dwDefValue
  10036. );
  10037. SendMessage(
  10038. hwndCombo,
  10039. CB_INSERTSTRING,
  10040. (WPARAM) -1,
  10041. (LPARAM) buf
  10042. );
  10043. }
  10044. SendMessage(
  10045. hwndCombo,
  10046. CB_INSERTSTRING,
  10047. (WPARAM) -1,
  10048. (LPARAM) (char far *) "ffffffff"
  10049. );
  10050. wsprintfA(
  10051. buf,
  10052. "%08lx",
  10053. pParamsHeader->aParams[lSel].dwValue
  10054. );
  10055. break;
  10056. }
  10057. case PT_ORDINAL:
  10058. {
  10059. //
  10060. // Stick the bit flag strings in the list box
  10061. //
  10062. PLOOKUP pLookup = (PLOOKUP)
  10063. pParamsHeader->aParams[lSel].pLookup;
  10064. for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
  10065. {
  10066. SendMessage(
  10067. hwndList2,
  10068. LB_INSERTSTRING,
  10069. (WPARAM) -1,
  10070. (LPARAM) pLookup[i].lpszVal
  10071. );
  10072. if (pParamsHeader->aParams[lSel].dwValue ==
  10073. pLookup[i].dwVal)
  10074. {
  10075. SendMessage(
  10076. hwndList2,
  10077. LB_SETSEL,
  10078. (WPARAM) TRUE,
  10079. (LPARAM) MAKELPARAM((WORD)i,0)
  10080. );
  10081. }
  10082. }
  10083. SendMessage(
  10084. hwndCombo,
  10085. CB_INSERTSTRING,
  10086. (WPARAM) -1,
  10087. (LPARAM) (char far *) "select none"
  10088. );
  10089. wsprintfA(
  10090. buf,
  10091. "%08lx",
  10092. pParamsHeader->aParams[lSel].dwValue
  10093. );
  10094. break;
  10095. }
  10096. case PT_FLAGS:
  10097. {
  10098. //
  10099. // Stick the bit flag strings in the list box
  10100. //
  10101. HWND hwndList2 = GetDlgItem (hwnd, IDC_LIST2);
  10102. PLOOKUP pLookup = (PLOOKUP)
  10103. pParamsHeader->aParams[lSel].pLookup;
  10104. for (i = 0; pLookup[i].dwVal != 0xffffffff; i++)
  10105. {
  10106. SendMessage(
  10107. hwndList2,
  10108. LB_INSERTSTRING,
  10109. (WPARAM) -1,
  10110. (LPARAM) pLookup[i].lpszVal
  10111. );
  10112. if (pParamsHeader->aParams[lSel].dwValue &
  10113. pLookup[i].dwVal)
  10114. {
  10115. SendMessage(
  10116. hwndList2,
  10117. LB_SETSEL,
  10118. (WPARAM) TRUE,
  10119. (LPARAM) MAKELPARAM((WORD)i,0)
  10120. );
  10121. }
  10122. }
  10123. SendMessage(
  10124. hwndCombo,
  10125. CB_INSERTSTRING,
  10126. (WPARAM) -1,
  10127. (LPARAM) (char far *) "select none"
  10128. );
  10129. SendMessage(
  10130. hwndCombo,
  10131. CB_INSERTSTRING,
  10132. (WPARAM) -1,
  10133. (LPARAM) (char far *) "select all"
  10134. );
  10135. wsprintfA(
  10136. buf,
  10137. "%08lx",
  10138. pParamsHeader->aParams[lSel].dwValue
  10139. );
  10140. break;
  10141. }
  10142. } //switch
  10143. SetWindowText (hwndCombo, lpstr);
  10144. lLastSel = lSel;
  10145. }
  10146. break;
  10147. case IDC_LIST2:
  10148. if (HIWORD(wParam) == LBN_SELCHANGE)
  10149. {
  10150. //
  10151. // BUGBUG in the PT_ORDINAL case we should compare the
  10152. // currently selected item(s) against the previous DWORD
  10153. // val and figure out which item we need to deselect,
  10154. // if any, in order to maintain a mutex of values
  10155. //
  10156. char buf[16];
  10157. LONG i;
  10158. int far *ai;
  10159. PLOOKUP pLookup = (PLOOKUP)
  10160. pParamsHeader->aParams[lLastSel].pLookup;
  10161. ULONG_PTR dwValue = 0;
  10162. LRESULT lSelCount =
  10163. SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
  10164. ai = (int far *) DrvAlloc ((size_t)lSelCount * sizeof(int));
  10165. // fix for bug 57371
  10166. if (!ai) break;
  10167. SendMessage(
  10168. hwndList2,
  10169. LB_GETSELITEMS,
  10170. (WPARAM) lSelCount,
  10171. (LPARAM) ai
  10172. );
  10173. if (pParamsHeader->aParams[lLastSel].dwType == PT_FLAGS)
  10174. {
  10175. for (i = 0; i < lSelCount; i++)
  10176. {
  10177. dwValue |= pLookup[ai[i]].dwVal;
  10178. }
  10179. }
  10180. else // if (.dwType == PT_ORDINAL)
  10181. {
  10182. if (lSelCount == 1)
  10183. {
  10184. dwValue = pLookup[ai[0]].dwVal;
  10185. }
  10186. else if (lSelCount == 2)
  10187. {
  10188. //
  10189. // Figure out which item we need to de-select, since
  10190. // we're doing ordinals & only want 1 item selected
  10191. // at a time
  10192. //
  10193. GetWindowText (hwndCombo, buf, 16);
  10194. if (ScanForDWORD (buf, &dwValue))
  10195. {
  10196. if (pLookup[ai[0]].dwVal == dwValue)
  10197. {
  10198. SendMessage(
  10199. hwndList2,
  10200. LB_SETSEL,
  10201. 0,
  10202. (LPARAM) ai[0]
  10203. );
  10204. dwValue = pLookup[ai[1]].dwVal;
  10205. }
  10206. else
  10207. {
  10208. SendMessage(
  10209. hwndList2,
  10210. LB_SETSEL,
  10211. 0,
  10212. (LPARAM) ai[1]
  10213. );
  10214. dwValue = pLookup[ai[0]].dwVal;
  10215. }
  10216. }
  10217. else
  10218. {
  10219. // BUGBUG de-select items???
  10220. dwValue = 0;
  10221. }
  10222. }
  10223. else if (lSelCount > 2)
  10224. {
  10225. //
  10226. // Determine previous selection & de-select all the
  10227. // latest selections
  10228. //
  10229. GetDlgItemText (hwnd, IDC_COMBO1, buf, 16);
  10230. if (ScanForDWORD (buf, &dwValue))
  10231. {
  10232. for (i = 0; i < lSelCount; i++)
  10233. {
  10234. if (pLookup[ai[i]].dwVal != dwValue)
  10235. {
  10236. SendMessage(
  10237. hwndList2,
  10238. LB_SETSEL,
  10239. 0,
  10240. (LPARAM) ai[i]
  10241. );
  10242. }
  10243. }
  10244. }
  10245. else
  10246. {
  10247. // BUGBUG de-select items???
  10248. dwValue = 0;
  10249. }
  10250. }
  10251. }
  10252. DrvFree (ai);
  10253. wsprintfA (buf, "%08lx", dwValue);
  10254. SetWindowText (hwndCombo, buf);
  10255. }
  10256. break;
  10257. case IDC_COMBO1:
  10258. switch (HIWORD(wParam))
  10259. {
  10260. case CBN_SELCHANGE:
  10261. {
  10262. LRESULT lSel = SendMessage (hwndCombo, CB_GETCURSEL, 0, 0);
  10263. switch (pParamsHeader->aParams[lLastSel].dwType)
  10264. {
  10265. case PT_ORDINAL:
  10266. //
  10267. // The only option here is "select none"
  10268. //
  10269. strcpy (szComboText, "00000000");
  10270. PostMessage (hwnd, WM_USER+55, 0, 0);
  10271. break;
  10272. case PT_FLAGS:
  10273. {
  10274. BOOL bSelect = (lSel ? TRUE : FALSE);
  10275. SendMessage(
  10276. hwndList2,
  10277. LB_SETSEL,
  10278. (WPARAM) bSelect,
  10279. (LPARAM) -1
  10280. );
  10281. if (bSelect)
  10282. {
  10283. PLOOKUP pLookup = (PLOOKUP)
  10284. pParamsHeader->aParams[lLastSel].pLookup;
  10285. DWORD dwValue = 0;
  10286. int far *ai;
  10287. LONG i;
  10288. LRESULT lSelCount =
  10289. SendMessage (hwndList2, LB_GETSELCOUNT, 0, 0);
  10290. ai = (int far *) DrvAlloc(
  10291. (size_t)lSelCount * sizeof(int)
  10292. );
  10293. SendMessage(
  10294. hwndList2,
  10295. LB_GETSELITEMS,
  10296. (WPARAM) lSelCount,
  10297. (LPARAM) ai
  10298. );
  10299. for (i = 0; i < lSelCount; i++)
  10300. {
  10301. dwValue |= pLookup[ai[i]].dwVal;
  10302. }
  10303. DrvFree (ai);
  10304. wsprintfA (szComboText, "%08lx", dwValue);
  10305. }
  10306. else
  10307. {
  10308. strcpy (szComboText, "00000000");
  10309. }
  10310. PostMessage (hwnd, WM_USER+55, 0, 0);
  10311. break;
  10312. }
  10313. case PT_STRING:
  10314. if (lSel == 1)
  10315. {
  10316. strncpy(
  10317. szComboText,
  10318. pParamsHeader->aParams[lLastSel].buf,
  10319. MAX_STRING_PARAM_SIZE
  10320. );
  10321. szComboText[MAX_STRING_PARAM_SIZE-1] = 0;
  10322. }
  10323. else
  10324. {
  10325. szComboText[0] = 0;
  10326. }
  10327. PostMessage (hwnd, WM_USER+55, 0, 0);
  10328. break;
  10329. case PT_DWORD:
  10330. break;
  10331. } // switch
  10332. break;
  10333. }
  10334. case CBN_EDITCHANGE:
  10335. {
  10336. //
  10337. // If user entered text in the edit field then copy the
  10338. // text to our buffer
  10339. //
  10340. if (pParamsHeader->aParams[lLastSel].dwType == PT_STRING)
  10341. {
  10342. char buf[MAX_STRING_PARAM_SIZE];
  10343. GetWindowText (hwndCombo, buf, MAX_STRING_PARAM_SIZE);
  10344. strncpy(
  10345. pParamsHeader->aParams[lLastSel].buf,
  10346. buf,
  10347. MAX_STRING_PARAM_SIZE
  10348. );
  10349. pParamsHeader->aParams[lLastSel].buf
  10350. [MAX_STRING_PARAM_SIZE-1] = 0;
  10351. }
  10352. break;
  10353. }
  10354. } // switch
  10355. } // switch
  10356. break;
  10357. }
  10358. case WM_USER+55:
  10359. SetWindowText (hwndCombo, szComboText);
  10360. break;
  10361. case WM_CTLCOLORSTATIC:
  10362. SetBkColor ((HDC) wParam, RGB (192,192,192));
  10363. return (INT_PTR) GetStockObject (LTGRAY_BRUSH);
  10364. case WM_PAINT:
  10365. {
  10366. PAINTSTRUCT ps;
  10367. BeginPaint (hwnd, &ps);
  10368. FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
  10369. EndPaint (hwnd, &ps);
  10370. break;
  10371. }
  10372. }
  10373. return FALSE;
  10374. }
  10375. BOOL
  10376. PASCAL
  10377. IsValidESPAddress(
  10378. LPCWSTR lpszDestAddress,
  10379. PDRVLINE *ppLine,
  10380. LPDWORD pdwAddressID
  10381. )
  10382. {
  10383. char *pszDestAddress, *p, c;
  10384. BOOL bResult = FALSE;
  10385. DWORD length, dwDestLineID, dwAddressID;
  10386. if (!lpszDestAddress)
  10387. {
  10388. return FALSE;
  10389. }
  10390. //
  10391. // Convert destination address from unicode to ascii
  10392. //
  10393. length = (lstrlenW (lpszDestAddress) + 1) * sizeof (WCHAR);
  10394. if (!(pszDestAddress = DrvAlloc (length)))
  10395. {
  10396. return FALSE;
  10397. }
  10398. WideCharToMultiByte(
  10399. CP_ACP,
  10400. 0,
  10401. lpszDestAddress,
  10402. -1,
  10403. pszDestAddress,
  10404. length,
  10405. NULL,
  10406. NULL
  10407. );
  10408. p = pszDestAddress;
  10409. //
  10410. // Skip valid junk we don't care about
  10411. //
  10412. while ((*p == 'T' || *p == 'P' || *p == ' ') && (*p != '\0'))
  10413. {
  10414. p++;
  10415. }
  10416. //
  10417. // See if destination address is in the format of either
  10418. // "<esp line id>" or "<esp line id>#<esp address id>"
  10419. //
  10420. if (*p < '0' || *p > '9')
  10421. {
  10422. goto ISESPAddress_freeAddr;
  10423. }
  10424. for (dwDestLineID = 0; (c = *p); p++)
  10425. {
  10426. if (c >= '0' && c <= '9')
  10427. {
  10428. dwDestLineID *= 10;
  10429. dwDestLineID += ((DWORD)(c - '0'));
  10430. }
  10431. else
  10432. {
  10433. break;
  10434. }
  10435. }
  10436. if (c != '\0' && c != '#')
  10437. {
  10438. goto ISESPAddress_freeAddr;
  10439. }
  10440. if (dwDestLineID < gESPGlobals.dwLineDeviceIDBase ||
  10441. dwDestLineID >= (gESPGlobals.dwNumLines +
  10442. gESPGlobals.dwLineDeviceIDBase))
  10443. {
  10444. goto ISESPAddress_freeAddr;
  10445. }
  10446. if (c == '\0')
  10447. {
  10448. *pdwAddressID = 0;
  10449. goto ISESPAddress_success;
  10450. }
  10451. p++;
  10452. if (*p < '0' || *p > '9')
  10453. {
  10454. goto ISESPAddress_freeAddr;
  10455. }
  10456. for (dwAddressID = 0; (c = *p); p++)
  10457. {
  10458. if (c >= '0' && c <= '9')
  10459. {
  10460. dwAddressID *= 10;
  10461. dwAddressID += ((DWORD)(c - '0'));
  10462. }
  10463. else
  10464. {
  10465. break;
  10466. }
  10467. }
  10468. if (c != '\0' || dwAddressID >= gESPGlobals.dwNumAddressesPerLine)
  10469. {
  10470. goto ISESPAddress_freeAddr;
  10471. }
  10472. *pdwAddressID = dwAddressID;
  10473. ISESPAddress_success:
  10474. *ppLine = GetLineFromID (dwDestLineID);
  10475. bResult = TRUE;
  10476. ISESPAddress_freeAddr:
  10477. DrvFree (pszDestAddress);
  10478. return bResult;
  10479. }
  10480. LONG
  10481. PASCAL
  10482. CreateIncomingCall(
  10483. LPCWSTR lpszDestAddress,
  10484. LPLINECALLPARAMS lpCallParams,
  10485. PDRVCALL pOutgoingCall,
  10486. BOOL *pbValidESPAddress,
  10487. PDRVLINE *ppIncomingLine,
  10488. PDRVCALL *ppIncomingCall
  10489. )
  10490. {
  10491. LONG lResult;
  10492. DWORD dwIncomingAddressID;
  10493. PDRVCALL pIncomingCall;
  10494. PDRVLINE pIncomingLine;
  10495. LINECALLPARAMS callParams;
  10496. *pbValidESPAddress = FALSE;
  10497. *ppIncomingLine = NULL;
  10498. *ppIncomingCall = NULL;
  10499. if (!IsValidESPAddress(
  10500. lpszDestAddress,
  10501. &pIncomingLine,
  10502. &dwIncomingAddressID
  10503. ))
  10504. {
  10505. return LINEERR_INVALADDRESS;
  10506. }
  10507. *pbValidESPAddress = TRUE;
  10508. if (pIncomingLine->htLine == NULL ||
  10509. (pOutgoingCall &&
  10510. !(pIncomingLine->dwMediaModes & pOutgoingCall->dwMediaMode)))
  10511. {
  10512. return LINEERR_INVALMEDIAMODE;
  10513. }
  10514. if (!lpCallParams)
  10515. {
  10516. lpCallParams = &callParams;
  10517. ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
  10518. callParams.dwTotalSize = sizeof (LINECALLPARAMS);
  10519. callParams.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
  10520. callParams.dwBearerMode = LINEBEARERMODE_VOICE;
  10521. }
  10522. lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  10523. lpCallParams->dwAddressID = dwIncomingAddressID;
  10524. if ((lResult = AllocCall(
  10525. pIncomingLine,
  10526. 0,
  10527. lpCallParams,
  10528. &pIncomingCall
  10529. )) == 0)
  10530. {
  10531. if (pOutgoingCall)
  10532. {
  10533. pOutgoingCall->pDestCall = pIncomingCall;
  10534. pIncomingCall->pDestCall = pOutgoingCall;
  10535. pIncomingCall->dwCallID = pOutgoingCall->dwCallID;
  10536. pIncomingCall->dwRelatedCallID = pOutgoingCall->dwRelatedCallID;
  10537. }
  10538. *ppIncomingLine = pIncomingLine;
  10539. *ppIncomingCall = pIncomingCall;
  10540. }
  10541. else
  10542. {
  10543. ShowStr(
  10544. TRUE,
  10545. "lineMakeCall couldn't create incoming call on" \
  10546. "line/addr id %d/%d, exceeded max calls per line/addr",
  10547. pIncomingLine->dwDeviceID,
  10548. dwIncomingAddressID
  10549. );
  10550. }
  10551. return lResult;
  10552. }
  10553. void
  10554. FAR
  10555. PASCAL
  10556. TransferCall_postProcess(
  10557. PASYNC_REQUEST_INFO pAsyncReqInfo,
  10558. BOOL bAsync
  10559. )
  10560. {
  10561. DWORD dwCallInstThen = (DWORD) pAsyncReqInfo->dwParam2,
  10562. dwValidCurrentCallStates = (DWORD) pAsyncReqInfo->dwParam5,
  10563. dwNewCallState = (DWORD) pAsyncReqInfo->dwParam6,
  10564. dwCallInstNow;
  10565. PDRVCALL pCall = (PDRVCALL) pAsyncReqInfo->dwParam1,
  10566. pDestCall = (PDRVCALL) pAsyncReqInfo->dwParam4;
  10567. PDRVLINE pDestLine = (PDRVLINE) pAsyncReqInfo->dwParam3;
  10568. DoCompletion (pAsyncReqInfo, bAsync);
  10569. if (pAsyncReqInfo->lResult == 0)
  10570. {
  10571. if ((pAsyncReqInfo->lResult = SetCallState(
  10572. pCall,
  10573. dwCallInstThen,
  10574. dwValidCurrentCallStates,
  10575. LINECALLSTATE_IDLE,
  10576. 0,
  10577. TRUE
  10578. )) != 0)
  10579. {
  10580. goto TSPI_lineBlindTransfer_postProcess_freeDestCall;
  10581. }
  10582. if (pDestCall)
  10583. {
  10584. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  10585. if (IsValidDrvCall (pCall, &dwCallInstNow) &&
  10586. dwCallInstNow == dwCallInstThen)
  10587. {
  10588. SendLineEvent(
  10589. pDestLine,
  10590. NULL,
  10591. LINE_NEWCALL,
  10592. (ULONG_PTR) pDestCall,
  10593. (ULONG_PTR) &pDestCall->htCall,
  10594. 0
  10595. );
  10596. if (pDestCall->htCall)
  10597. {
  10598. SetCallState(
  10599. pDestCall,
  10600. pDestCall->dwCallInstance,
  10601. 0xffffffff,
  10602. dwNewCallState,
  10603. 0,
  10604. TRUE
  10605. );
  10606. }
  10607. else
  10608. {
  10609. FreeCall (pDestCall, pDestCall->dwCallInstance);
  10610. }
  10611. }
  10612. else
  10613. {
  10614. FreeCall (pDestCall, pDestCall->dwCallInstance);
  10615. }
  10616. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  10617. }
  10618. }
  10619. else
  10620. {
  10621. TSPI_lineBlindTransfer_postProcess_freeDestCall:
  10622. if (pDestCall)
  10623. {
  10624. FreeCall (pDestCall, pDestCall->dwCallInstance);
  10625. }
  10626. }
  10627. }
  10628. LONG
  10629. PASCAL
  10630. TransferCall(
  10631. PFUNC_INFO pInfo,
  10632. PDRVCALL pCall,
  10633. DWORD dwValidCurrentCallStates,
  10634. DWORD dwNewCallState, // initial call state of new incoming call
  10635. LPCWSTR lpszDestAddress
  10636. )
  10637. {
  10638. BOOL bValidESPAddress;
  10639. LONG lResult = 0;
  10640. PDRVLINE pDestLine;
  10641. PDRVCALL pDestCall;
  10642. EnterCriticalSection (&gESPGlobals.CallListCritSec);
  10643. if (IsValidDrvCall (pCall, NULL) == FALSE)
  10644. {
  10645. lResult = LINEERR_INVALCALLHANDLE;
  10646. }
  10647. else if ((pCall->dwCallState & dwValidCurrentCallStates) == 0)
  10648. {
  10649. lResult = LINEERR_INVALCALLSTATE;
  10650. }
  10651. else
  10652. {
  10653. PDRVCALL pDestCallOrig = pCall->pDestCall;
  10654. LINECALLPARAMS callParams;
  10655. if (IsValidDrvCall (pDestCallOrig, NULL) == FALSE)
  10656. {
  10657. pDestCallOrig = NULL;
  10658. }
  10659. ZeroMemory (&callParams, sizeof (LINECALLPARAMS));
  10660. callParams.dwTotalSize = sizeof (LINECALLPARAMS);
  10661. callParams.dwMediaMode = pCall->dwMediaMode;
  10662. callParams.dwBearerMode = pCall->dwBearerMode;
  10663. callParams.dwMinRate = pCall->dwMinRate;
  10664. callParams.dwMaxRate = pCall->dwMaxRate;
  10665. if (CreateIncomingCall(
  10666. lpszDestAddress,
  10667. &callParams,
  10668. pDestCallOrig,
  10669. &bValidESPAddress,
  10670. &pDestLine,
  10671. &pDestCall
  10672. ) == 0)
  10673. {
  10674. pCall->pDestCall = NULL;
  10675. if (pCall->dwCallDataSize &&
  10676. (pDestCall->pCallData = DrvAlloc (pCall->dwCallDataSize)))
  10677. {
  10678. CopyMemory(
  10679. pDestCall->pCallData,
  10680. pCall->pCallData,
  10681. (pDestCall->dwCallDataSize = pCall->dwCallDataSize)
  10682. );
  10683. }
  10684. }
  10685. pInfo->pAsyncReqInfo->pfnPostProcessProc = (FARPROC)
  10686. TransferCall_postProcess;
  10687. pInfo->pAsyncReqInfo->dwParam1 = (ULONG_PTR) pCall;
  10688. pInfo->pAsyncReqInfo->dwParam2 = (ULONG_PTR) pCall->dwCallInstance;
  10689. pInfo->pAsyncReqInfo->dwParam3 = (ULONG_PTR) pDestLine;
  10690. pInfo->pAsyncReqInfo->dwParam4 = (ULONG_PTR) pDestCall;
  10691. pInfo->pAsyncReqInfo->dwParam5 = (ULONG_PTR) dwValidCurrentCallStates;
  10692. pInfo->pAsyncReqInfo->dwParam6 = (ULONG_PTR) dwNewCallState;
  10693. }
  10694. LeaveCriticalSection (&gESPGlobals.CallListCritSec);
  10695. return lResult;
  10696. }