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

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