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.

14608 lines
364 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. remotesp.c
  5. Abstract:
  6. This module contains
  7. Author:
  8. Dan Knudson (DanKn) 09-Aug-1995
  9. Revision History:
  10. Notes:
  11. In a nutshell, this service provider connects to tapisrv.exe on remote
  12. pc's via the same rpc interface used by tapi32, and sends the remote
  13. tapisrv's the same kinds of requests (as defined in \dev\server\line.h
  14. & phone.h).
  15. This service provider also acts as an rpc server, receiving async event
  16. notifications from the remote tapisrv's. Remote tapisrv's call our
  17. RemoteSPAttach() function at init time (during our call to their
  18. ClientAttach() proc) to establish a binding instance, and then can call
  19. RemoteSPEventProc() to send async events. Since we don't want to block
  20. the servers for any length of time, we immediately queue the events they
  21. send us, and a dedicated thread (EventHandlerThread) services this
  22. queue.
  23. Now a brief note on handle resolution. When we open a line or a phone,
  24. we alloc our own DRVXXX structure to represent this widget, and pass
  25. tapisrv a pointer to this widget in the open request (see the
  26. hRemoteLine field in LINEOPEN_PARAMS in line.h). Then, when remote
  27. tapisrv's send us events on those lines/phones, they pass us the
  28. widget pointer we passed them (instead of the normal hLine/hPhone).
  29. This allows us to easily find and reference our data structure
  30. associated with this widget. Dealing with calls is a little more
  31. problematic, since remote tapisrv's can present incoming calls, and
  32. there is no clean way to initially specify our own handle to the call
  33. as with lines or phones. (A RemoteSPNewCall() function which would
  34. allow for this handle swapping was considered, but not implemented due
  35. to possible blocking problems on the remote server.) The solution
  36. is to maintain a list of calls in each line structure, and when call
  37. events are parsed we resolve the hCall by walking the list of calls in
  38. the corresponding line (tapisrv is nice enough to indicate our line
  39. pointer in dwParam4 of the relevant messages). Since we expect client
  40. machines using remotesp to have a relatively low call bandwidth, this
  41. look up method should be pretty fast.
  42. --*/
  43. #include <tchar.h>
  44. #include "remotesp.h"
  45. #include "imperson.h"
  46. #include "rmotsp.h"
  47. #include "dslookup.h"
  48. #include "tapihndl.h"
  49. #include "shlwapi.h"
  50. #include "utils.h"
  51. // defined in server\private.h
  52. #define TAPIERR_INVALRPCCONTEXT 0xF101
  53. #if DBG
  54. BOOL gfBreakOnSeriousProblems = FALSE;
  55. #define DrvAlloc(x) RSPAlloc(x, __LINE__, __FILE__)
  56. #else
  57. #define DrvAlloc(x) RSPAlloc(x)
  58. #endif
  59. #define MODULE_NAME "remotesp.tsp"
  60. typedef struct _ASYNCEVENTMSGRSP
  61. {
  62. DWORD TotalSize;
  63. DWORD InitContext;
  64. ULONG_PTR fnPostProcessProcHandle;
  65. DWORD hDevice;
  66. DWORD Msg;
  67. DWORD OpenContext;
  68. union {
  69. ULONG_PTR Param1;
  70. };
  71. union {
  72. ULONG_PTR Param2;
  73. };
  74. union {
  75. ULONG_PTR Param3;
  76. };
  77. union {
  78. ULONG_PTR Param4;
  79. };
  80. } ASYNCEVENTMSGRSP, *PASYNCEVENTMSGRSP;
  81. HANDLE ghRSPHeap, ghHandleTable;
  82. LIST_ENTRY gTlsListHead;
  83. #undef DWORD_CAST
  84. #if DBG
  85. #define DWORD_CAST(v,f,l) (((v)>MAXDWORD)?(DbgPrt(0,"DWORD_CAST: information will be lost during cast from %p in file %s, line %d",(v),(f),(l)), DebugBreak(),((DWORD)(v))):((DWORD)(v)))
  86. #define DWORD_CAST_HINT(v,f,l,h) (((v)>MAXDWORD)?(DbgPrt(0,"DWORD_CAST: information will be lost during cast from %p in file %s, line %d, hint %d",(v),(f),(l),(h)), DebugBreak(),((DWORD)(v))):((DWORD)(v)))
  87. #else
  88. #define DWORD_CAST(v,f,l) ((DWORD)(v))
  89. #define DWORD_CAST_HINT(v,f,l,h) ((DWORD)(v))
  90. #endif
  91. VOID
  92. CALLBACK
  93. FreeContextCallback(
  94. LPVOID Context,
  95. LPVOID Context2
  96. )
  97. {
  98. if (Context2 == (LPVOID) 1)
  99. {
  100. //
  101. // Special case: don't free the Context
  102. //
  103. }
  104. else if (Context != (LPVOID) -1)
  105. {
  106. //
  107. // The general case, Context is the pointer to free
  108. //
  109. DrvFree (Context);
  110. }
  111. }
  112. BOOL
  113. WINAPI
  114. DllMain(
  115. HANDLE hDLL,
  116. DWORD dwReason,
  117. LPVOID lpReserved
  118. )
  119. {
  120. switch (dwReason)
  121. {
  122. case DLL_PROCESS_ATTACH:
  123. {
  124. gpStaleInitContexts = NULL;
  125. gdwNumStaleInitContexts = 0;
  126. #if DBG
  127. {
  128. HKEY hTelephonyKey;
  129. DWORD dwDataSize, dwDataType;
  130. TCHAR szRemotespDebugLevel[] = "RemotespDebugLevel";
  131. RegOpenKeyEx(
  132. HKEY_LOCAL_MACHINE,
  133. gszTelephonyKey,
  134. 0,
  135. KEY_ALL_ACCESS,
  136. &hTelephonyKey
  137. );
  138. dwDataSize = sizeof (DWORD);
  139. gdwDebugLevel=0;
  140. RegQueryValueEx(
  141. hTelephonyKey,
  142. szRemotespDebugLevel,
  143. 0,
  144. &dwDataType,
  145. (LPBYTE) &gdwDebugLevel,
  146. &dwDataSize
  147. );
  148. RegCloseKey (hTelephonyKey);
  149. }
  150. #endif
  151. //
  152. //
  153. //
  154. LOG((TL_INFO, "DLL_PROCESS_ATTACH"));
  155. ghInst = hDLL;
  156. //
  157. // Allocate a private heap (use process heap if that fails)
  158. //
  159. if (!(ghRSPHeap = HeapCreate(
  160. 0, // return NULL on failure, serialize access
  161. 0x1000, // initial heap size
  162. 0 // max heap size (0 == growable)
  163. )))
  164. {
  165. ghRSPHeap = GetProcessHeap();
  166. }
  167. //
  168. //
  169. //
  170. if (!(ghHandleTable = CreateHandleTable(
  171. ghRSPHeap,
  172. FreeContextCallback,
  173. 0x10000000,
  174. 0x7fffffff
  175. )))
  176. {
  177. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, CreateHandleTable() failed"));
  178. return FALSE;
  179. }
  180. //
  181. // Alloc a Tls index
  182. //
  183. if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
  184. {
  185. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, TlsAlloc() failed"));
  186. return FALSE;
  187. }
  188. //
  189. // Initialize Tls to NULL for this thread
  190. //
  191. TlsSetValue (gdwTlsIndex, NULL);
  192. //
  193. // Init a couple of critical sections for serializing
  194. // access to resources
  195. //
  196. InitializeCriticalSection (&gEventBufferCriticalSection);
  197. InitializeCriticalSection (&gCallListCriticalSection);
  198. InitializeCriticalSection (&gcsTlsList);
  199. TapiInitializeCriticalSectionAndSpinCount (&gCriticalSection, 100);
  200. InitializeListHead (&gTlsListHead);
  201. //
  202. // Load the device icons
  203. //
  204. {
  205. HINSTANCE hUser;
  206. typedef HICON ( WINAPI PLOADICON(
  207. HINSTANCE hInstance,
  208. LPCTSTR lpIconName
  209. ));
  210. PLOADICON *pLoadIcon;
  211. hUser = LoadLibrary( "USER32.DLL" );
  212. if ( NULL == hUser )
  213. {
  214. LOG((TL_ERROR, "Couldn't load USER32.DLL!!"));
  215. break;
  216. }
  217. pLoadIcon = (PLOADICON *)GetProcAddress( hUser, "LoadIconA");
  218. if ( NULL == pLoadIcon )
  219. {
  220. LOG((TL_ERROR, "Couldn't load LoadIconA()!!"));
  221. FreeLibrary( hUser );
  222. break;
  223. }
  224. ghLineIcon = pLoadIcon( hDLL, MAKEINTRESOURCE(IDI_ICON3) );
  225. ghPhoneIcon = pLoadIcon( hDLL, MAKEINTRESOURCE(IDI_ICON2) );
  226. FreeLibrary( hUser );
  227. }
  228. gEventHandlerThreadParams.hMailslot = INVALID_HANDLE_VALUE;
  229. break;
  230. }
  231. case DLL_PROCESS_DETACH:
  232. {
  233. PRSP_THREAD_INFO pTls;
  234. LOG((TL_INFO, "DLL_PROCESS_DETACH"));
  235. //
  236. // Clean up any Tls (no need to enter crit sec since process detaching)
  237. //
  238. while (!IsListEmpty (&gTlsListHead))
  239. {
  240. LIST_ENTRY *pEntry = RemoveHeadList (&gTlsListHead);
  241. pTls = CONTAINING_RECORD (pEntry, RSP_THREAD_INFO, TlsList);
  242. DrvFree (pTls->pBuf);
  243. DrvFree (pTls);
  244. }
  245. TlsFree (gdwTlsIndex);
  246. //
  247. // Free the critical sections & icons
  248. //
  249. DeleteCriticalSection (&gEventBufferCriticalSection);
  250. DeleteCriticalSection (&gCallListCriticalSection);
  251. DeleteCriticalSection (&gcsTlsList);
  252. TapiDeleteCriticalSection (&gCriticalSection);
  253. {
  254. HINSTANCE hUser;
  255. typedef BOOL ( WINAPI PDESTROYICON(
  256. HICON hIcon
  257. ));
  258. PDESTROYICON *pDestroyIcon;
  259. hUser = LoadLibrary( "USER32.DLL" );
  260. if ( NULL == hUser )
  261. {
  262. LOG((TL_ERROR, "Couldn't load USER32.DLL!!d"));
  263. break;
  264. }
  265. pDestroyIcon = (PDESTROYICON *)GetProcAddress( hUser, "DestroyIcon");
  266. if ( NULL == pDestroyIcon )
  267. {
  268. LOG((TL_ERROR, "Couldn't load DestroyIcon()!!"));
  269. FreeLibrary( hUser );
  270. break;
  271. }
  272. pDestroyIcon (ghLineIcon);
  273. pDestroyIcon (ghPhoneIcon);
  274. FreeLibrary( hUser );
  275. }
  276. DeleteHandleTable (ghHandleTable);
  277. if (ghRSPHeap != GetProcessHeap())
  278. {
  279. HeapDestroy (ghRSPHeap);
  280. }
  281. break;
  282. }
  283. case DLL_THREAD_ATTACH:
  284. //
  285. // Initialize Tls to NULL for this thread
  286. //
  287. TlsSetValue (gdwTlsIndex, NULL);
  288. break;
  289. case DLL_THREAD_DETACH:
  290. {
  291. PRSP_THREAD_INFO pTls;
  292. //
  293. // Clean up any Tls
  294. //
  295. if ((pTls = (PRSP_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
  296. {
  297. EnterCriticalSection (&gcsTlsList);
  298. RemoveEntryList (&pTls->TlsList);
  299. LeaveCriticalSection (&gcsTlsList);
  300. if (pTls->pBuf)
  301. {
  302. DrvFree (pTls->pBuf);
  303. }
  304. DrvFree (pTls);
  305. }
  306. break;
  307. }
  308. } // switch
  309. return TRUE;
  310. }
  311. BOOL
  312. PASCAL
  313. IsValidObject(
  314. PVOID pObject,
  315. DWORD dwKey
  316. )
  317. {
  318. BOOL fResult;
  319. try
  320. {
  321. fResult = (*((LPDWORD) pObject) == dwKey);
  322. }
  323. except (EXCEPTION_EXECUTE_HANDLER)
  324. {
  325. fResult = FALSE;
  326. }
  327. return fResult;
  328. }
  329. void LogRemoteSPError(CHAR * szServer, DWORD dwErrorContext,
  330. DWORD dwErrorCode, DWORD dwErrorDet,
  331. BOOL bNoKeyCreation)
  332. {
  333. HKEY hKeyServer = NULL;
  334. DWORD dwDisposition;
  335. CHAR szRegKeyServer[255];
  336. if (!szServer)
  337. {
  338. goto ExitHere;
  339. }
  340. wsprintf(szRegKeyServer, "%s\\Provider%d\\",
  341. gszTelephonyKey, gdwPermanentProviderID);
  342. lstrcat(szRegKeyServer, szServer);
  343. if (bNoKeyCreation)
  344. {
  345. // If the logging is requested from NetworkPollThread
  346. // do not create ProviderN key if not exist already
  347. if (ERROR_SUCCESS != RegOpenKeyEx (
  348. HKEY_LOCAL_MACHINE,
  349. szRegKeyServer,
  350. 0,
  351. KEY_WRITE,
  352. &hKeyServer
  353. ))
  354. {
  355. goto ExitHere;
  356. }
  357. }
  358. else
  359. {
  360. if (ERROR_SUCCESS != RegCreateKeyEx(
  361. HKEY_LOCAL_MACHINE,
  362. szRegKeyServer,
  363. 0,
  364. NULL,
  365. REG_OPTION_NON_VOLATILE,
  366. KEY_WRITE,
  367. NULL,
  368. &hKeyServer,
  369. &dwDisposition))
  370. {
  371. goto ExitHere;
  372. }
  373. }
  374. RegSetValueExW (hKeyServer,
  375. L"ErrorContext",
  376. 0,
  377. REG_DWORD,
  378. (LPBYTE)&dwErrorContext,
  379. sizeof(dwErrorContext));
  380. RegSetValueExW (hKeyServer,
  381. L"ErrorCode",
  382. 0,
  383. REG_DWORD,
  384. (LPBYTE)&dwErrorCode,
  385. sizeof(dwErrorCode));
  386. RegSetValueExW (hKeyServer,
  387. L"ErrorDetail",
  388. 0,
  389. REG_DWORD,
  390. (LPBYTE)&dwErrorDet,
  391. sizeof(dwErrorCode));
  392. ExitHere:
  393. if (hKeyServer)
  394. {
  395. RegCloseKey(hKeyServer);
  396. }
  397. return;
  398. }
  399. //
  400. // Function get called when the remotesp lost connection with the
  401. // remote server and the status is detected
  402. //
  403. LONG
  404. OnServerDisconnected(PDRVSERVER pServer)
  405. {
  406. LONG lResult = 0;
  407. TapiEnterCriticalSection(&gCriticalSection);
  408. if ( gEventHandlerThreadParams.bExit )
  409. {
  410. goto ExitHere;
  411. }
  412. //
  413. // It is possible we come here durning FinishEnumDevices
  414. // in which case pServer is not in any double link list
  415. //
  416. if (pServer->ServerList.Flink == NULL ||
  417. pServer->ServerList.Blink == NULL)
  418. {
  419. goto ExitHere;
  420. }
  421. //
  422. // Bail if not transiting from connected to disconnected state
  423. // otherwise set the disconnection flag
  424. //
  425. if (pServer->dwFlags & SERVER_DISCONNECTED)
  426. {
  427. goto ExitHere;
  428. }
  429. pServer->dwFlags |= SERVER_DISCONNECTED;
  430. TapiLeaveCriticalSection (&gCriticalSection);
  431. //
  432. // Leave Shutdown() outside of the CS to avoid deadlock
  433. //
  434. Shutdown (pServer);
  435. TapiEnterCriticalSection(&gCriticalSection);
  436. if ( gEventHandlerThreadParams.bExit )
  437. {
  438. goto ExitHere;
  439. }
  440. //
  441. // Put this server into the gNptListHead so that the
  442. // NetworkPollThread will try to re-establish the connection
  443. //
  444. RemoveEntryList (&pServer->ServerList);
  445. InsertTailList (&gNptListHead, &pServer->ServerList);
  446. //
  447. // Start the NetworkPollThread if not started yet
  448. //
  449. if (ghNetworkPollThread == NULL)
  450. {
  451. DWORD dwTID;
  452. ghNptShutdownEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  453. if (!ghNptShutdownEvent)
  454. {
  455. LOG((TL_ERROR, "OnServerDisconnected: Unable to create poll thread! Argh!"));
  456. }
  457. else
  458. {
  459. if (!(ghNetworkPollThread = CreateThread(
  460. NULL,
  461. 0,
  462. (LPTHREAD_START_ROUTINE) NetworkPollThread,
  463. (LPVOID) gpszThingToPassToServer,
  464. 0,
  465. &dwTID
  466. )))
  467. {
  468. LOG((TL_ERROR, "OnServerDisconnected: Unable to create poll thread! Argh!"));
  469. CloseHandle (ghNptShutdownEvent);
  470. ghNptShutdownEvent = NULL;
  471. }
  472. }
  473. if (!ghNptShutdownEvent || !ghNetworkPollThread)
  474. {
  475. // Failed to create Network Poll Thread
  476. // Ignore this server
  477. while (!IsListEmpty (&gNptListHead))
  478. {
  479. PDRVSERVER pServer;
  480. LIST_ENTRY *pEntry = RemoveHeadList (&gNptListHead);
  481. pServer = CONTAINING_RECORD (pEntry, DRVSERVER, ServerList);
  482. DereferenceObject(ghHandleTable, pServer->InitContext, 1);
  483. }
  484. }
  485. }
  486. ExitHere:
  487. TapiLeaveCriticalSection (&gCriticalSection);
  488. return lResult;
  489. }
  490. //
  491. // Function get called when remotesp is able to re-establis the
  492. // connection with the remote server after losing it
  493. //
  494. LONG
  495. OnServerConnected(PDRVSERVER pServer)
  496. {
  497. LONG lResult = 0;
  498. //
  499. // Clear the disconnection bit
  500. //
  501. TapiEnterCriticalSection(&gCriticalSection);
  502. pServer->dwFlags &= (~SERVER_DISCONNECTED);
  503. pServer->bShutdown = FALSE;
  504. TapiLeaveCriticalSection(&gCriticalSection);
  505. return lResult;
  506. }
  507. PASYNCEVENTMSG
  508. GetEventFromQueue(
  509. )
  510. {
  511. BOOL bAllocFailed = FALSE;
  512. DWORD dwMsgSize, dwUsedSize, dwMoveSize, dwMoveSizeReal,
  513. dwMoveSizeWrapped, dwMoveSizeWrappedReal;
  514. PASYNCEVENTMSG pMsg;
  515. //
  516. // Enter the critical section to serialize access to the event
  517. // queue, and grab an event from the queue. Copy it to our local
  518. // event buf so that we can leave the critical section asap and
  519. // not block other threads writing to the queue.
  520. //
  521. EnterCriticalSection (&gEventBufferCriticalSection);
  522. //
  523. // If there are no events in the queue return NULL
  524. //
  525. if (gEventHandlerThreadParams.dwEventBufferUsedSize == 0)
  526. {
  527. GetEventFromQueue_noEvents:
  528. pMsg = NULL;
  529. //
  530. // Take this opportunity to tidy up a bit. The reasoning for doing
  531. // this is that we should be reducing the odds we'll have to wrap
  532. // at the end of the buffer, or at least, put off dealing with such
  533. // things until later (as the non-wrap code executes quickest)
  534. //
  535. gEventHandlerThreadParams.pDataOut =
  536. gEventHandlerThreadParams.pDataIn =
  537. gEventHandlerThreadParams.pEventBuffer;
  538. ResetEvent (gEventHandlerThreadParams.hEvent);
  539. goto GetEventFromQueue_done;
  540. }
  541. //
  542. // Determine the size of this msg & the num bytes to the end of the
  543. // event buffer, then from these get the MoveSize & MoveSizeWrapped
  544. // values
  545. //
  546. dwMsgSize = (DWORD) ((PASYNCEVENTMSG)
  547. gEventHandlerThreadParams.pDataOut)->TotalSize;
  548. if ((dwMsgSize & 0x3) ||
  549. (dwMsgSize > gEventHandlerThreadParams.dwEventBufferTotalSize))
  550. {
  551. //
  552. // Something is corrupt (the msg or our queue), so just nuke
  553. // everything in the queue and bail out
  554. //
  555. LOG((TL_ERROR, "GetEventFromQueue: ERROR! bad msgSize=x%x", dwMsgSize));
  556. gEventHandlerThreadParams.dwEventBufferUsedSize = 0;
  557. goto GetEventFromQueue_noEvents;
  558. }
  559. dwUsedSize = (DWORD) ((gEventHandlerThreadParams.pEventBuffer +
  560. gEventHandlerThreadParams.dwEventBufferTotalSize) -
  561. gEventHandlerThreadParams.pDataOut);
  562. if (dwMsgSize <= dwUsedSize)
  563. {
  564. dwMoveSize = dwMoveSizeReal = dwMsgSize;
  565. dwMoveSizeWrapped = 0;
  566. }
  567. else
  568. {
  569. dwMoveSize = dwMoveSizeReal = dwUsedSize;
  570. dwMoveSizeWrapped = dwMoveSizeWrappedReal = dwMsgSize - dwUsedSize;
  571. }
  572. //
  573. // See if we need to grow the msg buffer before we copy
  574. //
  575. if (dwMsgSize > gEventHandlerThreadParams.dwMsgBufferTotalSize)
  576. {
  577. if ((pMsg = DrvAlloc (dwMsgSize)))
  578. {
  579. DrvFree (gEventHandlerThreadParams.pMsgBuffer);
  580. gEventHandlerThreadParams.pMsgBuffer = (LPBYTE) pMsg;
  581. gEventHandlerThreadParams.dwMsgBufferTotalSize = dwMsgSize;
  582. }
  583. else
  584. {
  585. //
  586. // Couldn't alloc a bigger buf, so try to complete this
  587. // msg as gracefully as possible, i.e. set the XxxReal
  588. // vars so that we'll only actually copy over the fixed
  589. // size of the msg (but the event buf ptrs will still
  590. // get updated correctly) and set a flag to say that
  591. // we need to do some munging on the msg before returning
  592. //
  593. dwMoveSizeReal = (dwMoveSizeReal <= sizeof (ASYNCEVENTMSG) ?
  594. dwMoveSizeReal : sizeof (ASYNCEVENTMSG));
  595. dwMoveSizeWrappedReal = (dwMoveSizeReal < sizeof (ASYNCEVENTMSG) ?
  596. sizeof (ASYNCEVENTMSG) - dwMoveSizeReal : 0);
  597. bAllocFailed = TRUE;
  598. }
  599. }
  600. //
  601. // Copy the msg from the event buf to the msg buf, and update the
  602. // event buf pointers
  603. //
  604. pMsg = (PASYNCEVENTMSG) gEventHandlerThreadParams.pMsgBuffer;
  605. CopyMemory (pMsg, gEventHandlerThreadParams.pDataOut, dwMoveSizeReal);
  606. if (dwMoveSizeWrapped)
  607. {
  608. CopyMemory(
  609. ((LPBYTE) pMsg) + dwMoveSizeReal,
  610. gEventHandlerThreadParams.pEventBuffer,
  611. dwMoveSizeWrappedReal
  612. );
  613. gEventHandlerThreadParams.pDataOut =
  614. gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
  615. }
  616. else
  617. {
  618. gEventHandlerThreadParams.pDataOut += dwMoveSize;
  619. //
  620. // If msg ran to end of the event buffer then reset pDataOut
  621. //
  622. if (gEventHandlerThreadParams.pDataOut >=
  623. (gEventHandlerThreadParams.pEventBuffer +
  624. gEventHandlerThreadParams.dwEventBufferTotalSize))
  625. {
  626. gEventHandlerThreadParams.pDataOut =
  627. gEventHandlerThreadParams.pEventBuffer;
  628. }
  629. }
  630. gEventHandlerThreadParams.dwEventBufferUsedSize -= dwMsgSize;
  631. //
  632. // Special msg param munging in case an attempt to grow the
  633. // buffer size above failed
  634. //
  635. if (bAllocFailed)
  636. {
  637. switch (pMsg->Msg)
  638. {
  639. case LINE_REPLY:
  640. pMsg->Param2 = LINEERR_NOMEM;
  641. break;
  642. case PHONE_REPLY:
  643. pMsg->Param2 = PHONEERR_NOMEM;
  644. break;
  645. default:
  646. break;
  647. }
  648. }
  649. GetEventFromQueue_done:
  650. LeaveCriticalSection (&gEventBufferCriticalSection);
  651. return pMsg;
  652. }
  653. BOOL
  654. GetEventsFromServer(
  655. DWORD dwInitContext
  656. )
  657. {
  658. BOOL bResult = FALSE;
  659. DWORD dwUsedSize, dwRetryCount;
  660. PDRVSERVER pServer;
  661. PTAPI32_MSG pMsg;
  662. if (!(pServer = (PDRVSERVER) ReferenceObject(
  663. ghHandleTable,
  664. dwInitContext,
  665. gdwDrvServerKey
  666. )) ||
  667. pServer->bShutdown)
  668. {
  669. LOG((TL_ERROR, "GetEventsFromServer: bad InitContext=x%x", dwInitContext));
  670. if (pServer)
  671. {
  672. DereferenceObject (ghHandleTable, dwInitContext, 1);
  673. }
  674. return FALSE;
  675. }
  676. getEvents:
  677. dwRetryCount = 0;
  678. pMsg = (PTAPI32_MSG) gEventHandlerThreadParams.pMsgBuffer;
  679. do
  680. {
  681. pMsg->u.Req_Func = xGetAsyncEvents;
  682. pMsg->Params[0] = gEventHandlerThreadParams.dwMsgBufferTotalSize -
  683. sizeof (TAPI32_MSG);
  684. dwUsedSize = sizeof (TAPI32_MSG);
  685. RpcTryExcept
  686. {
  687. ClientRequest(
  688. pServer->phContext,
  689. (char *) pMsg,
  690. gEventHandlerThreadParams.dwMsgBufferTotalSize,
  691. &dwUsedSize
  692. );
  693. if (pMsg->u.Ack_ReturnValue == TAPIERR_INVALRPCCONTEXT)
  694. {
  695. OnServerDisconnected (pServer);
  696. pMsg->u.Ack_ReturnValue = LINEERR_OPERATIONFAILED;
  697. }
  698. dwRetryCount = gdwRetryCount;
  699. }
  700. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  701. {
  702. LOG((TL_INFO,
  703. "GetEventsFromServer: rpc exception %d handled",
  704. RpcExceptionCode()
  705. ));
  706. dwRetryCount++;
  707. if (dwRetryCount < gdwRetryCount)
  708. {
  709. Sleep (gdwRetryTimeout);
  710. }
  711. else
  712. {
  713. unsigned long ulResult = RpcExceptionCode();
  714. if ((ulResult == RPC_S_SERVER_UNAVAILABLE) ||
  715. (ulResult == ERROR_INVALID_HANDLE))
  716. {
  717. OnServerDisconnected (pServer);
  718. LOG((TL_ERROR,
  719. "GetEventsFromServer: server '%s' unavailable",
  720. pServer->szServerName
  721. ));
  722. }
  723. pMsg->u.Ack_ReturnValue = LINEERR_OPERATIONFAILED;
  724. }
  725. }
  726. RpcEndExcept
  727. } while (dwRetryCount < gdwRetryCount);
  728. if (pMsg->u.Ack_ReturnValue == 0)
  729. {
  730. DWORD dwNeededSize = (DWORD) pMsg->Params[1],
  731. dwUsedSize = (DWORD) pMsg->Params[2];
  732. if (dwUsedSize)
  733. {
  734. RemoteSPEventProc(
  735. (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface),
  736. (unsigned char *) (pMsg + 1),
  737. dwUsedSize
  738. );
  739. //
  740. // RemoteSPEventProc will set the byte pointed to by (pMsg+1)
  741. // to non-zero on success, or zero on error (indicating
  742. // bad data in the event buffer, which we'll discard)
  743. //
  744. if (*((unsigned char *) (pMsg + 1)) != 0)
  745. {
  746. bResult = TRUE;
  747. }
  748. else
  749. {
  750. bResult = FALSE;
  751. goto GetEventsFromServer_dereference;
  752. }
  753. }
  754. if (dwNeededSize > dwUsedSize)
  755. {
  756. //
  757. // There's still more data to retrieve on the server.
  758. // Grow the buffer so we can get it all next time.
  759. //
  760. DWORD dwNewSize = dwNeededSize + 256;
  761. LPVOID p;
  762. if ((p = DrvAlloc (dwNewSize)))
  763. {
  764. DrvFree (gEventHandlerThreadParams.pMsgBuffer);
  765. gEventHandlerThreadParams.pMsgBuffer = p;
  766. gEventHandlerThreadParams.dwMsgBufferTotalSize = dwNewSize;
  767. }
  768. else if (dwUsedSize == 0)
  769. {
  770. }
  771. goto getEvents;
  772. }
  773. }
  774. GetEventsFromServer_dereference:
  775. DereferenceObject (ghHandleTable, dwInitContext, 1);
  776. return bResult;
  777. }
  778. void
  779. EventHandlerThread(
  780. LPVOID pParams
  781. )
  782. {
  783. //
  784. // NOTES:
  785. //
  786. // 1. depending on server side implementation, we may experience race
  787. // conditions where msgs that we expect to show up in a certain
  788. // sequence show up out of sequence (i.e. call state msgs that show
  789. // up before make call completion msgs), which could present problems.
  790. //
  791. // one solution is to to queue call state/info msgs to incomplete
  792. // calls (to be sent after call is completed). another is not to send
  793. // any call state msgs after the idle is received
  794. //
  795. DWORD dwMsgSize, dwNumObjects, dwResult, dwData,
  796. dwNumBytesRead, dwTimeout;
  797. HANDLE ahObjects[2];
  798. OVERLAPPED overlapped;
  799. PASYNCEVENTMSG pMsg;
  800. HANDLE hProcess;
  801. LOG((TL_INFO, "EventHandlerThread: enter"));
  802. //
  803. // This thread has no user context, which prevents it from rpc'ing
  804. // back to remote tapisrv when/if necessary. So, find the user
  805. // that is logged on and impersonate them in this thread.
  806. //
  807. if (!GetCurrentlyLoggedOnUser (&hProcess))
  808. {
  809. LOG((TL_ERROR, "GetCurrentlyLoggedOnUser failed"));
  810. }
  811. else
  812. {
  813. if (!SetProcessImpersonationToken(hProcess))
  814. {
  815. LOG((TL_ERROR, "SetProcessImpersonationToken failed"));
  816. }
  817. }
  818. //
  819. // Bump up the thread priority a bit so we don't get starved by
  820. // ill-behaved apps
  821. //
  822. if (!SetThreadPriority(
  823. GetCurrentThread(),
  824. THREAD_PRIORITY_ABOVE_NORMAL
  825. ))
  826. {
  827. LOG((TL_ERROR,
  828. "EventHandlerThread: SetThreadPriority failed, err=%d",
  829. GetLastError()
  830. ));
  831. }
  832. ahObjects[0] = gEventHandlerThreadParams.hEvent;
  833. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  834. {
  835. ZeroMemory (&overlapped, sizeof (overlapped));
  836. ahObjects[1] =
  837. overlapped.hEvent = gEventHandlerThreadParams.hMailslotEvent;
  838. dwNumObjects = 2;
  839. if (!ReadFile(
  840. gEventHandlerThreadParams.hMailslot,
  841. &dwData,
  842. sizeof (dwData),
  843. &dwNumBytesRead,
  844. &overlapped
  845. )
  846. && (GetLastError() != ERROR_IO_PENDING))
  847. {
  848. LOG((TL_ERROR,
  849. "EventHandlerThread: ReadFile failed, err=%d",
  850. GetLastError()
  851. ));
  852. }
  853. dwTimeout = MAX_MAILSLOT_TIMEOUT;
  854. }
  855. else
  856. {
  857. dwNumObjects = 1;
  858. dwTimeout = INFINITE;
  859. }
  860. while (1)
  861. {
  862. //
  863. // Wait for an event to show up in the queue or for a msg
  864. // to show up in the mailslot
  865. //
  866. dwResult = WaitForMultipleObjects(
  867. dwNumObjects,
  868. ahObjects,
  869. FALSE,
  870. dwTimeout
  871. );
  872. if (gEventHandlerThreadParams.bExit)
  873. {
  874. break;
  875. }
  876. switch (dwResult)
  877. {
  878. case WAIT_OBJECT_0:
  879. //
  880. // Simply break & process the events
  881. //
  882. break;
  883. case WAIT_OBJECT_0+1:
  884. //
  885. // Post another read, the retrieve & process the events
  886. //
  887. if (!ReadFile(
  888. gEventHandlerThreadParams.hMailslot,
  889. &dwData,
  890. sizeof (dwData),
  891. &dwNumBytesRead,
  892. &overlapped
  893. )
  894. && (GetLastError() != ERROR_IO_PENDING))
  895. {
  896. LOG((TL_ERROR,
  897. "EventHandlerThread: ReadFile failed, err=%d",
  898. GetLastError()
  899. ));
  900. }
  901. if (GetEventsFromServer (dwData))
  902. {
  903. dwTimeout = MIN_MAILSLOT_TIMEOUT;
  904. }
  905. break;
  906. case WAIT_TIMEOUT:
  907. {
  908. #define DWORD_ARRAY_BLOCK_SIZE 128
  909. //
  910. // Check to see if any of the mailslot servers have
  911. // events waiting for us
  912. //
  913. BOOL bGotSomeEvents = FALSE;
  914. PDRVSERVER pServer;
  915. LIST_ENTRY * pEntry;
  916. DWORD * pArray = NULL;
  917. DWORD * pTempArray = NULL;
  918. DWORD dwEntriesCount = 0;
  919. DWORD dwEntriesUsed = 0;
  920. DWORD dwIdx;
  921. BOOL bAddOK;
  922. pArray = (DWORD *) DrvAlloc ( sizeof(DWORD) * DWORD_ARRAY_BLOCK_SIZE );
  923. if ( pArray )
  924. {
  925. dwEntriesCount = DWORD_ARRAY_BLOCK_SIZE;
  926. }
  927. TapiEnterCriticalSection(&gCriticalSection);
  928. for(
  929. pEntry = gpCurrentInitContext->ServerList.Flink;
  930. pEntry != &gpCurrentInitContext->ServerList;
  931. // null op
  932. )
  933. {
  934. PDRVSERVER pServer;
  935. pServer = CONTAINING_RECORD(
  936. pEntry,
  937. DRVSERVER,
  938. ServerList
  939. );
  940. pEntry = pEntry->Flink;
  941. if (!pServer->bConnectionOriented &&
  942. pServer->dwFlags == 0)
  943. {
  944. //
  945. // if possible, store the InitContext and postpone
  946. // the RPC call for after we leave the Crit. Sec.
  947. //
  948. bAddOK = FALSE;
  949. if ( pArray )
  950. {
  951. if ( dwEntriesCount == dwEntriesUsed )
  952. {
  953. //
  954. // need to increase the array size
  955. //
  956. pTempArray = (DWORD *) DrvAlloc (
  957. sizeof(DWORD) * (DWORD_ARRAY_BLOCK_SIZE + dwEntriesCount)
  958. );
  959. if ( pTempArray )
  960. {
  961. bAddOK = TRUE;
  962. CopyMemory(
  963. pTempArray,
  964. pArray,
  965. sizeof(DWORD) * dwEntriesCount
  966. );
  967. dwEntriesCount += DWORD_ARRAY_BLOCK_SIZE;
  968. DrvFree( pArray );
  969. pArray = pTempArray;
  970. }
  971. }
  972. else
  973. {
  974. bAddOK = TRUE;
  975. }
  976. if ( bAddOK )
  977. {
  978. pArray[ dwEntriesUsed++ ] = pServer->InitContext;
  979. }
  980. }
  981. if ( !bAddOK )
  982. {
  983. if (GetEventsFromServer (pServer->InitContext))
  984. {
  985. bGotSomeEvents = TRUE;
  986. }
  987. }
  988. }
  989. }
  990. TapiLeaveCriticalSection(&gCriticalSection);
  991. if ( pArray )
  992. {
  993. for( dwIdx = 0; dwIdx < dwEntriesUsed; dwIdx++ )
  994. {
  995. if (GetEventsFromServer (pArray[ dwIdx ]))
  996. {
  997. bGotSomeEvents = TRUE;
  998. }
  999. }
  1000. DrvFree( pArray );
  1001. }
  1002. if (bGotSomeEvents)
  1003. {
  1004. dwTimeout = MIN_MAILSLOT_TIMEOUT;
  1005. }
  1006. else if (dwTimeout < MAX_MAILSLOT_TIMEOUT)
  1007. {
  1008. dwTimeout += 500;
  1009. }
  1010. break;
  1011. }
  1012. default:
  1013. //
  1014. // Print a dbg msg & process any available events
  1015. //
  1016. LOG((TL_ERROR,
  1017. "EventHandlerThread: WaitForMultObjs failed, result=%d/err=%d",
  1018. dwResult,
  1019. GetLastError()
  1020. ));
  1021. break;
  1022. }
  1023. //
  1024. // Process the events in the queue
  1025. //
  1026. while ((pMsg = GetEventFromQueue()))
  1027. {
  1028. //
  1029. // First validate the pDrvServer pointer in the msg
  1030. //
  1031. PDRVLINE pLine;
  1032. PDRVPHONE pPhone;
  1033. PDRVSERVER pServer;
  1034. if (!(pServer = ReferenceObject(
  1035. ghHandleTable,
  1036. pMsg->InitContext,
  1037. gdwDrvServerKey
  1038. )))
  1039. {
  1040. LOG((TL_ERROR,
  1041. "EventHandlerThread: bad InitContext=x%x in msg",
  1042. pMsg->InitContext
  1043. ));
  1044. continue;
  1045. }
  1046. switch (pMsg->Msg)
  1047. {
  1048. case LINE_CREATEDIALOGINSTANCE:
  1049. break;
  1050. case LINE_PROXYREQUEST:
  1051. break;
  1052. case LINE_ADDRESSSTATE:
  1053. case LINE_AGENTSTATUS:
  1054. case LINE_AGENTSESSIONSTATUS:
  1055. case LINE_QUEUESTATUS:
  1056. case LINE_AGENTSTATUSEX:
  1057. case LINE_GROUPSTATUS:
  1058. case LINE_PROXYSTATUS:
  1059. if ((pLine = ReferenceObject(
  1060. ghHandleTable,
  1061. pMsg->hDevice,
  1062. DRVLINE_KEY
  1063. )))
  1064. {
  1065. (*gpfnLineEventProc)(
  1066. pLine->htLine,
  1067. 0,
  1068. pMsg->Msg,
  1069. pMsg->Param1,
  1070. pMsg->Param2,
  1071. pMsg->Param3
  1072. );
  1073. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1074. }
  1075. break;
  1076. case LINE_AGENTSPECIFIC:
  1077. {
  1078. DWORD hDeviceCallback = (DWORD) (pMsg->Param4 ?
  1079. pMsg->Param4 : pMsg->hDevice);
  1080. PDRVCALL pCall;
  1081. HTAPICALL htCall;
  1082. if (!(pLine = ReferenceObject(
  1083. ghHandleTable,
  1084. hDeviceCallback,
  1085. DRVLINE_KEY
  1086. )))
  1087. {
  1088. break;
  1089. }
  1090. if (pMsg->Param4)
  1091. {
  1092. EnterCriticalSection (&gCallListCriticalSection);
  1093. pCall = (PDRVCALL) pLine->pCalls;
  1094. while (pCall && (pCall->hCall != (HCALL) pMsg->hDevice))
  1095. {
  1096. pCall = pCall->pNext;
  1097. }
  1098. if (!pCall || pCall->dwKey != DRVCALL_KEY)
  1099. {
  1100. LeaveCriticalSection (&gCallListCriticalSection);
  1101. DereferenceObject (ghHandleTable, hDeviceCallback, 1);
  1102. break;
  1103. }
  1104. htCall = pCall->htCall;
  1105. LeaveCriticalSection (&gCallListCriticalSection);
  1106. }
  1107. else
  1108. {
  1109. htCall = 0;
  1110. }
  1111. (*gpfnLineEventProc)(
  1112. pLine->htLine,
  1113. htCall,
  1114. pMsg->Msg,
  1115. pMsg->Param1,
  1116. pMsg->Param2,
  1117. pMsg->Param3
  1118. );
  1119. DereferenceObject (ghHandleTable, hDeviceCallback, 1);
  1120. break;
  1121. }
  1122. case LINE_CALLINFO:
  1123. case LINE_CALLSTATE:
  1124. case LINE_GENERATE:
  1125. case LINE_MONITORDIGITS:
  1126. case LINE_MONITORMEDIA:
  1127. case LINE_MONITORTONE:
  1128. {
  1129. //
  1130. // For all the msgs where hDevice refers to a call tapisrv
  1131. // will pass us the pLine (hRemoteLine) for that call in
  1132. // dwParam4 to make the lookup of the corresponding pCall
  1133. // easier
  1134. //
  1135. HCALL hCall = (HCALL) pMsg->hDevice;
  1136. PDRVCALL pCall;
  1137. HTAPICALL htCall;
  1138. ASYNCEVENTMSGRSP MsgRsp;
  1139. MsgRsp.TotalSize = pMsg->TotalSize;
  1140. MsgRsp.InitContext = pMsg->InitContext;
  1141. MsgRsp.fnPostProcessProcHandle = pMsg->fnPostProcessProcHandle;
  1142. MsgRsp.hDevice = pMsg->hDevice;
  1143. MsgRsp.Msg = pMsg->Msg;
  1144. MsgRsp.OpenContext = pMsg->OpenContext;
  1145. MsgRsp.Param1 = pMsg->Param1;
  1146. MsgRsp.Param2 = pMsg->Param2;
  1147. MsgRsp.Param3 = pMsg->Param3;
  1148. MsgRsp.Param4 = pMsg->Param4;
  1149. if (!(pLine = ReferenceObject(
  1150. ghHandleTable,
  1151. pMsg->Param4,
  1152. DRVLINE_KEY
  1153. )))
  1154. {
  1155. break;
  1156. }
  1157. EnterCriticalSection (&gCallListCriticalSection);
  1158. pCall = (PDRVCALL) pLine->pCalls;
  1159. while (pCall && (pCall->hCall != hCall))
  1160. {
  1161. pCall = pCall->pNext;
  1162. }
  1163. if (!pCall || pCall->dwKey != DRVCALL_KEY)
  1164. {
  1165. LeaveCriticalSection (&gCallListCriticalSection);
  1166. DereferenceObject (ghHandleTable, pMsg->Param4, 1);
  1167. LOG((TL_ERROR,"EventHandlerThread: Bad hCall(cs) x%lx",hCall));
  1168. break;
  1169. }
  1170. htCall = pCall->htCall;
  1171. #if DBG
  1172. if ( 0 == htCall )
  1173. {
  1174. LOG((TL_ERROR, "htCall is now NULL! pCall=x%lx", pCall));
  1175. }
  1176. #endif
  1177. if ( LINE_CALLINFO == MsgRsp.Msg )
  1178. {
  1179. pCall->dwDirtyStructs |= STRUCTCHANGE_LINECALLINFO;
  1180. if (MsgRsp.Param1 & LINECALLINFOSTATE_DEVSPECIFIC)
  1181. {
  1182. pCall->dwDirtyStructs |= STRUCTCHANGE_LINECALLSTATUS;
  1183. }
  1184. if (MsgRsp.Param1 & (LINECALLINFOSTATE_CALLID |
  1185. LINECALLINFOSTATE_RELATEDCALLID))
  1186. {
  1187. pCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  1188. }
  1189. }
  1190. else if (LINE_CALLSTATE == MsgRsp.Msg )
  1191. {
  1192. pCall->dwDirtyStructs |= STRUCTCHANGE_LINECALLSTATUS;
  1193. //
  1194. // If the state == CONFERENCED then dwParam2 should
  1195. // contain the hConfCall. Note that the real dwParam2
  1196. // actually lives in MsgRsp.pfnPostProcessProc (see note
  1197. // below), so we retrieve it from there and (if non-NULL)
  1198. // try to map it to an htCall, then write the htCall
  1199. // value back to MsgRsp.pfnPostProcessProc.
  1200. //
  1201. if (MsgRsp.Param1 == LINECALLSTATE_CONFERENCED &&
  1202. MsgRsp.fnPostProcessProcHandle)
  1203. {
  1204. HCALL hConfCall = (HCALL) DWORD_CAST(MsgRsp.fnPostProcessProcHandle,__FILE__,__LINE__);
  1205. PDRVCALL pConfCall = (PDRVCALL) pLine->pCalls;
  1206. while (pConfCall && (pConfCall->hCall != hConfCall))
  1207. {
  1208. pConfCall = pConfCall->pNext;
  1209. }
  1210. if (!pConfCall || pConfCall->dwKey != DRVCALL_KEY)
  1211. {
  1212. LOG((TL_ERROR,
  1213. "EventHandlerThread: Bad pConfCall(cs) x%lx",
  1214. pCall
  1215. ));
  1216. MsgRsp.fnPostProcessProcHandle = 0;
  1217. }
  1218. else
  1219. {
  1220. MsgRsp.fnPostProcessProcHandle = (ULONG_PTR)(pConfCall->htCall);
  1221. }
  1222. }
  1223. //
  1224. // HACK ALERT!
  1225. //
  1226. // The remote tapisrv will pass us the call privilege
  1227. // in MsgRsp.dwParam2, and the real dwParam2 (the call
  1228. // state mode) in MsgRsp.pfnPostProcess. For the very
  1229. // 1st CALLSTATE msg for an incoming call we want to
  1230. // indicate the appropriate privilege to the local
  1231. // tapisrv so it knows whether or not it needs to find
  1232. // find a local owner for the call. So, we save the
  1233. // privilege & real dwParam2 in the call struct and
  1234. // pass a pointer to these in dwParam2.
  1235. //
  1236. // For all other cases we set MsgRsp.dwParam2 to the
  1237. // real dwParam2 in MsgRsp.pfnPostProcess.
  1238. //
  1239. if (!pCall->dwInitialPrivilege)
  1240. {
  1241. pCall->dwInitialCallStateMode = MsgRsp.fnPostProcessProcHandle;
  1242. pCall->dwInitialPrivilege = MsgRsp.Param2;
  1243. MsgRsp.Param2 = (ULONG_PTR)
  1244. &pCall->dwInitialCallStateMode;
  1245. }
  1246. else
  1247. {
  1248. MsgRsp.Param2 = MsgRsp.fnPostProcessProcHandle;
  1249. }
  1250. }
  1251. LeaveCriticalSection (&gCallListCriticalSection);
  1252. if (MsgRsp.Msg == LINE_MONITORTONE)
  1253. {
  1254. MsgRsp.Param2 = 0;
  1255. }
  1256. (*gpfnLineEventProc)(
  1257. pLine->htLine,
  1258. htCall,
  1259. MsgRsp.Msg,
  1260. MsgRsp.Param1,
  1261. MsgRsp.Param2,
  1262. MsgRsp.Param3
  1263. );
  1264. DereferenceObject (ghHandleTable, pMsg->Param4, 1);
  1265. break;
  1266. }
  1267. case LINE_DEVSPECIFIC:
  1268. case LINE_DEVSPECIFICFEATURE:
  1269. {
  1270. //
  1271. // For all the msgs where hDevice refers to a call tapisrv
  1272. // will pass us the pLine (hRemoteLine) for that call in
  1273. // dwParam4 to make the lookup of the corresponding pCall
  1274. // easier
  1275. //
  1276. HTAPICALL htCall;
  1277. DWORD hDeviceCallback = (DWORD) (pMsg->Param4 ?
  1278. pMsg->Param4 : pMsg->hDevice);
  1279. if (!(pLine = ReferenceObject(
  1280. ghHandleTable,
  1281. hDeviceCallback,
  1282. DRVLINE_KEY
  1283. )))
  1284. {
  1285. break;
  1286. }
  1287. if (pMsg->Param4)
  1288. {
  1289. HCALL hCall = (HCALL) pMsg->hDevice;
  1290. PDRVCALL pCall;
  1291. EnterCriticalSection (&gCallListCriticalSection);
  1292. pCall = (PDRVCALL) pLine->pCalls;
  1293. while (pCall && (pCall->hCall != hCall))
  1294. {
  1295. pCall = pCall->pNext;
  1296. }
  1297. if (pCall)
  1298. {
  1299. if (pCall->dwKey != DRVCALL_KEY)
  1300. {
  1301. LeaveCriticalSection (&gCallListCriticalSection);
  1302. LOG((TL_ERROR,
  1303. "EventHandlerThread: Bad pCall(ds) x%lx",
  1304. pCall
  1305. ));
  1306. goto LINE_DEVSPECIFIC_dereference;
  1307. }
  1308. htCall = pCall->htCall;
  1309. LeaveCriticalSection (&gCallListCriticalSection);
  1310. pMsg->Msg = (pMsg->Msg == LINE_DEVSPECIFIC ?
  1311. LINE_CALLDEVSPECIFIC :
  1312. LINE_CALLDEVSPECIFICFEATURE);
  1313. }
  1314. else
  1315. {
  1316. LeaveCriticalSection (&gCallListCriticalSection);
  1317. goto LINE_DEVSPECIFIC_dereference;
  1318. }
  1319. }
  1320. else
  1321. {
  1322. htCall = 0;
  1323. }
  1324. (*gpfnLineEventProc)(
  1325. pLine->htLine,
  1326. htCall,
  1327. pMsg->Msg,
  1328. pMsg->Param1,
  1329. pMsg->Param2,
  1330. pMsg->Param3
  1331. );
  1332. LINE_DEVSPECIFIC_dereference:
  1333. DereferenceObject (ghHandleTable, hDeviceCallback, 1);
  1334. break;
  1335. }
  1336. case PHONE_BUTTON:
  1337. case PHONE_DEVSPECIFIC:
  1338. if ((pPhone = ReferenceObject(
  1339. ghHandleTable,
  1340. pMsg->hDevice,
  1341. DRVPHONE_KEY
  1342. )))
  1343. {
  1344. (*gpfnPhoneEventProc)(
  1345. pPhone->htPhone,
  1346. pMsg->Msg,
  1347. pMsg->Param1,
  1348. pMsg->Param2,
  1349. pMsg->Param3
  1350. );
  1351. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1352. }
  1353. break;
  1354. case LINE_LINEDEVSTATE:
  1355. if (pMsg->Param1 & LINEDEVSTATE_REINIT)
  1356. {
  1357. //
  1358. // Be on our best behavior and immediately shutdown
  1359. // our init instances on the server
  1360. //
  1361. if (pMsg->InitContext)
  1362. {
  1363. //
  1364. // In the case of TAPISRV shutdown, server sends
  1365. // LINEDEVSTATE_REINIT, then waits for everybody to
  1366. // finish, we do not want to retry the connection until
  1367. // it indeed stopped, so we insert a wait
  1368. //
  1369. Sleep (8000);
  1370. OnServerDisconnected(pServer);
  1371. break;
  1372. }
  1373. pMsg->hDevice = 0;
  1374. /*
  1375. if (pMsg->Param2 == RSP_MSG)
  1376. {
  1377. //
  1378. // This is a message from TAPISRV indicating that this
  1379. // client need to reinit. RemoteSP doesn't need to do
  1380. // it's shut down, but should notify client tapisrv
  1381. // that it needs to reinit.
  1382. }
  1383. else
  1384. {
  1385. Shutdown (pServer);
  1386. }
  1387. */
  1388. }
  1389. if (pMsg->Param1 & LINEDEVSTATE_TRANSLATECHANGE)
  1390. {
  1391. // we shouldn't send this up to tapisrv, since this
  1392. // means that the translatecaps have changed on the
  1393. // server. just ignore this message
  1394. break;
  1395. }
  1396. if (pMsg->hDevice)
  1397. {
  1398. if (!(pLine = ReferenceObject(
  1399. ghHandleTable,
  1400. pMsg->hDevice,
  1401. DRVLINE_KEY
  1402. )))
  1403. {
  1404. break;
  1405. }
  1406. }
  1407. (*gpfnLineEventProc)(
  1408. pMsg->hDevice ? pLine->htLine : 0,
  1409. 0,
  1410. pMsg->Msg,
  1411. pMsg->Param1,
  1412. pMsg->Param2,
  1413. pMsg->Param3
  1414. );
  1415. if (pMsg->hDevice)
  1416. {
  1417. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1418. }
  1419. break;
  1420. case PHONE_STATE:
  1421. if (pMsg->Param1 & PHONESTATE_REINIT)
  1422. {
  1423. //
  1424. // Be on our best behavior and immediately shutdown
  1425. // our init instances on the server
  1426. //
  1427. if (pMsg->InitContext)
  1428. {
  1429. //
  1430. // In the case of TAPISRV shutdown, server sends
  1431. // LINEDEVSTATE_REINIT, then waits for everybody to
  1432. // finish, we do not want to retry the connection until
  1433. // it indeed stopped, so we insert a wait
  1434. //
  1435. Sleep (8000);
  1436. OnServerDisconnected(pServer);
  1437. break;
  1438. }
  1439. pMsg->hDevice = 0;
  1440. }
  1441. if (pMsg->hDevice)
  1442. {
  1443. if (!(pPhone = ReferenceObject(
  1444. ghHandleTable,
  1445. pMsg->hDevice,
  1446. DRVPHONE_KEY
  1447. )))
  1448. {
  1449. break;
  1450. }
  1451. }
  1452. (*gpfnPhoneEventProc)(
  1453. pMsg->hDevice ? pPhone->htPhone : 0,
  1454. pMsg->Msg,
  1455. pMsg->Param1,
  1456. pMsg->Param2,
  1457. pMsg->Param3
  1458. );
  1459. if (pMsg->hDevice)
  1460. {
  1461. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1462. }
  1463. break;
  1464. case LINE_CLOSE:
  1465. {
  1466. PDRVCALL pCall;
  1467. if ((pLine = ReferenceObject(
  1468. ghHandleTable,
  1469. pMsg->hDevice,
  1470. DRVLINE_KEY
  1471. )))
  1472. {
  1473. //
  1474. // Nullify the hLine field so that when TSPI_Close
  1475. // is called we know not to call the server
  1476. //
  1477. pLine->hLine = 0;
  1478. //
  1479. // Safely walk the call list for this line & nullify
  1480. // each call's hCall field so that when TSPI_CloseCall
  1481. // is called we know not to call the server
  1482. //
  1483. EnterCriticalSection (&gCallListCriticalSection);
  1484. pCall = pLine->pCalls;
  1485. while (pCall)
  1486. {
  1487. if (pCall->dwKey != DRVCALL_KEY)
  1488. {
  1489. LOG((TL_ERROR,
  1490. "EventHandlerThread: Bad pCall(lc) x%lx",
  1491. pCall
  1492. ));
  1493. continue;
  1494. }
  1495. pCall->hCall = 0;
  1496. pCall = pCall->pNext;
  1497. }
  1498. LeaveCriticalSection (&gCallListCriticalSection);
  1499. (*gpfnLineEventProc)(
  1500. pLine->htLine,
  1501. 0,
  1502. LINE_CLOSE,
  1503. 0,
  1504. 0,
  1505. 0
  1506. );
  1507. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1508. }
  1509. break;
  1510. }
  1511. case PHONE_CLOSE:
  1512. {
  1513. if ((pPhone = ReferenceObject(
  1514. ghHandleTable,
  1515. pMsg->hDevice,
  1516. DRVPHONE_KEY
  1517. )))
  1518. {
  1519. //
  1520. // Nullify the hPhone field so that when TSPI_Close
  1521. // is called we know not to call the server
  1522. //
  1523. pPhone->hPhone = 0;
  1524. (*gpfnPhoneEventProc)(
  1525. pPhone->htPhone,
  1526. PHONE_CLOSE,
  1527. 0,
  1528. 0,
  1529. 0
  1530. );
  1531. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1532. }
  1533. break;
  1534. }
  1535. case LINE_GATHERDIGITS:
  1536. {
  1537. if (pMsg->TotalSize >= (sizeof (*pMsg) + sizeof (PDRVLINE)))
  1538. {
  1539. DWORD hLineCallback = ((DWORD *)(pMsg + 1))[1];
  1540. HCALL hCall = (HCALL) pMsg->hDevice;
  1541. PDRVCALL pCall;
  1542. HTAPICALL htCall;
  1543. if ((pLine = ReferenceObject(
  1544. ghHandleTable,
  1545. hLineCallback,
  1546. DRVLINE_KEY
  1547. )))
  1548. {
  1549. EnterCriticalSection (&gCallListCriticalSection);
  1550. pCall = (PDRVCALL) pLine->pCalls;
  1551. while (pCall && (pCall->hCall != hCall))
  1552. {
  1553. pCall = pCall->pNext;
  1554. }
  1555. htCall = (pCall ? pCall->htCall : 0);
  1556. if (pCall && pCall->dwKey != DRVCALL_KEY)
  1557. {
  1558. LeaveCriticalSection (&gCallListCriticalSection);
  1559. goto LINE_GATHERDIGITS_dereference;
  1560. }
  1561. LeaveCriticalSection (&gCallListCriticalSection);
  1562. TSPI_lineGatherDigits_PostProcess (pMsg);
  1563. (*gpfnLineEventProc)(
  1564. pLine->htLine,
  1565. htCall,
  1566. LINE_GATHERDIGITS,
  1567. pMsg->Param1,
  1568. pMsg->Param2, // dwEndToEndID
  1569. 0
  1570. );
  1571. LINE_GATHERDIGITS_dereference:
  1572. DereferenceObject (ghHandleTable, hLineCallback, 1);
  1573. }
  1574. }
  1575. break;
  1576. }
  1577. case LINE_REPLY:
  1578. case PHONE_REPLY:
  1579. {
  1580. ULONG_PTR Context2;
  1581. DWORD originalRequestID;
  1582. PASYNCREQUESTCONTEXT pContext;
  1583. if ((pContext = ReferenceObjectEx(
  1584. ghHandleTable,
  1585. pMsg->Param1,
  1586. 0,
  1587. (LPVOID *) &Context2
  1588. )))
  1589. {
  1590. originalRequestID = DWORD_CAST(Context2,__FILE__,__LINE__);
  1591. LOG((TL_INFO,
  1592. "Doing LINE_/PHONE_REPLY: LocID=x%x (RemID=x%x), " \
  1593. "Result=x%x",
  1594. originalRequestID,
  1595. pMsg->Param1,
  1596. pMsg->Param2
  1597. ));
  1598. if (pContext != (PASYNCREQUESTCONTEXT) -1)
  1599. {
  1600. if (pContext->dwKey == DRVASYNC_KEY)
  1601. {
  1602. //
  1603. // Set pContext->dwOriginalRequestID so
  1604. // MakeCallPostProcess &
  1605. // SetupConferencePostProcess can check it
  1606. // againt pCall->dwOriginalRequestID for
  1607. // verification.
  1608. //
  1609. pContext->dwOriginalRequestID = (DWORD)
  1610. originalRequestID;
  1611. (*pContext->pfnPostProcessProc)(
  1612. pMsg,
  1613. pContext
  1614. );
  1615. }
  1616. else
  1617. {
  1618. //
  1619. // Not a valid request id, do a single deref
  1620. // & break
  1621. //
  1622. DereferenceObject (ghHandleTable, pMsg->Param1, 1);
  1623. break;
  1624. }
  1625. }
  1626. (*gpfnCompletionProc)(
  1627. (DRV_REQUESTID) originalRequestID,
  1628. (LONG) pMsg->Param2
  1629. );
  1630. //
  1631. // Double deref to free the object
  1632. //
  1633. DereferenceObject (ghHandleTable, pMsg->Param1, 2);
  1634. }
  1635. break;
  1636. }
  1637. case LINE_CREATE:
  1638. {
  1639. //
  1640. // Check validity of new device ID to thwart RPC attacks.
  1641. // Compare with known/existing device ID's on for this
  1642. // server, and also try to get devCaps for this device
  1643. // from server.
  1644. //
  1645. #define V1_0_LINEDEVCAPS_SIZE 236
  1646. BYTE buf[sizeof (TAPI32_MSG) +
  1647. V1_0_LINEDEVCAPS_SIZE];
  1648. DWORD i, dwRetryCount = 0, dwUsedSize;
  1649. PTAPI32_MSG pReq = (PTAPI32_MSG) buf;
  1650. PDRVLINELOOKUP pLookup;
  1651. TapiEnterCriticalSection(&gCriticalSection);
  1652. pLookup = gpLineLookup;
  1653. while (pLookup)
  1654. {
  1655. for (i = 0; i < pLookup->dwUsedEntries; i++)
  1656. {
  1657. if ((pLookup->aEntries[i].pServer == pServer) &&
  1658. (pLookup->aEntries[i].dwDeviceIDServer ==
  1659. (DWORD) pMsg->Param1))
  1660. {
  1661. //
  1662. // This server/id combo is already in our global
  1663. // table, so blow off this msg
  1664. //
  1665. TapiLeaveCriticalSection(&gCriticalSection);
  1666. goto LINE_CREATE_break;
  1667. }
  1668. }
  1669. pLookup = pLookup->pNext;
  1670. }
  1671. TapiLeaveCriticalSection(&gCriticalSection);
  1672. do
  1673. {
  1674. pReq->u.Req_Func = lGetDevCaps;
  1675. pReq->Params[0] = pServer->hLineApp;
  1676. pReq->Params[1] = pMsg->Param1;
  1677. pReq->Params[2] = TAPI_VERSION1_0;
  1678. pReq->Params[3] = 0;
  1679. pReq->Params[4] = V1_0_LINEDEVCAPS_SIZE;
  1680. dwUsedSize = sizeof (TAPI32_MSG);
  1681. RpcTryExcept
  1682. {
  1683. ClientRequest(
  1684. pServer->phContext,
  1685. (char *) pReq,
  1686. sizeof (buf),
  1687. &dwUsedSize
  1688. );
  1689. dwRetryCount = gdwRetryCount;
  1690. }
  1691. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  1692. {
  1693. dwRetryCount++;
  1694. if (dwRetryCount < gdwRetryCount)
  1695. {
  1696. Sleep (gdwRetryTimeout);
  1697. }
  1698. else
  1699. {
  1700. pReq->u.Ack_ReturnValue = LINEERR_BADDEVICEID;
  1701. }
  1702. }
  1703. RpcEndExcept
  1704. } while (dwRetryCount < gdwRetryCount);
  1705. if ((LONG) pReq->u.Ack_ReturnValue != LINEERR_BADDEVICEID)
  1706. {
  1707. if (AddLine(
  1708. pServer,
  1709. gdwTempLineID,
  1710. (DWORD) pMsg->Param1,
  1711. FALSE,
  1712. FALSE,
  1713. 0,
  1714. NULL
  1715. ) == 0)
  1716. {
  1717. (*gpfnLineEventProc)(
  1718. 0,
  1719. 0,
  1720. LINE_CREATE,
  1721. (ULONG_PTR) ghProvider,
  1722. gdwTempLineID--,
  1723. 0
  1724. );
  1725. }
  1726. }
  1727. LINE_CREATE_break:
  1728. break;
  1729. }
  1730. case LINE_REMOVE:
  1731. {
  1732. PDRVLINELOOKUP pLookup;
  1733. BOOL fValidID = FALSE;
  1734. DWORD dwDeviceID, i;
  1735. TapiEnterCriticalSection(&gCriticalSection);
  1736. pLookup = gpLineLookup;
  1737. while (pLookup)
  1738. {
  1739. for (i = 0; i < pLookup->dwUsedEntries; i++)
  1740. {
  1741. if ((pLookup->aEntries[i].pServer == pServer) &&
  1742. (pLookup->aEntries[i].dwDeviceIDServer ==
  1743. (DWORD) pMsg->Param1))
  1744. {
  1745. //
  1746. // This server/id combo is in our global
  1747. //
  1748. fValidID = TRUE;
  1749. dwDeviceID = pLookup->aEntries[i].dwDeviceIDLocal;
  1750. pLookup->aEntries[i].dwDeviceIDServer = 0xffffffff;
  1751. break;
  1752. }
  1753. }
  1754. if (fValidID)
  1755. {
  1756. break;
  1757. }
  1758. pLookup = pLookup->pNext;
  1759. }
  1760. TapiLeaveCriticalSection(&gCriticalSection);
  1761. if (fValidID)
  1762. {
  1763. (*gpfnLineEventProc)(
  1764. 0,
  1765. 0,
  1766. LINE_REMOVE,
  1767. dwDeviceID,
  1768. 0,
  1769. 0
  1770. );
  1771. }
  1772. }
  1773. break;
  1774. case PHONE_CREATE:
  1775. {
  1776. //
  1777. // Check validity of new device ID to thwart RPC attacks.
  1778. // Compare with known/existing device ID's on for this
  1779. // server, and also try to get devCaps for this device
  1780. // from server.
  1781. //
  1782. #define V1_0_PHONECAPS_SIZE 144
  1783. BYTE buf[sizeof (TAPI32_MSG) + V1_0_PHONECAPS_SIZE];
  1784. DWORD i, dwRetryCount = 0, dwUsedSize;
  1785. PTAPI32_MSG pReq = (PTAPI32_MSG) buf;
  1786. PDRVPHONELOOKUP pLookup;
  1787. TapiEnterCriticalSection(&gCriticalSection);
  1788. pLookup = gpPhoneLookup;
  1789. while (pLookup)
  1790. {
  1791. for (i = 0; i < pLookup->dwUsedEntries; i++)
  1792. {
  1793. if ((pLookup->aEntries[i].pServer == pServer) &&
  1794. (pLookup->aEntries[i].dwDeviceIDServer ==
  1795. (DWORD) pMsg->Param1))
  1796. {
  1797. //
  1798. // This server/id combo is already in our global
  1799. // table, so blow off this msg
  1800. //
  1801. TapiLeaveCriticalSection(&gCriticalSection);
  1802. goto PHONE_CREATE_break;
  1803. }
  1804. }
  1805. pLookup = pLookup->pNext;
  1806. }
  1807. TapiLeaveCriticalSection(&gCriticalSection);
  1808. do
  1809. {
  1810. pReq->u.Req_Func = pGetDevCaps;
  1811. pReq->Params[0] = pServer->hPhoneApp;
  1812. pReq->Params[1] = pMsg->Param1;
  1813. pReq->Params[2] = TAPI_VERSION1_0;
  1814. pReq->Params[3] = 0;
  1815. pReq->Params[4] = V1_0_PHONECAPS_SIZE;
  1816. dwUsedSize = sizeof (TAPI32_MSG);
  1817. RpcTryExcept
  1818. {
  1819. ClientRequest(
  1820. pServer->phContext,
  1821. (char *) pReq,
  1822. sizeof (buf),
  1823. &dwUsedSize
  1824. );
  1825. dwRetryCount = gdwRetryCount;
  1826. }
  1827. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  1828. {
  1829. dwRetryCount++;
  1830. if (dwRetryCount < gdwRetryCount)
  1831. {
  1832. Sleep (gdwRetryTimeout);
  1833. }
  1834. else
  1835. {
  1836. pReq->u.Ack_ReturnValue = PHONEERR_BADDEVICEID;
  1837. }
  1838. }
  1839. RpcEndExcept
  1840. } while (dwRetryCount < gdwRetryCount);
  1841. if ((LONG) pReq->u.Ack_ReturnValue != PHONEERR_BADDEVICEID)
  1842. {
  1843. AddPhone(
  1844. pServer,
  1845. gdwTempPhoneID,
  1846. (DWORD) pMsg->Param1,
  1847. FALSE,
  1848. FALSE,
  1849. 0,
  1850. NULL
  1851. );
  1852. (*gpfnPhoneEventProc)(
  1853. 0,
  1854. PHONE_CREATE,
  1855. (ULONG_PTR) ghProvider,
  1856. gdwTempPhoneID--,
  1857. 0
  1858. );
  1859. }
  1860. PHONE_CREATE_break:
  1861. break;
  1862. }
  1863. case PHONE_REMOVE:
  1864. {
  1865. PDRVPHONELOOKUP pLookup;
  1866. BOOL fValidID = FALSE;
  1867. DWORD dwDeviceID, i;
  1868. TapiEnterCriticalSection(&gCriticalSection);
  1869. pLookup = gpPhoneLookup;
  1870. while (pLookup)
  1871. {
  1872. for (i = 0; i < pLookup->dwUsedEntries; i++)
  1873. {
  1874. if ((pLookup->aEntries[i].pServer == pServer) &&
  1875. (pLookup->aEntries[i].dwDeviceIDServer ==
  1876. (DWORD) pMsg->Param1))
  1877. {
  1878. //
  1879. // This server/id combo is in our global
  1880. //
  1881. fValidID = TRUE;
  1882. dwDeviceID = pLookup->aEntries[i].dwDeviceIDLocal;
  1883. break;
  1884. }
  1885. }
  1886. if (fValidID)
  1887. {
  1888. break;
  1889. }
  1890. pLookup = pLookup->pNext;
  1891. }
  1892. TapiLeaveCriticalSection(&gCriticalSection);
  1893. if (fValidID)
  1894. {
  1895. (*gpfnPhoneEventProc)(
  1896. 0,
  1897. PHONE_REMOVE,
  1898. dwDeviceID,
  1899. 0,
  1900. 0
  1901. );
  1902. }
  1903. }
  1904. break;
  1905. case LINE_APPNEWCALL:
  1906. {
  1907. PDRVCALL pCall;
  1908. HTAPICALL htCall;
  1909. if (!(pLine = ReferenceObject(
  1910. ghHandleTable,
  1911. pMsg->hDevice,
  1912. DRVLINE_KEY
  1913. )))
  1914. {
  1915. break;
  1916. }
  1917. if ((pCall = DrvAlloc (sizeof (DRVCALL))))
  1918. {
  1919. pCall->hCall = (HCALL) pMsg->Param2;
  1920. pCall->dwAddressID = (DWORD) pMsg->Param1;
  1921. if (pMsg->TotalSize >=
  1922. (sizeof (*pMsg) + 2 * sizeof (DWORD)))
  1923. {
  1924. pCall->dwCallID = (DWORD) *(&pMsg->Param4 + 1);
  1925. pCall->dwRelatedCallID = (DWORD) *(&pMsg->Param4 + 2);
  1926. }
  1927. else
  1928. {
  1929. pCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  1930. pLine->pServer->bVer2xServer = TRUE;
  1931. }
  1932. if (pLine->htLine)
  1933. {
  1934. (*gpfnLineEventProc)(
  1935. pLine->htLine,
  1936. 0,
  1937. LINE_NEWCALL,
  1938. (ULONG_PTR) pCall,
  1939. (ULONG_PTR) &(pCall->htCall),
  1940. (ULONG_PTR) 0
  1941. );
  1942. EnterCriticalSection (&gCallListCriticalSection);
  1943. AddCallToList (pLine, pCall);
  1944. htCall = pCall->htCall;
  1945. LeaveCriticalSection (&gCallListCriticalSection);
  1946. if (!htCall)
  1947. {
  1948. //
  1949. // tapi was not able to create it's own instance
  1950. // to represent ths incoming call, perhaps
  1951. // because the line was closed, or out of
  1952. // memory. if the line was closed then we've
  1953. // already notified the remote server, and it
  1954. // should have destroyed the call client.
  1955. // otherwise, we probably want to do a closecall
  1956. // here or in a worker thread
  1957. RemoveCallFromList (pCall);
  1958. }
  1959. }
  1960. else
  1961. {
  1962. DrvFree (pCall);
  1963. }
  1964. }
  1965. else
  1966. {
  1967. }
  1968. DereferenceObject (ghHandleTable, pMsg->hDevice, 1);
  1969. break;
  1970. }
  1971. #if DBG
  1972. default:
  1973. LOG((TL_ERROR,
  1974. "EventHandlerThread: unknown msg=x%x, hDev=x%x, p1=x%x",
  1975. pMsg->Msg,
  1976. pMsg->hDevice,
  1977. pMsg->Param1
  1978. ));
  1979. break;
  1980. #endif
  1981. } // switch (pMsg->dwMsg)
  1982. DereferenceObject (ghHandleTable, pMsg->InitContext, 1);
  1983. } // while ((pMsg = GetEventFromQueue()))
  1984. } // while (1)
  1985. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  1986. {
  1987. CancelIo (gEventHandlerThreadParams.hMailslot);
  1988. }
  1989. ClearImpersonationToken();
  1990. RevertImpersonation();
  1991. CloseHandle(hProcess);
  1992. LOG((TL_INFO, "EventHandlerThread: exit"));
  1993. ExitThread (0);
  1994. }
  1995. PDRVLINE
  1996. GetLineFromID(
  1997. DWORD dwDeviceID
  1998. )
  1999. {
  2000. PDRVLINE pLine;
  2001. //
  2002. // First check to see if it's a valid device ID.
  2003. //
  2004. if (dwDeviceID < gdwLineDeviceIDBase || gpLineLookup == NULL)
  2005. {
  2006. return NULL;
  2007. }
  2008. TapiEnterCriticalSection(&gCriticalSection);
  2009. //
  2010. // First check to see if it's a "static" device, i.e. a device
  2011. // that we knew about at start up time, in which case we know
  2012. // it's exact location in the lookup table
  2013. //
  2014. if (dwDeviceID < (gdwLineDeviceIDBase + gdwInitialNumLineDevices))
  2015. {
  2016. pLine = gpLineLookup->aEntries + dwDeviceID - gdwLineDeviceIDBase;
  2017. }
  2018. //
  2019. // If here, the id references a "dynamic" device, i.e. one that
  2020. // we found out about on the fly via a CREATE msg, so we need to
  2021. // walk the lookup table(s) to find it
  2022. //
  2023. // TODO: the while loops down below are not efficient at all
  2024. //
  2025. else
  2026. {
  2027. PDRVLINELOOKUP pLookup = gpLineLookup;
  2028. DWORD i;
  2029. pLine = NULL;
  2030. while (pLookup)
  2031. {
  2032. i = 0;
  2033. while (i != pLookup->dwUsedEntries &&
  2034. pLookup->aEntries[i].dwDeviceIDLocal != dwDeviceID)
  2035. {
  2036. i++;
  2037. }
  2038. if (i < pLookup->dwUsedEntries)
  2039. {
  2040. pLine = &(pLookup->aEntries[i]);
  2041. break;
  2042. }
  2043. pLookup = pLookup->pNext;
  2044. }
  2045. }
  2046. TapiLeaveCriticalSection(&gCriticalSection);
  2047. return pLine;
  2048. }
  2049. PDRVPHONE
  2050. GetPhoneFromID(
  2051. DWORD dwDeviceID
  2052. )
  2053. {
  2054. PDRVPHONE pPhone;
  2055. //
  2056. // First check to see if it's a valid device ID.
  2057. //
  2058. if (dwDeviceID < gdwPhoneDeviceIDBase || gpPhoneLookup == NULL)
  2059. {
  2060. return NULL;
  2061. }
  2062. TapiEnterCriticalSection(&gCriticalSection);
  2063. //
  2064. // Then check to see if it's a "static" device, i.e. a device
  2065. // that we knew about at start up time, in which case we know
  2066. // it's exact location in the lookup table
  2067. //
  2068. if (dwDeviceID < (gdwPhoneDeviceIDBase + gdwInitialNumPhoneDevices))
  2069. {
  2070. pPhone = gpPhoneLookup->aEntries + dwDeviceID - gdwPhoneDeviceIDBase;
  2071. }
  2072. //
  2073. // If here, the id references a "dynamic" device, i.e. one that
  2074. // we found out about on the fly via a CREATE msg, so we need to
  2075. // walk the lookup table(s) to find it
  2076. //
  2077. // TODO: the while loops down below are not efficient at all
  2078. //
  2079. else
  2080. {
  2081. PDRVPHONELOOKUP pLookup = gpPhoneLookup;
  2082. DWORD i;
  2083. pPhone = NULL;
  2084. while (pLookup)
  2085. {
  2086. i = 0;
  2087. while (i != pLookup->dwUsedEntries &&
  2088. pLookup->aEntries[i].dwDeviceIDLocal != dwDeviceID)
  2089. {
  2090. i++;
  2091. }
  2092. if (i < pLookup->dwUsedEntries)
  2093. {
  2094. pPhone = &(pLookup->aEntries[i]);
  2095. break;
  2096. }
  2097. pLookup = pLookup->pNext;
  2098. }
  2099. }
  2100. TapiLeaveCriticalSection(&gCriticalSection);
  2101. return pPhone;
  2102. }
  2103. BOOL
  2104. WINAPI
  2105. GrowBuf(
  2106. LPBYTE *ppBuf,
  2107. LPDWORD pdwBufSize,
  2108. DWORD dwCurrValidBytes,
  2109. DWORD dwBytesToAdd
  2110. )
  2111. {
  2112. DWORD dwCurrBufSize, dwNewBufSize;
  2113. LPBYTE pNewBuf;
  2114. //
  2115. // Try to get a new buffer big enough to hold everything
  2116. //
  2117. for(
  2118. dwNewBufSize = 2 * (dwCurrBufSize = *pdwBufSize);
  2119. dwNewBufSize < (dwCurrBufSize + dwBytesToAdd);
  2120. dwNewBufSize *= 2
  2121. );
  2122. if (!(pNewBuf = DrvAlloc (dwNewBufSize)))
  2123. {
  2124. return FALSE;
  2125. }
  2126. //
  2127. // Copy the "valid" bytes in the old buf to the new buf,
  2128. // then free the old buf
  2129. //
  2130. CopyMemory (pNewBuf, *ppBuf, dwCurrValidBytes);
  2131. DrvFree (*ppBuf);
  2132. //
  2133. // Reset the pointers to the new buf & buf size
  2134. //
  2135. *ppBuf = pNewBuf;
  2136. *pdwBufSize = dwNewBufSize;
  2137. return TRUE;
  2138. }
  2139. PRSP_THREAD_INFO
  2140. WINAPI
  2141. GetTls(
  2142. void
  2143. )
  2144. {
  2145. PRSP_THREAD_INFO pClientThreadInfo;
  2146. if (!(pClientThreadInfo = TlsGetValue (gdwTlsIndex)))
  2147. {
  2148. pClientThreadInfo = (PRSP_THREAD_INFO)
  2149. DrvAlloc (sizeof(RSP_THREAD_INFO));
  2150. if (!pClientThreadInfo)
  2151. {
  2152. return NULL;
  2153. }
  2154. pClientThreadInfo->pBuf = DrvAlloc (INITIAL_CLIENT_THREAD_BUF_SIZE);
  2155. if (!pClientThreadInfo->pBuf)
  2156. {
  2157. DrvFree (pClientThreadInfo);
  2158. return NULL;
  2159. }
  2160. pClientThreadInfo->dwBufSize = INITIAL_CLIENT_THREAD_BUF_SIZE;
  2161. EnterCriticalSection (&gcsTlsList);
  2162. InsertHeadList (&gTlsListHead, &pClientThreadInfo->TlsList);
  2163. LeaveCriticalSection (&gcsTlsList);
  2164. TlsSetValue (gdwTlsIndex, (LPVOID) pClientThreadInfo);
  2165. }
  2166. return pClientThreadInfo;
  2167. }
  2168. #if DBG
  2169. LONG
  2170. WINAPI
  2171. RemoteDoFunc(
  2172. PREMOTE_FUNC_ARGS pFuncArgs,
  2173. char *pszFuncName
  2174. )
  2175. #else
  2176. LONG
  2177. WINAPI
  2178. RemoteDoFunc(
  2179. PREMOTE_FUNC_ARGS pFuncArgs
  2180. )
  2181. #endif
  2182. {
  2183. LONG lResult;
  2184. BOOL bCopyOnSuccess = FALSE, bRpcImpersonate, bNeedToReInit = FALSE;
  2185. DWORD i, j, dwUsedSize, dwNeededSize;
  2186. DWORD dwFuncClassErrorIndex = (pFuncArgs->Flags & 0x00000030) >> 4;
  2187. DWORD requestID;
  2188. ULONG_PTR value;
  2189. PDRVSERVER pServer = NULL;
  2190. PRSP_THREAD_INFO pTls;
  2191. //
  2192. // Get the tls
  2193. //
  2194. if (!(pTls = GetTls()))
  2195. {
  2196. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2197. goto RemoteDoFunc_return;
  2198. }
  2199. //
  2200. // Validate all the func args
  2201. //
  2202. dwNeededSize = dwUsedSize = sizeof (TAPI32_MSG);
  2203. for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
  2204. {
  2205. value = pFuncArgs->Args[i];
  2206. switch (pFuncArgs->ArgTypes[i])
  2207. {
  2208. case lpContext:
  2209. // do nothing
  2210. continue;
  2211. case Dword:
  2212. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST_HINT(pFuncArgs->Args[i],__FILE__,__LINE__,i);
  2213. continue;
  2214. case LineID:
  2215. {
  2216. PDRVLINE pLine = GetLineFromID ((DWORD) value);
  2217. try
  2218. {
  2219. pServer = pLine->pServer;
  2220. }
  2221. except (EXCEPTION_EXECUTE_HANDLER)
  2222. {
  2223. lResult = LINEERR_BADDEVICEID;
  2224. goto RemoteDoFunc_return;
  2225. }
  2226. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pLine->dwDeviceIDServer;
  2227. continue;
  2228. }
  2229. case PhoneID:
  2230. {
  2231. PDRVPHONE pPhone = GetPhoneFromID ((DWORD) value);
  2232. try
  2233. {
  2234. pServer = pPhone->pServer;
  2235. }
  2236. except (EXCEPTION_EXECUTE_HANDLER)
  2237. {
  2238. lResult = PHONEERR_BADDEVICEID;
  2239. goto RemoteDoFunc_return;
  2240. }
  2241. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pPhone->dwDeviceIDServer;
  2242. continue;
  2243. }
  2244. case Hdcall:
  2245. //
  2246. // Save the pServer & adjust the call handle as understood by
  2247. // the server
  2248. //
  2249. try
  2250. {
  2251. pServer = ((PDRVCALL) value)->pServer;
  2252. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = ((PDRVCALL) value)->hCall;
  2253. }
  2254. except (EXCEPTION_EXECUTE_HANDLER)
  2255. {
  2256. lResult = LINEERR_INVALCALLHANDLE;
  2257. goto RemoteDoFunc_return;
  2258. }
  2259. continue;
  2260. case Hdline:
  2261. //
  2262. // Save the pServer & adjust the line handle as understood by
  2263. // the server. There's no need to wrap this in a try/except
  2264. // since the object pointed at by the pLine is static, whether
  2265. // or not the device is actually open.
  2266. //
  2267. pServer = ((PDRVLINE) value)->pServer;
  2268. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = ((PDRVLINE) value)->hLine;
  2269. continue;
  2270. case Hdphone:
  2271. //
  2272. // Save the pServer & adjust the phone handle as understood by
  2273. // the server. There's no need to wrap this in a try/except
  2274. // since the object pointed at by the pLine is static, whether
  2275. // or not the device is actually open.
  2276. //
  2277. pServer = ((PDRVPHONE) value)->pServer;
  2278. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = ((PDRVPHONE) value)->hPhone;
  2279. continue;
  2280. case lpDword:
  2281. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2282. bCopyOnSuccess = TRUE;
  2283. continue;
  2284. case lpsz:
  2285. //
  2286. // Check if value is a valid string ptr and if so
  2287. // copy the contents of the string to the extra data
  2288. // buffer passed to the server, else indicate no data
  2289. //
  2290. if (value)
  2291. {
  2292. DWORD n = (lstrlenW ((WCHAR *) value) + 1) *
  2293. sizeof (WCHAR),
  2294. nAligned = (n + 3) & 0xfffffffc;
  2295. if ((nAligned + dwUsedSize) > pTls->dwBufSize)
  2296. {
  2297. if (!GrowBuf(
  2298. &pTls->pBuf,
  2299. &pTls->dwBufSize,
  2300. dwUsedSize,
  2301. nAligned
  2302. ))
  2303. {
  2304. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2305. goto RemoteDoFunc_return;
  2306. }
  2307. }
  2308. CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) value, n);
  2309. //
  2310. // Pass the server the offset of the string in the var data
  2311. // portion of the buffer
  2312. //
  2313. ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
  2314. dwUsedSize - sizeof (TAPI32_MSG);
  2315. //
  2316. // Increment the total number of data bytes
  2317. //
  2318. dwUsedSize += nAligned;
  2319. dwNeededSize += nAligned;
  2320. }
  2321. else
  2322. {
  2323. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2324. }
  2325. continue;
  2326. case lpGet_Struct:
  2327. case lpGet_CallParamsStruct:
  2328. case lpGet_SizeToFollow:
  2329. {
  2330. BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpGet_SizeToFollow);
  2331. DWORD dwSize;
  2332. if (bSizeToFollow)
  2333. {
  2334. #if DBG
  2335. //
  2336. // Check to make sure the following arg is of type Size
  2337. //
  2338. if ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
  2339. (pFuncArgs->ArgTypes[i + 1] != Size))
  2340. {
  2341. LOG((TL_ERROR,
  2342. "DoFunc: error, lpGet_SizeToFollow !followed by Size"
  2343. ));
  2344. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2345. goto RemoteDoFunc_return;
  2346. }
  2347. #endif
  2348. dwSize = DWORD_CAST_HINT(pFuncArgs->Args[i + 1],__FILE__,__LINE__,i);
  2349. }
  2350. else
  2351. {
  2352. dwSize = *((LPDWORD) value); // lpXxx->dwTotalSize
  2353. }
  2354. if (bSizeToFollow)
  2355. {
  2356. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2357. ++j;++i;
  2358. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST_HINT(pFuncArgs->Args[i],__FILE__,__LINE__,i);
  2359. }
  2360. else
  2361. {
  2362. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = dwSize;
  2363. }
  2364. //
  2365. // Now set the bCopyOnSuccess flag to indicate that we've data
  2366. // to copy back on successful completion, and add to the
  2367. // dwNeededSize field
  2368. //
  2369. bCopyOnSuccess = TRUE;
  2370. dwNeededSize += dwSize;
  2371. continue;
  2372. }
  2373. case lpSet_Struct:
  2374. case lpSet_SizeToFollow:
  2375. {
  2376. BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
  2377. DWORD dwSize, dwSizeAligned;
  2378. #if DBG
  2379. //
  2380. // Check to make sure the following arg is of type Size
  2381. //
  2382. if (bSizeToFollow &&
  2383. ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
  2384. (pFuncArgs->ArgTypes[i + 1] != Size)))
  2385. {
  2386. LOG((TL_ERROR,
  2387. "DoFunc: error, lpSet_SizeToFollow !followed by Size"
  2388. ));
  2389. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2390. goto RemoteDoFunc_return;
  2391. }
  2392. #endif
  2393. if (bSizeToFollow)
  2394. {
  2395. dwSize = (value ? DWORD_CAST_HINT(pFuncArgs->Args[i + 1],__FILE__,__LINE__,i) : 0);
  2396. }
  2397. else
  2398. {
  2399. dwSize = (value ? *((LPDWORD) value) : 0);
  2400. }
  2401. if (dwSize)
  2402. {
  2403. //
  2404. // Grow the buffer if necessary, & do the copy
  2405. //
  2406. dwSizeAligned = (dwSize + 3) & 0xfffffffc;
  2407. if ((dwSizeAligned + dwUsedSize) > pTls->dwBufSize)
  2408. {
  2409. if (!GrowBuf(
  2410. &pTls->pBuf,
  2411. &pTls->dwBufSize,
  2412. dwUsedSize,
  2413. dwSizeAligned
  2414. ))
  2415. {
  2416. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2417. goto RemoteDoFunc_return;
  2418. }
  2419. }
  2420. CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) value, dwSize);
  2421. }
  2422. else
  2423. {
  2424. dwSizeAligned = 0;
  2425. }
  2426. //
  2427. // Pass the server the offset of the data in the var data
  2428. // portion of the buffer
  2429. //
  2430. if (dwSize)
  2431. {
  2432. ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
  2433. dwUsedSize - sizeof (TAPI32_MSG);
  2434. }
  2435. else
  2436. {
  2437. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2438. }
  2439. //
  2440. // Increment the dwXxxSize vars appropriately
  2441. //
  2442. dwUsedSize += dwSizeAligned;
  2443. dwNeededSize += dwSizeAligned;
  2444. //
  2445. // Since we already know the next arg (Size) just handle
  2446. // it here so we don't have to run thru the loop again
  2447. //
  2448. if (bSizeToFollow)
  2449. {
  2450. ++j;++i;
  2451. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST_HINT(pFuncArgs->Args[i],__FILE__,__LINE__,i);
  2452. }
  2453. continue;
  2454. }
  2455. case lpServer:
  2456. pServer = (PDRVSERVER) value;
  2457. --j;
  2458. continue;
  2459. #if DBG
  2460. case Size:
  2461. LOG((TL_ERROR, "DoFunc: error, hit case Size"));
  2462. continue;
  2463. default:
  2464. LOG((TL_ERROR, "DoFunc: error, unknown arg type"));
  2465. continue;
  2466. #endif
  2467. } // switch
  2468. } // for
  2469. //
  2470. // Verify if the target server is valid & in a good state
  2471. //
  2472. if (IsValidObject ((PVOID) pServer, gdwDrvServerKey))
  2473. {
  2474. if (SERVER_REINIT & pServer->dwFlags)
  2475. {
  2476. LOG((TL_ERROR, "pServer says REINIT in RemoteDoFunc"));
  2477. lResult = gaServerReInitErrors[dwFuncClassErrorIndex];
  2478. goto RemoteDoFunc_return;
  2479. }
  2480. if (SERVER_DISCONNECTED & pServer->dwFlags)
  2481. {
  2482. LOG((TL_ERROR, "pServer is disconnected in RemoteDoFunc"));
  2483. lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
  2484. goto RemoteDoFunc_return;
  2485. }
  2486. }
  2487. else
  2488. {
  2489. lResult = (pServer ?
  2490. gaOpFailedErrors[dwFuncClassErrorIndex] :
  2491. gaServerDisconnectedErrors[dwFuncClassErrorIndex]);
  2492. goto RemoteDoFunc_return;
  2493. }
  2494. //
  2495. // Now make the request
  2496. //
  2497. if (dwNeededSize > pTls->dwBufSize)
  2498. {
  2499. if (!GrowBuf(
  2500. &pTls->pBuf,
  2501. &pTls->dwBufSize,
  2502. dwUsedSize,
  2503. dwNeededSize - pTls->dwBufSize
  2504. ))
  2505. {
  2506. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2507. goto RemoteDoFunc_return;
  2508. }
  2509. }
  2510. ((PTAPI32_MSG) pTls->pBuf)->u.Req_Func = (DWORD)HIWORD(pFuncArgs->Flags);
  2511. //
  2512. // If this is an async request then add it to our "handle" table &
  2513. // used the returned value for the request id passed to the server.
  2514. //
  2515. // TODO: would be faster to do this before the loop above so could
  2516. // bypass 1 or 2 loop iterations
  2517. //
  2518. if (pFuncArgs->Flags & ASYNC)
  2519. {
  2520. PASYNCREQUESTCONTEXT pContext;
  2521. if (pFuncArgs->Flags & INCL_CONTEXT)
  2522. {
  2523. pContext = (PASYNCREQUESTCONTEXT) pFuncArgs->Args[1];
  2524. pContext->dwKey = DRVASYNC_KEY;
  2525. ((PTAPI32_MSG) pTls->pBuf)->Params[1] = 0;
  2526. }
  2527. else
  2528. {
  2529. pContext = (PASYNCREQUESTCONTEXT) -1;
  2530. }
  2531. requestID =
  2532. ((PTAPI32_MSG) pTls->pBuf)->Params[0] = NewObject(
  2533. ghHandleTable,
  2534. pContext,
  2535. (LPVOID) pFuncArgs->Args[0] // the original request id
  2536. );
  2537. if (!requestID)
  2538. {
  2539. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2540. goto RemoteDoFunc_return;
  2541. }
  2542. }
  2543. //
  2544. // Impersonate the client. In some cases impersonation
  2545. // will fail, mostly likely because we're being called
  2546. // by a worker thread in tapisrv to close a line/call/
  2547. // phone object; what we do in this case is impersonate
  2548. // the logged on user (like the EventHandlerThread does).
  2549. //
  2550. if (!pTls->bAlreadyImpersonated)
  2551. {
  2552. RPC_STATUS status;
  2553. status = RpcImpersonateClient(0);
  2554. if (status == RPC_S_OK)
  2555. {
  2556. bRpcImpersonate = TRUE;
  2557. }
  2558. else
  2559. {
  2560. bRpcImpersonate = FALSE;
  2561. LOG((TL_ERROR,
  2562. "RemoteDoFunc: RpcImpersonateClient failed, err=%d",
  2563. status
  2564. ));
  2565. if (!SetProcessImpersonationToken (NULL))
  2566. {
  2567. LOG((TL_ERROR,
  2568. "RemoteDoFunc: SetProcessImpersToken failed, lastErr=%d",
  2569. GetLastError()
  2570. ));
  2571. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2572. goto RemoteDoFunc_return;
  2573. }
  2574. }
  2575. }
  2576. {
  2577. DWORD dwRetryCount = 0;
  2578. do
  2579. {
  2580. //
  2581. // check if the server is shutting down, to avoid making RPC request
  2582. // with invalid handle
  2583. //
  2584. if (pServer->bShutdown)
  2585. {
  2586. lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
  2587. break;
  2588. }
  2589. RpcTryExcept
  2590. {
  2591. ClientRequest(
  2592. pServer->phContext,
  2593. pTls->pBuf,
  2594. dwNeededSize,
  2595. &dwUsedSize
  2596. );
  2597. lResult = (LONG) ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
  2598. if (lResult == TAPIERR_INVALRPCCONTEXT)
  2599. {
  2600. OnServerDisconnected (pServer);
  2601. lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
  2602. }
  2603. break; // break out of do while
  2604. }
  2605. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  2606. {
  2607. if (dwRetryCount++ < gdwRetryCount)
  2608. {
  2609. Sleep (gdwRetryTimeout);
  2610. }
  2611. else
  2612. {
  2613. unsigned long ulResult = RpcExceptionCode();
  2614. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2615. if ((ulResult == RPC_S_SERVER_UNAVAILABLE) ||
  2616. (ulResult == ERROR_INVALID_HANDLE))
  2617. {
  2618. OnServerDisconnected (pServer);
  2619. lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
  2620. }
  2621. break;
  2622. }
  2623. }
  2624. RpcEndExcept
  2625. } while (TRUE); //while (dwRetryCount < gdwRetryCount);
  2626. }
  2627. if (!pTls->bAlreadyImpersonated)
  2628. {
  2629. if (bRpcImpersonate)
  2630. {
  2631. RpcRevertToSelf();
  2632. }
  2633. else
  2634. {
  2635. ClearImpersonationToken();
  2636. }
  2637. }
  2638. //
  2639. // Post-processing for async requests:
  2640. // SUCCESS - restore the original/local request id for return to tapi
  2641. // ERROR - dereference the new/remote request id to free it
  2642. //
  2643. if ((pFuncArgs->Flags & ASYNC))
  2644. {
  2645. if (lResult == (LONG)requestID)
  2646. {
  2647. lResult = (LONG) pFuncArgs->Args[0];
  2648. }
  2649. else // error
  2650. {
  2651. DereferenceObject (ghHandleTable, requestID, 1);
  2652. }
  2653. }
  2654. //
  2655. // Check if server returned REINIT (it's EventNotificationThread
  2656. // timed out on an rpc request so it thinks we're toast)
  2657. //
  2658. if (lResult == LINEERR_REINIT)
  2659. {
  2660. LOG((TL_ERROR, "server returned REINIT in RemoteDoFunc"));
  2661. OnServerDisconnected (pServer);
  2662. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2663. goto RemoteDoFunc_return;
  2664. }
  2665. //
  2666. // If request completed successfully and the bCopyOnSuccess flag
  2667. // is set then we need to copy data back to client buffer(s)
  2668. //
  2669. if ((lResult == TAPI_SUCCESS) && bCopyOnSuccess)
  2670. {
  2671. for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
  2672. {
  2673. PTAPI32_MSG pMsg = (PTAPI32_MSG) pTls->pBuf;
  2674. switch (pFuncArgs->ArgTypes[i])
  2675. {
  2676. case Dword:
  2677. case LineID:
  2678. case PhoneID:
  2679. case Hdcall:
  2680. case Hdline:
  2681. case Hdphone:
  2682. case lpsz:
  2683. case lpSet_Struct:
  2684. continue;
  2685. case lpServer:
  2686. --j;
  2687. continue;
  2688. case lpDword:
  2689. //
  2690. // Fill in the pointer with the return value
  2691. //
  2692. *((LPDWORD) pFuncArgs->Args[i]) = pMsg->Params[j];
  2693. continue;
  2694. case lpGet_SizeToFollow:
  2695. //
  2696. // Fill in the buf with the return data
  2697. //
  2698. CopyMemory(
  2699. (LPBYTE) pFuncArgs->Args[i],
  2700. pTls->pBuf + pMsg->Params[j] + sizeof(TAPI32_MSG),
  2701. pMsg->Params[j+1]
  2702. );
  2703. //
  2704. // Increment i (and j, since Size passed as arg in msg)
  2705. // to skip following Size arg in pFuncArgs->Args
  2706. //
  2707. i++;
  2708. j++;
  2709. continue;
  2710. case lpSet_SizeToFollow:
  2711. //
  2712. // Increment i (and j, since Size passed as arg in msg)
  2713. // to skip following Size arg in pFuncArgs->Args
  2714. //
  2715. i++;
  2716. j++;
  2717. continue;
  2718. case lpGet_Struct:
  2719. //
  2720. // Params[j] contains the offset in the var data
  2721. // portion of pTls->pBuf of some TAPI struct.
  2722. // Get the dwUsedSize value from this struct &
  2723. // copy that many bytes from pTls->pBuf to client buf
  2724. //
  2725. if (pMsg->Params[j] != TAPI_NO_DATA)
  2726. {
  2727. LPDWORD pStruct;
  2728. pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
  2729. pMsg->Params[j]);
  2730. CopyMemory(
  2731. (LPBYTE) pFuncArgs->Args[i],
  2732. (LPBYTE) pStruct,
  2733. *(pStruct + 2) // ptr to dwUsedSize field
  2734. );
  2735. }
  2736. continue;
  2737. case lpGet_CallParamsStruct:
  2738. //
  2739. // Params[j] contains the offset in the var data
  2740. // portion of pTls->pBuf of some TAPI struct.
  2741. // Get the dwUsedSize value from this struct &
  2742. // copy that many bytes from pTls->pBuf to client buf
  2743. //
  2744. if (pMsg->Params[j] != TAPI_NO_DATA)
  2745. {
  2746. LPDWORD pStruct;
  2747. pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
  2748. pMsg->Params[j]);
  2749. CopyMemory(
  2750. (LPBYTE) pFuncArgs->Args[i],
  2751. (LPBYTE) pStruct,
  2752. *(pStruct) // callparams has no dwusedsize
  2753. );
  2754. }
  2755. continue;
  2756. default:
  2757. continue;
  2758. }
  2759. }
  2760. }
  2761. RemoteDoFunc_return:
  2762. #if DBG
  2763. LOG((TL_INFO, "%s: exit, returning x%x", pszFuncName, lResult));
  2764. #endif
  2765. if (bNeedToReInit)
  2766. {
  2767. ASYNCEVENTMSG msg;
  2768. LOG((TL_INFO,
  2769. "Telephony server is no longer available. " \
  2770. "Sending REINIT message to TAPI"
  2771. ));
  2772. msg.TotalSize = sizeof(msg);
  2773. msg.InitContext = pServer->InitContext;
  2774. msg.fnPostProcessProcHandle = 0;
  2775. msg.hDevice = 0;
  2776. msg.Msg = LINE_LINEDEVSTATE;
  2777. msg.OpenContext = 0;
  2778. msg.Param1 = LINEDEVSTATE_REINIT;
  2779. msg.Param2 = RSP_MSG;
  2780. msg.Param3 = 0;
  2781. msg.Param4 = 0;
  2782. RemoteSPEventProc (NULL, (unsigned char *)&msg, sizeof(msg));
  2783. }
  2784. return lResult;
  2785. }
  2786. //
  2787. // --------------------------- TAPI_lineXxx funcs -----------------------------
  2788. //
  2789. LONG
  2790. TSPIAPI
  2791. TSPI_lineAccept(
  2792. DRV_REQUESTID dwRequestID,
  2793. HDRVCALL hdCall,
  2794. LPCSTR lpsUserUserInfo,
  2795. DWORD dwSize
  2796. )
  2797. {
  2798. static REMOTE_ARG_TYPES argTypes[] =
  2799. {
  2800. Dword,
  2801. Hdcall,
  2802. lpSet_SizeToFollow,
  2803. Size
  2804. };
  2805. ULONG_PTR args[] =
  2806. {
  2807. (ULONG_PTR) dwRequestID,
  2808. (ULONG_PTR) hdCall,
  2809. (ULONG_PTR) lpsUserUserInfo,
  2810. (ULONG_PTR) dwSize
  2811. };
  2812. REMOTE_FUNC_ARGS funcArgs =
  2813. {
  2814. MAKELONG (LINE_FUNC | ASYNC | 4, lAccept),
  2815. args,
  2816. argTypes
  2817. };
  2818. return (REMOTEDOFUNC (&funcArgs, "lineAccept"));
  2819. }
  2820. LONG
  2821. TSPIAPI
  2822. TSPI_lineAddToConference(
  2823. DRV_REQUESTID dwRequestID,
  2824. HDRVCALL hdConfCall,
  2825. HDRVCALL hdConsultCall
  2826. )
  2827. {
  2828. static REMOTE_ARG_TYPES argTypes[] =
  2829. {
  2830. Dword,
  2831. Hdcall,
  2832. Hdcall
  2833. };
  2834. ULONG_PTR args[] =
  2835. {
  2836. (ULONG_PTR) dwRequestID,
  2837. (ULONG_PTR) hdConfCall,
  2838. (ULONG_PTR) hdConsultCall
  2839. };
  2840. REMOTE_FUNC_ARGS funcArgs =
  2841. {
  2842. MAKELONG (LINE_FUNC | ASYNC | 3, lAddToConference),
  2843. args,
  2844. argTypes
  2845. };
  2846. return (REMOTEDOFUNC (&funcArgs, "lineAddToConference"));
  2847. }
  2848. void
  2849. PASCAL
  2850. TSPI_lineGetAgentxxx_PostProcess(
  2851. PASYNCEVENTMSG pMsg,
  2852. PASYNCREQUESTCONTEXT pContext
  2853. )
  2854. {
  2855. LOG((TL_INFO, "lineGetAgentxxx_PostProcess: enter"));
  2856. LOG((TL_INFO,
  2857. "\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
  2858. pMsg->Param1,
  2859. pMsg->Param2,
  2860. pMsg->Param3,
  2861. pMsg->Param4
  2862. ));
  2863. if (pMsg->Param2 == 0)
  2864. {
  2865. DWORD dwSize = (DWORD) pMsg->Param4;
  2866. LPBYTE pParams = (LPBYTE) pContext->Params[0];
  2867. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  2868. }
  2869. }
  2870. void
  2871. PASCAL
  2872. TSPI_lineDevSpecific_PostProcess(
  2873. PASYNCEVENTMSG pMsg,
  2874. PASYNCREQUESTCONTEXT pContext
  2875. );
  2876. LONG
  2877. TSPIAPI
  2878. TSPI_lineAgentSpecific(
  2879. DRV_REQUESTID dwRequestID,
  2880. HDRVLINE hdLine,
  2881. DWORD dwAddressID,
  2882. DWORD dwAgentExtensionIDIndex,
  2883. LPVOID lpParams,
  2884. DWORD dwSize
  2885. )
  2886. {
  2887. static REMOTE_ARG_TYPES argTypes[] =
  2888. {
  2889. Dword,
  2890. Dword,
  2891. Hdline,
  2892. Dword,
  2893. Dword,
  2894. Dword,
  2895. lpSet_SizeToFollow,
  2896. Size
  2897. };
  2898. ULONG_PTR args[] =
  2899. {
  2900. (ULONG_PTR) dwRequestID,
  2901. (ULONG_PTR) 0,
  2902. (ULONG_PTR) hdLine,
  2903. (ULONG_PTR) dwAddressID,
  2904. (ULONG_PTR) dwAgentExtensionIDIndex,
  2905. (ULONG_PTR) 0,
  2906. (ULONG_PTR) lpParams,
  2907. (ULONG_PTR) dwSize
  2908. };
  2909. REMOTE_FUNC_ARGS funcArgs =
  2910. {
  2911. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 8, lAgentSpecific),
  2912. args,
  2913. argTypes
  2914. };
  2915. PASYNCREQUESTCONTEXT pContext;
  2916. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  2917. {
  2918. return LINEERR_NOMEM;
  2919. }
  2920. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  2921. TSPI_lineDevSpecific_PostProcess;
  2922. pContext->Params[0] = (ULONG_PTR) lpParams;
  2923. pContext->Params[1] = dwSize;
  2924. args[1] = (ULONG_PTR) pContext;
  2925. argTypes[1] = lpContext;
  2926. return (REMOTEDOFUNC (&funcArgs, "lAgentSpecific"));
  2927. }
  2928. LONG
  2929. TSPIAPI
  2930. TSPI_lineAnswer(
  2931. DRV_REQUESTID dwRequestID,
  2932. HDRVCALL hdCall,
  2933. LPCSTR lpsUserUserInfo,
  2934. DWORD dwSize
  2935. )
  2936. {
  2937. static REMOTE_ARG_TYPES argTypes[] =
  2938. {
  2939. Dword,
  2940. Hdcall,
  2941. lpSet_SizeToFollow,
  2942. Size
  2943. };
  2944. ULONG_PTR args[] =
  2945. {
  2946. (ULONG_PTR) dwRequestID,
  2947. (ULONG_PTR) hdCall,
  2948. (ULONG_PTR) lpsUserUserInfo,
  2949. (ULONG_PTR) dwSize
  2950. };
  2951. REMOTE_FUNC_ARGS funcArgs =
  2952. {
  2953. MAKELONG (LINE_FUNC | ASYNC | 4, lAnswer),
  2954. args,
  2955. argTypes
  2956. };
  2957. return (REMOTEDOFUNC (&funcArgs, "lineAnswer"));
  2958. }
  2959. LONG
  2960. TSPIAPI
  2961. TSPI_lineBlindTransfer(
  2962. DRV_REQUESTID dwRequestID,
  2963. HDRVCALL hdCall,
  2964. LPCWSTR lpszDestAddress,
  2965. DWORD dwCountryCode
  2966. )
  2967. {
  2968. static REMOTE_ARG_TYPES argTypes[] =
  2969. {
  2970. Dword,
  2971. Hdcall,
  2972. lpsz,
  2973. Dword
  2974. };
  2975. ULONG_PTR args[] =
  2976. {
  2977. (ULONG_PTR) dwRequestID,
  2978. (ULONG_PTR) hdCall,
  2979. (ULONG_PTR) lpszDestAddress,
  2980. (ULONG_PTR) dwCountryCode
  2981. };
  2982. REMOTE_FUNC_ARGS funcArgs =
  2983. {
  2984. MAKELONG (LINE_FUNC | ASYNC | 4, lBlindTransfer),
  2985. args,
  2986. argTypes
  2987. };
  2988. return (REMOTEDOFUNC (&funcArgs, "lineBlindTransfer"));
  2989. }
  2990. LONG
  2991. TSPIAPI
  2992. TSPI_lineClose(
  2993. HDRVLINE hdLine
  2994. )
  2995. {
  2996. //
  2997. // Check if the hLine is still valid (could have been zeroed
  2998. // out on LINE_CLOSE, so no need to call server)
  2999. //
  3000. if (((PDRVLINE) hdLine)->hLine)
  3001. {
  3002. static REMOTE_ARG_TYPES argTypes[] =
  3003. {
  3004. Hdline
  3005. };
  3006. REMOTE_FUNC_ARGS funcArgs =
  3007. {
  3008. MAKELONG (LINE_FUNC | SYNC | 1, lClose),
  3009. (ULONG_PTR *) &hdLine,
  3010. argTypes
  3011. };
  3012. DereferenceObject(
  3013. ghHandleTable,
  3014. ((PDRVLINE) hdLine)->hDeviceCallback,
  3015. 1
  3016. );
  3017. EnterCriticalSection (&gCallListCriticalSection);
  3018. ((PDRVLINE) hdLine)->htLine = 0;
  3019. ((PDRVLINE) hdLine)->hDeviceCallback = 0;
  3020. LeaveCriticalSection (&gCallListCriticalSection);
  3021. REMOTEDOFUNC (&funcArgs, "lineClose");
  3022. }
  3023. //assert (((PDRVLINE) hdLine)->pCalls == NULL);
  3024. return 0;
  3025. }
  3026. LONG
  3027. TSPIAPI
  3028. TSPI_lineCloseCall(
  3029. HDRVCALL hdCall
  3030. )
  3031. {
  3032. PDRVCALL pCall = (PDRVCALL) hdCall;
  3033. HTAPICALL htCall;
  3034. //
  3035. // Check if the hCall is still valid (could have been zeroed
  3036. // out on LINE_CLOSE, so no need to call server)
  3037. //
  3038. LOG((TL_INFO, "TSPI_lineCloseCall - pCall x%lx", hdCall));
  3039. EnterCriticalSection (&gCallListCriticalSection);
  3040. if (IsValidObject (pCall, DRVCALL_KEY))
  3041. {
  3042. htCall = pCall->htCall;
  3043. }
  3044. else
  3045. {
  3046. htCall = 0;
  3047. }
  3048. LeaveCriticalSection (&gCallListCriticalSection);
  3049. if (htCall)
  3050. {
  3051. static REMOTE_ARG_TYPES argTypes[] =
  3052. {
  3053. Hdcall
  3054. };
  3055. REMOTE_FUNC_ARGS funcArgs =
  3056. {
  3057. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall), // API differs
  3058. (ULONG_PTR *) &hdCall,
  3059. argTypes
  3060. };
  3061. REMOTEDOFUNC (&funcArgs, "lineCloseCall");
  3062. EnterCriticalSection (&gCallListCriticalSection);
  3063. RemoveCallFromList (pCall);
  3064. LeaveCriticalSection (&gCallListCriticalSection);
  3065. }
  3066. return 0;
  3067. }
  3068. void
  3069. PASCAL
  3070. TSPI_lineCompleteCall_PostProcess(
  3071. PASYNCEVENTMSG pMsg,
  3072. PASYNCREQUESTCONTEXT pContext
  3073. )
  3074. {
  3075. LOG((TL_INFO, "lineCompleteCall PostProcess: enter"));
  3076. LOG((TL_INFO,
  3077. "\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
  3078. pMsg->Param1,
  3079. pMsg->Param2,
  3080. pMsg->Param3,
  3081. pMsg->Param4
  3082. ));
  3083. if (pMsg->Param2 == 0)
  3084. {
  3085. LPDWORD lpdwCompletionID = (LPDWORD) pContext->Params[0];
  3086. *lpdwCompletionID = (DWORD) pMsg->Param3;
  3087. }
  3088. }
  3089. LONG
  3090. TSPIAPI
  3091. TSPI_lineCompleteCall(
  3092. DRV_REQUESTID dwRequestID,
  3093. HDRVCALL hdCall,
  3094. LPDWORD lpdwCompletionID,
  3095. DWORD dwCompletionMode,
  3096. DWORD dwMessageID
  3097. )
  3098. {
  3099. static REMOTE_ARG_TYPES argTypes[] =
  3100. {
  3101. Dword,
  3102. Dword,
  3103. Hdcall,
  3104. Dword,
  3105. Dword,
  3106. Dword
  3107. };
  3108. ULONG_PTR args[] =
  3109. {
  3110. (ULONG_PTR) dwRequestID,
  3111. (ULONG_PTR) 0,
  3112. (ULONG_PTR) hdCall,
  3113. (ULONG_PTR) 0,
  3114. (ULONG_PTR) dwCompletionMode,
  3115. (ULONG_PTR) dwMessageID
  3116. };
  3117. REMOTE_FUNC_ARGS funcArgs =
  3118. {
  3119. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lCompleteCall),
  3120. args,
  3121. argTypes
  3122. };
  3123. PASYNCREQUESTCONTEXT pContext;
  3124. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3125. {
  3126. return LINEERR_NOMEM;
  3127. }
  3128. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3129. TSPI_lineCompleteCall_PostProcess;
  3130. pContext->Params[0] = (ULONG_PTR) lpdwCompletionID;
  3131. args[1] = (ULONG_PTR) pContext;
  3132. argTypes[1] = lpContext;
  3133. return (REMOTEDOFUNC (&funcArgs, "lineCompleteCall"));
  3134. }
  3135. LONG
  3136. TSPIAPI
  3137. TSPI_lineCompleteTransfer(
  3138. DRV_REQUESTID dwRequestID,
  3139. HDRVCALL hdCall,
  3140. HDRVCALL hdConsultCall,
  3141. HTAPICALL htConfCall,
  3142. LPHDRVCALL lphdConfCall,
  3143. DWORD dwTransferMode
  3144. )
  3145. {
  3146. static REMOTE_ARG_TYPES argTypes[] =
  3147. {
  3148. Dword,
  3149. Dword,
  3150. Hdcall,
  3151. Hdcall,
  3152. Dword,
  3153. Dword
  3154. };
  3155. ULONG_PTR args[] =
  3156. {
  3157. (ULONG_PTR) dwRequestID,
  3158. (ULONG_PTR) 0,
  3159. (ULONG_PTR) hdCall,
  3160. (ULONG_PTR) hdConsultCall,
  3161. (ULONG_PTR) 0,
  3162. (ULONG_PTR) dwTransferMode
  3163. };
  3164. REMOTE_FUNC_ARGS funcArgs =
  3165. {
  3166. MAKELONG (LINE_FUNC | ASYNC | 6, lCompleteTransfer),
  3167. args,
  3168. argTypes
  3169. };
  3170. LONG lResult;
  3171. PDRVCALL pConfCall;
  3172. if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
  3173. {
  3174. PASYNCREQUESTCONTEXT pContext;
  3175. if (!(pConfCall = DrvAlloc (sizeof (DRVCALL))))
  3176. {
  3177. return LINEERR_NOMEM;
  3178. }
  3179. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3180. {
  3181. DrvFree (pConfCall);
  3182. return LINEERR_NOMEM;
  3183. }
  3184. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3185. TSPI_lineMakeCall_PostProcess;
  3186. pContext->Params[0] = (ULONG_PTR) pConfCall;
  3187. args[1] = (ULONG_PTR) pContext;
  3188. argTypes[1] = lpContext;
  3189. funcArgs.Flags |= INCL_CONTEXT;
  3190. //
  3191. // Assume success & add the call to the line's list before we
  3192. // even make the request. This makes cleanup alot easier if
  3193. // the server goes down or some such uncooth event.
  3194. //
  3195. pConfCall->dwOriginalRequestID = dwRequestID;
  3196. pConfCall->htCall = htConfCall;
  3197. pConfCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  3198. AddCallToList ((PDRVLINE) ((PDRVCALL) hdCall)->pLine, pConfCall);
  3199. *lphdConfCall = (HDRVCALL) pConfCall;
  3200. }
  3201. else
  3202. {
  3203. pConfCall = NULL;
  3204. }
  3205. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineCompleteTransfer")) < 0)
  3206. {
  3207. if (pConfCall)
  3208. {
  3209. RemoveCallFromList (pConfCall);
  3210. }
  3211. }
  3212. return lResult;
  3213. }
  3214. LONG
  3215. TSPIAPI
  3216. TSPI_lineConditionalMediaDetection(
  3217. HDRVLINE hdLine,
  3218. DWORD dwMediaModes,
  3219. LPLINECALLPARAMS const lpCallParams
  3220. )
  3221. {
  3222. static REMOTE_ARG_TYPES argTypes[] =
  3223. {
  3224. Hdline,
  3225. Dword,
  3226. lpSet_Struct,
  3227. Dword
  3228. };
  3229. ULONG_PTR args[] =
  3230. {
  3231. (ULONG_PTR) hdLine,
  3232. (ULONG_PTR) dwMediaModes,
  3233. (ULONG_PTR) lpCallParams,
  3234. (ULONG_PTR) 0xFFFFFFFF
  3235. };
  3236. REMOTE_FUNC_ARGS funcArgs =
  3237. {
  3238. MAKELONG (LINE_FUNC | SYNC | 4, lConditionalMediaDetection),
  3239. args,
  3240. argTypes
  3241. };
  3242. return (REMOTEDOFUNC (&funcArgs, "lineConditionalMediaDetection"));
  3243. }
  3244. void
  3245. PASCAL
  3246. TSPI_lineDevSpecific_PostProcess(
  3247. PASYNCEVENTMSG pMsg,
  3248. PASYNCREQUESTCONTEXT pContext
  3249. )
  3250. {
  3251. LOG((TL_INFO, "lineDevSpecificPostProcess: enter"));
  3252. if (pMsg->Param2 == 0)
  3253. {
  3254. DWORD dwSize = (DWORD) pContext->Params[1];
  3255. LPBYTE pParams = (LPBYTE) pContext->Params[0];
  3256. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  3257. }
  3258. }
  3259. LONG
  3260. TSPIAPI
  3261. TSPI_lineCreateAgent(
  3262. DRV_REQUESTID dwRequestID,
  3263. HDRVLINE hdLine,
  3264. LPWSTR lpszAgentID,
  3265. LPWSTR lpszAgentPIN,
  3266. LPHAGENT lphAgent
  3267. )
  3268. {
  3269. REMOTE_ARG_TYPES argTypes[] =
  3270. {
  3271. Dword,
  3272. Dword,
  3273. Hdline,
  3274. lpszAgentID?lpsz:Dword,
  3275. lpszAgentPIN?lpsz:Dword,
  3276. Dword
  3277. };
  3278. ULONG_PTR args[] =
  3279. {
  3280. (ULONG_PTR) dwRequestID,
  3281. (ULONG_PTR) 0,
  3282. (ULONG_PTR) hdLine,
  3283. (ULONG_PTR) lpszAgentID,
  3284. (ULONG_PTR) lpszAgentPIN,
  3285. (ULONG_PTR) 0
  3286. };
  3287. REMOTE_FUNC_ARGS funcArgs =
  3288. {
  3289. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lCreateAgent),
  3290. args,
  3291. argTypes
  3292. };
  3293. PASYNCREQUESTCONTEXT pContext;
  3294. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3295. {
  3296. return LINEERR_NOMEM;
  3297. }
  3298. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3299. TSPI_lineGetAgentxxx_PostProcess;
  3300. pContext->Params[0] = (ULONG_PTR) lphAgent;
  3301. args[1] = (ULONG_PTR) pContext;
  3302. argTypes[1] = lpContext;
  3303. if ( lpszAgentID == NULL )
  3304. {
  3305. funcArgs.Args[3] = TAPI_NO_DATA;
  3306. funcArgs.ArgTypes[3] = Dword;
  3307. }
  3308. if ( lpszAgentPIN == NULL)
  3309. {
  3310. funcArgs.Args[4] = TAPI_NO_DATA;
  3311. funcArgs.ArgTypes[4] = Dword;
  3312. }
  3313. return (REMOTEDOFUNC (&funcArgs, "lCreateAgent"));
  3314. }
  3315. LONG
  3316. TSPIAPI
  3317. TSPI_lineCreateAgentSession(
  3318. DRV_REQUESTID dwRequestID,
  3319. HDRVLINE hdLine,
  3320. HAGENT hAgent,
  3321. LPWSTR lpszAgentPIN,
  3322. DWORD dwWorkingAddressID,
  3323. LPGUID lpGroupID,
  3324. LPHAGENTSESSION lphAgentSession
  3325. )
  3326. {
  3327. REMOTE_ARG_TYPES argTypes[] =
  3328. {
  3329. Dword,
  3330. Dword,
  3331. Hdline,
  3332. Dword,
  3333. lpszAgentPIN ? lpsz : Dword,
  3334. Dword,
  3335. lpSet_SizeToFollow,
  3336. Size,
  3337. Dword
  3338. };
  3339. ULONG_PTR args[] =
  3340. {
  3341. (ULONG_PTR) dwRequestID,
  3342. (ULONG_PTR) 0,
  3343. (ULONG_PTR) hdLine,
  3344. (ULONG_PTR) hAgent,
  3345. (ULONG_PTR) lpszAgentPIN,
  3346. (ULONG_PTR) dwWorkingAddressID,
  3347. (ULONG_PTR) lpGroupID,
  3348. (ULONG_PTR) sizeof(GUID),
  3349. (ULONG_PTR) 0
  3350. };
  3351. REMOTE_FUNC_ARGS funcArgs =
  3352. {
  3353. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 9, lCreateAgentSession),
  3354. args,
  3355. argTypes
  3356. };
  3357. PASYNCREQUESTCONTEXT pContext;
  3358. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3359. {
  3360. return LINEERR_NOMEM;
  3361. }
  3362. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3363. TSPI_lineGetAgentxxx_PostProcess;
  3364. pContext->Params[0] = (ULONG_PTR) lphAgentSession;
  3365. args[1] = (ULONG_PTR) pContext;
  3366. argTypes[1] = lpContext;
  3367. if ( lpszAgentPIN == NULL )
  3368. {
  3369. funcArgs.Args[4] = TAPI_NO_DATA;
  3370. funcArgs.ArgTypes[4] = Dword;
  3371. }
  3372. return (REMOTEDOFUNC (&funcArgs, "lCreateAgentSession"));
  3373. }
  3374. LONG
  3375. TSPIAPI
  3376. TSPI_lineDevSpecific(
  3377. DRV_REQUESTID dwRequestID,
  3378. HDRVLINE hdLine,
  3379. DWORD dwAddressID,
  3380. HDRVCALL hdCall,
  3381. LPVOID lpParams,
  3382. DWORD dwSize
  3383. )
  3384. {
  3385. REMOTE_ARG_TYPES argTypes[] =
  3386. {
  3387. Dword,
  3388. Dword,
  3389. Hdline,
  3390. Dword,
  3391. (hdCall ? Hdcall : Dword ),
  3392. Dword,
  3393. lpSet_SizeToFollow,
  3394. Size
  3395. };
  3396. ULONG_PTR args[] =
  3397. {
  3398. (ULONG_PTR) dwRequestID,
  3399. (ULONG_PTR) 0,
  3400. (ULONG_PTR) hdLine,
  3401. (ULONG_PTR) dwAddressID,
  3402. (ULONG_PTR) hdCall,
  3403. (ULONG_PTR) 0,
  3404. (ULONG_PTR) lpParams, // pass data
  3405. (ULONG_PTR) dwSize
  3406. };
  3407. REMOTE_FUNC_ARGS funcArgs =
  3408. {
  3409. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 8, lDevSpecific),
  3410. args,
  3411. argTypes
  3412. };
  3413. PASYNCREQUESTCONTEXT pContext;
  3414. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3415. {
  3416. return LINEERR_NOMEM;
  3417. }
  3418. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3419. TSPI_lineDevSpecific_PostProcess;
  3420. pContext->Params[0] = (ULONG_PTR) lpParams;
  3421. pContext->Params[1] = dwSize;
  3422. args[1] = (ULONG_PTR) pContext;
  3423. argTypes[1] = lpContext;
  3424. return (REMOTEDOFUNC (&funcArgs, "lineDevSpecific"));
  3425. }
  3426. LONG
  3427. TSPIAPI
  3428. TSPI_lineDevSpecificFeature(
  3429. DRV_REQUESTID dwRequestID,
  3430. HDRVLINE hdLine,
  3431. DWORD dwFeature,
  3432. LPVOID lpParams,
  3433. DWORD dwSize
  3434. )
  3435. {
  3436. static REMOTE_ARG_TYPES argTypes[] =
  3437. {
  3438. Dword,
  3439. Dword,
  3440. Hdline,
  3441. Dword,
  3442. Dword,
  3443. lpSet_SizeToFollow,
  3444. Size
  3445. };
  3446. ULONG_PTR args[] =
  3447. {
  3448. (ULONG_PTR) dwRequestID,
  3449. (ULONG_PTR) 0,
  3450. (ULONG_PTR) hdLine,
  3451. (ULONG_PTR) dwFeature,
  3452. (ULONG_PTR) 0,
  3453. (ULONG_PTR) lpParams, // pass data
  3454. (ULONG_PTR) dwSize
  3455. };
  3456. REMOTE_FUNC_ARGS funcArgs =
  3457. {
  3458. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 7, lDevSpecificFeature),
  3459. args,
  3460. argTypes
  3461. };
  3462. PASYNCREQUESTCONTEXT pContext;
  3463. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3464. {
  3465. return LINEERR_NOMEM;
  3466. }
  3467. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3468. TSPI_lineDevSpecific_PostProcess;
  3469. pContext->Params[0] = (ULONG_PTR) lpParams;
  3470. pContext->Params[1] = dwSize;
  3471. args[1] = (ULONG_PTR) pContext;
  3472. argTypes[1] = lpContext;
  3473. return (REMOTEDOFUNC (&funcArgs, "lineDevSpecificFeature"));
  3474. }
  3475. LONG
  3476. TSPIAPI
  3477. TSPI_lineDial(
  3478. DRV_REQUESTID dwRequestID,
  3479. HDRVCALL hdCall,
  3480. LPCWSTR lpszDestAddress,
  3481. DWORD dwCountryCode
  3482. )
  3483. {
  3484. static REMOTE_ARG_TYPES argTypes[] =
  3485. {
  3486. Dword,
  3487. Hdcall,
  3488. lpsz,
  3489. Dword
  3490. };
  3491. ULONG_PTR args[] =
  3492. {
  3493. (ULONG_PTR) dwRequestID,
  3494. (ULONG_PTR) hdCall,
  3495. (ULONG_PTR) lpszDestAddress,
  3496. (ULONG_PTR) dwCountryCode
  3497. };
  3498. REMOTE_FUNC_ARGS funcArgs =
  3499. {
  3500. MAKELONG (LINE_FUNC | ASYNC | 4, lDial),
  3501. args,
  3502. argTypes
  3503. };
  3504. return (REMOTEDOFUNC (&funcArgs, "lineDial"));
  3505. }
  3506. LONG
  3507. TSPIAPI
  3508. TSPI_lineDrop(
  3509. DRV_REQUESTID dwRequestID,
  3510. HDRVCALL hdCall,
  3511. LPCSTR lpsUserUserInfo,
  3512. DWORD dwSize
  3513. )
  3514. {
  3515. static REMOTE_ARG_TYPES argTypes[] =
  3516. {
  3517. Dword,
  3518. Hdcall,
  3519. lpSet_SizeToFollow,
  3520. Size
  3521. };
  3522. ULONG_PTR args[] =
  3523. {
  3524. (ULONG_PTR) dwRequestID,
  3525. (ULONG_PTR) hdCall,
  3526. (ULONG_PTR) lpsUserUserInfo,
  3527. (ULONG_PTR) dwSize
  3528. };
  3529. REMOTE_FUNC_ARGS funcArgs =
  3530. {
  3531. MAKELONG (LINE_FUNC | ASYNC | 4, lDrop),
  3532. args,
  3533. argTypes
  3534. };
  3535. return (REMOTEDOFUNC (&funcArgs, "lineDrop"));
  3536. }
  3537. LONG
  3538. TSPIAPI
  3539. TSPI_lineForward(
  3540. DRV_REQUESTID dwRequestID,
  3541. HDRVLINE hdLine,
  3542. DWORD bAllAddresses,
  3543. DWORD dwAddressID,
  3544. LPLINEFORWARDLIST const lpForwardList,
  3545. DWORD dwNumRingsNoAnswer,
  3546. HTAPICALL htConsultCall,
  3547. LPHDRVCALL lphdConsultCall,
  3548. LPLINECALLPARAMS const lpCallParams
  3549. )
  3550. {
  3551. static REMOTE_ARG_TYPES argTypes[] =
  3552. {
  3553. Dword,
  3554. Dword,
  3555. Hdline,
  3556. Dword,
  3557. Dword,
  3558. lpSet_Struct,
  3559. Dword,
  3560. Dword,
  3561. lpSet_Struct,
  3562. Dword
  3563. };
  3564. PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
  3565. ULONG_PTR args[] =
  3566. {
  3567. (ULONG_PTR) dwRequestID,
  3568. (ULONG_PTR) 0,
  3569. (ULONG_PTR) hdLine,
  3570. (ULONG_PTR) bAllAddresses,
  3571. (ULONG_PTR) dwAddressID,
  3572. (ULONG_PTR) lpForwardList,
  3573. (ULONG_PTR) dwNumRingsNoAnswer,
  3574. (ULONG_PTR) 0,
  3575. (ULONG_PTR) lpCallParams,
  3576. (ULONG_PTR) 0xFFFFFFFF
  3577. };
  3578. REMOTE_FUNC_ARGS funcArgs =
  3579. {
  3580. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 10, lForward),
  3581. args,
  3582. argTypes
  3583. };
  3584. LONG lResult;
  3585. if (pCall)
  3586. {
  3587. PASYNCREQUESTCONTEXT pContext;
  3588. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3589. {
  3590. DrvFree (pCall);
  3591. return LINEERR_NOMEM;
  3592. }
  3593. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3594. TSPI_lineMakeCall_PostProcess;
  3595. pContext->Params[0] = (ULONG_PTR) pCall;
  3596. pContext->Params[1] = (ULONG_PTR) lphdConsultCall;
  3597. // save the ptr in case we need to NULL-ify later
  3598. args[1] = (ULONG_PTR) pContext;
  3599. argTypes[1] = lpContext;
  3600. pCall->htCall = htConsultCall;
  3601. pCall->dwOriginalRequestID = dwRequestID;
  3602. pCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  3603. AddCallToList ((PDRVLINE) hdLine, pCall);
  3604. *lphdConsultCall = (HDRVCALL) pCall;
  3605. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineForward")) < 0)
  3606. {
  3607. RemoveCallFromList (pCall);
  3608. }
  3609. }
  3610. else
  3611. {
  3612. lResult = LINEERR_NOMEM;
  3613. }
  3614. return lResult;
  3615. }
  3616. void
  3617. PASCAL
  3618. TSPI_lineGatherDigits_PostProcess(
  3619. PASYNCEVENTMSG pMsg
  3620. )
  3621. {
  3622. DWORD dwEndToEndIDRemoteSP = ((DWORD *)(pMsg + 1))[0];
  3623. PASYNCREQUESTCONTEXT pContext;
  3624. LOG((TL_INFO, "TSPI_lineGatherDigits_PostProcess: enter"));
  3625. if ((pContext = ReferenceObject(
  3626. ghHandleTable,
  3627. dwEndToEndIDRemoteSP,
  3628. 0
  3629. )))
  3630. {
  3631. if (pMsg->Param1 &
  3632. (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
  3633. LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
  3634. {
  3635. LPSTR lpsDigits = (LPSTR) pContext->Params[0];
  3636. DWORD dwNumDigits = (DWORD) pMsg->Param4;
  3637. LPCWSTR pBuffer = (LPCWSTR) ( ( (DWORD *) (pMsg + 1) ) + 2);
  3638. try
  3639. {
  3640. CopyMemory (lpsDigits, pBuffer, dwNumDigits * sizeof(WCHAR));
  3641. }
  3642. except (EXCEPTION_EXECUTE_HANDLER)
  3643. {
  3644. }
  3645. }
  3646. pMsg->Param2 = DWORD_CAST(pContext->Params[1],__FILE__,__LINE__);
  3647. DereferenceObject (ghHandleTable, dwEndToEndIDRemoteSP, 2);
  3648. }
  3649. else
  3650. {
  3651. pMsg->Param2 = 0;
  3652. }
  3653. }
  3654. LONG
  3655. TSPIAPI
  3656. TSPI_lineGatherDigits(
  3657. HDRVCALL hdCall,
  3658. DWORD dwEndToEndID,
  3659. DWORD dwDigitModes,
  3660. LPWSTR lpsDigits,
  3661. DWORD dwNumDigits,
  3662. LPCWSTR lpszTerminationDigits,
  3663. DWORD dwFirstDigitTimeout,
  3664. DWORD dwInterDigitTimeout
  3665. )
  3666. {
  3667. static REMOTE_ARG_TYPES argTypes[] =
  3668. {
  3669. Dword,
  3670. Hdcall,
  3671. Dword,
  3672. Dword,
  3673. Dword,
  3674. Dword,
  3675. lpsz,
  3676. Dword,
  3677. Dword
  3678. };
  3679. ULONG_PTR args[] =
  3680. {
  3681. (ULONG_PTR) 0,
  3682. (ULONG_PTR) hdCall,
  3683. (ULONG_PTR) 0, // dwEndToEndID,
  3684. (ULONG_PTR) dwDigitModes,
  3685. (ULONG_PTR) 0, // lpsDigits,
  3686. (ULONG_PTR) dwNumDigits,
  3687. (ULONG_PTR) lpszTerminationDigits,
  3688. (ULONG_PTR) dwFirstDigitTimeout,
  3689. (ULONG_PTR) dwInterDigitTimeout
  3690. };
  3691. REMOTE_FUNC_ARGS funcArgs =
  3692. {
  3693. MAKELONG (LINE_FUNC | SYNC | 9, lGatherDigits),
  3694. args,
  3695. argTypes
  3696. };
  3697. PASYNCREQUESTCONTEXT pContext;
  3698. if (lpsDigits)
  3699. {
  3700. if (IsBadWritePtr (lpsDigits, dwNumDigits * sizeof(WCHAR)))
  3701. {
  3702. return LINEERR_INVALPOINTER;
  3703. }
  3704. if (!(pContext = DrvAlloc (sizeof(*pContext))))
  3705. {
  3706. return LINEERR_NOMEM;
  3707. }
  3708. pContext->Params[0] = (ULONG_PTR) lpsDigits;
  3709. pContext->Params[1] = dwEndToEndID;
  3710. if (!(args[2] = NewObject (ghHandleTable, pContext, NULL)))
  3711. {
  3712. DrvFree (pContext);
  3713. return LINEERR_NOMEM;
  3714. }
  3715. args[4] = 1; // Set the lpsDigits param to something non-zero
  3716. }
  3717. if (lpszTerminationDigits == (LPCWSTR) NULL)
  3718. {
  3719. funcArgs.ArgTypes[6] = Dword;
  3720. funcArgs.Args[6] = TAPI_NO_DATA;
  3721. }
  3722. return (REMOTEDOFUNC (&funcArgs, "lineGatherDigits"));
  3723. }
  3724. LONG
  3725. TSPIAPI
  3726. TSPI_lineGenerateDigits(
  3727. HDRVCALL hdCall,
  3728. DWORD dwEndToEndID,
  3729. DWORD dwDigitMode,
  3730. LPCWSTR lpszDigits,
  3731. DWORD dwDuration
  3732. )
  3733. {
  3734. static REMOTE_ARG_TYPES argTypes[] =
  3735. {
  3736. Hdcall,
  3737. Dword,
  3738. lpsz,
  3739. Dword,
  3740. Dword
  3741. };
  3742. ULONG_PTR args[] =
  3743. {
  3744. (ULONG_PTR) hdCall,
  3745. (ULONG_PTR) dwDigitMode,
  3746. (ULONG_PTR) lpszDigits,
  3747. (ULONG_PTR) dwDuration,
  3748. (ULONG_PTR) dwEndToEndID,
  3749. };
  3750. REMOTE_FUNC_ARGS funcArgs =
  3751. {
  3752. MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
  3753. args,
  3754. argTypes
  3755. };
  3756. return (REMOTEDOFUNC (&funcArgs, "lineGenerateDigits"));
  3757. }
  3758. LONG
  3759. TSPIAPI
  3760. TSPI_lineGenerateTone(
  3761. HDRVCALL hdCall,
  3762. DWORD dwEndToEndID,
  3763. DWORD dwToneMode,
  3764. DWORD dwDuration,
  3765. DWORD dwNumTones,
  3766. LPLINEGENERATETONE const lpTones
  3767. )
  3768. {
  3769. REMOTE_ARG_TYPES argTypes[] =
  3770. {
  3771. Hdcall,
  3772. Dword,
  3773. Dword,
  3774. Dword,
  3775. Dword,
  3776. Dword,
  3777. Dword
  3778. };
  3779. ULONG_PTR args[] =
  3780. {
  3781. (ULONG_PTR) hdCall,
  3782. (ULONG_PTR) dwToneMode,
  3783. (ULONG_PTR) dwDuration,
  3784. (ULONG_PTR) dwNumTones,
  3785. (ULONG_PTR) TAPI_NO_DATA,
  3786. (ULONG_PTR) 0,
  3787. (ULONG_PTR) dwEndToEndID
  3788. };
  3789. REMOTE_FUNC_ARGS funcArgs =
  3790. {
  3791. MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
  3792. args,
  3793. argTypes
  3794. };
  3795. if (dwToneMode == LINETONEMODE_CUSTOM)
  3796. {
  3797. argTypes[4] = lpSet_SizeToFollow;
  3798. args[4] = (ULONG_PTR) lpTones;
  3799. argTypes[5] = Size;
  3800. args[5] = dwNumTones * sizeof(LINEGENERATETONE);
  3801. }
  3802. return (REMOTEDOFUNC (&funcArgs, "lineGenerateTone"));
  3803. }
  3804. LONG
  3805. TSPIAPI
  3806. TSPI_lineGetAddressCaps(
  3807. DWORD dwDeviceID,
  3808. DWORD dwAddressID,
  3809. DWORD dwTSPIVersion,
  3810. DWORD dwExtVersion,
  3811. LPLINEADDRESSCAPS lpAddressCaps
  3812. )
  3813. {
  3814. static REMOTE_ARG_TYPES argTypes[] =
  3815. {
  3816. Dword,
  3817. LineID,
  3818. Dword,
  3819. Dword,
  3820. Dword,
  3821. lpGet_Struct
  3822. };
  3823. ULONG_PTR args[] =
  3824. {
  3825. (ULONG_PTR) 0,
  3826. (ULONG_PTR) dwDeviceID,
  3827. (ULONG_PTR) dwAddressID,
  3828. (ULONG_PTR) dwTSPIVersion,
  3829. (ULONG_PTR) dwExtVersion,
  3830. (ULONG_PTR) lpAddressCaps,
  3831. };
  3832. REMOTE_FUNC_ARGS funcArgs =
  3833. {
  3834. MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
  3835. args,
  3836. argTypes
  3837. };
  3838. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  3839. if (NULL == pLine)
  3840. {
  3841. return LINEERR_BADDEVICEID;
  3842. }
  3843. args[0] = pLine->pServer->hLineApp;
  3844. return (REMOTEDOFUNC (&funcArgs, "lineGetAddressCaps"));
  3845. }
  3846. LONG
  3847. TSPIAPI
  3848. TSPI_lineGetAddressID(
  3849. HDRVLINE hdLine,
  3850. LPDWORD lpdwAddressID,
  3851. DWORD dwAddressMode,
  3852. LPCWSTR lpsAddress,
  3853. DWORD dwSize
  3854. )
  3855. {
  3856. static REMOTE_ARG_TYPES argTypes[] =
  3857. {
  3858. Hdline,
  3859. lpDword,
  3860. Dword,
  3861. lpSet_SizeToFollow,
  3862. Size
  3863. };
  3864. ULONG_PTR args[] =
  3865. {
  3866. (ULONG_PTR) hdLine,
  3867. (ULONG_PTR) lpdwAddressID,
  3868. (ULONG_PTR) dwAddressMode,
  3869. (ULONG_PTR) lpsAddress,
  3870. (ULONG_PTR) dwSize
  3871. };
  3872. REMOTE_FUNC_ARGS funcArgs =
  3873. {
  3874. MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
  3875. args,
  3876. argTypes
  3877. };
  3878. return (REMOTEDOFUNC (&funcArgs, "lineGetAddressID"));
  3879. }
  3880. LONG
  3881. TSPIAPI
  3882. TSPI_lineGetAddressStatus(
  3883. HDRVLINE hdLine,
  3884. DWORD dwAddressID,
  3885. LPLINEADDRESSSTATUS lpAddressStatus
  3886. )
  3887. {
  3888. static REMOTE_ARG_TYPES argTypes[] =
  3889. {
  3890. Hdline,
  3891. Dword,
  3892. lpGet_Struct
  3893. };
  3894. ULONG_PTR args[] =
  3895. {
  3896. (ULONG_PTR) hdLine,
  3897. (ULONG_PTR) dwAddressID,
  3898. (ULONG_PTR) lpAddressStatus
  3899. };
  3900. REMOTE_FUNC_ARGS funcArgs =
  3901. {
  3902. MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
  3903. args,
  3904. argTypes
  3905. };
  3906. return (REMOTEDOFUNC (&funcArgs, "lineGetAddressStatus"));
  3907. }
  3908. LONG
  3909. TSPIAPI
  3910. TSPI_lineGetAgentActivityList(
  3911. DRV_REQUESTID dwRequestID,
  3912. HDRVLINE hdLine,
  3913. DWORD dwAddressID,
  3914. LPLINEAGENTACTIVITYLIST lpAgentActivityList
  3915. )
  3916. {
  3917. static REMOTE_ARG_TYPES argTypes[] =
  3918. {
  3919. Dword,
  3920. Dword,
  3921. Hdline,
  3922. Dword,
  3923. Dword,
  3924. lpGet_Struct
  3925. };
  3926. ULONG_PTR args[] =
  3927. {
  3928. (ULONG_PTR) dwRequestID,
  3929. (ULONG_PTR) 0,
  3930. (ULONG_PTR) hdLine,
  3931. (ULONG_PTR) dwAddressID,
  3932. (ULONG_PTR) 0,
  3933. (ULONG_PTR) lpAgentActivityList
  3934. };
  3935. REMOTE_FUNC_ARGS funcArgs =
  3936. {
  3937. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentActivityList),
  3938. args,
  3939. argTypes
  3940. };
  3941. PASYNCREQUESTCONTEXT pContext;
  3942. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3943. {
  3944. return LINEERR_NOMEM;
  3945. }
  3946. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  3947. TSPI_lineGetAgentxxx_PostProcess;
  3948. pContext->Params[0] = (ULONG_PTR) lpAgentActivityList;
  3949. args[1] = (ULONG_PTR) pContext;
  3950. argTypes[1] = lpContext;
  3951. return (REMOTEDOFUNC (&funcArgs, "lGetAgentActivityList"));
  3952. }
  3953. LONG
  3954. TSPIAPI
  3955. TSPI_lineGetAgentCaps(
  3956. DRV_REQUESTID dwRequestID,
  3957. DWORD dwDeviceID,
  3958. DWORD dwAddressID,
  3959. DWORD dwAppAPIVersion,
  3960. LPLINEAGENTCAPS lpAgentCaps
  3961. )
  3962. {
  3963. static REMOTE_ARG_TYPES argTypes[] =
  3964. {
  3965. Dword,
  3966. Dword,
  3967. Dword,
  3968. LineID,
  3969. Dword,
  3970. Dword,
  3971. Dword,
  3972. lpGet_Struct
  3973. };
  3974. ULONG_PTR args[] =
  3975. {
  3976. (ULONG_PTR) dwRequestID,
  3977. (ULONG_PTR) 0,
  3978. (ULONG_PTR) 0,
  3979. (ULONG_PTR) dwDeviceID,
  3980. (ULONG_PTR) dwAddressID,
  3981. (ULONG_PTR) dwAppAPIVersion,
  3982. (ULONG_PTR) 0,
  3983. (ULONG_PTR) lpAgentCaps
  3984. };
  3985. REMOTE_FUNC_ARGS funcArgs =
  3986. {
  3987. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 8, lGetAgentCaps),
  3988. args,
  3989. argTypes
  3990. };
  3991. PASYNCREQUESTCONTEXT pContext;
  3992. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  3993. if (NULL == pLine)
  3994. {
  3995. return LINEERR_BADDEVICEID;
  3996. }
  3997. args[2] = pLine->pServer->hLineApp;
  3998. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  3999. {
  4000. return LINEERR_NOMEM;
  4001. }
  4002. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4003. TSPI_lineGetAgentxxx_PostProcess;
  4004. pContext->Params[0] = (ULONG_PTR) lpAgentCaps;
  4005. args[1] = (ULONG_PTR) pContext;
  4006. argTypes[1] = lpContext;
  4007. return (REMOTEDOFUNC (&funcArgs, "lGetAgentCaps"));
  4008. }
  4009. LONG
  4010. TSPIAPI
  4011. TSPI_lineGetAgentGroupList(
  4012. DRV_REQUESTID dwRequestID,
  4013. HDRVLINE hdLine,
  4014. DWORD dwAddressID,
  4015. LPLINEAGENTGROUPLIST lpAgentGroupList
  4016. )
  4017. {
  4018. static REMOTE_ARG_TYPES argTypes[] =
  4019. {
  4020. Dword,
  4021. Dword,
  4022. Hdline,
  4023. Dword,
  4024. Dword,
  4025. lpGet_Struct
  4026. };
  4027. ULONG_PTR args[] =
  4028. {
  4029. (ULONG_PTR) dwRequestID,
  4030. (ULONG_PTR) 0,
  4031. (ULONG_PTR) hdLine,
  4032. (ULONG_PTR) dwAddressID,
  4033. (ULONG_PTR) 0,
  4034. (ULONG_PTR) lpAgentGroupList
  4035. };
  4036. REMOTE_FUNC_ARGS funcArgs =
  4037. {
  4038. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentGroupList),
  4039. args,
  4040. argTypes
  4041. };
  4042. PASYNCREQUESTCONTEXT pContext;
  4043. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4044. {
  4045. return LINEERR_NOMEM;
  4046. }
  4047. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4048. TSPI_lineGetAgentxxx_PostProcess;
  4049. pContext->Params[0] = (ULONG_PTR) lpAgentGroupList;
  4050. args[1] = (ULONG_PTR) pContext;
  4051. argTypes[1] = lpContext;
  4052. return (REMOTEDOFUNC (&funcArgs, "lGetAgentGroupList"));
  4053. }
  4054. LONG
  4055. TSPIAPI
  4056. TSPI_lineGetAgentInfo(
  4057. DRV_REQUESTID dwRequestID,
  4058. HDRVLINE hdLine,
  4059. HAGENT hAgent,
  4060. LPLINEAGENTINFO lpAgentInfo
  4061. )
  4062. {
  4063. static REMOTE_ARG_TYPES argTypes[] =
  4064. {
  4065. Dword,
  4066. Dword,
  4067. Hdline,
  4068. Dword,
  4069. Dword,
  4070. lpGet_Struct
  4071. };
  4072. ULONG_PTR args[] =
  4073. {
  4074. (ULONG_PTR) dwRequestID,
  4075. (ULONG_PTR) 0,
  4076. (ULONG_PTR) hdLine,
  4077. (ULONG_PTR) hAgent,
  4078. (ULONG_PTR) 0,
  4079. (ULONG_PTR) lpAgentInfo
  4080. };
  4081. REMOTE_FUNC_ARGS funcArgs =
  4082. {
  4083. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentInfo),
  4084. args,
  4085. argTypes
  4086. };
  4087. PASYNCREQUESTCONTEXT pContext;
  4088. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4089. {
  4090. return LINEERR_NOMEM;
  4091. }
  4092. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4093. TSPI_lineGetAgentxxx_PostProcess;
  4094. pContext->Params[0] = (ULONG_PTR) lpAgentInfo;
  4095. args[1] = (ULONG_PTR) pContext;
  4096. argTypes[1] = lpContext;
  4097. return (REMOTEDOFUNC (&funcArgs, "lGetAgentInfo"));
  4098. }
  4099. LONG
  4100. TSPIAPI
  4101. TSPI_lineGetAgentSessionInfo(
  4102. DRV_REQUESTID dwRequestID,
  4103. HDRVLINE hdLine,
  4104. HAGENT hAgent,
  4105. LPLINEAGENTSESSIONINFO lpAgentSessionInfo
  4106. )
  4107. {
  4108. static REMOTE_ARG_TYPES argTypes[] =
  4109. {
  4110. Dword,
  4111. Dword,
  4112. Hdline,
  4113. Dword,
  4114. Dword,
  4115. lpGet_Struct
  4116. };
  4117. ULONG_PTR args[] =
  4118. {
  4119. (ULONG_PTR) dwRequestID,
  4120. (ULONG_PTR) 0,
  4121. (ULONG_PTR) hdLine,
  4122. (ULONG_PTR) hAgent,
  4123. (ULONG_PTR) 0,
  4124. (ULONG_PTR) lpAgentSessionInfo
  4125. };
  4126. REMOTE_FUNC_ARGS funcArgs =
  4127. {
  4128. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentSessionInfo),
  4129. args,
  4130. argTypes
  4131. };
  4132. PASYNCREQUESTCONTEXT pContext;
  4133. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4134. {
  4135. return LINEERR_NOMEM;
  4136. }
  4137. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4138. TSPI_lineGetAgentxxx_PostProcess;
  4139. pContext->Params[0] = (ULONG_PTR) lpAgentSessionInfo;
  4140. args[1] = (ULONG_PTR) pContext;
  4141. argTypes[1] = lpContext;
  4142. return (REMOTEDOFUNC (&funcArgs, "lGetAgentSessionInfo"));
  4143. }
  4144. LONG
  4145. TSPIAPI
  4146. TSPI_lineGetAgentSessionList(
  4147. DRV_REQUESTID dwRequestID,
  4148. HDRVLINE hdLine,
  4149. HAGENT hAgent,
  4150. LPLINEAGENTSESSIONLIST lpAgentSessionList
  4151. )
  4152. {
  4153. static REMOTE_ARG_TYPES argTypes[] =
  4154. {
  4155. Dword,
  4156. Dword,
  4157. Hdline,
  4158. Dword,
  4159. Dword,
  4160. lpGet_Struct
  4161. };
  4162. ULONG_PTR args[] =
  4163. {
  4164. (ULONG_PTR) dwRequestID,
  4165. (ULONG_PTR) 0,
  4166. (ULONG_PTR) hdLine,
  4167. (ULONG_PTR) hAgent,
  4168. (ULONG_PTR) 0,
  4169. (ULONG_PTR) lpAgentSessionList
  4170. };
  4171. REMOTE_FUNC_ARGS funcArgs =
  4172. {
  4173. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentSessionList),
  4174. args,
  4175. argTypes
  4176. };
  4177. PASYNCREQUESTCONTEXT pContext;
  4178. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4179. {
  4180. return LINEERR_NOMEM;
  4181. }
  4182. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4183. TSPI_lineGetAgentxxx_PostProcess;
  4184. pContext->Params[0] = (ULONG_PTR) lpAgentSessionList;
  4185. args[1] = (ULONG_PTR) pContext;
  4186. argTypes[1] = lpContext;
  4187. return (REMOTEDOFUNC (&funcArgs, "lGetAgentSessionList"));
  4188. }
  4189. LONG
  4190. TSPIAPI
  4191. TSPI_lineGetAgentStatus(
  4192. DRV_REQUESTID dwRequestID,
  4193. HDRVLINE hdLine,
  4194. DWORD dwAddressID,
  4195. LPLINEAGENTSTATUS lpAgentStatus
  4196. )
  4197. {
  4198. static REMOTE_ARG_TYPES argTypes[] =
  4199. {
  4200. Dword,
  4201. Dword,
  4202. Hdline,
  4203. Dword,
  4204. Dword,
  4205. lpGet_Struct
  4206. };
  4207. ULONG_PTR args[] =
  4208. {
  4209. (ULONG_PTR) dwRequestID,
  4210. (ULONG_PTR) 0,
  4211. (ULONG_PTR) hdLine,
  4212. (ULONG_PTR) dwAddressID,
  4213. (ULONG_PTR) 0,
  4214. (ULONG_PTR) lpAgentStatus
  4215. };
  4216. REMOTE_FUNC_ARGS funcArgs =
  4217. {
  4218. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetAgentStatus),
  4219. args,
  4220. argTypes
  4221. };
  4222. PASYNCREQUESTCONTEXT pContext;
  4223. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4224. {
  4225. return LINEERR_NOMEM;
  4226. }
  4227. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4228. TSPI_lineGetAgentxxx_PostProcess;
  4229. pContext->Params[0] = (ULONG_PTR) lpAgentStatus;
  4230. args[1] = (ULONG_PTR) pContext;
  4231. argTypes[1] = lpContext;
  4232. return (REMOTEDOFUNC (&funcArgs, "lGetAgentStatus"));
  4233. }
  4234. LONG
  4235. TSPIAPI
  4236. TSPI_lineGetCallAddressID(
  4237. HDRVCALL hdCall,
  4238. LPDWORD lpdwAddressID
  4239. )
  4240. {
  4241. LONG lResult = LINEERR_INVALCALLHANDLE;
  4242. try
  4243. {
  4244. *lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
  4245. if (((PDRVCALL) hdCall)->dwKey == DRVCALL_KEY)
  4246. {
  4247. lResult = 0;
  4248. }
  4249. }
  4250. except (EXCEPTION_EXECUTE_HANDLER)
  4251. {
  4252. // do nothing, just fall thru
  4253. }
  4254. return lResult;
  4255. }
  4256. LONG
  4257. TSPIAPI
  4258. TSPI_lineGetCallHubTracking(
  4259. HDRVLINE hdLine,
  4260. LPLINECALLHUBTRACKINGINFO lpTrackingInfo
  4261. )
  4262. {
  4263. static REMOTE_ARG_TYPES argTypes[] =
  4264. {
  4265. Hdline,
  4266. lpGet_Struct
  4267. };
  4268. ULONG_PTR args[] =
  4269. {
  4270. (ULONG_PTR) hdLine,
  4271. (ULONG_PTR) lpTrackingInfo
  4272. };
  4273. REMOTE_FUNC_ARGS funcArgs =
  4274. {
  4275. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallHubTracking),
  4276. args,
  4277. argTypes
  4278. };
  4279. return (REMOTEDOFUNC (&funcArgs, "lineGetCallHubTracking"));
  4280. }
  4281. LONG
  4282. TSPIAPI
  4283. TSPI_lineGetCallIDs(
  4284. HDRVCALL hdCall,
  4285. LPDWORD lpdwAddressID,
  4286. LPDWORD lpdwCallID,
  4287. LPDWORD lpdwRelatedCallID
  4288. )
  4289. {
  4290. LONG lResult = LINEERR_INVALCALLHANDLE;
  4291. PDRVCALL pCall = (PDRVCALL) hdCall;
  4292. PDRVSERVER pServer;
  4293. try
  4294. {
  4295. *lpdwAddressID = pCall->dwAddressID;
  4296. *lpdwCallID = pCall->dwCallID;
  4297. *lpdwRelatedCallID = pCall->dwRelatedCallID;
  4298. pServer = pCall->pServer;
  4299. if (pCall->dwKey == DRVCALL_KEY)
  4300. {
  4301. lResult = (pCall->dwDirtyStructs & STRUCTCHANGE_CALLIDS ? 1 : 0);
  4302. }
  4303. }
  4304. except (EXCEPTION_EXECUTE_HANDLER)
  4305. {
  4306. // do nothing, just fall thru
  4307. }
  4308. if (lResult == 1)
  4309. {
  4310. if (!pServer->bVer2xServer)
  4311. {
  4312. static REMOTE_ARG_TYPES argTypes[] =
  4313. {
  4314. Hdcall,
  4315. lpDword,
  4316. lpDword,
  4317. lpDword
  4318. };
  4319. ULONG_PTR args[] =
  4320. {
  4321. (ULONG_PTR) hdCall,
  4322. (ULONG_PTR) lpdwAddressID,
  4323. (ULONG_PTR) lpdwCallID,
  4324. (ULONG_PTR) lpdwRelatedCallID
  4325. };
  4326. REMOTE_FUNC_ARGS funcArgs =
  4327. {
  4328. MAKELONG (LINE_FUNC | SYNC | 4, lGetCallIDs),
  4329. args,
  4330. argTypes
  4331. };
  4332. lResult = REMOTEDOFUNC (&funcArgs, "lGetCallIDs");
  4333. }
  4334. else
  4335. {
  4336. LINECALLINFO callInfo;
  4337. callInfo.dwTotalSize = sizeof (callInfo);
  4338. if ((lResult = TSPI_lineGetCallInfo (hdCall, &callInfo)) == 0)
  4339. {
  4340. *lpdwAddressID = callInfo.dwAddressID;
  4341. *lpdwCallID = callInfo.dwCallID;
  4342. *lpdwRelatedCallID = callInfo.dwRelatedCallID;
  4343. }
  4344. }
  4345. if (lResult == 0)
  4346. {
  4347. EnterCriticalSection (&gCallListCriticalSection);
  4348. if (IsValidObject (pCall, DRVCALL_KEY))
  4349. {
  4350. pCall->dwAddressID = *lpdwAddressID;
  4351. pCall->dwCallID = *lpdwCallID;
  4352. pCall->dwRelatedCallID = *lpdwRelatedCallID;
  4353. pCall->dwDirtyStructs &= ~STRUCTCHANGE_CALLIDS;
  4354. }
  4355. LeaveCriticalSection (&gCallListCriticalSection);
  4356. }
  4357. }
  4358. return lResult;
  4359. }
  4360. LONG
  4361. TSPIAPI
  4362. TSPI_lineGetCallInfo(
  4363. HDRVCALL hdCall,
  4364. LPLINECALLINFO lpCallInfo
  4365. )
  4366. {
  4367. LONG lResult;
  4368. static REMOTE_ARG_TYPES argTypes[] =
  4369. {
  4370. Hdcall,
  4371. lpGet_Struct
  4372. };
  4373. ULONG_PTR args[] =
  4374. {
  4375. (ULONG_PTR) hdCall,
  4376. (ULONG_PTR) lpCallInfo
  4377. };
  4378. REMOTE_FUNC_ARGS funcArgs =
  4379. {
  4380. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
  4381. args,
  4382. argTypes
  4383. };
  4384. PDRVCALL pCall = (PDRVCALL)hdCall;
  4385. //
  4386. // Has the cached structure been invalidated?
  4387. //
  4388. EnterCriticalSection (&gCallListCriticalSection);
  4389. if (!IsValidObject (pCall, DRVCALL_KEY))
  4390. {
  4391. LeaveCriticalSection (&gCallListCriticalSection);
  4392. return LINEERR_INVALCALLHANDLE;
  4393. }
  4394. if ( ( pCall->dwDirtyStructs & STRUCTCHANGE_LINECALLINFO ) ||
  4395. ( pCall->dwCachedCallInfoCount > gdwCacheForceCallCount ) )
  4396. {
  4397. //
  4398. // The cache not valid, get the real info
  4399. //
  4400. LeaveCriticalSection (&gCallListCriticalSection);
  4401. lResult = (REMOTEDOFUNC (&funcArgs, "lineGetCallInfo"));
  4402. //
  4403. // Did the function succeed and was the entire struct returned?
  4404. //
  4405. if (
  4406. (ERROR_SUCCESS == lResult)
  4407. &&
  4408. (lpCallInfo->dwNeededSize <= lpCallInfo->dwTotalSize)
  4409. )
  4410. {
  4411. EnterCriticalSection (&gCallListCriticalSection);
  4412. if (!IsValidObject (pCall, DRVCALL_KEY))
  4413. {
  4414. LeaveCriticalSection (&gCallListCriticalSection);
  4415. return LINEERR_INVALCALLHANDLE;
  4416. }
  4417. //
  4418. // Did we already have a good pointer?
  4419. //
  4420. if ( pCall->pCachedCallInfo )
  4421. {
  4422. DrvFree( pCall->pCachedCallInfo );
  4423. }
  4424. pCall->pCachedCallInfo = DrvAlloc( lpCallInfo->dwUsedSize );
  4425. if ( pCall->pCachedCallInfo )
  4426. {
  4427. //
  4428. // Mark the cache data as clean
  4429. //
  4430. pCall->dwDirtyStructs &= ~STRUCTCHANGE_LINECALLINFO;
  4431. pCall->dwCachedCallInfoCount = 0;
  4432. //
  4433. // Adjust the LineID for the local machine
  4434. //
  4435. lpCallInfo->dwLineDeviceID += gdwLineDeviceIDBase;
  4436. CopyMemory( pCall->pCachedCallInfo,
  4437. lpCallInfo,
  4438. lpCallInfo->dwUsedSize
  4439. );
  4440. }
  4441. LeaveCriticalSection (&gCallListCriticalSection);
  4442. }
  4443. }
  4444. else
  4445. {
  4446. //
  4447. // The cache is valid, return data from there
  4448. //
  4449. if ( lpCallInfo->dwTotalSize >= pCall->pCachedCallInfo->dwUsedSize )
  4450. {
  4451. CopyMemory(
  4452. (PBYTE)&(((PDWORD)lpCallInfo)[1]),
  4453. (PBYTE)&(((PDWORD)(pCall->pCachedCallInfo))[1]),
  4454. pCall->pCachedCallInfo->dwUsedSize - sizeof(DWORD)
  4455. );
  4456. }
  4457. else
  4458. {
  4459. // Copy fixed size starting past the dwTotalSize field
  4460. CopyMemory(
  4461. (PBYTE)&(((PDWORD)lpCallInfo)[3]),
  4462. (PBYTE)&(((PDWORD)(pCall->pCachedCallInfo))[3]),
  4463. lpCallInfo->dwTotalSize - sizeof(DWORD)*3
  4464. );
  4465. lpCallInfo->dwNeededSize = pCall->pCachedCallInfo->dwUsedSize;
  4466. lpCallInfo->dwUsedSize = lpCallInfo->dwTotalSize;
  4467. //
  4468. // Zero the dwXxxSize fields so app won't try to read from them
  4469. // (& so tapi32.dll won't try to convert them from unicode to ascii)
  4470. //
  4471. lpCallInfo->dwCallerIDSize =
  4472. lpCallInfo->dwCallerIDNameSize =
  4473. lpCallInfo->dwCalledIDSize =
  4474. lpCallInfo->dwCalledIDNameSize =
  4475. lpCallInfo->dwConnectedIDSize =
  4476. lpCallInfo->dwConnectedIDNameSize =
  4477. lpCallInfo->dwRedirectionIDSize =
  4478. lpCallInfo->dwRedirectionIDNameSize =
  4479. lpCallInfo->dwRedirectingIDSize =
  4480. lpCallInfo->dwRedirectingIDNameSize =
  4481. lpCallInfo->dwAppNameSize =
  4482. lpCallInfo->dwDisplayableAddressSize =
  4483. lpCallInfo->dwCalledPartySize =
  4484. lpCallInfo->dwCommentSize =
  4485. lpCallInfo->dwDisplaySize =
  4486. lpCallInfo->dwUserUserInfoSize =
  4487. lpCallInfo->dwHighLevelCompSize =
  4488. lpCallInfo->dwLowLevelCompSize =
  4489. lpCallInfo->dwChargingInfoSize =
  4490. lpCallInfo->dwTerminalModesSize =
  4491. lpCallInfo->dwDevSpecificSize = 0;
  4492. if (pCall->pLine->dwXPIVersion >= TAPI_VERSION2_0)
  4493. {
  4494. lpCallInfo->dwCallDataSize =
  4495. lpCallInfo->dwSendingFlowspecSize =
  4496. lpCallInfo->dwReceivingFlowspecSize = 0;
  4497. }
  4498. }
  4499. pCall->dwCachedCallInfoCount++;
  4500. LeaveCriticalSection (&gCallListCriticalSection);
  4501. lResult = 0;
  4502. }
  4503. return( lResult );
  4504. }
  4505. LONG
  4506. TSPIAPI
  4507. TSPI_lineGetCallStatus(
  4508. HDRVCALL hdCall,
  4509. LPLINECALLSTATUS lpCallStatus
  4510. )
  4511. {
  4512. LONG lResult=0;
  4513. static REMOTE_ARG_TYPES argTypes[] =
  4514. {
  4515. Hdcall,
  4516. lpGet_Struct
  4517. };
  4518. ULONG_PTR args[] =
  4519. {
  4520. (ULONG_PTR) hdCall,
  4521. (ULONG_PTR) lpCallStatus
  4522. };
  4523. REMOTE_FUNC_ARGS funcArgs =
  4524. {
  4525. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
  4526. args,
  4527. argTypes
  4528. };
  4529. PDRVCALL pCall = (PDRVCALL)hdCall;
  4530. //
  4531. // Has the cached structure been invalidated?
  4532. //
  4533. EnterCriticalSection (&gCallListCriticalSection);
  4534. if (!IsValidObject (pCall, DRVCALL_KEY))
  4535. {
  4536. LeaveCriticalSection (&gCallListCriticalSection);
  4537. return LINEERR_INVALCALLHANDLE;
  4538. }
  4539. if ( ( pCall->dwDirtyStructs & STRUCTCHANGE_LINECALLSTATUS ) ||
  4540. ( pCall->dwCachedCallStatusCount > gdwCacheForceCallCount ) )
  4541. {
  4542. //
  4543. // The cache not valid, get the real info
  4544. //
  4545. LeaveCriticalSection (&gCallListCriticalSection);
  4546. lResult = (REMOTEDOFUNC (&funcArgs, "lineGetCallStatus"));
  4547. //
  4548. // Did the function succeed and was the entire struct returned?
  4549. //
  4550. if (
  4551. (ERROR_SUCCESS == lResult)
  4552. &&
  4553. (lpCallStatus->dwNeededSize <= lpCallStatus->dwTotalSize)
  4554. )
  4555. {
  4556. EnterCriticalSection (&gCallListCriticalSection);
  4557. if (!IsValidObject (pCall, DRVCALL_KEY))
  4558. {
  4559. LeaveCriticalSection (&gCallListCriticalSection);
  4560. return LINEERR_INVALCALLHANDLE;
  4561. }
  4562. //
  4563. // Did we already have a good pointer?
  4564. //
  4565. if ( pCall->pCachedCallStatus )
  4566. {
  4567. DrvFree( pCall->pCachedCallStatus );
  4568. }
  4569. pCall->pCachedCallStatus = DrvAlloc( lpCallStatus->dwUsedSize );
  4570. if ( pCall->pCachedCallStatus )
  4571. {
  4572. //
  4573. // Mark the cache data as clean
  4574. //
  4575. pCall->dwDirtyStructs &= ~STRUCTCHANGE_LINECALLSTATUS;
  4576. pCall->dwCachedCallStatusCount = 0;
  4577. CopyMemory( pCall->pCachedCallStatus,
  4578. lpCallStatus,
  4579. lpCallStatus->dwUsedSize
  4580. );
  4581. }
  4582. LeaveCriticalSection (&gCallListCriticalSection);
  4583. }
  4584. }
  4585. else
  4586. {
  4587. //
  4588. // The cache is valid, return data from there
  4589. //
  4590. if ( lpCallStatus->dwTotalSize >= pCall->pCachedCallStatus->dwUsedSize )
  4591. {
  4592. CopyMemory(
  4593. (PBYTE)&(((PDWORD)lpCallStatus)[1]),
  4594. (PBYTE)&(((PDWORD)(pCall->pCachedCallStatus))[1]),
  4595. pCall->pCachedCallStatus->dwUsedSize - sizeof(DWORD)
  4596. );
  4597. }
  4598. else
  4599. {
  4600. // Copy fixed size starting past the dwTotalSize field
  4601. CopyMemory(
  4602. (PBYTE)&(((PDWORD)lpCallStatus)[3]),
  4603. (PBYTE)&(((PDWORD)(pCall->pCachedCallStatus))[3]),
  4604. lpCallStatus->dwTotalSize - sizeof(DWORD)*3
  4605. );
  4606. lpCallStatus->dwNeededSize = pCall->pCachedCallStatus->dwUsedSize;
  4607. lpCallStatus->dwUsedSize = lpCallStatus->dwTotalSize;
  4608. //
  4609. // Zero the dwXxxSize fields so app won't try to read from them
  4610. //
  4611. lpCallStatus->dwDevSpecificSize = 0;
  4612. }
  4613. pCall->dwCachedCallStatusCount++;
  4614. LeaveCriticalSection (&gCallListCriticalSection);
  4615. lResult = 0;
  4616. }
  4617. return( lResult );
  4618. }
  4619. LONG
  4620. TSPIAPI
  4621. TSPI_lineGetDevCaps(
  4622. DWORD dwDeviceID,
  4623. DWORD dwTSPIVersion,
  4624. DWORD dwExtVersion,
  4625. LPLINEDEVCAPS lpLineDevCaps
  4626. )
  4627. {
  4628. LONG lResult;
  4629. static REMOTE_ARG_TYPES argTypes[] =
  4630. {
  4631. Dword,
  4632. LineID,
  4633. Dword,
  4634. Dword,
  4635. lpGet_Struct
  4636. };
  4637. ULONG_PTR args[] =
  4638. {
  4639. (ULONG_PTR) 0,
  4640. (ULONG_PTR) dwDeviceID,
  4641. (ULONG_PTR) dwTSPIVersion,
  4642. (ULONG_PTR) dwExtVersion,
  4643. (ULONG_PTR) lpLineDevCaps
  4644. };
  4645. REMOTE_FUNC_ARGS funcArgs =
  4646. {
  4647. MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
  4648. args,
  4649. argTypes
  4650. };
  4651. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  4652. if (NULL == pLine)
  4653. {
  4654. return LINEERR_BADDEVICEID;
  4655. }
  4656. args[0] = pLine->pServer->hLineApp;
  4657. lResult = REMOTEDOFUNC (&funcArgs, "lineGetDevCaps");
  4658. //
  4659. // We were munging the PermID in the original release of tapi 2.1.
  4660. // The intent was to make sure that we didn't present apps with
  4661. // overlapping id's (both local & remote), but none of our other service
  4662. // providers (i.e. unimdm, kmddsp) use the HIWORD(providerID) /
  4663. // LOWORD(devID) model, so it really doesn't do any good.
  4664. //
  4665. // if (lResult == 0)
  4666. // {
  4667. // lpLineDevCaps->dwPermanentLineID = MAKELONG(
  4668. // LOWORD(lpLineDevCaps->dwPermanentLineID),
  4669. // gdwPermanentProviderID
  4670. // );
  4671. // }
  4672. //
  4673. return lResult;
  4674. }
  4675. LONG
  4676. TSPIAPI
  4677. TSPI_lineGetDevConfig(
  4678. DWORD dwDeviceID,
  4679. LPVARSTRING lpDeviceConfig,
  4680. LPCWSTR lpszDeviceClass
  4681. )
  4682. {
  4683. static REMOTE_ARG_TYPES argTypes[] =
  4684. {
  4685. LineID,
  4686. lpGet_Struct,
  4687. lpsz
  4688. };
  4689. ULONG_PTR args[] =
  4690. {
  4691. (ULONG_PTR) dwDeviceID,
  4692. (ULONG_PTR) lpDeviceConfig,
  4693. (ULONG_PTR) lpszDeviceClass
  4694. };
  4695. REMOTE_FUNC_ARGS funcArgs =
  4696. {
  4697. MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
  4698. args,
  4699. argTypes
  4700. };
  4701. return (REMOTEDOFUNC (&funcArgs, "lineGetDevConfig"));
  4702. }
  4703. LONG
  4704. TSPIAPI
  4705. TSPI_lineGetExtensionID(
  4706. DWORD dwDeviceID,
  4707. DWORD dwTSPIVersion,
  4708. LPLINEEXTENSIONID lpExtensionID
  4709. )
  4710. {
  4711. PDRVLINE pDrvLine = GetLineFromID (dwDeviceID);
  4712. if (NULL == pDrvLine)
  4713. {
  4714. return LINEERR_BADDEVICEID;
  4715. }
  4716. CopyMemory(
  4717. lpExtensionID,
  4718. &pDrvLine->ExtensionID,
  4719. sizeof (LINEEXTENSIONID)
  4720. );
  4721. return 0;
  4722. }
  4723. LONG
  4724. TSPIAPI
  4725. TSPI_lineGetGroupList(
  4726. DRV_REQUESTID dwRequestID,
  4727. HDRVLINE hdLine,
  4728. LPLINEAGENTGROUPLIST lpAgentGroupList
  4729. )
  4730. {
  4731. static REMOTE_ARG_TYPES argTypes[] =
  4732. {
  4733. Dword,
  4734. Dword,
  4735. Hdline,
  4736. Dword,
  4737. lpGet_Struct
  4738. };
  4739. ULONG_PTR args[] =
  4740. {
  4741. (ULONG_PTR) dwRequestID,
  4742. (ULONG_PTR) 0,
  4743. (ULONG_PTR) hdLine,
  4744. (ULONG_PTR) 0,
  4745. (ULONG_PTR) lpAgentGroupList
  4746. };
  4747. REMOTE_FUNC_ARGS funcArgs =
  4748. {
  4749. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 5, lGetGroupList),
  4750. args,
  4751. argTypes
  4752. };
  4753. PASYNCREQUESTCONTEXT pContext;
  4754. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  4755. {
  4756. return LINEERR_NOMEM;
  4757. }
  4758. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  4759. TSPI_lineGetAgentxxx_PostProcess;
  4760. pContext->Params[0] = (ULONG_PTR) lpAgentGroupList;
  4761. args[1] = (ULONG_PTR) pContext;
  4762. argTypes[1] = lpContext;
  4763. return (REMOTEDOFUNC (&funcArgs, "lineGetGroupList"));
  4764. }
  4765. LONG
  4766. TSPIAPI
  4767. TSPI_lineGetIcon(
  4768. DWORD dwDeviceID,
  4769. LPCWSTR lpszDeviceClass,
  4770. LPHICON lphIcon
  4771. )
  4772. {
  4773. *lphIcon = ghLineIcon;
  4774. return 0;
  4775. }
  4776. LONG
  4777. TSPIAPI
  4778. TSPI_lineGetID(
  4779. HDRVLINE hdLine,
  4780. DWORD dwAddressID,
  4781. HDRVCALL hdCall,
  4782. DWORD dwSelect,
  4783. LPVARSTRING lpDeviceID,
  4784. LPCWSTR lpszDeviceClass,
  4785. HANDLE hTargetProcess
  4786. )
  4787. {
  4788. //
  4789. // NOTE: Tapisrv will handle the "tapi/line" class
  4790. //
  4791. // NOTE: The "GetNewCalls" class is just for remotesp, & is
  4792. // special cased below
  4793. //
  4794. LONG lResult;
  4795. const WCHAR szGetNewCalls[] = L"GetNewCalls";
  4796. const WCHAR szTapiPhone[] = L"tapi/phone";
  4797. //
  4798. // The device ID for wave devices is meaningless on remote machines.
  4799. // Return op. unavailable
  4800. //
  4801. if (lpszDeviceClass &&
  4802. ( !_wcsicmp(lpszDeviceClass, L"wave/in") ||
  4803. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  4804. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  4805. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  4806. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  4807. )
  4808. )
  4809. {
  4810. return LINEERR_OPERATIONUNAVAIL;
  4811. }
  4812. if (lpDeviceID || // should be NULL if class == "GetNewCalls"
  4813. lstrcmpiW (lpszDeviceClass, szGetNewCalls))
  4814. {
  4815. REMOTE_ARG_TYPES argTypes[] =
  4816. {
  4817. Dword,
  4818. //(dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
  4819. Dword,
  4820. Dword,
  4821. //(dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
  4822. Dword,
  4823. lpGet_Struct,
  4824. lpsz
  4825. };
  4826. ULONG_PTR args[] =
  4827. {
  4828. (ULONG_PTR) hdLine,
  4829. (ULONG_PTR) dwAddressID,
  4830. (ULONG_PTR) hdCall,
  4831. (ULONG_PTR) dwSelect,
  4832. (ULONG_PTR) lpDeviceID,
  4833. (ULONG_PTR) lpszDeviceClass
  4834. };
  4835. REMOTE_FUNC_ARGS funcArgs =
  4836. {
  4837. MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
  4838. args,
  4839. argTypes
  4840. };
  4841. switch (dwSelect)
  4842. {
  4843. case LINECALLSELECT_CALL:
  4844. argTypes[2] = Hdcall;
  4845. break;
  4846. case LINECALLSELECT_ADDRESS:
  4847. case LINECALLSELECT_LINE:
  4848. argTypes[0] = Hdline;
  4849. break;
  4850. case LINECALLSELECT_DEVICEID:
  4851. break;
  4852. }
  4853. lResult = REMOTEDOFUNC (&funcArgs, "lineGetID");
  4854. //
  4855. // If success && dev class == "tapi/phone" && there was
  4856. // enough room in the device ID struct for a returned ID,
  4857. // then we need to map the 0-based server ID back to it's
  4858. // corresponding local ID.
  4859. //
  4860. if (lResult == 0 &&
  4861. lstrcmpiW (lpszDeviceClass, szTapiPhone) == 0 &&
  4862. lpDeviceID->dwUsedSize >= (sizeof (*lpDeviceID) + sizeof (DWORD)))
  4863. {
  4864. LPDWORD pdwPhoneID = (LPDWORD) (((LPBYTE) lpDeviceID) +
  4865. lpDeviceID->dwStringOffset);
  4866. PDRVPHONE pPhone;
  4867. PDRVSERVER pServer = ((PDRVLINE) hdLine)->pServer;
  4868. if ((pPhone = GetPhoneFromID (gdwPhoneDeviceIDBase + *pdwPhoneID)))
  4869. {
  4870. if (pPhone->pServer == pServer &&
  4871. pPhone->dwDeviceIDServer == *pdwPhoneID)
  4872. {
  4873. //
  4874. // The easy case - a direct mapping between the ID
  4875. // returned from the server & the index into the
  4876. // lookup table
  4877. //
  4878. *pdwPhoneID = pPhone->dwDeviceIDLocal;
  4879. }
  4880. else
  4881. {
  4882. //
  4883. // The hard case - have to walk the lookup table(s)
  4884. // looking for the matching device.
  4885. //
  4886. // We'll take the simplest, though slowest, route
  4887. // and start at the first entry of the first table.
  4888. // The good news is that there generally won't be
  4889. // many devices, and this request won't occur often.
  4890. //
  4891. DWORD i;
  4892. PDRVPHONELOOKUP pLookup = gpPhoneLookup;
  4893. while (pLookup)
  4894. {
  4895. for (i = 0; i < pLookup->dwUsedEntries; i++)
  4896. {
  4897. if (pLookup->aEntries[i].dwDeviceIDServer ==
  4898. *pdwPhoneID &&
  4899. pLookup->aEntries[i].pServer == pServer)
  4900. {
  4901. *pdwPhoneID =
  4902. pLookup->aEntries[i].dwDeviceIDLocal;
  4903. goto TSPI_lineGetID_return;
  4904. }
  4905. }
  4906. pLookup = pLookup->pNext;
  4907. }
  4908. //
  4909. // If here no matching local ID, so fail the request
  4910. //
  4911. lResult = LINEERR_OPERATIONFAILED;
  4912. }
  4913. }
  4914. else
  4915. {
  4916. lResult = LINEERR_OPERATIONFAILED;
  4917. }
  4918. }
  4919. }
  4920. else
  4921. {
  4922. //
  4923. // An app has done lineGetNewCalls for a remote line.
  4924. // We deal with this by retrieving any new calls for
  4925. // this line (or address), and indicating NEWCALL &
  4926. // CALLSTTE\UNKNOWN msgs to tapi.
  4927. //
  4928. // Note that hTargetProcess is really a pointer to the
  4929. // internal tapisrv!LineEventProc, which actually processes
  4930. // call state msgs, etc inline instead of queueing them for
  4931. // later processing like tapisrv!LineEventProcSP does.
  4932. // We want to submit the LINE_CALLSTATE msgs to this
  4933. // function to make sure they get processed right away
  4934. // so call monitors get created, etc before we return to
  4935. // the call function.
  4936. //
  4937. DWORD dwTotalSize;
  4938. LINECALLLIST fastCallList[2], *pCallList = fastCallList;
  4939. LINEEVENT internalLineEventProc = (LINEEVENT)
  4940. ((ULONG_PTR) hTargetProcess);
  4941. REMOTE_ARG_TYPES argTypes[] =
  4942. {
  4943. Hdline,
  4944. Dword,
  4945. Dword,
  4946. lpGet_Struct
  4947. };
  4948. ULONG_PTR args[] =
  4949. {
  4950. (ULONG_PTR) hdLine,
  4951. (ULONG_PTR) dwAddressID,
  4952. (ULONG_PTR) dwSelect,
  4953. (ULONG_PTR) 0
  4954. };
  4955. REMOTE_FUNC_ARGS funcArgs =
  4956. {
  4957. MAKELONG (LINE_FUNC | SYNC | 4, lGetNewCalls),
  4958. args,
  4959. argTypes
  4960. };
  4961. dwTotalSize = sizeof (fastCallList);
  4962. do
  4963. {
  4964. pCallList->dwTotalSize = dwTotalSize;
  4965. args[3] = (ULONG_PTR) pCallList;
  4966. lResult = REMOTEDOFUNC (&funcArgs, "lineGetNewCalls");
  4967. if (lResult == 0)
  4968. {
  4969. if (pCallList->dwNeededSize > pCallList->dwTotalSize)
  4970. {
  4971. //
  4972. // Get a bigger buffer & try again
  4973. //
  4974. dwTotalSize = pCallList->dwNeededSize + 4 * sizeof (HCALL);
  4975. if (pCallList != fastCallList)
  4976. {
  4977. DrvFree (pCallList);
  4978. }
  4979. if (!(pCallList = DrvAlloc (dwTotalSize)))
  4980. {
  4981. return LINEERR_NOMEM;
  4982. }
  4983. }
  4984. else
  4985. {
  4986. //
  4987. // We got all the info, so break
  4988. //
  4989. break;
  4990. }
  4991. }
  4992. } while (lResult == 0);
  4993. if (lResult == 0)
  4994. {
  4995. if (pCallList->dwCallsNumEntries == 0)
  4996. {
  4997. lResult = LINEERR_OPERATIONFAILED;
  4998. }
  4999. else
  5000. {
  5001. //
  5002. // For each returned call in the list indicate a NEWCALL
  5003. // & a CALLSTATE\UNKNOWN msg. (We could call over to the
  5004. // server to retrieve the current call state, call id's,
  5005. // etc, but that would be painful)
  5006. //
  5007. DWORD i;
  5008. LPHCALL phCall = (LPHCALL) (((LPBYTE) pCallList) +
  5009. pCallList->dwCallsOffset);
  5010. PDRVLINE pLine = (PDRVLINE) hdLine;
  5011. PDRVCALL pCall;
  5012. EnterCriticalSection (&gCallListCriticalSection);
  5013. if (pLine->htLine)
  5014. {
  5015. for (i = 0; i < pCallList->dwCallsNumEntries; i++,phCall++)
  5016. {
  5017. if ((pCall = DrvAlloc (sizeof (DRVCALL))))
  5018. {
  5019. pCall->hCall = *phCall;
  5020. pCall->dwInitialCallStateMode = 0xa5a5a5a5;
  5021. pCall->dwInitialPrivilege =
  5022. LINECALLPRIVILEGE_MONITOR;
  5023. pCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  5024. AddCallToList (pLine, pCall);
  5025. (*gpfnLineEventProc)(
  5026. pLine->htLine,
  5027. 0,
  5028. LINE_NEWCALL,
  5029. (ULONG_PTR) pCall,
  5030. (ULONG_PTR) &(pCall->htCall),
  5031. (ULONG_PTR) 0
  5032. );
  5033. if (!pCall->htCall)
  5034. {
  5035. //
  5036. // tapi was not able to create it's own inst
  5037. // to represent ths incoming call, perhaps
  5038. // because the line was closed, or out of
  5039. // memory. if the line was closed then we've
  5040. // already notified the remote server, and it
  5041. // should have destroyed the call client.
  5042. // otherwise, we probably want to do a
  5043. // closecall here or in a worker thread
  5044. //
  5045. static REMOTE_ARG_TYPES argTypes[] =
  5046. {
  5047. Hdcall
  5048. };
  5049. REMOTE_FUNC_ARGS funcArgs =
  5050. {
  5051. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
  5052. (ULONG_PTR *) &pCall,
  5053. argTypes
  5054. };
  5055. REMOTEDOFUNC (&funcArgs, "lineCloseCall");
  5056. RemoveCallFromList (pCall);
  5057. break;
  5058. }
  5059. //
  5060. // Note we call the internalLineEventProc here,
  5061. // using ghProvider as a key
  5062. //
  5063. (*internalLineEventProc)(
  5064. pLine->htLine,
  5065. pCall->htCall,
  5066. LINE_CALLSTATE,
  5067. (ULONG_PTR) LINECALLSTATE_UNKNOWN,
  5068. (ULONG_PTR) &pCall->dwInitialCallStateMode,
  5069. (ULONG_PTR) 0
  5070. );
  5071. }
  5072. else
  5073. {
  5074. break;
  5075. }
  5076. }
  5077. }
  5078. LeaveCriticalSection (&gCallListCriticalSection);
  5079. }
  5080. }
  5081. if (pCallList != fastCallList)
  5082. {
  5083. DrvFree (pCallList);
  5084. }
  5085. }
  5086. TSPI_lineGetID_return:
  5087. return lResult;
  5088. }
  5089. LONG
  5090. TSPIAPI
  5091. TSPI_lineGetLineDevStatus(
  5092. HDRVLINE hdLine,
  5093. LPLINEDEVSTATUS lpLineDevStatus
  5094. )
  5095. {
  5096. static REMOTE_ARG_TYPES argTypes[] =
  5097. {
  5098. Hdline,
  5099. lpGet_Struct
  5100. };
  5101. ULONG_PTR args[] =
  5102. {
  5103. (ULONG_PTR) hdLine,
  5104. (ULONG_PTR) lpLineDevStatus
  5105. };
  5106. REMOTE_FUNC_ARGS funcArgs =
  5107. {
  5108. MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
  5109. args,
  5110. argTypes
  5111. };
  5112. return (REMOTEDOFUNC (&funcArgs, "lineGetLineDevStatus"));
  5113. }
  5114. LONG
  5115. TSPIAPI
  5116. TSPI_lineGetProxyStatus(
  5117. DWORD dwDeviceID,
  5118. DWORD dwAppAPIVersion,
  5119. LPLINEPROXYREQUESTLIST lpLineProxyReqestList
  5120. )
  5121. {
  5122. static REMOTE_ARG_TYPES argTypes[] =
  5123. {
  5124. Dword,
  5125. LineID,
  5126. Dword,
  5127. lpGet_Struct
  5128. };
  5129. ULONG_PTR args[] =
  5130. {
  5131. (ULONG_PTR) 0,
  5132. (ULONG_PTR) dwDeviceID,
  5133. (ULONG_PTR) dwAppAPIVersion,
  5134. (ULONG_PTR) lpLineProxyReqestList
  5135. };
  5136. REMOTE_FUNC_ARGS funcArgs =
  5137. {
  5138. MAKELONG (LINE_FUNC | SYNC | 4, lGetProxyStatus),
  5139. args,
  5140. argTypes
  5141. };
  5142. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  5143. if (NULL == pLine)
  5144. {
  5145. return LINEERR_BADDEVICEID;
  5146. }
  5147. args[0] = pLine->pServer->hLineApp;
  5148. return (REMOTEDOFUNC (&funcArgs, "lineGetProxyStatus"));
  5149. }
  5150. LONG
  5151. TSPIAPI
  5152. TSPI_lineGetQueueInfo(
  5153. DRV_REQUESTID dwRequestID,
  5154. HDRVLINE hdLine,
  5155. DWORD dwQueueID,
  5156. LPLINEQUEUEINFO lpQueueInfo
  5157. )
  5158. {
  5159. static REMOTE_ARG_TYPES argTypes[] =
  5160. {
  5161. Dword,
  5162. Dword,
  5163. Hdline,
  5164. Dword,
  5165. Dword,
  5166. lpGet_Struct
  5167. };
  5168. ULONG_PTR args[] =
  5169. {
  5170. (ULONG_PTR) dwRequestID,
  5171. (ULONG_PTR) 0,
  5172. (ULONG_PTR) hdLine,
  5173. (ULONG_PTR) dwQueueID,
  5174. (ULONG_PTR) 0,
  5175. (ULONG_PTR) lpQueueInfo
  5176. };
  5177. REMOTE_FUNC_ARGS funcArgs =
  5178. {
  5179. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lGetQueueInfo),
  5180. args,
  5181. argTypes
  5182. };
  5183. PASYNCREQUESTCONTEXT pContext;
  5184. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5185. {
  5186. return LINEERR_NOMEM;
  5187. }
  5188. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5189. TSPI_lineGetAgentxxx_PostProcess;
  5190. pContext->Params[0] = (ULONG_PTR) lpQueueInfo;
  5191. args[1] = (ULONG_PTR) pContext;
  5192. argTypes[1] = lpContext;
  5193. return (REMOTEDOFUNC (&funcArgs, "lGetQueueInfo"));
  5194. }
  5195. LONG
  5196. TSPIAPI
  5197. TSPI_lineGetQueueList(
  5198. DRV_REQUESTID dwRequestID,
  5199. HDRVLINE hdLine,
  5200. GUID *pGroupID,
  5201. LPLINEQUEUELIST lpQueueList
  5202. )
  5203. {
  5204. static REMOTE_ARG_TYPES argTypes[] =
  5205. {
  5206. Dword,
  5207. Dword,
  5208. Hdline,
  5209. lpSet_SizeToFollow,
  5210. Size,
  5211. Dword,
  5212. lpGet_Struct
  5213. };
  5214. ULONG_PTR args[] =
  5215. {
  5216. (ULONG_PTR) dwRequestID,
  5217. (ULONG_PTR) 0,
  5218. (ULONG_PTR) hdLine,
  5219. (ULONG_PTR) pGroupID,
  5220. (ULONG_PTR) sizeof( GUID ),
  5221. (ULONG_PTR) 0,
  5222. (ULONG_PTR) lpQueueList
  5223. };
  5224. REMOTE_FUNC_ARGS funcArgs =
  5225. {
  5226. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 7, lGetQueueList),
  5227. args,
  5228. argTypes
  5229. };
  5230. PASYNCREQUESTCONTEXT pContext;
  5231. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5232. {
  5233. return LINEERR_NOMEM;
  5234. }
  5235. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5236. TSPI_lineGetAgentxxx_PostProcess;
  5237. pContext->Params[0] = (ULONG_PTR) lpQueueList;
  5238. args[1] = (ULONG_PTR) pContext;
  5239. argTypes[1] = lpContext;
  5240. return (REMOTEDOFUNC (&funcArgs, "lGetQueueList"));
  5241. }
  5242. LONG
  5243. TSPIAPI
  5244. TSPI_lineGetNumAddressIDs(
  5245. HDRVLINE hdLine,
  5246. LPDWORD lpdwNumAddressIDs
  5247. )
  5248. {
  5249. static REMOTE_ARG_TYPES argTypes[] =
  5250. {
  5251. Hdline,
  5252. lpDword
  5253. };
  5254. ULONG_PTR args[] =
  5255. {
  5256. (ULONG_PTR) hdLine,
  5257. (ULONG_PTR) lpdwNumAddressIDs
  5258. };
  5259. REMOTE_FUNC_ARGS funcArgs =
  5260. {
  5261. MAKELONG (LINE_FUNC | SYNC | 2, lGetNumAddressIDs),
  5262. args,
  5263. argTypes
  5264. };
  5265. return (REMOTEDOFUNC (&funcArgs, "lineGetNumAddressIDs"));
  5266. }
  5267. LONG
  5268. TSPIAPI
  5269. TSPI_lineHold(
  5270. DRV_REQUESTID dwRequestID,
  5271. HDRVCALL hdCall
  5272. )
  5273. {
  5274. static REMOTE_ARG_TYPES argTypes[] =
  5275. {
  5276. Dword,
  5277. Hdcall
  5278. };
  5279. ULONG_PTR args[] =
  5280. {
  5281. (ULONG_PTR) dwRequestID,
  5282. (ULONG_PTR) hdCall
  5283. };
  5284. REMOTE_FUNC_ARGS funcArgs =
  5285. {
  5286. MAKELONG (LINE_FUNC | ASYNC | 2, lHold),
  5287. args,
  5288. argTypes
  5289. };
  5290. return (REMOTEDOFUNC (&funcArgs, "lineHold"));
  5291. }
  5292. void
  5293. PASCAL
  5294. TSPI_lineMakeCall_PostProcess(
  5295. PASYNCEVENTMSG pMsg,
  5296. PASYNCREQUESTCONTEXT pContext
  5297. )
  5298. {
  5299. PDRVCALL pCall = (PDRVCALL) pContext->Params[0];
  5300. LOG((TL_INFO, "TSPI_lineMakeCall_PostProcess: enter"));
  5301. LOG((TL_INFO,
  5302. "\t\tp1=x%x, p2=x%x, p3=x%x, p4=x%x",
  5303. pMsg->Param1,
  5304. pMsg->Param2,
  5305. pMsg->Param3,
  5306. pMsg->Param4
  5307. ));
  5308. EnterCriticalSection (&gCallListCriticalSection);
  5309. if (!IsValidObject (pCall, DRVCALL_KEY) ||
  5310. (pCall->dwOriginalRequestID != pContext->dwOriginalRequestID))
  5311. {
  5312. LOG((TL_ERROR,
  5313. "TSPI_lineMakeCall_PostProcess: Bad pCall or ID - pCall x%lx",
  5314. pCall
  5315. ));
  5316. pMsg->Param2 = LINEERR_INVALLINEHANDLE;
  5317. }
  5318. else
  5319. {
  5320. if (pMsg->Param2 == 0)
  5321. {
  5322. if (pMsg->Param3 != 0)
  5323. {
  5324. // this is the normal success case
  5325. pCall->hCall = (HCALL) pMsg->Param3;
  5326. if (pMsg->TotalSize >= (sizeof (*pMsg) + 3 * sizeof(ULONG_PTR)))
  5327. {
  5328. pCall->dwAddressID = (DWORD) *(&pMsg->Param4 + 1);
  5329. pCall->dwCallID = (DWORD) *(&pMsg->Param4 + 2);
  5330. pCall->dwRelatedCallID = (DWORD) *(&pMsg->Param4 + 3);
  5331. }
  5332. else
  5333. {
  5334. pCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  5335. pCall->pServer->bVer2xServer = TRUE;
  5336. }
  5337. }
  5338. else
  5339. {
  5340. if (pContext->Params[1])
  5341. {
  5342. //
  5343. // This is the special lineforward case
  5344. // where we save the lphdCall in case
  5345. // we need to null it out
  5346. //
  5347. LPHDRVCALL lphdConsultCall = (LPHDRVCALL)
  5348. pContext->Params[1];
  5349. *lphdConsultCall = 0;
  5350. RemoveCallFromList (pCall);
  5351. }
  5352. else
  5353. {
  5354. }
  5355. }
  5356. }
  5357. else
  5358. {
  5359. RemoveCallFromList (pCall);
  5360. }
  5361. }
  5362. LeaveCriticalSection (&gCallListCriticalSection);
  5363. }
  5364. LONG
  5365. TSPIAPI
  5366. TSPI_lineMakeCall(
  5367. DRV_REQUESTID dwRequestID,
  5368. HDRVLINE hdLine,
  5369. HTAPICALL htCall,
  5370. LPHDRVCALL lphdCall,
  5371. LPCWSTR lpszDestAddress,
  5372. DWORD dwCountryCode,
  5373. LPLINECALLPARAMS const lpCallParams
  5374. )
  5375. {
  5376. static REMOTE_ARG_TYPES argTypes[] =
  5377. {
  5378. Dword,
  5379. Dword,
  5380. Hdline,
  5381. Dword,
  5382. lpsz,
  5383. Dword,
  5384. lpSet_Struct,
  5385. Dword
  5386. };
  5387. PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
  5388. ULONG_PTR args[] =
  5389. {
  5390. (ULONG_PTR) DWORD_CAST(dwRequestID,__FILE__,__LINE__),
  5391. (ULONG_PTR) 0,
  5392. (ULONG_PTR) hdLine,
  5393. (ULONG_PTR) 0,
  5394. (ULONG_PTR) lpszDestAddress,
  5395. (ULONG_PTR) DWORD_CAST(dwCountryCode,__FILE__,__LINE__),
  5396. (ULONG_PTR) lpCallParams,
  5397. (ULONG_PTR) 0xffffffff // dwCallParamsCodePage
  5398. };
  5399. REMOTE_FUNC_ARGS funcArgs =
  5400. {
  5401. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 8, lMakeCall),
  5402. args,
  5403. argTypes
  5404. };
  5405. LONG lResult;
  5406. if (pCall)
  5407. {
  5408. PASYNCREQUESTCONTEXT pContext;
  5409. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5410. {
  5411. DrvFree (pCall);
  5412. return LINEERR_NOMEM;
  5413. }
  5414. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5415. TSPI_lineMakeCall_PostProcess;
  5416. pContext->Params[0] = (ULONG_PTR) pCall;
  5417. args[1] = (ULONG_PTR) pContext;
  5418. argTypes[1] = lpContext;
  5419. //
  5420. // Assume success & add the call to the line's list before we
  5421. // even make the request. This makes cleanup alot easier if
  5422. // the server goes down or some such uncooth event.
  5423. //
  5424. pCall->dwOriginalRequestID = dwRequestID;
  5425. pCall->htCall = htCall;
  5426. pCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  5427. AddCallToList ((PDRVLINE) hdLine, pCall);
  5428. *lphdCall = (HDRVCALL) pCall;
  5429. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineMakeCall")) < 0)
  5430. {
  5431. RemoveCallFromList (pCall);
  5432. }
  5433. LOG((TL_INFO, "TSPI_lineMakeCall - new pCall x%lx", pCall));
  5434. }
  5435. else
  5436. {
  5437. lResult = LINEERR_NOMEM;
  5438. }
  5439. return lResult;
  5440. }
  5441. LONG
  5442. TSPIAPI
  5443. TSPI_lineMonitorDigits(
  5444. HDRVCALL hdCall,
  5445. DWORD dwDigitModes
  5446. )
  5447. {
  5448. static REMOTE_ARG_TYPES argTypes[] =
  5449. {
  5450. Hdcall,
  5451. Dword
  5452. };
  5453. ULONG_PTR args[] =
  5454. {
  5455. (ULONG_PTR) hdCall,
  5456. (ULONG_PTR) dwDigitModes
  5457. };
  5458. REMOTE_FUNC_ARGS funcArgs =
  5459. {
  5460. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
  5461. args,
  5462. argTypes
  5463. };
  5464. return (REMOTEDOFUNC (&funcArgs, "lineMonitorDigits"));
  5465. }
  5466. LONG
  5467. TSPIAPI
  5468. TSPI_lineMonitorMedia(
  5469. HDRVCALL hdCall,
  5470. DWORD dwMediaModes
  5471. )
  5472. {
  5473. static REMOTE_ARG_TYPES argTypes[] =
  5474. {
  5475. Hdcall,
  5476. Dword
  5477. };
  5478. ULONG_PTR args[] =
  5479. {
  5480. (ULONG_PTR) hdCall,
  5481. (ULONG_PTR) dwMediaModes
  5482. };
  5483. REMOTE_FUNC_ARGS funcArgs =
  5484. {
  5485. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
  5486. args,
  5487. argTypes
  5488. };
  5489. return (REMOTEDOFUNC (&funcArgs, "lineMonitorMedia"));
  5490. }
  5491. LONG
  5492. TSPIAPI
  5493. TSPI_lineMonitorTones(
  5494. HDRVCALL hdCall,
  5495. DWORD dwToneListID,
  5496. LPLINEMONITORTONE const lpToneList,
  5497. DWORD dwNumEntries
  5498. )
  5499. {
  5500. REMOTE_ARG_TYPES argTypes[] =
  5501. {
  5502. Hdcall,
  5503. lpSet_SizeToFollow,
  5504. Size,
  5505. Dword
  5506. };
  5507. ULONG_PTR args[] =
  5508. {
  5509. (ULONG_PTR) hdCall,
  5510. (ULONG_PTR) lpToneList,
  5511. (ULONG_PTR) dwNumEntries * sizeof (LINEMONITORTONE),
  5512. (ULONG_PTR) dwToneListID
  5513. };
  5514. REMOTE_FUNC_ARGS funcArgs =
  5515. {
  5516. MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
  5517. args,
  5518. argTypes
  5519. };
  5520. if (!lpToneList)
  5521. {
  5522. funcArgs.ArgTypes[1] = Dword;
  5523. funcArgs.Args[1] = TAPI_NO_DATA;
  5524. funcArgs.ArgTypes[2] = Dword;
  5525. }
  5526. return (REMOTEDOFUNC (&funcArgs, "lineMonitorTones"));
  5527. }
  5528. LONG
  5529. TSPIAPI
  5530. TSPI_lineNegotiateExtVersion(
  5531. DWORD dwDeviceID,
  5532. DWORD dwTSPIVersion,
  5533. DWORD dwLowVersion,
  5534. DWORD dwHighVersion,
  5535. LPDWORD lpdwExtVersion
  5536. )
  5537. {
  5538. static REMOTE_ARG_TYPES argTypes[] =
  5539. {
  5540. Dword,
  5541. LineID,
  5542. Dword,
  5543. Dword,
  5544. Dword,
  5545. lpDword
  5546. };
  5547. ULONG_PTR args[] =
  5548. {
  5549. (ULONG_PTR) 0,
  5550. (ULONG_PTR) dwDeviceID,
  5551. (ULONG_PTR) dwTSPIVersion,
  5552. (ULONG_PTR) dwLowVersion,
  5553. (ULONG_PTR) dwHighVersion,
  5554. (ULONG_PTR) lpdwExtVersion,
  5555. };
  5556. REMOTE_FUNC_ARGS funcArgs =
  5557. {
  5558. MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
  5559. args,
  5560. argTypes
  5561. };
  5562. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  5563. if (NULL == pLine)
  5564. {
  5565. return LINEERR_BADDEVICEID;
  5566. }
  5567. args[0] = pLine->pServer->hLineApp;
  5568. return (REMOTEDOFUNC (&funcArgs, "lineNegotiateExtVersion"));
  5569. }
  5570. LONG
  5571. TSPIAPI
  5572. TSPI_lineNegotiateTSPIVersion(
  5573. DWORD dwDeviceID,
  5574. DWORD dwLowVersion,
  5575. DWORD dwHighVersion,
  5576. LPDWORD lpdwTSPIVersion
  5577. )
  5578. {
  5579. LONG lRet = 0;
  5580. //
  5581. // Check ghInst to ensure DllMain(DLL_PROCESS_ATTACH) has been called properly
  5582. //
  5583. if ( NULL == ghInst )
  5584. {
  5585. return LINEERR_OPERATIONFAILED;
  5586. }
  5587. if (dwDeviceID == INITIALIZE_NEGOTIATION)
  5588. {
  5589. *lpdwTSPIVersion = TAPI_VERSION_CURRENT;
  5590. }
  5591. else
  5592. {
  5593. try
  5594. {
  5595. *lpdwTSPIVersion = (GetLineFromID (dwDeviceID))->dwXPIVersion;
  5596. }
  5597. except (EXCEPTION_EXECUTE_HANDLER)
  5598. {
  5599. lRet = LINEERR_OPERATIONFAILED;
  5600. }
  5601. }
  5602. return lRet;
  5603. }
  5604. LONG
  5605. TSPIAPI
  5606. TSPI_lineOpen(
  5607. DWORD dwDeviceID,
  5608. HTAPILINE pParams, // Hack Alert! see below
  5609. LPHDRVLINE lphdLine,
  5610. DWORD dwTSPIVersion,
  5611. LINEEVENT lpfnEventProc
  5612. )
  5613. {
  5614. //
  5615. // Hack Alert!
  5616. //
  5617. // Tapisrv does a special case for remotesp and line open
  5618. // to pass in the privileges, etc - htLine is really pParams,
  5619. // pointing at a ULONG_PTR array containing the htLine,
  5620. // privileges, media modes, call params, & ext version
  5621. //
  5622. LONG lResult;
  5623. REMOTE_ARG_TYPES argTypes[] =
  5624. {
  5625. Dword, // hLineApp
  5626. LineID, // dev id
  5627. lpDword, // lphLine
  5628. Dword, // API version
  5629. Dword, // ext version
  5630. Dword, // callback inst
  5631. Dword, // privileges
  5632. Dword, // dw media modes
  5633. lpSet_Struct, // call params
  5634. Dword, // dwAsciiCallParamsCodePage
  5635. lpGet_CallParamsStruct,
  5636. Dword // remote hLine
  5637. };
  5638. PDRVLINE pLine = GetLineFromID (dwDeviceID);
  5639. ULONG_PTR args[] =
  5640. {
  5641. (ULONG_PTR) 0,
  5642. (ULONG_PTR) dwDeviceID,
  5643. (ULONG_PTR) 0,
  5644. (ULONG_PTR) dwTSPIVersion,
  5645. (ULONG_PTR) ((ULONG_PTR *) pParams)[4], // ext version
  5646. (ULONG_PTR) 0,
  5647. (ULONG_PTR) ((ULONG_PTR *) pParams)[1], // privilege(s)
  5648. (ULONG_PTR) ((ULONG_PTR *) pParams)[2], // media mode
  5649. (ULONG_PTR) ((ULONG_PTR *) pParams)[3], // pCallParams
  5650. (ULONG_PTR) 0xffffffff,
  5651. (ULONG_PTR) ((ULONG_PTR *) pParams)[3],
  5652. (ULONG_PTR) 0
  5653. };
  5654. REMOTE_FUNC_ARGS funcArgs =
  5655. {
  5656. MAKELONG (LINE_FUNC | SYNC | 12, lOpen),
  5657. args,
  5658. argTypes
  5659. };
  5660. if (NULL == pLine)
  5661. {
  5662. return LINEERR_BADDEVICEID;
  5663. }
  5664. args[0] = pLine->pServer->hLineApp;
  5665. args[2] = (ULONG_PTR)&pLine->hLine;
  5666. if (!(args[11] = NewObject (ghHandleTable, pLine, (LPVOID) 1)))
  5667. {
  5668. return LINEERR_NOMEM;
  5669. }
  5670. pLine->hDeviceCallback = (DWORD) args[11];
  5671. if ( (((ULONG_PTR *) pParams)[3] == 0) ||
  5672. (((ULONG_PTR *) pParams)[3] == TAPI_NO_DATA) )
  5673. {
  5674. argTypes[8] = Dword;
  5675. args[8] = TAPI_NO_DATA;
  5676. argTypes[10] = Dword;
  5677. args[10] = TAPI_NO_DATA;
  5678. }
  5679. pLine->dwKey = DRVLINE_KEY;
  5680. pLine->htLine = (HTAPILINE) (((ULONG_PTR *) pParams)[0]);
  5681. *lphdLine = (HDRVLINE) pLine;
  5682. lResult = REMOTEDOFUNC (&funcArgs, "lineOpen");
  5683. if (lResult != 0)
  5684. {
  5685. DereferenceObject (ghHandleTable, pLine->hDeviceCallback, 1);
  5686. if ((HIWORD(lResult) == RSP_CALLPARAMS))
  5687. {
  5688. //
  5689. // Hack Alert!
  5690. //
  5691. // If structure too small, give tapisrv the
  5692. // needed size in lphdLine
  5693. //
  5694. *lphdLine = (HDRVLINE)(LOWORD(lResult));
  5695. lResult = LINEERR_STRUCTURETOOSMALL;
  5696. }
  5697. }
  5698. return lResult;
  5699. }
  5700. void
  5701. PASCAL
  5702. TSPI_linePark_PostProcess(
  5703. PASYNCEVENTMSG pMsg,
  5704. PASYNCREQUESTCONTEXT pContext
  5705. )
  5706. {
  5707. LOG((TL_INFO, "lineParkPostProcess: enter"));
  5708. LOG((TL_INFO,
  5709. "\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
  5710. pMsg->Param1,
  5711. pMsg->Param2,
  5712. pMsg->Param3,
  5713. pMsg->Param4
  5714. ));
  5715. if (pMsg->Param2 == 0)
  5716. {
  5717. DWORD dwSize = (DWORD) pMsg->Param4;
  5718. LPVARSTRING pNonDirAddress = (LPVARSTRING) pContext->Params[0];
  5719. CopyMemory (pNonDirAddress, (LPBYTE) (pMsg + 1), dwSize);
  5720. }
  5721. }
  5722. LONG
  5723. TSPIAPI
  5724. TSPI_linePark(
  5725. DRV_REQUESTID dwRequestID,
  5726. HDRVCALL hdCall,
  5727. DWORD dwParkMode,
  5728. LPCWSTR lpszDirAddress,
  5729. LPVARSTRING lpNonDirAddress
  5730. )
  5731. {
  5732. REMOTE_ARG_TYPES argTypes[] =
  5733. {
  5734. Dword,
  5735. Dword,
  5736. Hdcall,
  5737. Dword,
  5738. (dwParkMode == LINEPARKMODE_DIRECTED) ? lpsz : Dword,
  5739. Dword, // pass ptr as Dword for post processing
  5740. (lpNonDirAddress ? lpGet_Struct : Dword) // pass ptr as lpGet_Xx to retrieve dwTotalSize
  5741. };
  5742. ULONG_PTR args[] =
  5743. {
  5744. (ULONG_PTR) dwRequestID,
  5745. (ULONG_PTR) 0,
  5746. (ULONG_PTR) hdCall,
  5747. (ULONG_PTR) dwParkMode,
  5748. (ULONG_PTR) lpszDirAddress,
  5749. (ULONG_PTR) 0,
  5750. (ULONG_PTR) lpNonDirAddress
  5751. };
  5752. REMOTE_FUNC_ARGS funcArgs =
  5753. {
  5754. MAKELONG (LINE_FUNC | ASYNC | 7, lPark),
  5755. args,
  5756. argTypes
  5757. };
  5758. PASYNCREQUESTCONTEXT pContext;
  5759. if (dwParkMode == LINEPARKMODE_NONDIRECTED)
  5760. {
  5761. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5762. {
  5763. return LINEERR_NOMEM;
  5764. }
  5765. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5766. TSPI_linePark_PostProcess;
  5767. pContext->Params[0] = (ULONG_PTR) lpNonDirAddress;
  5768. args[1] = (ULONG_PTR) pContext;
  5769. argTypes[1] = lpContext;
  5770. funcArgs.Flags |= INCL_CONTEXT;
  5771. }
  5772. return (REMOTEDOFUNC (&funcArgs, "linePark"));
  5773. }
  5774. LONG
  5775. TSPIAPI
  5776. TSPI_linePickup(
  5777. DRV_REQUESTID dwRequestID,
  5778. HDRVLINE hdLine,
  5779. DWORD dwAddressID,
  5780. HTAPICALL htCall,
  5781. LPHDRVCALL lphdCall,
  5782. LPCWSTR lpszDestAddress,
  5783. LPCWSTR lpszGroupID
  5784. )
  5785. {
  5786. static REMOTE_ARG_TYPES argTypes[] =
  5787. {
  5788. Dword,
  5789. Dword,
  5790. Hdline,
  5791. Dword,
  5792. Dword,
  5793. lpsz,
  5794. lpsz
  5795. };
  5796. PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
  5797. ULONG_PTR args[] =
  5798. {
  5799. (ULONG_PTR) dwRequestID,
  5800. (ULONG_PTR) 0,
  5801. (ULONG_PTR) hdLine,
  5802. (ULONG_PTR) dwAddressID,
  5803. (ULONG_PTR) 0,
  5804. (ULONG_PTR) lpszDestAddress,
  5805. (ULONG_PTR) lpszGroupID
  5806. };
  5807. REMOTE_FUNC_ARGS funcArgs =
  5808. {
  5809. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 7, lPickup),
  5810. args,
  5811. argTypes
  5812. };
  5813. LONG lResult;
  5814. if (pCall)
  5815. {
  5816. PASYNCREQUESTCONTEXT pContext;
  5817. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5818. {
  5819. DrvFree (pCall);
  5820. return LINEERR_NOMEM;
  5821. }
  5822. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5823. TSPI_lineMakeCall_PostProcess;
  5824. pContext->Params[0] = (ULONG_PTR) pCall;
  5825. args[1] = (ULONG_PTR) pContext;
  5826. argTypes[1] = lpContext;
  5827. pCall->htCall = htCall;
  5828. pCall->dwOriginalRequestID = dwRequestID;
  5829. pCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  5830. AddCallToList ((PDRVLINE) hdLine, pCall);
  5831. *lphdCall = (HDRVCALL) pCall;
  5832. if ((lResult = REMOTEDOFUNC (&funcArgs, "linePickup")) < 0)
  5833. {
  5834. RemoveCallFromList (pCall);
  5835. }
  5836. }
  5837. else
  5838. {
  5839. lResult = LINEERR_NOMEM;
  5840. }
  5841. return lResult;
  5842. }
  5843. LONG
  5844. TSPIAPI
  5845. TSPI_linePrepareAddToConference(
  5846. DRV_REQUESTID dwRequestID,
  5847. HDRVCALL hdConfCall,
  5848. HTAPICALL htConsultCall,
  5849. LPHDRVCALL lphdConsultCall,
  5850. LPLINECALLPARAMS const lpCallParams
  5851. )
  5852. {
  5853. static REMOTE_ARG_TYPES argTypes[] =
  5854. {
  5855. Dword,
  5856. Dword,
  5857. Hdcall,
  5858. Dword,
  5859. lpSet_Struct,
  5860. Dword
  5861. };
  5862. PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
  5863. ULONG_PTR args[] =
  5864. {
  5865. (ULONG_PTR) dwRequestID,
  5866. (ULONG_PTR) 0,
  5867. (ULONG_PTR) hdConfCall,
  5868. (ULONG_PTR) 0,
  5869. (ULONG_PTR) lpCallParams,
  5870. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  5871. };
  5872. REMOTE_FUNC_ARGS funcArgs =
  5873. {
  5874. MAKELONG(LINE_FUNC | ASYNC | INCL_CONTEXT | 6,lPrepareAddToConference),
  5875. args,
  5876. argTypes
  5877. };
  5878. LONG lResult;
  5879. if (pConsultCall)
  5880. {
  5881. PASYNCREQUESTCONTEXT pContext;
  5882. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  5883. {
  5884. DrvFree (pConsultCall);
  5885. return LINEERR_NOMEM;
  5886. }
  5887. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  5888. TSPI_lineMakeCall_PostProcess;
  5889. pContext->Params[0] = (ULONG_PTR) pConsultCall;
  5890. args[1] = (ULONG_PTR) pContext;
  5891. argTypes[1] = lpContext;
  5892. pConsultCall->htCall = htConsultCall;
  5893. pConsultCall->dwOriginalRequestID = dwRequestID;
  5894. pConsultCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  5895. AddCallToList (((PDRVCALL) hdConfCall)->pLine, pConsultCall);
  5896. *lphdConsultCall = (HDRVCALL) pConsultCall;
  5897. if ((lResult = REMOTEDOFUNC (&funcArgs, "linePrepareAddToConference"))
  5898. < 0)
  5899. {
  5900. RemoveCallFromList (pConsultCall);
  5901. }
  5902. }
  5903. else
  5904. {
  5905. lResult = LINEERR_NOMEM;
  5906. }
  5907. return lResult;
  5908. }
  5909. LONG
  5910. TSPIAPI
  5911. TSPI_lineRedirect(
  5912. DRV_REQUESTID dwRequestID,
  5913. HDRVCALL hdCall,
  5914. LPCWSTR lpszDestAddress,
  5915. DWORD dwCountryCode
  5916. )
  5917. {
  5918. static REMOTE_ARG_TYPES argTypes[] =
  5919. {
  5920. Dword,
  5921. Hdcall,
  5922. lpsz,
  5923. Dword
  5924. };
  5925. ULONG_PTR args[] =
  5926. {
  5927. (ULONG_PTR) dwRequestID,
  5928. (ULONG_PTR) hdCall,
  5929. (ULONG_PTR) lpszDestAddress,
  5930. (ULONG_PTR) dwCountryCode
  5931. };
  5932. REMOTE_FUNC_ARGS funcArgs =
  5933. {
  5934. MAKELONG (LINE_FUNC | ASYNC | 4, lRedirect),
  5935. args,
  5936. argTypes
  5937. };
  5938. return (REMOTEDOFUNC (&funcArgs, "lineRedirect"));
  5939. }
  5940. LONG
  5941. TSPIAPI
  5942. TSPI_lineReleaseUserUserInfo(
  5943. DRV_REQUESTID dwRequestID,
  5944. HDRVCALL hdCall
  5945. )
  5946. {
  5947. static REMOTE_ARG_TYPES argTypes[] =
  5948. {
  5949. Dword,
  5950. Hdcall
  5951. };
  5952. ULONG_PTR args[] =
  5953. {
  5954. (ULONG_PTR) dwRequestID,
  5955. (ULONG_PTR) hdCall
  5956. };
  5957. REMOTE_FUNC_ARGS funcArgs =
  5958. {
  5959. MAKELONG (LINE_FUNC | ASYNC | 2, lReleaseUserUserInfo),
  5960. args,
  5961. argTypes
  5962. };
  5963. return (REMOTEDOFUNC (&funcArgs, "lineReleaseUserUserInfo"));
  5964. }
  5965. LONG
  5966. TSPIAPI
  5967. TSPI_lineRemoveFromConference(
  5968. DRV_REQUESTID dwRequestID,
  5969. HDRVCALL hdCall
  5970. )
  5971. {
  5972. static REMOTE_ARG_TYPES argTypes[] =
  5973. {
  5974. Dword,
  5975. Hdcall
  5976. };
  5977. ULONG_PTR args[] =
  5978. {
  5979. (ULONG_PTR) dwRequestID,
  5980. (ULONG_PTR) hdCall
  5981. };
  5982. REMOTE_FUNC_ARGS funcArgs =
  5983. {
  5984. MAKELONG (LINE_FUNC | ASYNC | 2, lRemoveFromConference),
  5985. args,
  5986. argTypes
  5987. };
  5988. return (REMOTEDOFUNC (&funcArgs, "lineRemoveFromConference"));
  5989. }
  5990. LONG
  5991. TSPIAPI
  5992. TSPI_lineSecureCall(
  5993. DRV_REQUESTID dwRequestID,
  5994. HDRVCALL hdCall
  5995. )
  5996. {
  5997. static REMOTE_ARG_TYPES argTypes[] =
  5998. {
  5999. Dword,
  6000. Hdcall
  6001. };
  6002. ULONG_PTR args[] =
  6003. {
  6004. (ULONG_PTR) dwRequestID,
  6005. (ULONG_PTR) hdCall
  6006. };
  6007. REMOTE_FUNC_ARGS funcArgs =
  6008. {
  6009. MAKELONG (LINE_FUNC | ASYNC | 2, lSecureCall),
  6010. args,
  6011. argTypes
  6012. };
  6013. return (REMOTEDOFUNC (&funcArgs, "lineSecureCall"));
  6014. }
  6015. LONG
  6016. TSPIAPI
  6017. TSPI_lineSelectExtVersion(
  6018. HDRVLINE hdLine,
  6019. DWORD dwExtVersion
  6020. )
  6021. {
  6022. static REMOTE_ARG_TYPES argTypes[] =
  6023. {
  6024. Hdline,
  6025. Dword
  6026. };
  6027. ULONG_PTR args[] =
  6028. {
  6029. (ULONG_PTR) hdLine,
  6030. (ULONG_PTR) dwExtVersion
  6031. };
  6032. REMOTE_FUNC_ARGS funcArgs =
  6033. {
  6034. MAKELONG (LINE_FUNC | SYNC | 2, lSelectExtVersion),
  6035. args,
  6036. argTypes
  6037. };
  6038. return (REMOTEDOFUNC (&funcArgs, "lineSelectExtVersion"));
  6039. }
  6040. LONG
  6041. TSPIAPI
  6042. TSPI_lineSendUserUserInfo(
  6043. DRV_REQUESTID dwRequestID,
  6044. HDRVCALL hdCall,
  6045. LPCSTR lpsUserUserInfo,
  6046. DWORD dwSize
  6047. )
  6048. {
  6049. static REMOTE_ARG_TYPES argTypes[] =
  6050. {
  6051. Dword,
  6052. Hdcall,
  6053. lpSet_SizeToFollow,
  6054. Size
  6055. };
  6056. ULONG_PTR args[] =
  6057. {
  6058. (ULONG_PTR) dwRequestID,
  6059. (ULONG_PTR) hdCall,
  6060. (ULONG_PTR) lpsUserUserInfo,
  6061. (ULONG_PTR) dwSize
  6062. };
  6063. REMOTE_FUNC_ARGS funcArgs =
  6064. {
  6065. MAKELONG (LINE_FUNC | ASYNC | 4, lSendUserUserInfo),
  6066. args,
  6067. argTypes
  6068. };
  6069. return (REMOTEDOFUNC (&funcArgs, "lineSendUserUserInfo"));
  6070. }
  6071. LONG
  6072. TSPIAPI
  6073. TSPI_lineSetAgentActivity(
  6074. DRV_REQUESTID dwRequestID,
  6075. HDRVLINE hdLine,
  6076. DWORD dwAddressID,
  6077. DWORD dwActivityID
  6078. )
  6079. {
  6080. static REMOTE_ARG_TYPES argTypes[] =
  6081. {
  6082. Dword,
  6083. Hdline,
  6084. Dword,
  6085. Dword
  6086. };
  6087. ULONG_PTR args[] =
  6088. {
  6089. (ULONG_PTR) dwRequestID,
  6090. (ULONG_PTR) hdLine,
  6091. (ULONG_PTR) dwAddressID,
  6092. (ULONG_PTR) dwActivityID
  6093. };
  6094. REMOTE_FUNC_ARGS funcArgs =
  6095. {
  6096. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentActivity),
  6097. args,
  6098. argTypes
  6099. };
  6100. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentActivity"));
  6101. }
  6102. LONG
  6103. TSPIAPI
  6104. TSPI_lineSetAgentGroup(
  6105. DRV_REQUESTID dwRequestID,
  6106. HDRVLINE hdLine,
  6107. DWORD dwAddressID,
  6108. LPLINEAGENTGROUPLIST lpAgentGroupList
  6109. )
  6110. {
  6111. static REMOTE_ARG_TYPES argTypes[] =
  6112. {
  6113. Dword,
  6114. Hdline,
  6115. Dword,
  6116. lpSet_Struct
  6117. };
  6118. ULONG_PTR args[] =
  6119. {
  6120. (ULONG_PTR) dwRequestID,
  6121. (ULONG_PTR) hdLine,
  6122. (ULONG_PTR) dwAddressID,
  6123. (ULONG_PTR) lpAgentGroupList
  6124. };
  6125. REMOTE_FUNC_ARGS funcArgs =
  6126. {
  6127. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentGroup),
  6128. args,
  6129. argTypes
  6130. };
  6131. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentGroup"));
  6132. }
  6133. LONG
  6134. TSPIAPI
  6135. TSPI_lineSetAgentMeasurementPeriod(
  6136. DRV_REQUESTID dwRequestID,
  6137. HDRVLINE hdLine,
  6138. HAGENT hAgent,
  6139. DWORD dwMeasurementPeriod
  6140. )
  6141. {
  6142. static REMOTE_ARG_TYPES argTypes[] =
  6143. {
  6144. Dword,
  6145. Hdline,
  6146. Dword,
  6147. Dword
  6148. };
  6149. ULONG_PTR args[] =
  6150. {
  6151. (ULONG_PTR) dwRequestID,
  6152. (ULONG_PTR) hdLine,
  6153. (ULONG_PTR) hAgent,
  6154. (ULONG_PTR) dwMeasurementPeriod
  6155. };
  6156. REMOTE_FUNC_ARGS funcArgs =
  6157. {
  6158. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentMeasurementPeriod),
  6159. args,
  6160. argTypes
  6161. };
  6162. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentMeasurementPeriod"));
  6163. }
  6164. LONG
  6165. TSPIAPI
  6166. TSPI_lineSetAgentSessionState(
  6167. DRV_REQUESTID dwRequestID,
  6168. HDRVLINE hdLine,
  6169. HAGENTSESSION hAgentSession,
  6170. DWORD dwAgentState,
  6171. DWORD dwNextAgentState
  6172. )
  6173. {
  6174. static REMOTE_ARG_TYPES argTypes[] =
  6175. {
  6176. Dword,
  6177. Hdline,
  6178. Dword,
  6179. Dword,
  6180. Dword
  6181. };
  6182. ULONG_PTR args[] =
  6183. {
  6184. (ULONG_PTR) dwRequestID,
  6185. (ULONG_PTR) hdLine,
  6186. (ULONG_PTR) hAgentSession,
  6187. (ULONG_PTR) dwAgentState,
  6188. (ULONG_PTR) dwNextAgentState
  6189. };
  6190. REMOTE_FUNC_ARGS funcArgs =
  6191. {
  6192. MAKELONG (LINE_FUNC | ASYNC | 5, lSetAgentSessionState),
  6193. args,
  6194. argTypes
  6195. };
  6196. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentSessionState"));
  6197. }
  6198. LONG
  6199. TSPIAPI
  6200. TSPI_lineSetAgentState(
  6201. DRV_REQUESTID dwRequestID,
  6202. HDRVLINE hdLine,
  6203. DWORD dwAddressID,
  6204. DWORD dwAgentState,
  6205. DWORD dwNextAgentState
  6206. )
  6207. {
  6208. static REMOTE_ARG_TYPES argTypes[] =
  6209. {
  6210. Dword,
  6211. Hdline,
  6212. Dword,
  6213. Dword,
  6214. Dword
  6215. };
  6216. ULONG_PTR args[] =
  6217. {
  6218. (ULONG_PTR) dwRequestID,
  6219. (ULONG_PTR) hdLine,
  6220. (ULONG_PTR) dwAddressID,
  6221. (ULONG_PTR) dwAgentState,
  6222. (ULONG_PTR) dwNextAgentState
  6223. };
  6224. REMOTE_FUNC_ARGS funcArgs =
  6225. {
  6226. MAKELONG (LINE_FUNC | ASYNC | 5, lSetAgentState),
  6227. args,
  6228. argTypes
  6229. };
  6230. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentState"));
  6231. }
  6232. LONG
  6233. TSPIAPI
  6234. TSPI_lineSetAgentStateEx(
  6235. DRV_REQUESTID dwRequestID,
  6236. HDRVLINE hdLine,
  6237. HAGENT hAgent,
  6238. DWORD dwAgentState,
  6239. DWORD dwNextAgentState
  6240. )
  6241. {
  6242. static REMOTE_ARG_TYPES argTypes[] =
  6243. {
  6244. Dword,
  6245. Hdline,
  6246. Dword,
  6247. Dword,
  6248. Dword
  6249. };
  6250. ULONG_PTR args[] =
  6251. {
  6252. (ULONG_PTR) dwRequestID,
  6253. (ULONG_PTR) hdLine,
  6254. (ULONG_PTR) hAgent,
  6255. (ULONG_PTR) dwAgentState,
  6256. (ULONG_PTR) dwNextAgentState
  6257. };
  6258. REMOTE_FUNC_ARGS funcArgs =
  6259. {
  6260. MAKELONG (LINE_FUNC | ASYNC | 5, lSetAgentStateEx),
  6261. args,
  6262. argTypes
  6263. };
  6264. return (REMOTEDOFUNC (&funcArgs, "lineSetAgentStateEx"));
  6265. }
  6266. LONG
  6267. TSPIAPI
  6268. TSPI_lineSetAppSpecific(
  6269. HDRVCALL hdCall,
  6270. DWORD dwAppSpecific
  6271. )
  6272. {
  6273. static REMOTE_ARG_TYPES argTypes[] =
  6274. {
  6275. Hdcall,
  6276. Dword
  6277. };
  6278. ULONG_PTR args[] =
  6279. {
  6280. (ULONG_PTR) hdCall,
  6281. (ULONG_PTR) dwAppSpecific
  6282. };
  6283. REMOTE_FUNC_ARGS funcArgs =
  6284. {
  6285. MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
  6286. args,
  6287. argTypes
  6288. };
  6289. return (REMOTEDOFUNC (&funcArgs, "lineSetAppSpecific"));
  6290. }
  6291. LONG
  6292. TSPIAPI
  6293. TSPI_lineSetCallData(
  6294. DRV_REQUESTID dwRequestID,
  6295. HDRVCALL hdCall,
  6296. LPVOID lpCallData,
  6297. DWORD dwSize
  6298. )
  6299. {
  6300. static REMOTE_ARG_TYPES argTypes[] =
  6301. {
  6302. Dword,
  6303. Hdcall,
  6304. lpSet_SizeToFollow,
  6305. Size
  6306. };
  6307. ULONG_PTR args[] =
  6308. {
  6309. (ULONG_PTR) dwRequestID,
  6310. (ULONG_PTR) hdCall,
  6311. (ULONG_PTR) lpCallData,
  6312. (ULONG_PTR) dwSize
  6313. };
  6314. REMOTE_FUNC_ARGS funcArgs =
  6315. {
  6316. MAKELONG (LINE_FUNC | ASYNC | 4, lSetCallData),
  6317. args,
  6318. argTypes
  6319. };
  6320. return (REMOTEDOFUNC (&funcArgs, "lineSetCallData"));
  6321. }
  6322. LONG
  6323. TSPIAPI
  6324. TSPI_lineSetCallHubTracking(
  6325. HDRVLINE hdLine,
  6326. LPLINECALLHUBTRACKINGINFO lpTrackingInfo
  6327. )
  6328. {
  6329. static REMOTE_ARG_TYPES argTypes[] =
  6330. {
  6331. Hdline,
  6332. lpSet_Struct
  6333. };
  6334. ULONG_PTR args[] =
  6335. {
  6336. (ULONG_PTR) hdLine,
  6337. (ULONG_PTR) lpTrackingInfo
  6338. };
  6339. REMOTE_FUNC_ARGS funcArgs =
  6340. {
  6341. MAKELONG (LINE_FUNC | SYNC | 2, lSetCallHubTracking),
  6342. args,
  6343. argTypes
  6344. };
  6345. return (REMOTEDOFUNC (&funcArgs, "lineSetCallHubTracking"));
  6346. }
  6347. LONG
  6348. TSPIAPI
  6349. TSPI_lineSetCallParams(
  6350. DRV_REQUESTID dwRequestID,
  6351. HDRVCALL hdCall,
  6352. DWORD dwBearerMode,
  6353. DWORD dwMinRate,
  6354. DWORD dwMaxRate,
  6355. LPLINEDIALPARAMS const lpDialParams
  6356. )
  6357. {
  6358. static REMOTE_ARG_TYPES argTypes[] =
  6359. {
  6360. Dword,
  6361. Hdcall,
  6362. Dword,
  6363. Dword,
  6364. Dword,
  6365. lpSet_SizeToFollow,
  6366. Size
  6367. };
  6368. ULONG_PTR args[] =
  6369. {
  6370. (ULONG_PTR) dwRequestID,
  6371. (ULONG_PTR) hdCall,
  6372. (ULONG_PTR) dwBearerMode,
  6373. (ULONG_PTR) dwMinRate,
  6374. (ULONG_PTR) dwMaxRate,
  6375. (ULONG_PTR) lpDialParams,
  6376. (ULONG_PTR) (lpDialParams ? sizeof (LINEDIALPARAMS) : 0)
  6377. };
  6378. REMOTE_FUNC_ARGS funcArgs =
  6379. {
  6380. MAKELONG (LINE_FUNC | ASYNC | 7, lSetCallParams),
  6381. args,
  6382. argTypes
  6383. };
  6384. return (REMOTEDOFUNC (&funcArgs, "lineSetCallParams"));
  6385. }
  6386. LONG
  6387. TSPIAPI
  6388. TSPI_lineSetCallQualityOfService(
  6389. DRV_REQUESTID dwRequestID,
  6390. HDRVCALL hdCall,
  6391. LPVOID lpSendingFlowspec,
  6392. DWORD dwSendingFlowspecSize,
  6393. LPVOID lpReceivingFlowspec,
  6394. DWORD dwReceivingFlowspecSize
  6395. )
  6396. {
  6397. static REMOTE_ARG_TYPES argTypes[] =
  6398. {
  6399. Dword,
  6400. Hdcall,
  6401. lpSet_SizeToFollow,
  6402. Size,
  6403. lpSet_SizeToFollow,
  6404. Size
  6405. };
  6406. ULONG_PTR args[] =
  6407. {
  6408. (ULONG_PTR) dwRequestID,
  6409. (ULONG_PTR) hdCall,
  6410. (ULONG_PTR) lpSendingFlowspec,
  6411. (ULONG_PTR) dwSendingFlowspecSize,
  6412. (ULONG_PTR) lpReceivingFlowspec,
  6413. (ULONG_PTR) dwReceivingFlowspecSize
  6414. };
  6415. REMOTE_FUNC_ARGS funcArgs =
  6416. {
  6417. MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallQualityOfService),
  6418. args,
  6419. argTypes
  6420. };
  6421. return (REMOTEDOFUNC (&funcArgs, "lineSetCallQualityOfService"));
  6422. }
  6423. LONG
  6424. TSPIAPI
  6425. TSPI_lineSetCallTreatment(
  6426. DRV_REQUESTID dwRequestID,
  6427. HDRVCALL hdCall,
  6428. DWORD dwTreatment
  6429. )
  6430. {
  6431. static REMOTE_ARG_TYPES argTypes[] =
  6432. {
  6433. Dword,
  6434. Hdcall,
  6435. Dword
  6436. };
  6437. ULONG_PTR args[] =
  6438. {
  6439. (ULONG_PTR) dwRequestID,
  6440. (ULONG_PTR) hdCall,
  6441. (ULONG_PTR) dwTreatment
  6442. };
  6443. REMOTE_FUNC_ARGS funcArgs =
  6444. {
  6445. MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallTreatment),
  6446. args,
  6447. argTypes
  6448. };
  6449. return (REMOTEDOFUNC (&funcArgs, "lineSetCallTreatment"));
  6450. }
  6451. LONG
  6452. TSPIAPI
  6453. TSPI_lineSetCurrentLocation(
  6454. DWORD dwLocation
  6455. )
  6456. {
  6457. return LINEERR_OPERATIONUNAVAIL;
  6458. }
  6459. LONG
  6460. TSPIAPI
  6461. TSPI_lineSetDefaultMediaDetection(
  6462. HDRVLINE hdLine,
  6463. DWORD dwMediaModes
  6464. )
  6465. {
  6466. static REMOTE_ARG_TYPES argTypes[] =
  6467. {
  6468. Hdline,
  6469. Dword
  6470. };
  6471. ULONG_PTR args[] =
  6472. {
  6473. (ULONG_PTR) hdLine,
  6474. (ULONG_PTR) dwMediaModes,
  6475. };
  6476. REMOTE_FUNC_ARGS funcArgs =
  6477. {
  6478. MAKELONG (LINE_FUNC | SYNC | 2, lSetDefaultMediaDetection),
  6479. args,
  6480. argTypes
  6481. };
  6482. return (REMOTEDOFUNC (&funcArgs, "lineSetDefaultMediaDetection"));
  6483. }
  6484. LONG
  6485. TSPIAPI
  6486. TSPI_lineSetDevConfig(
  6487. DWORD dwDeviceID,
  6488. LPVOID const lpDeviceConfig,
  6489. DWORD dwSize,
  6490. LPCWSTR lpszDeviceClass
  6491. )
  6492. {
  6493. static REMOTE_ARG_TYPES argTypes[] =
  6494. {
  6495. LineID,
  6496. lpSet_SizeToFollow,
  6497. Size,
  6498. lpsz
  6499. };
  6500. ULONG_PTR args[] =
  6501. {
  6502. (ULONG_PTR) dwDeviceID,
  6503. (ULONG_PTR) lpDeviceConfig,
  6504. (ULONG_PTR) dwSize,
  6505. (ULONG_PTR) lpszDeviceClass
  6506. };
  6507. REMOTE_FUNC_ARGS funcArgs =
  6508. {
  6509. MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
  6510. args,
  6511. argTypes
  6512. };
  6513. return (REMOTEDOFUNC (&funcArgs, "lineSetDevConfig"));
  6514. }
  6515. LONG
  6516. TSPIAPI
  6517. TSPI_lineSetLineDevStatus(
  6518. DRV_REQUESTID dwRequestID,
  6519. HDRVLINE hdLine,
  6520. DWORD dwStatusToChange,
  6521. DWORD fStatus
  6522. )
  6523. {
  6524. static REMOTE_ARG_TYPES argTypes[] =
  6525. {
  6526. Dword,
  6527. Hdline,
  6528. Dword,
  6529. Dword
  6530. };
  6531. ULONG_PTR args[] =
  6532. {
  6533. (ULONG_PTR) dwRequestID,
  6534. (ULONG_PTR) hdLine,
  6535. (ULONG_PTR) dwStatusToChange,
  6536. (ULONG_PTR) fStatus
  6537. };
  6538. REMOTE_FUNC_ARGS funcArgs =
  6539. {
  6540. MAKELONG (LINE_FUNC | ASYNC | 4, lSetLineDevStatus),
  6541. args,
  6542. argTypes
  6543. };
  6544. return (REMOTEDOFUNC (&funcArgs, "lineSetLineDevStatus"));
  6545. }
  6546. LONG
  6547. TSPIAPI
  6548. TSPI_lineSetMediaControl(
  6549. HDRVLINE hdLine,
  6550. DWORD dwAddressID,
  6551. HDRVCALL hdCall,
  6552. DWORD dwSelect,
  6553. LPLINEMEDIACONTROLDIGIT const lpDigitList,
  6554. DWORD dwDigitNumEntries,
  6555. LPLINEMEDIACONTROLMEDIA const lpMediaList,
  6556. DWORD dwMediaNumEntries,
  6557. LPLINEMEDIACONTROLTONE const lpToneList,
  6558. DWORD dwToneNumEntries,
  6559. LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
  6560. DWORD dwCallStateNumEntries
  6561. )
  6562. {
  6563. REMOTE_ARG_TYPES argTypes[] =
  6564. {
  6565. (dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
  6566. Dword,
  6567. (dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
  6568. Dword,
  6569. lpSet_SizeToFollow,
  6570. Size,
  6571. lpSet_SizeToFollow,
  6572. Size,
  6573. lpSet_SizeToFollow,
  6574. Size,
  6575. lpSet_SizeToFollow,
  6576. Size
  6577. };
  6578. ULONG_PTR args[] =
  6579. {
  6580. (ULONG_PTR) hdLine,
  6581. (ULONG_PTR) dwAddressID,
  6582. (ULONG_PTR) hdCall,
  6583. (ULONG_PTR) dwSelect,
  6584. (ULONG_PTR) lpDigitList,
  6585. (ULONG_PTR) dwDigitNumEntries,
  6586. (ULONG_PTR) lpMediaList,
  6587. (ULONG_PTR) dwMediaNumEntries,
  6588. (ULONG_PTR) lpToneList,
  6589. (ULONG_PTR) dwToneNumEntries,
  6590. (ULONG_PTR) lpCallStateList,
  6591. (ULONG_PTR) dwCallStateNumEntries
  6592. };
  6593. REMOTE_FUNC_ARGS funcArgs =
  6594. {
  6595. MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
  6596. args,
  6597. argTypes
  6598. };
  6599. dwDigitNumEntries *= sizeof (LINEMEDIACONTROLDIGIT);
  6600. dwMediaNumEntries *= sizeof (LINEMEDIACONTROLMEDIA);
  6601. dwToneNumEntries *= sizeof (LINEMEDIACONTROLTONE);
  6602. dwCallStateNumEntries *= sizeof (LINEMEDIACONTROLCALLSTATE);
  6603. return (REMOTEDOFUNC (&funcArgs, "lineSetMediaControl"));
  6604. }
  6605. LONG
  6606. TSPIAPI
  6607. TSPI_lineSetMediaMode(
  6608. HDRVCALL hdCall,
  6609. DWORD dwMediaMode
  6610. )
  6611. {
  6612. static REMOTE_ARG_TYPES argTypes[] =
  6613. {
  6614. Hdcall,
  6615. Dword
  6616. };
  6617. ULONG_PTR args[] =
  6618. {
  6619. (ULONG_PTR) hdCall,
  6620. (ULONG_PTR) dwMediaMode
  6621. };
  6622. REMOTE_FUNC_ARGS funcArgs =
  6623. {
  6624. MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
  6625. args,
  6626. argTypes
  6627. };
  6628. return (REMOTEDOFUNC (&funcArgs, "lineSetMediaMode"));
  6629. }
  6630. LONG
  6631. TSPIAPI
  6632. TSPI_lineSetQueueMeasurementPeriod(
  6633. DRV_REQUESTID dwRequestID,
  6634. HDRVLINE hdLine,
  6635. DWORD dwQueueID,
  6636. DWORD dwMeasurementPeriod
  6637. )
  6638. {
  6639. static REMOTE_ARG_TYPES argTypes[] =
  6640. {
  6641. Dword,
  6642. Hdline,
  6643. Dword,
  6644. Dword
  6645. };
  6646. ULONG_PTR args[] =
  6647. {
  6648. (ULONG_PTR) dwRequestID,
  6649. (ULONG_PTR) hdLine,
  6650. (ULONG_PTR) dwQueueID,
  6651. (ULONG_PTR) dwMeasurementPeriod
  6652. };
  6653. REMOTE_FUNC_ARGS funcArgs =
  6654. {
  6655. MAKELONG (LINE_FUNC | ASYNC | 4, lSetQueueMeasurementPeriod),
  6656. args,
  6657. argTypes
  6658. };
  6659. return (REMOTEDOFUNC (&funcArgs, "lineSetQueueMeasurementPeriod"));
  6660. }
  6661. LONG
  6662. TSPIAPI
  6663. TSPI_lineSetStatusMessages(
  6664. HDRVLINE hdLine,
  6665. DWORD dwLineStates,
  6666. DWORD dwAddressStates
  6667. )
  6668. {
  6669. static REMOTE_ARG_TYPES argTypes[] =
  6670. {
  6671. Hdline,
  6672. Dword,
  6673. Dword
  6674. };
  6675. ULONG_PTR args[] =
  6676. {
  6677. (ULONG_PTR) hdLine,
  6678. (ULONG_PTR) dwLineStates,
  6679. (ULONG_PTR) dwAddressStates
  6680. };
  6681. REMOTE_FUNC_ARGS funcArgs =
  6682. {
  6683. MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
  6684. args,
  6685. argTypes
  6686. };
  6687. return (REMOTEDOFUNC (&funcArgs, "lineSetStatusMessages"));
  6688. }
  6689. LONG
  6690. TSPIAPI
  6691. TSPI_lineSetTerminal(
  6692. DRV_REQUESTID dwRequestID,
  6693. HDRVLINE hdLine,
  6694. DWORD dwAddressID,
  6695. HDRVCALL hdCall,
  6696. DWORD dwSelect,
  6697. DWORD dwTerminalModes,
  6698. DWORD dwTerminalID,
  6699. DWORD bEnable
  6700. )
  6701. {
  6702. REMOTE_ARG_TYPES argTypes[] =
  6703. {
  6704. Dword,
  6705. (dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
  6706. Dword,
  6707. (dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
  6708. Dword,
  6709. Dword,
  6710. Dword,
  6711. Dword
  6712. };
  6713. ULONG_PTR args[] =
  6714. {
  6715. (ULONG_PTR) dwRequestID,
  6716. (ULONG_PTR) hdLine,
  6717. (ULONG_PTR) dwAddressID,
  6718. (ULONG_PTR) hdCall,
  6719. (ULONG_PTR) dwSelect,
  6720. (ULONG_PTR) dwTerminalModes,
  6721. (ULONG_PTR) dwTerminalID,
  6722. (ULONG_PTR) bEnable
  6723. };
  6724. REMOTE_FUNC_ARGS funcArgs =
  6725. {
  6726. MAKELONG (LINE_FUNC | ASYNC | 8, lSetTerminal),
  6727. args,
  6728. argTypes
  6729. };
  6730. return (REMOTEDOFUNC (&funcArgs, "lineSetTerminal"));
  6731. }
  6732. void
  6733. PASCAL
  6734. TSPI_lineSetupConference_PostProcess(
  6735. PASYNCEVENTMSG pMsg,
  6736. PASYNCREQUESTCONTEXT pContext
  6737. )
  6738. {
  6739. PDRVCALL pConfCall = (PDRVCALL) pContext->Params[0],
  6740. pConsultCall = (PDRVCALL) pContext->Params[1];
  6741. LOG((TL_INFO, "TSPI_lineSetupConference_PostProcess: enter"));
  6742. EnterCriticalSection (&gCallListCriticalSection);
  6743. if (!IsValidObject (pConfCall, DRVCALL_KEY) ||
  6744. pConfCall->dwOriginalRequestID != pContext->dwOriginalRequestID)
  6745. {
  6746. LOG((TL_ERROR,"TSPI_lineSetupConference_PostProcess: Bad pConfCall dwID"));
  6747. pMsg->Param2 = LINEERR_INVALLINEHANDLE;
  6748. }
  6749. else
  6750. {
  6751. if (!IsValidObject (pConsultCall, DRVCALL_KEY) ||
  6752. pConsultCall->dwOriginalRequestID != pContext->dwOriginalRequestID)
  6753. {
  6754. //
  6755. // If here then the was closed & the calls have
  6756. // already been destroyed
  6757. //
  6758. LOG((TL_ERROR,
  6759. "TSPI_lineSetupConference_PostProcess: Bad pConsultCall dwID"
  6760. ));
  6761. pMsg->Param2 = LINEERR_INVALLINEHANDLE;
  6762. }
  6763. else
  6764. {
  6765. LOG((TL_INFO,
  6766. "\t\tp1=x%x, p2=x%x, p3=x%x",
  6767. pMsg->Param1,
  6768. pMsg->Param2,
  6769. pMsg->Param3
  6770. ));
  6771. LOG((TL_INFO,
  6772. "\t\tp4=x%x, p5=x%x, p6=x%x",
  6773. pMsg->Param4,
  6774. *(&pMsg->Param4 + 1),
  6775. pConsultCall
  6776. ));
  6777. if (pMsg->Param2 == 0)
  6778. {
  6779. HCALL hConfCall = (HCALL) pMsg->Param3,
  6780. hConsultCall = (HCALL) *(&pMsg->Param4 + 1);
  6781. pConfCall->hCall = hConfCall;
  6782. pConsultCall->hCall = hConsultCall;
  6783. if (pMsg->TotalSize >= (sizeof (*pMsg) + 8 * sizeof (DWORD)))
  6784. {
  6785. pConfCall->dwAddressID = (DWORD) *(&pMsg->Param4 + 3);
  6786. pConfCall->dwCallID = (DWORD) *(&pMsg->Param4 + 4);
  6787. pConfCall->dwRelatedCallID = (DWORD) *(&pMsg->Param4 + 5);
  6788. pConsultCall->dwAddressID = (DWORD) *(&pMsg->Param4+6);
  6789. pConsultCall->dwCallID = (DWORD) *(&pMsg->Param4+7);
  6790. pConsultCall->dwRelatedCallID = (DWORD) *(&pMsg->Param4+8);
  6791. }
  6792. else
  6793. {
  6794. pConfCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  6795. pConfCall->pServer->bVer2xServer = TRUE;
  6796. pConsultCall->dwDirtyStructs |= STRUCTCHANGE_CALLIDS;
  6797. }
  6798. }
  6799. else
  6800. {
  6801. RemoveCallFromList (pConfCall);
  6802. RemoveCallFromList (pConsultCall);
  6803. }
  6804. }
  6805. }
  6806. LeaveCriticalSection (&gCallListCriticalSection);
  6807. }
  6808. LONG
  6809. TSPIAPI
  6810. TSPI_lineSetupConference(
  6811. DRV_REQUESTID dwRequestID,
  6812. HDRVCALL hdCall,
  6813. HDRVLINE hdLine,
  6814. HTAPICALL htConfCall,
  6815. LPHDRVCALL lphdConfCall,
  6816. HTAPICALL htConsultCall,
  6817. LPHDRVCALL lphdConsultCall,
  6818. DWORD dwNumParties,
  6819. LPLINECALLPARAMS const lpCallParams
  6820. )
  6821. {
  6822. REMOTE_ARG_TYPES argTypes[] =
  6823. {
  6824. Dword,
  6825. Dword,
  6826. (hdCall ? Hdcall : Dword),
  6827. (hdCall ? Dword : Hdline),
  6828. Dword,
  6829. Dword,
  6830. Dword,
  6831. lpSet_Struct,
  6832. Dword
  6833. };
  6834. PDRVCALL pConfCall = DrvAlloc (sizeof (DRVCALL)),
  6835. pConsultCall = DrvAlloc (sizeof (DRVCALL));
  6836. ULONG_PTR args[] =
  6837. {
  6838. (ULONG_PTR) dwRequestID,
  6839. (ULONG_PTR) 0,
  6840. (ULONG_PTR) hdCall,
  6841. (ULONG_PTR) hdLine,
  6842. (ULONG_PTR) pConfCall,
  6843. (ULONG_PTR) pConsultCall,
  6844. (ULONG_PTR) dwNumParties,
  6845. (ULONG_PTR) lpCallParams,
  6846. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  6847. };
  6848. REMOTE_FUNC_ARGS funcArgs =
  6849. {
  6850. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 9, lSetupConference),
  6851. args,
  6852. argTypes
  6853. };
  6854. LONG lResult;
  6855. if (pConfCall)
  6856. {
  6857. if (pConsultCall)
  6858. {
  6859. PDRVLINE pLine;
  6860. PASYNCREQUESTCONTEXT pContext;
  6861. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  6862. {
  6863. DrvFree (pConfCall);
  6864. DrvFree (pConsultCall);
  6865. return LINEERR_NOMEM;
  6866. }
  6867. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  6868. TSPI_lineSetupConference_PostProcess;
  6869. pContext->Params[0] = (ULONG_PTR) pConfCall;
  6870. pContext->Params[1] = (ULONG_PTR) pConsultCall;
  6871. args[1] = (ULONG_PTR) pContext;
  6872. argTypes[1] = lpContext;
  6873. pConfCall->htCall = htConfCall;
  6874. pConsultCall->htCall = htConsultCall;
  6875. pConfCall->dwOriginalRequestID = dwRequestID;
  6876. pConsultCall->dwOriginalRequestID = dwRequestID;
  6877. pConfCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  6878. pConsultCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  6879. if (hdCall)
  6880. {
  6881. EnterCriticalSection (&gCallListCriticalSection);
  6882. if (IsValidObject ((PVOID) hdCall, DRVCALL_KEY))
  6883. {
  6884. pLine = ((PDRVCALL) hdCall)->pLine;
  6885. }
  6886. else
  6887. {
  6888. LeaveCriticalSection (&gCallListCriticalSection);
  6889. DrvFree (pConfCall);
  6890. DrvFree (pConsultCall);
  6891. return LINEERR_INVALCALLHANDLE;
  6892. }
  6893. LeaveCriticalSection (&gCallListCriticalSection);
  6894. }
  6895. else
  6896. {
  6897. pLine = (PDRVLINE) hdLine;
  6898. }
  6899. AddCallToList (pLine, pConfCall);
  6900. AddCallToList (pLine, pConsultCall);
  6901. *lphdConfCall = (HDRVCALL) pConfCall;
  6902. *lphdConsultCall = (HDRVCALL) pConsultCall;
  6903. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupConference"))
  6904. < 0)
  6905. {
  6906. RemoveCallFromList (pConfCall);
  6907. RemoveCallFromList (pConsultCall);
  6908. }
  6909. }
  6910. else
  6911. {
  6912. DrvFree (pConfCall);
  6913. lResult = LINEERR_NOMEM;
  6914. }
  6915. }
  6916. else
  6917. {
  6918. lResult = LINEERR_NOMEM;
  6919. }
  6920. return lResult;
  6921. }
  6922. LONG
  6923. TSPIAPI
  6924. TSPI_lineSetupTransfer(
  6925. DRV_REQUESTID dwRequestID,
  6926. HDRVCALL hdCall,
  6927. HTAPICALL htConsultCall,
  6928. LPHDRVCALL lphdConsultCall,
  6929. LPLINECALLPARAMS const lpCallParams
  6930. )
  6931. {
  6932. REMOTE_ARG_TYPES argTypes[] =
  6933. {
  6934. Dword,
  6935. Dword,
  6936. Hdcall,
  6937. Dword,
  6938. lpSet_Struct,
  6939. Dword
  6940. };
  6941. PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
  6942. ULONG_PTR args[] =
  6943. {
  6944. (ULONG_PTR) dwRequestID,
  6945. (ULONG_PTR) 0,
  6946. (ULONG_PTR) hdCall,
  6947. (ULONG_PTR) 0,
  6948. (ULONG_PTR) lpCallParams,
  6949. (ULONG_PTR) 0xffffffff, // dwAsciiCallParamsCodePage
  6950. };
  6951. REMOTE_FUNC_ARGS funcArgs =
  6952. {
  6953. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lSetupTransfer),
  6954. args,
  6955. argTypes
  6956. };
  6957. LONG lResult;
  6958. if (pConsultCall)
  6959. {
  6960. PASYNCREQUESTCONTEXT pContext;
  6961. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  6962. {
  6963. DrvFree (pConsultCall);
  6964. return LINEERR_NOMEM;
  6965. }
  6966. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  6967. TSPI_lineMakeCall_PostProcess;
  6968. pContext->Params[0] = (ULONG_PTR) pConsultCall;
  6969. args[1] = (ULONG_PTR) pContext;
  6970. argTypes[1] = lpContext;
  6971. pConsultCall->dwOriginalRequestID = dwRequestID;
  6972. pConsultCall->htCall = htConsultCall;
  6973. pConsultCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  6974. AddCallToList (((PDRVCALL) hdCall)->pLine, pConsultCall);
  6975. *lphdConsultCall = (HDRVCALL) pConsultCall;
  6976. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupTransfer")) < 0)
  6977. {
  6978. RemoveCallFromList (pConsultCall);
  6979. }
  6980. }
  6981. else
  6982. {
  6983. lResult = LINEERR_NOMEM;
  6984. }
  6985. return lResult;
  6986. }
  6987. LONG
  6988. TSPIAPI
  6989. TSPI_lineSwapHold(
  6990. DRV_REQUESTID dwRequestID,
  6991. HDRVCALL hdActiveCall,
  6992. HDRVCALL hdHeldCall
  6993. )
  6994. {
  6995. static REMOTE_ARG_TYPES argTypes[] =
  6996. {
  6997. Dword,
  6998. Hdcall,
  6999. Hdcall
  7000. };
  7001. ULONG_PTR args[] =
  7002. {
  7003. (ULONG_PTR) dwRequestID,
  7004. (ULONG_PTR) hdActiveCall,
  7005. (ULONG_PTR) hdHeldCall
  7006. };
  7007. REMOTE_FUNC_ARGS funcArgs =
  7008. {
  7009. MAKELONG (LINE_FUNC | ASYNC | 3, lSwapHold),
  7010. args,
  7011. argTypes
  7012. };
  7013. return (REMOTEDOFUNC (&funcArgs, "lineSwapHold"));
  7014. }
  7015. LONG
  7016. TSPIAPI
  7017. TSPI_lineUncompleteCall(
  7018. DRV_REQUESTID dwRequestID,
  7019. HDRVLINE hdLine,
  7020. DWORD dwCompletionID
  7021. )
  7022. {
  7023. static REMOTE_ARG_TYPES argTypes[] =
  7024. {
  7025. Dword,
  7026. Hdline,
  7027. Dword
  7028. };
  7029. ULONG_PTR args[] =
  7030. {
  7031. (ULONG_PTR) dwRequestID,
  7032. (ULONG_PTR) hdLine,
  7033. (ULONG_PTR) dwCompletionID
  7034. };
  7035. REMOTE_FUNC_ARGS funcArgs =
  7036. {
  7037. MAKELONG (LINE_FUNC | ASYNC | 3, lUncompleteCall),
  7038. args,
  7039. argTypes
  7040. };
  7041. return (REMOTEDOFUNC (&funcArgs, "lineUncompleteCall"));
  7042. }
  7043. LONG
  7044. TSPIAPI
  7045. TSPI_lineUnhold(
  7046. DRV_REQUESTID dwRequestID,
  7047. HDRVCALL hdCall
  7048. )
  7049. {
  7050. static REMOTE_ARG_TYPES argTypes[] =
  7051. {
  7052. Dword,
  7053. Hdcall
  7054. };
  7055. ULONG_PTR args[] =
  7056. {
  7057. (ULONG_PTR) dwRequestID,
  7058. (ULONG_PTR) hdCall
  7059. };
  7060. REMOTE_FUNC_ARGS funcArgs =
  7061. {
  7062. MAKELONG (LINE_FUNC | ASYNC | 2, lUnhold),
  7063. args,
  7064. argTypes
  7065. };
  7066. return (REMOTEDOFUNC (&funcArgs, "lineUnhold"));
  7067. }
  7068. LONG
  7069. TSPIAPI
  7070. TSPI_lineUnpark(
  7071. DRV_REQUESTID dwRequestID,
  7072. HDRVLINE hdLine,
  7073. DWORD dwAddressID,
  7074. HTAPICALL htCall,
  7075. LPHDRVCALL lphdCall,
  7076. LPCWSTR lpszDestAddress
  7077. )
  7078. {
  7079. REMOTE_ARG_TYPES argTypes[] =
  7080. {
  7081. Dword,
  7082. Dword,
  7083. Hdline,
  7084. Dword,
  7085. Dword,
  7086. lpsz
  7087. };
  7088. PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
  7089. ULONG_PTR args[] =
  7090. {
  7091. (ULONG_PTR) dwRequestID,
  7092. (ULONG_PTR) 0,
  7093. (ULONG_PTR) hdLine,
  7094. (ULONG_PTR) dwAddressID,
  7095. (ULONG_PTR) 0,
  7096. (ULONG_PTR) lpszDestAddress
  7097. };
  7098. REMOTE_FUNC_ARGS funcArgs =
  7099. {
  7100. MAKELONG (LINE_FUNC | ASYNC | INCL_CONTEXT | 6, lUnpark),
  7101. args,
  7102. argTypes
  7103. };
  7104. LONG lResult;
  7105. if (pCall)
  7106. {
  7107. PASYNCREQUESTCONTEXT pContext;
  7108. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  7109. {
  7110. DrvFree (pCall);
  7111. return LINEERR_NOMEM;
  7112. }
  7113. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  7114. TSPI_lineMakeCall_PostProcess;
  7115. pContext->Params[0] = (ULONG_PTR) pCall;
  7116. args[1] = (ULONG_PTR) pContext;
  7117. argTypes[1] = lpContext;
  7118. pCall->dwOriginalRequestID = dwRequestID;
  7119. pCall->htCall = htCall;
  7120. pCall->dwInitialPrivilege = LINECALLPRIVILEGE_OWNER;
  7121. AddCallToList ((PDRVLINE) hdLine, pCall);
  7122. *lphdCall = (HDRVCALL) pCall;
  7123. if ((lResult = REMOTEDOFUNC (&funcArgs, "lineUnpark")) < 0)
  7124. {
  7125. RemoveCallFromList (pCall);
  7126. }
  7127. }
  7128. else
  7129. {
  7130. lResult = LINEERR_NOMEM;
  7131. }
  7132. return lResult;
  7133. }
  7134. //
  7135. // -------------------------- TSPI_phoneXxx funcs -----------------------------
  7136. //
  7137. LONG
  7138. TSPIAPI
  7139. TSPI_phoneClose(
  7140. HDRVPHONE hdPhone
  7141. )
  7142. {
  7143. //
  7144. // Check if the hPhone is still valid (could have been zeroed
  7145. // out on PHONE_CLOSE, so no need to call server)
  7146. //
  7147. if (((PDRVPHONE) hdPhone)->hPhone)
  7148. {
  7149. static REMOTE_ARG_TYPES argTypes[] =
  7150. {
  7151. Hdphone
  7152. };
  7153. REMOTE_FUNC_ARGS funcArgs =
  7154. {
  7155. MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
  7156. (ULONG_PTR *) &hdPhone,
  7157. argTypes
  7158. };
  7159. DereferenceObject(
  7160. ghHandleTable,
  7161. ((PDRVPHONE) hdPhone)->hDeviceCallback,
  7162. 1
  7163. );
  7164. EnterCriticalSection (&gCallListCriticalSection);
  7165. ((PDRVPHONE) hdPhone)->htPhone = 0;
  7166. ((PDRVPHONE) hdPhone)->hDeviceCallback = 0;
  7167. LeaveCriticalSection (&gCallListCriticalSection);
  7168. REMOTEDOFUNC (&funcArgs, "phoneClose");
  7169. }
  7170. return 0;
  7171. }
  7172. LONG
  7173. TSPIAPI
  7174. TSPI_phoneDevSpecific(
  7175. DRV_REQUESTID dwRequestID,
  7176. HDRVPHONE hdPhone,
  7177. LPVOID lpParams,
  7178. DWORD dwSize
  7179. )
  7180. {
  7181. static REMOTE_ARG_TYPES argTypes[] =
  7182. {
  7183. Dword,
  7184. Dword,
  7185. Hdphone,
  7186. Dword,
  7187. lpSet_SizeToFollow,
  7188. Size
  7189. };
  7190. ULONG_PTR args[] =
  7191. {
  7192. (ULONG_PTR) dwRequestID,
  7193. (ULONG_PTR) 0,
  7194. (ULONG_PTR) hdPhone,
  7195. (ULONG_PTR) 0,
  7196. (ULONG_PTR) lpParams, // pass data
  7197. (ULONG_PTR) dwSize
  7198. };
  7199. REMOTE_FUNC_ARGS funcArgs =
  7200. {
  7201. MAKELONG (PHONE_FUNC | ASYNC | INCL_CONTEXT | 6, pDevSpecific),
  7202. args,
  7203. argTypes
  7204. };
  7205. PASYNCREQUESTCONTEXT pContext;
  7206. if (!(pContext = DrvAlloc (sizeof (*pContext))))
  7207. {
  7208. return PHONEERR_NOMEM;
  7209. }
  7210. pContext->pfnPostProcessProc = (RSPPOSTPROCESSPROC)
  7211. TSPI_lineDevSpecific_PostProcess;
  7212. pContext->Params[0] = (ULONG_PTR) lpParams;
  7213. pContext->Params[1] = dwSize;
  7214. args[1] = (ULONG_PTR) pContext;
  7215. argTypes[1] = lpContext;
  7216. return (REMOTEDOFUNC (&funcArgs, "phoneDevSpecific"));
  7217. }
  7218. LONG
  7219. TSPIAPI
  7220. TSPI_phoneGetButtonInfo(
  7221. HDRVPHONE hdPhone,
  7222. DWORD dwButtonLampID,
  7223. LPPHONEBUTTONINFO lpButtonInfo
  7224. )
  7225. {
  7226. static REMOTE_ARG_TYPES argTypes[] =
  7227. {
  7228. Hdphone,
  7229. Dword,
  7230. lpGet_Struct
  7231. };
  7232. ULONG_PTR args[] =
  7233. {
  7234. (ULONG_PTR) hdPhone,
  7235. (ULONG_PTR) dwButtonLampID,
  7236. (ULONG_PTR) lpButtonInfo
  7237. };
  7238. REMOTE_FUNC_ARGS funcArgs =
  7239. {
  7240. MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
  7241. args,
  7242. argTypes
  7243. };
  7244. return (REMOTEDOFUNC (&funcArgs, "phoneGetButtonInfo"));
  7245. }
  7246. LONG
  7247. TSPIAPI
  7248. TSPI_phoneGetData(
  7249. HDRVPHONE hdPhone,
  7250. DWORD dwDataID,
  7251. LPVOID lpData,
  7252. DWORD dwSize
  7253. )
  7254. {
  7255. static REMOTE_ARG_TYPES argTypes[] =
  7256. {
  7257. Hdphone,
  7258. Dword,
  7259. lpGet_SizeToFollow,
  7260. Size
  7261. };
  7262. ULONG_PTR args[] =
  7263. {
  7264. (ULONG_PTR) hdPhone,
  7265. (ULONG_PTR) dwDataID,
  7266. (ULONG_PTR) lpData,
  7267. (ULONG_PTR) dwSize
  7268. };
  7269. REMOTE_FUNC_ARGS funcArgs =
  7270. {
  7271. MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
  7272. args,
  7273. argTypes
  7274. };
  7275. return (REMOTEDOFUNC (&funcArgs, "phoneGetData"));
  7276. }
  7277. LONG
  7278. TSPIAPI
  7279. TSPI_phoneGetDevCaps(
  7280. DWORD dwDeviceID,
  7281. DWORD dwTSPIVersion,
  7282. DWORD dwExtVersion,
  7283. LPPHONECAPS lpPhoneCaps
  7284. )
  7285. {
  7286. LONG lResult;
  7287. static REMOTE_ARG_TYPES argTypes[] =
  7288. {
  7289. Dword,
  7290. PhoneID,
  7291. Dword,
  7292. Dword,
  7293. lpGet_Struct
  7294. };
  7295. ULONG_PTR args[] =
  7296. {
  7297. (ULONG_PTR) 0,
  7298. (ULONG_PTR) dwDeviceID,
  7299. (ULONG_PTR) dwTSPIVersion,
  7300. (ULONG_PTR) dwExtVersion,
  7301. (ULONG_PTR) lpPhoneCaps
  7302. };
  7303. REMOTE_FUNC_ARGS funcArgs =
  7304. {
  7305. MAKELONG (LINE_FUNC | SYNC | 5, pGetDevCaps),
  7306. args,
  7307. argTypes
  7308. };
  7309. PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
  7310. if (NULL == pPhone)
  7311. {
  7312. return PHONEERR_BADDEVICEID;
  7313. }
  7314. args[0] = pPhone->pServer->hPhoneApp;
  7315. lResult = REMOTEDOFUNC (&funcArgs, "phoneGetDevCaps");
  7316. //
  7317. // We were munging the PermID in the original release of tapi 2.1.
  7318. // The intent was to make sure that we didn't present apps with
  7319. // overlapping id's (both local & remote), but none of our other service
  7320. // providers (i.e. unimdm, kmddsp) use the HIWORD(providerID) /
  7321. // LOWORD(devID) model, so it really doesn't do any good.
  7322. //
  7323. // if (lResult == 0)
  7324. // {
  7325. // lpPhoneCaps->dwPermanentPhoneID = MAKELONG(
  7326. // LOWORD(lpPhoneCaps->dwPermanentPhoneID),
  7327. // gdwPermanentProviderID
  7328. // );
  7329. // }
  7330. //
  7331. return lResult;
  7332. }
  7333. LONG
  7334. TSPIAPI
  7335. TSPI_phoneGetDisplay(
  7336. HDRVPHONE hdPhone,
  7337. LPVARSTRING lpDisplay
  7338. )
  7339. {
  7340. static REMOTE_ARG_TYPES argTypes[] =
  7341. {
  7342. Hdphone,
  7343. lpGet_Struct
  7344. };
  7345. ULONG_PTR args[] =
  7346. {
  7347. (ULONG_PTR) hdPhone,
  7348. (ULONG_PTR) lpDisplay
  7349. };
  7350. REMOTE_FUNC_ARGS funcArgs =
  7351. {
  7352. MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
  7353. args,
  7354. argTypes
  7355. };
  7356. return (REMOTEDOFUNC (&funcArgs, "phoneGetDisplay"));
  7357. }
  7358. LONG
  7359. TSPIAPI
  7360. TSPI_phoneGetExtensionID(
  7361. DWORD dwDeviceID,
  7362. DWORD dwTSPIVersion,
  7363. LPPHONEEXTENSIONID lpExtensionID
  7364. )
  7365. {
  7366. PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
  7367. if (NULL == pPhone)
  7368. {
  7369. return PHONEERR_BADDEVICEID;
  7370. }
  7371. CopyMemory(
  7372. lpExtensionID,
  7373. &pPhone->ExtensionID,
  7374. sizeof (PHONEEXTENSIONID)
  7375. );
  7376. return 0;
  7377. }
  7378. LONG
  7379. TSPIAPI
  7380. TSPI_phoneGetGain(
  7381. HDRVPHONE hdPhone,
  7382. DWORD dwHookSwitchDev,
  7383. LPDWORD lpdwGain
  7384. )
  7385. {
  7386. static REMOTE_ARG_TYPES argTypes[] =
  7387. {
  7388. Hdphone,
  7389. Dword,
  7390. lpDword
  7391. };
  7392. ULONG_PTR args[] =
  7393. {
  7394. (ULONG_PTR) hdPhone,
  7395. (ULONG_PTR) dwHookSwitchDev,
  7396. (ULONG_PTR) lpdwGain
  7397. };
  7398. REMOTE_FUNC_ARGS funcArgs =
  7399. {
  7400. MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
  7401. args,
  7402. argTypes
  7403. };
  7404. return (REMOTEDOFUNC (&funcArgs, "phoneGetGain"));
  7405. }
  7406. LONG
  7407. TSPIAPI
  7408. TSPI_phoneGetHookSwitch(
  7409. HDRVPHONE hdPhone,
  7410. LPDWORD lpdwHookSwitchDevs
  7411. )
  7412. {
  7413. static REMOTE_ARG_TYPES argTypes[] =
  7414. {
  7415. Hdphone,
  7416. lpDword
  7417. };
  7418. ULONG_PTR args[] =
  7419. {
  7420. (ULONG_PTR) hdPhone,
  7421. (ULONG_PTR) lpdwHookSwitchDevs
  7422. };
  7423. REMOTE_FUNC_ARGS funcArgs =
  7424. {
  7425. MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
  7426. args,
  7427. argTypes
  7428. };
  7429. return (REMOTEDOFUNC (&funcArgs, "phoneGetHookSwitch"));
  7430. }
  7431. LONG
  7432. TSPIAPI
  7433. TSPI_phoneGetIcon(
  7434. DWORD dwDeviceID,
  7435. LPCWSTR lpszDeviceClass,
  7436. LPHICON lphIcon
  7437. )
  7438. {
  7439. *lphIcon = ghPhoneIcon;
  7440. return 0;
  7441. }
  7442. LONG
  7443. TSPIAPI
  7444. TSPI_phoneGetID(
  7445. HDRVPHONE hdPhone,
  7446. LPVARSTRING lpDeviceID,
  7447. LPCWSTR lpszDeviceClass,
  7448. HANDLE hTargetProcess
  7449. )
  7450. {
  7451. //
  7452. // NOTE: Tapisrv will handle the "tapi/phone" class
  7453. //
  7454. LONG lResult;
  7455. static REMOTE_ARG_TYPES argTypes[] =
  7456. {
  7457. Hdphone,
  7458. lpGet_Struct,
  7459. lpsz
  7460. };
  7461. ULONG_PTR args[] =
  7462. {
  7463. (ULONG_PTR) hdPhone,
  7464. (ULONG_PTR) lpDeviceID,
  7465. (ULONG_PTR) lpszDeviceClass
  7466. };
  7467. REMOTE_FUNC_ARGS funcArgs =
  7468. {
  7469. MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
  7470. args,
  7471. argTypes
  7472. };
  7473. //
  7474. // The device ID for wave devices is meaningless on remote machines.
  7475. // Return op. unavailable
  7476. //
  7477. if (lpszDeviceClass &&
  7478. ( !_wcsicmp(lpszDeviceClass, L"wave/in") ||
  7479. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  7480. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  7481. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  7482. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  7483. )
  7484. )
  7485. {
  7486. return PHONEERR_OPERATIONUNAVAIL;
  7487. }
  7488. lResult = REMOTEDOFUNC (&funcArgs, "phoneGetID");
  7489. //
  7490. // If success && dev class == "tapi/line" && there was
  7491. // enough room in the device ID struct for a returned ID,
  7492. // then we need to map the 0-based server ID back to it's
  7493. // corresponding local ID.
  7494. //
  7495. if (lResult == 0 &&
  7496. lstrcmpiW (lpszDeviceClass, L"tapi/line") == 0 &&
  7497. lpDeviceID->dwUsedSize >= (sizeof (*lpDeviceID) + sizeof (DWORD)))
  7498. {
  7499. LPDWORD pdwLineID = (LPDWORD) (((LPBYTE) lpDeviceID) +
  7500. lpDeviceID->dwStringOffset);
  7501. PDRVLINE pLine;
  7502. PDRVSERVER pServer = ((PDRVPHONE) hdPhone)->pServer;
  7503. if ((pLine = GetLineFromID (gdwLineDeviceIDBase + *pdwLineID)))
  7504. {
  7505. if (pLine->pServer == pServer &&
  7506. pLine->dwDeviceIDServer == *pdwLineID)
  7507. {
  7508. //
  7509. // The easy case - a direct mapping between the ID
  7510. // returned from the server & the index into the
  7511. // lookup table
  7512. //
  7513. *pdwLineID = pLine->dwDeviceIDLocal;
  7514. }
  7515. else
  7516. {
  7517. //
  7518. // The hard case - have to walk the lookup table(s)
  7519. // looking for the matching device.
  7520. //
  7521. // We'll take the simplest, though slowest, route
  7522. // and start at the first entry of the first table.
  7523. // The good news is that there generally won't be
  7524. // many devices, and this request won't occur often.
  7525. //
  7526. DWORD i;
  7527. PDRVLINELOOKUP pLookup;
  7528. TapiEnterCriticalSection(&gCriticalSection);
  7529. pLookup = gpLineLookup;
  7530. while (pLookup)
  7531. {
  7532. for (i = 0; i < pLookup->dwUsedEntries; i++)
  7533. {
  7534. if (pLookup->aEntries[i].dwDeviceIDServer ==
  7535. *pdwLineID &&
  7536. pLookup->aEntries[i].pServer == pServer)
  7537. {
  7538. *pdwLineID = pLookup->aEntries[i].dwDeviceIDLocal;
  7539. TapiLeaveCriticalSection(&gCriticalSection);
  7540. goto TSPI_phoneGetID_return;
  7541. }
  7542. }
  7543. pLookup = pLookup->pNext;
  7544. }
  7545. TapiLeaveCriticalSection(&gCriticalSection);
  7546. //
  7547. // If here no matching local ID, so fail the request
  7548. //
  7549. lResult = PHONEERR_OPERATIONFAILED;
  7550. }
  7551. }
  7552. else
  7553. {
  7554. lResult = PHONEERR_OPERATIONFAILED;
  7555. }
  7556. }
  7557. TSPI_phoneGetID_return:
  7558. return lResult;
  7559. }
  7560. LONG
  7561. TSPIAPI
  7562. TSPI_phoneGetLamp(
  7563. HDRVPHONE hdPhone,
  7564. DWORD dwButtonLampID,
  7565. LPDWORD lpdwLampMode
  7566. )
  7567. {
  7568. static REMOTE_ARG_TYPES argTypes[] =
  7569. {
  7570. Hdphone,
  7571. Dword,
  7572. lpDword
  7573. };
  7574. ULONG_PTR args[] =
  7575. {
  7576. (ULONG_PTR) hdPhone,
  7577. (ULONG_PTR) dwButtonLampID,
  7578. (ULONG_PTR) lpdwLampMode
  7579. };
  7580. REMOTE_FUNC_ARGS funcArgs =
  7581. {
  7582. MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
  7583. args,
  7584. argTypes
  7585. };
  7586. return (REMOTEDOFUNC (&funcArgs, "phoneGetLamp"));
  7587. }
  7588. LONG
  7589. TSPIAPI
  7590. TSPI_phoneGetRing(
  7591. HDRVPHONE hdPhone,
  7592. LPDWORD lpdwRingMode,
  7593. LPDWORD lpdwVolume
  7594. )
  7595. {
  7596. static REMOTE_ARG_TYPES argTypes[] =
  7597. {
  7598. Hdphone,
  7599. lpDword,
  7600. lpDword
  7601. };
  7602. ULONG_PTR args[] =
  7603. {
  7604. (ULONG_PTR) hdPhone,
  7605. (ULONG_PTR) lpdwRingMode,
  7606. (ULONG_PTR) lpdwVolume
  7607. };
  7608. REMOTE_FUNC_ARGS funcArgs =
  7609. {
  7610. MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
  7611. args,
  7612. argTypes
  7613. };
  7614. return (REMOTEDOFUNC (&funcArgs, "phoneGetRing"));
  7615. }
  7616. LONG
  7617. TSPIAPI
  7618. TSPI_phoneGetStatus(
  7619. HDRVPHONE hdPhone,
  7620. LPPHONESTATUS lpPhoneStatus
  7621. )
  7622. {
  7623. static REMOTE_ARG_TYPES argTypes[] =
  7624. {
  7625. Hdphone,
  7626. lpGet_Struct
  7627. };
  7628. ULONG_PTR args[] =
  7629. {
  7630. (ULONG_PTR) hdPhone,
  7631. (ULONG_PTR) lpPhoneStatus
  7632. };
  7633. REMOTE_FUNC_ARGS funcArgs =
  7634. {
  7635. MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
  7636. args,
  7637. argTypes
  7638. };
  7639. return (REMOTEDOFUNC (&funcArgs, "phoneGetStatus"));
  7640. }
  7641. LONG
  7642. TSPIAPI
  7643. TSPI_phoneGetVolume(
  7644. HDRVPHONE hdPhone,
  7645. DWORD dwHookSwitchDev,
  7646. LPDWORD lpdwVolume
  7647. )
  7648. {
  7649. static REMOTE_ARG_TYPES argTypes[] =
  7650. {
  7651. Hdphone,
  7652. Dword,
  7653. lpDword
  7654. };
  7655. ULONG_PTR args[] =
  7656. {
  7657. (ULONG_PTR) hdPhone,
  7658. (ULONG_PTR) dwHookSwitchDev,
  7659. (ULONG_PTR) lpdwVolume
  7660. };
  7661. REMOTE_FUNC_ARGS funcArgs =
  7662. {
  7663. MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
  7664. args,
  7665. argTypes
  7666. };
  7667. return (REMOTEDOFUNC (&funcArgs, "phoneGetVolume"));
  7668. }
  7669. LONG
  7670. TSPIAPI
  7671. TSPI_phoneNegotiateExtVersion(
  7672. DWORD dwDeviceID,
  7673. DWORD dwTSPIVersion,
  7674. DWORD dwLowVersion,
  7675. DWORD dwHighVersion,
  7676. LPDWORD lpdwExtVersion
  7677. )
  7678. {
  7679. static REMOTE_ARG_TYPES argTypes[] =
  7680. {
  7681. Dword,
  7682. PhoneID,
  7683. Dword,
  7684. Dword,
  7685. Dword,
  7686. lpDword
  7687. };
  7688. ULONG_PTR args[] =
  7689. {
  7690. (ULONG_PTR) 0,
  7691. (ULONG_PTR) dwDeviceID,
  7692. (ULONG_PTR) dwTSPIVersion,
  7693. (ULONG_PTR) dwLowVersion,
  7694. (ULONG_PTR) dwHighVersion,
  7695. (ULONG_PTR) lpdwExtVersion,
  7696. };
  7697. REMOTE_FUNC_ARGS funcArgs =
  7698. {
  7699. MAKELONG (LINE_FUNC | SYNC | 6, pNegotiateExtVersion),
  7700. args,
  7701. argTypes
  7702. };
  7703. PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
  7704. if (NULL == pPhone)
  7705. {
  7706. return PHONEERR_BADDEVICEID;
  7707. }
  7708. args[0] = pPhone->pServer->hPhoneApp;
  7709. return (REMOTEDOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
  7710. }
  7711. LONG
  7712. TSPIAPI
  7713. TSPI_phoneNegotiateTSPIVersion(
  7714. DWORD dwDeviceID,
  7715. DWORD dwLowVersion,
  7716. DWORD dwHighVersion,
  7717. LPDWORD lpdwTSPIVersion
  7718. )
  7719. {
  7720. LONG lRet = 0;
  7721. if (dwDeviceID == INITIALIZE_NEGOTIATION)
  7722. {
  7723. *lpdwTSPIVersion = TAPI_VERSION_CURRENT;
  7724. }
  7725. else
  7726. {
  7727. try
  7728. {
  7729. *lpdwTSPIVersion = (GetPhoneFromID (dwDeviceID))->dwXPIVersion;
  7730. }
  7731. except (EXCEPTION_EXECUTE_HANDLER)
  7732. {
  7733. lRet = PHONEERR_OPERATIONFAILED;
  7734. }
  7735. }
  7736. return lRet;
  7737. }
  7738. LONG
  7739. TSPIAPI
  7740. TSPI_phoneOpen(
  7741. DWORD dwDeviceID,
  7742. HTAPIPHONE pParams, // Hack Alert! See below
  7743. LPHDRVPHONE lphdPhone,
  7744. DWORD dwTSPIVersion,
  7745. PHONEEVENT lpfnEventProc
  7746. )
  7747. {
  7748. //
  7749. // Hack Alert!
  7750. //
  7751. // Tapisrv does a special case for remotesp and phone open
  7752. // to pass in the ext version - htPhone is really pParams,
  7753. // pointing at a ULONG_PTR array containing the htPhone &
  7754. // ext version
  7755. //
  7756. static REMOTE_ARG_TYPES argTypes[] =
  7757. {
  7758. Dword, // hPhoneApp
  7759. PhoneID, // dev id
  7760. lpDword, // lphPhone
  7761. Dword, // API version
  7762. Dword, // ext version
  7763. Dword, // callback inst
  7764. Dword, // privilege
  7765. Dword // remote hPhone
  7766. };
  7767. PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
  7768. ULONG_PTR args[] =
  7769. {
  7770. (ULONG_PTR) 0,
  7771. (ULONG_PTR) dwDeviceID,
  7772. (ULONG_PTR) 0,
  7773. (ULONG_PTR) dwTSPIVersion,
  7774. (ULONG_PTR) ((ULONG_PTR *) pParams)[1], // ext version
  7775. (ULONG_PTR) 0,
  7776. (ULONG_PTR) PHONEPRIVILEGE_OWNER,
  7777. (ULONG_PTR) pPhone
  7778. };
  7779. REMOTE_FUNC_ARGS funcArgs =
  7780. {
  7781. MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
  7782. args,
  7783. argTypes
  7784. };
  7785. LONG lResult;
  7786. if (NULL == pPhone)
  7787. {
  7788. return PHONEERR_BADDEVICEID;
  7789. }
  7790. args[0] = pPhone->pServer->hPhoneApp;
  7791. args[2] = (ULONG_PTR)&pPhone->hPhone;
  7792. if (!(args[7] = NewObject (ghHandleTable, pPhone, (LPVOID) 1)))
  7793. {
  7794. return PHONEERR_NOMEM;
  7795. }
  7796. pPhone->hDeviceCallback = (DWORD) args[7];
  7797. pPhone->dwKey = DRVPHONE_KEY;
  7798. pPhone->htPhone = (HTAPIPHONE) ((ULONG_PTR *) pParams)[0];
  7799. *lphdPhone = (HDRVPHONE) pPhone;
  7800. lResult = REMOTEDOFUNC (&funcArgs, "phoneOpen");
  7801. if (lResult != 0)
  7802. {
  7803. DereferenceObject (ghHandleTable, pPhone->hDeviceCallback, 1);
  7804. }
  7805. return lResult;
  7806. }
  7807. LONG
  7808. TSPIAPI
  7809. TSPI_phoneSelectExtVersion(
  7810. HDRVPHONE hdPhone,
  7811. DWORD dwExtVersion
  7812. )
  7813. {
  7814. static REMOTE_ARG_TYPES argTypes[] =
  7815. {
  7816. Hdphone,
  7817. Dword
  7818. };
  7819. ULONG_PTR args[] =
  7820. {
  7821. (ULONG_PTR) hdPhone,
  7822. (ULONG_PTR) dwExtVersion
  7823. };
  7824. REMOTE_FUNC_ARGS funcArgs =
  7825. {
  7826. MAKELONG (PHONE_FUNC | SYNC | 2, pSelectExtVersion),
  7827. args,
  7828. argTypes
  7829. };
  7830. return (REMOTEDOFUNC (&funcArgs, "phoneSelectExtVersion"));
  7831. }
  7832. LONG
  7833. TSPIAPI
  7834. TSPI_phoneSetButtonInfo(
  7835. DRV_REQUESTID dwRequestID,
  7836. HDRVPHONE hdPhone,
  7837. DWORD dwButtonLampID,
  7838. LPPHONEBUTTONINFO const lpButtonInfo
  7839. )
  7840. {
  7841. static REMOTE_ARG_TYPES argTypes[] =
  7842. {
  7843. Dword,
  7844. Hdphone,
  7845. Dword,
  7846. lpSet_Struct
  7847. };
  7848. ULONG_PTR args[] =
  7849. {
  7850. (ULONG_PTR) dwRequestID,
  7851. (ULONG_PTR) hdPhone,
  7852. (ULONG_PTR) dwButtonLampID,
  7853. (ULONG_PTR) lpButtonInfo
  7854. };
  7855. REMOTE_FUNC_ARGS funcArgs =
  7856. {
  7857. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetButtonInfo),
  7858. args,
  7859. argTypes
  7860. };
  7861. return (REMOTEDOFUNC (&funcArgs, "phoneSetButtonInfo"));
  7862. }
  7863. LONG
  7864. TSPIAPI
  7865. TSPI_phoneSetData(
  7866. DRV_REQUESTID dwRequestID,
  7867. HDRVPHONE hdPhone,
  7868. DWORD dwDataID,
  7869. LPVOID const lpData,
  7870. DWORD dwSize
  7871. )
  7872. {
  7873. static REMOTE_ARG_TYPES argTypes[] =
  7874. {
  7875. Dword,
  7876. Hdphone,
  7877. Dword,
  7878. lpSet_SizeToFollow,
  7879. Size
  7880. };
  7881. ULONG_PTR args[] =
  7882. {
  7883. (ULONG_PTR) dwRequestID,
  7884. (ULONG_PTR) hdPhone,
  7885. (ULONG_PTR) dwDataID,
  7886. (ULONG_PTR) lpData,
  7887. (ULONG_PTR) dwSize
  7888. };
  7889. REMOTE_FUNC_ARGS funcArgs =
  7890. {
  7891. MAKELONG (PHONE_FUNC | ASYNC | 5, pSetData),
  7892. args,
  7893. argTypes
  7894. };
  7895. return (REMOTEDOFUNC (&funcArgs, "phoneSetData"));
  7896. }
  7897. LONG
  7898. TSPIAPI
  7899. TSPI_phoneSetDisplay(
  7900. DRV_REQUESTID dwRequestID,
  7901. HDRVPHONE hdPhone,
  7902. DWORD dwRow,
  7903. DWORD dwColumn,
  7904. LPCWSTR lpsDisplay,
  7905. DWORD dwSize
  7906. )
  7907. {
  7908. static REMOTE_ARG_TYPES argTypes[] =
  7909. {
  7910. Dword,
  7911. Hdphone,
  7912. Dword,
  7913. Dword,
  7914. lpSet_SizeToFollow,
  7915. Size
  7916. };
  7917. ULONG_PTR args[] =
  7918. {
  7919. (ULONG_PTR) dwRequestID,
  7920. (ULONG_PTR) hdPhone,
  7921. (ULONG_PTR) dwRow,
  7922. (ULONG_PTR) dwColumn,
  7923. (ULONG_PTR) lpsDisplay,
  7924. (ULONG_PTR) dwSize
  7925. };
  7926. REMOTE_FUNC_ARGS funcArgs =
  7927. {
  7928. MAKELONG (PHONE_FUNC | ASYNC | 6, pSetDisplay),
  7929. args,
  7930. argTypes
  7931. };
  7932. return (REMOTEDOFUNC (&funcArgs, "phoneSetDisplay"));
  7933. }
  7934. LONG
  7935. TSPIAPI
  7936. TSPI_phoneSetGain(
  7937. DRV_REQUESTID dwRequestID,
  7938. HDRVPHONE hdPhone,
  7939. DWORD dwHookSwitchDev,
  7940. DWORD dwGain
  7941. )
  7942. {
  7943. static REMOTE_ARG_TYPES argTypes[] =
  7944. {
  7945. Dword,
  7946. Hdphone,
  7947. Dword,
  7948. Dword
  7949. };
  7950. ULONG_PTR args[] =
  7951. {
  7952. (ULONG_PTR) dwRequestID,
  7953. (ULONG_PTR) hdPhone,
  7954. (ULONG_PTR) dwHookSwitchDev,
  7955. (ULONG_PTR) dwGain
  7956. };
  7957. REMOTE_FUNC_ARGS funcArgs =
  7958. {
  7959. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetGain),
  7960. args,
  7961. argTypes
  7962. };
  7963. return (REMOTEDOFUNC (&funcArgs, "phoneSetGain"));
  7964. }
  7965. LONG
  7966. TSPIAPI
  7967. TSPI_phoneSetHookSwitch(
  7968. DRV_REQUESTID dwRequestID,
  7969. HDRVPHONE hdPhone,
  7970. DWORD dwHookSwitchDevs,
  7971. DWORD dwHookSwitchMode
  7972. )
  7973. {
  7974. static REMOTE_ARG_TYPES argTypes[] =
  7975. {
  7976. Dword,
  7977. Hdphone,
  7978. Dword,
  7979. Dword
  7980. };
  7981. ULONG_PTR args[] =
  7982. {
  7983. (ULONG_PTR) dwRequestID,
  7984. (ULONG_PTR) hdPhone,
  7985. (ULONG_PTR) dwHookSwitchDevs,
  7986. (ULONG_PTR) dwHookSwitchMode
  7987. };
  7988. REMOTE_FUNC_ARGS funcArgs =
  7989. {
  7990. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetHookSwitch),
  7991. args,
  7992. argTypes
  7993. };
  7994. return (REMOTEDOFUNC (&funcArgs, "phoneSetHookswitch"));
  7995. }
  7996. LONG
  7997. TSPIAPI
  7998. TSPI_phoneSetLamp(
  7999. DRV_REQUESTID dwRequestID,
  8000. HDRVPHONE hdPhone,
  8001. DWORD dwButtonLampID,
  8002. DWORD dwLampMode
  8003. )
  8004. {
  8005. static REMOTE_ARG_TYPES argTypes[] =
  8006. {
  8007. Dword,
  8008. Hdphone,
  8009. Dword,
  8010. Dword
  8011. };
  8012. ULONG_PTR args[] =
  8013. {
  8014. (ULONG_PTR) dwRequestID,
  8015. (ULONG_PTR) hdPhone,
  8016. (ULONG_PTR) dwButtonLampID,
  8017. (ULONG_PTR) dwLampMode
  8018. };
  8019. REMOTE_FUNC_ARGS funcArgs =
  8020. {
  8021. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetLamp),
  8022. args,
  8023. argTypes
  8024. };
  8025. return (REMOTEDOFUNC (&funcArgs, "phoneSetLamp"));
  8026. }
  8027. LONG
  8028. TSPIAPI
  8029. TSPI_phoneSetRing(
  8030. DRV_REQUESTID dwRequestID,
  8031. HDRVPHONE hdPhone,
  8032. DWORD dwRingMode,
  8033. DWORD dwVolume
  8034. )
  8035. {
  8036. static REMOTE_ARG_TYPES argTypes[] =
  8037. {
  8038. Dword,
  8039. Hdphone,
  8040. Dword,
  8041. Dword
  8042. };
  8043. ULONG_PTR args[] =
  8044. {
  8045. (ULONG_PTR) dwRequestID,
  8046. (ULONG_PTR) hdPhone,
  8047. (ULONG_PTR) dwRingMode,
  8048. (ULONG_PTR) dwVolume
  8049. };
  8050. REMOTE_FUNC_ARGS funcArgs =
  8051. {
  8052. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetRing),
  8053. args,
  8054. argTypes
  8055. };
  8056. return (REMOTEDOFUNC (&funcArgs, "phoneSetRing"));
  8057. }
  8058. LONG
  8059. TSPIAPI
  8060. TSPI_phoneSetStatusMessages(
  8061. HDRVPHONE hdPhone,
  8062. DWORD dwPhoneStates,
  8063. DWORD dwButtonModes,
  8064. DWORD dwButtonStates
  8065. )
  8066. {
  8067. static REMOTE_ARG_TYPES argTypes[] =
  8068. {
  8069. Hdphone,
  8070. Dword,
  8071. Dword,
  8072. Dword
  8073. };
  8074. ULONG_PTR args[] =
  8075. {
  8076. (ULONG_PTR) hdPhone,
  8077. (ULONG_PTR) dwPhoneStates,
  8078. (ULONG_PTR) dwButtonModes,
  8079. (ULONG_PTR) dwButtonStates
  8080. };
  8081. REMOTE_FUNC_ARGS funcArgs =
  8082. {
  8083. MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
  8084. args,
  8085. argTypes
  8086. };
  8087. return (REMOTEDOFUNC (&funcArgs, "phoneSetStatusMessages"));
  8088. }
  8089. LONG
  8090. TSPIAPI
  8091. TSPI_phoneSetVolume(
  8092. DRV_REQUESTID dwRequestID,
  8093. HDRVPHONE hdPhone,
  8094. DWORD dwHookSwitchDev,
  8095. DWORD dwVolume
  8096. )
  8097. {
  8098. static REMOTE_ARG_TYPES argTypes[] =
  8099. {
  8100. Dword,
  8101. Hdphone,
  8102. Dword,
  8103. Dword
  8104. };
  8105. ULONG_PTR args[] =
  8106. {
  8107. (ULONG_PTR) dwRequestID,
  8108. (ULONG_PTR) hdPhone,
  8109. (ULONG_PTR) dwHookSwitchDev,
  8110. (ULONG_PTR) dwVolume
  8111. };
  8112. REMOTE_FUNC_ARGS funcArgs =
  8113. {
  8114. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetVolume),
  8115. args,
  8116. argTypes
  8117. };
  8118. return (REMOTEDOFUNC (&funcArgs, "phoneSetVolume"));
  8119. }
  8120. //
  8121. // ------------------------- TSPI_providerXxx funcs ---------------------------
  8122. //
  8123. LONG
  8124. TSPIAPI
  8125. TSPI_providerCheckForNewUser(
  8126. DWORD dwPermanentProviderID
  8127. )
  8128. {
  8129. //
  8130. // This func gets called when a new process attaches to TAPISRV.
  8131. // We take advantage of this notification by checking to see if
  8132. // we've previously gone through full initialization, and if not
  8133. // (because previously attached processes were running in the
  8134. // system account which didn't allow for net access, and there
  8135. // was no logged on user to impersonate) then we try again here.
  8136. //
  8137. // Note that TAPISRV serializes calls to this func along with calls
  8138. // to init & shutdown, so we don't have to worry about serialization
  8139. // ourselves.
  8140. //
  8141. if (!gbInitialized)
  8142. {
  8143. LONG lResult;
  8144. DWORD dwNumLines, dwNumPhones;
  8145. LOG((TL_INFO,
  8146. "TSPI_providerCheckForNewUser: trying deferred init..."
  8147. ));
  8148. lResult = TSPI_providerEnumDevices(
  8149. 0xffffffff,
  8150. &dwNumLines,
  8151. &dwNumPhones,
  8152. 0,
  8153. NULL,
  8154. NULL
  8155. );
  8156. if (lResult == 1)
  8157. {
  8158. lResult = TSPI_providerInit(
  8159. TAPI_VERSION_CURRENT,
  8160. 0xffffffff, // dwPermanentProviderID,
  8161. 0, // dwLineDeviceIDBase,
  8162. 0, // dwPhoneDeviceIDBase,
  8163. 0, // dwNumLines,
  8164. 0, // dwNumPhones,
  8165. NULL, // lpfnCompletionProc,
  8166. NULL // lpdwTSPIOptions
  8167. );
  8168. LOG((TL_INFO,
  8169. "TSPI_providerCheckForNewUser: deferred Init result=x%x",
  8170. lResult
  8171. ));
  8172. }
  8173. }
  8174. return 0;
  8175. }
  8176. LONG
  8177. TSPIAPI
  8178. TSPI_providerConfig(
  8179. HWND hwndOwner,
  8180. DWORD dwPermanentProviderID
  8181. )
  8182. {
  8183. //
  8184. // Although this func is never called by TAPI v2.0, we export
  8185. // it so that the Telephony Control Panel Applet knows that it
  8186. // can configure this provider via lineConfigProvider(),
  8187. // otherwise Telephon.cpl will not consider it configurable
  8188. //
  8189. // for this release, we do not implement provider UI functions
  8190. return LINEERR_OPERATIONFAILED;
  8191. }
  8192. LONG
  8193. TSPIAPI
  8194. TSPI_providerCreateLineDevice(
  8195. ULONG_PTR TempID,
  8196. DWORD dwDeviceID
  8197. )
  8198. {
  8199. PDRVLINE pLine = GetLineFromID ((DWORD) TempID);
  8200. if (NULL == pLine)
  8201. {
  8202. return LINEERR_BADDEVICEID;
  8203. }
  8204. pLine->dwDeviceIDLocal = dwDeviceID;
  8205. if (pLine->dwXPIVersion == 0)
  8206. {
  8207. static REMOTE_ARG_TYPES argTypes[] =
  8208. {
  8209. Dword,
  8210. LineID,
  8211. Dword,
  8212. Dword,
  8213. lpDword,
  8214. lpGet_SizeToFollow,
  8215. Size
  8216. };
  8217. ULONG_PTR args[] =
  8218. {
  8219. (ULONG_PTR) pLine->pServer->hLineApp,
  8220. (ULONG_PTR) dwDeviceID,
  8221. (ULONG_PTR) TAPI_VERSION1_0,
  8222. (ULONG_PTR) TAPI_VERSION_CURRENT,
  8223. (ULONG_PTR) &pLine->dwXPIVersion,
  8224. (ULONG_PTR) &pLine->ExtensionID,
  8225. (ULONG_PTR) sizeof (LINEEXTENSIONID)
  8226. };
  8227. REMOTE_FUNC_ARGS funcArgs =
  8228. {
  8229. MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
  8230. args,
  8231. argTypes
  8232. };
  8233. REMOTEDOFUNC (&funcArgs, "lineNegotiateAPIVersion");
  8234. }
  8235. return 0;
  8236. }
  8237. LONG
  8238. TSPIAPI
  8239. TSPI_providerCreatePhoneDevice(
  8240. ULONG_PTR TempID,
  8241. DWORD dwDeviceID
  8242. )
  8243. {
  8244. PDRVPHONE pPhone = GetPhoneFromID ((DWORD) TempID);
  8245. if (NULL == pPhone)
  8246. {
  8247. return PHONEERR_BADDEVICEID;
  8248. }
  8249. pPhone->dwDeviceIDLocal = dwDeviceID;
  8250. if (pPhone->dwXPIVersion == 0)
  8251. {
  8252. static REMOTE_ARG_TYPES argTypes[] =
  8253. {
  8254. Dword,
  8255. PhoneID,
  8256. Dword,
  8257. Dword,
  8258. lpDword,
  8259. lpGet_SizeToFollow,
  8260. Size
  8261. };
  8262. ULONG_PTR args[] =
  8263. {
  8264. (ULONG_PTR) pPhone->pServer->hPhoneApp,
  8265. (ULONG_PTR) dwDeviceID,
  8266. (ULONG_PTR) TAPI_VERSION1_0,
  8267. (ULONG_PTR) TAPI_VERSION_CURRENT,
  8268. (ULONG_PTR) &pPhone->dwXPIVersion,
  8269. (ULONG_PTR) &pPhone->ExtensionID,
  8270. (ULONG_PTR) sizeof (PHONEEXTENSIONID),
  8271. };
  8272. REMOTE_FUNC_ARGS funcArgs =
  8273. {
  8274. MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
  8275. args,
  8276. argTypes
  8277. };
  8278. REMOTEDOFUNC (&funcArgs, "phoneNegotiateAPIVersion");
  8279. }
  8280. return 0;
  8281. }
  8282. LONG
  8283. TSPIAPI
  8284. TSPI_providerEnumDevices(
  8285. DWORD dwPermanentProviderID,
  8286. LPDWORD lpdwNumLines,
  8287. LPDWORD lpdwNumPhones,
  8288. HPROVIDER hProvider,
  8289. LINEEVENT lpfnLineCreateProc,
  8290. PHONEEVENT lpfnPhoneCreateProc
  8291. )
  8292. {
  8293. char szProviderN[16], szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  8294. DWORD dwSize, dwTID,
  8295. dwConnectionOrientedOnly,
  8296. dwRSPInitRpcTimeout;
  8297. HKEY hTelephonyKey;
  8298. HKEY hProviderNKey;
  8299. DWORD dwDataSize;
  8300. DWORD dwDataType;
  8301. PWSTR pszThingToPassToServer;
  8302. LONG lResult;
  8303. HANDLE hProcess;
  8304. PDRVSERVER pServer;
  8305. PRSP_THREAD_INFO pTls;
  8306. DWORD dwDisp;
  8307. RSPSOCKET socket;
  8308. //
  8309. // Check ghInst to ensure DllMain(DLL_PROCESS_ATTACH) has been called properly
  8310. //
  8311. if ( NULL == ghInst )
  8312. {
  8313. return LINEERR_OPERATIONFAILED;
  8314. }
  8315. //
  8316. // Init globals.
  8317. //
  8318. // If dwPermanentProviderID != 0xffffffff then we're being called
  8319. // directly by TAPISRV, so we want to init all the globals and
  8320. // keep going.
  8321. //
  8322. // Otherwise, we're being called from TSPI_providerCheckForNewUser,
  8323. // and we only want to continue if we've not actually initialized
  8324. // yet.
  8325. //
  8326. if (dwPermanentProviderID != 0xffffffff)
  8327. {
  8328. ghProvider = hProvider;
  8329. gdwPermanentProviderID = dwPermanentProviderID;
  8330. gpfnLineEventProc = lpfnLineCreateProc;
  8331. gpfnPhoneEventProc = lpfnPhoneCreateProc;
  8332. gbInitialized = FALSE;
  8333. TRACELOGREGISTER(_T("remotesp"));
  8334. LOG((TL_TRACE,
  8335. "TSPI_providerEnumDevices: enter, prov ID: 0x%x",
  8336. dwPermanentProviderID
  8337. ));
  8338. }
  8339. else
  8340. {
  8341. LOG((TL_TRACE,
  8342. "TSPI_providerEnumDevices: enter, called from TSPI_providerCheckForNewUser"
  8343. ));
  8344. if (gbInitialized)
  8345. {
  8346. return 0;
  8347. }
  8348. }
  8349. //
  8350. // Is the client app running in the system account? If so,
  8351. // then try to impersonate the logged-on user, because the
  8352. // system account doesn't have net privileges. If no one is
  8353. // logged in yet then we'll simply return success & no devices,
  8354. // and if a user happens to log on later & run a tapi app
  8355. // then we'll try to do init at that time (from within
  8356. // TSPI_providerCheckForNewUser).
  8357. //
  8358. if (IsClientSystem())
  8359. {
  8360. LOG((TL_INFO,
  8361. "TSPI_providerEnumDevices: Client is system account"
  8362. ));
  8363. LOG((TL_INFO,
  8364. " ...attempting logged-on-user impersonation"
  8365. ));
  8366. if (!GetCurrentlyLoggedOnUser (&hProcess))
  8367. {
  8368. LOG((TL_ERROR,
  8369. "TSPI_providerEnumDevices: GetCurrentlyLoggedOnUser failed"
  8370. ));
  8371. LOG((TL_INFO,
  8372. " ...deferring initialization"
  8373. ));
  8374. gdwInitialNumLineDevices = 0;
  8375. gdwInitialNumPhoneDevices = 0;
  8376. return 0;
  8377. }
  8378. }
  8379. else
  8380. {
  8381. hProcess = NULL;
  8382. }
  8383. gbInitialized = TRUE;
  8384. gdwDrvServerKey = GetTickCount();
  8385. if (!(gpCurrentInitContext = DrvAlloc (sizeof (RSP_INIT_CONTEXT))))
  8386. {
  8387. if (hProcess)
  8388. {
  8389. CloseHandle (hProcess);
  8390. }
  8391. return LINEERR_NOMEM;
  8392. }
  8393. gpCurrentInitContext->dwDrvServerKey = gdwDrvServerKey;
  8394. InitializeListHead (&gpCurrentInitContext->ServerList);
  8395. InitializeListHead (&gNptListHead);
  8396. if (!(pszThingToPassToServer = DrvAlloc(
  8397. MAX_COMPUTERNAME_LENGTH+1 + 256) // incl protseq 0-N, endpoint 0-N
  8398. ))
  8399. {
  8400. if (hProcess)
  8401. {
  8402. CloseHandle (hProcess);
  8403. }
  8404. DrvFree (gpCurrentInitContext);
  8405. return LINEERR_NOMEM;
  8406. }
  8407. gdwInitialNumLineDevices = gdwLineDeviceIDBase =
  8408. gdwInitialNumPhoneDevices = gdwPhoneDeviceIDBase = 0;
  8409. if (ERROR_SUCCESS !=
  8410. RegOpenKeyEx(
  8411. HKEY_LOCAL_MACHINE,
  8412. gszTelephonyKey,
  8413. 0,
  8414. KEY_ALL_ACCESS,
  8415. &hTelephonyKey
  8416. ))
  8417. {
  8418. if (hProcess)
  8419. {
  8420. CloseHandle (hProcess);
  8421. }
  8422. DrvFree (gpCurrentInitContext);
  8423. DrvFree (pszThingToPassToServer);
  8424. return LINEERR_OPERATIONFAILED;
  8425. }
  8426. {
  8427. DWORD dwSize;
  8428. dwSize = MAX_COMPUTERNAME_LENGTH + 1;
  8429. #ifdef PARTIAL_UNICODE
  8430. {
  8431. CHAR buf[MAX_COMPUTERNAME_LENGTH + 1];
  8432. GetComputerName (buf, &dwSize);
  8433. MultiByteToWideChar(
  8434. GetACP(),
  8435. MB_PRECOMPOSED,
  8436. buf,
  8437. dwSize,
  8438. gszMachineName,
  8439. dwSize
  8440. );
  8441. }
  8442. #else
  8443. GetComputerNameW (gszMachineName, &dwSize);
  8444. #endif
  8445. }
  8446. wcscpy( pszThingToPassToServer, gszMachineName );
  8447. wcscat( pszThingToPassToServer, L"\"");
  8448. //
  8449. // See if multi-protocol support is enabled in the registry
  8450. // (for talking to post-TAPI 2.1 servers)
  8451. //
  8452. wsprintf (szProviderN, "Provider%d", gdwPermanentProviderID);
  8453. RegCreateKeyEx(
  8454. hTelephonyKey,
  8455. szProviderN,
  8456. 0,
  8457. NULL,
  8458. REG_OPTION_NON_VOLATILE,
  8459. KEY_ALL_ACCESS,
  8460. NULL,
  8461. &hProviderNKey,
  8462. &dwDisp
  8463. );
  8464. dwDataSize = sizeof (dwConnectionOrientedOnly);
  8465. dwConnectionOrientedOnly = 0;
  8466. RegQueryValueEx(
  8467. hProviderNKey,
  8468. "ConnectionOrientedOnly",
  8469. 0,
  8470. &dwDataType,
  8471. (LPBYTE) &dwConnectionOrientedOnly,
  8472. &dwDataSize
  8473. );
  8474. dwDataSize = sizeof (gdwRSPRpcTimeout);
  8475. if (RegQueryValueEx(
  8476. hTelephonyKey,
  8477. "RspRpcTimeout",
  8478. 0,
  8479. &dwDataType,
  8480. (LPBYTE) &gdwRSPRpcTimeout,
  8481. &dwDataSize
  8482. ) != ERROR_SUCCESS)
  8483. {
  8484. gdwRSPRpcTimeout = 5 * 60 * 1000; // default to 5 minutes
  8485. }
  8486. if (gdwRSPRpcTimeout < 10 * 1000)
  8487. {
  8488. // Do not allow a value less then 10 seconds
  8489. gdwRSPRpcTimeout = 10 * 1000;
  8490. }
  8491. dwDataSize = sizeof (dwRSPInitRpcTimeout);
  8492. if (RegQueryValueEx(
  8493. hTelephonyKey,
  8494. "RspInitRpcTimeout",
  8495. 0,
  8496. &dwDataType,
  8497. (LPBYTE) &dwRSPInitRpcTimeout,
  8498. &dwDataSize
  8499. ) != ERROR_SUCCESS)
  8500. {
  8501. dwRSPInitRpcTimeout = 10 * 1000; // default to 10 seconds
  8502. }
  8503. if (dwRSPInitRpcTimeout < 1000)
  8504. {
  8505. // Do not allow this to be less than 1 second
  8506. dwRSPInitRpcTimeout = 1000;
  8507. }
  8508. dwDataSize = sizeof (gdwMaxEventBufferSize);
  8509. gdwMaxEventBufferSize = DEF_MAX_EVENT_BUFFER_SIZE;
  8510. RegQueryValueEx(
  8511. hProviderNKey,
  8512. "MaxEventBufferSize",
  8513. 0,
  8514. &dwDataType,
  8515. (LPBYTE) &gdwMaxEventBufferSize,
  8516. &dwDataSize
  8517. );
  8518. RegCloseKey (hProviderNKey);
  8519. //
  8520. // Init gEventHandlerThreadParams
  8521. //
  8522. gEventHandlerThreadParams.dwEventBufferTotalSize = 1024;
  8523. gEventHandlerThreadParams.dwEventBufferUsedSize = 0;
  8524. if (!(gEventHandlerThreadParams.pEventBuffer = DrvAlloc(
  8525. gEventHandlerThreadParams.dwEventBufferTotalSize
  8526. )))
  8527. {
  8528. if (hProcess)
  8529. {
  8530. CloseHandle (hProcess);
  8531. }
  8532. DrvFree (gpCurrentInitContext);
  8533. DrvFree (pszThingToPassToServer);
  8534. CloseHandle (hTelephonyKey);
  8535. return LINEERR_NOMEM;
  8536. }
  8537. gEventHandlerThreadParams.pDataIn =
  8538. gEventHandlerThreadParams.pDataOut =
  8539. gEventHandlerThreadParams.pEventBuffer;
  8540. if (!(gEventHandlerThreadParams.hEvent = CreateEvent(
  8541. (LPSECURITY_ATTRIBUTES) NULL, // no security attrs
  8542. TRUE, // manual reset
  8543. FALSE, // initially non-signaled
  8544. NULL // unnamed
  8545. )))
  8546. {
  8547. if (hProcess)
  8548. {
  8549. CloseHandle (hProcess);
  8550. }
  8551. DrvFree (gpCurrentInitContext);
  8552. DrvFree (pszThingToPassToServer);
  8553. CloseHandle (hTelephonyKey);
  8554. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  8555. return LINEERR_NOMEM;
  8556. }
  8557. gEventHandlerThreadParams.dwMsgBufferTotalSize = 1024;
  8558. if (!(gEventHandlerThreadParams.pMsgBuffer = DrvAlloc(
  8559. gEventHandlerThreadParams.dwMsgBufferTotalSize
  8560. )))
  8561. {
  8562. if (hProcess)
  8563. {
  8564. CloseHandle (hProcess);
  8565. }
  8566. DrvFree (gpCurrentInitContext);
  8567. DrvFree (pszThingToPassToServer);
  8568. CloseHandle (hTelephonyKey);
  8569. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  8570. CloseHandle (gEventHandlerThreadParams.hEvent);
  8571. return LINEERR_NOMEM;
  8572. }
  8573. //
  8574. // Register the Rpc interface (leverage tapisrv's rpc server thread)
  8575. //
  8576. {
  8577. RPC_STATUS status;
  8578. unsigned char * pszSecurity = NULL;
  8579. unsigned int cMaxCalls = 20;
  8580. unsigned char * szProtseq = "ncacn_ip_tcp";
  8581. unsigned char * szEndpoint = "251";
  8582. const WCHAR * wszProtseq = L"ncacn_ip_tcp\"";
  8583. const WCHAR * wszEndpoint = L"251";
  8584. status = RpcServerUseProtseqEp(
  8585. szProtseq,
  8586. cMaxCalls,
  8587. szEndpoint,
  8588. pszSecurity // Security descriptor
  8589. );
  8590. LOG((TL_INFO,
  8591. "RpcServerUseProtseqEp(%s) ret'd %d",
  8592. szProtseq,
  8593. status
  8594. ));
  8595. if (status == 0 || status == RPC_S_DUPLICATE_ENDPOINT)
  8596. {
  8597. wcscat (pszThingToPassToServer, wszProtseq);
  8598. wcscat (pszThingToPassToServer, wszEndpoint);
  8599. }
  8600. else
  8601. {
  8602. LOG((TL_ERROR,
  8603. "TSPI_providerEnumDevices: fatal error, couldn't get a protseq"
  8604. ));
  8605. if (hProcess)
  8606. {
  8607. CloseHandle (hProcess);
  8608. }
  8609. DrvFree (gpCurrentInitContext);
  8610. DrvFree (pszThingToPassToServer);
  8611. CloseHandle (hTelephonyKey);
  8612. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  8613. CloseHandle (gEventHandlerThreadParams.hEvent);
  8614. return LINEERR_OPERATIONFAILED;
  8615. }
  8616. status = RpcServerRegisterIfEx(
  8617. remotesp_ServerIfHandle, // interface to register
  8618. NULL, // MgrTypeUuid
  8619. NULL, // MgrEpv; null means use default
  8620. RPC_IF_AUTOLISTEN | RPC_IF_ALLOW_SECURE_ONLY,
  8621. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  8622. NULL
  8623. );
  8624. if (status)
  8625. {
  8626. LOG((TL_INFO,
  8627. "TSPI_providerEnumDevices: RpcServerRegisterIf ret'd %d",
  8628. status
  8629. ));
  8630. }
  8631. status = RpcServerRegisterAuthInfo(
  8632. NULL,
  8633. RPC_C_AUTHN_WINNT,
  8634. NULL,
  8635. NULL
  8636. );
  8637. if (status)
  8638. {
  8639. LOG((TL_INFO,
  8640. "TSPI_providerEnumDevices: RpcServerRegisterAuthInfo " \
  8641. "returned %d",
  8642. status
  8643. ));
  8644. }
  8645. }
  8646. //
  8647. // Open a mailslot iff appropriate (use a semi-random name seeded
  8648. // via process id)
  8649. //
  8650. if (!dwConnectionOrientedOnly)
  8651. {
  8652. DWORD dwPID = GetCurrentProcessId(), dwRandomNum;
  8653. WCHAR szMailslotName[32];
  8654. dwRandomNum = (65537 * dwPID * dwPID * dwPID) & 0x00ffffff;
  8655. wsprintfW(
  8656. gszMailslotName,
  8657. L"\\\\%ws\\mailslot\\tapi\\tp%x",
  8658. gszMachineName,
  8659. dwRandomNum
  8660. );
  8661. wsprintfW(
  8662. szMailslotName,
  8663. L"\\\\.\\mailslot\\tapi\\tp%x",
  8664. dwRandomNum
  8665. );
  8666. LOG((TL_TRACE,
  8667. "TSPI_providerEnumDevices: calling CreateMailslot"
  8668. ));
  8669. if ((gEventHandlerThreadParams.hMailslot = CreateMailslotW(
  8670. szMailslotName,
  8671. sizeof (DWORD), // max msg size
  8672. MAILSLOT_WAIT_FOREVER,
  8673. (LPSECURITY_ATTRIBUTES) NULL
  8674. )) == INVALID_HANDLE_VALUE)
  8675. {
  8676. LOG((TL_ERROR,
  8677. "TSPI_providerEnumDevices: CreateMailslot failed, err=%d",
  8678. GetLastError()
  8679. ));
  8680. goto no_mailslot;
  8681. }
  8682. else
  8683. {
  8684. RegOpenKeyEx(
  8685. hTelephonyKey,
  8686. szProviderN,
  8687. 0,
  8688. KEY_ALL_ACCESS,
  8689. &hProviderNKey
  8690. );
  8691. RegCloseKey (hProviderNKey);
  8692. }
  8693. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  8694. {
  8695. gEventHandlerThreadParams.hMailslotEvent = CreateEvent(
  8696. NULL, // no security attrs
  8697. FALSE, // auto-reset
  8698. FALSE, // initially non-signaled
  8699. NULL // unnamed
  8700. );
  8701. if (!gEventHandlerThreadParams.hMailslotEvent)
  8702. {
  8703. LOG((TL_ERROR,
  8704. "TSPI_providerEnumDevices: CreateEvent failed, err=%d",
  8705. GetLastError()
  8706. ));
  8707. goto no_mailslot;
  8708. }
  8709. }
  8710. }
  8711. else
  8712. {
  8713. no_mailslot:
  8714. LOG((TL_INFO,"TSPI_providerEnumDevices: doing connection-oriented only"));
  8715. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  8716. {
  8717. CloseHandle (gEventHandlerThreadParams.hMailslot);
  8718. gEventHandlerThreadParams.hMailslot = INVALID_HANDLE_VALUE;
  8719. }
  8720. gszMailslotName[0] = (WCHAR) 0;
  8721. }
  8722. //
  8723. // Init globals
  8724. //
  8725. // NOTE: TAPI's xxxEvent & xxxCreate procs are currently one in the same
  8726. //
  8727. wsprintf (szProviderN, "Provider%d", gdwPermanentProviderID);
  8728. gpLineLookup = (PDRVLINELOOKUP) NULL;
  8729. gpPhoneLookup = (PDRVPHONELOOKUP) NULL;
  8730. RegOpenKeyEx(
  8731. hTelephonyKey,
  8732. szProviderN,
  8733. 0,
  8734. KEY_ALL_ACCESS,
  8735. &hProviderNKey
  8736. );
  8737. dwDataSize = sizeof(gdwRetryCount);
  8738. gdwRetryCount = 2;
  8739. RegQueryValueEx(
  8740. hProviderNKey,
  8741. "RetryCount",
  8742. 0,
  8743. &dwDataType,
  8744. (LPBYTE) &gdwRetryCount,
  8745. &dwDataSize
  8746. );
  8747. dwDataSize = sizeof(gdwRetryTimeout);
  8748. gdwRetryTimeout = 1000;
  8749. RegQueryValueEx(
  8750. hProviderNKey,
  8751. "RetryTimeout",
  8752. 0,
  8753. &dwDataType,
  8754. (LPBYTE) &gdwRetryTimeout,
  8755. &dwDataSize
  8756. );
  8757. gfCacheStructures = TRUE;
  8758. dwDataSize = sizeof(gfCacheStructures);
  8759. RegQueryValueEx(
  8760. hProviderNKey,
  8761. "CacheStructures",
  8762. 0,
  8763. &dwDataType,
  8764. (LPBYTE)&gfCacheStructures,
  8765. &dwDataSize
  8766. );
  8767. if (gfCacheStructures)
  8768. {
  8769. gdwCacheForceCallCount = 5;
  8770. dwDataSize = sizeof(gdwCacheForceCallCount);
  8771. RegQueryValueEx(
  8772. hProviderNKey,
  8773. "CacheForceCallCount",
  8774. 0,
  8775. &dwDataType,
  8776. (LPBYTE)&gdwCacheForceCallCount,
  8777. &dwDataSize
  8778. );
  8779. }
  8780. dwSize = MAX_COMPUTERNAME_LENGTH+1;
  8781. GetComputerName (szComputerName, &dwSize);
  8782. //
  8783. // Initialize Directory server lookup
  8784. // we pass in a registry key in case the
  8785. // Directory does not exist
  8786. //
  8787. if (!OpenServerLookup(hProviderNKey))
  8788. {
  8789. LOG((TL_ERROR, "TSPI_providerEnumDevices: OpenServerLookup() failed"));
  8790. fatal_error:
  8791. if (hProcess)
  8792. {
  8793. CloseHandle (hProcess);
  8794. }
  8795. DrvFree (gpCurrentInitContext);
  8796. DrvFree (pszThingToPassToServer);
  8797. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  8798. CloseHandle (gEventHandlerThreadParams.hEvent);
  8799. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  8800. {
  8801. CloseHandle (gEventHandlerThreadParams.hMailslot);
  8802. gEventHandlerThreadParams.hMailslot = INVALID_HANDLE_VALUE;
  8803. }
  8804. RegCloseKey (hProviderNKey);
  8805. RegCloseKey (hTelephonyKey);
  8806. return LINEERR_OPERATIONFAILED;
  8807. }
  8808. if (!hProcess)
  8809. {
  8810. RPC_STATUS status;
  8811. status = RpcImpersonateClient(0);
  8812. if (status != RPC_S_OK && status != RPC_S_NO_CALL_ACTIVE)
  8813. {
  8814. LOG((TL_ERROR, "RpcImpersonateClient failed, err %d", status));
  8815. CloseLookup();
  8816. goto fatal_error;
  8817. }
  8818. }
  8819. else if (!SetProcessImpersonationToken(hProcess))
  8820. {
  8821. LOG((TL_ERROR, "SetProcessImpersonationToken failed"));
  8822. CloseLookup();
  8823. goto fatal_error;
  8824. }
  8825. if (pTls = GetTls())
  8826. {
  8827. pTls->bAlreadyImpersonated = TRUE;
  8828. }
  8829. if (SockStartup (&socket) != S_OK)
  8830. {
  8831. goto fatal_error;
  8832. }
  8833. //
  8834. // Loop trying to attach to each server
  8835. //
  8836. while (1)
  8837. {
  8838. char szServerName[MAX_COMPUTERNAME_LENGTH+1];
  8839. PCONTEXT_HANDLE_TYPE phContext = NULL;
  8840. BOOL bFromReg;
  8841. if (!GetNextServer(szServerName, sizeof(szServerName), &bFromReg))
  8842. {
  8843. CloseLookup();
  8844. break;
  8845. }
  8846. LOG((TL_INFO, "init: Server name='%s'", szServerName));
  8847. if (!szServerName[0])
  8848. {
  8849. continue;
  8850. }
  8851. if (!lstrcmpi(szComputerName, szServerName))
  8852. {
  8853. LOG((TL_ERROR,"init: ServerName is the same a local computer name"));
  8854. LOG((TL_INFO," Ignoring this server"));
  8855. continue;
  8856. }
  8857. //
  8858. // Init the RPC connection
  8859. //
  8860. pServer = DrvAlloc (sizeof (DRVSERVER));
  8861. pServer->pInitContext = gpCurrentInitContext;
  8862. pServer->dwKey = gdwDrvServerKey;
  8863. lstrcpy (pServer->szServerName, szServerName);
  8864. {
  8865. //
  8866. // For RPC calls, we use a timeout value of 5 minutes based
  8867. // on RPC team recommendation (dwRSPRpcTimeout). But
  8868. // during RemoteSP startup, we use a even shorter
  8869. // timeout value for RPC (dwRSPInitRpcTimeout), this could
  8870. // cause us falsely declare a server dead when it is in fact not
  8871. // if the network connection is bad or the server is busy.
  8872. // But this would not be a problem because such a server
  8873. // will be inserted into the gNptListHead list and eventually
  8874. // recover by the NetworkPollThread.
  8875. //
  8876. // Both the above timeout value can be configured from
  8877. // registry by using DWORD registry value of
  8878. // "RspRpcTimeout" & "RspInitRpcTimeout
  8879. // under HKLM\Software\Microsoft\Windows\CurrentVersion\Telephony
  8880. // They should be expressed in the unit of milli-seconds
  8881. //
  8882. RPC_STATUS status;
  8883. unsigned char * pszStringBinding = NULL;
  8884. LOG((TL_INFO, "Creating binding..."));
  8885. status = RpcStringBindingCompose(
  8886. NULL, // uuid
  8887. "ncacn_np", // prot
  8888. szServerName, // server name
  8889. "\\pipe\\tapsrv", // interface name
  8890. NULL, // options
  8891. &pszStringBinding
  8892. );
  8893. if (status)
  8894. {
  8895. LOG((TL_ERROR,
  8896. "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
  8897. status,
  8898. szServerName
  8899. ));
  8900. }
  8901. else
  8902. {
  8903. status = RpcBindingFromStringBinding(
  8904. pszStringBinding,
  8905. &hTapSrv
  8906. );
  8907. RpcStringFree (&pszStringBinding);
  8908. if (status)
  8909. {
  8910. LOG((TL_ERROR,
  8911. "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
  8912. status,
  8913. pszStringBinding
  8914. ));
  8915. }
  8916. else
  8917. {
  8918. RpcBindingSetOption (
  8919. hTapSrv,
  8920. RPC_C_OPT_CALL_TIMEOUT,
  8921. dwRSPInitRpcTimeout
  8922. );
  8923. if (SockIsServerResponding(&socket, szServerName) != S_OK)
  8924. {
  8925. LOG((TL_ERROR,"init: %s is not responding", szServerName));
  8926. LOG((TL_INFO," Ignoring this server"));
  8927. lResult = RPC_S_SERVER_UNAVAILABLE;
  8928. }
  8929. else
  8930. {
  8931. status = RpcBindingSetAuthInfo(
  8932. hTapSrv,
  8933. NULL,
  8934. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  8935. RPC_C_AUTHN_WINNT,
  8936. NULL,
  8937. 0
  8938. );
  8939. if (status)
  8940. {
  8941. LOG((TL_ERROR,
  8942. "RpcBindingSetAuthInfo failed, err=%d",
  8943. status
  8944. ));
  8945. lResult = LINEERR_OPERATIONFAILED;
  8946. }
  8947. else
  8948. {
  8949. DWORD dwException = 0;
  8950. pServer->bSetAuthInfo = TRUE;
  8951. pServer->dwSpecialHack = 0;
  8952. //
  8953. // Set the global which RemoteSPAttach looks at to know
  8954. // who the current server is
  8955. //
  8956. gpCurrInitServer = pServer;
  8957. RpcTryExcept
  8958. {
  8959. LOG((TL_INFO, "Calling ClientAttach..."));
  8960. lResult = ClientAttach(
  8961. &phContext,
  8962. 0xffffffff, // dwProcessID, -1 implies remotesp
  8963. &pServer->dwSpecialHack,
  8964. gszMailslotName,
  8965. pszThingToPassToServer // gszMachineName
  8966. );
  8967. LOG((TL_INFO, "ClientAttach returned 0x%x", lResult));
  8968. if (lResult != 0)
  8969. {
  8970. LogRemoteSPError(pServer->szServerName,
  8971. ERROR_REMOTESP_ATTACH, lResult, 0,
  8972. FALSE);
  8973. }
  8974. else
  8975. {
  8976. LogRemoteSPError(pServer->szServerName,
  8977. ERROR_REMOTESP_NONE, 0, 0,
  8978. FALSE);
  8979. }
  8980. }
  8981. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  8982. {
  8983. dwException = RpcExceptionCode();
  8984. LOG((TL_INFO, "ClientAttach threw RPC exception 0x%x", dwException));
  8985. //
  8986. // Go onto next server. The poll thread
  8987. // will take care of things...
  8988. //
  8989. LOG((TL_ERROR,
  8990. "ClientAttach failed - check server name"
  8991. ));
  8992. lResult = LINEERR_OPERATIONFAILED;
  8993. }
  8994. RpcEndExcept
  8995. }
  8996. pServer->hTapSrv = hTapSrv;
  8997. if ( 0 != lResult )
  8998. {
  8999. //
  9000. // RPC attach failed. We'll start a thread
  9001. // and poll for it. When it works, we can add
  9002. // the phones/lines dynamically.
  9003. // In the meantime, this thread will continue
  9004. // to contact other servers.
  9005. //
  9006. RpcBindingSetOption (
  9007. hTapSrv,
  9008. RPC_C_OPT_CALL_TIMEOUT,
  9009. gdwRSPRpcTimeout
  9010. );
  9011. InsertTailList (&gNptListHead, &pServer->ServerList);
  9012. continue;
  9013. }
  9014. //
  9015. // Enable all events for remotesp
  9016. //
  9017. pServer->phContext = phContext;
  9018. RSPSetEventFilterMasks (
  9019. pServer,
  9020. TAPIOBJ_NULL,
  9021. (LONG_PTR)NULL,
  9022. (ULONG64)EM_ALL
  9023. );
  9024. //
  9025. // Now that we have contacted this server, init it and
  9026. // add the phones/lines.
  9027. //
  9028. FinishEnumDevices(
  9029. pServer,
  9030. phContext,
  9031. lpdwNumLines,
  9032. lpdwNumPhones,
  9033. (dwPermanentProviderID == 0xffffffff ? FALSE : TRUE),
  9034. bFromReg
  9035. );
  9036. }
  9037. }
  9038. }
  9039. }
  9040. }
  9041. SockShutdown (&socket);
  9042. //
  9043. // If we successfully attached to all servers then clean up,
  9044. // otherwise start the poll thread
  9045. //
  9046. if (gpszThingToPassToServer)
  9047. {
  9048. DrvFree (gpszThingToPassToServer);
  9049. }
  9050. gpszThingToPassToServer = pszThingToPassToServer;
  9051. TapiEnterCriticalSection ( &gCriticalSection );
  9052. if (!IsListEmpty (&gNptListHead) && !ghNetworkPollThread)
  9053. {
  9054. ghNptShutdownEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  9055. if (!ghNptShutdownEvent)
  9056. {
  9057. LOG((TL_ERROR, "Unable to create ghNptShutdownEvent!"));
  9058. }
  9059. else
  9060. {
  9061. if (!(ghNetworkPollThread = CreateThread(
  9062. NULL,
  9063. 0,
  9064. (LPTHREAD_START_ROUTINE) NetworkPollThread,
  9065. (LPVOID) pszThingToPassToServer,
  9066. 0,
  9067. &dwTID
  9068. )))
  9069. {
  9070. LOG((TL_ERROR, "Unable to create poll thread! Argh!"));
  9071. CloseHandle (ghNptShutdownEvent);
  9072. ghNptShutdownEvent = NULL;
  9073. }
  9074. }
  9075. if (!ghNptShutdownEvent || !ghNetworkPollThread)
  9076. {
  9077. // Error creating the NetworkPollThread
  9078. // We'll just run with the servers we already attached to
  9079. while (!IsListEmpty (&gNptListHead))
  9080. {
  9081. LIST_ENTRY *pEntry = RemoveHeadList (&gNptListHead);
  9082. DrvFree(
  9083. CONTAINING_RECORD (pEntry, DRVSERVER, ServerList)
  9084. );
  9085. }
  9086. }
  9087. }
  9088. TapiLeaveCriticalSection( &gCriticalSection );
  9089. RegCloseKey (hProviderNKey);
  9090. RegCloseKey (hTelephonyKey);
  9091. if (hProcess)
  9092. {
  9093. ClearImpersonationToken();
  9094. CloseHandle (hProcess);
  9095. }
  9096. else
  9097. {
  9098. RevertToSelf();
  9099. }
  9100. if (pTls)
  9101. {
  9102. pTls->bAlreadyImpersonated = FALSE;
  9103. }
  9104. //
  9105. // If dwPermanentProviderID == 0xffffffff we're being called by
  9106. // TSPI_providerCheckForNewUser, so return a special value of 1
  9107. // so that it'll know to follow up with a TSPI_providerInit.
  9108. //
  9109. // Otherwise, we're being called directly from TAPI so simply
  9110. // return 0 to indicate success.
  9111. //
  9112. return (dwPermanentProviderID == 0xffffffff ? 1 : 0);
  9113. }
  9114. LONG
  9115. TSPIAPI
  9116. TSPI_providerFreeDialogInstance(
  9117. HDRVDIALOGINSTANCE hdDlgInst
  9118. )
  9119. {
  9120. return 0;
  9121. }
  9122. LONG
  9123. TSPIAPI
  9124. TSPI_providerGenericDialogData(
  9125. ULONG_PTR ObjectID,
  9126. DWORD dwObjectType,
  9127. LPVOID lpParams,
  9128. DWORD dwSize
  9129. )
  9130. {
  9131. LPDWORD lpBuffer;
  9132. REMOTE_ARG_TYPES argTypes[] =
  9133. {
  9134. LineID,
  9135. Dword,
  9136. lpSet_SizeToFollow,
  9137. Size,
  9138. lpGet_SizeToFollow,
  9139. Size
  9140. };
  9141. ULONG_PTR args[] =
  9142. {
  9143. (ULONG_PTR) ObjectID,
  9144. (ULONG_PTR) dwObjectType,
  9145. (ULONG_PTR) lpParams,
  9146. (ULONG_PTR) dwSize,
  9147. (ULONG_PTR) lpParams,
  9148. (ULONG_PTR) dwSize
  9149. };
  9150. REMOTE_FUNC_ARGS funcArgs =
  9151. {
  9152. MAKELONG (LINE_FUNC | SYNC | 6, xUIDLLCallback),
  9153. args,
  9154. argTypes
  9155. };
  9156. // first check to see if this is a message to ourselves.
  9157. lpBuffer = (LPDWORD) lpParams;
  9158. if ((dwSize > (2 * sizeof(DWORD))) &&
  9159. (lpBuffer[0] == RSP_MSG) &&
  9160. (lpBuffer[1] == RSP_MSG_UIID))
  9161. {
  9162. // if it is, we're looking for the real provider ui dll. fill in the
  9163. // buffer and return
  9164. // note that we only handle one sp here, but it may be easy to handle multiple
  9165. // by sending in additional info in the buffer ( like the line ID or something)
  9166. wcscpy ((LPWSTR)(lpBuffer+2), gszRealSPUIDLL);
  9167. return 0;
  9168. }
  9169. switch (dwObjectType)
  9170. {
  9171. case TUISPIDLL_OBJECT_LINEID:
  9172. // argTypes[0] already set correctly, just break
  9173. break;
  9174. case TUISPIDLL_OBJECT_PHONEID:
  9175. argTypes[0] = PhoneID;
  9176. break;
  9177. case TUISPIDLL_OBJECT_PROVIDERID:
  9178. default: // case TUISPIDLL_OBJECT_DIALOGINSTANCE:
  9179. break;
  9180. }
  9181. return (REMOTEDOFUNC (&funcArgs, "UIDLLCallback"));
  9182. }
  9183. LONG
  9184. TSPIAPI
  9185. TSPI_providerInit(
  9186. DWORD dwTSPIVersion,
  9187. DWORD dwPermanentProviderID,
  9188. DWORD dwLineDeviceIDBase,
  9189. DWORD dwPhoneDeviceIDBase,
  9190. DWORD_PTR dwNumLines,
  9191. DWORD_PTR dwNumPhones,
  9192. ASYNC_COMPLETION lpfnCompletionProc,
  9193. LPDWORD lpdwTSPIOptions
  9194. )
  9195. {
  9196. DWORD i;
  9197. //
  9198. // Init globals
  9199. //
  9200. // If dwPermanentProviderID != 0xffffffff then we're being called
  9201. // directly by TAPISRV, so we want to init all the globals and
  9202. // keep going only if the gbInitialized flag is set (implying
  9203. // that we've gone thru all the code in EnumDevices).
  9204. //
  9205. // Otherwise, we're being called from TSPI_providerCheckForNewUser.
  9206. //
  9207. if (dwPermanentProviderID != 0xffffffff)
  9208. {
  9209. gdwLineDeviceIDBase = dwLineDeviceIDBase;
  9210. gdwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
  9211. gpfnCompletionProc = lpfnCompletionProc;
  9212. *lpdwTSPIOptions = 0;
  9213. if (!gbInitialized)
  9214. {
  9215. return 0;
  9216. }
  9217. }
  9218. //
  9219. // Adjust the .dwDeviceIDLocal values for all the initial devices
  9220. // now that we know the device id bases
  9221. //
  9222. for (i = 0; i < gdwInitialNumLineDevices; i++)
  9223. {
  9224. gpLineLookup->aEntries[i].dwDeviceIDLocal = dwLineDeviceIDBase + i;
  9225. }
  9226. for (i = 0; i < gdwInitialNumPhoneDevices; i++)
  9227. {
  9228. gpPhoneLookup->aEntries[i].dwDeviceIDLocal = dwPhoneDeviceIDBase + i;
  9229. }
  9230. //
  9231. // Start EventHandlerThread
  9232. //
  9233. gEventHandlerThreadParams.bExit = FALSE;
  9234. if (!(gEventHandlerThreadParams.hThread = CreateThread(
  9235. (LPSECURITY_ATTRIBUTES) NULL,
  9236. 0,
  9237. (LPTHREAD_START_ROUTINE) EventHandlerThread,
  9238. NULL,
  9239. 0,
  9240. &i // &dwThreadID
  9241. )))
  9242. {
  9243. LOG((TL_ERROR,
  9244. "CreateThread('EventHandlerThread') failed, err=%d",
  9245. GetLastError()
  9246. ));
  9247. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  9248. CloseHandle (gEventHandlerThreadParams.hEvent);
  9249. return LINEERR_OPERATIONFAILED;
  9250. }
  9251. return 0;
  9252. }
  9253. LONG
  9254. TSPIAPI
  9255. TSPI_providerInstall(
  9256. HWND hwndOwner,
  9257. DWORD dwPermanentProviderID
  9258. )
  9259. {
  9260. //
  9261. // Although this func is never called by TAPI v2.0, we export
  9262. // it so that the Telephony Control Panel Applet knows that it
  9263. // can add this provider via lineAddProvider(), otherwise
  9264. // Telephon.cpl will not consider it installable
  9265. //
  9266. //
  9267. return 0;
  9268. }
  9269. LONG
  9270. TSPIAPI
  9271. TSPI_providerRemove(
  9272. HWND hwndOwner,
  9273. DWORD dwPermanentProviderID
  9274. )
  9275. {
  9276. //
  9277. // Although this func is never called by TAPI v2.0, we export
  9278. // it so that the Telephony Control Panel Applet knows that it
  9279. // can remove this provider via lineRemoveProvider(), otherwise
  9280. // Telephon.cpl will not consider it removable
  9281. //
  9282. return 0;
  9283. }
  9284. LONG
  9285. TSPIAPI
  9286. TSPI_providerShutdown(
  9287. DWORD dwTSPIVersion,
  9288. DWORD dwPermanentProviderID
  9289. )
  9290. {
  9291. DWORD i;
  9292. PDRVSERVER pServer;
  9293. RPC_STATUS status;
  9294. LIST_ENTRY *pEntry;
  9295. //
  9296. // If the gbInitialized flag is not set then we never fully
  9297. // initialized because no client process with user (as opposed
  9298. // to system) privileges ever attached to tapisrv and/or there
  9299. // was no logged on user to impersonate. So we can just return 0.
  9300. //
  9301. if (!gbInitialized)
  9302. {
  9303. return 0;
  9304. }
  9305. //
  9306. // Set the flag instructing the EventHandlerThread to terminate
  9307. //
  9308. TapiEnterCriticalSection ( &gCriticalSection );
  9309. gEventHandlerThreadParams.bExit = TRUE;
  9310. //
  9311. // If there's a network poll thread running then tell it to exit
  9312. // & wait for it to terminate
  9313. //
  9314. if (ghNetworkPollThread)
  9315. {
  9316. if (ghNptShutdownEvent)
  9317. {
  9318. SetEvent (ghNptShutdownEvent);
  9319. }
  9320. TapiLeaveCriticalSection( &gCriticalSection );
  9321. WaitForSingleObject (ghNetworkPollThread, INFINITE);
  9322. TapiEnterCriticalSection ( &gCriticalSection );
  9323. CloseHandle (ghNetworkPollThread);
  9324. ghNetworkPollThread = NULL;
  9325. }
  9326. TapiLeaveCriticalSection( &gCriticalSection );
  9327. if (gpszThingToPassToServer)
  9328. {
  9329. DrvFree (gpszThingToPassToServer);
  9330. gpszThingToPassToServer = NULL;
  9331. }
  9332. //
  9333. // Tell the event handler thread to exit wait for it to terminate
  9334. //
  9335. while (WaitForSingleObject (gEventHandlerThreadParams.hThread, 0) !=
  9336. WAIT_OBJECT_0)
  9337. {
  9338. SetEvent (gEventHandlerThreadParams.hEvent);
  9339. Sleep (50);
  9340. }
  9341. CloseHandle (gEventHandlerThreadParams.hThread);
  9342. //
  9343. // Send detach to each server
  9344. //
  9345. status = RpcImpersonateClient(0);
  9346. if (status != RPC_S_OK)
  9347. {
  9348. LOG((TL_ERROR, "RpcImpersonateClient failed, err=%d", status));
  9349. // fall thru
  9350. }
  9351. TapiEnterCriticalSection(&gCriticalSection);
  9352. pEntry = gpCurrentInitContext->ServerList.Flink;
  9353. while (pEntry != &gpCurrentInitContext->ServerList)
  9354. {
  9355. DWORD dwRetryCount = 0;
  9356. pServer = CONTAINING_RECORD (pEntry, DRVSERVER, ServerList);
  9357. do
  9358. {
  9359. RpcTryExcept
  9360. {
  9361. ClientDetach (&pServer->phContext);
  9362. dwRetryCount = gdwRetryCount;
  9363. }
  9364. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  9365. {
  9366. if (dwRetryCount++ < gdwRetryCount)
  9367. {
  9368. Sleep (gdwRetryTimeout);
  9369. }
  9370. }
  9371. RpcEndExcept
  9372. } while (dwRetryCount < gdwRetryCount);
  9373. pEntry = pEntry->Flink;
  9374. }
  9375. TapiLeaveCriticalSection(&gCriticalSection);
  9376. RpcRevertToSelf();
  9377. //
  9378. // Wait a period of time for all the expected rundowns to occur.
  9379. // If they all occur then free up context info for this
  9380. // provider initialization instance; otherwise, do a LoadLibrary
  9381. // on ourself (only once) to prevent the possiblity of the
  9382. // rundown routine getting called after the DLL has been unloaded,
  9383. // and insert the current init context in a "stale" queue, removing
  9384. // & freeing the oldest item in the queue if we've reached a
  9385. // pre-determined queue limit
  9386. //
  9387. #define MAX_RSP_WAIT_TIME 2000
  9388. #define RSP_WAIT_INCR 250
  9389. for(
  9390. i = 0;
  9391. ((gpCurrentInitContext->dwNumRundownsExpected != 0) &&
  9392. (i < MAX_RSP_WAIT_TIME));
  9393. i += RSP_WAIT_INCR
  9394. )
  9395. {
  9396. Sleep (RSP_WAIT_INCR);
  9397. }
  9398. if (i < MAX_RSP_WAIT_TIME)
  9399. {
  9400. FreeInitContext (gpCurrentInitContext);
  9401. }
  9402. else
  9403. {
  9404. if (!gbLoadedSelf)
  9405. {
  9406. LoadLibrary (MODULE_NAME);
  9407. gbLoadedSelf = TRUE;
  9408. }
  9409. gpCurrentInitContext->pNextStaleInitContext = gpStaleInitContexts;
  9410. gpStaleInitContexts = gpCurrentInitContext;
  9411. LOG((TL_INFO, "Queued stale init context x%x", gpCurrentInitContext));
  9412. #define RSP_MAX_NUM_STALE_INIT_CONTEXTS 4
  9413. if (gdwNumStaleInitContexts >= RSP_MAX_NUM_STALE_INIT_CONTEXTS)
  9414. {
  9415. PRSP_INIT_CONTEXT pPrevStaleInitContext;
  9416. while (gpCurrentInitContext->pNextStaleInitContext)
  9417. {
  9418. pPrevStaleInitContext = gpCurrentInitContext;
  9419. gpCurrentInitContext =
  9420. gpCurrentInitContext->pNextStaleInitContext;
  9421. }
  9422. pPrevStaleInitContext->pNextStaleInitContext = NULL;
  9423. FreeInitContext (gpCurrentInitContext);
  9424. LOG((TL_INFO, "Freed stale init context x%x", gpCurrentInitContext));
  9425. }
  9426. else
  9427. {
  9428. gdwNumStaleInitContexts++;
  9429. }
  9430. }
  9431. //
  9432. // Unregister out rpc server interface
  9433. //
  9434. status = RpcServerUnregisterIf(
  9435. remotesp_ServerIfHandle, // interface to register
  9436. NULL, // MgrTypeUuid
  9437. TRUE // wait for calls to complete
  9438. );
  9439. LOG((TL_INFO, "RpcServerUnregisterIf ret'd %d", status));
  9440. //
  9441. // Clean up resources
  9442. //
  9443. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  9444. CloseHandle (gEventHandlerThreadParams.hEvent);
  9445. //
  9446. // Note: We intentionally leak the hMailslot for now, because the
  9447. // docs say that the mailslot is not actually destroyed
  9448. // until the process exits. Since service providers can get
  9449. // loaded & unloaded alot without tapisrv.exe ever exiting,
  9450. // we could wind up with alot of mailslots laying around.
  9451. //
  9452. // Closing this hMailSlot to avoid dependance on the registry to
  9453. // remember the hMailSlot.
  9454. //
  9455. if (gEventHandlerThreadParams.hMailslot != INVALID_HANDLE_VALUE)
  9456. {
  9457. CloseHandle (gEventHandlerThreadParams.hMailslot);
  9458. CloseHandle (gEventHandlerThreadParams.hMailslotEvent);
  9459. }
  9460. DrvFree (gEventHandlerThreadParams.pMsgBuffer);
  9461. //
  9462. // Manually walk the handle table, completing any pending async
  9463. // requests with an error. No need to call any post-processing
  9464. // procs, since any calls would've been torn down already, and
  9465. // the other non-MakeCall-style post processing procs simply do
  9466. // CopyMemory, etc.
  9467. //
  9468. // Also, if the gbLoadedSelf flag is set, then we want to deref
  9469. // active handles left in the table, because the table is
  9470. // only freed in DLL_PROCESS_DETACH (which won't get called now)
  9471. // and we don't want to end up leaking handles.
  9472. //
  9473. {
  9474. PHANDLETABLEENTRY pEntry, pEnd;
  9475. PHANDLETABLEHEADER pHeader = ghHandleTable;
  9476. EnterCriticalSection (&pHeader->Lock);
  9477. pEnd = pHeader->Table + pHeader->NumEntries;
  9478. for (pEntry = pHeader->Table; pEntry != pEnd; pEntry++)
  9479. {
  9480. if (pEntry->Handle)
  9481. {
  9482. PASYNCREQUESTCONTEXT pContext = pEntry->Context.C;
  9483. if (pEntry->Context.C2 == (LPVOID) 1)
  9484. {
  9485. DereferenceObject (
  9486. ghHandleTable,
  9487. pEntry->Handle,
  9488. (DWORD)pEntry->ReferenceCount
  9489. );
  9490. }
  9491. else if (pContext == (PASYNCREQUESTCONTEXT) -1 ||
  9492. pContext->dwKey == DRVASYNC_KEY)
  9493. {
  9494. (*gpfnCompletionProc)(
  9495. DWORD_CAST((ULONG_PTR)pEntry->Context.C2,__FILE__,__LINE__),
  9496. LINEERR_OPERATIONFAILED
  9497. );
  9498. if (gbLoadedSelf)
  9499. {
  9500. DereferenceObject(
  9501. ghHandleTable,
  9502. pEntry->Handle,
  9503. (DWORD)pEntry->ReferenceCount
  9504. );
  9505. }
  9506. }
  9507. }
  9508. }
  9509. LeaveCriticalSection (&pHeader->Lock);
  9510. }
  9511. //
  9512. // Free the lookup tables
  9513. //
  9514. while (gpLineLookup)
  9515. {
  9516. PDRVLINELOOKUP pNextLineLookup = gpLineLookup->pNext;
  9517. DrvFree (gpLineLookup);
  9518. gpLineLookup = pNextLineLookup;
  9519. }
  9520. while (gpPhoneLookup)
  9521. {
  9522. PDRVPHONELOOKUP pNextPhoneLookup = gpPhoneLookup->pNext;
  9523. DrvFree (gpPhoneLookup);
  9524. gpPhoneLookup = pNextPhoneLookup;
  9525. }
  9526. TRACELOGDEREGISTER();
  9527. return 0;
  9528. }
  9529. LONG
  9530. TSPIAPI
  9531. TSPI_providerUIIdentify(
  9532. LPWSTR lpszUIDLLName
  9533. )
  9534. {
  9535. LONG lResult;
  9536. PDRVSERVER pServer = NULL;
  9537. LPDWORD lpdwHold = (LPDWORD) lpszUIDLLName;
  9538. // we've put a special case into tapisrv to give this addtional info
  9539. // to remotesp. the buffer passed in is in the following
  9540. // format
  9541. // DWORD dwKey == RSP_MSG tells us that TAPISRV did fill in this info
  9542. // DWORD dwDeviceID == device ID of whatever
  9543. // DWORD dwType == TUISPIDLL_ type
  9544. // this way, remotesp can intelligently rpc over to the
  9545. // telephony server.
  9546. BOOL bOK = (lpdwHold[0] == RSP_MSG);
  9547. DWORD dwDeviceID = (bOK ? lpdwHold[1] : 0);
  9548. DWORD dwType = (bOK ? lpdwHold[2] : TUISPIDLL_OBJECT_LINEID);
  9549. // we're being asked for the ui dll name
  9550. // we will return remotesp, but at this point we'll try to find out the
  9551. // real ui dll
  9552. // note that we only only one service provider here, but we may be able
  9553. // to add support for additonal ones by saving the ui dll name on
  9554. // a per provider basis
  9555. REMOTE_ARG_TYPES argTypes[] =
  9556. {
  9557. LineID,
  9558. Dword,
  9559. lpGet_SizeToFollow,
  9560. Size
  9561. };
  9562. ULONG_PTR args[] =
  9563. {
  9564. (ULONG_PTR) dwDeviceID,
  9565. (ULONG_PTR) dwType,
  9566. (ULONG_PTR) gszRealSPUIDLL,
  9567. (ULONG_PTR) MAX_PATH
  9568. };
  9569. REMOTE_FUNC_ARGS funcArgs =
  9570. {
  9571. MAKELONG (LINE_FUNC | SYNC | 4, xGetUIDllName),
  9572. args,
  9573. argTypes
  9574. };
  9575. if (bOK)
  9576. {
  9577. // need to get the server first
  9578. if (dwType == TUISPIDLL_OBJECT_LINEID)
  9579. {
  9580. if (gpLineLookup)
  9581. {
  9582. PDRVLINE pLine;
  9583. if ((pLine = GetLineFromID (dwDeviceID)))
  9584. {
  9585. pServer = pLine->pServer;
  9586. }
  9587. }
  9588. }
  9589. else if (dwType == TUISPIDLL_OBJECT_LINEID)
  9590. {
  9591. argTypes[0] = PhoneID;
  9592. if (gpPhoneLookup)
  9593. {
  9594. PDRVPHONE pPhone;
  9595. if ((pPhone = GetPhoneFromID (dwDeviceID)))
  9596. {
  9597. pServer = pPhone->pServer;
  9598. }
  9599. }
  9600. }
  9601. else
  9602. {
  9603. }
  9604. // call over.
  9605. // in the case of the telephony cpl, pLine has not been initialized yet,
  9606. // so we have to do this check. in that case, we won't have a
  9607. // gszuidllname, but it's OK since the cpl only calls provider UI functions
  9608. // which remotesp can handle by itself.
  9609. if (pServer)
  9610. {
  9611. LOG((TL_INFO, "Calling GetUIDllName in server"));
  9612. lResult = REMOTEDOFUNC (&funcArgs, "GetUIDllName");
  9613. }
  9614. }
  9615. // always return remotesp
  9616. wcscpy(lpszUIDLLName, L"remotesp.tsp");
  9617. return 0;
  9618. }
  9619. HINSTANCE
  9620. TAPILoadLibraryW(
  9621. PWSTR pLibrary
  9622. )
  9623. {
  9624. PSTR pszTempString;
  9625. HINSTANCE hResult;
  9626. DWORD dwSize;
  9627. dwSize = WideCharToMultiByte(
  9628. GetACP(),
  9629. 0,
  9630. pLibrary,
  9631. -1,
  9632. NULL,
  9633. 0,
  9634. NULL,
  9635. NULL
  9636. );
  9637. if ( NULL == (pszTempString = LocalAlloc( LPTR, dwSize )) )
  9638. {
  9639. LOG((TL_ERROR, "Alloc failed - LoadLibW - 0x%08lx", dwSize));
  9640. return NULL;
  9641. }
  9642. WideCharToMultiByte(
  9643. GetACP(),
  9644. 0,
  9645. pLibrary,
  9646. dwSize,
  9647. pszTempString,
  9648. dwSize,
  9649. NULL,
  9650. NULL
  9651. );
  9652. hResult = LoadLibrary (pszTempString);
  9653. LocalFree (pszTempString);
  9654. return hResult;
  9655. }
  9656. //
  9657. // ---------------------------- TUISPI_xxx funcs ------------------------------
  9658. //
  9659. LONG
  9660. LoadUIDll(
  9661. DWORD dwDeviceID,
  9662. DWORD dwDeviceType,
  9663. HANDLE *phDll,
  9664. CHAR *pszTUISPI_xxx,
  9665. TUISPIPROC *ppfnTUISPI_xxx,
  9666. TUISPIDLLCALLBACK lpfnUIDLLCallback
  9667. )
  9668. {
  9669. //
  9670. // At this point, remotesp is loaded as a ui dll in tapi32.dll's
  9671. // (& the client's) context, so we have none of the global info
  9672. // normally available. Use the ui callback to call into the
  9673. // other instance of remotesp to get the real ui dll name.
  9674. //
  9675. // Note we only handle on sp here, but can easily add in more
  9676. // info when we handle more than one
  9677. //
  9678. LPDWORD lpBuffer;
  9679. if (!(lpBuffer = DrvAlloc (MAX_PATH + 2 * sizeof (DWORD))))
  9680. {
  9681. return (dwDeviceType == TUISPIDLL_OBJECT_PHONEID ?
  9682. PHONEERR_NOMEM : LINEERR_NOMEM);
  9683. }
  9684. // format is
  9685. // DWORD dwKey
  9686. // DWORD dwMsgType
  9687. // LPWSTR szUIDLLName (returned)
  9688. lpBuffer[0] = RSP_MSG;
  9689. lpBuffer[1] = RSP_MSG_UIID;
  9690. lpfnUIDLLCallback(
  9691. dwDeviceID,
  9692. dwDeviceType,
  9693. lpBuffer,
  9694. MAX_PATH + 2 * sizeof (DWORD)
  9695. );
  9696. *phDll = TAPILoadLibraryW((LPWSTR)(lpBuffer + 2));
  9697. DrvFree (lpBuffer);
  9698. if (!*phDll)
  9699. {
  9700. LOG((TL_ERROR, "LoadLibrary failed in the LoadUIDll"));
  9701. return (dwDeviceType == TUISPIDLL_OBJECT_PHONEID ?
  9702. PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
  9703. }
  9704. if (!(*ppfnTUISPI_xxx = (TUISPIPROC) GetProcAddress(
  9705. *phDll,
  9706. pszTUISPI_xxx
  9707. )))
  9708. {
  9709. LOG((TL_ERROR, "GetProcAddress failed on LoadUIDll"));
  9710. FreeLibrary(*phDll);
  9711. return (dwDeviceType == TUISPIDLL_OBJECT_PHONEID ?
  9712. PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
  9713. }
  9714. return 0;
  9715. }
  9716. LONG
  9717. TSPIAPI
  9718. TUISPI_lineConfigDialog(
  9719. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  9720. DWORD dwDeviceID,
  9721. HWND hwndOwner,
  9722. LPCWSTR lpszDeviceClass
  9723. )
  9724. {
  9725. TUISPIPROC pfnTUISPI_lineConfigDialog;
  9726. HANDLE hDll;
  9727. LONG lResult;
  9728. lResult = LoadUIDll(
  9729. dwDeviceID,
  9730. TUISPIDLL_OBJECT_LINEID,
  9731. &hDll,
  9732. "TUISPI_lineConfigDialog",
  9733. &pfnTUISPI_lineConfigDialog,
  9734. lpfnUIDLLCallback
  9735. );
  9736. if (lResult)
  9737. {
  9738. return lResult;
  9739. }
  9740. LOG((TL_INFO, "Calling TUISPI_lineConfigDialog"));
  9741. lResult = (*pfnTUISPI_lineConfigDialog)(
  9742. lpfnUIDLLCallback,
  9743. dwDeviceID,
  9744. hwndOwner,
  9745. lpszDeviceClass
  9746. );
  9747. FreeLibrary (hDll);
  9748. return lResult;
  9749. }
  9750. LONG
  9751. TSPIAPI
  9752. TUISPI_lineConfigDialogEdit(
  9753. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  9754. DWORD dwDeviceID,
  9755. HWND hwndOwner,
  9756. LPCWSTR lpszDeviceClass,
  9757. LPVOID const lpDeviceConfigIn,
  9758. DWORD dwSize,
  9759. LPVARSTRING lpDeviceConfigOut
  9760. )
  9761. {
  9762. TUISPIPROC pfnTUISPI_lineConfigDialogEdit;
  9763. HANDLE hDll;
  9764. LONG lResult;
  9765. lResult = LoadUIDll(
  9766. dwDeviceID,
  9767. TUISPIDLL_OBJECT_LINEID,
  9768. &hDll,
  9769. "TUISPI_lineConfigDialogEdit",
  9770. &pfnTUISPI_lineConfigDialogEdit,
  9771. lpfnUIDLLCallback
  9772. );
  9773. if (lResult)
  9774. {
  9775. return lResult;
  9776. }
  9777. LOG((TL_INFO, "Calling TUISPI_lineConfigDialogEdit"));
  9778. lResult = (*pfnTUISPI_lineConfigDialogEdit)(
  9779. lpfnUIDLLCallback,
  9780. dwDeviceID,
  9781. hwndOwner,
  9782. lpszDeviceClass,
  9783. lpDeviceConfigIn,
  9784. dwSize,
  9785. lpDeviceConfigOut
  9786. );
  9787. FreeLibrary(hDll);
  9788. return lResult;
  9789. }
  9790. LONG
  9791. TSPIAPI
  9792. TUISPI_phoneConfigDialog(
  9793. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  9794. DWORD dwDeviceID,
  9795. HWND hwndOwner,
  9796. LPCWSTR lpszDeviceClass
  9797. )
  9798. {
  9799. TUISPIPROC pfnTUISPI_phoneConfigDialog;
  9800. HANDLE hDll;
  9801. LONG lResult;
  9802. lResult = LoadUIDll(
  9803. dwDeviceID,
  9804. TUISPIDLL_OBJECT_PHONEID,
  9805. &hDll,
  9806. "TUISPI_phoneConfigDialog",
  9807. &pfnTUISPI_phoneConfigDialog,
  9808. lpfnUIDLLCallback
  9809. );
  9810. if (lResult)
  9811. {
  9812. return lResult;
  9813. }
  9814. LOG((TL_INFO, "Calling TUISPI_phoneConfigDialog"));
  9815. lResult = (*pfnTUISPI_phoneConfigDialog)(
  9816. lpfnUIDLLCallback,
  9817. dwDeviceID,
  9818. hwndOwner,
  9819. lpszDeviceClass
  9820. );
  9821. FreeLibrary(hDll);
  9822. return lResult;
  9823. }
  9824. LONG
  9825. TSPIAPI
  9826. TUISPI_providerConfig(
  9827. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  9828. HWND hwndOwner,
  9829. DWORD dwPermanentProviderID
  9830. )
  9831. {
  9832. return LINEERR_OPERATIONFAILED;
  9833. /*
  9834. DialogBoxParam(
  9835. ghInst,
  9836. MAKEINTRESOURCE(IDD_REMOTESPCONFIG),
  9837. hwndOwner,
  9838. ConfiglgProc,
  9839. (LPARAM) dwPermanentProviderID
  9840. );
  9841. return 0;
  9842. */
  9843. }
  9844. /*
  9845. LONG
  9846. TSPIAPI
  9847. TUISPI_providerGenericDialog(
  9848. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  9849. HTAPIDIALOGINSTANCE htDlgInst,
  9850. LPVOID lpParams,
  9851. DWORD dwSize,
  9852. HANDLE hEvent
  9853. )
  9854. {
  9855. TUISPIPROC pfnTUISPI_providerGenericDialog;
  9856. HANDLE hDll;
  9857. LONG lResult;
  9858. lResult = LoadUIDll(
  9859. (HWND) 0,
  9860. 0, // hardcode 0
  9861. TUISPIDLL_OBJECT_LINEID,
  9862. &hDll,
  9863. "TUISPI_providerGenericDialog",
  9864. &pfnTUISPI_providerGenericDialog
  9865. );
  9866. if (lResult == 0)
  9867. {
  9868. LOG((TL_INFO, "Calling TUISPI_providerGenericDialog"));
  9869. lResult = (*pfnTUISPI_providerGenericDialog)(
  9870. lpfnUIDLLCallback,
  9871. htDlgInst,
  9872. lpParams,
  9873. dwSize,
  9874. hEvent
  9875. );
  9876. FreeLibrary(hDll);
  9877. }
  9878. else
  9879. {
  9880. LOG((TL_ERROR, "Failed to load UI DLL"));
  9881. }
  9882. return lResult;
  9883. }
  9884. LONG
  9885. TSPIAPI
  9886. TUISPI_providerGenericDialogData(
  9887. HTAPIDIALOGINSTANCE htDlgInst,
  9888. LPVOID lpParams,
  9889. DWORD dwSize
  9890. )
  9891. {
  9892. TUISPIPROC pfnTUISPI_providerGenericDialogData;
  9893. HANDLE hDll;
  9894. LONG lResult;
  9895. DBGOUT((
  9896. 3,
  9897. "TUISPI_providerGenericDialogData: enter (lpParams=x%x, dwSize=x%x)",
  9898. lpParams,
  9899. dwSize
  9900. ));
  9901. lResult = LoadUIDll(
  9902. (HWND) 0,
  9903. 0,
  9904. TUISPIDLL_OBJECT_LINEID,
  9905. &hDll,
  9906. "TUISPI_providerGenericDialogData",
  9907. &pfnTUISPI_providerGenericDialogData
  9908. );
  9909. if (lResult == 0)
  9910. {
  9911. LOG((TL_INFO, "Calling TUISPI_providerGenericDialogData"));
  9912. lResult = (*pfnTUISPI_providerGenericDialogData)(
  9913. htDlgInst,
  9914. lpParams,
  9915. dwSize
  9916. );
  9917. FreeLibrary(hDll);
  9918. }
  9919. else
  9920. {
  9921. LOG((TL_ERROR, "Failed to load UI DLL"));
  9922. }
  9923. return lResult;
  9924. }
  9925. */
  9926. //
  9927. // GetRSPID
  9928. // To return the provider ID of remotesp if any. Otherwise
  9929. // return zero
  9930. //
  9931. DWORD
  9932. GetRSPID (
  9933. )
  9934. {
  9935. DWORD dwRet = 0;
  9936. LONG (WINAPI *pfnGetProviderList)();
  9937. DWORD dwTotalSize, i;
  9938. HINSTANCE hTapi32 = NULL;
  9939. LPLINEPROVIDERLIST pProviderList = NULL;
  9940. LPLINEPROVIDERENTRY pProviderEntry;
  9941. //
  9942. // Load Tapi32.dll & get a pointer to the lineGetProviderList
  9943. // func. We could just statically link with Tapi32.lib and
  9944. // avoid the hassle (and this wouldn't have any adverse
  9945. // performance effects because of the fact that this
  9946. // implementation has a separate ui dll that runs only on the
  9947. // client context), but a provider who implemented these funcs
  9948. // in it's TSP module would want to do an explicit load like
  9949. // we do here to prevent the performance hit of Tapi32.dll
  9950. // always getting loaded in Tapisrv.exe's context.
  9951. //
  9952. if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
  9953. {
  9954. LOG((TL_ERROR,
  9955. "LoadLibrary(tapi32.dll) failed, err=%d",
  9956. GetLastError()
  9957. ));
  9958. goto ExitHere;
  9959. }
  9960. if (!((FARPROC) pfnGetProviderList = GetProcAddress(
  9961. hTapi32,
  9962. (LPCSTR) "lineGetProviderList"
  9963. )))
  9964. {
  9965. LOG((TL_ERROR,
  9966. "GetProcAddr(lineGetProviderList) failed, err=%d",
  9967. GetLastError()
  9968. ));
  9969. goto ExitHere;
  9970. }
  9971. //
  9972. // Loop until we get the full provider list
  9973. //
  9974. dwTotalSize = sizeof (LINEPROVIDERLIST);
  9975. while (1)
  9976. {
  9977. if (!(pProviderList = DrvAlloc (dwTotalSize)))
  9978. {
  9979. goto ExitHere;
  9980. }
  9981. pProviderList->dwTotalSize = dwTotalSize;
  9982. if (((*pfnGetProviderList)(0x00020000, pProviderList)) != 0)
  9983. {
  9984. goto ExitHere;
  9985. }
  9986. if (pProviderList->dwNeededSize > pProviderList->dwTotalSize)
  9987. {
  9988. dwTotalSize = pProviderList->dwNeededSize;
  9989. DrvFree (pProviderList);
  9990. }
  9991. else
  9992. {
  9993. break;
  9994. }
  9995. }
  9996. //
  9997. // Inspect the provider list entries to see if this provider
  9998. // is already installed
  9999. //
  10000. pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
  10001. pProviderList->dwProviderListOffset);
  10002. for (i = 0; i < pProviderList->dwNumProviders; i++)
  10003. {
  10004. char *pszInstalledProviderName = ((char *) pProviderList) +
  10005. pProviderEntry->dwProviderFilenameOffset,
  10006. *psz;
  10007. if ((psz = strrchr (pszInstalledProviderName, '\\')))
  10008. {
  10009. pszInstalledProviderName = psz + 1;
  10010. }
  10011. if (lstrcmpi (pszInstalledProviderName, "remotesp.tsp") == 0)
  10012. {
  10013. dwRet = pProviderEntry->dwPermanentProviderID;
  10014. goto ExitHere;
  10015. }
  10016. pProviderEntry++;
  10017. }
  10018. ExitHere:
  10019. if (hTapi32)
  10020. {
  10021. FreeLibrary (hTapi32);
  10022. }
  10023. if (pProviderList)
  10024. {
  10025. DrvFree (pProviderList);
  10026. }
  10027. return dwRet;
  10028. }
  10029. LONG
  10030. TSPIAPI
  10031. TUISPI_providerInstall(
  10032. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  10033. HWND hwndOwner,
  10034. DWORD dwPermanentProviderID
  10035. )
  10036. {
  10037. if (GetRSPID())
  10038. {
  10039. // Return failure if it is already installed
  10040. // to prevent duplication
  10041. return TAPIERR_PROVIDERALREADYINSTALLED;
  10042. }
  10043. else
  10044. {
  10045. return S_OK;
  10046. }
  10047. }
  10048. LONG
  10049. TSPIAPI
  10050. TUISPI_providerRemove(
  10051. TUISPIDLLCALLBACK lpfnUIDLLCallback,
  10052. HWND hwndOwner,
  10053. DWORD dwPermanentProviderID
  10054. )
  10055. {
  10056. DWORD dwProviderID = GetRSPID();
  10057. LONG lResult = S_OK;
  10058. char buf[32];
  10059. HKEY hTelephonyKey;
  10060. if (dwProviderID == 0 || dwProviderID != dwPermanentProviderID)
  10061. {
  10062. // return failure if remotesp is not installed
  10063. lResult = LINEERR_OPERATIONFAILED;
  10064. goto ExitHere;
  10065. }
  10066. //
  10067. // Clean up our ProviderN section
  10068. //
  10069. wsprintf (buf, "Provider%d", dwPermanentProviderID);
  10070. if (RegOpenKeyExA(
  10071. HKEY_LOCAL_MACHINE,
  10072. gszTelephonyKey,
  10073. 0,
  10074. KEY_ALL_ACCESS,
  10075. &hTelephonyKey
  10076. ) == ERROR_SUCCESS)
  10077. {
  10078. SHDeleteKey (hTelephonyKey, buf);
  10079. RegCloseKey (hTelephonyKey);
  10080. }
  10081. else
  10082. {
  10083. lResult = LINEERR_OPERATIONFAILED;
  10084. }
  10085. ExitHere:
  10086. return lResult;
  10087. }
  10088. //
  10089. // ------------------------ Private support routines --------------------------
  10090. //
  10091. #if DBG
  10092. VOID
  10093. DbgPrt(
  10094. IN DWORD dwDbgLevel,
  10095. IN PUCHAR lpszFormat,
  10096. IN ...
  10097. )
  10098. /*++
  10099. Routine Description:
  10100. Formats the incoming debug message & calls DbgPrint
  10101. Arguments:
  10102. DbgLevel - level of message verboseness
  10103. DbgMessage - printf-style format string, followed by appropriate
  10104. list of arguments
  10105. Return Value:
  10106. --*/
  10107. {
  10108. if (dwDbgLevel <= gdwDebugLevel)
  10109. {
  10110. char buf[128] = "REMOTESP: ";
  10111. va_list ap;
  10112. va_start(ap, lpszFormat);
  10113. wvsprintf (&buf[10], lpszFormat, ap);
  10114. lstrcatA (buf, "\n");
  10115. OutputDebugStringA (buf);
  10116. va_end(ap);
  10117. }
  10118. }
  10119. #endif
  10120. LONG
  10121. AddLine(
  10122. PDRVSERVER pServer,
  10123. DWORD dwLocalID,
  10124. DWORD dwServerID,
  10125. BOOL bInit,
  10126. BOOL bNegotiate,
  10127. DWORD dwAPIVersion,
  10128. LPLINEEXTENSIONID pExtID
  10129. )
  10130. {
  10131. PDRVLINE pLine;
  10132. PDRVLINELOOKUP pLineLookup;
  10133. LONG lResult = 0;
  10134. BOOL bLeaveCriticalSection = FALSE;
  10135. LINEDEVCAPS lineDevCaps;
  10136. DWORD dwPermLineID;
  10137. int iEntry;
  10138. //
  10139. // Get the permanent line device ID
  10140. //
  10141. static REMOTE_ARG_TYPES argTypes[] =
  10142. {
  10143. lpServer,
  10144. Dword,
  10145. Dword,
  10146. Dword,
  10147. Dword,
  10148. lpGet_Struct
  10149. };
  10150. ULONG_PTR args[] =
  10151. {
  10152. (ULONG_PTR) pServer,
  10153. (ULONG_PTR) pServer->hLineApp,
  10154. (ULONG_PTR) dwServerID,
  10155. (ULONG_PTR) (dwAPIVersion?dwAPIVersion:TAPI_VERSION1_0),
  10156. (ULONG_PTR) 0,
  10157. (ULONG_PTR) &lineDevCaps
  10158. };
  10159. REMOTE_FUNC_ARGS funcArgs =
  10160. {
  10161. MAKELONG (LINE_FUNC | SYNC | 6, lGetDevCaps),
  10162. args,
  10163. argTypes
  10164. };
  10165. lineDevCaps.dwTotalSize = sizeof(LINEDEVCAPS);
  10166. lResult = REMOTEDOFUNC(&funcArgs, "lineGetDevCaps");
  10167. if (lResult != 0)
  10168. {
  10169. goto ExitHere;
  10170. }
  10171. dwPermLineID = lineDevCaps.dwPermanentLineID;
  10172. TapiEnterCriticalSection(&gCriticalSection);
  10173. bLeaveCriticalSection = TRUE;
  10174. if (!gpLineLookup)
  10175. {
  10176. if (!(gpLineLookup = DrvAlloc(
  10177. sizeof(DRVLINELOOKUP) +
  10178. (DEF_NUM_LINE_ENTRIES-1) * sizeof (DRVLINE)
  10179. )))
  10180. {
  10181. lResult = LINEERR_NOMEM;
  10182. goto ExitHere;
  10183. }
  10184. gpLineLookup->dwTotalEntries = DEF_NUM_LINE_ENTRIES;
  10185. }
  10186. pLineLookup = gpLineLookup;
  10187. //
  10188. // Check if the line is already in based on the permanent ID
  10189. //
  10190. if (!bInit)
  10191. {
  10192. while (pLineLookup)
  10193. {
  10194. pLine = pLineLookup->aEntries;
  10195. for (iEntry = 0;
  10196. iEntry < (int)pLineLookup->dwUsedEntries;
  10197. ++iEntry, ++pLine)
  10198. {
  10199. if ((pLine->dwPermanentLineID == dwPermLineID) &&
  10200. (pLine->pServer->hTapSrv == pServer->hTapSrv))
  10201. {
  10202. //
  10203. // if dwDeviceIDServer == (-1), it was removed earlier
  10204. // put it back, otherwise fail the operation
  10205. //
  10206. if (pLine->dwDeviceIDServer == 0xffffffff)
  10207. {
  10208. pLine->dwDeviceIDServer = dwServerID;
  10209. pLine->dwDeviceIDLocal = dwLocalID;
  10210. }
  10211. else
  10212. {
  10213. lResult = LINEERR_INUSE;
  10214. }
  10215. goto ExitHere;
  10216. }
  10217. }
  10218. pLineLookup = pLineLookup->pNext;
  10219. }
  10220. }
  10221. pLineLookup = gpLineLookup;
  10222. while (pLineLookup->pNext)
  10223. {
  10224. pLineLookup = pLineLookup->pNext;
  10225. }
  10226. if (pLineLookup->dwUsedEntries == pLineLookup->dwTotalEntries)
  10227. {
  10228. PDRVLINELOOKUP pNewLineLookup;
  10229. if (!(pNewLineLookup = DrvAlloc(
  10230. sizeof(DRVLINELOOKUP) +
  10231. (2 * pLineLookup->dwTotalEntries - 1) * sizeof(DRVLINE)
  10232. )))
  10233. {
  10234. lResult = LINEERR_NOMEM;
  10235. goto ExitHere;
  10236. }
  10237. pNewLineLookup->dwTotalEntries = 2 * pLineLookup->dwTotalEntries;
  10238. if (bInit)
  10239. {
  10240. pNewLineLookup->dwUsedEntries = pLineLookup->dwTotalEntries;
  10241. CopyMemory(
  10242. pNewLineLookup->aEntries,
  10243. pLineLookup->aEntries,
  10244. pLineLookup->dwTotalEntries * sizeof (DRVLINE)
  10245. );
  10246. DrvFree (pLineLookup);
  10247. gpLineLookup = pNewLineLookup;
  10248. }
  10249. else
  10250. {
  10251. pLineLookup->pNext = pNewLineLookup;
  10252. }
  10253. pLineLookup = pNewLineLookup;
  10254. //
  10255. // Fix the hDeviceCallback in PDRVLINE
  10256. //
  10257. pLine = pLineLookup->aEntries;
  10258. for (iEntry = 0; iEntry < (int)pLineLookup->dwUsedEntries; ++iEntry)
  10259. {
  10260. if (pLine->hDeviceCallback)
  10261. {
  10262. DereferenceObject (
  10263. ghHandleTable,
  10264. pLine->hDeviceCallback,
  10265. 1
  10266. );
  10267. pLine->hDeviceCallback = (DWORD) NewObject (
  10268. ghHandleTable,
  10269. pLine,
  10270. (LPVOID) 1
  10271. );
  10272. }
  10273. }
  10274. }
  10275. pLine = pLineLookup->aEntries + pLineLookup->dwUsedEntries;
  10276. pLine->pServer = pServer;
  10277. pLine->dwDeviceIDLocal = dwLocalID;
  10278. pLine->dwDeviceIDServer = dwServerID;
  10279. pLine->dwPermanentLineID = dwPermLineID;
  10280. if (bInit)
  10281. {
  10282. gdwInitialNumLineDevices++;
  10283. }
  10284. pLineLookup->dwUsedEntries++;
  10285. //
  10286. // Negotiate the API/SPI version
  10287. //
  10288. if (bNegotiate)
  10289. {
  10290. if (dwAPIVersion)
  10291. {
  10292. pLine->dwXPIVersion = dwAPIVersion;
  10293. CopyMemory (&pLine->ExtensionID, pExtID, sizeof (*pExtID));
  10294. }
  10295. else
  10296. {
  10297. static REMOTE_ARG_TYPES argTypes[] =
  10298. {
  10299. Dword,
  10300. LineID,
  10301. Dword,
  10302. Dword,
  10303. lpDword,
  10304. lpGet_SizeToFollow,
  10305. Size
  10306. };
  10307. ULONG_PTR args[] =
  10308. {
  10309. (ULONG_PTR) pServer->hLineApp,
  10310. (ULONG_PTR) dwLocalID, // dwServerID,
  10311. (ULONG_PTR) TAPI_VERSION1_0,
  10312. (ULONG_PTR) TAPI_VERSION_CURRENT,
  10313. (ULONG_PTR) &pLine->dwXPIVersion,
  10314. (ULONG_PTR) &pLine->ExtensionID,
  10315. (ULONG_PTR) sizeof (LINEEXTENSIONID)
  10316. };
  10317. REMOTE_FUNC_ARGS funcArgs =
  10318. {
  10319. MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
  10320. args,
  10321. argTypes
  10322. };
  10323. REMOTEDOFUNC (&funcArgs, "lineNegotiateAPIVersion");
  10324. }
  10325. }
  10326. ExitHere:
  10327. if (bLeaveCriticalSection)
  10328. {
  10329. TapiLeaveCriticalSection(&gCriticalSection);
  10330. }
  10331. return lResult;
  10332. }
  10333. LONG
  10334. AddPhone(
  10335. PDRVSERVER pServer,
  10336. DWORD dwDeviceIDLocal,
  10337. DWORD dwDeviceIDServer,
  10338. BOOL bInit,
  10339. BOOL bNegotiate,
  10340. DWORD dwAPIVersion,
  10341. LPPHONEEXTENSIONID pExtID
  10342. )
  10343. {
  10344. PDRVPHONE pPhone;
  10345. PDRVPHONELOOKUP pPhoneLookup;
  10346. LONG lResult = 0;
  10347. BOOL bLeaveCriticalSection = FALSE;
  10348. PHONECAPS phoneDevCaps;
  10349. DWORD dwPermPhoneID;
  10350. int iEntry;
  10351. //
  10352. // Get the permanent phone device ID
  10353. //
  10354. static REMOTE_ARG_TYPES argTypes[] =
  10355. {
  10356. lpServer,
  10357. Dword,
  10358. Dword,
  10359. Dword,
  10360. Dword,
  10361. lpGet_Struct
  10362. };
  10363. ULONG_PTR args[] =
  10364. {
  10365. (ULONG_PTR) pServer,
  10366. (ULONG_PTR) pServer->hPhoneApp,
  10367. (ULONG_PTR) dwDeviceIDServer,
  10368. (ULONG_PTR) (dwAPIVersion?dwAPIVersion:TAPI_VERSION1_0),
  10369. (ULONG_PTR) 0,
  10370. (ULONG_PTR) &phoneDevCaps
  10371. };
  10372. REMOTE_FUNC_ARGS funcArgs =
  10373. {
  10374. MAKELONG (PHONE_FUNC | SYNC | 6, pGetDevCaps),
  10375. args,
  10376. argTypes
  10377. };
  10378. phoneDevCaps.dwTotalSize = sizeof(PHONECAPS);
  10379. lResult = REMOTEDOFUNC (&funcArgs, "phoneGetDevCaps");
  10380. if (lResult != 0)
  10381. {
  10382. goto ExitHere;
  10383. }
  10384. dwPermPhoneID = phoneDevCaps.dwPermanentPhoneID;
  10385. TapiEnterCriticalSection(&gCriticalSection);
  10386. bLeaveCriticalSection = TRUE;
  10387. if (!gpPhoneLookup)
  10388. {
  10389. if (!(gpPhoneLookup = DrvAlloc(
  10390. sizeof(DRVPHONELOOKUP) +
  10391. (DEF_NUM_PHONE_ENTRIES-1) * sizeof (DRVPHONE)
  10392. )))
  10393. {
  10394. lResult = (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
  10395. goto ExitHere;
  10396. }
  10397. gpPhoneLookup->dwTotalEntries = DEF_NUM_PHONE_ENTRIES;
  10398. }
  10399. //
  10400. // Check if the phone device is already in based on the permanent ID
  10401. //
  10402. if (!bInit)
  10403. {
  10404. pPhoneLookup = gpPhoneLookup;
  10405. while (pPhoneLookup)
  10406. {
  10407. pPhone = pPhoneLookup->aEntries;
  10408. for (iEntry = 0;
  10409. iEntry < (int)pPhoneLookup->dwUsedEntries;
  10410. ++iEntry, ++pPhone)
  10411. {
  10412. if ((pPhone->dwPermanentPhoneID == dwPermPhoneID) &&
  10413. (pPhone->pServer->hTapSrv == pServer->hTapSrv))
  10414. {
  10415. //
  10416. // if dwDeviceIDServer == (-1), it was removed earlier
  10417. // put it back, otherwise fail the operation
  10418. //
  10419. if (pPhone->dwDeviceIDServer == 0xffffffff)
  10420. {
  10421. pPhone->dwDeviceIDServer = dwDeviceIDServer;
  10422. pPhone->dwDeviceIDLocal = dwDeviceIDLocal;
  10423. }
  10424. else
  10425. {
  10426. lResult = PHONEERR_INUSE;
  10427. }
  10428. goto ExitHere;
  10429. }
  10430. }
  10431. pPhoneLookup = pPhoneLookup->pNext;
  10432. }
  10433. }
  10434. pPhoneLookup = gpPhoneLookup;
  10435. while (pPhoneLookup->pNext)
  10436. {
  10437. pPhoneLookup = pPhoneLookup->pNext;
  10438. }
  10439. if (pPhoneLookup->dwUsedEntries == pPhoneLookup->dwTotalEntries)
  10440. {
  10441. PDRVPHONELOOKUP pNewPhoneLookup;
  10442. if (!(pNewPhoneLookup = DrvAlloc(
  10443. sizeof(DRVPHONELOOKUP) +
  10444. (2 * pPhoneLookup->dwTotalEntries - 1) * sizeof(DRVPHONE)
  10445. )))
  10446. {
  10447. lResult = (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
  10448. goto ExitHere;
  10449. }
  10450. pNewPhoneLookup->dwTotalEntries = 2 * pPhoneLookup->dwTotalEntries;
  10451. if (bInit)
  10452. {
  10453. pNewPhoneLookup->dwUsedEntries = pPhoneLookup->dwTotalEntries;
  10454. CopyMemory(
  10455. pNewPhoneLookup->aEntries,
  10456. pPhoneLookup->aEntries,
  10457. pPhoneLookup->dwTotalEntries * sizeof (DRVPHONE)
  10458. );
  10459. DrvFree (pPhoneLookup);
  10460. gpPhoneLookup = pNewPhoneLookup;
  10461. }
  10462. else
  10463. {
  10464. pPhoneLookup->pNext = pNewPhoneLookup;
  10465. }
  10466. pPhoneLookup = pNewPhoneLookup;
  10467. //
  10468. // Fix the hDeviceCallback in PDRVPHONE
  10469. //
  10470. pPhone = pPhoneLookup->aEntries;
  10471. for (iEntry = 0; iEntry < (int) pPhoneLookup->dwUsedEntries; ++iEntry)
  10472. {
  10473. if (pPhone->hDeviceCallback)
  10474. {
  10475. DereferenceObject (
  10476. ghHandleTable,
  10477. pPhone->hDeviceCallback,
  10478. 1
  10479. );
  10480. pPhone->hDeviceCallback = (DWORD) NewObject (
  10481. ghHandleTable,
  10482. pPhone,
  10483. (LPVOID) 1
  10484. );
  10485. }
  10486. }
  10487. }
  10488. pPhone = pPhoneLookup->aEntries + pPhoneLookup->dwUsedEntries;
  10489. pPhone->pServer = pServer;
  10490. pPhone->dwDeviceIDLocal = dwDeviceIDLocal;
  10491. pPhone->dwDeviceIDServer = dwDeviceIDServer;
  10492. pPhone->dwPermanentPhoneID = dwPermPhoneID;
  10493. if (bInit)
  10494. {
  10495. gdwInitialNumPhoneDevices++;
  10496. }
  10497. pPhoneLookup->dwUsedEntries++;
  10498. //
  10499. // Negotiate the API/SPI version
  10500. //
  10501. if (bNegotiate)
  10502. {
  10503. if (dwAPIVersion)
  10504. {
  10505. pPhone->dwXPIVersion = dwAPIVersion;
  10506. CopyMemory (&pPhone->ExtensionID, pExtID, sizeof (*pExtID));
  10507. }
  10508. else
  10509. {
  10510. static REMOTE_ARG_TYPES argTypes[] =
  10511. {
  10512. Dword,
  10513. PhoneID,
  10514. Dword,
  10515. Dword,
  10516. lpDword,
  10517. lpGet_SizeToFollow,
  10518. Size
  10519. };
  10520. ULONG_PTR args[] =
  10521. {
  10522. (ULONG_PTR) pServer->hPhoneApp,
  10523. (ULONG_PTR) dwDeviceIDLocal,
  10524. (ULONG_PTR) TAPI_VERSION1_0,
  10525. (ULONG_PTR) TAPI_VERSION_CURRENT,
  10526. (ULONG_PTR) &pPhone->dwXPIVersion,
  10527. (ULONG_PTR) &pPhone->ExtensionID,
  10528. (ULONG_PTR) sizeof (PHONEEXTENSIONID),
  10529. };
  10530. REMOTE_FUNC_ARGS funcArgs =
  10531. {
  10532. MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
  10533. args,
  10534. argTypes
  10535. };
  10536. TapiLeaveCriticalSection(&gCriticalSection);
  10537. bLeaveCriticalSection = FALSE;
  10538. REMOTEDOFUNC (&funcArgs, "phoneNegotiateAPIVersion");
  10539. }
  10540. }
  10541. ExitHere:
  10542. if (bLeaveCriticalSection)
  10543. {
  10544. TapiLeaveCriticalSection(&gCriticalSection);
  10545. }
  10546. return lResult;
  10547. }
  10548. #if DBG
  10549. LPVOID
  10550. WINAPI
  10551. RSPAlloc(
  10552. DWORD dwSize,
  10553. DWORD dwLine,
  10554. PSTR pszFile
  10555. )
  10556. #else
  10557. LPVOID
  10558. WINAPI
  10559. RSPAlloc(
  10560. DWORD dwSize
  10561. )
  10562. #endif
  10563. {
  10564. LPVOID p;
  10565. #if DBG
  10566. dwSize += sizeof (MYMEMINFO);
  10567. #endif
  10568. p = HeapAlloc (ghRSPHeap, HEAP_ZERO_MEMORY, dwSize);
  10569. #if DBG
  10570. if (p)
  10571. {
  10572. ((PMYMEMINFO) p)->dwLine = dwLine;
  10573. ((PMYMEMINFO) p)->pszFile = pszFile;
  10574. p = (LPVOID) (((PMYMEMINFO) p) + 1);
  10575. }
  10576. #endif
  10577. return p;
  10578. }
  10579. void
  10580. DrvFree(
  10581. LPVOID p
  10582. )
  10583. {
  10584. if (!p)
  10585. {
  10586. return;
  10587. }
  10588. #if DBG
  10589. //
  10590. // Fill the buffer (but not the MYMEMINFO header) with 0xa9's
  10591. // to facilitate debugging
  10592. //
  10593. {
  10594. LPVOID p2 = p;
  10595. p = (LPVOID) (((PMYMEMINFO) p) - 1);
  10596. FillMemory(
  10597. p2,
  10598. HeapSize (ghRSPHeap, 0, p) - sizeof (MYMEMINFO),
  10599. 0xa9
  10600. );
  10601. }
  10602. #endif
  10603. HeapFree (ghRSPHeap, 0, p);
  10604. }
  10605. void
  10606. __RPC_FAR *
  10607. __RPC_API
  10608. midl_user_allocate(
  10609. size_t len
  10610. )
  10611. {
  10612. return (DrvAlloc (len));
  10613. }
  10614. void
  10615. __RPC_API
  10616. midl_user_free(
  10617. void __RPC_FAR * ptr
  10618. )
  10619. {
  10620. DrvFree (ptr);
  10621. }
  10622. LONG
  10623. RemoteSPAttach(
  10624. PCONTEXT_HANDLE_TYPE2 *pphContext
  10625. )
  10626. {
  10627. //
  10628. // This func is called by TapiSrv.exe on a remote machine as a
  10629. // result of the call to ClientAttach in TSPI_providerEnumDevices.
  10630. // The gpServer variable contains a pointer to the DRVSERVER
  10631. // structure we are currently initializing for this tapi server,
  10632. // so we'll use this as the context value.
  10633. //
  10634. LOG((TL_INFO, "RemoteSPAttach: enter"));
  10635. // DBGOUT((9, " hLineApp= 0x%08lx", gpServer));
  10636. *pphContext = (PCONTEXT_HANDLE_TYPE) gpCurrInitServer;
  10637. gpCurrInitServer->bConnectionOriented = TRUE;
  10638. return 0;
  10639. }
  10640. void
  10641. RemoteSPEventProc(
  10642. PCONTEXT_HANDLE_TYPE2 phContext,
  10643. unsigned char *pBuffer,
  10644. long lSize
  10645. )
  10646. {
  10647. //
  10648. // This func is called by tapisrv on a remote machine. We want to do
  10649. // things as quickly as possible here and return so we don't block the
  10650. // calling server thread.
  10651. //
  10652. // This func might also be called by the EventHandlerThread, in the
  10653. // case where we're using a connectionless event notification scheme
  10654. // and we pull events over from the server. In this case, phContext
  10655. // will == 0xfeedface, and prior to returning we want to set
  10656. // the char pointed at by pBuffer to 1 on success, or 0 otherwise.
  10657. //
  10658. DWORD dwMsgSize, dwRemainingSize = (DWORD) lSize,
  10659. dwMoveSize = (DWORD) lSize,
  10660. dwMoveSizeWrapped = 0;
  10661. unsigned char *pMsg = pBuffer;
  10662. //
  10663. // Make sure the buffer is DWORD aligned, big enough for at least 1 msg,
  10664. // and that the lSize is not overly large (overflow)
  10665. //
  10666. if ((lSize < 0) ||
  10667. (lSize & 0x3) ||
  10668. (lSize < sizeof (ASYNCEVENTMSG)) ||
  10669. ((pBuffer + lSize) < pBuffer))
  10670. {
  10671. LOG((TL_ERROR, "RemoteSPEventProc: ERROR! bad lSize=x%x", lSize));
  10672. if (phContext == (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface))
  10673. {
  10674. *pBuffer = 0;
  10675. }
  10676. return;
  10677. }
  10678. //
  10679. // Validate the pDrvServer pointer in the first msg
  10680. //
  10681. if (!ReferenceObject(
  10682. ghHandleTable,
  10683. ((PASYNCEVENTMSG) pMsg)->InitContext,
  10684. gdwDrvServerKey
  10685. ))
  10686. {
  10687. LOG((TL_ERROR,
  10688. "RemoteSPEventProc: bad InitContext=x%x in msg",
  10689. ((PASYNCEVENTMSG) pMsg)->InitContext
  10690. ));
  10691. if (phContext == (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface))
  10692. {
  10693. *pBuffer = 0;
  10694. }
  10695. return;
  10696. }
  10697. DereferenceObject (ghHandleTable, ((PASYNCEVENTMSG) pMsg)->InitContext, 1);
  10698. //
  10699. // Make sure every msg in the buffer has a valid dwTotalSize
  10700. //
  10701. do
  10702. {
  10703. dwMsgSize = (DWORD) ((PASYNCEVENTMSG) pMsg)->TotalSize;
  10704. if ((dwMsgSize & 0x3) ||
  10705. (dwMsgSize < sizeof (ASYNCEVENTMSG)) ||
  10706. (dwMsgSize > dwRemainingSize))
  10707. {
  10708. LOG((TL_ERROR, "RemoteSPEventProc: ERROR! bad msgSize=x%x",dwMsgSize));
  10709. if (phContext == (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface))
  10710. {
  10711. *pBuffer = 0;
  10712. }
  10713. return;
  10714. }
  10715. dwRemainingSize -= dwMsgSize;
  10716. pMsg += dwMsgSize;
  10717. } while (dwRemainingSize >= sizeof(ASYNCEVENTMSG));
  10718. if (0 != dwRemainingSize)
  10719. {
  10720. LOG((TL_ERROR, "RemoteSPEventProc: ERROR! bad last msgSize=x%x",dwRemainingSize));
  10721. if (phContext == (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface))
  10722. {
  10723. *pBuffer = 0;
  10724. }
  10725. return;
  10726. }
  10727. //
  10728. // Enter the critical section to sync access to gEventHandlerThreadParams
  10729. //
  10730. EnterCriticalSection (&gEventBufferCriticalSection);
  10731. {
  10732. PASYNCEVENTMSG pMsg = (PASYNCEVENTMSG) pBuffer;
  10733. LOG((TL_INFO, "RemoteSPEventProc: x%lx", pMsg));
  10734. if (pMsg->Msg == LINE_REPLY)
  10735. {
  10736. LOG((TL_INFO,
  10737. "Got a LINE_REPLY: p1=%lx, p2=%lx",
  10738. pMsg->Param1,
  10739. pMsg->Param2
  10740. ));
  10741. }
  10742. }
  10743. //
  10744. // Check to see if there's enough room for this msg in the event buffer.
  10745. // If not, then alloc a new event buffer, copy contents of existing buffer
  10746. // to new buffer (careful to preserve ordering of valid data), free the
  10747. // existing buffer, and reset the pointers.
  10748. //
  10749. if ((gEventHandlerThreadParams.dwEventBufferUsedSize + lSize) >
  10750. gEventHandlerThreadParams.dwEventBufferTotalSize)
  10751. {
  10752. DWORD dwMoveSize2, dwMoveSizeWrapped2, dwNewEventBufferTotalSize;
  10753. LPBYTE pNewEventBuffer;
  10754. LOG((TL_INFO, "EventHandlerThread: we're gonna need a bigger boat..."));
  10755. //
  10756. // Make sure we're not exceeding our max allowedable buffer size, &
  10757. // alloc a few more bytes than actually needed in the hope that we
  10758. // won't have to do this again soon (we don't want to go overboard
  10759. // & alloc a whole bunch since we don't currently free the buffer
  10760. // until provider shutdown)
  10761. //
  10762. dwNewEventBufferTotalSize =
  10763. gEventHandlerThreadParams.dwEventBufferTotalSize + lSize;
  10764. if (dwNewEventBufferTotalSize > gdwMaxEventBufferSize)
  10765. {
  10766. LOG((TL_ERROR,
  10767. "RemoveSPEventProc: event buf max'd, discarding events"
  10768. ));
  10769. LeaveCriticalSection (&gEventBufferCriticalSection);
  10770. return;
  10771. }
  10772. else if (dwNewEventBufferTotalSize + 512 <= gdwMaxEventBufferSize)
  10773. {
  10774. dwNewEventBufferTotalSize += 512;
  10775. }
  10776. if (!(pNewEventBuffer = DrvAlloc (dwNewEventBufferTotalSize)))
  10777. {
  10778. LeaveCriticalSection (&gEventBufferCriticalSection);
  10779. return;
  10780. }
  10781. if (gEventHandlerThreadParams.dwEventBufferUsedSize != 0)
  10782. {
  10783. if (gEventHandlerThreadParams.pDataIn >
  10784. gEventHandlerThreadParams.pDataOut)
  10785. {
  10786. dwMoveSize2 = (DWORD) (gEventHandlerThreadParams.pDataIn -
  10787. gEventHandlerThreadParams.pDataOut);
  10788. dwMoveSizeWrapped2 = 0;
  10789. }
  10790. else
  10791. {
  10792. dwMoveSize2 = (DWORD) ((gEventHandlerThreadParams.pEventBuffer
  10793. + gEventHandlerThreadParams.dwEventBufferTotalSize)
  10794. - gEventHandlerThreadParams.pDataOut);
  10795. dwMoveSizeWrapped2 = (DWORD) (gEventHandlerThreadParams.pDataIn
  10796. - gEventHandlerThreadParams.pEventBuffer);
  10797. }
  10798. CopyMemory(
  10799. pNewEventBuffer,
  10800. gEventHandlerThreadParams.pDataOut,
  10801. dwMoveSize2
  10802. );
  10803. if (dwMoveSizeWrapped2)
  10804. {
  10805. CopyMemory(
  10806. pNewEventBuffer + dwMoveSize2,
  10807. gEventHandlerThreadParams.pEventBuffer,
  10808. dwMoveSizeWrapped2
  10809. );
  10810. }
  10811. gEventHandlerThreadParams.pDataIn = pNewEventBuffer + dwMoveSize2 +
  10812. dwMoveSizeWrapped2;
  10813. }
  10814. else
  10815. {
  10816. gEventHandlerThreadParams.pDataIn = pNewEventBuffer;
  10817. }
  10818. DrvFree (gEventHandlerThreadParams.pEventBuffer);
  10819. gEventHandlerThreadParams.pDataOut =
  10820. gEventHandlerThreadParams.pEventBuffer = pNewEventBuffer;
  10821. gEventHandlerThreadParams.dwEventBufferTotalSize =
  10822. dwNewEventBufferTotalSize;
  10823. }
  10824. //
  10825. // Write the msg data to the buffer
  10826. //
  10827. if (gEventHandlerThreadParams.pDataIn >=
  10828. gEventHandlerThreadParams.pDataOut)
  10829. {
  10830. DWORD dwFreeSize;
  10831. dwFreeSize = gEventHandlerThreadParams.dwEventBufferTotalSize -
  10832. (DWORD) (gEventHandlerThreadParams.pDataIn -
  10833. gEventHandlerThreadParams.pEventBuffer);
  10834. if (dwMoveSize > dwFreeSize)
  10835. {
  10836. dwMoveSizeWrapped = dwMoveSize - dwFreeSize;
  10837. dwMoveSize = dwFreeSize;
  10838. }
  10839. }
  10840. CopyMemory (gEventHandlerThreadParams.pDataIn, pBuffer, dwMoveSize);
  10841. if (dwMoveSizeWrapped != 0)
  10842. {
  10843. CopyMemory(
  10844. gEventHandlerThreadParams.pEventBuffer,
  10845. pBuffer + dwMoveSize,
  10846. dwMoveSizeWrapped
  10847. );
  10848. gEventHandlerThreadParams.pDataIn =
  10849. gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
  10850. }
  10851. else
  10852. {
  10853. gEventHandlerThreadParams.pDataIn += dwMoveSize;
  10854. if (gEventHandlerThreadParams.pDataIn >=
  10855. (gEventHandlerThreadParams.pEventBuffer +
  10856. gEventHandlerThreadParams.dwEventBufferTotalSize))
  10857. {
  10858. gEventHandlerThreadParams.pDataIn =
  10859. gEventHandlerThreadParams.pEventBuffer;
  10860. }
  10861. }
  10862. gEventHandlerThreadParams.dwEventBufferUsedSize += (DWORD) lSize;
  10863. //
  10864. // Tell the EventHandlerThread there's another event to handle by
  10865. // signaling the event (if we're getting called by that thread
  10866. // [phContext == 0xfeedface] then set *pBuffer = 1 to indicate success)
  10867. //
  10868. if (phContext != (PCONTEXT_HANDLE_TYPE2) IntToPtr(0xfeedface))
  10869. {
  10870. SetEvent (gEventHandlerThreadParams.hEvent);
  10871. }
  10872. else
  10873. {
  10874. *pBuffer = 1;
  10875. }
  10876. //
  10877. // We're done...
  10878. //
  10879. LeaveCriticalSection (&gEventBufferCriticalSection);
  10880. LOG((TL_INFO, "RemoteSPEventProc: bytesWritten=x%x", lSize));
  10881. }
  10882. void
  10883. __RPC_USER
  10884. PCONTEXT_HANDLE_TYPE2_rundown(
  10885. PCONTEXT_HANDLE_TYPE2 phContext
  10886. )
  10887. {
  10888. //
  10889. // This happens (at least) when the server trys to call to REMOTESP, but
  10890. // times out and cancels the RPC request. When that happens, the RPC
  10891. // session will be broken.
  10892. //
  10893. PDRVSERVER pServer = (PDRVSERVER) phContext;
  10894. LOG((TL_INFO, "Rundown: phContext=x%x", phContext));
  10895. try
  10896. {
  10897. if (pServer->dwKey != pServer->pInitContext->dwDrvServerKey)
  10898. {
  10899. LOG((TL_ERROR, "Rundown: bad phContext=x%x", phContext));
  10900. return;
  10901. }
  10902. }
  10903. except (EXCEPTION_EXECUTE_HANDLER)
  10904. {
  10905. LOG((TL_ERROR, "Rundown: bad phContext=x%x", phContext));
  10906. return;
  10907. }
  10908. if (!pServer->pInitContext->bShutdown)
  10909. {
  10910. OnServerDisconnected(pServer);
  10911. }
  10912. InterlockedDecrement (&pServer->pInitContext->dwNumRundownsExpected);
  10913. }
  10914. void
  10915. RemoteSPDetach(
  10916. PCONTEXT_HANDLE_TYPE2 *pphContext
  10917. )
  10918. {
  10919. PCONTEXT_HANDLE_TYPE2 phContext;
  10920. LOG((TL_INFO, "RemoteSPDetach: phContext=x%x", *pphContext));
  10921. try
  10922. {
  10923. phContext = *pphContext;
  10924. *pphContext = (PCONTEXT_HANDLE_TYPE) NULL;
  10925. ((PDRVSERVER)phContext)->pInitContext->bShutdown = TRUE;
  10926. }
  10927. myexcept
  10928. {
  10929. phContext = NULL;
  10930. }
  10931. if (phContext)
  10932. {
  10933. PCONTEXT_HANDLE_TYPE2_rundown (phContext);
  10934. }
  10935. LOG((TL_INFO, "RemoteSPDetach: exit"));
  10936. }
  10937. LONG
  10938. AddCallToList(
  10939. PDRVLINE pLine,
  10940. PDRVCALL pCall
  10941. )
  10942. {
  10943. //
  10944. // Initialize some common fields in the call
  10945. //
  10946. pCall->dwKey = DRVCALL_KEY;
  10947. pCall->pServer = pLine->pServer;
  10948. pCall->pLine = pLine;
  10949. pCall->pCachedCallInfo = NULL;
  10950. pCall->dwDirtyStructs =
  10951. STRUCTCHANGE_LINECALLSTATUS | STRUCTCHANGE_LINECALLINFO;
  10952. //
  10953. // Safely add the call to the line's list
  10954. //
  10955. EnterCriticalSection (&gCallListCriticalSection);
  10956. if ((pCall->pNext = (PDRVCALL) pLine->pCalls))
  10957. {
  10958. pCall->pNext->pPrev = pCall;
  10959. }
  10960. pLine->pCalls = pCall;
  10961. LeaveCriticalSection (&gCallListCriticalSection);
  10962. return 0;
  10963. }
  10964. LONG
  10965. RemoveCallFromList(
  10966. PDRVCALL pCall
  10967. )
  10968. {
  10969. //
  10970. // Safely remove the call from the line's list
  10971. //
  10972. EnterCriticalSection (&gCallListCriticalSection);
  10973. if (!IsValidObject (pCall, DRVCALL_KEY))
  10974. {
  10975. LOG((TL_ERROR, "RemoveCallFromList: Call x%lx: Call key does not match.", pCall));
  10976. LeaveCriticalSection(&gCallListCriticalSection);
  10977. return 0;
  10978. }
  10979. //
  10980. // Mark the pCall as toast
  10981. //
  10982. pCall->dwKey = DRVINVAL_KEY;
  10983. if (pCall->pNext)
  10984. {
  10985. pCall->pNext->pPrev = pCall->pPrev;
  10986. }
  10987. if (pCall->pPrev)
  10988. {
  10989. pCall->pPrev->pNext = pCall->pNext;
  10990. }
  10991. else
  10992. {
  10993. pCall->pLine->pCalls = pCall->pNext;
  10994. }
  10995. LeaveCriticalSection (&gCallListCriticalSection);
  10996. // free structures
  10997. if ( pCall->pCachedCallInfo )
  10998. {
  10999. DrvFree( pCall->pCachedCallInfo );
  11000. }
  11001. if ( pCall->pCachedCallStatus )
  11002. {
  11003. DrvFree( pCall->pCachedCallStatus );
  11004. }
  11005. DrvFree(pCall);
  11006. return 0;
  11007. }
  11008. void
  11009. Shutdown(
  11010. PDRVSERVER pServer
  11011. )
  11012. {
  11013. TapiEnterCriticalSection (&gCriticalSection);
  11014. if ((pServer == NULL) || pServer->bShutdown)
  11015. {
  11016. TapiLeaveCriticalSection (&gCriticalSection);
  11017. goto ExitHere;
  11018. }
  11019. pServer->bShutdown = TRUE;
  11020. TapiLeaveCriticalSection (&gCriticalSection);
  11021. //
  11022. // Do a lineShutdown
  11023. //
  11024. {
  11025. DWORD dwSize;
  11026. TAPI32_MSG msg;
  11027. PLINESHUTDOWN_PARAMS pParams;
  11028. msg.u.Req_Func = lShutdown;
  11029. pParams = (PLINESHUTDOWN_PARAMS) &msg;
  11030. pParams->hLineApp = pServer->hLineApp;
  11031. dwSize = sizeof (TAPI32_MSG);
  11032. {
  11033. DWORD dwRetryCount = 0;
  11034. do
  11035. {
  11036. RpcTryExcept
  11037. {
  11038. ClientRequest(
  11039. pServer->phContext,
  11040. (char *) &msg,
  11041. dwSize,
  11042. &dwSize
  11043. );
  11044. dwRetryCount = gdwRetryCount;
  11045. }
  11046. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11047. {
  11048. // TODO may want to increase the retry count here since we
  11049. // have to do this, & a million other clients may be
  11050. // trying to do the same thing at the same time
  11051. if (dwRetryCount++ < gdwRetryCount)
  11052. {
  11053. Sleep (gdwRetryTimeout);
  11054. }
  11055. }
  11056. RpcEndExcept
  11057. } while (dwRetryCount < gdwRetryCount);
  11058. }
  11059. }
  11060. //
  11061. // Do a phoneShutdown
  11062. //
  11063. {
  11064. DWORD dwSize;
  11065. TAPI32_MSG msg;
  11066. PPHONESHUTDOWN_PARAMS pParams;
  11067. msg.u.Req_Func = pShutdown;
  11068. pParams = (PPHONESHUTDOWN_PARAMS) &msg;
  11069. pParams->hPhoneApp = pServer->hPhoneApp;
  11070. dwSize = sizeof (TAPI32_MSG);
  11071. {
  11072. DWORD dwRetryCount = 0;
  11073. do
  11074. {
  11075. RpcTryExcept
  11076. {
  11077. ClientRequest(
  11078. pServer->phContext,
  11079. (char *) &msg,
  11080. dwSize,
  11081. &dwSize
  11082. );
  11083. dwRetryCount = gdwRetryCount;
  11084. }
  11085. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11086. {
  11087. // TODO may want to increase the retry count here since we
  11088. // have to do this, & a million other clients may be
  11089. // trying to do the same thing at the same time
  11090. if (dwRetryCount++ < gdwRetryCount)
  11091. {
  11092. Sleep (gdwRetryTimeout);
  11093. }
  11094. }
  11095. RpcEndExcept
  11096. } while (dwRetryCount < gdwRetryCount);
  11097. }
  11098. }
  11099. RpcTryExcept
  11100. {
  11101. ClientDetach (&pServer->phContext);
  11102. pServer->phContext = NULL;
  11103. }
  11104. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11105. {
  11106. pServer->phContext = NULL;
  11107. }
  11108. RpcEndExcept
  11109. TapiEnterCriticalSection (&gCriticalSection);
  11110. //
  11111. // Walk the line lookup tables & send a CLOSE msg for each open line
  11112. // associated with the server
  11113. //
  11114. {
  11115. PDRVLINELOOKUP pLookup = gpLineLookup;
  11116. try
  11117. {
  11118. while (pLookup)
  11119. {
  11120. DWORD i;
  11121. PDRVLINE pLine;
  11122. for(
  11123. i = 0, pLine = pLookup->aEntries;
  11124. i < pLookup->dwUsedEntries;
  11125. i++, pLine++
  11126. )
  11127. {
  11128. if (pLine->pServer == pServer)
  11129. {
  11130. if (pLine->htLine)
  11131. {
  11132. PDRVCALL pCall;
  11133. pLine->hLine = 0;
  11134. EnterCriticalSection (&gCallListCriticalSection);
  11135. try
  11136. {
  11137. pCall = pLine->pCalls;
  11138. while (pCall)
  11139. {
  11140. pCall->hCall = 0;
  11141. pCall = pCall->pNext;
  11142. }
  11143. }
  11144. except (EXCEPTION_EXECUTE_HANDLER)
  11145. {
  11146. LOG((TL_ERROR, "Shutdown: Exception x%lx while walking the calls list",
  11147. GetExceptionCode()));
  11148. }
  11149. LeaveCriticalSection (&gCallListCriticalSection);
  11150. try
  11151. {
  11152. (*gpfnLineEventProc)(
  11153. pLine->htLine,
  11154. 0,
  11155. LINE_CLOSE,
  11156. 0,
  11157. 0,
  11158. 0
  11159. );
  11160. }
  11161. except (EXCEPTION_EXECUTE_HANDLER)
  11162. {
  11163. LOG((TL_ERROR, "Shutdown: Exception x%lx while sending the LINE_CLOSE message",
  11164. GetExceptionCode()));
  11165. }
  11166. }
  11167. }
  11168. }
  11169. pLookup = pLookup->pNext;
  11170. }
  11171. }
  11172. except (EXCEPTION_EXECUTE_HANDLER)
  11173. {
  11174. LOG((TL_ERROR, "Shutdown: Exception x%lx while walking the line lookup table",
  11175. GetExceptionCode()));
  11176. }
  11177. }
  11178. //
  11179. // Walk the phone lookup tables & send a CLOSE msg for each open phone
  11180. // associated with the server
  11181. //
  11182. {
  11183. PDRVPHONELOOKUP pLookup = gpPhoneLookup;
  11184. while (pLookup)
  11185. {
  11186. DWORD i;
  11187. PDRVPHONE pPhone;
  11188. for(
  11189. i = 0, pPhone = pLookup->aEntries;
  11190. i < pLookup->dwUsedEntries;
  11191. i++, pPhone++
  11192. )
  11193. {
  11194. if (pPhone->pServer == pServer)
  11195. {
  11196. if (pPhone->htPhone)
  11197. {
  11198. pPhone->hPhone = 0;
  11199. (*gpfnPhoneEventProc)(
  11200. pPhone->htPhone,
  11201. PHONE_CLOSE,
  11202. 0,
  11203. 0,
  11204. 0
  11205. );
  11206. }
  11207. }
  11208. }
  11209. pLookup = pLookup->pNext;
  11210. }
  11211. }
  11212. TapiLeaveCriticalSection (&gCriticalSection);
  11213. ExitHere:
  11214. return;
  11215. }
  11216. PNEGOTIATEAPIVERSIONFORALLDEVICES_PARAMS
  11217. NegotiateAllDevices(
  11218. HLINEAPP hLineApp,
  11219. DWORD dwNumLineDevices,
  11220. DWORD dwNumPhoneDevices,
  11221. PCONTEXT_HANDLE_TYPE phContext
  11222. )
  11223. {
  11224. DWORD dwBufSize, dwUsedSize,
  11225. dwRetryCount = 0;
  11226. PNEGOTIATEAPIVERSIONFORALLDEVICES_PARAMS pParams;
  11227. if (!dwNumLineDevices && !dwNumPhoneDevices)
  11228. {
  11229. return NULL;
  11230. }
  11231. dwBufSize =
  11232. sizeof (TAPI32_MSG) +
  11233. (dwNumLineDevices * sizeof (DWORD)) +
  11234. (dwNumLineDevices * sizeof (LINEEXTENSIONID)) +
  11235. (dwNumPhoneDevices * sizeof (DWORD)) +
  11236. (dwNumPhoneDevices * sizeof (PHONEEXTENSIONID));
  11237. if (!(pParams = DrvAlloc (dwBufSize)))
  11238. {
  11239. return NULL;
  11240. }
  11241. pParams->lResult = xNegotiateAPIVersionForAllDevices;
  11242. pParams->hLineApp = hLineApp;
  11243. pParams->dwNumLineDevices = dwNumLineDevices;
  11244. pParams->dwNumPhoneDevices = dwNumPhoneDevices;
  11245. pParams->dwAPIHighVersion = TAPI_VERSION_CURRENT;
  11246. pParams->dwLineAPIVersionListSize = dwNumLineDevices * sizeof (DWORD);
  11247. pParams->dwLineExtensionIDListSize = dwNumLineDevices *
  11248. sizeof (LINEEXTENSIONID);
  11249. pParams->dwPhoneAPIVersionListSize = dwNumPhoneDevices * sizeof (DWORD);
  11250. pParams->dwPhoneExtensionIDListSize = dwNumPhoneDevices *
  11251. sizeof (PHONEEXTENSIONID);
  11252. dwUsedSize = sizeof (TAPI32_MSG);
  11253. {
  11254. do
  11255. {
  11256. RpcTryExcept
  11257. {
  11258. ClientRequest(
  11259. phContext,
  11260. (char *) pParams,
  11261. dwBufSize,
  11262. &dwUsedSize
  11263. );
  11264. dwRetryCount = gdwRetryCount;
  11265. }
  11266. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11267. {
  11268. LOG((TL_ERROR,
  11269. "NegotiateAllDevices: exception %d doing negotiation",
  11270. RpcExceptionCode()
  11271. ));
  11272. if (dwRetryCount++ < gdwRetryCount)
  11273. {
  11274. Sleep (gdwRetryTimeout);
  11275. }
  11276. else
  11277. {
  11278. pParams->lResult = LINEERR_OPERATIONFAILED;
  11279. }
  11280. }
  11281. RpcEndExcept
  11282. } while (dwRetryCount < gdwRetryCount);
  11283. }
  11284. if (pParams->lResult != 0)
  11285. {
  11286. LOG((TL_ERROR,
  11287. "NegotiateAllDevices: negotiation failed (x%x)",
  11288. pParams->lResult
  11289. ));
  11290. DrvFree (pParams);
  11291. pParams = NULL;
  11292. }
  11293. return pParams;
  11294. }
  11295. LONG
  11296. FinishEnumDevices(
  11297. PDRVSERVER pServer,
  11298. PCONTEXT_HANDLE_TYPE phContext,
  11299. LPDWORD lpdwNumLines,
  11300. LPDWORD lpdwNumPhones,
  11301. BOOL fStartup,
  11302. BOOL bFromReg
  11303. )
  11304. /*++
  11305. Function: FinishEnumDevices
  11306. Purpose: Initializes remote server and queries for
  11307. # of lines and phones.
  11308. Notes: We must already be connected via ClientAttach
  11309. and we must already be impersonating the client
  11310. Created: 6/26/97 t-mperh
  11311. --*/
  11312. {
  11313. TAPI32_MSG msg[2];
  11314. DWORD dwUsedSize, dwBufSize;
  11315. DWORD dwRetryCount = 0;
  11316. HLINEAPP hLineApp;
  11317. HPHONEAPP hPhoneApp;
  11318. DWORD dwNumLineDevices, dwNumPhoneDevices;
  11319. DWORD dwNumDevices = 0;
  11320. BOOL bFailed = FALSE;
  11321. PNEGOTIATEAPIVERSIONFORALLDEVICES_PARAMS pNegoAPIVerParams;
  11322. if (!(pServer->InitContext))
  11323. {
  11324. if (!(pServer->InitContext = (DWORD) NewObject(
  11325. ghHandleTable,
  11326. pServer,
  11327. NULL
  11328. )))
  11329. {
  11330. dwNumLineDevices = 0;
  11331. dwNumPhoneDevices = 0;
  11332. bFailed = TRUE;
  11333. goto cleanup;
  11334. }
  11335. }
  11336. {
  11337. PLINEINITIALIZE_PARAMS pParams;
  11338. msg[0].u.Req_Func = lInitialize;
  11339. pParams = (PLINEINITIALIZE_PARAMS) msg;
  11340. //
  11341. // NOTE: we pass the pServer in place of the lpfnCallback
  11342. // so the we always know which server is sending us
  11343. // async events
  11344. //
  11345. pParams->InitContext = pServer->InitContext;
  11346. pParams->hInstance =
  11347. pParams->dwFriendlyNameOffset =
  11348. pParams->dwModuleNameOffset = 0;
  11349. pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
  11350. wcscpy ((WCHAR *) (msg + 1), gszMachineName);
  11351. dwBufSize =
  11352. dwUsedSize = sizeof (TAPI32_MSG) +
  11353. (lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
  11354. {
  11355. DWORD dwRetryCount = 0;
  11356. do
  11357. {
  11358. RpcTryExcept
  11359. {
  11360. ClientRequest(
  11361. phContext,
  11362. (char *) &msg,
  11363. dwBufSize,
  11364. &dwUsedSize
  11365. );
  11366. dwRetryCount = gdwRetryCount;
  11367. }
  11368. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11369. {
  11370. LOG((TL_ERROR,
  11371. "FinishEnumDevices: exception %d doing lineInit",
  11372. RpcExceptionCode()
  11373. ));
  11374. if (dwRetryCount++ < gdwRetryCount)
  11375. {
  11376. Sleep (gdwRetryTimeout);
  11377. }
  11378. else
  11379. {
  11380. bFailed = TRUE;
  11381. }
  11382. }
  11383. RpcEndExcept
  11384. } while (dwRetryCount < gdwRetryCount);
  11385. }
  11386. hLineApp = pParams->hLineApp;
  11387. if (pParams->lResult == 0)
  11388. {
  11389. dwNumLineDevices = pParams->dwNumDevs;
  11390. }
  11391. else
  11392. {
  11393. LOG((TL_ERROR,
  11394. "FinishEnumDevices: lineInit failed (x%x) on server %s",
  11395. pParams->lResult,
  11396. pServer->szServerName
  11397. ));
  11398. dwNumLineDevices = 0;
  11399. dwNumPhoneDevices = 0;
  11400. bFailed = TRUE;
  11401. goto cleanup;
  11402. }
  11403. }
  11404. {
  11405. PPHONEINITIALIZE_PARAMS pParams;
  11406. msg[0].u.Req_Func = pInitialize;
  11407. pParams = (PPHONEINITIALIZE_PARAMS) msg;
  11408. //
  11409. // NOTE: we pass the pServer in place of the lpfnCallback
  11410. // so the we always know which server is sending us
  11411. // async events
  11412. //
  11413. pParams->InitContext = pServer->InitContext;
  11414. pParams->hInstance =
  11415. pParams->dwFriendlyNameOffset =
  11416. pParams->dwModuleNameOffset = 0;
  11417. pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
  11418. wcscpy ((WCHAR *) (msg + 1), gszMachineName);
  11419. dwBufSize =
  11420. dwUsedSize = sizeof (TAPI32_MSG) +
  11421. (lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
  11422. {
  11423. DWORD dwRetryCount = 0;
  11424. do
  11425. {
  11426. RpcTryExcept
  11427. {
  11428. ClientRequest(
  11429. phContext,
  11430. (char *) &msg,
  11431. dwBufSize,
  11432. &dwUsedSize
  11433. );
  11434. dwRetryCount = gdwRetryCount;
  11435. }
  11436. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11437. {
  11438. LOG((TL_ERROR,
  11439. "FinishEnumDevices: exception %d doing phoneInit",
  11440. RpcExceptionCode()
  11441. ));
  11442. if (dwRetryCount++ < gdwRetryCount)
  11443. {
  11444. Sleep (gdwRetryTimeout);
  11445. }
  11446. else
  11447. {
  11448. bFailed = TRUE;
  11449. }
  11450. }
  11451. RpcEndExcept
  11452. } while (dwRetryCount < gdwRetryCount);
  11453. }
  11454. hPhoneApp = pParams->hPhoneApp;
  11455. if (pParams->lResult == 0)
  11456. {
  11457. dwNumPhoneDevices = pParams->dwNumDevs;
  11458. }
  11459. else
  11460. {
  11461. LOG((TL_ERROR,
  11462. "FinishEnumDevices: phoneInit failed (x%x) on server %s",
  11463. pParams->lResult,
  11464. pServer->szServerName
  11465. ));
  11466. dwNumPhoneDevices = 0;
  11467. dwNumLineDevices = 0;
  11468. bFailed = TRUE;
  11469. goto cleanup;
  11470. }
  11471. }
  11472. LOG((TL_INFO,
  11473. "FinishEnumDevices: srv='%s', lines=%d, phones=%d",
  11474. pServer->szServerName,
  11475. dwNumLineDevices,
  11476. dwNumPhoneDevices
  11477. ));
  11478. LogRemoteSPError(pServer->szServerName,
  11479. ERROR_REMOTESP_NONE,
  11480. dwNumLineDevices,
  11481. dwNumPhoneDevices,
  11482. !fStartup);
  11483. if (pServer->dwSpecialHack == 0xa5c369a5)
  11484. {
  11485. pNegoAPIVerParams = NegotiateAllDevices(
  11486. hLineApp,
  11487. dwNumLineDevices,
  11488. dwNumPhoneDevices,
  11489. phContext
  11490. );
  11491. }
  11492. else
  11493. {
  11494. pNegoAPIVerParams = NULL;
  11495. }
  11496. {
  11497. DWORD dwServerID,
  11498. dwLocalID,
  11499. myLineDevIDBase,
  11500. myTempLineID,
  11501. myPhoneDevIDBase,
  11502. myTempPhoneID,
  11503. dwZero = 0,
  11504. *pdwAPIVersion;
  11505. LPLINEEXTENSIONID pExtID;
  11506. LONG lResult;
  11507. pServer->phContext = phContext;
  11508. pServer->hLineApp = hLineApp;
  11509. pServer->hPhoneApp = hPhoneApp;
  11510. //
  11511. // If we are not being called during initialization
  11512. // we need to simulate LINE_CREATE and PHONE_CREATE
  11513. // messages from the server SP.
  11514. //
  11515. // Note we differentiate between static line devices
  11516. // (those avail. at startup) and dynamic line devices
  11517. // (those we are notified of dynamically) based on the
  11518. // fStartup flag.
  11519. //
  11520. // _NOTE ALSO_ that the local device id's we assign to
  11521. // devices at startup are 0-based, rather than based
  11522. // on the dwDeviceIDBase's (which we don't know yet
  11523. // because providerInit hasn't been called). This
  11524. // is desirable because AddLine/Phone might have to
  11525. // negotiate versions, which requires a call to DoFunc,
  11526. // which needss to know how to get pDevices from ID's.
  11527. // We'll reset the .dwDeviceIDLocal fields for static
  11528. // devices later on, in TSPI_providerInit.
  11529. //
  11530. myLineDevIDBase = gdwInitialNumLineDevices;
  11531. myTempLineID = gdwTempLineID;
  11532. myPhoneDevIDBase = gdwInitialNumPhoneDevices;
  11533. myTempPhoneID = gdwTempPhoneID;
  11534. if (pNegoAPIVerParams)
  11535. {
  11536. pdwAPIVersion = (LPDWORD)
  11537. (((LPBYTE) pNegoAPIVerParams) + sizeof (TAPI32_MSG) +
  11538. pNegoAPIVerParams->dwLineAPIVersionListOffset);
  11539. pExtID = (LPLINEEXTENSIONID)
  11540. (((LPBYTE) pNegoAPIVerParams) + sizeof (TAPI32_MSG) +
  11541. pNegoAPIVerParams->dwLineExtensionIDListOffset);
  11542. }
  11543. else
  11544. {
  11545. pdwAPIVersion = &dwZero;
  11546. pExtID = (LPLINEEXTENSIONID) NULL;
  11547. }
  11548. for (dwServerID = 0; dwServerID < dwNumLineDevices; dwServerID++)
  11549. {
  11550. dwLocalID = (fStartup ? myLineDevIDBase++ : myTempLineID);
  11551. lResult = AddLine(
  11552. pServer,
  11553. dwLocalID,
  11554. dwServerID,
  11555. fStartup,
  11556. TRUE,
  11557. *pdwAPIVersion,
  11558. pExtID
  11559. );
  11560. if (lResult == LINEERR_NODEVICE)
  11561. {
  11562. if (fStartup)
  11563. {
  11564. --myLineDevIDBase;
  11565. }
  11566. continue;
  11567. }
  11568. if (lResult != 0)
  11569. {
  11570. break;
  11571. }
  11572. ++dwNumDevices;
  11573. if (pNegoAPIVerParams)
  11574. {
  11575. pdwAPIVersion++;
  11576. pExtID++;
  11577. }
  11578. if (!fStartup)
  11579. {
  11580. --myTempLineID;
  11581. (*gpfnLineEventProc)(
  11582. 0,
  11583. 0,
  11584. LINE_CREATE,
  11585. (ULONG_PTR) ghProvider,
  11586. dwLocalID,
  11587. 0
  11588. );
  11589. }
  11590. }
  11591. gdwTempLineID = myTempLineID;
  11592. if (pNegoAPIVerParams)
  11593. {
  11594. pdwAPIVersion = (LPDWORD)
  11595. (((LPBYTE) pNegoAPIVerParams) + sizeof (TAPI32_MSG) +
  11596. pNegoAPIVerParams->dwPhoneAPIVersionListOffset);
  11597. pExtID = (LPLINEEXTENSIONID)
  11598. (((LPBYTE) pNegoAPIVerParams) + sizeof (TAPI32_MSG) +
  11599. pNegoAPIVerParams->dwPhoneExtensionIDListOffset);
  11600. }
  11601. for (dwServerID = 0; dwServerID < dwNumPhoneDevices; dwServerID++)
  11602. {
  11603. dwLocalID = (fStartup ? myPhoneDevIDBase++ : myTempPhoneID);
  11604. lResult = AddPhone(
  11605. pServer,
  11606. dwLocalID,
  11607. dwServerID,
  11608. fStartup,
  11609. TRUE,
  11610. *pdwAPIVersion,
  11611. (LPPHONEEXTENSIONID) pExtID
  11612. );
  11613. if (lResult == PHONEERR_NODEVICE)
  11614. {
  11615. if (fStartup)
  11616. {
  11617. --myPhoneDevIDBase;
  11618. }
  11619. continue;
  11620. }
  11621. if (lResult != 0)
  11622. {
  11623. break;
  11624. }
  11625. ++dwNumDevices;
  11626. if (pNegoAPIVerParams)
  11627. {
  11628. pdwAPIVersion++;
  11629. pExtID++;
  11630. }
  11631. if (!fStartup)
  11632. {
  11633. myTempPhoneID--;
  11634. (*gpfnPhoneEventProc)(
  11635. 0,
  11636. PHONE_CREATE,
  11637. (ULONG_PTR) ghProvider,
  11638. dwLocalID,
  11639. 0
  11640. );
  11641. }
  11642. }
  11643. gdwTempPhoneID = myTempPhoneID;
  11644. }
  11645. if (pNegoAPIVerParams)
  11646. {
  11647. DrvFree (pNegoAPIVerParams);
  11648. }
  11649. cleanup:
  11650. if (pServer->bConnectionOriented)
  11651. {
  11652. InterlockedIncrement(
  11653. &gpCurrentInitContext->dwNumRundownsExpected
  11654. );
  11655. }
  11656. TapiEnterCriticalSection(&gCriticalSection);
  11657. InsertTailList(
  11658. &gpCurrentInitContext->ServerList,
  11659. &pServer->ServerList
  11660. );
  11661. TapiLeaveCriticalSection(&gCriticalSection);
  11662. if (TRUE == fStartup)
  11663. {
  11664. gdwInitialNumLineDevices =
  11665. *lpdwNumLines = (gpLineLookup ? gpLineLookup->dwUsedEntries : 0);
  11666. gdwInitialNumPhoneDevices =
  11667. *lpdwNumPhones = (gpPhoneLookup ? gpPhoneLookup->dwUsedEntries : 0);
  11668. }
  11669. if (bFailed)
  11670. {
  11671. //
  11672. // Failed in seting up lines for this server, retry later.
  11673. //
  11674. Sleep (4000);
  11675. if (RPC_S_OK != RpcBindingSetOption (
  11676. pServer->hTapSrv,
  11677. RPC_C_OPT_CALL_TIMEOUT,
  11678. gdwRSPRpcTimeout
  11679. ))
  11680. {
  11681. LOG((TL_ERROR, "FinishEnumDevices: RpcBindingSetOption failed"));
  11682. }
  11683. OnServerDisconnected (pServer);
  11684. }
  11685. else
  11686. {
  11687. if (!bFromReg && dwNumDevices == 0)
  11688. {
  11689. //
  11690. // The server is found from DS and does not
  11691. // contain any lines for me, detach from it
  11692. //
  11693. TapiEnterCriticalSection(&gCriticalSection);
  11694. RemoveEntryList (&pServer->ServerList);
  11695. TapiLeaveCriticalSection(&gCriticalSection);
  11696. Shutdown (pServer);
  11697. RpcBindingFree(&pServer->hTapSrv);
  11698. pServer->hTapSrv = NULL;
  11699. DereferenceObject (ghHandleTable, pServer->InitContext, 1);
  11700. }
  11701. else
  11702. {
  11703. RpcBindingSetOption (
  11704. pServer->hTapSrv,
  11705. RPC_C_OPT_CALL_TIMEOUT,
  11706. gdwRSPRpcTimeout
  11707. );
  11708. }
  11709. }
  11710. return 0;
  11711. }
  11712. VOID
  11713. WINAPI
  11714. NetworkPollThread(
  11715. LPVOID pszThingtoPassToServer
  11716. )
  11717. {
  11718. LONG lResult;
  11719. LIST_ENTRY *pEntry;
  11720. PCONTEXT_HANDLE_TYPE phContext = NULL;
  11721. HANDLE hProcess;
  11722. PRSP_THREAD_INFO pTls;
  11723. LOG((TL_INFO, "NetworkPollThread: enter"));
  11724. //
  11725. // This thread has no user context, which would prevent us from rpc'ing
  11726. // back to remote tapisrv if necessary. So, find the user that is logged
  11727. // on and impersonate them in this thread.
  11728. //
  11729. if (!GetCurrentlyLoggedOnUser (&hProcess))
  11730. {
  11731. LOG((TL_ERROR, "NetworkPollThread: GetCurrentlyLoggedOnUser failed"));
  11732. goto cleanup;
  11733. }
  11734. else if (!SetProcessImpersonationToken(hProcess))
  11735. {
  11736. LOG((TL_ERROR, "NetworkPollThread: SetProcessImpersonationToken failed"));
  11737. goto cleanup;
  11738. }
  11739. if ((pTls = GetTls()))
  11740. {
  11741. pTls->bAlreadyImpersonated = TRUE;
  11742. }
  11743. else
  11744. {
  11745. goto cleanup;
  11746. }
  11747. //
  11748. // Try to attach to servers once in a while. If we successfully attach
  11749. // to a server then remove it from the Npt list and insert it in the
  11750. // global "current" list. When all the servers have been initialized
  11751. // or TSPI_providerShutdown has signalled us then drop out of the loop
  11752. // and clean up.
  11753. //
  11754. while (WaitForSingleObject (ghNptShutdownEvent, NPT_TIMEOUT)
  11755. == WAIT_TIMEOUT)
  11756. {
  11757. BOOL bListEmpty;
  11758. if (gEventHandlerThreadParams.bExit)
  11759. {
  11760. goto cleanup;
  11761. }
  11762. TapiEnterCriticalSection (&gCriticalSection);
  11763. bListEmpty = IsListEmpty (&gNptListHead);
  11764. pEntry = gNptListHead.Flink;
  11765. TapiLeaveCriticalSection (&gCriticalSection);
  11766. if (bListEmpty)
  11767. {
  11768. continue;
  11769. }
  11770. while (pEntry != &gNptListHead)
  11771. {
  11772. BOOL bCalledSetAuthInfo = FALSE;
  11773. DWORD dwException = 0;
  11774. RPC_STATUS status;
  11775. if (gEventHandlerThreadParams.bExit)
  11776. {
  11777. goto cleanup;
  11778. }
  11779. //
  11780. // Set the global which RemoteSPAttach looks at to know
  11781. // who the current server is
  11782. //
  11783. gpCurrInitServer =
  11784. CONTAINING_RECORD (pEntry, DRVSERVER, ServerList);
  11785. if (!gpCurrInitServer->bSetAuthInfo)
  11786. {
  11787. bCalledSetAuthInfo = TRUE;
  11788. status = RpcBindingSetAuthInfo(
  11789. gpCurrInitServer->hTapSrv,
  11790. NULL,
  11791. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  11792. RPC_C_AUTHN_WINNT,
  11793. NULL,
  11794. 0
  11795. );
  11796. if (status == RPC_S_OK)
  11797. {
  11798. gpCurrInitServer->bSetAuthInfo = TRUE;
  11799. }
  11800. else
  11801. {
  11802. lResult = LINEERR_OPERATIONFAILED;
  11803. }
  11804. }
  11805. if (0 == lResult)
  11806. {
  11807. RpcTryExcept
  11808. {
  11809. // set RPC binding
  11810. hTapSrv = gpCurrInitServer->hTapSrv;
  11811. gpCurrInitServer->dwSpecialHack = 0;
  11812. lResult = ClientAttach(
  11813. &phContext,
  11814. 0xffffffff,
  11815. &gpCurrInitServer->dwSpecialHack,
  11816. gszMailslotName,
  11817. pszThingtoPassToServer
  11818. );
  11819. if (lResult != 0)
  11820. {
  11821. LogRemoteSPError(gpCurrInitServer->szServerName,
  11822. ERROR_REMOTESP_NP_ATTACH, lResult, 0,
  11823. TRUE);
  11824. }
  11825. else
  11826. {
  11827. LogRemoteSPError(gpCurrInitServer->szServerName,
  11828. ERROR_REMOTESP_NONE, 0, 0,
  11829. TRUE);
  11830. }
  11831. }
  11832. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  11833. {
  11834. dwException = RpcExceptionCode();
  11835. LogRemoteSPError (gpCurrInitServer->szServerName,
  11836. ERROR_REMOTESP_NP_EXCEPTION,
  11837. dwException, 0, TRUE);
  11838. lResult = LINEERR_OPERATIONFAILED;
  11839. }
  11840. RpcEndExcept
  11841. }
  11842. if (lResult == 0)
  11843. {
  11844. LOG((TL_INFO,
  11845. "NetworkPollThread: attached to server %s",
  11846. gpCurrInitServer->szServerName
  11847. ));
  11848. TapiEnterCriticalSection(&gCriticalSection);
  11849. RemoveEntryList (pEntry);
  11850. pEntry->Blink = NULL; //This node now is not in any link list
  11851. pEntry = pEntry->Flink;
  11852. TapiLeaveCriticalSection (&gCriticalSection);
  11853. if (gpCurrInitServer->dwFlags & SERVER_DISCONNECTED)
  11854. {
  11855. OnServerConnected(gpCurrInitServer);
  11856. }
  11857. //
  11858. // Enable all events for remotesp
  11859. //
  11860. gpCurrInitServer->phContext = phContext;
  11861. RSPSetEventFilterMasks (
  11862. gpCurrInitServer,
  11863. TAPIOBJ_NULL,
  11864. (LONG_PTR)NULL,
  11865. (ULONG64)EM_ALL
  11866. );
  11867. FinishEnumDevices(
  11868. gpCurrInitServer,
  11869. phContext,
  11870. NULL,
  11871. NULL,
  11872. FALSE, // after init
  11873. TRUE
  11874. );
  11875. }
  11876. else
  11877. {
  11878. TapiEnterCriticalSection (&gCriticalSection);
  11879. pEntry = pEntry->Flink;
  11880. TapiLeaveCriticalSection (&gCriticalSection);
  11881. }
  11882. }
  11883. }
  11884. cleanup:
  11885. ClearImpersonationToken();
  11886. CloseHandle(hProcess);
  11887. CloseHandle (ghNptShutdownEvent);
  11888. TapiEnterCriticalSection (&gCriticalSection);
  11889. while (!IsListEmpty (&gNptListHead))
  11890. {
  11891. PDRVSERVER pServer;
  11892. pEntry = RemoveHeadList (&gNptListHead);
  11893. pServer = CONTAINING_RECORD (pEntry, DRVSERVER, ServerList);
  11894. RpcBindingFree (&pServer->hTapSrv);
  11895. DereferenceObject (ghHandleTable, pServer->InitContext, 1);
  11896. }
  11897. TapiLeaveCriticalSection (&gCriticalSection);
  11898. LOG((TL_INFO, "NetworkPollThread: exit"));
  11899. ExitThread (0);
  11900. }
  11901. VOID
  11902. PASCAL
  11903. FreeInitContext(
  11904. PRSP_INIT_CONTEXT pInitContext
  11905. )
  11906. {
  11907. LIST_ENTRY *pEntry;
  11908. while (!IsListEmpty (&pInitContext->ServerList))
  11909. {
  11910. PDRVSERVER pServer;
  11911. pEntry = RemoveHeadList (&pInitContext->ServerList);
  11912. pServer = CONTAINING_RECORD (pEntry, DRVSERVER, ServerList);
  11913. RpcBindingFree(&pServer->hTapSrv);
  11914. DereferenceObject (ghHandleTable, pServer->InitContext, 1);
  11915. }
  11916. DrvFree (pInitContext);
  11917. }
  11918. BOOL
  11919. IsClientSystem(
  11920. VOID
  11921. )
  11922. {
  11923. BOOL bResult = FALSE;
  11924. DWORD dwInfoBufferSize, dwSize;
  11925. HANDLE hAccessToken;
  11926. LPWSTR InfoBuffer;
  11927. PTOKEN_USER ptuUser;
  11928. PSID pLocalSystemSid = NULL;
  11929. PSID pLocalServiceSid = NULL;
  11930. PSID pNetworkServiceSid = NULL;
  11931. SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
  11932. // First, build the SID for LocalSystem;
  11933. if (!AllocateAndInitializeSid (
  11934. &NtAuthority,
  11935. 1,
  11936. SECURITY_LOCAL_SYSTEM_RID,
  11937. 0, 0, 0, 0, 0, 0, 0,
  11938. &pLocalSystemSid) ||
  11939. !AllocateAndInitializeSid (
  11940. &NtAuthority,
  11941. 1,
  11942. SECURITY_LOCAL_SERVICE_RID,
  11943. 0, 0, 0, 0, 0, 0, 0,
  11944. &pLocalServiceSid) ||
  11945. !AllocateAndInitializeSid (
  11946. &NtAuthority,
  11947. 1,
  11948. SECURITY_NETWORK_SERVICE_RID,
  11949. 0, 0, 0, 0, 0, 0, 0,
  11950. &pNetworkServiceSid)
  11951. )
  11952. {
  11953. goto Return;
  11954. }
  11955. // Impersonate the client, and get it's SID
  11956. if (RPC_S_OK != RpcImpersonateClient (0))
  11957. {
  11958. goto Return;
  11959. }
  11960. if (OpenThreadToken(
  11961. GetCurrentThread(),
  11962. TOKEN_READ,
  11963. FALSE,
  11964. &hAccessToken
  11965. ))
  11966. {
  11967. dwSize = 2048;
  11968. alloc_infobuffer:
  11969. dwInfoBufferSize = 0;
  11970. InfoBuffer = (LPWSTR) DrvAlloc (dwSize);
  11971. if (NULL != InfoBuffer)
  11972. {
  11973. ptuUser = (PTOKEN_USER) InfoBuffer;
  11974. if (GetTokenInformation(
  11975. hAccessToken,
  11976. TokenUser,
  11977. InfoBuffer,
  11978. dwSize,
  11979. &dwInfoBufferSize
  11980. ))
  11981. {
  11982. // Now, compare the 2 SIDs
  11983. if (EqualSid (pLocalSystemSid, ptuUser->User.Sid) ||
  11984. EqualSid (pLocalServiceSid, ptuUser->User.Sid) ||
  11985. EqualSid (pNetworkServiceSid, ptuUser->User.Sid))
  11986. {
  11987. bResult = TRUE;
  11988. }
  11989. }
  11990. else
  11991. {
  11992. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  11993. {
  11994. DrvFree (InfoBuffer);
  11995. dwSize *= 2;
  11996. goto alloc_infobuffer;
  11997. }
  11998. LOG((TL_ERROR,
  11999. "IsClientSystem: GetTokenInformation failed, error=%d",
  12000. GetLastError()
  12001. ));
  12002. }
  12003. DrvFree (InfoBuffer);
  12004. CloseHandle (hAccessToken);
  12005. }
  12006. else
  12007. {
  12008. LOG((TL_ERROR,
  12009. "IsClientSystem: DrvAlloc (%d) failed",
  12010. dwSize
  12011. ));
  12012. }
  12013. }
  12014. else
  12015. {
  12016. LOG((TL_ERROR,
  12017. "IsClientSystem: OpenThreadToken failed, error=%d",
  12018. GetLastError()
  12019. ));
  12020. }
  12021. RpcRevertToSelf ();
  12022. Return:
  12023. if (pLocalSystemSid)
  12024. {
  12025. FreeSid (pLocalSystemSid);
  12026. }
  12027. if (pLocalServiceSid)
  12028. {
  12029. FreeSid (pLocalServiceSid);
  12030. }
  12031. if (pNetworkServiceSid)
  12032. {
  12033. FreeSid (pNetworkServiceSid);
  12034. }
  12035. return bResult;
  12036. }
  12037. #define LOWDWORD(ul64) ((DWORD)(ul64 & 0xffffffff))
  12038. #define HIDWORD(ul64) ((DWORD)((ul64 & 0xffffffff00000000) >> 32))
  12039. LONG
  12040. WINAPI
  12041. RSPSetEventFilterMasks (
  12042. PDRVSERVER pServer,
  12043. DWORD dwObjType,
  12044. LONG_PTR lObjectID,
  12045. ULONG64 ulEventMasks
  12046. )
  12047. {
  12048. ULONG_PTR args[] =
  12049. {
  12050. (ULONG_PTR) pServer, // The server to call
  12051. (ULONG_PTR) dwObjType, // type of object handle
  12052. (ULONG_PTR) lObjectID, // object handle
  12053. (ULONG_PTR) FALSE, // fSubMask
  12054. (ULONG_PTR) 0, // dwSubMasks
  12055. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasks low
  12056. (ULONG_PTR) HIDWORD(ulEventMasks) // ulEventMasks hi
  12057. };
  12058. REMOTE_ARG_TYPES argTypes[] =
  12059. {
  12060. lpServer,
  12061. Dword,
  12062. Dword,
  12063. Dword,
  12064. Dword,
  12065. Dword,
  12066. Dword
  12067. };
  12068. REMOTE_FUNC_ARGS funcArgs =
  12069. {
  12070. MAKELONG (TAPI_FUNC | SYNC | 6, tSetEventMasksOrSubMasks),
  12071. args,
  12072. argTypes
  12073. };
  12074. return (REMOTEDOFUNC (&funcArgs, "RSPSetEventFilter"));
  12075. }