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.

16474 lines
404 KiB

  1. /*++ BUILD Version: 0000 // Increment this if a change has global effects
  2. Copyright (c) 1996 - 1999 Microsoft Corporation
  3. Module Name:
  4. client.c
  5. Abstract:
  6. This module contains the tapi.dll implementation (client-side tapi)
  7. Author:
  8. Dan Knudson (DanKn) 01-Apr-1995
  9. Revision History:
  10. Notes:
  11. 1. Make all funcArg structs STATIC, & just do whatever mov's necessary
  12. for the params (saves mov's for flags, pfnPostProcess, funcName, &
  13. argTypes)
  14. --*/
  15. #include "stdafx.h"
  16. #include "windows.h"
  17. #include "wownt32.h"
  18. #include "stdarg.h"
  19. #include "stdio.h"
  20. #include "private.h"
  21. #include "tapsrv.h"
  22. #include "loc_comn.h"
  23. #include "prsht.h"
  24. #include "shellapi.h"
  25. #include "tapiperf.h"
  26. #include "tlnklist.h"
  27. #include "tapievt.h"
  28. #include <mmsystem.h>
  29. #include <mmddk.h>
  30. extern "C" {
  31. #include "tapihndl.h"
  32. }
  33. #ifdef _WIN64
  34. #define TALIGN_MASK 0xfffffff8
  35. #define TALIGN_COUNT 7
  36. #else
  37. #define TALIGN_MASK 0xfffffffc
  38. #define TALIGN_COUNT 3
  39. #endif
  40. #define ALIGN(a) (((a)+TALIGN_COUNT)&TALIGN_MASK)
  41. #define TAPILoadLibraryW LoadLibraryW
  42. CComModule _Module;
  43. BEGIN_OBJECT_MAP(ObjectMap)
  44. OBJECT_ENTRY(CLSID_TAPI, CTAPI)
  45. OBJECT_ENTRY(CLSID_DispatchMapper, CDispatchMapper)
  46. OBJECT_ENTRY(CLSID_RequestMakeCall, CRequest)
  47. END_OBJECT_MAP()
  48. typedef LONG (PASCAL *PQCSPROC)(HANDLE, DWORD, DWORD, LPOVERLAPPED);
  49. typedef LONG (PASCAL *TUIGDDPROC)(HTAPIDIALOGINSTANCE, LPVOID, DWORD);
  50. typedef LONG (PASCAL *TUIGDPROC)(TUISPIDLLCALLBACK, HTAPIDIALOGINSTANCE, LPVOID, DWORD, HANDLE);
  51. typedef LONG (PASCAL *TUIPROVPROC)(TUISPIDLLCALLBACK, HWND, DWORD);
  52. static PQCSPROC gpPostQueuedCompletionStatus = NULL;
  53. typedef LONG (PASCAL *TUILINECONFIGPROC)(TUISPIDLLCALLBACK, DWORD, HWND, LPCSTR);
  54. typedef LONG (PASCAL *TUILINECONFIGEDITPROC)(TUISPIDLLCALLBACK, DWORD, HWND, LPCSTR, LPVOID, DWORD, LPVARSTRING);
  55. typedef LONG (PASCAL *TUIPHONECONFIGPROC)(TUISPIDLLCALLBACK, DWORD, HWND, LPCSTR);
  56. typedef BOOL (PASCAL *ShellExecutePROC)(LPSHELLEXECUTEINFOW);
  57. HRESULT mapTAPIErrorCode(long lErrorCode);
  58. char *eventName(TAPI_EVENT event);
  59. //
  60. // messge handlers
  61. //
  62. void HandleLineDevStateMessage( CTAPI * pTapi, PASYNCEVENTMSG pParams );
  63. void HandleAddressStateMessage( PASYNCEVENTMSG pParams );
  64. void HandlePrivateChannelDataMessage( PASYNCEVENTMSG pParams );
  65. void HandleAgentStatusMessage(PASYNCEVENTMSG pParams);
  66. void HandleAgentSessionStatusMessage(PASYNCEVENTMSG pParams);
  67. void HandleQueueStatusMessage(PASYNCEVENTMSG pParams);
  68. void handleGroupStatusMessage(PASYNCEVENTMSG pParams);
  69. void handleProxyStatusMessage( CTAPI * pTapi, PASYNCEVENTMSG pParams);
  70. void HandleLineDevSpecificMessage( PASYNCEVENTMSG pParams );
  71. void HandlePhoneDevSpecificMessage( PASYNCEVENTMSG pParams );
  72. void HandleDevSpecificFeatureMessage( PASYNCEVENTMSG pParams );
  73. void HandleMonitorMediaMessage( PASYNCEVENTMSG pParams );
  74. void HandlePrivateUnadviseMessage( PASYNCEVENTMSG pParams );
  75. void HandlePrivateCallhubMessage( PASYNCEVENTMSG pParams );
  76. HRESULT HandleCallStateMessage( PASYNCEVENTMSG pParams );
  77. HRESULT HandleCallInfoMessage( PASYNCEVENTMSG pParams );
  78. HRESULT HandleMonitorDigitsMessage( PASYNCEVENTMSG pParams );
  79. HRESULT HandleMonitorToneMessage( PASYNCEVENTMSG pParams );
  80. HRESULT HandleGatherDigitsMessage( PASYNCEVENTMSG pParams );
  81. HRESULT HandleSendMSPDataMessage( PASYNCEVENTMSG pParams );
  82. HRESULT HandleLineQOSInfoMessage( PASYNCEVENTMSG pParams );
  83. void HandleLineCreate( PASYNCEVENTMSG pParams );
  84. void HandleLineRemove( PASYNCEVENTMSG pParams );
  85. void HandleLineRequest( CTAPI * pTapi, PASYNCEVENTMSG pParams );
  86. void HandleCallHubClose( PASYNCEVENTMSG pParams );
  87. void HandlePrivateMSPEvent( PASYNCEVENTMSG pParams );
  88. void HandleAcceptToAlert( PASYNCEVENTMSG pParams );
  89. HRESULT HandleLineGenerateMessage( PASYNCEVENTMSG pParams );
  90. HRESULT HandleLineCloseMessage( PASYNCEVENTMSG pParams );
  91. void HandlePhoneCreate( PASYNCEVENTMSG pParams );
  92. void HandlePhoneRemove( PASYNCEVENTMSG pParams );
  93. HRESULT HandlePhoneButtonMessage( PASYNCEVENTMSG pParams );
  94. HRESULT HandlePhoneStateMessage( PASYNCEVENTMSG pParams );
  95. HRESULT HandlePhoneCloseMessage( PASYNCEVENTMSG pParams );
  96. LONG WINAPI AllocClientResources( DWORD dwErrorClass );
  97. CAsyncReplyList * gpLineAsyncReplyList;
  98. CAsyncReplyList * gpPhoneAsyncReplyList;
  99. // The global retry queue
  100. CRetryQueue *gpRetryQueue;
  101. //
  102. //
  103. //
  104. #define ASNYC_MSG_BUF_SIZE 1024
  105. typedef struct _ASYNC_EVENTS_THREAD_PARAMS
  106. {
  107. BOOL bExitThread;
  108. DWORD dwBufSize;
  109. HANDLE hTapi32;
  110. HANDLE hWow32;
  111. HANDLE hThreadStartupEvent;
  112. LPBYTE pBuf;
  113. } ASYNC_EVENTS_THREAD_PARAMS, *PASYNC_EVENTS_THREAD_PARAMS;
  114. //
  115. // N.B. This structure MUST be a multiple of 8 bytes in size.
  116. //
  117. #if DBG
  118. typedef struct _MYMEMINFO
  119. {
  120. struct _MYMEMINFO * pNext;
  121. struct _MYMEMINFO * pPrev;
  122. DWORD dwSize;
  123. DWORD dwLine;
  124. PSTR pszFile;
  125. DWORD dwAlign;
  126. // LPTSTR pName;
  127. } MYMEMINFO, *PMYMEMINFO;
  128. PMYMEMINFO gpMemFirst = NULL, gpMemLast = NULL;
  129. CRITICAL_SECTION csMemoryList;
  130. BOOL gbBreakOnLeak = FALSE;
  131. void
  132. DumpMemoryList();
  133. #endif
  134. //
  135. // Global vars
  136. //
  137. BOOL gbExitThread = FALSE;
  138. HANDLE ghCallbackThread = NULL;
  139. HANDLE ghAsyncEventsThread = NULL;
  140. DWORD gdwTlsIndex;
  141. DWORD gdwNumLineDevices = 0;
  142. DWORD gdwNumPhoneDevices = 0;
  143. HANDLE ghAsyncEventsEvent = NULL;
  144. HANDLE ghAsyncRetryQueueEvent = NULL;
  145. HANDLE ghCallbackThreadEvent= NULL;
  146. HANDLE ghTapiInitShutdownSerializeMutex;
  147. //
  148. // handle table handle
  149. //
  150. extern HANDLE ghHandleTable;
  151. #if DBG
  152. DWORD gdwDebugLevel = 0;
  153. #endif
  154. typedef LONG (PASCAL *TAPIREQUESTMAKECALLPROC)(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
  155. typedef LONG (PASCAL *LINETRANSLATEDIALOGPROC)(HLINEAPP, DWORD, DWORD, HWND, LPWSTR);
  156. typedef LONG (PASCAL *LINEINITIALIZEPROC)(LPHLINEAPP, HINSTANCE, LINECALLBACK, LPWSTR, LPDWORD, LPDWORD,LPLINEINITIALIZEEXPARAMS);
  157. typedef LONG (PASCAL *LINESHUTDOWNPROC)(HLINEAPP);
  158. HINSTANCE ghTapi32 = NULL;
  159. HLINEAPP ghLineApp = NULL;
  160. LINEINITIALIZEPROC gpInitialize = NULL;
  161. LINESHUTDOWNPROC gpShutdown = NULL;
  162. CHashTable * gpCallHashTable = NULL;
  163. CHashTable * gpLineHashTable = NULL;
  164. CHashTable * gpCallHubHashTable = NULL;
  165. CHashTable * gpPrivateObjectHashTable = NULL;
  166. CHashTable * gpAgentHandlerHashTable = NULL;
  167. CHashTable * gpPhoneHashTable = NULL;
  168. CHashTable * gpHandleHashTable = NULL;
  169. PtrList gCallbackEventPtrList;
  170. HINSTANCE ghInst;
  171. PASYNC_EVENTS_THREAD_PARAMS gpAsyncEventsThreadParams = NULL;
  172. const CHAR gszTapi32MaxNumRequestRetries[] = "Tapi32MaxNumRequestRetries";
  173. const CHAR gszTapi32RequestRetryTimeout[] = "Tapi32RequestRetryTimeout";
  174. const CHAR gszTapi2AsynchronousCallTimeout[] = "AsynchronousCallTimeout";
  175. const CHAR gszTapi3RetryProcessingSleep[] = "Tapi3RetryProcessingSleep";
  176. const CHAR gszTapi3SyncWaitTimeOut[] = "Tapi3SyncWaitTimeOut"; // "Tapi3BlockingCallSleep";
  177. DWORD gdwMaxNumRequestRetries;
  178. DWORD gdwRequestRetryTimeout;
  179. DWORD gdwTapi2AsynchronousCallTimeout;
  180. static const DWORD DEFAULT_TAPI2_ASYNCRONOUS_CALL_TIMEOUT = 120000;
  181. static const DWORD DEFAULT_TAPI3_RETRY_PROCESSING_SLEEP = 0;
  182. static const DWORD DEFAULT_TAPI3_BLOCKING_CALL_SLEEP = 60000;
  183. DWORD gdwTapi3RetryProcessingSleep = DEFAULT_TAPI3_RETRY_PROCESSING_SLEEP;
  184. DWORD gdwTapi3SyncWaitTimeOut = DEFAULT_TAPI3_BLOCKING_CALL_SLEEP;
  185. const char szTapi32WndClass[] = "Tapi32WndClass";
  186. const CHAR gszTUISPI_providerConfig[] = "TUISPI_providerConfig";
  187. const CHAR gszTUISPI_providerGenericDialog[] = "TUISPI_providerGenericDialog";
  188. const CHAR gszTUISPI_providerGenericDialogData[] = "TUISPI_providerGenericDialogData";
  189. const CHAR gszTUISPI_providerInstall[] = "TUISPI_providerInstall";
  190. const CHAR gszTUISPI_providerRemove[] = "TUISPI_providerRemove";
  191. const CHAR gszTUISPI_lineConfigDialog[] = "TUISPI_lineConfigDialog";
  192. const CHAR gszTUISPI_lineConfigDialogEdit[] = "TUISPI_lineConfigDialogEdit";
  193. const CHAR gszTUISPI_phoneConfigDialog[] = "TUISPI_phoneConfigDialog";
  194. const CHAR gszTelephonyKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
  195. const CHAR gszNumEntries[] = "NumEntries";
  196. const CHAR gszLocations[] = "Locations";
  197. const WCHAR gszTAPI3[] = L"TAPI3";
  198. BOOL gbTranslateSimple = FALSE;
  199. BOOL gbTranslateSilent = FALSE;
  200. HINSTANCE ghWow32Dll = NULL;
  201. PUITHREADDATA gpUIThreadInstances = NULL;
  202. CRITICAL_SECTION gcsTapisrvCommunication;
  203. CRITICAL_SECTION gcsCallbackQueue;
  204. CRITICAL_SECTION gcsTapi32;
  205. CRITICAL_SECTION gcsGlobalInterfaceTable;
  206. /*This is the CRITICAL_SECTION to protect m_sTapiObjectArray*/
  207. CRITICAL_SECTION gcsTapiObjectArray;
  208. //This is the CRITICAL_SECTION to serialize access to functions
  209. //AllocClientResources and FreeClientResources
  210. CRITICAL_SECTION gcsClientResources;
  211. PCONTEXT_HANDLE_TYPE gphCx = (PCONTEXT_HANDLE_TYPE) NULL;
  212. LIST_ENTRY gTlsListHead;
  213. CRITICAL_SECTION gTlsCriticalSection;
  214. BOOL gbCriticalSectionsInitialized = FALSE;
  215. #if DBG
  216. const char *aszMsgs[] =
  217. {
  218. "LINE_ADDRESSSTATE",
  219. "LINE_CALLINFO",
  220. "LINE_CALLSTATE",
  221. "LINE_CLOSE",
  222. "LINE_DEVSPECIFIC",
  223. "LINE_DEVSPECIFICFEATURE",
  224. "LINE_GATHERDIGITS",
  225. "LINE_GENERATE",
  226. "LINE_LINEDEVSTATE",
  227. "LINE_MONITORDIGITS",
  228. "LINE_MONITORMEDIA",
  229. "LINE_MONITORTONE",
  230. "LINE_REPLY",
  231. "LINE_REQUEST",
  232. "PHONE_BUTTON",
  233. "PHONE_CLOSE",
  234. "PHONE_DEVSPECIFIC",
  235. "PHONE_REPLY",
  236. "PHONE_STATE",
  237. "LINE_CREATE",
  238. "PHONE_CREATE",
  239. "LINE_AGENTSPECIFIC",
  240. "LINE_AGENTSTATUS",
  241. "LINE_APPNEWCALL",
  242. "LINE_PROXYREQUEST",
  243. "LINE_REMOVE",
  244. "PHONE_REMOVE"
  245. };
  246. #endif
  247. LONG gaNoMemErrors[3] =
  248. {
  249. TAPIERR_REQUESTFAILED,
  250. LINEERR_NOMEM,
  251. PHONEERR_NOMEM
  252. };
  253. LONG gaInvalHwndErrors[3] =
  254. {
  255. TAPIERR_INVALWINDOWHANDLE,
  256. LINEERR_INVALPARAM,
  257. PHONEERR_INVALPARAM
  258. };
  259. LONG gaInvalPtrErrors[3] =
  260. {
  261. TAPIERR_INVALPOINTER,
  262. LINEERR_INVALPOINTER,
  263. PHONEERR_INVALPOINTER
  264. };
  265. LONG gaOpFailedErrors[3] =
  266. {
  267. TAPIERR_REQUESTFAILED,
  268. LINEERR_OPERATIONFAILED,
  269. PHONEERR_OPERATIONFAILED
  270. };
  271. LONG gaStructTooSmallErrors[3] =
  272. {
  273. TAPIERR_REQUESTFAILED,
  274. LINEERR_STRUCTURETOOSMALL,
  275. PHONEERR_STRUCTURETOOSMALL
  276. };
  277. LONG gaServiceNotRunningErrors[3] =
  278. {
  279. TAPIERR_REQUESTFAILED,
  280. LINEERR_SERVICE_NOT_RUNNING,
  281. PHONEERR_SERVICE_NOT_RUNNING
  282. };
  283. #define AllInitExOptions2_0 \
  284. (LINEINITIALIZEEXOPTION_USEHIDDENWINDOW | \
  285. LINEINITIALIZEEXOPTION_USEEVENT | \
  286. LINEINITIALIZEEXOPTION_USECOMPLETIONPORT)
  287. //
  288. // Function prototypes
  289. //
  290. void
  291. PASCAL
  292. lineMakeCallPostProcess(
  293. PASYNCEVENTMSG pMsg
  294. );
  295. #ifdef __cplusplus
  296. extern "C" {
  297. #endif
  298. BOOL
  299. WINAPI
  300. _CRT_INIT(
  301. HINSTANCE hDLL,
  302. DWORD dwReason,
  303. LPVOID lpReserved
  304. );
  305. #ifdef __cplusplus
  306. }
  307. #endif
  308. void
  309. FreeInitData(
  310. PT3INIT_DATA pInitData
  311. );
  312. LONG
  313. WINAPI
  314. FreeClientResources(
  315. void
  316. );
  317. LONG
  318. CALLBACK
  319. TUISPIDLLCallback(
  320. ULONG_PTR dwObjectID,
  321. DWORD dwObjectType,
  322. LPVOID lpParams,
  323. DWORD dwSize
  324. );
  325. BOOL
  326. CALLBACK
  327. TranslateDlgProc(
  328. HWND hwnd,
  329. UINT msg,
  330. WPARAM wParam,
  331. LPARAM lParam
  332. );
  333. void
  334. UIThread(
  335. LPVOID pParams
  336. );
  337. char *
  338. PASCAL
  339. MapResultCodeToText(
  340. LONG lResult,
  341. char *pszResult
  342. );
  343. void
  344. PASCAL
  345. lineDevSpecificPostProcess(
  346. PASYNCEVENTMSG pMsg
  347. );
  348. BOOL
  349. WaveStringIdToDeviceId(
  350. LPWSTR pwszStringID,
  351. LPCWSTR pwszDeviceType,
  352. LPDWORD pdwDeviceId
  353. );
  354. HRESULT
  355. ProcessMessage(
  356. PT3INIT_DATA,
  357. PASYNCEVENTMSG
  358. );
  359. //
  360. // The code...
  361. //
  362. #if DBG
  363. ////////////////////////////////////////////////////////////////////////////
  364. //
  365. // DWORD_CAST
  366. //
  367. // casts the argument from type ULONG_PTR to DWORD. provides verification
  368. // to make sure no data is lost during the cast. these casts are currently
  369. // unavoidable due to the way some of our tapisrv communication logic is
  370. // implemented.
  371. //
  372. // note that casts produce lvalues as long as the size of result does not
  373. // exceed the size of the value that is being cast (this is ms-specific
  374. // compiler extension that can be disabled by /Za). To be consistent with this
  375. // compiler cast behavior, this function returns result by reference.
  376. //
  377. DWORD DWORD_CAST(ULONG_PTR v)
  378. {
  379. DWORD dwReturnValue = (DWORD)v;
  380. if (v > dwReturnValue)
  381. {
  382. LOG((TL_ERROR,
  383. "DWORD_CAST: information will be lost during cast from %p to %lx",
  384. v, dwReturnValue));
  385. DebugBreak();
  386. }
  387. return dwReturnValue;
  388. }
  389. #endif
  390. ///////////////////////////////////////////////////////////////////////////////
  391. //
  392. // DWORD CreateHandleTableEntry(ULONG_PTR nEntry)
  393. //
  394. // indended to be used to map ULONG_PTR-sized values to 32-bit handles.
  395. //
  396. // CreateHandleTableEntry creates an entry in the handle table and returns a
  397. // 32-bit handle corresponding to it. the handle can later be used to retrieve
  398. // the original ULONG_PTR-sized value by calling GetHandleTableEntry or to
  399. // remove the entry in handle table by calling DeleteHandleTableEntry
  400. //
  401. // returns 0 if handle table entry creation failed.
  402. //
  403. DWORD CreateHandleTableEntry(ULONG_PTR nEntry)
  404. {
  405. LOG((TL_INFO,
  406. "CreateHandleTableEntry - enter. nEntry %p",
  407. nEntry));
  408. if (0 == ghHandleTable)
  409. {
  410. LOG((TL_ERROR,
  411. "CreateHandleTableEntry - handle table does not exist."));
  412. //
  413. // debug to see why this happened
  414. //
  415. _ASSERTE(FALSE);
  416. return 0;
  417. }
  418. //
  419. // get a 32-bit handle from the (up to) 64-bit pAddressLine. this
  420. // is needed to avoid marshaling/passing 64-bit values to tapisrv
  421. // (to preserve backward compatibility with older clients and servers)
  422. //
  423. DWORD dwHandle = NewObject(ghHandleTable, (LPVOID)nEntry, NULL);
  424. LOG((TL_INFO, "CreateHandleTableEntry - completed. returning [0x%lx]", dwHandle));
  425. return dwHandle;
  426. }
  427. //////////////////////////////////////////////////////////////////////////////
  428. //
  429. // void DeleteHandleTableEntry(DWORD dwHandle)
  430. //
  431. // DeleteHandleTableEntry function removes the specified entry from the
  432. // handle table.
  433. //
  434. void DeleteHandleTableEntry(DWORD dwHandle)
  435. {
  436. LOG((TL_INFO,
  437. "DeleteHandleTableEntry - enter. dwHandle 0x%lx", dwHandle ));
  438. if (0 == ghHandleTable)
  439. {
  440. LOG((TL_ERROR,
  441. "DeleteHandleTableEntry - handle table does not exist."));
  442. return;
  443. }
  444. //
  445. // handle 0 is a non-handle. deleting handle 0 is analogous to deleting NULL
  446. //
  447. if (0 == dwHandle)
  448. {
  449. LOG((TL_INFO,
  450. "DeleteHandleTableEntry - the handle is 0. Returning."));
  451. return;
  452. }
  453. //
  454. // if there are no other outstanding references to the handle (and there
  455. // should not be any), this will remove the entry from the handle table.
  456. //
  457. DereferenceObject(ghHandleTable, dwHandle, 1);
  458. LOG((TL_TRACE, "DeleteHandleTableEntry - finished."));
  459. return;
  460. }
  461. //////////////////////////////////////////////////////////////////////////////
  462. //
  463. // ULONG_PTR GetHandleTableEntry(DWORD dwHandle)
  464. //
  465. // this function uses the supplied 32-bit value to get the corresponding
  466. // ULONG_PTR entry from the handle table. This is used under 64-bit to
  467. // recover the original 64-bit value from the handle
  468. //
  469. ULONG_PTR GetHandleTableEntry(DWORD dwHandle)
  470. {
  471. LOG((TL_TRACE,
  472. "GetHandleTableEntry - enter. dwHandle 0x%lx",
  473. dwHandle));
  474. if (0 == ghHandleTable)
  475. {
  476. LOG((TL_ERROR,
  477. "GetHandleTableEntry - handle table does not exist."));
  478. return NULL;
  479. }
  480. //
  481. // get the pointer-sized value from the table
  482. //
  483. ULONG_PTR nValue = (ULONG_PTR)ReferenceObject(ghHandleTable, dwHandle, 0);
  484. //
  485. // we don't really need to keep a reference to it.
  486. // so don't -- this will simplify client logic
  487. //
  488. DereferenceObject(ghHandleTable, dwHandle, 1);
  489. LOG((TL_TRACE,
  490. "GetHandleTableEntry - succeeded. returning 0x%p",
  491. nValue));
  492. return nValue;
  493. }
  494. //***************************************************************************
  495. //***************************************************************************
  496. //***************************************************************************
  497. PWSTR
  498. PASCAL
  499. NotSoWideStringToWideString(
  500. LPCSTR lpStr,
  501. DWORD dwLength
  502. )
  503. {
  504. DWORD dwSize;
  505. PWSTR pwStr;
  506. if (IsBadStringPtrA (lpStr, dwLength))
  507. {
  508. return NULL;
  509. }
  510. dwSize = MultiByteToWideChar(
  511. GetACP(),
  512. MB_PRECOMPOSED,
  513. lpStr,
  514. dwLength,
  515. NULL,
  516. 0
  517. );
  518. pwStr = (PWSTR)ClientAlloc( dwSize * sizeof(WCHAR) );
  519. if (NULL != pwStr)
  520. {
  521. MultiByteToWideChar(
  522. GetACP(),
  523. MB_PRECOMPOSED,
  524. lpStr,
  525. dwLength,
  526. pwStr,
  527. dwSize
  528. );
  529. }
  530. return pwStr;
  531. }
  532. //***************************************************************************
  533. //***************************************************************************
  534. //***************************************************************************
  535. //
  536. //NOTE: This function requires that lpBase is a pointer to the start of
  537. // a TAPI struct that has dwTotalSize as the first DWORD
  538. //
  539. void
  540. PASCAL
  541. WideStringToNotSoWideString(
  542. LPBYTE lpBase,
  543. LPDWORD lpdwXxxSize
  544. )
  545. {
  546. DWORD dwSize;
  547. DWORD dwNewSize;
  548. DWORD dwOffset;
  549. DWORD dwTotalSize;
  550. DWORD dwUsedSize;
  551. PWSTR pString;
  552. PSTR lpszStringA;
  553. if ((dwSize = *lpdwXxxSize) != 0)
  554. {
  555. dwTotalSize = *((LPDWORD) lpBase);
  556. dwUsedSize = *(((LPDWORD) lpBase)+2);
  557. dwOffset = *(lpdwXxxSize + 1);
  558. pString = (PWSTR)(lpBase + dwOffset);
  559. if (IsBadStringPtrW (pString, dwSize))
  560. {
  561. LOG((TL_ERROR, "The service provider returned an invalid field in the structure 0x%p : 0x%p",
  562. lpBase, lpdwXxxSize));
  563. *lpdwXxxSize = 0;
  564. *(lpdwXxxSize+1) = 0;
  565. return;
  566. }
  567. //
  568. // Did we get enough chars?
  569. //
  570. if (dwUsedSize > dwOffset )
  571. {
  572. dwNewSize = WideCharToMultiByte(
  573. GetACP(),
  574. 0,
  575. pString,
  576. ( dwUsedSize >= (dwOffset+dwSize)) ?
  577. (dwSize/sizeof(WCHAR)) :
  578. (dwUsedSize - dwOffset) / sizeof(WCHAR),
  579. NULL,
  580. 0,
  581. NULL,
  582. NULL
  583. );
  584. lpszStringA = (PSTR)ClientAlloc( dwNewSize );
  585. if ( NULL == lpszStringA )
  586. {
  587. LOG((TL_ERROR, "Memory alloc failed - alloc(0x%08lx)",
  588. dwSize));
  589. LOG((TL_ERROR, "The service provider returned an invalid field size in the structure 0x08lx : 0x08lx",
  590. dwSize));
  591. *lpdwXxxSize = 0;
  592. *(lpdwXxxSize+1) = 0;
  593. return;
  594. }
  595. // lpszStringA[dwNewSize] = '\0';
  596. WideCharToMultiByte(
  597. GetACP(),
  598. 0,
  599. pString,
  600. // dwSize,
  601. ( dwUsedSize >= (dwOffset+dwSize)) ?
  602. (dwSize/sizeof(WCHAR)) :
  603. (dwUsedSize - dwOffset) / sizeof(WCHAR),
  604. lpszStringA,
  605. dwNewSize,
  606. NULL,
  607. NULL
  608. );
  609. //
  610. // Copy the new ANSI string back to where the Unicode string was
  611. // // and write out NULL terminator if possible.
  612. //
  613. CopyMemory ( (LPBYTE) pString,
  614. lpszStringA,
  615. dwNewSize // + (
  616. // ((dwNewSize + dwOffset) < dwUsedSize ) ?
  617. // 1 :
  618. // 0
  619. // )
  620. );
  621. ClientFree (lpszStringA);
  622. //
  623. // Update the number of bytes
  624. //
  625. *lpdwXxxSize = dwNewSize;
  626. }
  627. }
  628. }
  629. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  630. //
  631. // ReadRegistryValues
  632. //
  633. // During initialization, reads various values from the registry
  634. //
  635. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  636. BOOL
  637. ReadRegistryValues()
  638. {
  639. HKEY hKey;
  640. #if DBG
  641. gdwDebugLevel = 0;
  642. #endif
  643. gdwMaxNumRequestRetries = 40;
  644. gdwRequestRetryTimeout = 250; // milliseconds
  645. gdwTapi2AsynchronousCallTimeout = DEFAULT_TAPI2_ASYNCRONOUS_CALL_TIMEOUT;
  646. //
  647. // open the telephony key
  648. //
  649. if (RegOpenKeyEx(
  650. HKEY_LOCAL_MACHINE,
  651. gszTelephonyKey,
  652. 0,
  653. KEY_READ,
  654. &hKey
  655. ) == ERROR_SUCCESS)
  656. {
  657. DWORD dwDataSize, dwDataType;
  658. //
  659. // get the rpc max num of retries
  660. //
  661. dwDataSize = sizeof(DWORD);
  662. RegQueryValueEx(
  663. hKey,
  664. gszTapi32MaxNumRequestRetries,
  665. 0,
  666. &dwDataType,
  667. (LPBYTE) &gdwMaxNumRequestRetries,
  668. &dwDataSize
  669. );
  670. //
  671. // get the retry timeout
  672. //
  673. dwDataSize = sizeof(DWORD);
  674. RegQueryValueEx(
  675. hKey,
  676. gszTapi32RequestRetryTimeout,
  677. 0,
  678. &dwDataType,
  679. (LPBYTE) &gdwRequestRetryTimeout,
  680. &dwDataSize
  681. );
  682. //
  683. // get the timeout for asynchronous calls to tapi2
  684. //
  685. dwDataSize = sizeof(DWORD);
  686. LONG rc = RegQueryValueEx(
  687. hKey,
  688. gszTapi2AsynchronousCallTimeout,
  689. 0,
  690. &dwDataType,
  691. (LPBYTE) &gdwTapi2AsynchronousCallTimeout,
  692. &dwDataSize
  693. );
  694. if (rc != ERROR_SUCCESS)
  695. {
  696. gdwTapi2AsynchronousCallTimeout = DEFAULT_TAPI2_ASYNCRONOUS_CALL_TIMEOUT;
  697. }
  698. LOG((TL_INFO, "AsynchronousCallTimeout initialized to %d",
  699. gdwTapi2AsynchronousCallTimeout));
  700. //
  701. // get sleep time for retry processing
  702. //
  703. dwDataSize = sizeof(DWORD);
  704. rc = RegQueryValueEx(
  705. hKey,
  706. gszTapi3RetryProcessingSleep,
  707. 0,
  708. &dwDataType,
  709. (LPBYTE) &gdwTapi3RetryProcessingSleep,
  710. &dwDataSize
  711. );
  712. if (rc != ERROR_SUCCESS)
  713. {
  714. gdwTapi3RetryProcessingSleep = DEFAULT_TAPI3_RETRY_PROCESSING_SLEEP;
  715. }
  716. LOG((TL_INFO, "gdwTapi3RetryProcessingSleep initialized to %ld",
  717. gdwTapi3RetryProcessingSleep));
  718. //
  719. // get sleep time for blocking call timeout
  720. //
  721. dwDataSize = sizeof(DWORD);
  722. rc = RegQueryValueEx(
  723. hKey,
  724. gszTapi3SyncWaitTimeOut,
  725. 0,
  726. &dwDataType,
  727. (LPBYTE) &gdwTapi3SyncWaitTimeOut,
  728. &dwDataSize
  729. );
  730. if (rc != ERROR_SUCCESS)
  731. {
  732. gdwTapi3SyncWaitTimeOut = DEFAULT_TAPI3_BLOCKING_CALL_SLEEP;
  733. }
  734. LOG((TL_INFO, "gdwTapi3SyncWaitTimeOut initialized to %ld",
  735. gdwTapi3SyncWaitTimeOut));
  736. RegCloseKey (hKey);
  737. }
  738. return TRUE;
  739. }
  740. //***************************************************************************
  741. //***************************************************************************
  742. //***************************************************************************
  743. extern "C"
  744. BOOL
  745. WINAPI
  746. DllMain(
  747. HANDLE hDLL,
  748. DWORD dwReason,
  749. LPVOID lpReserved
  750. )
  751. {
  752. switch (dwReason)
  753. {
  754. case DLL_PROCESS_ATTACH:
  755. {
  756. gbCriticalSectionsInitialized = FALSE;
  757. #if DBG
  758. _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
  759. #endif
  760. ghInst = (HINSTANCE)hDLL;
  761. //
  762. // ATL initialization
  763. //
  764. #ifdef _MERGE_PROXYSTUB
  765. if (!PrxDllMain(ghInst, dwReason, lpReserved))
  766. {
  767. return FALSE;
  768. }
  769. #endif
  770. _Module.Init(ObjectMap, ghInst);
  771. //
  772. // Init CRT
  773. //
  774. if (!_CRT_INIT (ghInst, dwReason, lpReserved))
  775. {
  776. LOG((TL_ERROR,
  777. "DLL_PROCESS_ATTACH, _CRT_INIT() failed"
  778. ));
  779. return FALSE;
  780. }
  781. // Register for trace output.
  782. TRACELOGREGISTER(_T("tapi3"));
  783. LOG((TL_INFO, "DLL_PROCESS_ATTACH"));
  784. //
  785. // initialize stuff from the registry
  786. //
  787. ReadRegistryValues();
  788. //
  789. // Alloc a Tls index
  790. //
  791. if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
  792. {
  793. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, TlsAlloc() failed"));
  794. return FALSE;
  795. }
  796. //
  797. // Initialize Tls to NULL for this thread
  798. //
  799. TlsSetValue (gdwTlsIndex, NULL);
  800. //
  801. // Create mutex
  802. //
  803. ghTapiInitShutdownSerializeMutex = CreateMutex(NULL, FALSE, NULL);
  804. //
  805. // init critical sections
  806. //
  807. try
  808. {
  809. InitializeCriticalSection (&gcsTapisrvCommunication);
  810. }
  811. catch(...)
  812. {
  813. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  814. return FALSE;
  815. }
  816. try
  817. {
  818. InitializeCriticalSection (&gTlsCriticalSection);
  819. }
  820. catch(...)
  821. {
  822. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  823. DeleteCriticalSection (&gcsTapisrvCommunication);
  824. return FALSE;
  825. }
  826. try
  827. {
  828. InitializeCriticalSection (&gcsCallbackQueue);
  829. }
  830. catch(...)
  831. {
  832. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  833. DeleteCriticalSection (&gcsTapisrvCommunication);
  834. DeleteCriticalSection (&gTlsCriticalSection);
  835. return FALSE;
  836. }
  837. try
  838. {
  839. InitializeCriticalSection (&gcsTapi32);
  840. }
  841. catch(...)
  842. {
  843. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  844. DeleteCriticalSection (&gcsTapisrvCommunication);
  845. DeleteCriticalSection (&gTlsCriticalSection);
  846. DeleteCriticalSection (&gcsCallbackQueue);
  847. return FALSE;
  848. }
  849. try
  850. {
  851. InitializeCriticalSection (&gcsGlobalInterfaceTable);
  852. }
  853. catch(...)
  854. {
  855. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  856. DeleteCriticalSection (&gcsTapisrvCommunication);
  857. DeleteCriticalSection (&gTlsCriticalSection);
  858. DeleteCriticalSection (&gcsCallbackQueue);
  859. DeleteCriticalSection (&gcsTapi32);
  860. return FALSE;
  861. }
  862. try
  863. {
  864. InitializeCriticalSection (&gcsClientResources);
  865. }
  866. catch(...)
  867. {
  868. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  869. DeleteCriticalSection (&gcsTapisrvCommunication);
  870. DeleteCriticalSection (&gTlsCriticalSection);
  871. DeleteCriticalSection (&gcsCallbackQueue);
  872. DeleteCriticalSection (&gcsTapi32);
  873. DeleteCriticalSection (&gcsGlobalInterfaceTable);
  874. return FALSE;
  875. }
  876. try
  877. {
  878. InitializeCriticalSection (&gcsTapiObjectArray);
  879. }
  880. catch(...)
  881. {
  882. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  883. DeleteCriticalSection (&gcsTapisrvCommunication);
  884. DeleteCriticalSection (&gTlsCriticalSection);
  885. DeleteCriticalSection (&gcsCallbackQueue);
  886. DeleteCriticalSection (&gcsTapi32);
  887. DeleteCriticalSection (&gcsGlobalInterfaceTable);
  888. DeleteCriticalSection (&gcsClientResources);
  889. return FALSE;
  890. }
  891. #if DBG
  892. try
  893. {
  894. InitializeCriticalSection( &csMemoryList);
  895. }
  896. catch(...)
  897. {
  898. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, InitializeCriticalSection failed"));
  899. DeleteCriticalSection (&gcsTapisrvCommunication);
  900. DeleteCriticalSection (&gTlsCriticalSection);
  901. DeleteCriticalSection (&gcsCallbackQueue);
  902. DeleteCriticalSection (&gcsTapi32);
  903. DeleteCriticalSection (&gcsGlobalInterfaceTable);
  904. DeleteCriticalSection (&gcsClientResources);
  905. DeleteCriticalSection (&gcsTapiObjectArray);
  906. return FALSE;
  907. }
  908. #endif
  909. gbCriticalSectionsInitialized = TRUE;
  910. InitializeListHead (&gTlsListHead);
  911. HRESULT hr;
  912. //
  913. // gpCallHashTable
  914. //
  915. try
  916. {
  917. gpCallHashTable = new CHashTable;
  918. }
  919. catch(...)
  920. {
  921. // Initialize critical section in the constructor most likely threw this exception
  922. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHashTable constructor threw an exception"));
  923. return FALSE;
  924. }
  925. if ( NULL == gpCallHashTable )
  926. {
  927. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHashTable alloc failed"));
  928. return FALSE;
  929. }
  930. hr = gpCallHashTable->Initialize( 1 );
  931. if ( !SUCCEEDED(hr) )
  932. {
  933. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHashTable init failed"));
  934. return FALSE;
  935. }
  936. //
  937. // gpLineHashTable
  938. //
  939. try
  940. {
  941. gpLineHashTable = new CHashTable;
  942. }
  943. catch(...)
  944. {
  945. // Initialize critical section in the constructor most likely threw this exception
  946. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpLineHashTable constructor threw an exception"));
  947. return FALSE;
  948. }
  949. if ( NULL == gpLineHashTable )
  950. {
  951. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpLineHashTable alloc failed"));
  952. return FALSE;
  953. }
  954. hr = gpLineHashTable->Initialize( 1 );
  955. if ( !SUCCEEDED(hr) )
  956. {
  957. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpLineHashTable init failed"));
  958. return FALSE;
  959. }
  960. //
  961. // gpCallHubHashTable
  962. //
  963. try
  964. {
  965. gpCallHubHashTable = new CHashTable;
  966. }
  967. catch(...)
  968. {
  969. // Initialize critical section in the constructor most likely threw this exception
  970. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHubHashTable constructor threw an exception"));
  971. return FALSE;
  972. }
  973. if ( NULL == gpCallHubHashTable )
  974. {
  975. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHubHashTable alloc failed"));
  976. return FALSE;
  977. }
  978. hr = gpCallHubHashTable->Initialize( 1 );
  979. if ( !SUCCEEDED(hr) )
  980. {
  981. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpCallHubHashTable init failed"));
  982. return FALSE;
  983. }
  984. //
  985. // gpAgentHandlerHashTable
  986. //
  987. try
  988. {
  989. gpAgentHandlerHashTable = new CHashTable;
  990. }
  991. catch(...)
  992. {
  993. // Initialize critical section in the constructor most likely threw this exception
  994. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpAgentHandlerHashTable constructor threw an exception"));
  995. return FALSE;
  996. }
  997. if ( NULL == gpAgentHandlerHashTable )
  998. {
  999. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpAgentHandlerHashTable alloc failed"));
  1000. return FALSE;
  1001. }
  1002. hr = gpAgentHandlerHashTable->Initialize( 1 );
  1003. if ( !SUCCEEDED(hr) )
  1004. {
  1005. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpAgentHandlerHashTable init failed"));
  1006. return FALSE;
  1007. }
  1008. //
  1009. // gpPhoneHashTable
  1010. //
  1011. try
  1012. {
  1013. gpPhoneHashTable = new CHashTable;
  1014. }
  1015. catch(...)
  1016. {
  1017. // Initialize critical section in the constructor most likely threw this exception
  1018. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpPhoneHashTable constructor threw an exception"));
  1019. return FALSE;
  1020. }
  1021. if ( NULL == gpPhoneHashTable )
  1022. {
  1023. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpPhoneHashTable alloc failed"));
  1024. return FALSE;
  1025. }
  1026. hr = gpPhoneHashTable->Initialize( 1 );
  1027. if ( !SUCCEEDED(hr) )
  1028. {
  1029. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpPhoneHashTable init failed"));
  1030. return FALSE;
  1031. }
  1032. //
  1033. // gpHandleHashTable
  1034. //
  1035. try
  1036. {
  1037. gpHandleHashTable = new CHashTable;
  1038. }
  1039. catch(...)
  1040. {
  1041. // Initialize critical section in the constructor most likely threw this exception
  1042. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpHandleHashTable constructor threw an exception"));
  1043. return FALSE;
  1044. }
  1045. if ( NULL == gpHandleHashTable )
  1046. {
  1047. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpHandleHashTable alloc failed"));
  1048. return FALSE;
  1049. }
  1050. hr = gpHandleHashTable->Initialize( 1 );
  1051. if ( !SUCCEEDED(hr) )
  1052. {
  1053. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpHandleHashTable init failed"));
  1054. return FALSE;
  1055. }
  1056. //
  1057. // gpLineAsyncReplyList
  1058. //
  1059. try
  1060. {
  1061. gpLineAsyncReplyList = new CAsyncReplyList;
  1062. }
  1063. catch(...)
  1064. {
  1065. // Initialize critical section in the constructor most likely threw this exception
  1066. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpLineAsyncReplyList constructor threw an exception"));
  1067. return FALSE;
  1068. }
  1069. if ( NULL == gpLineAsyncReplyList )
  1070. {
  1071. LOG((TL_ERROR, "DLL_PROCESS_ATTACH - gpLineAsyncReplyList alloc failed"));
  1072. return FALSE;
  1073. }
  1074. //
  1075. // gpPhoneAsyncReplyList
  1076. //
  1077. try
  1078. {
  1079. gpPhoneAsyncReplyList = new CAsyncReplyList;
  1080. }
  1081. catch(...)
  1082. {
  1083. // Initialize critical section in the constructor most likely threw this exception
  1084. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpPhoneAsyncReplyList constructor threw an exception"));
  1085. return FALSE;
  1086. }
  1087. if ( NULL == gpPhoneAsyncReplyList )
  1088. {
  1089. LOG((TL_ERROR, "DLL_PROCESS_ATTACH - gpPhoneAsyncReplyList alloc failed"));
  1090. return FALSE;
  1091. }
  1092. //
  1093. // gpRetryQueue
  1094. //
  1095. try
  1096. {
  1097. gpRetryQueue = new CRetryQueue;
  1098. }
  1099. catch(...)
  1100. {
  1101. // Initialize critical section in the constructor most likely threw this exception
  1102. LOG((TL_ERROR, "DLL_PROCESS_ATTACH, gpRetryQueue constructor threw an exception"));
  1103. return FALSE;
  1104. }
  1105. if ( NULL == gpRetryQueue )
  1106. {
  1107. LOG((TL_ERROR, "DLL_PROCESS_ATTACH - gpRetryQueue alloc failed"));
  1108. return FALSE;
  1109. }
  1110. break;
  1111. }
  1112. case DLL_PROCESS_DETACH:
  1113. {
  1114. PCLIENT_THREAD_INFO pTls;
  1115. LOG((TL_INFO, "DLL_PROCESS_DETACH"));
  1116. if (gpCallHashTable != NULL)
  1117. {
  1118. gpCallHashTable->Shutdown();
  1119. delete gpCallHashTable;
  1120. }
  1121. if (gpLineHashTable != NULL)
  1122. {
  1123. gpLineHashTable->Shutdown();
  1124. delete gpLineHashTable;
  1125. }
  1126. if (gpCallHubHashTable != NULL)
  1127. {
  1128. gpCallHubHashTable->Shutdown();
  1129. delete gpCallHubHashTable;
  1130. }
  1131. if (gpAgentHandlerHashTable != NULL)
  1132. {
  1133. gpAgentHandlerHashTable->Shutdown();
  1134. delete gpAgentHandlerHashTable;
  1135. }
  1136. if (gpPhoneHashTable != NULL)
  1137. {
  1138. gpPhoneHashTable->Shutdown();
  1139. delete gpPhoneHashTable;
  1140. }
  1141. if (gpHandleHashTable != NULL)
  1142. {
  1143. gpHandleHashTable->Shutdown();
  1144. delete gpHandleHashTable;
  1145. }
  1146. CTAPI::m_sTAPIObjectArray.Shutdown();
  1147. delete gpLineAsyncReplyList;
  1148. delete gpPhoneAsyncReplyList;
  1149. delete gpRetryQueue;
  1150. //
  1151. // Clean up any Tls (no need to enter crit sec since process detaching)
  1152. //
  1153. while (!IsListEmpty (&gTlsListHead))
  1154. {
  1155. LIST_ENTRY *pEntry = RemoveHeadList (&gTlsListHead);
  1156. pTls = CONTAINING_RECORD (pEntry, CLIENT_THREAD_INFO, TlsList);
  1157. ClientFree (pTls->pBuf);
  1158. ClientFree (pTls);
  1159. }
  1160. //
  1161. // ATL shutdown
  1162. //
  1163. _Module.Term();
  1164. TlsFree( gdwTlsIndex );
  1165. if (!_CRT_INIT (ghInst, dwReason, lpReserved))
  1166. {
  1167. LOG((TL_ERROR, "_CRT_INIT() failed"));
  1168. }
  1169. //
  1170. // delete all our critical sections
  1171. //
  1172. if (gbCriticalSectionsInitialized)
  1173. {
  1174. DeleteCriticalSection (&gcsTapisrvCommunication);
  1175. DeleteCriticalSection (&gTlsCriticalSection);
  1176. DeleteCriticalSection (&gcsCallbackQueue);
  1177. DeleteCriticalSection (&gcsTapi32);
  1178. DeleteCriticalSection (&gcsGlobalInterfaceTable);
  1179. DeleteCriticalSection (&gcsClientResources);
  1180. DeleteCriticalSection (&gcsTapiObjectArray);
  1181. }
  1182. #if DBG
  1183. DumpMemoryList();
  1184. _CrtDumpMemoryLeaks();
  1185. if (gbCriticalSectionsInitialized)
  1186. {
  1187. DeleteCriticalSection( &csMemoryList );
  1188. }
  1189. #endif
  1190. //
  1191. // Close our mutex
  1192. //
  1193. CloseHandle( ghTapiInitShutdownSerializeMutex );
  1194. //
  1195. // do not deregister if the process is terminating -- working around
  1196. // bugs in rtutils that could cause a "deadlock" if DeregisterTracing
  1197. // is called from DllMain on process termination.
  1198. // also we want to delay unregistering until the end so that debugger
  1199. // output gets logged up to this point, if it is configured.
  1200. //
  1201. if (NULL == lpReserved)
  1202. {
  1203. TRACELOGDEREGISTER();
  1204. }
  1205. break;
  1206. }
  1207. case DLL_THREAD_ATTACH:
  1208. //
  1209. // First must init CRT
  1210. //
  1211. if (!_CRT_INIT (ghInst, dwReason, lpReserved))
  1212. {
  1213. LOG((TL_ERROR, "_CRT_INIT() failed"));
  1214. return FALSE;
  1215. }
  1216. //
  1217. // Initialize Tls to NULL for this thread
  1218. //
  1219. TlsSetValue (gdwTlsIndex, NULL);
  1220. break;
  1221. case DLL_THREAD_DETACH:
  1222. {
  1223. PCLIENT_THREAD_INFO pTls;
  1224. //
  1225. // Clean up any Tls
  1226. //
  1227. if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
  1228. {
  1229. EnterCriticalSection (&gTlsCriticalSection);
  1230. RemoveEntryList (&pTls->TlsList);
  1231. LeaveCriticalSection (&gTlsCriticalSection);
  1232. if (pTls->pBuf)
  1233. {
  1234. ClientFree (pTls->pBuf);
  1235. }
  1236. ClientFree (pTls);
  1237. }
  1238. //
  1239. // Finally, alert CRT
  1240. //
  1241. if (!_CRT_INIT (ghInst, dwReason, lpReserved))
  1242. {
  1243. LOG((TL_ERROR, "_CRT_INIT() failed"));
  1244. }
  1245. break;
  1246. }
  1247. } // switch
  1248. return TRUE;
  1249. }
  1250. ////////////////////////////////////////////////////////////////////
  1251. // QueueCallbackEvent
  1252. //
  1253. // Queues a raw async message that will be processed in the
  1254. // CallbackThread.
  1255. ////////////////////////////////////////////////////////////////////
  1256. void
  1257. QueueCallbackEvent(
  1258. PASYNCEVENTMSG pParams
  1259. )
  1260. {
  1261. PTAPICALLBACKEVENT pNew;
  1262. DWORD dwSize; // = sizeof (ASYNCEVENTMSG);
  1263. LOG((TL_TRACE, "QueueCallbackEvent - enter"));
  1264. LOG((TL_INFO, " hDevice ----> %lx", pParams->hDevice));
  1265. LOG((TL_INFO, " Msg ----> %lx", pParams->Msg));
  1266. LOG((TL_INFO, " Param1 ---> %lx", pParams->Param1));
  1267. LOG((TL_INFO, " Param2 ---> %lx", pParams->Param2));
  1268. LOG((TL_INFO, " Param3 ---> %lx", pParams->Param3));
  1269. dwSize = pParams->TotalSize;
  1270. pNew = (PTAPICALLBACKEVENT)ClientAlloc( sizeof(TAPICALLBACKEVENT) + (dwSize-sizeof(ASYNCEVENTMSG) ) );
  1271. if ( pNew != NULL)
  1272. {
  1273. pNew->type = CALLBACKTYPE_RAW_ASYNC_MESSAGE;
  1274. pNew->pTapi = NULL;
  1275. CopyMemory(
  1276. &pNew->data.asyncMessage,
  1277. pParams,
  1278. dwSize
  1279. );
  1280. // add to list
  1281. EnterCriticalSection( &gcsCallbackQueue );
  1282. try
  1283. {
  1284. gCallbackEventPtrList.push_back( (PVOID)pNew );
  1285. }
  1286. catch(...)
  1287. {
  1288. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1289. ClientFree( pNew );
  1290. }
  1291. LeaveCriticalSection( &gcsCallbackQueue );
  1292. SetEvent( ghCallbackThreadEvent );
  1293. LOG((TL_INFO, "QueueCallbackEvent - New pParams is ----> %p", pNew ));
  1294. }
  1295. else
  1296. {
  1297. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1298. return;
  1299. }
  1300. }
  1301. ////////////////////////////////////////////////////////////////////
  1302. // QueueCallbackEvent
  1303. //
  1304. // Queues a raw async message that will be processed in the
  1305. // CallbackThread.
  1306. ////////////////////////////////////////////////////////////////////
  1307. void
  1308. QueueCallbackEvent(
  1309. CTAPI *pTapi,
  1310. PASYNCEVENTMSG pParams
  1311. )
  1312. {
  1313. PTAPICALLBACKEVENT pNew;
  1314. DWORD dwSize; // = sizeof (ASYNCEVENTMSG);
  1315. LOG((TL_TRACE, "QueueCallbackEvent - enter"));
  1316. LOG((TL_INFO, " hDevice ----> %lx", pParams->hDevice));
  1317. LOG((TL_INFO, " Msg ----> %lx", pParams->Msg));
  1318. LOG((TL_INFO, " Param1 ---> %lx", pParams->Param1));
  1319. LOG((TL_INFO, " Param2 ---> %lx", pParams->Param2));
  1320. LOG((TL_INFO, " Param3 ---> %lx", pParams->Param3));
  1321. dwSize = pParams->TotalSize;
  1322. pNew = (PTAPICALLBACKEVENT)ClientAlloc( sizeof(TAPICALLBACKEVENT) + (dwSize-sizeof(ASYNCEVENTMSG) ) );
  1323. if ( pNew != NULL)
  1324. {
  1325. pNew->type = CALLBACKTYPE_RAW_ASYNC_MESSAGE;
  1326. pNew->pTapi = pTapi;
  1327. CopyMemory(
  1328. &pNew->data.asyncMessage,
  1329. pParams,
  1330. dwSize
  1331. );
  1332. // add to list
  1333. EnterCriticalSection( &gcsCallbackQueue );
  1334. try
  1335. {
  1336. gCallbackEventPtrList.push_back( (PVOID)pNew );
  1337. }
  1338. catch(...)
  1339. {
  1340. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1341. ClientFree( pNew );
  1342. }
  1343. LeaveCriticalSection( &gcsCallbackQueue );
  1344. SetEvent( ghCallbackThreadEvent );
  1345. LOG((TL_INFO, "QueueCallbackEvent - New pParams is ----> %p", pNew ));
  1346. }
  1347. else
  1348. {
  1349. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1350. return;
  1351. }
  1352. }
  1353. ////////////////////////////////////////////////////////////////////
  1354. // QueueCallbackEvent
  1355. //
  1356. // Queues a TAPI event message object that will be processed in the
  1357. // CallbackThread.
  1358. ////////////////////////////////////////////////////////////////////
  1359. BOOL
  1360. QueueCallbackEvent(
  1361. CTAPI * pTapi,
  1362. TAPI_EVENT te,
  1363. IDispatch * pEvent
  1364. )
  1365. {
  1366. BOOL bResult = TRUE;
  1367. PTAPICALLBACKEVENT pNew;
  1368. LOG((TL_TRACE, "QueueCallbackEvent - enter"));
  1369. #if DBG
  1370. LOG((TL_INFO, "QueueCallbackEvent - TAPI Event -> %lx %s", te, eventName(te) ));
  1371. #endif
  1372. pNew = (PTAPICALLBACKEVENT)ClientAlloc( sizeof(TAPICALLBACKEVENT) );
  1373. if ( pNew != NULL)
  1374. {
  1375. pNew->type = CALLBACKTYPE_TAPI_EVENT_OBJECT;
  1376. pNew->pTapi = pTapi;
  1377. pNew->data.tapiEvent.te = te;
  1378. pNew->data.tapiEvent.pEvent = pEvent;
  1379. // add to list
  1380. EnterCriticalSection( &gcsCallbackQueue );
  1381. try
  1382. {
  1383. gCallbackEventPtrList.push_back( (PVOID)pNew );
  1384. }
  1385. catch(...)
  1386. {
  1387. bResult = FALSE;
  1388. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1389. ClientFree( pNew );
  1390. }
  1391. LeaveCriticalSection( &gcsCallbackQueue );
  1392. if( bResult )
  1393. {
  1394. SetEvent( ghCallbackThreadEvent );
  1395. }
  1396. LOG((TL_INFO, "QueueCallbackEvent - New pParams is ----> %p", pNew ));
  1397. }
  1398. else
  1399. {
  1400. LOG((TL_ERROR, "QueueCallbackEvent - out of memory - losing message"));
  1401. bResult = FALSE;
  1402. }
  1403. return bResult;
  1404. }
  1405. ////////////////////////////////////////////////////////////////////
  1406. // DequeueCallbackEvent
  1407. //
  1408. // Pulls an event from the queue for the CallbackThread
  1409. ////////////////////////////////////////////////////////////////////
  1410. BOOL
  1411. DequeueCallbackEvent(
  1412. PTAPICALLBACKEVENT * ppCallBackEvent
  1413. )
  1414. {
  1415. BOOL bResult = TRUE;
  1416. LOG((TL_TRACE, "DequeueCallbackEvent - enter"));
  1417. EnterCriticalSection( &gcsCallbackQueue );
  1418. if (gCallbackEventPtrList.size() > 0)
  1419. {
  1420. *ppCallBackEvent = (PTAPICALLBACKEVENT) gCallbackEventPtrList.front();
  1421. try
  1422. {
  1423. gCallbackEventPtrList.pop_front();
  1424. }
  1425. catch(...)
  1426. {
  1427. LOG((TL_ERROR, "DequeueCallbackEvent - failed to pop from gCallbackEventPtrList"));
  1428. bResult = FALSE;
  1429. }
  1430. if( bResult )
  1431. {
  1432. if(IsBadReadPtr(*ppCallBackEvent, sizeof( TAPICALLBACKEVENT )) )
  1433. {
  1434. bResult = FALSE;
  1435. LOG((TL_ERROR, "DequeueCallbackEvent - IsBadReadPtr *ppCallBackEvent"));
  1436. }
  1437. }
  1438. }
  1439. else
  1440. {
  1441. // return false if there are no more messages
  1442. LOG((TL_ERROR, "DequeueCallbackEvent - no more messages"));
  1443. bResult = FALSE;
  1444. }
  1445. LeaveCriticalSection( &gcsCallbackQueue );
  1446. #if DBG
  1447. if (bResult)
  1448. {
  1449. LOG((TL_INFO, "DequeueCallbackEvent - returning %p", *ppCallBackEvent));
  1450. }
  1451. else
  1452. {
  1453. LOG((TL_INFO, "DequeueCallbackEvent - no event"));
  1454. }
  1455. #endif
  1456. return bResult;
  1457. }
  1458. BOOL WaitWithMessageLoop(HANDLE hEvent)
  1459. {
  1460. DWORD dwRet;
  1461. MSG msg;
  1462. while(1)
  1463. {
  1464. dwRet = MsgWaitForMultipleObjects(
  1465. 1, // One event to wait for
  1466. &hEvent, // The array of events
  1467. FALSE, // Wait for 1 event
  1468. INFINITE, // Timeout value
  1469. QS_ALLINPUT
  1470. ); // Any message wakes up
  1471. // There is a window message available. Dispatch it.
  1472. while(PeekMessage(&msg,NULL,0,0xFFFFFFFF,PM_REMOVE))
  1473. {
  1474. TranslateMessage(&msg);
  1475. DispatchMessage(&msg);
  1476. }
  1477. if (dwRet == WAIT_OBJECT_0)
  1478. {
  1479. return TRUE;
  1480. }
  1481. }
  1482. }
  1483. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1484. //
  1485. // CallbackThread
  1486. //
  1487. // Thread proc used to call application's callback routines.
  1488. //
  1489. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  1490. void
  1491. CallbackThread(
  1492. LPVOID pv
  1493. )
  1494. {
  1495. HINSTANCE hLib;
  1496. LOG((TL_TRACE, "CallbackThread: enter"));
  1497. //
  1498. // make sure we're CoInitialized
  1499. //
  1500. if ( !(SUCCEEDED( CoInitializeEx(NULL, COINIT_MULTITHREADED) ) ) )
  1501. {
  1502. LOG((TL_ERROR, "CallbackThread: CoInitialize failed"));
  1503. }
  1504. hLib = LoadLibrary("tapi3.dll");
  1505. while (TRUE)
  1506. {
  1507. //
  1508. // put the break here, so when the
  1509. // flag is set, we still flush the callbackevent
  1510. // queue in the while(TRUE) loop below
  1511. //
  1512. if (gbExitThread)
  1513. {
  1514. LOG((TL_TRACE, "CallbackThread: gbExitThread"));
  1515. break;
  1516. }
  1517. LOG((TL_INFO, "CallbackThread: Wait for event"));
  1518. DWORD dwSignalled;
  1519. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  1520. INFINITE,
  1521. 1,
  1522. &ghCallbackThreadEvent,
  1523. &dwSignalled);
  1524. /*
  1525. WaitForSingleObject(
  1526. ghCallbackThreadEvent,
  1527. INFINITE
  1528. );
  1529. */
  1530. while (TRUE)
  1531. {
  1532. PTAPICALLBACKEVENT pCallBackEvent;
  1533. HRESULT hr = S_OK;
  1534. //
  1535. // get the event
  1536. //
  1537. if (!DequeueCallbackEvent(&pCallBackEvent ) )
  1538. {
  1539. LOG((TL_ERROR, "CallbackThread: The DequeueCallbackEvent returned a wrong value"));
  1540. break;
  1541. }
  1542. if(pCallBackEvent->type == CALLBACKTYPE_RAW_ASYNC_MESSAGE)
  1543. {
  1544. PASYNCEVENTMSG pParams;
  1545. LOG((TL_INFO, "CallbackThread: event type is CALLBACKTYPE_RAW_ASYNC_MESSAGE"));
  1546. pParams = &pCallBackEvent->data.asyncMessage;
  1547. //
  1548. // call the handler
  1549. //
  1550. switch( pParams->Msg )
  1551. {
  1552. #ifdef USE_PHONEMSP
  1553. case PRIVATE_PHONESETHOOKSWITCH:
  1554. {
  1555. CPhoneMSPCall::HandlePrivateHookSwitch( pParams );
  1556. break;
  1557. }
  1558. #endif USE_PHONEMSP
  1559. case LINE_CREATE:
  1560. {
  1561. HandleLineCreate( pParams );
  1562. break;
  1563. }
  1564. case LINE_REMOVE:
  1565. {
  1566. HandleLineRemove( pParams );
  1567. break;
  1568. }
  1569. case PHONE_STATE:
  1570. {
  1571. HandlePhoneStateMessage( pParams );
  1572. break;
  1573. }
  1574. case PHONE_CREATE:
  1575. {
  1576. HandlePhoneCreate( pParams );
  1577. break;
  1578. }
  1579. case PHONE_REMOVE:
  1580. {
  1581. HandlePhoneRemove( pParams );
  1582. break;
  1583. }
  1584. case PRIVATE_ISDN__ACCEPTTOALERT:
  1585. {
  1586. HandleAcceptToAlert( pParams );
  1587. break;
  1588. }
  1589. case LINE_PROXYSTATUS:
  1590. {
  1591. handleProxyStatusMessage(pCallBackEvent->pTapi, pParams);
  1592. break;
  1593. }
  1594. default:
  1595. LOG((TL_WARN, "CallbackThread: asyncevent type not handled %x", pParams->Msg ));
  1596. break;
  1597. }
  1598. }
  1599. else
  1600. {
  1601. //
  1602. // fire the event
  1603. //
  1604. CTAPI * pTapi = pCallBackEvent->pTapi;
  1605. LOG((TL_INFO, "CallbackThread: event type is CALLBACKTYPE_TAPI_EVENT_OBJECT"));
  1606. #if DBG
  1607. LOG((TL_INFO, "CallbackThread: firing event event -> %lx %s tapi[%p]",
  1608. pCallBackEvent->data.tapiEvent.te,
  1609. eventName(pCallBackEvent->data.tapiEvent.te),
  1610. pTapi));
  1611. #endif
  1612. pTapi->EventFire(
  1613. pCallBackEvent->data.tapiEvent.te,
  1614. pCallBackEvent->data.tapiEvent.pEvent
  1615. );
  1616. pTapi->Release();
  1617. }
  1618. //
  1619. // free the message
  1620. //
  1621. ClientFree( pCallBackEvent );
  1622. }
  1623. }
  1624. CoUninitialize();
  1625. if (hLib != NULL)
  1626. {
  1627. FreeLibraryAndExitThread ((HINSTANCE)hLib, 0);
  1628. }
  1629. else
  1630. {
  1631. ExitThread(0);
  1632. }
  1633. LOG((TL_TRACE, "CallbackThread: exit"));
  1634. }
  1635. void
  1636. PASCAL
  1637. lineCompleteCallPostProcess(
  1638. PASYNCEVENTMSG pMsg
  1639. );
  1640. void
  1641. PASCAL
  1642. lineGatherDigitsWPostProcess(
  1643. PASYNCEVENTMSG pMsg
  1644. );
  1645. void
  1646. PASCAL
  1647. lineSetupConferencePostProcess(
  1648. PASYNCEVENTMSG pMsg
  1649. );
  1650. void
  1651. PASCAL
  1652. phoneDevSpecificPostProcess(
  1653. PASYNCEVENTMSG pMsg
  1654. );
  1655. ///////////////////////////////////////////////////////////////////////////////
  1656. //
  1657. // array of functions. function index is passed to tapisrv when we make an
  1658. // asynchronous tapisrv call. in LINE_REPLY, we get this index back, and call
  1659. // the appropriate function. we need to do this because we cannot pass function
  1660. // address to tapisrv
  1661. //
  1662. POSTPROCESSPROC gPostProcessingFunctions[] =
  1663. {
  1664. NULL,
  1665. lineDevSpecificPostProcess,
  1666. lineCompleteCallPostProcess,
  1667. lineMakeCallPostProcess,
  1668. lineGatherDigitsWPostProcess,
  1669. lineSetupConferencePostProcess,
  1670. phoneDevSpecificPostProcess
  1671. };
  1672. /////////////////////////////////////
  1673. //
  1674. // GetFunctionIndex
  1675. //
  1676. // find the array index of the function.
  1677. //
  1678. // returns 0 if the function was not found in the array
  1679. //
  1680. DWORD GetFunctionIndex(POSTPROCESSPROC Function)
  1681. {
  1682. const int nArraySize =
  1683. sizeof(gPostProcessingFunctions)/sizeof(POSTPROCESSPROC);
  1684. for (int i = 0; i < nArraySize; i++)
  1685. {
  1686. if (Function == gPostProcessingFunctions[i])
  1687. {
  1688. break;
  1689. }
  1690. }
  1691. //
  1692. // the function that is passed in had better be in the array. if not -- this should be caught in testing!
  1693. //
  1694. _ASSERTE( (0 != i) && (i < nArraySize) );
  1695. if (i == nArraySize)
  1696. {
  1697. LOG((TL_ERROR,
  1698. "GetFunctionIndex: function %p is not found in the array of functions!",
  1699. Function));
  1700. i = 0;
  1701. }
  1702. LOG((TL_INFO,
  1703. "GetFunctionIndex: function %p mapped to index %d.", Function, i));
  1704. return i;
  1705. }
  1706. //**************************************************************************
  1707. //**************************************************************************
  1708. //**************************************************************************
  1709. void
  1710. AsyncEventsThread(
  1711. PASYNC_EVENTS_THREAD_PARAMS pAsyncEventsThreadParams
  1712. )
  1713. {
  1714. BOOL *pbExitThread = &pAsyncEventsThreadParams->bExitThread,
  1715. bRetry;
  1716. HANDLE hStartupEvent = pAsyncEventsThreadParams->hThreadStartupEvent;
  1717. DWORD dwBufSize = pAsyncEventsThreadParams->dwBufSize;
  1718. LPBYTE pBuf = pAsyncEventsThreadParams->pBuf;
  1719. PTAPI32_MSG pMsg = (PTAPI32_MSG) pBuf;
  1720. HANDLE ahWaitForTheseEvents[]={
  1721. ghAsyncRetryQueueEvent,
  1722. ghAsyncEventsEvent
  1723. };
  1724. LOG((TL_TRACE, "AsyncEventsThread: enter"));
  1725. if ( !(SUCCEEDED( CoInitializeEx(NULL, COINIT_MULTITHREADED) ) ) )
  1726. {
  1727. LOG((TL_ERROR, "AsyncEventsThread: CoInitialize failed "));
  1728. }
  1729. //
  1730. // mark retryqueue as open for new entries
  1731. //
  1732. gpRetryQueue->OpenForNewEntries();
  1733. //
  1734. // it is now ok for events to be posted to the retry queue
  1735. //
  1736. BOOL bSetStartuptEvent = SetEvent(hStartupEvent);
  1737. if (!bSetStartuptEvent)
  1738. {
  1739. LOG((TL_ERROR,
  1740. "AsyncEventsThread - failed to signal hStartupEvent event. LastError = 0x%lx",
  1741. GetLastError()));
  1742. return;
  1743. }
  1744. //
  1745. // we will never need this event again. the creator of the thread will
  1746. // release it
  1747. //
  1748. hStartupEvent = NULL;
  1749. //
  1750. // Just loop reading async events/completions from server &
  1751. // handling them
  1752. //
  1753. while (1)
  1754. {
  1755. DWORD dwUsedSize, dwNeededSize;
  1756. PASYNCEVENTMSG pAsyncEventMsg;
  1757. //
  1758. // Check to see if xxxShutdown or FreeClientResources
  1759. // is signaling us to exit (we need to check both before
  1760. // & after the wait to dela with a event setting/resetting
  1761. // race condition between FreeClientResources & Tapisrv)
  1762. //
  1763. if (*pbExitThread)
  1764. {
  1765. LOG((TL_INFO, "AsyncEventsThread: exit requested"));
  1766. break;
  1767. }
  1768. //
  1769. // Block until tapisrv signals us that it has some event data for us
  1770. //
  1771. {
  1772. DWORD dwSignalled;
  1773. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  1774. INFINITE,
  1775. sizeof(ahWaitForTheseEvents)/sizeof(HANDLE),
  1776. ahWaitForTheseEvents,
  1777. &dwSignalled);
  1778. /*
  1779. dwSignalled = WaitForMultipleObjects(
  1780. sizeof(ahWaitForTheseEvents)/sizeof(HANDLE),
  1781. ahWaitForTheseEvents,
  1782. FALSE,
  1783. INFINITE
  1784. );
  1785. */
  1786. //
  1787. // map for dwSignalled:
  1788. //
  1789. // 0 == ghAsyncRetryQueueEvent,
  1790. // 1 == ghAsyncEventsEvent,
  1791. //
  1792. dwSignalled = dwSignalled - WAIT_OBJECT_0;
  1793. if( 0 == dwSignalled )
  1794. {
  1795. //
  1796. // Now lets process the Re-try Queue
  1797. //
  1798. LOG((TL_INFO, "AsyncEventsThread: Retry Queue signalled"));
  1799. gpRetryQueue->ProcessQueue();
  1800. //
  1801. // Don't want to process RPC so...
  1802. //
  1803. continue;
  1804. }
  1805. }
  1806. //
  1807. // Check to see if xxxShutdown or FreeClientResources
  1808. // is signaling us to exit
  1809. //
  1810. if (*pbExitThread)
  1811. {
  1812. LOG((TL_INFO, "AsyncEventsThread: exit requested."));
  1813. break;
  1814. }
  1815. //
  1816. // Retrieve the data from tapisrv
  1817. //
  1818. AsyncEventsThread_clientRequest:
  1819. do
  1820. {
  1821. pMsg->u.Req_Func = xGetAsyncEvents;
  1822. pMsg->Params[0] = dwBufSize - sizeof (TAPI32_MSG);
  1823. dwUsedSize = sizeof (TAPI32_MSG);
  1824. RpcTryExcept
  1825. {
  1826. ClientRequest (gphCx, (unsigned char *) pMsg, dwBufSize, (LONG *)&dwUsedSize);
  1827. bRetry = FALSE;
  1828. }
  1829. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  1830. {
  1831. bRetry = !(*pbExitThread);
  1832. LOG((
  1833. TL_WARN,
  1834. "AsyncEventsThread: rpc exception %d handled",
  1835. RpcExceptionCode()
  1836. ));
  1837. Sleep (10);
  1838. }
  1839. RpcEndExcept
  1840. } while (bRetry);
  1841. #if DBG
  1842. if (
  1843. ( dwUsedSize > dwBufSize )
  1844. ||
  1845. ( pMsg->Params[2] > dwBufSize )
  1846. )
  1847. {
  1848. LOG((TL_ERROR, "OVERFLOW!!!"));
  1849. LOG((TL_ERROR, "Watch this..."));
  1850. ClientFree( ClientAlloc( 0x10000 ) );
  1851. }
  1852. #endif
  1853. if ((dwUsedSize = pMsg->Params[2]) == 0 &&
  1854. (dwNeededSize = pMsg->Params[1]) != 0)
  1855. {
  1856. //
  1857. // There's a msg waiting for us that is bigger than our buffer,
  1858. // so alloc a larger buffer & try again
  1859. //
  1860. dwNeededSize += sizeof (TAPI32_MSG) + 128;
  1861. LOG((
  1862. TL_INFO,
  1863. "AsyncEventsThread: allocating larger event buf (size=x%x)",
  1864. dwNeededSize
  1865. ));
  1866. //
  1867. // deallocate buffer that we currently have
  1868. //
  1869. ClientFree(pBuf);
  1870. pBuf = NULL;
  1871. dwBufSize = 0;
  1872. //
  1873. // allocate a bigger memory chunk. try until successful or exit is requested.
  1874. //
  1875. while (!(*pbExitThread))
  1876. {
  1877. //
  1878. // attempt to allocate a bigger memory chunk
  1879. //
  1880. pBuf = (LPBYTE)ClientAlloc (dwNeededSize);
  1881. if ((NULL == pBuf))
  1882. {
  1883. //
  1884. // no memory. log a message and yeld, giving other apps/
  1885. // threads a chance to free up some memory
  1886. //
  1887. LOG((TL_ERROR,
  1888. "AsyncEventsThread: failed to allocate memory for a larger event buffer"
  1889. ));
  1890. Sleep(10);
  1891. }
  1892. else
  1893. {
  1894. //
  1895. // we got our memory. break out of allocation attempt cycle
  1896. //
  1897. break;
  1898. }
  1899. }
  1900. //
  1901. // did we have any luck allocating memory?
  1902. //
  1903. if (NULL == pBuf)
  1904. {
  1905. //
  1906. // we tried hard but did not get the memory. we did our best.
  1907. // now break out of message processing loop.
  1908. //
  1909. LOG((TL_ERROR,
  1910. "AsyncEventsThread: failed to allocate memory."
  1911. ));
  1912. break;
  1913. }
  1914. //
  1915. // reallocated memory to get a larger buffer. try to get the message again.
  1916. //
  1917. dwBufSize = dwNeededSize;
  1918. pMsg = (PTAPI32_MSG) pBuf;
  1919. goto AsyncEventsThread_clientRequest;
  1920. }
  1921. //
  1922. // Handle the events
  1923. //
  1924. pAsyncEventMsg = (PASYNCEVENTMSG) (pBuf + sizeof (TAPI32_MSG));
  1925. while (dwUsedSize)
  1926. {
  1927. //
  1928. // pAsyncEventMsg->InitContext the 32-bit handle. recover the
  1929. // pointer value for pInitData from the handle.
  1930. //
  1931. PT3INIT_DATA pInitData = (PT3INIT_DATA) GetHandleTableEntry(pAsyncEventMsg->InitContext);
  1932. DWORD dwNumInits;
  1933. LOG((
  1934. TL_INFO,
  1935. "AsyncEventsThread: msg=%ld, hDevice=x%x, OpenContext =x%lx, p1=x%lx, p2=x%lx, p3=x%lx, pInitData=%p",
  1936. pAsyncEventMsg->Msg,
  1937. pAsyncEventMsg->hDevice,
  1938. pAsyncEventMsg->OpenContext,
  1939. pAsyncEventMsg->Param1,
  1940. pAsyncEventMsg->Param2,
  1941. pAsyncEventMsg->Param3,
  1942. pInitData
  1943. ));
  1944. //
  1945. // Special case for UI msgs (not fwd'd to client)
  1946. //
  1947. switch (pAsyncEventMsg->Msg)
  1948. {
  1949. case LINE_CREATEDIALOGINSTANCE:
  1950. {
  1951. LOG((TL_INFO, "AsyncEventsThread: LINE_CREATEDIALOGINSTANCE"));
  1952. DWORD dwThreadID,
  1953. dwDataOffset = pAsyncEventMsg->Param1,
  1954. dwDataSize = pAsyncEventMsg->Param2,
  1955. dwUIDllNameOffset = pAsyncEventMsg->Param3;
  1956. PUITHREADDATA pUIThreadData;
  1957. if (!(pUIThreadData = (PUITHREADDATA)ClientAlloc (sizeof (UITHREADDATA))))
  1958. {
  1959. goto LINE_CREATEDIALOGINSTANCE_error;
  1960. }
  1961. if ((pUIThreadData->dwSize = dwDataSize) != 0)
  1962. {
  1963. if (!(pUIThreadData->pParams = ClientAlloc (dwDataSize)))
  1964. {
  1965. goto LINE_CREATEDIALOGINSTANCE_error;
  1966. }
  1967. CopyMemory(
  1968. pUIThreadData->pParams,
  1969. ((LPBYTE)pAsyncEventMsg) + dwDataOffset,
  1970. dwDataSize
  1971. );
  1972. }
  1973. if (!(pUIThreadData->hUIDll = TAPILoadLibraryW(
  1974. (PWSTR)(((LPBYTE) pAsyncEventMsg) +
  1975. dwUIDllNameOffset)
  1976. )))
  1977. {
  1978. LOG((
  1979. TL_ERROR,
  1980. "LoadLibraryW(%ls) failed, err=%d",
  1981. ((LPBYTE) pAsyncEventMsg) + dwUIDllNameOffset,
  1982. GetLastError()
  1983. ));
  1984. goto LINE_CREATEDIALOGINSTANCE_error;
  1985. }
  1986. if (!(pUIThreadData->pfnTUISPI_providerGenericDialog =
  1987. (TUISPIPROC) GetProcAddress(
  1988. pUIThreadData->hUIDll,
  1989. (LPCSTR) gszTUISPI_providerGenericDialog
  1990. )))
  1991. {
  1992. LOG((
  1993. TL_INFO,
  1994. "GetProcAddr(TUISPI_providerGenericDialog) failed"
  1995. ));
  1996. goto LINE_CREATEDIALOGINSTANCE_error;
  1997. }
  1998. pUIThreadData->pfnTUISPI_providerGenericDialogData =
  1999. (TUISPIPROC) GetProcAddress(
  2000. pUIThreadData->hUIDll,
  2001. (LPCSTR) gszTUISPI_providerGenericDialogData
  2002. );
  2003. if (!(pUIThreadData->hEvent = CreateEvent(
  2004. (LPSECURITY_ATTRIBUTES) NULL,
  2005. TRUE, // manual reset
  2006. FALSE, // non-signaled
  2007. NULL // unnamed
  2008. )))
  2009. {
  2010. goto LINE_CREATEDIALOGINSTANCE_error;
  2011. }
  2012. pUIThreadData->htDlgInst = (HTAPIDIALOGINSTANCE)
  2013. pAsyncEventMsg->hDevice;
  2014. //
  2015. // Safely add this instance to the global list
  2016. // (check if dwNumInits == 0, & if so fail)
  2017. //
  2018. EnterCriticalSection( &gcsTapiObjectArray );
  2019. dwNumInits = CTAPI::m_sTAPIObjectArray.GetSize();
  2020. LeaveCriticalSection ( &gcsTapiObjectArray );
  2021. EnterCriticalSection (&gcsTapisrvCommunication);
  2022. if (dwNumInits != 0)
  2023. {
  2024. if ((pUIThreadData->pNext = gpUIThreadInstances))
  2025. {
  2026. pUIThreadData->pNext->pPrev = pUIThreadData;
  2027. }
  2028. gpUIThreadInstances = pUIThreadData;
  2029. LeaveCriticalSection (&gcsTapisrvCommunication);
  2030. }
  2031. else
  2032. {
  2033. LeaveCriticalSection (&gcsTapisrvCommunication);
  2034. goto LINE_CREATEDIALOGINSTANCE_error;
  2035. }
  2036. if ((pUIThreadData->hThread = CreateThread(
  2037. (LPSECURITY_ATTRIBUTES) NULL,
  2038. 0,
  2039. (LPTHREAD_START_ROUTINE) UIThread,
  2040. (LPVOID) pUIThreadData,
  2041. 0,
  2042. &dwThreadID
  2043. )))
  2044. {
  2045. goto AsyncEventsThread_decrUsedSize;
  2046. }
  2047. //
  2048. // If here an error occured, so safely remove the ui
  2049. // thread data struct from the global list
  2050. //
  2051. EnterCriticalSection (&gcsTapisrvCommunication);
  2052. if (pUIThreadData->pNext)
  2053. {
  2054. pUIThreadData->pNext->pPrev = pUIThreadData->pPrev;
  2055. }
  2056. if (pUIThreadData->pPrev)
  2057. {
  2058. pUIThreadData->pPrev->pNext = pUIThreadData->pNext;
  2059. }
  2060. else
  2061. {
  2062. gpUIThreadInstances = pUIThreadData->pNext;
  2063. }
  2064. LeaveCriticalSection (&gcsTapisrvCommunication);
  2065. LINE_CREATEDIALOGINSTANCE_error:
  2066. if (pUIThreadData)
  2067. {
  2068. if (pUIThreadData->pParams)
  2069. {
  2070. ClientFree (pUIThreadData->pParams);
  2071. }
  2072. if (pUIThreadData->hUIDll)
  2073. {
  2074. FreeLibrary (pUIThreadData->hUIDll);
  2075. }
  2076. if (pUIThreadData->hEvent)
  2077. {
  2078. CloseHandle (pUIThreadData->hEvent);
  2079. }
  2080. ClientFree (pUIThreadData);
  2081. }
  2082. {
  2083. FUNC_ARGS funcArgs =
  2084. {
  2085. MAKELONG (LINE_FUNC | SYNC | 1, xFreeDialogInstance),
  2086. {
  2087. pAsyncEventMsg->hDevice
  2088. },
  2089. {
  2090. Dword
  2091. }
  2092. };
  2093. DOFUNC (&funcArgs, "FreeDialogInstance");
  2094. }
  2095. goto AsyncEventsThread_decrUsedSize;
  2096. }
  2097. case LINE_SENDDIALOGINSTANCEDATA:
  2098. {
  2099. LOG((TL_INFO, "AsyncEventsThread: LINE_SENDDIALOGINSTANCEDATA"));
  2100. PUITHREADDATA pUIThreadData = gpUIThreadInstances;
  2101. HTAPIDIALOGINSTANCE htDlgInst = (HTAPIDIALOGINSTANCE)
  2102. pAsyncEventMsg->hDevice;
  2103. EnterCriticalSection (&gcsTapisrvCommunication);
  2104. while (pUIThreadData)
  2105. {
  2106. if (pUIThreadData->htDlgInst == htDlgInst)
  2107. {
  2108. WaitForSingleObject (pUIThreadData->hEvent, INFINITE);
  2109. ((TUIGDDPROC)(*pUIThreadData->pfnTUISPI_providerGenericDialogData))(
  2110. htDlgInst,
  2111. ((LPBYTE) pAsyncEventMsg) +
  2112. pAsyncEventMsg->Param1, // data offset
  2113. pAsyncEventMsg->Param2 // data size
  2114. );
  2115. break;
  2116. }
  2117. pUIThreadData = pUIThreadData->pNext;
  2118. }
  2119. LeaveCriticalSection (&gcsTapisrvCommunication);
  2120. goto AsyncEventsThread_decrUsedSize;
  2121. }
  2122. }
  2123. //
  2124. // Enter the critical section so we've exclusive access
  2125. // to the init data, & verify it
  2126. //
  2127. EnterCriticalSection (&gcsTapisrvCommunication);
  2128. //
  2129. // see if pInitData is null
  2130. //
  2131. if (NULL == pInitData)
  2132. {
  2133. LOG((TL_WARN, "AsyncEventsThread: pInitInst is NULL. discarding msg"));
  2134. goto AsyncEventsThread_leaveCritSec;
  2135. }
  2136. //
  2137. // properly aligned?
  2138. //
  2139. if ((ULONG_PTR) pInitData & 0x7)
  2140. {
  2141. LOG((TL_ERROR,
  2142. "AsyncEventsThread: misaligned pInitInst[%p]. discarding msg", pInitData));
  2143. goto AsyncEventsThread_leaveCritSec;
  2144. }
  2145. //
  2146. // points to unreadeable memory?
  2147. //
  2148. if ( IsBadReadPtr(pInitData, sizeof(T3INIT_DATA)) )
  2149. {
  2150. LOG((TL_ERROR,
  2151. "AsyncEventsThread: pInitData[%p] points to unreadable memory. discarding msg", pInitData));
  2152. goto AsyncEventsThread_leaveCritSec;
  2153. }
  2154. //
  2155. // appears to have valid data?
  2156. //
  2157. // just in case the pointer became invalid since we checked, do
  2158. // this in try/catch
  2159. //
  2160. __try
  2161. {
  2162. if (pInitData->dwKey != INITDATA_KEY )
  2163. {
  2164. LOG((TL_ERROR,
  2165. "AsyncEventsThread: Bad pInitInst[%p], key[%ld] discarding msg",
  2166. pInitData, pInitData->dwKey));
  2167. goto AsyncEventsThread_leaveCritSec;
  2168. }
  2169. }
  2170. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  2171. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2172. {
  2173. LOG((TL_ERROR, "AsyncEventsThread: exception. bad pInitData[%p]", pInitData ));
  2174. goto AsyncEventsThread_leaveCritSec;
  2175. }
  2176. //
  2177. // Special case for PROXYREQUEST
  2178. //
  2179. if (pAsyncEventMsg->Msg == LINE_PROXYREQUEST)
  2180. {
  2181. LOG((TL_INFO, "AsyncEventsThread: LINE_PROXYREQUEST"));
  2182. PPROXYREQUESTHEADER pProxyRequestHeader;
  2183. LPLINEPROXYREQUEST pProxyRequest = (LPLINEPROXYREQUEST)
  2184. (pAsyncEventMsg + 1),
  2185. pProxyRequestApp;
  2186. switch (pProxyRequest->dwRequestType)
  2187. {
  2188. case LINEPROXYREQUEST_SETAGENTGROUP:
  2189. case LINEPROXYREQUEST_SETAGENTSTATE:
  2190. case LINEPROXYREQUEST_SETAGENTACTIVITY:
  2191. case LINEPROXYREQUEST_AGENTSPECIFIC:
  2192. case LINEPROXYREQUEST_CREATEAGENT:
  2193. case LINEPROXYREQUEST_CREATEAGENTSESSION:
  2194. case LINEPROXYREQUEST_SETAGENTMEASUREMENTPERIOD:
  2195. case LINEPROXYREQUEST_SETAGENTSESSIONSTATE:
  2196. case LINEPROXYREQUEST_SETQUEUEMEASUREMENTPERIOD:
  2197. case LINEPROXYREQUEST_SETAGENTSTATEEX:
  2198. //
  2199. // For these msgs the proxy request as received from
  2200. // the tapisrv already contains the exact bits we want
  2201. // to pass on to the app, so we just alloc a buffer of
  2202. // the same size (plus a little extra for the key at
  2203. // the head of the buffer) and copy the data to it
  2204. //
  2205. if (!(pProxyRequestHeader = (PPROXYREQUESTHEADER)ClientAlloc(
  2206. sizeof (PROXYREQUESTHEADER) + pProxyRequest->dwSize
  2207. )))
  2208. {
  2209. //
  2210. // if we could not allocate memory, log a message and break out.
  2211. //
  2212. LOG((TL_ERROR,
  2213. "AsyncEventsThread: failed to allocate memory for proxy request"));
  2214. goto AsyncEventsThread_leaveCritSec;
  2215. }
  2216. pProxyRequestApp = (LPLINEPROXYREQUEST)
  2217. (pProxyRequestHeader + 1);
  2218. CopyMemory(
  2219. pProxyRequestApp,
  2220. pProxyRequest,
  2221. pProxyRequest->dwSize
  2222. );
  2223. break;
  2224. case LINEPROXYREQUEST_GETAGENTCAPS:
  2225. case LINEPROXYREQUEST_GETAGENTSTATUS:
  2226. case LINEPROXYREQUEST_GETAGENTACTIVITYLIST:
  2227. case LINEPROXYREQUEST_GETAGENTGROUPLIST:
  2228. case LINEPROXYREQUEST_GETQUEUEINFO:
  2229. case LINEPROXYREQUEST_GETGROUPLIST:
  2230. case LINEPROXYREQUEST_GETQUEUELIST:
  2231. case LINEPROXYREQUEST_GETAGENTINFO:
  2232. case LINEPROXYREQUEST_GETAGENTSESSIONINFO:
  2233. case LINEPROXYREQUEST_GETAGENTSESSIONLIST:
  2234. //
  2235. // For these msgs tapisrv only embedded the dwTotalSize
  2236. // field of the corresponding structure (to save having
  2237. // to send us a bunch of unused bits), so we want to
  2238. // increase the pProxyRequest->dwSize by the dwTotalSize
  2239. // - sizeof (DWORD), alloc a buffer (including a little
  2240. // extra space for the key at the head of the buffer),
  2241. // and rebuild the request
  2242. //
  2243. if ( pProxyRequest->dwRequestType ==
  2244. LINEPROXYREQUEST_GETGROUPLIST )
  2245. {
  2246. pProxyRequest->dwSize +=
  2247. pProxyRequest->GetGroupList.GroupList.dwTotalSize;
  2248. }
  2249. else if ( pProxyRequest->dwRequestType ==
  2250. LINEPROXYREQUEST_GETQUEUELIST )
  2251. {
  2252. pProxyRequest->dwSize +=
  2253. pProxyRequest->GetQueueList.QueueList.dwTotalSize;
  2254. }
  2255. else
  2256. {
  2257. //
  2258. // all of the rest of the structures have the
  2259. // same format
  2260. //
  2261. pProxyRequest->dwSize +=
  2262. pProxyRequest->GetAgentCaps.AgentCaps.dwTotalSize;
  2263. }
  2264. if (!(pProxyRequestHeader = (PROXYREQUESTHEADER *)ClientAlloc(
  2265. sizeof (PROXYREQUESTHEADER) + pProxyRequest->dwSize
  2266. )))
  2267. {
  2268. //
  2269. // if we could not allocate memory, log a message and break out.
  2270. //
  2271. LOG((TL_ERROR,
  2272. "AsyncEventsThread: failed to allocate memory for proxy request."));
  2273. goto AsyncEventsThread_leaveCritSec;
  2274. }
  2275. pProxyRequestApp = (LPLINEPROXYREQUEST)
  2276. (pProxyRequestHeader + 1);
  2277. //
  2278. // The following will copy the non-union fields in the
  2279. // proxy message, as well as the first two DWORD in the
  2280. // union (which currently are the dwAddressID and the
  2281. // dwTotalSize field of the corresponding structure)
  2282. //
  2283. if ( pProxyRequest->dwRequestType ==
  2284. LINEPROXYREQUEST_GETGROUPLIST )
  2285. {
  2286. CopyMemory(
  2287. pProxyRequestApp,
  2288. pProxyRequest,
  2289. 8 * sizeof (DWORD)
  2290. );
  2291. }
  2292. else if ( pProxyRequest->dwRequestType ==
  2293. LINEPROXYREQUEST_GETQUEUELIST )
  2294. {
  2295. CopyMemory(
  2296. pProxyRequestApp,
  2297. pProxyRequest,
  2298. 8 * sizeof (DWORD) + sizeof(GUID)
  2299. );
  2300. }
  2301. else
  2302. {
  2303. CopyMemory(
  2304. pProxyRequestApp,
  2305. pProxyRequest,
  2306. 9 * sizeof (DWORD)
  2307. );
  2308. }
  2309. //
  2310. // Relocate the machine & user names to the end of the
  2311. // structure
  2312. //
  2313. pProxyRequestApp->dwClientMachineNameOffset =
  2314. pProxyRequest->dwSize -
  2315. pProxyRequest->dwClientMachineNameSize;
  2316. wcscpy(
  2317. (WCHAR *)(((LPBYTE) pProxyRequestApp) +
  2318. pProxyRequestApp->dwClientMachineNameOffset),
  2319. (WCHAR *)(((LPBYTE) pProxyRequest) +
  2320. pProxyRequest->dwClientMachineNameOffset)
  2321. );
  2322. pProxyRequestApp->dwClientUserNameOffset =
  2323. pProxyRequestApp->dwClientMachineNameOffset -
  2324. pProxyRequest->dwClientUserNameSize;
  2325. wcscpy(
  2326. (WCHAR *)(((LPBYTE) pProxyRequestApp) +
  2327. pProxyRequestApp->dwClientUserNameOffset),
  2328. (WCHAR *)(((LPBYTE) pProxyRequest) +
  2329. pProxyRequest->dwClientUserNameOffset)
  2330. );
  2331. break;
  2332. }
  2333. pProxyRequestHeader->dwKey = TPROXYREQUESTHEADER_KEY;
  2334. pProxyRequestHeader->dwInstance = pAsyncEventMsg->Param1;
  2335. pAsyncEventMsg->Param1 = (ULONG_PTR) pProxyRequestApp;
  2336. }
  2337. //
  2338. // Call the post processing proc if there is one
  2339. //
  2340. if (pAsyncEventMsg->fnPostProcessProcHandle)
  2341. {
  2342. LOG((TL_INFO,
  2343. "AsyncEventsThread: calling postprocessing function,"
  2344. "function index (pAsyncEventMsg->fnPostProcessProcHandle) = "
  2345. "[%d]", pAsyncEventMsg->fnPostProcessProcHandle));
  2346. (*(gPostProcessingFunctions[
  2347. pAsyncEventMsg->fnPostProcessProcHandle]))(pAsyncEventMsg);
  2348. }
  2349. LOG((TL_INFO, "AsyncEventsThread: calling ProcessMessage()"));
  2350. if FAILED(ProcessMessage(
  2351. pInitData,
  2352. pAsyncEventMsg
  2353. ) )
  2354. {
  2355. LOG((TL_INFO, "AsyncEventsThread: ProcessMessage()"
  2356. " did not succeed. requeueing..."));
  2357. BOOL bQueueSuccess = gpRetryQueue->QueueEvent(pAsyncEventMsg);
  2358. if (!bQueueSuccess)
  2359. {
  2360. //
  2361. // QueueEvent failed to allocate resources needed to queue
  2362. // the message. other than log a message, there is nothing
  2363. // much we can do.
  2364. //
  2365. LOG((TL_ERROR, "AsyncEventsThread: ProcessMessage() - "
  2366. "failed to requeue item"));
  2367. }
  2368. }
  2369. AsyncEventsThread_leaveCritSec:
  2370. // LOG((TL_INFO, "AsyncEventsThread: releasing critical section (0x%08lx)", gcsTapisrvCommunication));
  2371. LeaveCriticalSection (&gcsTapisrvCommunication);
  2372. AsyncEventsThread_decrUsedSize:
  2373. dwUsedSize -= pAsyncEventMsg->TotalSize;
  2374. pAsyncEventMsg = (PASYNCEVENTMSG)
  2375. ((LPBYTE) pAsyncEventMsg + pAsyncEventMsg->TotalSize);
  2376. #if DBG
  2377. if ( (LONG)dwUsedSize < 0 )
  2378. {
  2379. LOG((TL_ERROR, "dwUsedSize went negative!!!"));
  2380. }
  2381. #endif
  2382. } // END while (dwUsedSize)
  2383. // LOG((TL_INFO, "AsyncEventsThread: Done processing TAPISRV message block"));
  2384. // We've now processed all the messages in the last RPC block from TAPISRV
  2385. // Now lets process the Re-try Queue
  2386. gpRetryQueue->ProcessQueue();
  2387. } // end of message reading/processing loop
  2388. //
  2389. // the thread is about to exit, we don't want to leave anything behind in
  2390. // the retry queue, so close the queue for new entries and process all the
  2391. // entries that are already in there
  2392. //
  2393. //
  2394. // mark the queue as closed for new entries
  2395. //
  2396. gpRetryQueue->CloseForNewEntries();
  2397. //
  2398. // process elements still remaining in the queue
  2399. //
  2400. gpRetryQueue->ProcessQueue();
  2401. {
  2402. //
  2403. // Free our resources, and then exit
  2404. //
  2405. HANDLE hTapi32 = pAsyncEventsThreadParams->hTapi32;
  2406. if (pAsyncEventsThreadParams->hWow32)
  2407. {
  2408. FreeLibrary ((HINSTANCE)(pAsyncEventsThreadParams->hWow32));
  2409. }
  2410. ClientFree (pBuf);
  2411. ClientFree (pAsyncEventsThreadParams);
  2412. CoUninitialize();
  2413. LOG((TL_TRACE, "AsyncEventsThread: exit"));
  2414. FreeLibraryAndExitThread ((HINSTANCE)hTapi32, 0);
  2415. }
  2416. }
  2417. BOOL
  2418. PASCAL
  2419. IsBadDwordPtr(
  2420. LPDWORD p
  2421. )
  2422. {
  2423. DWORD dwError;
  2424. __try
  2425. {
  2426. *p = *p + 1;
  2427. }
  2428. __except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
  2429. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  2430. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2431. {
  2432. return TRUE;
  2433. }
  2434. *p = *p - 1;
  2435. return FALSE;
  2436. }
  2437. BOOL
  2438. WINAPI
  2439. GrowBuf(
  2440. LPBYTE *ppBuf,
  2441. LPDWORD pdwBufSize,
  2442. DWORD dwCurrValidBytes,
  2443. DWORD dwBytesToAdd
  2444. )
  2445. {
  2446. DWORD dwCurrBufSize, dwNewBufSize;
  2447. LPBYTE pNewBuf;
  2448. //
  2449. // Try to get a new buffer big enough to hold everything
  2450. //
  2451. for(
  2452. dwNewBufSize = 2 * (dwCurrBufSize = *pdwBufSize);
  2453. dwNewBufSize < (dwCurrBufSize + dwBytesToAdd);
  2454. dwNewBufSize *= 2
  2455. );
  2456. if (!(pNewBuf = (LPBYTE)ClientAlloc (dwNewBufSize)))
  2457. {
  2458. return FALSE;
  2459. }
  2460. //
  2461. // Copy the "valid" bytes in the old buf to the new buf,
  2462. // then free the old buf
  2463. //
  2464. CopyMemory (pNewBuf, *ppBuf, dwCurrValidBytes);
  2465. ClientFree (*ppBuf);
  2466. //
  2467. // Reset the pointers to the new buf & buf size
  2468. //
  2469. *ppBuf = pNewBuf;
  2470. *pdwBufSize = dwNewBufSize;
  2471. return TRUE;
  2472. }
  2473. PCLIENT_THREAD_INFO
  2474. WINAPI
  2475. GetTls(
  2476. void
  2477. )
  2478. {
  2479. PCLIENT_THREAD_INFO pClientThreadInfo;
  2480. if (!(pClientThreadInfo = (PCLIENT_THREAD_INFO)TlsGetValue (gdwTlsIndex)))
  2481. {
  2482. pClientThreadInfo = (PCLIENT_THREAD_INFO)
  2483. ClientAlloc (sizeof(CLIENT_THREAD_INFO));
  2484. if (!pClientThreadInfo)
  2485. {
  2486. return NULL;
  2487. }
  2488. pClientThreadInfo->pBuf = (unsigned char *)ClientAlloc (INITIAL_CLIENT_THREAD_BUF_SIZE);
  2489. if (!pClientThreadInfo->pBuf)
  2490. {
  2491. ClientFree (pClientThreadInfo);
  2492. return NULL;
  2493. }
  2494. pClientThreadInfo->dwBufSize = INITIAL_CLIENT_THREAD_BUF_SIZE;
  2495. TlsSetValue (gdwTlsIndex, (LPVOID) pClientThreadInfo);
  2496. EnterCriticalSection (&gTlsCriticalSection);
  2497. InsertHeadList (&gTlsListHead, &pClientThreadInfo->TlsList);
  2498. LeaveCriticalSection (&gTlsCriticalSection);
  2499. }
  2500. return pClientThreadInfo;
  2501. }
  2502. #if DBG
  2503. LONG
  2504. WINAPI
  2505. DoFunc(
  2506. PFUNC_ARGS pFuncArgs,
  2507. char *pszFuncName
  2508. )
  2509. #else
  2510. LONG
  2511. WINAPI
  2512. DoFunc(
  2513. PFUNC_ARGS pFuncArgs
  2514. )
  2515. #endif
  2516. {
  2517. DWORD dwFuncClassErrorIndex = (pFuncArgs->Flags & 0x00000030) >> 4;
  2518. LONG lResult;
  2519. BOOL bCopyOnSuccess = FALSE;
  2520. DWORD i, j, dwUsedSize, dwNeededSize;
  2521. ULONG_PTR Value;
  2522. PCLIENT_THREAD_INFO pTls;
  2523. #if DBG
  2524. LOG((TL_INFO, "About to call %s", pszFuncName));
  2525. #endif
  2526. //
  2527. // Get the tls
  2528. //
  2529. if (!(pTls = GetTls()))
  2530. {
  2531. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2532. goto DoFunc_return;
  2533. }
  2534. //
  2535. // The first arg of all async msg blocks is a remote request id; set
  2536. // this to zero to indicate that we are a local client (not remotesp)
  2537. //
  2538. if (pFuncArgs->Flags & ASYNC)
  2539. {
  2540. ((PTAPI32_MSG) pTls->pBuf)->Params[0] = 0;
  2541. }
  2542. //
  2543. // Validate all the func args
  2544. //
  2545. dwNeededSize = dwUsedSize = ALIGN (sizeof (TAPI32_MSG));
  2546. for(
  2547. i = 0, j = (pFuncArgs->Flags & ASYNC ? 1 : 0);
  2548. i < (pFuncArgs->Flags & NUM_ARGS_MASK);
  2549. i++, j++
  2550. )
  2551. {
  2552. //
  2553. // extract the ptr-sized value from the arguments
  2554. //
  2555. Value = pFuncArgs->Args[i];
  2556. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pFuncArgs->Args[i];
  2557. switch (pFuncArgs->ArgTypes[i])
  2558. {
  2559. case Dword:
  2560. //
  2561. // make sure the data is 32bit at most
  2562. //
  2563. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST(pFuncArgs->Args[i]);
  2564. continue;
  2565. case lpDword:
  2566. if (IsBadDwordPtr ((LPDWORD) Value))
  2567. {
  2568. LOG((TL_ERROR, "Bad lpdword in dofunc"));
  2569. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2570. goto DoFunc_return;
  2571. }
  2572. //
  2573. // we don't need to send the actual pointer. but send the value we point to.
  2574. //
  2575. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = *((DWORD*)Value);
  2576. bCopyOnSuccess = TRUE;
  2577. continue;
  2578. case hXxxApp_NULLOK:
  2579. case hXxxApp:
  2580. {
  2581. //
  2582. // Verify that the hXxxApp is a pointer to a valid InitData
  2583. // struct, then retrieve the real hXxxApp from that struct.
  2584. // If the hXxxApp is bad, pass the server 0xffffffff so that
  2585. // it can figure out whether to return an UNINITIALIZED error
  2586. // or a INVALAPPHANDLE error.
  2587. //
  2588. DWORD dwError;
  2589. if (
  2590. (0 == pFuncArgs->Args[i])
  2591. &&
  2592. (hXxxApp_NULLOK == pFuncArgs->ArgTypes[i])
  2593. )
  2594. {
  2595. //
  2596. // Looks good to me...
  2597. //
  2598. continue;
  2599. }
  2600. __try
  2601. {
  2602. //
  2603. // Value contains the 32-bit handle to be passed to tapisrv
  2604. //
  2605. // recover the pointer corresponding to the 32-bit handle in Value
  2606. //
  2607. PT3INIT_DATA pInitData = (PT3INIT_DATA) GetHandleTableEntry(Value);
  2608. if (pInitData->dwKey != INITDATA_KEY)
  2609. {
  2610. LOG((TL_ERROR, "DoFunc: Bad hxxxapp [%p] in dofunc", pInitData));
  2611. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0xffffffff;
  2612. }
  2613. else
  2614. {
  2615. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pInitData->hXxxApp;
  2616. }
  2617. }
  2618. __except ((((dwError = GetExceptionCode())
  2619. == EXCEPTION_ACCESS_VIOLATION) ||
  2620. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  2621. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2622. {
  2623. LOG((TL_ERROR, "DoFunc: Bad hxxxapp2 in dofunc (0x%08lx)", dwError));
  2624. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0xffffffff;
  2625. }
  2626. continue;
  2627. }
  2628. case Hwnd:
  2629. if (!IsWindow ((HWND) Value))
  2630. {
  2631. LOG((TL_ERROR, "DoFunc: Bad hWnd in dofunc"));
  2632. lResult = gaInvalHwndErrors[dwFuncClassErrorIndex];
  2633. goto DoFunc_return;
  2634. }
  2635. continue;
  2636. // case lpsz:
  2637. case lpszW:
  2638. //
  2639. // Check if Value is a valid string ptr and if so
  2640. // copy the contents of the string to the extra data
  2641. // buffer passed to the server
  2642. //
  2643. __try
  2644. {
  2645. DWORD n = (lstrlenW((WCHAR *) Value) + 1) * sizeof(WCHAR),
  2646. nAligned = ALIGN (n);
  2647. if ((nAligned + dwUsedSize) > pTls->dwBufSize)
  2648. {
  2649. if (!GrowBuf(
  2650. &pTls->pBuf,
  2651. &pTls->dwBufSize,
  2652. dwUsedSize,
  2653. nAligned
  2654. ))
  2655. {
  2656. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2657. goto DoFunc_return;
  2658. }
  2659. }
  2660. CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) Value, n);
  2661. //
  2662. // Pass the server the offset of the string in the var data
  2663. // portion of the buffer
  2664. //
  2665. ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
  2666. dwUsedSize - sizeof (TAPI32_MSG);
  2667. //
  2668. // Increment the total number of data bytes
  2669. //
  2670. dwUsedSize += nAligned;
  2671. dwNeededSize += nAligned;
  2672. }
  2673. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  2674. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2675. {
  2676. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2677. goto DoFunc_return;
  2678. }
  2679. continue;
  2680. case lpGet_Struct:
  2681. case lpGet_SizeToFollow:
  2682. {
  2683. BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpGet_SizeToFollow);
  2684. DWORD dwSize;
  2685. if (bSizeToFollow)
  2686. {
  2687. #if DBG
  2688. //
  2689. // Check to make sure the following arg is of type Size
  2690. //
  2691. if ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
  2692. (pFuncArgs->ArgTypes[i + 1] != Size))
  2693. {
  2694. LOG((
  2695. TL_ERROR,
  2696. "DoFunc: error, lpGet_SizeToFollow !followed by Size"
  2697. ));
  2698. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2699. goto DoFunc_return;
  2700. }
  2701. #endif
  2702. dwSize = pFuncArgs->Args[i + 1];
  2703. }
  2704. else
  2705. {
  2706. DWORD dwError;
  2707. __try
  2708. {
  2709. dwSize = *((LPDWORD) Value);
  2710. }
  2711. __except ((((dwError = GetExceptionCode())
  2712. == EXCEPTION_ACCESS_VIOLATION) ||
  2713. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  2714. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2715. {
  2716. LOG((TL_ERROR, "Bad get struct/size in dofunc"));
  2717. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2718. goto DoFunc_return;
  2719. }
  2720. }
  2721. if (TAPIIsBadWritePtr ((LPVOID) Value, dwSize))
  2722. {
  2723. LOG((TL_ERROR, "Bad get size/struct2 in dofunc"));
  2724. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2725. goto DoFunc_return;
  2726. }
  2727. if (bSizeToFollow)
  2728. {
  2729. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2730. ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
  2731. }
  2732. else
  2733. {
  2734. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = dwSize;
  2735. }
  2736. //
  2737. // Now set the bCopyOnSuccess flag to indicate that we've data
  2738. // to copy back on successful completion, and add to the
  2739. // dwNeededSize field
  2740. //
  2741. bCopyOnSuccess = TRUE;
  2742. dwNeededSize += ALIGN (dwSize);
  2743. continue;
  2744. }
  2745. case lpSet_Struct:
  2746. case lpSet_SizeToFollow:
  2747. {
  2748. BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
  2749. DWORD dwSize, dwError, dwSizeAligned;
  2750. #if DBG
  2751. //
  2752. // Check to make sure the following arg is of type Size
  2753. //
  2754. if (bSizeToFollow &&
  2755. ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
  2756. (pFuncArgs->ArgTypes[i + 1] != Size)))
  2757. {
  2758. LOG((
  2759. TL_ERROR,
  2760. "DoFunc: error, lpSet_SizeToFollow !followed by Size"
  2761. ));
  2762. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2763. goto DoFunc_return;
  2764. }
  2765. #endif
  2766. __try
  2767. {
  2768. //
  2769. // First determine the data size & if the ptr is bad
  2770. //
  2771. dwSize = (bSizeToFollow ? pFuncArgs->Args[i + 1] :
  2772. *((LPDWORD) Value));
  2773. if (IsBadReadPtr ((LPVOID) Value, dwSize))
  2774. {
  2775. LOG((TL_ERROR, "Bad set size/struct in dofunc"));
  2776. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2777. goto DoFunc_return;
  2778. }
  2779. dwSizeAligned = ALIGN (dwSize);
  2780. //
  2781. // Special case if the size isn't even big enough to pass
  2782. // over a complete DWORD for the dwTotalSize field
  2783. //
  2784. if (!bSizeToFollow && (dwSize < sizeof (DWORD)))
  2785. {
  2786. static DWORD dwZeroTotalSize = 0;
  2787. dwSize = dwSizeAligned = sizeof (DWORD);
  2788. Value = (ULONG_PTR) &dwZeroTotalSize;
  2789. // LOG((TL_1, "Bad set size/struct2 in dofunc"));
  2790. // lResult = gaStructTooSmallErrors[dwFuncClassErrorIndex];
  2791. // goto DoFunc_return;
  2792. }
  2793. //
  2794. // Grow the buffer if necessary, & do the copy
  2795. //
  2796. if ((dwSizeAligned + dwUsedSize) > pTls->dwBufSize)
  2797. {
  2798. if (!GrowBuf(
  2799. &pTls->pBuf,
  2800. &pTls->dwBufSize,
  2801. dwUsedSize,
  2802. dwSizeAligned
  2803. ))
  2804. {
  2805. LOG((TL_ERROR, "Nomem set size/struct in dofunc"));
  2806. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2807. goto DoFunc_return;
  2808. }
  2809. }
  2810. CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) Value, dwSize);
  2811. }
  2812. __except ((((dwError = GetExceptionCode())
  2813. == EXCEPTION_ACCESS_VIOLATION) ||
  2814. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  2815. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2816. {
  2817. LOG((TL_ERROR, "Bad pointer in get size/struct in dofunc"));
  2818. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2819. goto DoFunc_return;
  2820. }
  2821. //
  2822. // Pass the server the offset of the data in the var data
  2823. // portion of the buffer
  2824. //
  2825. if (dwSize)
  2826. {
  2827. ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
  2828. dwUsedSize - sizeof (TAPI32_MSG);
  2829. }
  2830. else
  2831. {
  2832. ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
  2833. }
  2834. //
  2835. // Increment the dwXxxSize vars appropriately
  2836. //
  2837. dwUsedSize += dwSizeAligned;
  2838. dwNeededSize += dwSizeAligned;
  2839. //
  2840. // Since we already know the next arg (Size) just handle
  2841. // it here so we don't have to run thru the loop again
  2842. //
  2843. if (bSizeToFollow)
  2844. {
  2845. ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
  2846. }
  2847. continue;
  2848. }
  2849. #if DBG
  2850. case Size:
  2851. LOG((TL_ERROR, "DoFunc: error, hit case Size"));
  2852. continue;
  2853. default:
  2854. LOG((TL_ERROR, "DoFunc: error, unknown arg type"));
  2855. continue;
  2856. #endif
  2857. } // switch
  2858. } // for
  2859. //
  2860. // Now make the request
  2861. //
  2862. if (dwNeededSize > pTls->dwBufSize)
  2863. {
  2864. if (!GrowBuf(
  2865. &pTls->pBuf,
  2866. &pTls->dwBufSize,
  2867. dwUsedSize,
  2868. dwNeededSize - pTls->dwBufSize
  2869. ))
  2870. {
  2871. lResult = gaNoMemErrors[dwFuncClassErrorIndex];
  2872. goto DoFunc_return;
  2873. }
  2874. }
  2875. ((PTAPI32_MSG) pTls->pBuf)->u.Req_Func = (DWORD)HIWORD(pFuncArgs->Flags);
  2876. {
  2877. DWORD dwRetryCount = 0;
  2878. BOOL bReinitResource;
  2879. do
  2880. {
  2881. bReinitResource = FALSE;
  2882. RpcTryExcept
  2883. {
  2884. ClientRequest (gphCx, pTls->pBuf, dwNeededSize, (LONG *)&dwUsedSize);
  2885. lResult = ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
  2886. if (lResult == TAPIERR_INVALRPCCONTEXT)
  2887. {
  2888. if (dwRetryCount ++ >= gdwMaxNumRequestRetries)
  2889. {
  2890. bReinitResource = FALSE;
  2891. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2892. dwRetryCount = 0;
  2893. }
  2894. else
  2895. {
  2896. bReinitResource = TRUE;
  2897. }
  2898. }
  2899. else
  2900. {
  2901. bReinitResource = FALSE;
  2902. dwRetryCount = 0;
  2903. }
  2904. }
  2905. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  2906. {
  2907. unsigned long rpcException = RpcExceptionCode();
  2908. if (rpcException == RPC_S_SERVER_TOO_BUSY)
  2909. {
  2910. if (dwRetryCount++ < gdwMaxNumRequestRetries)
  2911. {
  2912. Sleep (gdwRequestRetryTimeout);
  2913. }
  2914. else
  2915. {
  2916. dwRetryCount = 0;
  2917. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2918. }
  2919. }
  2920. else if ((rpcException == RPC_S_SERVER_UNAVAILABLE) ||
  2921. (rpcException == RPC_S_CALL_FAILED_DNE))
  2922. {
  2923. if (dwRetryCount ++ >= gdwMaxNumRequestRetries)
  2924. {
  2925. bReinitResource = FALSE;
  2926. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2927. dwRetryCount = 0;
  2928. }
  2929. else
  2930. {
  2931. bReinitResource = TRUE;
  2932. }
  2933. }
  2934. else
  2935. {
  2936. LOG((TL_ERROR, "DoFunc: rpcException # %d", rpcException));
  2937. lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
  2938. dwRetryCount = 0;
  2939. }
  2940. }
  2941. RpcEndExcept
  2942. if (bReinitResource)
  2943. {
  2944. FreeClientResources();
  2945. AllocClientResources(dwFuncClassErrorIndex);
  2946. }
  2947. } while (dwRetryCount != 0);
  2948. }
  2949. // note: 99.99% of the time this result dump will == the one at end of the
  2950. // func (only when ptrs have gone bad will the result differ), no reason
  2951. // to dump 2x unless doing internal dbgging
  2952. //
  2953. LOG((TL_INFO, "DoFunc: back from srv- return code=0x%08lx", lResult));
  2954. //
  2955. // If request completed successfully and the bCopyOnSuccess flag
  2956. // is set then we need to copy data back to client buffer(s)
  2957. //
  2958. if ((lResult == TAPI_SUCCESS) && bCopyOnSuccess)
  2959. {
  2960. for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
  2961. {
  2962. PTAPI32_MSG pMsg = (PTAPI32_MSG) pTls->pBuf;
  2963. DWORD dwServerData = pMsg->Params[j];
  2964. switch (pFuncArgs->ArgTypes[i])
  2965. {
  2966. case Dword:
  2967. case Hwnd:
  2968. // case lpsz:
  2969. case lpszW:
  2970. case lpSet_Struct:
  2971. continue;
  2972. case lpDword:
  2973. __try
  2974. {
  2975. //
  2976. // Fill in the pointer with the return value
  2977. //
  2978. *((LPDWORD) pFuncArgs->Args[i]) = dwServerData;
  2979. }
  2980. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  2981. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  2982. {
  2983. //
  2984. // this should really never happen -- the memory was
  2985. // checked before the call to tapisrv ws made
  2986. //
  2987. _ASSERTE(FALSE);
  2988. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  2989. goto DoFunc_return;
  2990. }
  2991. continue;
  2992. case lpGet_SizeToFollow:
  2993. __try
  2994. {
  2995. //
  2996. // Fill in the pointer with the return value
  2997. //
  2998. CopyMemory(
  2999. (LPBYTE) pFuncArgs->Args[i],
  3000. pTls->pBuf + dwServerData + sizeof(TAPI32_MSG),
  3001. pMsg->Params[j+1]
  3002. );
  3003. }
  3004. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  3005. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  3006. {
  3007. LOG((TL_ERROR, "DoFunc: lpGet_SizeToFollow MemCopy failed"));
  3008. //
  3009. // we made sure the memory was writeable before the call to tapisrv
  3010. // if we catch an exception here, that means that tapisrv did not
  3011. // return us proper information. in which case we cannot make any
  3012. // assumtions about its state, so we are not responsible
  3013. // for cleaning it up.
  3014. //
  3015. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  3016. goto DoFunc_return;
  3017. }
  3018. //
  3019. // Increment i (and j, since Size passed as arg in msg)
  3020. // to skip following Size arg in pFuncArgs->Args
  3021. //
  3022. i++;
  3023. j++;
  3024. continue;
  3025. case lpSet_SizeToFollow:
  3026. //
  3027. // Increment i (and j, since Size passed as arg in msg)
  3028. // to skip following Size arg in pFuncArgs->Args
  3029. //
  3030. i++;
  3031. j++;
  3032. continue;
  3033. case lpGet_Struct:
  3034. __try
  3035. {
  3036. //
  3037. // Params[j] contains the offset in the var data
  3038. // portion of pTls->pBuf of some TAPI struct.
  3039. // Get the dwUsedSize value from this struct &
  3040. // copy that many bytes from pTls->pBuf to client buf
  3041. //
  3042. if (dwServerData != TAPI_NO_DATA)
  3043. {
  3044. LPDWORD pStruct;
  3045. pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
  3046. dwServerData);
  3047. CopyMemory(
  3048. (LPBYTE) pFuncArgs->Args[i],
  3049. (LPBYTE) pStruct,
  3050. *(pStruct + 2) // ptr to dwUsedSize field
  3051. );
  3052. }
  3053. }
  3054. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  3055. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  3056. {
  3057. LOG((TL_WARN, "DoFunc: lpGet_Struct MemCopy failed"));
  3058. //
  3059. // we made sure the memory of the size of the struct was
  3060. // writeable before the call to tapisrv if we catch an
  3061. // exception here, that most likely means that tapisrv
  3062. // did not return us proper information. in which case
  3063. // we cannot make any assumtions about its state, or
  3064. // make an effort clean up tapisrv's state.
  3065. //
  3066. lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
  3067. goto DoFunc_return;
  3068. }
  3069. continue;
  3070. default:
  3071. continue;
  3072. }
  3073. }
  3074. }
  3075. // else if ((pFuncArgs->Flags & ASYNC) && (lResult < TAPI_SUCCESS))
  3076. // {
  3077. // }
  3078. DoFunc_return:
  3079. #if DBG
  3080. {
  3081. char szResult[32];
  3082. LOG((
  3083. TL_INFO,
  3084. "%s: result = %s",
  3085. pszFuncName,
  3086. MapResultCodeToText (lResult, szResult)
  3087. ));
  3088. }
  3089. #endif
  3090. return lResult;
  3091. }
  3092. HRESULT
  3093. CreateMSPObject(
  3094. DWORD dwDeviceID,
  3095. IUnknown * pUnk,
  3096. IUnknown ** ppMSPAggAddress
  3097. )
  3098. {
  3099. HRESULT hr;
  3100. CLSID clsid;
  3101. FUNC_ARGS funcArgs =
  3102. {
  3103. MAKELONG (LINE_FUNC | SYNC | 3, lMSPIdentify),
  3104. {
  3105. (ULONG_PTR) dwDeviceID,
  3106. (ULONG_PTR) &clsid,
  3107. (ULONG_PTR) sizeof(clsid)
  3108. },
  3109. {
  3110. Dword,
  3111. lpGet_SizeToFollow,
  3112. Size
  3113. }
  3114. };
  3115. if ((hr = DOFUNC (&funcArgs, "lineMSPIdentify")) == 0)
  3116. {
  3117. hr = CoCreateInstance(
  3118. clsid,
  3119. pUnk,
  3120. CLSCTX_ALL,
  3121. IID_IUnknown,
  3122. (void **) ppMSPAggAddress
  3123. );
  3124. if (!SUCCEEDED(hr))
  3125. {
  3126. LOG((
  3127. TL_ERROR,
  3128. "CoCreate failed for MSP on dwDeviceID %ld - error %lx",
  3129. dwDeviceID,
  3130. hr
  3131. ));
  3132. }
  3133. }
  3134. else
  3135. {
  3136. LOG((TL_ERROR, "GetMSPClsid failed on dwDeviceID %l", dwDeviceID));
  3137. }
  3138. return hr;
  3139. }
  3140. HRESULT
  3141. LineReceiveMSPData(
  3142. HLINE hLine,
  3143. HCALL hCall,
  3144. PBYTE pBuffer,
  3145. DWORD dwSize
  3146. )
  3147. {
  3148. HRESULT hr = S_OK;
  3149. FUNC_ARGS funcArgs =
  3150. {
  3151. MAKELONG (LINE_FUNC | SYNC | 4, lReceiveMSPData),
  3152. {
  3153. (ULONG_PTR) hLine,
  3154. (ULONG_PTR) hCall,
  3155. (ULONG_PTR) pBuffer,
  3156. (ULONG_PTR) dwSize
  3157. },
  3158. {
  3159. Dword,
  3160. Dword,
  3161. lpSet_SizeToFollow,
  3162. Size
  3163. }
  3164. };
  3165. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LineReceiveMSPData") );
  3166. return hr;
  3167. }
  3168. LONG
  3169. LoadUIDll(
  3170. HWND hwndOwner,
  3171. DWORD dwWidgetID,
  3172. DWORD dwWidgetType,
  3173. HANDLE *phDll,
  3174. const CHAR *pszTUISPI_xxx,
  3175. TUISPIPROC *ppfnTUISPI_xxx
  3176. )
  3177. {
  3178. LONG lResult;
  3179. HANDLE hDll = NULL;
  3180. WCHAR szUIDllName[MAX_PATH];
  3181. FUNC_ARGS funcArgs =
  3182. {
  3183. MAKELONG (LINE_FUNC | SYNC | 4, xGetUIDllName),
  3184. {
  3185. (ULONG_PTR) dwWidgetID,
  3186. (ULONG_PTR) dwWidgetType,
  3187. (ULONG_PTR) szUIDllName,
  3188. (ULONG_PTR) MAX_PATH
  3189. },
  3190. {
  3191. Dword,
  3192. Dword,
  3193. lpGet_SizeToFollow,
  3194. Size
  3195. }
  3196. };
  3197. if (hwndOwner && !IsWindow (hwndOwner))
  3198. {
  3199. lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
  3200. PHONEERR_INVALPARAM : LINEERR_INVALPARAM);
  3201. goto LoadUIDll_return;
  3202. }
  3203. if ((lResult = DOFUNC (&funcArgs, "GetUIDllName")) == 0)
  3204. {
  3205. if (hDll = TAPILoadLibraryW(szUIDllName))
  3206. {
  3207. if ((*ppfnTUISPI_xxx = (TUISPIPROC) GetProcAddress(
  3208. (HINSTANCE)hDll,
  3209. pszTUISPI_xxx
  3210. )))
  3211. {
  3212. *phDll = hDll;
  3213. lResult = 0;
  3214. }
  3215. else
  3216. {
  3217. LOG((
  3218. TL_ERROR,
  3219. "LoadUIDll: GetProcAddress(%ls,%s) failed, err=%d",
  3220. szUIDllName,
  3221. pszTUISPI_xxx,
  3222. GetLastError()
  3223. ));
  3224. FreeLibrary ((HINSTANCE)hDll);
  3225. lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
  3226. PHONEERR_OPERATIONUNAVAIL : LINEERR_OPERATIONUNAVAIL);
  3227. }
  3228. }
  3229. else
  3230. {
  3231. LOG((
  3232. TL_ERROR,
  3233. "LoadLibraryW(%ls) failed, err=%d",
  3234. szUIDllName,
  3235. GetLastError()
  3236. ));
  3237. lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
  3238. PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
  3239. }
  3240. }
  3241. LoadUIDll_return:
  3242. return lResult;
  3243. }
  3244. LONG
  3245. PASCAL
  3246. lineXxxProvider(
  3247. const CHAR *pszTUISPI_providerXxx,
  3248. LPCSTR lpszProviderFilename,
  3249. HWND hwndOwner,
  3250. DWORD dwPermProviderID,
  3251. LPDWORD lpdwPermProviderID
  3252. )
  3253. {
  3254. BOOL bAddProvider = (pszTUISPI_providerXxx ==
  3255. gszTUISPI_providerInstall);
  3256. WCHAR szUIDllName[MAX_PATH];
  3257. LONG lResult;
  3258. HINSTANCE hDll;
  3259. TUISPIPROC pfnTUISPI_providerXxx;
  3260. HTAPIDIALOGINSTANCE htDlgInst;
  3261. #ifndef _WIN64
  3262. if (
  3263. (GetVersion() & 0x80000000)
  3264. &&
  3265. ( 0xffff0000 == ( (DWORD)hwndOwner & 0xffff0000) )
  3266. )
  3267. {
  3268. //
  3269. // Yeah. It don't play no ffff.
  3270. //
  3271. hwndOwner = (HWND) ( (DWORD)hwndOwner & 0x0000ffff );
  3272. }
  3273. #endif
  3274. if (bAddProvider && IsBadDwordPtr (lpdwPermProviderID))
  3275. {
  3276. LOG((TL_ERROR, "Bad lpdwPermProviderID pointer"));
  3277. return LINEERR_INVALPOINTER;
  3278. }
  3279. else if (hwndOwner && !IsWindow (hwndOwner))
  3280. {
  3281. LOG((TL_ERROR, "hwndOwner is not a window"));
  3282. return LINEERR_INVALPARAM;
  3283. }
  3284. {
  3285. FUNC_ARGS funcArgs =
  3286. {
  3287. MAKELONG (LINE_FUNC | SYNC | 7, xGetUIDllName),
  3288. {
  3289. (ULONG_PTR) (bAddProvider ? (ULONG_PTR) &dwPermProviderID :
  3290. dwPermProviderID),
  3291. (ULONG_PTR) TUISPIDLL_OBJECT_PROVIDERID,
  3292. (ULONG_PTR) szUIDllName,
  3293. (ULONG_PTR) MAX_PATH,
  3294. (ULONG_PTR) (bAddProvider ? (ULONG_PTR) lpszProviderFilename :
  3295. TAPI_NO_DATA),
  3296. (ULONG_PTR) (pszTUISPI_providerXxx==gszTUISPI_providerRemove ?1:0),
  3297. (ULONG_PTR) &htDlgInst
  3298. },
  3299. {
  3300. (bAddProvider ? lpDword : Dword),
  3301. Dword,
  3302. lpGet_SizeToFollow,
  3303. Size,
  3304. (bAddProvider ? lpszW : Dword),
  3305. Dword,
  3306. lpDword
  3307. }
  3308. };
  3309. if ((lResult = DOFUNC (&funcArgs,"lineXxxProvider/GetUIDllName")) != 0)
  3310. {
  3311. if (lResult == TAPI16BITSUCCESS)
  3312. {
  3313. // 16 bit sp success
  3314. // set result correctly, and return here
  3315. lResult = 0;
  3316. }
  3317. return lResult;
  3318. }
  3319. }
  3320. if ((hDll = TAPILoadLibraryW(szUIDllName)))
  3321. {
  3322. if ((pfnTUISPI_providerXxx = (TUISPIPROC) GetProcAddress(
  3323. hDll,
  3324. pszTUISPI_providerXxx
  3325. )))
  3326. {
  3327. LOG((TL_INFO, "Calling %ls...", pszTUISPI_providerXxx));
  3328. lResult = ((TUIPROVPROC)(*pfnTUISPI_providerXxx))(
  3329. TUISPIDLLCallback,
  3330. hwndOwner,
  3331. dwPermProviderID
  3332. );
  3333. #if DBG
  3334. {
  3335. char szResult[32];
  3336. LOG((
  3337. TL_INFO,
  3338. "%ls: result = %s",
  3339. pszTUISPI_providerXxx,
  3340. MapResultCodeToText (lResult, szResult)
  3341. ));
  3342. }
  3343. #endif
  3344. }
  3345. else
  3346. {
  3347. LOG((
  3348. TL_ERROR,
  3349. "lineXxxProvider: GetProcAddr(%ls,%ls) failed, err=%d",
  3350. szUIDllName,
  3351. pszTUISPI_providerXxx,
  3352. GetLastError()
  3353. ));
  3354. lResult = LINEERR_OPERATIONUNAVAIL;
  3355. }
  3356. FreeLibrary (hDll);
  3357. }
  3358. else
  3359. {
  3360. LOG((
  3361. TL_ERROR,
  3362. "lineXxxProvider: LoadLibraryW('%ls') failed, err=%d",
  3363. szUIDllName,
  3364. GetLastError()
  3365. ));
  3366. lResult = LINEERR_OPERATIONFAILED;
  3367. }
  3368. {
  3369. LONG lResult2;
  3370. FUNC_ARGS funcArgs =
  3371. {
  3372. MAKELONG (LINE_FUNC | SYNC | 2, xFreeDialogInstance),
  3373. {
  3374. (ULONG_PTR) htDlgInst,
  3375. (ULONG_PTR) lResult
  3376. },
  3377. {
  3378. Dword,
  3379. Dword
  3380. }
  3381. };
  3382. //
  3383. // If TUISPI_providerXxx failed then we want to pass that error back
  3384. // to the app, else if it succeeded & FreeDlgInst failed then pass
  3385. // that error back to the app
  3386. //
  3387. if ((lResult2 = DOFUNC(
  3388. &funcArgs,
  3389. "lineXxxProvider/FreeDialogInstance"
  3390. )) == 0)
  3391. {
  3392. if (bAddProvider)
  3393. {
  3394. *lpdwPermProviderID = dwPermProviderID;
  3395. }
  3396. }
  3397. else if (lResult == 0)
  3398. {
  3399. lResult = lResult2;
  3400. }
  3401. }
  3402. return lResult;
  3403. }
  3404. LONG
  3405. PASCAL
  3406. ValidateXxxInitializeParams(
  3407. DWORD dwAPIVersion,
  3408. BOOL bLine,
  3409. LPLINEINITIALIZEEXPARAMS pXxxInitExParams,
  3410. LINECALLBACK pfnCallback
  3411. )
  3412. {
  3413. DWORD dwError;
  3414. __try
  3415. {
  3416. DWORD dwTotalSize = pXxxInitExParams->dwTotalSize;
  3417. if (dwTotalSize < sizeof (LINEINITIALIZEEXPARAMS))
  3418. {
  3419. return (bLine ? LINEERR_STRUCTURETOOSMALL :
  3420. PHONEERR_STRUCTURETOOSMALL);
  3421. }
  3422. if (TAPIIsBadWritePtr (pXxxInitExParams, dwTotalSize))
  3423. {
  3424. return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
  3425. }
  3426. //
  3427. // When checking the dwOptions field be careful about compatibility
  3428. // with future vers, so we only look at the currently valid bits
  3429. //
  3430. switch ((pXxxInitExParams->dwOptions & 0xf))
  3431. {
  3432. case 0:
  3433. case LINEINITIALIZEEXOPTION_USEHIDDENWINDOW:
  3434. if (IsBadCodePtr ((FARPROC) pfnCallback))
  3435. {
  3436. return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
  3437. }
  3438. break;
  3439. case LINEINITIALIZEEXOPTION_USECOMPLETIONPORT:
  3440. if ( !gpPostQueuedCompletionStatus )
  3441. {
  3442. HINSTANCE hInst;
  3443. hInst = GetModuleHandle( "Kernel32.dll" );
  3444. {
  3445. gpPostQueuedCompletionStatus = (PQCSPROC)GetProcAddress(
  3446. hInst,
  3447. "PostQueuedCompletionStatus"
  3448. );
  3449. if ( NULL == gpPostQueuedCompletionStatus )
  3450. {
  3451. LOG((TL_ERROR, "It would seem CompletionPorts are not supported on this platform"));
  3452. return (bLine ? LINEERR_INVALFEATURE : PHONEERR_OPERATIONFAILED);
  3453. }
  3454. }
  3455. }
  3456. break;
  3457. case LINEINITIALIZEEXOPTION_USEEVENT:
  3458. break;
  3459. default:
  3460. if (
  3461. (TAPI_VERSION2_0 == dwAPIVersion)
  3462. ||
  3463. (TAPI_VERSION2_1 == dwAPIVersion)
  3464. )
  3465. {
  3466. //
  3467. // This 2.x app is nuts.
  3468. //
  3469. return (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
  3470. }
  3471. else
  3472. {
  3473. //
  3474. // This >2.0 app is asking for something we can't do.
  3475. //
  3476. return (bLine ? LINEERR_INCOMPATIBLEAPIVERSION :
  3477. PHONEERR_INCOMPATIBLEAPIVERSION);
  3478. }
  3479. }
  3480. pXxxInitExParams->dwNeededSize =
  3481. pXxxInitExParams->dwUsedSize = sizeof (LINEINITIALIZEEXPARAMS);
  3482. }
  3483. __except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
  3484. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  3485. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  3486. {
  3487. return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
  3488. }
  3489. return 0;
  3490. }
  3491. LONG
  3492. GetTheModuleFileName( WCHAR ** ppName )
  3493. {
  3494. DWORD dwSize = MAX_PATH, dwLength;
  3495. WCHAR * pszModuleNamePathW;
  3496. alloc_module_name_buf:
  3497. if (!(pszModuleNamePathW = (WCHAR *)ClientAlloc (dwSize*sizeof(WCHAR))))
  3498. {
  3499. return LINEERR_NOMEM;
  3500. }
  3501. if (GetVersion() & 0x80000000)
  3502. {
  3503. PSTR pTemp;
  3504. //
  3505. // We're on Win9x - do ANSI
  3506. //
  3507. pTemp = (PSTR) ClientAlloc( dwSize );
  3508. if ( NULL == pTemp )
  3509. {
  3510. LOG((
  3511. TL_ERROR,
  3512. "Mem alloc failed (for mod name) size:0x%08lx",
  3513. dwSize
  3514. ));
  3515. return LINEERR_NOMEM;
  3516. }
  3517. if ((dwLength = GetModuleFileName(
  3518. NULL,
  3519. pTemp,
  3520. dwSize
  3521. )) == 0)
  3522. {
  3523. LOG((
  3524. TL_ERROR,
  3525. "GetModuleFileNameA failed, err=%d",
  3526. GetLastError()
  3527. ));
  3528. ClientFree( pTemp );
  3529. return LINEERR_INVALPARAM;
  3530. }
  3531. else if (dwLength >= dwSize)
  3532. {
  3533. ClientFree (pTemp);
  3534. ClientFree (pszModuleNamePathW);
  3535. dwSize *= 2;
  3536. goto alloc_module_name_buf;
  3537. }
  3538. MultiByteToWideChar(
  3539. GetACP(),
  3540. MB_PRECOMPOSED,
  3541. pTemp,
  3542. dwLength,
  3543. pszModuleNamePathW,
  3544. dwSize
  3545. );
  3546. ClientFree( pTemp );
  3547. }
  3548. else
  3549. {
  3550. //
  3551. // We're on WinNT - do Unicode
  3552. //
  3553. if ((dwLength = GetModuleFileNameW(
  3554. NULL,
  3555. pszModuleNamePathW,
  3556. dwSize
  3557. )) == 0)
  3558. {
  3559. LOG((
  3560. TL_ERROR,
  3561. "GetModuleFileNameW failed, err=%d",
  3562. GetLastError()
  3563. ));
  3564. return LINEERR_INVALPARAM;
  3565. }
  3566. else if (dwLength >= dwSize)
  3567. {
  3568. ClientFree (pszModuleNamePathW);
  3569. dwSize *= 2;
  3570. goto alloc_module_name_buf;
  3571. }
  3572. }
  3573. *ppName = pszModuleNamePathW;
  3574. return 0;
  3575. }
  3576. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3577. //
  3578. // CreateThreadsAndStuff
  3579. //
  3580. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  3581. // only and hence access to it is serialized. Calling this function from some
  3582. // other functionality would need making an alternate arrangement to serialize
  3583. // access to this function
  3584. //
  3585. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3586. LONG
  3587. CreateThreadsAndStuff()
  3588. {
  3589. DWORD dwThreadID;
  3590. LOG((TL_TRACE, "CreateThreadsAndStuff: enter"));
  3591. //
  3592. // Alloc resources for a new async events thread, then
  3593. // create the thread
  3594. //
  3595. gpAsyncEventsThreadParams = (PASYNC_EVENTS_THREAD_PARAMS) ClientAlloc(
  3596. sizeof (ASYNC_EVENTS_THREAD_PARAMS));
  3597. if (NULL == gpAsyncEventsThreadParams)
  3598. {
  3599. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate gpAsyncEventsThreadParams"));
  3600. return LINEERR_OPERATIONFAILED;
  3601. }
  3602. //
  3603. // we don't want the thread to exit as soon as it starts
  3604. //
  3605. gpAsyncEventsThreadParams->bExitThread = FALSE;
  3606. //
  3607. // Create the initial buffer the thread will use for
  3608. // retreiving async events
  3609. //
  3610. gpAsyncEventsThreadParams->dwBufSize =
  3611. ASNYC_MSG_BUF_SIZE;
  3612. gpAsyncEventsThreadParams->pBuf = (LPBYTE) ClientAlloc(
  3613. gpAsyncEventsThreadParams->dwBufSize);
  3614. if (NULL == gpAsyncEventsThreadParams->pBuf)
  3615. {
  3616. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate gpAsyncEventsThreadParams->pBuf"));
  3617. ClientFree( gpAsyncEventsThreadParams );
  3618. gpAsyncEventsThreadParams = NULL;
  3619. return LINEERR_OPERATIONFAILED;
  3620. }
  3621. ghAsyncRetryQueueEvent = CreateEvent(
  3622. NULL,
  3623. FALSE,
  3624. FALSE,
  3625. NULL
  3626. );
  3627. if (NULL == ghAsyncRetryQueueEvent)
  3628. {
  3629. LOG((TL_ERROR,
  3630. "CreateThreadsAndStuff - failed to create ghAsyncRetryQueueEvent event"));
  3631. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3632. ClientFree( gpAsyncEventsThreadParams );
  3633. gpAsyncEventsThreadParams = NULL;
  3634. return LINEERR_OPERATIONFAILED;
  3635. }
  3636. //
  3637. // create startup event -- the thread will signal it when it is up and
  3638. // ready to do stuff
  3639. //
  3640. gpAsyncEventsThreadParams->hThreadStartupEvent =
  3641. CreateEvent(NULL, FALSE, FALSE, NULL);
  3642. if (NULL == gpAsyncEventsThreadParams->hThreadStartupEvent)
  3643. {
  3644. LOG((TL_ERROR,
  3645. "CreateThreadsAndStuff - failed to create hThreadStartupEvent event. LastError= 0x%lx",
  3646. GetLastError()));
  3647. CloseHandle(ghAsyncRetryQueueEvent);
  3648. ghAsyncRetryQueueEvent = NULL;
  3649. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3650. ClientFree( gpAsyncEventsThreadParams );
  3651. gpAsyncEventsThreadParams = NULL;
  3652. return LINEERR_OPERATIONFAILED;
  3653. }
  3654. //
  3655. // Now that we've allocated all the resources try to exec
  3656. // the thread
  3657. //
  3658. ghAsyncEventsThread = CreateThread(
  3659. NULL,
  3660. 0,
  3661. (LPTHREAD_START_ROUTINE) AsyncEventsThread,
  3662. (LPVOID) gpAsyncEventsThreadParams,
  3663. 0,
  3664. &dwThreadID
  3665. );
  3666. if (NULL == ghAsyncEventsThread)
  3667. {
  3668. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate AsyncEventsThread"));
  3669. CloseHandle(ghAsyncRetryQueueEvent);
  3670. ghAsyncRetryQueueEvent = NULL;
  3671. CloseHandle(gpAsyncEventsThreadParams->hThreadStartupEvent);
  3672. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3673. ClientFree(gpAsyncEventsThreadParams);
  3674. gpAsyncEventsThreadParams = NULL;
  3675. return LINEERR_OPERATIONFAILED;
  3676. }
  3677. //
  3678. // wait for the thread to have completed initialization or for the thread
  3679. // to exit. if the thread exited, it had an error, so return an error.
  3680. //
  3681. // this is needed so msp's do not initialize and start posting events
  3682. // before asynceventsthread opens up RetryQueue to accept these events.
  3683. //
  3684. // it would be more efficient to wait for these events immediately before
  3685. // creating address objects, but the code would be much more complex and
  3686. // the performance gain would be for tapi initialization only, so we won't
  3687. // bother.
  3688. //
  3689. HANDLE ahAsyncThreadEvents[] =
  3690. {
  3691. gpAsyncEventsThreadParams->hThreadStartupEvent,
  3692. ghAsyncEventsThread
  3693. };
  3694. DWORD dwWaitResult = WaitForMultipleObjectsEx(
  3695. sizeof(ahAsyncThreadEvents)/sizeof(HANDLE),
  3696. ahAsyncThreadEvents,
  3697. FALSE,
  3698. INFINITE,
  3699. FALSE);
  3700. //
  3701. // succeeded or failed, this event is no longer needed
  3702. //
  3703. CloseHandle(gpAsyncEventsThreadParams->hThreadStartupEvent);
  3704. gpAsyncEventsThreadParams->hThreadStartupEvent = NULL;
  3705. //
  3706. // did we unblock because the thread exited?
  3707. //
  3708. if (dwWaitResult == WAIT_OBJECT_0 + 1)
  3709. {
  3710. //
  3711. // thread exited
  3712. //
  3713. LOG((TL_ERROR, "CreateThreadsAndStuff: AsyncEventsThread exited"));
  3714. CloseHandle(ghAsyncRetryQueueEvent);
  3715. ghAsyncRetryQueueEvent = NULL;
  3716. CloseHandle(ghAsyncEventsThread);
  3717. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3718. ClientFree(gpAsyncEventsThreadParams);
  3719. gpAsyncEventsThreadParams = NULL;
  3720. return LINEERR_OPERATIONFAILED;
  3721. }
  3722. //
  3723. // did we unblock for any reason other than thread exited or success?
  3724. //
  3725. if (dwWaitResult != WAIT_OBJECT_0)
  3726. {
  3727. LOG((TL_ERROR, "CreateThreadsAndStuff: failed waiting tor AsyncEventsThread initialization"));
  3728. //
  3729. // we had an error waiting for the thread to signal its successful
  3730. // startup.
  3731. //
  3732. //
  3733. // if the thread is still up, tell it to stop.
  3734. //
  3735. gpAsyncEventsThreadParams->bExitThread = TRUE;
  3736. //
  3737. // we could wait for the thread to exit... but we got here because wait
  3738. // failed, so there is little benefit in retrying. so take our chances
  3739. // and clean up.
  3740. //
  3741. CloseHandle(ghAsyncRetryQueueEvent);
  3742. ghAsyncRetryQueueEvent = NULL;
  3743. CloseHandle(ghAsyncEventsThread);
  3744. ghAsyncEventsThread = NULL;
  3745. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3746. ClientFree(gpAsyncEventsThreadParams);
  3747. gpAsyncEventsThreadParams = NULL;
  3748. return LINEERR_OPERATIONFAILED;
  3749. }
  3750. //
  3751. // if we got here, async events thread initialized and is running
  3752. //
  3753. ghCallbackThreadEvent = CreateEvent(
  3754. NULL,
  3755. FALSE,
  3756. FALSE,
  3757. NULL
  3758. );
  3759. gbExitThread = FALSE;
  3760. ghCallbackThread = CreateThread(
  3761. NULL,
  3762. 0,
  3763. (LPTHREAD_START_ROUTINE) CallbackThread,
  3764. (LPVOID) NULL,
  3765. 0,
  3766. &dwThreadID
  3767. );
  3768. if (NULL == ghCallbackThread)
  3769. {
  3770. // don't free these buffers. The other thread
  3771. // is already running at this point, the these
  3772. // buffers will be cleaned up during normal
  3773. // shutdown
  3774. //ClientFree(gpAsyncEventsThreadParams->pBuf);
  3775. //ClientFree(gpAsyncEventsThreadParams);
  3776. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to create CallbackThread"));
  3777. return LINEERR_OPERATIONFAILED;
  3778. }
  3779. LOG((TL_TRACE, "CreateThreadsAndStuff: exit"));
  3780. return 0;
  3781. }
  3782. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3783. //
  3784. // NewInitialize
  3785. //
  3786. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  3787. // only and hence access to it is serialized. Calling this function from some
  3788. // other functionality would need making an alternate arrangement to serialize
  3789. // access to this function
  3790. //
  3791. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3792. HRESULT
  3793. CTAPI::NewInitialize()
  3794. {
  3795. LOG((TL_INFO, "NewInitialize - enter"));
  3796. FUNC_ARGS funcArgs =
  3797. {
  3798. MAKELONG (LINE_FUNC | SYNC | 7, lInitialize),
  3799. {
  3800. (ULONG_PTR) &m_hLineApp,
  3801. // tapisrv ignores this argument, so pass 0 and save on HINSTANCE<->32bit conversion
  3802. 0,
  3803. 0,
  3804. (ULONG_PTR) gszTAPI3,
  3805. (ULONG_PTR) &m_dwLineDevs,
  3806. 0, // pszModuleName
  3807. TAPI_CURRENT_VERSION
  3808. },
  3809. {
  3810. lpDword,
  3811. Dword,
  3812. Dword,
  3813. lpszW,
  3814. lpDword,
  3815. lpszW,
  3816. Dword
  3817. }
  3818. };
  3819. WCHAR * pszModuleNamePathW = NULL;
  3820. LONG lResult = (LONG)S_OK;
  3821. int tapiObjectArraySize=0;
  3822. lResult = GetTheModuleFileName( &pszModuleNamePathW );
  3823. if ( 0!= lResult )
  3824. {
  3825. goto xxxInitialize_return;
  3826. }
  3827. funcArgs.Args[5] = (ULONG_PTR) wcsrchr (pszModuleNamePathW, '\\') +
  3828. sizeof(WCHAR);
  3829. _ASSERTE(m_pLineInitData == NULL);
  3830. m_pLineInitData = (PT3INIT_DATA) ClientAlloc (sizeof(T3INIT_DATA));
  3831. if (NULL == m_pLineInitData)
  3832. {
  3833. LOG((TL_ERROR, "NewInitialize: failed to allocate m_pLineInitData"));
  3834. lResult = LINEERR_NOMEM;
  3835. goto xxxInitialize_return;
  3836. }
  3837. m_pLineInitData->dwInitOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW |
  3838. LINEINITIALIZEEXOPTION_CALLHUBTRACKING;
  3839. m_pLineInitData->bPendingAsyncEventMsg = FALSE;
  3840. m_pLineInitData->dwKey = INITDATA_KEY;
  3841. m_pLineInitData->pTAPI = this;
  3842. //
  3843. // We want to pass TAPISRV pInitData so that later when it does async
  3844. // completion/event notification it can pass pInitData along too so
  3845. // we know which init instance to talk to
  3846. //
  3847. //
  3848. // convert the pointer into a 32-bit handle, so we don't need to pass a
  3849. // 64-bit value between tapi3.dll and tapisrv
  3850. //
  3851. _ASSERTE(m_dwLineInitDataHandle == 0);
  3852. m_dwLineInitDataHandle = CreateHandleTableEntry((ULONG_PTR)m_pLineInitData);
  3853. LOG((TL_INFO, "NewInitialize: handle for m_pLineInitData = [0x%lx]", m_dwLineInitDataHandle));
  3854. if (0 == m_dwLineInitDataHandle)
  3855. {
  3856. LOG((TL_ERROR, "NewInitialize: failed to create handle"));
  3857. ClientFree(m_pLineInitData);
  3858. m_pLineInitData = NULL;
  3859. lResult = LINEERR_NOMEM;
  3860. goto xxxInitialize_return;
  3861. }
  3862. funcArgs.Args[2] = m_dwLineInitDataHandle;
  3863. //
  3864. // call lineInitialize
  3865. //
  3866. lResult = DOFUNC (&funcArgs, "lineInitialize");
  3867. if (lResult == 0)
  3868. {
  3869. LOG((TL_INFO, "NewInitialize: lineInitialize succeeded. m_hLineApp %p", m_hLineApp));
  3870. }
  3871. else
  3872. {
  3873. LOG((TL_ERROR, "NewInitialize: lineInitialize failed. "));
  3874. //
  3875. // undo the deed
  3876. //
  3877. ClientFree(m_pLineInitData);
  3878. m_pLineInitData = NULL;
  3879. DeleteHandleTableEntry(m_dwLineInitDataHandle);
  3880. m_dwLineInitDataHandle = NULL;
  3881. goto xxxInitialize_return;
  3882. }
  3883. //
  3884. // Save the hLineApp returned by TAPISRV in our InitData struct,
  3885. // and give the app back a pointer to the InitData struct instead
  3886. //
  3887. m_pLineInitData->hXxxApp = m_hLineApp;
  3888. //
  3889. // now setup for phoneinitialize
  3890. //
  3891. funcArgs.Args[0] = (ULONG_PTR)&m_hPhoneApp;
  3892. funcArgs.Args[4] = (ULONG_PTR)&m_dwPhoneDevs;
  3893. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 7, pInitialize);
  3894. _ASSERTE(m_pPhoneInitData == NULL);
  3895. m_pPhoneInitData = (PT3INIT_DATA) ClientAlloc (sizeof(T3INIT_DATA));
  3896. if ( NULL == m_pPhoneInitData )
  3897. {
  3898. LOG((TL_ERROR, "NewInitialize: failed to allocate m_pPhoneInitData"));
  3899. lResult = LINEERR_NOMEM;
  3900. goto xxxInitialize_return;
  3901. }
  3902. m_pPhoneInitData->dwInitOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
  3903. m_pPhoneInitData->bPendingAsyncEventMsg = FALSE;
  3904. m_pPhoneInitData->dwKey = INITDATA_KEY;
  3905. m_pPhoneInitData ->pTAPI = this;
  3906. //
  3907. // We want to pass TAPISRV pInitData so that later when it does async
  3908. // completion/event notification it can pass pInitData along too so
  3909. // we know which init instance to talk to
  3910. //
  3911. //
  3912. // convert the pointer into a 32-bit handle, so we don't need to pass a
  3913. // 64-bit value between tapi3.dll and tapisrv
  3914. //
  3915. _ASSERTE(m_dwPhoneInitDataHandle == 0);
  3916. m_dwPhoneInitDataHandle = CreateHandleTableEntry((ULONG_PTR)m_pPhoneInitData );
  3917. LOG((TL_INFO, "NewInitialize: handle for m_pPhoneInitData = [0x%lx]", m_dwPhoneInitDataHandle));
  3918. if (0 == m_dwPhoneInitDataHandle)
  3919. {
  3920. LOG((TL_ERROR, "NewInitialize: failed to create handle"));
  3921. //
  3922. // free the phone-related resources that we have already allocated
  3923. //
  3924. ClientFree(m_pPhoneInitData);
  3925. m_pPhoneInitData = NULL;
  3926. lResult = LINEERR_NOMEM;
  3927. goto xxxInitialize_return;
  3928. }
  3929. funcArgs.Args[2] = m_dwPhoneInitDataHandle;
  3930. lResult = DOFUNC (&funcArgs, "phoneInitialize");
  3931. if (lResult == 0)
  3932. {
  3933. LOG((TL_INFO, "NewInitialize: phoneInitialize succeeded. m_hPhoneApp %p", m_hPhoneApp));
  3934. }
  3935. else
  3936. {
  3937. LOG((TL_ERROR, "NewInitialize: phoneInitialize failed. "));
  3938. //
  3939. // deallocate whatever resources we have allocated for the phone
  3940. //
  3941. ClientFree(m_pPhoneInitData);
  3942. m_pPhoneInitData = NULL;
  3943. DeleteHandleTableEntry(m_dwPhoneInitDataHandle);
  3944. m_dwPhoneInitDataHandle = 0;
  3945. goto xxxInitialize_return;
  3946. }
  3947. m_pPhoneInitData ->hXxxApp = m_hPhoneApp;
  3948. //
  3949. // If total number of init instances is 0 we need to start a
  3950. // new async events thread
  3951. //
  3952. EnterCriticalSection( &gcsTapiObjectArray );
  3953. tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
  3954. LeaveCriticalSection ( &gcsTapiObjectArray );
  3955. if ( 0 == tapiObjectArraySize )
  3956. {
  3957. lResult = CreateThreadsAndStuff();
  3958. if ( 0 != lResult )
  3959. {
  3960. goto xxxInitialize_return;
  3961. }
  3962. }
  3963. xxxInitialize_return:
  3964. if (pszModuleNamePathW)
  3965. {
  3966. ClientFree (pszModuleNamePathW);
  3967. }
  3968. if ( 0 != lResult )
  3969. {
  3970. //
  3971. // cleanup all line- and phone-related resources.
  3972. //
  3973. NewShutdown();
  3974. }
  3975. #if DBG
  3976. {
  3977. char szResult[32];
  3978. LOG((
  3979. TL_INFO,
  3980. "Initialize exit, result=%s",
  3981. MapResultCodeToText (lResult, szResult)
  3982. ));
  3983. }
  3984. #else
  3985. //
  3986. // we may want to know what happened even with non-debug build
  3987. //
  3988. LOG((TL_INFO, "NewInitialize - exit, result=0x%lx", lResult));
  3989. #endif
  3990. return mapTAPIErrorCode( lResult );
  3991. }
  3992. //
  3993. // --------------------------------- lineXxx ----------------------------------
  3994. //
  3995. HRESULT
  3996. LineAccept(
  3997. HCALL hCall,
  3998. LPCSTR lpsUserUserInfo,
  3999. DWORD dwSize
  4000. )
  4001. {
  4002. FUNC_ARGS funcArgs =
  4003. {
  4004. MAKELONG (LINE_FUNC | ASYNC | 3, lAccept),
  4005. {
  4006. (ULONG_PTR) hCall,
  4007. (ULONG_PTR) lpsUserUserInfo,
  4008. dwSize
  4009. },
  4010. {
  4011. Dword,
  4012. lpSet_SizeToFollow,
  4013. Size
  4014. }
  4015. };
  4016. if (!lpsUserUserInfo)
  4017. {
  4018. //
  4019. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4020. //
  4021. funcArgs.ArgTypes[1] = Dword;
  4022. funcArgs.Args[1] = TAPI_NO_DATA;
  4023. funcArgs.ArgTypes[2] = Dword;
  4024. }
  4025. return mapTAPIErrorCode( (DOFUNC (&funcArgs, "lineAccept")) );
  4026. }
  4027. HRESULT
  4028. LineAddToConference(
  4029. HCALL hConfCall,
  4030. HCALL hConsultCall
  4031. )
  4032. {
  4033. FUNC_ARGS funcArgs =
  4034. {
  4035. MAKELONG (LINE_FUNC | ASYNC | 2, lAddToConference),
  4036. {
  4037. (ULONG_PTR) hConfCall,
  4038. (ULONG_PTR) hConsultCall
  4039. },
  4040. {
  4041. Dword,
  4042. Dword
  4043. }
  4044. };
  4045. return mapTAPIErrorCode( (DOFUNC (&funcArgs, "LineAddToConference")) );
  4046. }
  4047. LONG
  4048. WINAPI
  4049. lineAgentSpecific(
  4050. HLINE hLine,
  4051. DWORD dwAddressID,
  4052. DWORD dwAgentExtensionIDIndex,
  4053. LPVOID lpParams,
  4054. DWORD dwSize
  4055. )
  4056. {
  4057. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR) lpParams);
  4058. FUNC_ARGS funcArgs =
  4059. {
  4060. MAKELONG (LINE_FUNC | ASYNC | 7, lAgentSpecific),
  4061. {
  4062. GetFunctionIndex(lineDevSpecificPostProcess),
  4063. (ULONG_PTR) hLine,
  4064. (ULONG_PTR) dwAddressID,
  4065. (ULONG_PTR) dwAgentExtensionIDIndex,
  4066. hpParams,
  4067. (ULONG_PTR) lpParams,
  4068. (ULONG_PTR) dwSize
  4069. },
  4070. {
  4071. Dword,
  4072. Dword,
  4073. Dword,
  4074. Dword,
  4075. Dword,
  4076. lpSet_SizeToFollow,
  4077. Size
  4078. }
  4079. };
  4080. LONG lResult = DOFUNC (&funcArgs, "lineAgentSpecific");
  4081. //
  4082. // in case of failure or synchronous call, delete the entry from the table
  4083. // otherwise, the callback will do that
  4084. //
  4085. if (lResult <= 0)
  4086. {
  4087. DeleteHandleTableEntry(hpParams);
  4088. }
  4089. return lResult;
  4090. }
  4091. HRESULT
  4092. LineAnswer(
  4093. HCALL hCall
  4094. )
  4095. {
  4096. FUNC_ARGS funcArgs =
  4097. {
  4098. MAKELONG (LINE_FUNC | ASYNC | 3, lAnswer),
  4099. {
  4100. (ULONG_PTR) hCall,
  4101. (ULONG_PTR) 0,
  4102. 0
  4103. },
  4104. {
  4105. Dword,
  4106. Dword,
  4107. Dword
  4108. }
  4109. };
  4110. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineAnswer") );
  4111. }
  4112. HRESULT
  4113. LineBlindTransfer(
  4114. HCALL hCall,
  4115. LPCWSTR lpszDestAddress,
  4116. DWORD dwCountryCode
  4117. )
  4118. {
  4119. FUNC_ARGS funcArgs =
  4120. {
  4121. MAKELONG (LINE_FUNC | ASYNC | 3, lBlindTransfer),
  4122. {
  4123. (ULONG_PTR) hCall,
  4124. (ULONG_PTR) lpszDestAddress,
  4125. dwCountryCode
  4126. },
  4127. {
  4128. Dword,
  4129. lpszW,
  4130. Dword
  4131. }
  4132. };
  4133. if ( IsBadStringPtrW( lpszDestAddress, (UINT)-1 ) )
  4134. {
  4135. LOG((TL_ERROR, "LineBlindTransfer: bad lpszDestAddress: 0x%p", lpszDestAddress));
  4136. return mapTAPIErrorCode(LINEERR_INVALPOINTER);
  4137. }
  4138. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineBlindTransfer") );
  4139. }
  4140. HRESULT
  4141. LineClose(
  4142. T3LINE * pt3Line
  4143. )
  4144. {
  4145. LONG lResult;
  4146. FUNC_ARGS funcArgs =
  4147. {
  4148. MAKELONG (LINE_FUNC | SYNC | 1, lClose),
  4149. {
  4150. (ULONG_PTR) pt3Line->hLine
  4151. },
  4152. {
  4153. Dword
  4154. }
  4155. };
  4156. gpLineHashTable->Lock();
  4157. lResult = DOFUNC (&funcArgs, "lineClose");
  4158. LOG((TL_INFO, "lineClose: line - %lx lResult %lx", pt3Line->hLine, lResult));
  4159. gpLineHashTable->Remove( (ULONG_PTR)(pt3Line->hLine) );
  4160. gpLineHashTable->Unlock();
  4161. //
  4162. // remove the corresponding entry from the callback instance handle table
  4163. //
  4164. if (0 != pt3Line->dwAddressLineStructHandle)
  4165. {
  4166. LOG((TL_INFO, "lineClose: removing address line handle [%lx] from the handle table",
  4167. pt3Line->dwAddressLineStructHandle));
  4168. DeleteHandleTableEntry(pt3Line->dwAddressLineStructHandle);
  4169. pt3Line->dwAddressLineStructHandle = 0;
  4170. }
  4171. return mapTAPIErrorCode( lResult );
  4172. }
  4173. void
  4174. PASCAL
  4175. lineCompleteCallPostProcess(
  4176. PASYNCEVENTMSG pMsg
  4177. )
  4178. {
  4179. LOG((TL_TRACE, "lineCompleteCallPostProcess: enter"));
  4180. LOG((
  4181. TL_INFO,
  4182. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4183. pMsg->Param1,
  4184. pMsg->Param2,
  4185. pMsg->Param3,
  4186. pMsg->Param4
  4187. ));
  4188. if (pMsg->Param2 == 0)
  4189. {
  4190. DWORD dwCompletionID = pMsg->Param3;
  4191. LPDWORD lpdwCompletionID = (LPDWORD)GetHandleTableEntry(pMsg->Param4);
  4192. DeleteHandleTableEntry(pMsg->Param4);
  4193. __try
  4194. {
  4195. {
  4196. *lpdwCompletionID = dwCompletionID;
  4197. }
  4198. }
  4199. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4200. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4201. {
  4202. LOG((TL_WARN, "lineCompleteCallPostProcess: failed "
  4203. "to write to [%p]: LINEERR_INVALPOINTER",
  4204. lpdwCompletionID));
  4205. pMsg->Param2 = LINEERR_INVALPOINTER;
  4206. }
  4207. }
  4208. }
  4209. LONG
  4210. WINAPI
  4211. lineCompleteCall(
  4212. HCALL hCall,
  4213. LPDWORD lpdwCompletionID,
  4214. DWORD dwCompletionMode,
  4215. DWORD dwMessageID
  4216. )
  4217. {
  4218. DWORD hpdwCompletionID = CreateHandleTableEntry((ULONG_PTR)lpdwCompletionID);
  4219. FUNC_ARGS funcArgs =
  4220. {
  4221. MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteCall),
  4222. {
  4223. GetFunctionIndex(lineCompleteCallPostProcess),
  4224. (ULONG_PTR) hCall,
  4225. hpdwCompletionID,
  4226. dwCompletionMode,
  4227. dwMessageID
  4228. },
  4229. {
  4230. Dword,
  4231. Dword,
  4232. lpDword,
  4233. Dword,
  4234. Dword
  4235. }
  4236. };
  4237. LONG lResult = (DOFUNC (&funcArgs, "lineCompleteCall"));
  4238. //
  4239. // in case of failure or synchronous call, delete the entry from the table
  4240. // otherwise, the callback will do that
  4241. //
  4242. if (lResult <= 0)
  4243. {
  4244. DeleteHandleTableEntry(hpdwCompletionID);
  4245. }
  4246. return lResult;
  4247. }
  4248. HRESULT
  4249. LineCompleteTransfer(
  4250. HCALL hCall,
  4251. HCALL hConsultCall,
  4252. T3CALL * pt3ConfCall,
  4253. DWORD dwTransferMode
  4254. )
  4255. {
  4256. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR) &(pt3ConfCall->hCall));
  4257. FUNC_ARGS funcArgs =
  4258. {
  4259. MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteTransfer),
  4260. {
  4261. GetFunctionIndex(lineMakeCallPostProcess),
  4262. hCall,
  4263. hConsultCall,
  4264. hpCallHandle,
  4265. dwTransferMode,
  4266. },
  4267. {
  4268. Dword,
  4269. Dword,
  4270. Dword,
  4271. Dword,
  4272. Dword,
  4273. }
  4274. };
  4275. if (dwTransferMode == LINETRANSFERMODE_TRANSFER)
  4276. {
  4277. funcArgs.Args[0] = 0;
  4278. //
  4279. // hpCallHandle should be ignored
  4280. //
  4281. funcArgs.Args[3] = 0;
  4282. DeleteHandleTableEntry(hpCallHandle);
  4283. hpCallHandle = 0;
  4284. }
  4285. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCompleteTransfer") );
  4286. if (FAILED(hr))
  4287. {
  4288. DeleteHandleTableEntry(hpCallHandle);
  4289. hpCallHandle = 0;
  4290. }
  4291. return hr ;
  4292. }
  4293. HRESULT
  4294. LineConfigDialogW(
  4295. DWORD dwDeviceID,
  4296. HWND hwndOwner,
  4297. LPCWSTR lpszDeviceClass
  4298. )
  4299. {
  4300. LONG lResult;
  4301. HANDLE hDll;
  4302. TUISPIPROC pfnTUISPI_lineConfigDialog;
  4303. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, 256))
  4304. {
  4305. return E_POINTER;
  4306. }
  4307. if ((lResult = LoadUIDll(
  4308. hwndOwner,
  4309. dwDeviceID,
  4310. TUISPIDLL_OBJECT_LINEID,
  4311. &hDll,
  4312. gszTUISPI_lineConfigDialog,
  4313. &pfnTUISPI_lineConfigDialog
  4314. )) == 0)
  4315. {
  4316. LOG((TL_INFO, "Calling TUISPI_lineConfigDialog..."));
  4317. lResult = ((TUILINECONFIGPROC)(*pfnTUISPI_lineConfigDialog))(
  4318. TUISPIDLLCallback,
  4319. dwDeviceID,
  4320. (HWND)hwndOwner,
  4321. (LPCSTR)lpszDeviceClass
  4322. );
  4323. #if DBG
  4324. {
  4325. char szResult[32];
  4326. LOG((TL_INFO,
  4327. "TUISPI_lineConfigDialog: result = %s",
  4328. MapResultCodeToText (lResult, szResult)
  4329. ));
  4330. }
  4331. #endif
  4332. FreeLibrary ((HINSTANCE)hDll);
  4333. }
  4334. return mapTAPIErrorCode(lResult);
  4335. }
  4336. HRESULT
  4337. LineConfigDialogEditW(
  4338. DWORD dwDeviceID,
  4339. HWND hwndOwner,
  4340. LPCWSTR lpszDeviceClass,
  4341. LPVOID const lpDeviceConfigIn,
  4342. DWORD dwSizeIn,
  4343. LPVARSTRING * ppDeviceConfigOut
  4344. )
  4345. {
  4346. LONG lResult;
  4347. HANDLE hDll;
  4348. TUISPIPROC pfnTUISPI_lineConfigDialogEdit;
  4349. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, (UINT) -1))
  4350. {
  4351. return E_POINTER;
  4352. }
  4353. if (IsBadReadPtr (lpDeviceConfigIn, dwSizeIn))
  4354. {
  4355. return E_POINTER;
  4356. }
  4357. DWORD dwSize = sizeof (VARSTRING) + 500;
  4358. *ppDeviceConfigOut = (LPVARSTRING) ClientAlloc( dwSize );
  4359. if (NULL == *ppDeviceConfigOut)
  4360. {
  4361. LOG((TL_ERROR, "LineConfigDialogEditW exit - return E_OUTOFMEMORY"));
  4362. return E_OUTOFMEMORY;
  4363. }
  4364. (*ppDeviceConfigOut)->dwTotalSize = dwSize;
  4365. if ((lResult = LoadUIDll(
  4366. hwndOwner,
  4367. dwDeviceID,
  4368. TUISPIDLL_OBJECT_LINEID,
  4369. &hDll,
  4370. gszTUISPI_lineConfigDialogEdit,
  4371. &pfnTUISPI_lineConfigDialogEdit
  4372. )) == 0)
  4373. {
  4374. while (TRUE)
  4375. {
  4376. LOG((TL_INFO, "Calling TUISPI_lineConfigDialogEdit..."));
  4377. lResult = ((TUILINECONFIGEDITPROC)(*pfnTUISPI_lineConfigDialogEdit))(
  4378. TUISPIDLLCallback,
  4379. dwDeviceID,
  4380. (HWND)hwndOwner,
  4381. (char *)lpszDeviceClass,
  4382. lpDeviceConfigIn,
  4383. dwSizeIn,
  4384. *ppDeviceConfigOut
  4385. );
  4386. #if DBG
  4387. {
  4388. char szResult[32];
  4389. LOG((TL_INFO,
  4390. "TUISPI_lineConfigDialogEdit: result = %s",
  4391. MapResultCodeToText (lResult, szResult)
  4392. ));
  4393. }
  4394. #endif
  4395. if ((lResult == 0) && ((*ppDeviceConfigOut)->dwNeededSize > (*ppDeviceConfigOut)->dwTotalSize))
  4396. {
  4397. dwSize = (*ppDeviceConfigOut)->dwNeededSize;
  4398. ClientFree(*ppDeviceConfigOut);
  4399. *ppDeviceConfigOut = (LPVARSTRING)ClientAlloc(dwSize);
  4400. if (NULL == *ppDeviceConfigOut)
  4401. {
  4402. LOG((TL_ERROR, "LineConfigDialogEditW exit - return E_OUTOFMEMORY"));
  4403. return E_OUTOFMEMORY;
  4404. }
  4405. (*ppDeviceConfigOut)->dwTotalSize = dwSize;
  4406. }
  4407. else
  4408. {
  4409. break;
  4410. }
  4411. }
  4412. FreeLibrary ((HINSTANCE)hDll);
  4413. }
  4414. return mapTAPIErrorCode(lResult);
  4415. }
  4416. LONG
  4417. WINAPI
  4418. lineConfigProvider(
  4419. HWND hwndOwner,
  4420. DWORD dwPermanentProviderID
  4421. )
  4422. {
  4423. return (lineXxxProvider(
  4424. gszTUISPI_providerConfig, // func name
  4425. NULL, // lpszProviderFilename
  4426. hwndOwner, // hwndOwner
  4427. dwPermanentProviderID, // dwPermProviderID
  4428. NULL // lpdwPermProviderID
  4429. ));
  4430. }
  4431. HRESULT
  4432. LineDeallocateCall(
  4433. HCALL hCall
  4434. )
  4435. {
  4436. HRESULT hr;
  4437. FUNC_ARGS funcArgs =
  4438. {
  4439. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
  4440. {
  4441. (ULONG_PTR) hCall
  4442. },
  4443. {
  4444. Dword
  4445. }
  4446. };
  4447. LOG((TL_INFO, "lineDeallocateCall - hCall = 0x%08lx", hCall));
  4448. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineDeallocateCall") );
  4449. return hr;
  4450. }
  4451. void
  4452. PASCAL
  4453. lineDevSpecificPostProcess(
  4454. PASYNCEVENTMSG pMsg
  4455. )
  4456. {
  4457. LOG((TL_TRACE, "lineDevSpecificPostProcess: enter"));
  4458. LOG((TL_INFO,
  4459. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4460. pMsg->Param1,
  4461. pMsg->Param2,
  4462. pMsg->Param3,
  4463. pMsg->Param4
  4464. ));
  4465. if (pMsg->Param2 == 0)
  4466. {
  4467. DWORD dwSize = pMsg->Param4;
  4468. LPBYTE pParams = (LPBYTE) GetHandleTableEntry(pMsg->Param3);
  4469. //
  4470. // no longer need the handle table entry for this handle
  4471. //
  4472. DeleteHandleTableEntry(pMsg->Param3);
  4473. __try
  4474. {
  4475. {
  4476. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  4477. }
  4478. }
  4479. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4480. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4481. {
  4482. pMsg->Param2 = LINEERR_INVALPOINTER;
  4483. LOG((TL_INFO,
  4484. "lineDevSpecificPostProcess: failed to copy memory to "
  4485. "[%p] from [%p]: LINEERR_INVALPOINTER",
  4486. pParams, (LPBYTE) (pMsg + 1)));
  4487. }
  4488. }
  4489. LOG((TL_TRACE, "lineDevSpecificPostProcess: exit"));
  4490. }
  4491. HRESULT
  4492. WINAPI
  4493. lineDevSpecific(
  4494. HLINE hLine,
  4495. DWORD dwAddressID,
  4496. HCALL hCall,
  4497. LPVOID lpParams,
  4498. DWORD dwSize
  4499. )
  4500. {
  4501. //
  4502. // convert the pointer to a handle. the table entry will be removed in
  4503. // the callback
  4504. //
  4505. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  4506. FUNC_ARGS funcArgs =
  4507. {
  4508. MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecific),
  4509. {
  4510. GetFunctionIndex(lineDevSpecificPostProcess),
  4511. (ULONG_PTR) hLine,
  4512. dwAddressID,
  4513. (ULONG_PTR) hCall,
  4514. hpParams, // pass the handle to actual pointer (for post processing)
  4515. (ULONG_PTR) lpParams, // pass data
  4516. dwSize
  4517. },
  4518. {
  4519. Dword,
  4520. Dword,
  4521. Dword,
  4522. Dword,
  4523. Dword,
  4524. lpSet_SizeToFollow,
  4525. Size
  4526. }
  4527. };
  4528. LONG lResult = DOFUNC (&funcArgs, "lineDevSpecific");
  4529. //
  4530. // if failed, or synchronous call, remove the handle table entry. otherwise
  4531. // the callback will do this.
  4532. //
  4533. HRESULT hr = E_FAIL;
  4534. if (lResult <= 0)
  4535. {
  4536. DeleteHandleTableEntry(hpParams);
  4537. hpParams = 0;
  4538. hr = mapTAPIErrorCode(lResult);
  4539. }
  4540. else
  4541. {
  4542. //
  4543. // block to see if the operation succeeds
  4544. //
  4545. hr = WaitForReply(lResult);
  4546. }
  4547. return hr;
  4548. }
  4549. LONG
  4550. WINAPI
  4551. lineDevSpecificFeature(
  4552. HLINE hLine,
  4553. DWORD dwFeature,
  4554. LPVOID lpParams,
  4555. DWORD dwSize
  4556. )
  4557. {
  4558. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  4559. FUNC_ARGS funcArgs =
  4560. {
  4561. MAKELONG (LINE_FUNC | ASYNC | 6, lDevSpecificFeature),
  4562. {
  4563. GetFunctionIndex(lineDevSpecificPostProcess),
  4564. (ULONG_PTR) hLine,
  4565. dwFeature,
  4566. hpParams, // pass the actual pointer (for post processing)
  4567. (ULONG_PTR) lpParams, // pass data
  4568. dwSize
  4569. },
  4570. {
  4571. Dword,
  4572. Dword,
  4573. Dword,
  4574. Dword,
  4575. lpSet_SizeToFollow,
  4576. Size
  4577. }
  4578. };
  4579. LONG lResult = DOFUNC (&funcArgs, "lineDevSpecificFeature");
  4580. //
  4581. // if failed, or synchronous call, remove the handle table entry.
  4582. // otherwise the callback will do this.
  4583. //
  4584. if (lResult <= 0)
  4585. {
  4586. DeleteHandleTableEntry(hpParams);
  4587. }
  4588. return lResult;
  4589. }
  4590. HRESULT
  4591. LineDial(
  4592. HCALL hCall,
  4593. LPCWSTR lpszDestAddress,
  4594. DWORD dwCountryCode
  4595. )
  4596. {
  4597. FUNC_ARGS funcArgs =
  4598. {
  4599. MAKELONG (LINE_FUNC | ASYNC | 3, lDial),
  4600. {
  4601. (ULONG_PTR) hCall,
  4602. (ULONG_PTR) lpszDestAddress,
  4603. dwCountryCode
  4604. },
  4605. {
  4606. Dword,
  4607. lpszW,
  4608. Dword
  4609. }
  4610. };
  4611. if ( IsBadStringPtrW(lpszDestAddress, (UINT)-1) )
  4612. {
  4613. LOG((TL_ERROR, "Bad lpszDestAddress in lineDial"));
  4614. return mapTAPIErrorCode( LINEERR_INVALPOINTER );
  4615. }
  4616. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineDial") );
  4617. }
  4618. LONG
  4619. LineDrop(
  4620. HCALL hCall,
  4621. LPCSTR lpsUserUserInfo,
  4622. DWORD dwSize
  4623. )
  4624. {
  4625. FUNC_ARGS funcArgs =
  4626. {
  4627. MAKELONG (LINE_FUNC | ASYNC | 3, lDrop),
  4628. {
  4629. (ULONG_PTR) hCall,
  4630. (ULONG_PTR) lpsUserUserInfo,
  4631. dwSize
  4632. },
  4633. {
  4634. Dword,
  4635. lpSet_SizeToFollow,
  4636. Size
  4637. }
  4638. };
  4639. if (!lpsUserUserInfo)
  4640. {
  4641. //
  4642. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4643. //
  4644. funcArgs.ArgTypes[1] = Dword;
  4645. funcArgs.Args[1] = TAPI_NO_DATA;
  4646. funcArgs.ArgTypes[2] = Dword;
  4647. }
  4648. return (DOFUNC (&funcArgs, "lineDrop"));
  4649. }
  4650. HRESULT
  4651. LineForward(
  4652. T3LINE * pt3Line,
  4653. DWORD dwAddressID,
  4654. LPLINEFORWARDLIST const lpForwardList,
  4655. DWORD dwNumRingsNoAnswer,
  4656. LPHCALL lphConsultCall
  4657. )
  4658. {
  4659. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)lphConsultCall);
  4660. FUNC_ARGS funcArgs =
  4661. {
  4662. MAKELONG (LINE_FUNC | ASYNC | 9, lForward),
  4663. {
  4664. GetFunctionIndex(lineMakeCallPostProcess),
  4665. (ULONG_PTR) pt3Line->hLine,
  4666. FALSE,
  4667. dwAddressID,
  4668. (ULONG_PTR) lpForwardList,
  4669. dwNumRingsNoAnswer,
  4670. hpCallHandle,
  4671. TAPI_NO_DATA,
  4672. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  4673. },
  4674. {
  4675. Dword,
  4676. Dword,
  4677. Dword,
  4678. Dword,
  4679. lpSet_Struct,
  4680. Dword,
  4681. Dword,
  4682. Dword,
  4683. Dword
  4684. }
  4685. };
  4686. if (!lpForwardList)
  4687. {
  4688. //
  4689. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4690. //
  4691. funcArgs.ArgTypes[4] = Dword;
  4692. funcArgs.Args[4] = TAPI_NO_DATA;
  4693. }
  4694. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineForwardW") );
  4695. if (FAILED(hr))
  4696. {
  4697. DeleteHandleTableEntry(hpCallHandle);
  4698. }
  4699. return hr;
  4700. }
  4701. void
  4702. PASCAL
  4703. lineGatherDigitsWPostProcess(
  4704. PASYNCEVENTMSG pMsg
  4705. )
  4706. {
  4707. LOG((TL_TRACE, "lineGatherDigitsWPostProcess: enter"));
  4708. LOG((TL_INFO,
  4709. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4710. pMsg->Param1,
  4711. pMsg->Param2,
  4712. pMsg->Param3,
  4713. pMsg->Param4
  4714. ));
  4715. if (pMsg->Param1 & (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
  4716. LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
  4717. {
  4718. LPSTR lpsDigits = (LPSTR) GetHandleTableEntry(pMsg->Param2);
  4719. //
  4720. // no longer need the handle table entry
  4721. //
  4722. DeleteHandleTableEntry(pMsg->Param2);
  4723. DWORD dwNumDigits = pMsg->Param4;
  4724. LPWSTR pBuffer = (LPWSTR) (((ULONG_PTR *)(pMsg + 1)) + 2);
  4725. __try
  4726. {
  4727. {
  4728. CopyMemory (lpsDigits, pBuffer, dwNumDigits * sizeof(WCHAR));
  4729. }
  4730. }
  4731. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4732. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4733. {
  4734. //
  4735. // Don't do anything if we GPF
  4736. //
  4737. LOG((TL_WARN,
  4738. "lineGatherDigitsWPostProcess: "
  4739. "failed to write %lx digits to memory [%p]",
  4740. dwNumDigits, lpsDigits));
  4741. }
  4742. }
  4743. pMsg->Param2 = pMsg->Param3 = 0;
  4744. }
  4745. HRESULT
  4746. LineGatherDigits(
  4747. HCALL hCall,
  4748. DWORD dwDigitModes,
  4749. LPWSTR lpsDigits,
  4750. DWORD dwNumDigits,
  4751. LPCWSTR lpszTerminationDigits,
  4752. DWORD dwFirstDigitTimeout,
  4753. DWORD dwInterDigitTimeout
  4754. )
  4755. {
  4756. //
  4757. // Note: we do the ptr check here rather than in DOFUNC because we're
  4758. // not passing any digits data within the context of this func
  4759. //
  4760. if (lpsDigits && TAPIIsBadWritePtr (lpsDigits, dwNumDigits * sizeof (WCHAR)))
  4761. {
  4762. return LINEERR_INVALPOINTER;
  4763. }
  4764. //
  4765. // this entry will be cleared in the callback (lineGatherDigitsWPostProcess)
  4766. //
  4767. DWORD hpOutputBuffer = CreateHandleTableEntry((ULONG_PTR)lpsDigits);
  4768. FUNC_ARGS funcArgs =
  4769. {
  4770. MAKELONG (LINE_FUNC | SYNC | 9, lGatherDigits),
  4771. {
  4772. GetFunctionIndex(lineGatherDigitsWPostProcess),
  4773. (ULONG_PTR) hCall,
  4774. (ULONG_PTR) 0, // this is the dwendtoendid for remotesp
  4775. dwDigitModes,
  4776. hpOutputBuffer,
  4777. dwNumDigits,
  4778. (ULONG_PTR) lpszTerminationDigits,
  4779. dwFirstDigitTimeout,
  4780. dwInterDigitTimeout
  4781. },
  4782. {
  4783. Dword,
  4784. Dword,
  4785. Dword,
  4786. Dword,
  4787. Dword,
  4788. Dword,
  4789. lpszW,
  4790. Dword,
  4791. Dword
  4792. }
  4793. };
  4794. if (lpszTerminationDigits == (LPCWSTR) NULL)
  4795. {
  4796. //
  4797. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4798. //
  4799. funcArgs.ArgTypes[6] = Dword;
  4800. funcArgs.Args[6] = TAPI_NO_DATA;
  4801. }
  4802. else
  4803. {
  4804. if ( IsBadStringPtrW(lpszTerminationDigits, (UINT)-1) )
  4805. {
  4806. DeleteHandleTableEntry(hpOutputBuffer);
  4807. hpOutputBuffer = 0;
  4808. LOG((TL_ERROR, "Bad lpszDestAddress in lineGatherDigitsW"));
  4809. return( LINEERR_INVALPOINTER );
  4810. }
  4811. }
  4812. LONG lResult = DOFUNC (&funcArgs, "lineGatherDigits");
  4813. if (lResult < 0)
  4814. {
  4815. DeleteHandleTableEntry(hpOutputBuffer);
  4816. hpOutputBuffer = 0;
  4817. }
  4818. return mapTAPIErrorCode(lResult);
  4819. }
  4820. HRESULT
  4821. LineGenerateDigits(
  4822. HCALL hCall,
  4823. DWORD dwDigitMode,
  4824. LPCWSTR lpszDigits,
  4825. DWORD dwDuration
  4826. )
  4827. {
  4828. FUNC_ARGS funcArgs =
  4829. {
  4830. MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
  4831. {
  4832. (ULONG_PTR) hCall,
  4833. dwDigitMode,
  4834. (ULONG_PTR) lpszDigits,
  4835. dwDuration,
  4836. 0 // dwEndToEndID, remotesp only
  4837. },
  4838. {
  4839. Dword,
  4840. Dword,
  4841. lpszW,
  4842. Dword,
  4843. Dword
  4844. }
  4845. };
  4846. if (!lpszDigits)
  4847. {
  4848. funcArgs.Args[2] = TAPI_NO_DATA;
  4849. funcArgs.ArgTypes[2] = Dword;
  4850. }
  4851. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGenerateDigits") );
  4852. }
  4853. HRESULT
  4854. LineGenerateTone(
  4855. HCALL hCall,
  4856. DWORD dwToneMode,
  4857. DWORD dwDuration,
  4858. DWORD dwNumTones,
  4859. LPLINEGENERATETONE const lpTones
  4860. )
  4861. {
  4862. FUNC_ARGS funcArgs =
  4863. {
  4864. MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
  4865. {
  4866. (ULONG_PTR) hCall,
  4867. dwToneMode,
  4868. dwDuration,
  4869. dwNumTones,
  4870. TAPI_NO_DATA, // (DWORD) lpTones,
  4871. 0, // dwNumTones * sizeof(LINEGENERATETONE)
  4872. 0 // dwEndToEndID, remotesp only
  4873. },
  4874. {
  4875. Dword,
  4876. Dword,
  4877. Dword,
  4878. Dword,
  4879. Dword, // lpSet_SizeToFollow,
  4880. Dword, // Size
  4881. Dword
  4882. }
  4883. };
  4884. if (dwToneMode == LINETONEMODE_CUSTOM)
  4885. {
  4886. //
  4887. // Set lpTones (& following Size arg) since in this case
  4888. // they are valid args
  4889. //
  4890. funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
  4891. funcArgs.Args[4] = (ULONG_PTR) lpTones;
  4892. funcArgs.ArgTypes[5] = Size;
  4893. funcArgs.Args[5] = dwNumTones * sizeof(LINEGENERATETONE);
  4894. }
  4895. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGenerateTone"));
  4896. }
  4897. HRESULT
  4898. LineGetCallHubTracking(
  4899. DWORD dwDeviceID,
  4900. LINECALLHUBTRACKINGINFO ** ppTrackingInfo
  4901. )
  4902. {
  4903. return E_NOTIMPL;
  4904. }
  4905. HRESULT
  4906. LineGetHubRelatedCalls(
  4907. HCALLHUB hCallHub,
  4908. HCALL hCall,
  4909. LINECALLLIST ** ppCallHubList
  4910. )
  4911. {
  4912. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD) * 20;
  4913. HRESULT hr;
  4914. *ppCallHubList = (LINECALLLIST *)ClientAlloc( dwSize );
  4915. if (NULL == *ppCallHubList)
  4916. {
  4917. return E_OUTOFMEMORY;
  4918. }
  4919. (*ppCallHubList)->dwTotalSize = dwSize;
  4920. FUNC_ARGS funcArgs =
  4921. {
  4922. MAKELONG (LINE_FUNC | SYNC | 3, lGetHubRelatedCalls),
  4923. {
  4924. (ULONG_PTR) hCallHub,
  4925. (ULONG_PTR) hCall,
  4926. (ULONG_PTR) *ppCallHubList
  4927. },
  4928. {
  4929. Dword,
  4930. Dword,
  4931. lpGet_Struct
  4932. }
  4933. };
  4934. while (TRUE)
  4935. {
  4936. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetHubRelatedCalls") );
  4937. if (!SUCCEEDED(hr))
  4938. {
  4939. ClientFree( *ppCallHubList );
  4940. *ppCallHubList = NULL;
  4941. return hr;
  4942. }
  4943. if ((*ppCallHubList)->dwNeededSize > (*ppCallHubList)->dwTotalSize)
  4944. {
  4945. dwSize = (*ppCallHubList)->dwNeededSize;
  4946. ClientFree( *ppCallHubList );
  4947. *ppCallHubList = (LINECALLLIST *)ClientAlloc( dwSize );
  4948. if (NULL == *ppCallHubList)
  4949. {
  4950. return E_OUTOFMEMORY;
  4951. }
  4952. (*ppCallHubList)->dwTotalSize = dwSize;
  4953. funcArgs.Args[2] = (ULONG_PTR) *ppCallHubList;
  4954. }
  4955. else
  4956. {
  4957. break;
  4958. }
  4959. }
  4960. return hr;
  4961. }
  4962. HRESULT
  4963. LineGetCallHub(
  4964. HCALL hCall,
  4965. HCALLHUB * pCallHub
  4966. )
  4967. {
  4968. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD);
  4969. HRESULT hr;
  4970. LINECALLLIST * pCallList;
  4971. pCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  4972. if (NULL == pCallList)
  4973. {
  4974. return E_OUTOFMEMORY;
  4975. }
  4976. pCallList->dwTotalSize = dwSize;
  4977. FUNC_ARGS funcArgs =
  4978. {
  4979. MAKELONG (LINE_FUNC | SYNC | 3, lGetHubRelatedCalls),
  4980. {
  4981. (ULONG_PTR) 0,
  4982. (ULONG_PTR) hCall,
  4983. (ULONG_PTR) pCallList
  4984. },
  4985. {
  4986. Dword,
  4987. Dword,
  4988. lpGet_Struct
  4989. }
  4990. };
  4991. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetHubRelatedCalls") );
  4992. if (SUCCEEDED(hr))
  4993. {
  4994. *pCallHub = *(LPHCALLHUB)(((LPBYTE)pCallList) + pCallList->dwCallsOffset);
  4995. }
  4996. ClientFree( pCallList );
  4997. return hr;
  4998. }
  4999. HRESULT
  5000. LineGetAddressCaps(
  5001. HLINEAPP hLineApp,
  5002. DWORD dwDeviceID,
  5003. DWORD dwAddressID,
  5004. DWORD dwAPIVersion,
  5005. LPLINEADDRESSCAPS * ppAddressCaps
  5006. )
  5007. {
  5008. LONG lResult;
  5009. FUNC_ARGS funcArgs =
  5010. {
  5011. MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
  5012. {
  5013. (ULONG_PTR) hLineApp,
  5014. dwDeviceID,
  5015. dwAddressID,
  5016. dwAPIVersion,
  5017. 0,
  5018. (ULONG_PTR) *ppAddressCaps
  5019. },
  5020. {
  5021. hXxxApp,
  5022. Dword,
  5023. Dword,
  5024. Dword,
  5025. Dword,
  5026. lpGet_Struct
  5027. }
  5028. };
  5029. while (TRUE)
  5030. {
  5031. lResult = DOFUNC (&funcArgs, "lineGetAddressCaps");
  5032. if ((0 == lResult) && ((*ppAddressCaps)->dwNeededSize > (*ppAddressCaps)->dwTotalSize))
  5033. {
  5034. DWORD dwSize;
  5035. dwSize = (*ppAddressCaps)->dwNeededSize;
  5036. ClientFree(*ppAddressCaps);
  5037. *ppAddressCaps = (LPLINEADDRESSCAPS) ClientAlloc( dwSize );
  5038. if (NULL == (*ppAddressCaps))
  5039. {
  5040. return E_OUTOFMEMORY;
  5041. }
  5042. (*ppAddressCaps)->dwTotalSize = dwSize;
  5043. funcArgs.Args[5] = (ULONG_PTR) *ppAddressCaps;
  5044. }
  5045. else
  5046. {
  5047. break;
  5048. }
  5049. }
  5050. return mapTAPIErrorCode( lResult );
  5051. }
  5052. LONG
  5053. WINAPI
  5054. lineGetAddressIDW(
  5055. HLINE hLine,
  5056. LPDWORD lpdwAddressID,
  5057. DWORD dwAddressMode,
  5058. LPCWSTR lpsAddress,
  5059. DWORD dwSize
  5060. )
  5061. {
  5062. FUNC_ARGS funcArgs =
  5063. {
  5064. MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
  5065. {
  5066. (ULONG_PTR) hLine,
  5067. (ULONG_PTR) lpdwAddressID,
  5068. dwAddressMode,
  5069. (ULONG_PTR) lpsAddress,
  5070. dwSize
  5071. },
  5072. {
  5073. Dword,
  5074. lpDword,
  5075. Dword,
  5076. lpSet_SizeToFollow,
  5077. Size
  5078. }
  5079. };
  5080. return (DOFUNC (&funcArgs, "lineGetAddressID"));
  5081. }
  5082. HRESULT
  5083. LineGetAddressStatus(
  5084. T3LINE * pt3Line,
  5085. DWORD dwAddressID,
  5086. LPLINEADDRESSSTATUS * ppAddressStatus
  5087. )
  5088. {
  5089. HRESULT hr;
  5090. DWORD dwSize;
  5091. dwSize = sizeof( LINEADDRESSSTATUS ) + 500;
  5092. *ppAddressStatus = (LINEADDRESSSTATUS *)ClientAlloc( dwSize );
  5093. if ( NULL == *ppAddressStatus )
  5094. {
  5095. LOG((TL_ERROR, "Alloc failed in LineGetAddressStatus"));
  5096. return E_OUTOFMEMORY;
  5097. }
  5098. (*ppAddressStatus)->dwTotalSize = dwSize;
  5099. FUNC_ARGS funcArgs =
  5100. {
  5101. MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
  5102. {
  5103. (ULONG_PTR) pt3Line->hLine,
  5104. dwAddressID,
  5105. (ULONG_PTR) *ppAddressStatus
  5106. },
  5107. {
  5108. Dword,
  5109. Dword,
  5110. lpGet_Struct
  5111. }
  5112. };
  5113. while (TRUE)
  5114. {
  5115. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetAddressStatus") );
  5116. if ( 0 != hr )
  5117. {
  5118. ClientFree( *ppAddressStatus );
  5119. *ppAddressStatus = NULL;
  5120. return hr;
  5121. }
  5122. if ((0 == hr) && ((*ppAddressStatus)->dwNeededSize > (*ppAddressStatus)->dwTotalSize))
  5123. {
  5124. dwSize = (*ppAddressStatus)->dwNeededSize;
  5125. ClientFree( *ppAddressStatus );
  5126. *ppAddressStatus = (LPLINEADDRESSSTATUS) ClientAlloc( dwSize );
  5127. if (NULL == *ppAddressStatus)
  5128. {
  5129. LOG((TL_ERROR, "Alloc failed 2 in LineGetAddressStatus"));
  5130. return E_OUTOFMEMORY;
  5131. }
  5132. (*ppAddressStatus)->dwTotalSize = dwSize;
  5133. funcArgs.Args[2] = (ULONG_PTR)*ppAddressStatus;
  5134. }
  5135. else
  5136. {
  5137. break;
  5138. }
  5139. }
  5140. return hr;
  5141. }
  5142. LONG
  5143. WINAPI
  5144. lineGetAgentActivityListW(
  5145. HLINE hLine,
  5146. DWORD dwAddressID,
  5147. LPLINEAGENTACTIVITYLIST lpAgentActivityList
  5148. )
  5149. {
  5150. DWORD hpAgentActivityList = CreateHandleTableEntry((ULONG_PTR)lpAgentActivityList);
  5151. FUNC_ARGS funcArgs =
  5152. {
  5153. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentActivityList),
  5154. {
  5155. GetFunctionIndex(lineDevSpecificPostProcess),
  5156. (ULONG_PTR) hLine,
  5157. (ULONG_PTR) dwAddressID,
  5158. (ULONG_PTR) hpAgentActivityList, // pass the actual ptr (for ppproc)
  5159. (ULONG_PTR) lpAgentActivityList // pass data
  5160. },
  5161. {
  5162. Dword,
  5163. Dword,
  5164. Dword,
  5165. Dword,
  5166. lpGet_Struct,
  5167. }
  5168. };
  5169. LONG lResult = DOFUNC (&funcArgs, "lineGetAgentActivityListW");
  5170. //
  5171. // if failed, or synchronous call, remove the handle table entry.
  5172. // otherwise the callback will do this.
  5173. //
  5174. if (lResult <= 0)
  5175. {
  5176. DeleteHandleTableEntry(hpAgentActivityList);
  5177. }
  5178. return lResult;
  5179. }
  5180. HRESULT
  5181. LineGetAgentCaps(
  5182. HLINEAPP hLineApp,
  5183. DWORD dwDeviceID,
  5184. DWORD dwAddressID,
  5185. DWORD dwAppAPIVersion,
  5186. LPLINEAGENTCAPS *ppAgentCaps
  5187. )
  5188. {
  5189. HRESULT hr = S_OK;
  5190. long lResult;
  5191. DWORD dwSize = sizeof(LINEAGENTCAPS) + 500;
  5192. *ppAgentCaps = (LPLINEAGENTCAPS) ClientAlloc( dwSize );
  5193. if (NULL == *ppAgentCaps)
  5194. {
  5195. return E_OUTOFMEMORY;
  5196. }
  5197. (*ppAgentCaps)->dwTotalSize = dwSize;
  5198. DWORD hpAgentCaps = CreateHandleTableEntry((ULONG_PTR)*ppAgentCaps);
  5199. FUNC_ARGS funcArgs =
  5200. {
  5201. MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
  5202. {
  5203. GetFunctionIndex(lineDevSpecificPostProcess),
  5204. (ULONG_PTR) hLineApp,
  5205. (ULONG_PTR) dwDeviceID,
  5206. (ULONG_PTR) dwAddressID,
  5207. (ULONG_PTR) dwAppAPIVersion,
  5208. hpAgentCaps, // pass the actual ptr (for ppproc)
  5209. (ULONG_PTR) *ppAgentCaps // pass data
  5210. },
  5211. {
  5212. Dword,
  5213. hXxxApp,
  5214. Dword,
  5215. Dword,
  5216. Dword,
  5217. Dword,
  5218. lpGet_Struct,
  5219. }
  5220. };
  5221. while (TRUE)
  5222. {
  5223. lResult = DOFUNC (&funcArgs, "LineGetAgentCaps");
  5224. if (lResult > 0) // async reply
  5225. {
  5226. hr = WaitForReply( lResult );
  5227. if ((hr == S_OK) )
  5228. {
  5229. if (((*ppAgentCaps)->dwNeededSize > (*ppAgentCaps)->dwTotalSize))
  5230. {
  5231. // didnt Work , adjust buffer size & try again
  5232. DeleteHandleTableEntry(hpAgentCaps);
  5233. hpAgentCaps = 0;
  5234. LOG((TL_INFO, "LineGetAgentCaps failed - buffer to small"));
  5235. dwSize = (*ppAgentCaps)->dwNeededSize;
  5236. ClientFree( *ppAgentCaps );
  5237. *ppAgentCaps = NULL;
  5238. *ppAgentCaps = (LPLINEAGENTCAPS) ClientAlloc( dwSize );
  5239. if (*ppAgentCaps == NULL)
  5240. {
  5241. LOG((TL_ERROR, "LineGetAgentCaps - repeat ClientAlloc failed"));
  5242. hr = E_OUTOFMEMORY;
  5243. break;
  5244. }
  5245. else
  5246. {
  5247. (*ppAgentCaps)->dwTotalSize = dwSize;
  5248. hpAgentCaps = CreateHandleTableEntry((ULONG_PTR)*ppAgentCaps);
  5249. funcArgs.Args[5] = hpAgentCaps;
  5250. funcArgs.Args[6] = (ULONG_PTR)*ppAgentCaps;
  5251. }
  5252. } // buffer too small
  5253. else
  5254. {
  5255. // WaitForReply succeeded and the buffer was big enough.
  5256. // break out of the loop
  5257. break;
  5258. }
  5259. } // waitforreply succeeded
  5260. else
  5261. {
  5262. // waitforreply failed. not likely to receive a callback.
  5263. // clear handle table entries.
  5264. LOG((TL_ERROR, "LineGetAgentCaps - WaitForReply failed"));
  5265. DeleteHandleTableEntry(hpAgentCaps);
  5266. hpAgentCaps = 0;
  5267. }
  5268. }
  5269. else // failed sync
  5270. {
  5271. LOG((TL_ERROR, "LineGetAgentCaps - failed sync"));
  5272. DeleteHandleTableEntry(hpAgentCaps);
  5273. hpAgentCaps = 0;
  5274. hr = mapTAPIErrorCode( lResult );
  5275. break;
  5276. }
  5277. } // end while(TRUE)
  5278. return hr;
  5279. }
  5280. LONG
  5281. WINAPI
  5282. lineGetAgentGroupListW(
  5283. HLINE hLine,
  5284. DWORD dwAddressID,
  5285. LPLINEAGENTGROUPLIST lpAgentGroupList
  5286. )
  5287. {
  5288. DWORD hpAgentGroupList = CreateHandleTableEntry((ULONG_PTR)lpAgentGroupList);
  5289. FUNC_ARGS funcArgs =
  5290. {
  5291. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
  5292. {
  5293. GetFunctionIndex(lineDevSpecificPostProcess),
  5294. (ULONG_PTR) hLine,
  5295. (ULONG_PTR) dwAddressID,
  5296. hpAgentGroupList, // pass the actual ptr (for ppproc)
  5297. (ULONG_PTR) lpAgentGroupList // pass data
  5298. },
  5299. {
  5300. Dword,
  5301. Dword,
  5302. Dword,
  5303. Dword,
  5304. lpGet_Struct,
  5305. }
  5306. };
  5307. LONG lResult = DOFUNC (&funcArgs, "lineGetAgentGroupListW");
  5308. //
  5309. // if failed, or synchronous call, remove the handle table entry.
  5310. // otherwise the callback will do this.
  5311. //
  5312. if (lResult <= 0)
  5313. {
  5314. DeleteHandleTableEntry(hpAgentGroupList);
  5315. }
  5316. return lResult;
  5317. }
  5318. LONG
  5319. WINAPI
  5320. lineGetAgentStatusW(
  5321. HLINE hLine,
  5322. DWORD dwAddressID,
  5323. LPLINEAGENTSTATUS lpAgentStatus
  5324. )
  5325. {
  5326. DWORD hpAgentStatus = CreateHandleTableEntry((ULONG_PTR)lpAgentStatus);
  5327. FUNC_ARGS funcArgs =
  5328. {
  5329. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
  5330. {
  5331. GetFunctionIndex(lineDevSpecificPostProcess),
  5332. (ULONG_PTR) hLine,
  5333. (ULONG_PTR) dwAddressID,
  5334. hpAgentStatus, // pass the actual ptr (for ppproc)
  5335. (ULONG_PTR) lpAgentStatus // pass data
  5336. },
  5337. {
  5338. Dword,
  5339. Dword,
  5340. Dword,
  5341. Dword,
  5342. lpGet_Struct,
  5343. }
  5344. };
  5345. LONG lResult = DOFUNC(&funcArgs, "lineGetAgentStatusW");
  5346. if (lResult <= 0)
  5347. {
  5348. DeleteHandleTableEntry(hpAgentStatus);
  5349. }
  5350. return lResult;
  5351. }
  5352. LONG
  5353. WINAPI
  5354. lineGetAppPriorityW(
  5355. LPCWSTR lpszAppName,
  5356. DWORD dwMediaMode,
  5357. LPLINEEXTENSIONID lpExtensionID,
  5358. DWORD dwRequestMode,
  5359. LPVARSTRING lpExtensionName,
  5360. LPDWORD lpdwPriority
  5361. )
  5362. {
  5363. FUNC_ARGS funcArgs =
  5364. {
  5365. MAKELONG (LINE_FUNC | SYNC | 7, lGetAppPriority),
  5366. {
  5367. (ULONG_PTR) lpszAppName,
  5368. dwMediaMode,
  5369. 0,
  5370. 0,
  5371. dwRequestMode,
  5372. 0,
  5373. (ULONG_PTR) lpdwPriority
  5374. },
  5375. {
  5376. lpszW, // app name
  5377. Dword, // media mode
  5378. Dword, // ext id (offset)
  5379. Dword, // ext id (size)
  5380. Dword, // request mode
  5381. Dword, // ext name total size
  5382. lpDword // lp pri
  5383. }
  5384. };
  5385. if (dwMediaMode & 0xff000000)
  5386. {
  5387. if ((LPVOID) lpExtensionName == (LPVOID) lpdwPriority)
  5388. {
  5389. return LINEERR_INVALPOINTER;
  5390. }
  5391. //
  5392. // We have to do some arg list munging here (adding an extra arg)
  5393. //
  5394. //
  5395. // Set lpExtensionID, the following Size arg,
  5396. // lpExtensionName, and the following MinSize
  5397. // Type's and Value appropriately since they're
  5398. // valid args in this case
  5399. //
  5400. funcArgs.ArgTypes[2] = lpSet_SizeToFollow;
  5401. funcArgs.Args[2] = (ULONG_PTR) lpExtensionID;
  5402. funcArgs.ArgTypes[3] = Size;
  5403. funcArgs.Args[3] = sizeof (LINEEXTENSIONID);
  5404. funcArgs.ArgTypes[5] = lpGet_Struct;
  5405. funcArgs.Args[5] = (ULONG_PTR) lpExtensionName;
  5406. }
  5407. if ( IsBadStringPtrW(lpszAppName, (UINT)-1) )
  5408. {
  5409. LOG((TL_ERROR, "Bad lpszDestAddress in lineGetAppPriorityW"));
  5410. return( LINEERR_INVALPOINTER );
  5411. }
  5412. return (DOFUNC (&funcArgs, "lineGetAppPriority"));
  5413. }
  5414. HRESULT
  5415. LineGetCallIDs(
  5416. HCALL hCall,
  5417. LPDWORD lpdwAddressID,
  5418. LPDWORD lpdwCallID,
  5419. LPDWORD lpdwRelatedCallID
  5420. )
  5421. {
  5422. FUNC_ARGS funcArgs =
  5423. {
  5424. MAKELONG (LINE_FUNC | SYNC | 4, lGetCallIDs),
  5425. {
  5426. (ULONG_PTR) hCall,
  5427. (ULONG_PTR) lpdwAddressID,
  5428. (ULONG_PTR) lpdwCallID,
  5429. (ULONG_PTR) lpdwRelatedCallID
  5430. },
  5431. {
  5432. Dword,
  5433. lpDword,
  5434. lpDword,
  5435. lpDword
  5436. }
  5437. };
  5438. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallIDs"));
  5439. }
  5440. HRESULT
  5441. LineGetCallInfo(
  5442. HCALL hCall,
  5443. LPLINECALLINFO * ppCallInfo
  5444. )
  5445. {
  5446. if ( NULL == hCall )
  5447. {
  5448. LOG((TL_WARN, "LineGetCallInfo: NULL hCall"));
  5449. *ppCallInfo = NULL;
  5450. return TAPI_E_INVALCALLSTATE;
  5451. }
  5452. *ppCallInfo = (LPLINECALLINFO) ClientAlloc( sizeof(LINECALLINFO) + 500 );
  5453. if (NULL == *ppCallInfo)
  5454. {
  5455. return E_OUTOFMEMORY;
  5456. }
  5457. (*ppCallInfo)->dwTotalSize = sizeof(LINECALLINFO) + 500;
  5458. FUNC_ARGS funcArgs =
  5459. {
  5460. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
  5461. {
  5462. (ULONG_PTR) hCall,
  5463. (ULONG_PTR) *ppCallInfo
  5464. },
  5465. {
  5466. Dword,
  5467. lpGet_Struct
  5468. }
  5469. };
  5470. HRESULT hr = E_FAIL;
  5471. while (TRUE)
  5472. {
  5473. hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallInfo"));
  5474. //
  5475. // if we fail, free alloc
  5476. //
  5477. if ( FAILED(hr) )
  5478. {
  5479. ClientFree( *ppCallInfo );
  5480. *ppCallInfo = NULL;
  5481. return hr;
  5482. }
  5483. //
  5484. // do we need to realloc?
  5485. //
  5486. if ((*ppCallInfo)->dwNeededSize > (*ppCallInfo)->dwTotalSize)
  5487. {
  5488. DWORD dwSize = (*ppCallInfo)->dwNeededSize;
  5489. ClientFree( *ppCallInfo );
  5490. *ppCallInfo = (LPLINECALLINFO) ClientAlloc( dwSize );
  5491. if (NULL == *ppCallInfo)
  5492. {
  5493. // return LINEERR_NOMEM;
  5494. return E_OUTOFMEMORY;
  5495. }
  5496. (*ppCallInfo)->dwTotalSize = dwSize;
  5497. funcArgs.Args[1] = (ULONG_PTR)*ppCallInfo;
  5498. }
  5499. else
  5500. {
  5501. break;
  5502. }
  5503. }
  5504. return hr;
  5505. }
  5506. HRESULT
  5507. LineGetCallStatus(
  5508. HCALL hCall,
  5509. LPLINECALLSTATUS * ppCallStatus
  5510. )
  5511. {
  5512. *ppCallStatus = (LPLINECALLSTATUS) ClientAlloc( sizeof(LINECALLSTATUS) + 500 );
  5513. if (NULL == *ppCallStatus)
  5514. {
  5515. return E_OUTOFMEMORY;
  5516. }
  5517. (*ppCallStatus)->dwTotalSize = sizeof(LINECALLSTATUS) + 500;
  5518. FUNC_ARGS funcArgs =
  5519. {
  5520. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
  5521. {
  5522. (ULONG_PTR) hCall,
  5523. (ULONG_PTR) *ppCallStatus
  5524. },
  5525. {
  5526. Dword,
  5527. lpGet_Struct
  5528. }
  5529. };
  5530. HRESULT hr = E_FAIL;
  5531. while (TRUE)
  5532. {
  5533. hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallStatus"));
  5534. //
  5535. // if we fail, free alloc
  5536. //
  5537. if ( FAILED(hr) )
  5538. {
  5539. ClientFree( *ppCallStatus );
  5540. *ppCallStatus = NULL;
  5541. return hr;
  5542. }
  5543. //
  5544. // do we need to realloc?
  5545. //
  5546. if ((*ppCallStatus)->dwNeededSize > (*ppCallStatus)->dwTotalSize)
  5547. {
  5548. DWORD dwSize = (*ppCallStatus)->dwNeededSize;
  5549. ClientFree( *ppCallStatus );
  5550. *ppCallStatus = (LPLINECALLSTATUS) ClientAlloc( dwSize );
  5551. if (NULL == *ppCallStatus)
  5552. {
  5553. return mapTAPIErrorCode( LINEERR_NOMEM );
  5554. }
  5555. (*ppCallStatus)->dwTotalSize = dwSize;
  5556. funcArgs.Args[1] = (ULONG_PTR)*ppCallStatus;
  5557. }
  5558. else
  5559. {
  5560. break;
  5561. }
  5562. }
  5563. return hr;
  5564. }
  5565. HRESULT
  5566. LineGetConfRelatedCalls(
  5567. HCALL hCall,
  5568. LINECALLLIST ** ppCallList
  5569. )
  5570. {
  5571. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD) * 20;
  5572. LONG lResult;
  5573. HRESULT hr;
  5574. *ppCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  5575. if (NULL == *ppCallList)
  5576. {
  5577. return E_OUTOFMEMORY;
  5578. }
  5579. (*ppCallList)->dwTotalSize = dwSize;
  5580. FUNC_ARGS funcArgs =
  5581. {
  5582. MAKELONG (LINE_FUNC | SYNC| 2, lGetConfRelatedCalls),
  5583. {
  5584. (ULONG_PTR) hCall,
  5585. (ULONG_PTR) *ppCallList
  5586. },
  5587. {
  5588. Dword,
  5589. lpGet_Struct
  5590. }
  5591. };
  5592. while (TRUE)
  5593. {
  5594. lResult = DOFUNC (&funcArgs, "lineGetConfRelatedCalls") ;
  5595. if ( (0 == lResult) && ((*ppCallList)->dwNeededSize > (*ppCallList)->dwTotalSize) )
  5596. {
  5597. dwSize = (*ppCallList)->dwNeededSize;
  5598. ClientFree( *ppCallList );
  5599. *ppCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  5600. if (NULL == *ppCallList)
  5601. {
  5602. hr = E_OUTOFMEMORY;
  5603. break;
  5604. }
  5605. (*ppCallList)->dwTotalSize = dwSize;
  5606. funcArgs.Args[1] = (ULONG_PTR) *ppCallList;
  5607. }
  5608. else
  5609. {
  5610. hr = mapTAPIErrorCode( lResult );
  5611. break;
  5612. }
  5613. }
  5614. return hr;
  5615. }
  5616. LONG
  5617. WINAPI
  5618. lineGetCountryW(
  5619. DWORD dwCountryID,
  5620. DWORD dwAPIVersion,
  5621. LPLINECOUNTRYLIST lpLineCountryList
  5622. )
  5623. {
  5624. FUNC_ARGS funcArgs =
  5625. {
  5626. MAKELONG (LINE_FUNC | SYNC | 4, lGetCountry),
  5627. {
  5628. dwCountryID,
  5629. dwAPIVersion,
  5630. 0,
  5631. (ULONG_PTR) lpLineCountryList
  5632. },
  5633. {
  5634. Dword,
  5635. Dword,
  5636. Dword,
  5637. lpGet_Struct
  5638. }
  5639. };
  5640. if (
  5641. ( TAPI_CURRENT_VERSION != dwAPIVersion )
  5642. &&
  5643. ( 0x00020000 != dwAPIVersion )
  5644. &&
  5645. ( 0x00010004 != dwAPIVersion )
  5646. &&
  5647. ( 0x00010003 != dwAPIVersion )
  5648. )
  5649. {
  5650. LOG((TL_ERROR, "lineGetCountryW - bad API version 0x%08lx", dwAPIVersion));
  5651. return LINEERR_INCOMPATIBLEAPIVERSION;
  5652. }
  5653. return (DOFUNC (&funcArgs, "lineGetCountry"));
  5654. }
  5655. HRESULT
  5656. LineGetDevCapsWithAlloc(
  5657. HLINEAPP hLineApp,
  5658. DWORD dwDeviceID,
  5659. DWORD dwAPIVersion,
  5660. LPLINEDEVCAPS * ppLineDevCaps
  5661. )
  5662. {
  5663. LONG lResult;
  5664. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( sizeof(LINEDEVCAPS) + 500 );
  5665. if (NULL == *ppLineDevCaps)
  5666. {
  5667. return E_OUTOFMEMORY;
  5668. }
  5669. (*ppLineDevCaps)->dwTotalSize = sizeof(LINEDEVCAPS) + 500;
  5670. FUNC_ARGS funcArgs =
  5671. {
  5672. MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
  5673. {
  5674. (ULONG_PTR) hLineApp,
  5675. dwDeviceID,
  5676. dwAPIVersion,
  5677. 0,
  5678. (ULONG_PTR) *ppLineDevCaps
  5679. },
  5680. {
  5681. hXxxApp,
  5682. Dword,
  5683. Dword,
  5684. Dword,
  5685. lpGet_Struct
  5686. }
  5687. };
  5688. while (TRUE)
  5689. {
  5690. lResult = DOFUNC (&funcArgs, "lineGetDevCaps");
  5691. if ((0 == lResult) && ((*ppLineDevCaps)->dwNeededSize > (*ppLineDevCaps)->dwTotalSize))
  5692. {
  5693. DWORD dwSize = (*ppLineDevCaps)->dwNeededSize;
  5694. ClientFree( *ppLineDevCaps );
  5695. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( dwSize );
  5696. if (NULL == *ppLineDevCaps)
  5697. {
  5698. // return LINEERR_NOMEM;
  5699. return E_OUTOFMEMORY;
  5700. }
  5701. (*ppLineDevCaps)->dwTotalSize = dwSize;
  5702. funcArgs.Args[4] = (ULONG_PTR)*ppLineDevCaps;
  5703. }
  5704. else
  5705. {
  5706. break;
  5707. }
  5708. }
  5709. return mapTAPIErrorCode( lResult );
  5710. }
  5711. HRESULT
  5712. LineGetDevCaps(
  5713. HLINEAPP hLineApp,
  5714. DWORD dwDeviceID,
  5715. DWORD dwAPIVersion,
  5716. LPLINEDEVCAPS * ppLineDevCaps
  5717. )
  5718. {
  5719. LONG lResult;
  5720. FUNC_ARGS funcArgs =
  5721. {
  5722. MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
  5723. {
  5724. (ULONG_PTR) hLineApp,
  5725. dwDeviceID,
  5726. dwAPIVersion,
  5727. 0,
  5728. (ULONG_PTR) *ppLineDevCaps
  5729. },
  5730. {
  5731. hXxxApp,
  5732. Dword,
  5733. Dword,
  5734. Dword,
  5735. lpGet_Struct
  5736. }
  5737. };
  5738. while (TRUE)
  5739. {
  5740. lResult = DOFUNC (&funcArgs, "lineGetDevCaps");
  5741. if ((0 == lResult) && ((*ppLineDevCaps)->dwNeededSize > (*ppLineDevCaps)->dwTotalSize))
  5742. {
  5743. DWORD dwSize = (*ppLineDevCaps)->dwNeededSize;
  5744. ClientFree( *ppLineDevCaps );
  5745. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( dwSize );
  5746. if (NULL == *ppLineDevCaps)
  5747. {
  5748. // return LINEERR_NOMEM;
  5749. return E_OUTOFMEMORY;
  5750. }
  5751. (*ppLineDevCaps)->dwTotalSize = dwSize;
  5752. funcArgs.Args[4] = (ULONG_PTR)*ppLineDevCaps;
  5753. }
  5754. else
  5755. {
  5756. break;
  5757. }
  5758. }
  5759. return mapTAPIErrorCode( lResult );
  5760. }
  5761. HRESULT
  5762. LineGetDevConfig(
  5763. DWORD dwDeviceID,
  5764. LPVARSTRING * ppDeviceConfig,
  5765. LPCWSTR lpszDeviceClass
  5766. )
  5767. {
  5768. LONG lResult;
  5769. DWORD dwSize = sizeof (VARSTRING) + 500;
  5770. *ppDeviceConfig = (LPVARSTRING) ClientAlloc( dwSize );
  5771. if (NULL == *ppDeviceConfig)
  5772. {
  5773. return E_OUTOFMEMORY;
  5774. }
  5775. (*ppDeviceConfig)->dwTotalSize = dwSize;
  5776. FUNC_ARGS funcArgs =
  5777. {
  5778. MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
  5779. {
  5780. dwDeviceID,
  5781. (ULONG_PTR) *ppDeviceConfig,
  5782. (ULONG_PTR) lpszDeviceClass
  5783. },
  5784. {
  5785. Dword,
  5786. lpGet_Struct,
  5787. lpszW
  5788. }
  5789. };
  5790. while ( TRUE )
  5791. {
  5792. lResult = DOFUNC (&funcArgs, "lineGetDevConfig");
  5793. if ((lResult == 0) && ((*ppDeviceConfig)->dwNeededSize > (*ppDeviceConfig)->dwTotalSize))
  5794. {
  5795. dwSize = (*ppDeviceConfig)->dwNeededSize;
  5796. ClientFree(*ppDeviceConfig);
  5797. *ppDeviceConfig = (LPVARSTRING)ClientAlloc(dwSize);
  5798. if (NULL == *ppDeviceConfig)
  5799. {
  5800. LOG((TL_ERROR, "LineGetDevConfig exit - return E_OUTOFMEMORY"));
  5801. return E_OUTOFMEMORY;
  5802. }
  5803. (*ppDeviceConfig)->dwTotalSize = dwSize;
  5804. funcArgs.Args[1] = (ULONG_PTR)*ppDeviceConfig;
  5805. }
  5806. else
  5807. {
  5808. break;
  5809. }
  5810. }
  5811. LOG((TL_TRACE, "LineGetDevConfig exit - return %lx", lResult));
  5812. return mapTAPIErrorCode( lResult );
  5813. }
  5814. LONG
  5815. WINAPI
  5816. lineGetIconW(
  5817. DWORD dwDeviceID,
  5818. LPCWSTR lpszDeviceClass,
  5819. LPHICON lphIcon
  5820. )
  5821. {
  5822. HICON hIcon;
  5823. LONG lResult;
  5824. FUNC_ARGS funcArgs =
  5825. {
  5826. MAKELONG (LINE_FUNC | SYNC | 3, lGetIcon),
  5827. {
  5828. dwDeviceID,
  5829. (ULONG_PTR) lpszDeviceClass,
  5830. (ULONG_PTR) &hIcon
  5831. },
  5832. {
  5833. Dword,
  5834. lpszW,
  5835. lpDword
  5836. }
  5837. };
  5838. if (IsBadDwordPtr ((LPDWORD) lphIcon))
  5839. {
  5840. LOG((TL_ERROR, "lphIcon is an invalid pointer!"));
  5841. return LINEERR_INVALPOINTER;
  5842. }
  5843. if (lpszDeviceClass == (LPCWSTR) NULL)
  5844. {
  5845. //
  5846. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  5847. //
  5848. funcArgs.ArgTypes[1] = Dword;
  5849. funcArgs.Args[1] = TAPI_NO_DATA;
  5850. }
  5851. if ((lResult = DOFUNC (&funcArgs, "lineGetIcon")) == 0)
  5852. {
  5853. *lphIcon = hIcon;
  5854. }
  5855. return lResult;
  5856. }
  5857. HRESULT
  5858. LineGetID(
  5859. HLINE hLine,
  5860. DWORD dwID,
  5861. HCALL hCall,
  5862. DWORD dwSelect,
  5863. LPVARSTRING * ppDeviceID,
  5864. LPCWSTR lpszDeviceClass
  5865. )
  5866. {
  5867. LONG lResult;
  5868. DWORD dwNumDevices;
  5869. DWORD dwDeviceId1, dwDeviceId2;
  5870. BOOL bWaveDevice = FALSE;
  5871. *ppDeviceID = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  5872. if (NULL == *ppDeviceID)
  5873. {
  5874. return E_OUTOFMEMORY;
  5875. }
  5876. (*ppDeviceID)->dwTotalSize = sizeof (VARSTRING) + 500;
  5877. FUNC_ARGS funcArgs =
  5878. {
  5879. MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
  5880. {
  5881. (ULONG_PTR) hLine,
  5882. dwID,
  5883. (ULONG_PTR) hCall,
  5884. dwSelect,
  5885. (ULONG_PTR) *ppDeviceID,
  5886. (ULONG_PTR) lpszDeviceClass
  5887. },
  5888. {
  5889. Dword,
  5890. Dword,
  5891. Dword,
  5892. Dword,
  5893. lpGet_Struct,
  5894. lpszW
  5895. }
  5896. };
  5897. LOG((TL_TRACE, "LineGetID - enter"));
  5898. LOG((TL_INFO, " hLine --------->%lx", hLine));
  5899. LOG((TL_INFO, " hCall ----------->%lx", hCall));
  5900. LOG((TL_INFO, " dwSelect -------->%lx", dwSelect));
  5901. LOG((TL_INFO, " ppDeviceID ------>%p", ppDeviceID));
  5902. LOG((TL_INFO, " lpszDeviceClass ->%p", lpszDeviceClass));
  5903. //
  5904. // If the request is for a wave device, call LGetIDEx.
  5905. // This will return a device string ID which is guaranteed to be unique across
  5906. // all processes.
  5907. // Then we will convert the string ID to the correct device ID in the client process context.
  5908. //
  5909. if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
  5910. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  5911. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  5912. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  5913. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  5914. )
  5915. {
  5916. bWaveDevice = TRUE;
  5917. dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
  5918. funcArgs.Flags = MAKELONG (LINE_FUNC | SYNC | 6, lGetIDEx);
  5919. }
  5920. while ( TRUE )
  5921. {
  5922. lResult = DOFUNC (&funcArgs, bWaveDevice ? "lineGetIDEx" : "lineGetID");
  5923. if ((lResult == 0) && ((*ppDeviceID)->dwNeededSize > (*ppDeviceID)->dwTotalSize))
  5924. {
  5925. DWORD dwSize = (*ppDeviceID)->dwNeededSize;
  5926. ClientFree(*ppDeviceID);
  5927. *ppDeviceID = (LPVARSTRING)ClientAlloc(dwSize);
  5928. if (NULL == *ppDeviceID)
  5929. {
  5930. LOG((TL_ERROR, "LineGetID exit - return LINEERR_NOMEM"));
  5931. // return LINEERR_NOMEM;
  5932. return E_OUTOFMEMORY;
  5933. }
  5934. (*ppDeviceID)->dwTotalSize = dwSize;
  5935. funcArgs.Args[4] = (ULONG_PTR)*ppDeviceID;
  5936. }
  5937. else
  5938. {
  5939. if (lResult != 0)
  5940. {
  5941. ClientFree (*ppDeviceID);
  5942. *ppDeviceID = NULL;
  5943. }
  5944. break;
  5945. }
  5946. }
  5947. if (bWaveDevice && lResult == 0)
  5948. {
  5949. //
  5950. // We got the string ID(s), now we need to convert them to numeric device ID(s)
  5951. //
  5952. BOOL bConversionOk;
  5953. if ( dwNumDevices == 1 )
  5954. {
  5955. bConversionOk = WaveStringIdToDeviceId (
  5956. (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset),
  5957. lpszDeviceClass,
  5958. &dwDeviceId1);
  5959. }
  5960. else
  5961. {
  5962. _ASSERTE(dwNumDevices == 2);
  5963. //
  5964. // for "wave/in/out", we get back two devices from tapisrv -> convert both
  5965. //
  5966. LPWSTR szString1 = (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset);
  5967. // first convert the wave/in device
  5968. bConversionOk = WaveStringIdToDeviceId (
  5969. szString1,
  5970. L"wave/in",
  5971. &dwDeviceId1);
  5972. // next convert the wave/out device
  5973. bConversionOk = bConversionOk && WaveStringIdToDeviceId (
  5974. szString1 + wcslen(szString1),
  5975. L"wave/out",
  5976. &dwDeviceId2);
  5977. }
  5978. if (!bConversionOk)
  5979. {
  5980. LOG((TL_ERROR, "LineGetID - WaveStringIdToDeviceId failed"));
  5981. ClientFree(*ppDeviceID);
  5982. *ppDeviceID = NULL;
  5983. lResult = LINEERR_OPERATIONFAILED;
  5984. }
  5985. else
  5986. {
  5987. //
  5988. // conversion succeeded, now fill the VARSTRING to be returned to the caller
  5989. //
  5990. (*ppDeviceID)->dwNeededSize = (*ppDeviceID)->dwUsedSize =
  5991. sizeof(VARSTRING) + sizeof(DWORD) * dwNumDevices;
  5992. (*ppDeviceID)->dwStringFormat = STRINGFORMAT_BINARY;
  5993. (*ppDeviceID)->dwStringSize = sizeof(DWORD) * dwNumDevices;
  5994. (*ppDeviceID)->dwStringOffset = sizeof(VARSTRING);
  5995. *(DWORD *)((*ppDeviceID) + 1) = dwDeviceId1;
  5996. if (dwNumDevices == 2)
  5997. *((DWORD *)((*ppDeviceID) + 1) + 1) = dwDeviceId2;
  5998. }
  5999. }
  6000. LOG((TL_TRACE, "LineGetID exit - return %lx", lResult));
  6001. return mapTAPIErrorCode( lResult );
  6002. }
  6003. HRESULT
  6004. LineGetLineDevStatus(
  6005. HLINE hLine,
  6006. LPLINEDEVSTATUS * ppDevStatus
  6007. )
  6008. {
  6009. HRESULT hr;
  6010. DWORD dwSize = sizeof(LINEDEVSTATUS) + 500;
  6011. *ppDevStatus = ( LPLINEDEVSTATUS ) ClientAlloc( dwSize );
  6012. if ( NULL == *ppDevStatus )
  6013. {
  6014. LOG((TL_ERROR, "LineGetLineDevStatus - alloc failed"));
  6015. return E_OUTOFMEMORY;
  6016. }
  6017. (*ppDevStatus)->dwTotalSize = dwSize;
  6018. FUNC_ARGS funcArgs =
  6019. {
  6020. MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
  6021. {
  6022. (ULONG_PTR) hLine,
  6023. (ULONG_PTR) *ppDevStatus
  6024. },
  6025. {
  6026. Dword,
  6027. lpGet_Struct
  6028. }
  6029. };
  6030. while (TRUE)
  6031. {
  6032. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetLineDevStatus") );
  6033. if ( 0 != hr )
  6034. {
  6035. ClientFree( *ppDevStatus );
  6036. *ppDevStatus = NULL;
  6037. return hr;
  6038. }
  6039. if ((0 == hr) && ((*ppDevStatus)->dwNeededSize > (*ppDevStatus)->dwTotalSize))
  6040. {
  6041. dwSize = (*ppDevStatus)->dwNeededSize;
  6042. ClientFree( *ppDevStatus );
  6043. *ppDevStatus = (LPLINEDEVSTATUS) ClientAlloc( dwSize );
  6044. if (NULL == *ppDevStatus)
  6045. {
  6046. return E_OUTOFMEMORY;
  6047. }
  6048. (*ppDevStatus)->dwTotalSize = dwSize;
  6049. funcArgs.Args[1] = (ULONG_PTR)*ppDevStatus;
  6050. }
  6051. else
  6052. {
  6053. break;
  6054. }
  6055. }
  6056. return hr;
  6057. }
  6058. HRESULT
  6059. LineGetProxyStatus(
  6060. HLINEAPP hLineApp,
  6061. DWORD dwDeviceID,
  6062. DWORD dwAppAPIVersion,
  6063. LPLINEPROXYREQUESTLIST * ppLineProxyReqestList
  6064. )
  6065. {
  6066. HRESULT hr;
  6067. DWORD dwSize = sizeof(LINEPROXYREQUESTLIST) + 100;
  6068. *ppLineProxyReqestList = ( LPLINEPROXYREQUESTLIST ) ClientAlloc( dwSize );
  6069. if ( NULL == *ppLineProxyReqestList )
  6070. {
  6071. LOG((TL_ERROR, "LineGetProxyStatus - alloc failed"));
  6072. return E_OUTOFMEMORY;
  6073. }
  6074. (*ppLineProxyReqestList)->dwTotalSize = dwSize;
  6075. FUNC_ARGS funcArgs =
  6076. {
  6077. MAKELONG (LINE_FUNC | SYNC | 4, lGetProxyStatus),
  6078. {
  6079. (ULONG_PTR)hLineApp,
  6080. dwDeviceID,
  6081. dwAppAPIVersion,
  6082. (ULONG_PTR) *ppLineProxyReqestList
  6083. },
  6084. {
  6085. hXxxApp,
  6086. Dword,
  6087. Dword,
  6088. lpGet_Struct
  6089. }
  6090. };
  6091. while (TRUE)
  6092. {
  6093. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetProxyStatus") );
  6094. if ( FAILED(hr) )
  6095. {
  6096. ClientFree( *ppLineProxyReqestList );
  6097. *ppLineProxyReqestList = NULL;
  6098. return hr;
  6099. }
  6100. //
  6101. // succeeded, but need a bigger buffer?
  6102. //
  6103. if ( (*ppLineProxyReqestList)->dwNeededSize > (*ppLineProxyReqestList)->dwTotalSize )
  6104. {
  6105. dwSize = (*ppLineProxyReqestList)->dwNeededSize;
  6106. ClientFree( *ppLineProxyReqestList );
  6107. *ppLineProxyReqestList = (LPLINEPROXYREQUESTLIST) ClientAlloc( dwSize );
  6108. if (NULL == *ppLineProxyReqestList)
  6109. {
  6110. return E_OUTOFMEMORY;
  6111. }
  6112. (*ppLineProxyReqestList)->dwTotalSize = dwSize;
  6113. funcArgs.Args[3] = (ULONG_PTR)*ppLineProxyReqestList;
  6114. }
  6115. else
  6116. {
  6117. //
  6118. // plain success
  6119. //
  6120. break;
  6121. }
  6122. }
  6123. return hr;
  6124. }
  6125. LONG
  6126. WINAPI
  6127. lineGetNewCalls(
  6128. HLINE hLine,
  6129. DWORD dwAddressID,
  6130. DWORD dwSelect,
  6131. LPLINECALLLIST lpCallList
  6132. )
  6133. {
  6134. FUNC_ARGS funcArgs =
  6135. {
  6136. MAKELONG (LINE_FUNC | SYNC | 4, lGetNewCalls),
  6137. {
  6138. (ULONG_PTR) hLine,
  6139. dwAddressID,
  6140. dwSelect,
  6141. (ULONG_PTR) lpCallList
  6142. },
  6143. {
  6144. Dword,
  6145. Dword,
  6146. Dword,
  6147. lpGet_Struct
  6148. }
  6149. };
  6150. return (DOFUNC (&funcArgs, "lineGetNewCalls"));
  6151. }
  6152. LONG
  6153. WINAPI
  6154. lineGetNumRings(
  6155. HLINE hLine,
  6156. DWORD dwAddressID,
  6157. LPDWORD lpdwNumRings
  6158. )
  6159. {
  6160. FUNC_ARGS funcArgs =
  6161. {
  6162. MAKELONG (LINE_FUNC | SYNC | 3, lGetNumRings),
  6163. {
  6164. (ULONG_PTR) hLine,
  6165. dwAddressID,
  6166. (ULONG_PTR) lpdwNumRings
  6167. },
  6168. {
  6169. Dword,
  6170. Dword,
  6171. lpDword
  6172. }
  6173. };
  6174. return (DOFUNC (&funcArgs, "lineGetNumRings"));
  6175. }
  6176. HRESULT
  6177. LineGetProviderList(
  6178. LPLINEPROVIDERLIST * ppProviderList
  6179. )
  6180. {
  6181. LONG lResult;
  6182. *ppProviderList = (LPLINEPROVIDERLIST) ClientAlloc( sizeof (LINEPROVIDERLIST) +
  6183. 5*sizeof(LINEPROVIDERENTRY));
  6184. if (NULL == *ppProviderList)
  6185. {
  6186. return E_OUTOFMEMORY;
  6187. }
  6188. (*ppProviderList)->dwTotalSize = sizeof(LINEPROVIDERLIST) + 5*sizeof(LINEPROVIDERENTRY);
  6189. FUNC_ARGS funcArgs =
  6190. {
  6191. MAKELONG (LINE_FUNC | SYNC | 2, lGetProviderList),
  6192. {
  6193. TAPI_CURRENT_VERSION,
  6194. (ULONG_PTR) *ppProviderList
  6195. },
  6196. {
  6197. Dword,
  6198. lpGet_Struct
  6199. }
  6200. };
  6201. while (TRUE)
  6202. {
  6203. lResult = DOFUNC (&funcArgs, "lineGetProviderList");
  6204. if ((0 == lResult) && ((*ppProviderList)->dwNeededSize > (*ppProviderList)->dwTotalSize))
  6205. {
  6206. DWORD dwSize;
  6207. dwSize = (*ppProviderList)->dwNeededSize;
  6208. ClientFree(*ppProviderList);
  6209. *ppProviderList = (LPLINEPROVIDERLIST) ClientAlloc( dwSize );
  6210. if (NULL == (*ppProviderList))
  6211. {
  6212. return E_OUTOFMEMORY;
  6213. }
  6214. (*ppProviderList)->dwTotalSize = dwSize;
  6215. funcArgs.Args[1] = (ULONG_PTR) *ppProviderList;
  6216. }
  6217. else if ( 0 != lResult )
  6218. {
  6219. ClientFree( *ppProviderList );
  6220. *ppProviderList = NULL;
  6221. break;
  6222. }
  6223. else
  6224. {
  6225. break;
  6226. }
  6227. }
  6228. return mapTAPIErrorCode( lResult );
  6229. }
  6230. HRESULT
  6231. LineGetRequest(
  6232. HLINEAPP hLineApp,
  6233. DWORD dwRequestMode,
  6234. LPLINEREQMAKECALLW * ppReqMakeCall
  6235. )
  6236. {
  6237. *ppReqMakeCall = (LPLINEREQMAKECALLW)ClientAlloc( sizeof(LINEREQMAKECALLW) );
  6238. if ( NULL == *ppReqMakeCall )
  6239. {
  6240. return E_OUTOFMEMORY;
  6241. }
  6242. FUNC_ARGS funcArgs =
  6243. {
  6244. MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
  6245. {
  6246. (ULONG_PTR) hLineApp,
  6247. dwRequestMode,
  6248. (ULONG_PTR) *ppReqMakeCall,
  6249. 0
  6250. },
  6251. {
  6252. hXxxApp,
  6253. Dword,
  6254. lpGet_SizeToFollow,
  6255. Size
  6256. }
  6257. };
  6258. if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
  6259. {
  6260. //
  6261. // Set the size param appropriately
  6262. //
  6263. funcArgs.Args[3] = sizeof(LINEREQMAKECALLW);
  6264. }
  6265. else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
  6266. {
  6267. //
  6268. // Set the size param appropriately
  6269. //
  6270. funcArgs.Args[3] = sizeof(LINEREQMEDIACALLW);
  6271. }
  6272. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetRequest"));
  6273. }
  6274. LONG
  6275. WINAPI
  6276. lineGetStatusMessages(
  6277. HLINE hLine,
  6278. LPDWORD lpdwLineStates,
  6279. LPDWORD lpdwAddressStates
  6280. )
  6281. {
  6282. FUNC_ARGS funcArgs =
  6283. {
  6284. MAKELONG (LINE_FUNC | SYNC | 3, lGetStatusMessages),
  6285. {
  6286. (ULONG_PTR) hLine,
  6287. (ULONG_PTR) lpdwLineStates,
  6288. (ULONG_PTR) lpdwAddressStates
  6289. },
  6290. {
  6291. Dword,
  6292. lpDword,
  6293. lpDword
  6294. }
  6295. };
  6296. if (lpdwLineStates == lpdwAddressStates)
  6297. {
  6298. return LINEERR_INVALPOINTER;
  6299. }
  6300. return (DOFUNC (&funcArgs, "lineGetStatusMessages"));
  6301. }
  6302. HRESULT
  6303. LineHandoff(
  6304. HCALL hCall,
  6305. LPCWSTR lpszFileName,
  6306. DWORD dwMediaMode
  6307. )
  6308. {
  6309. FUNC_ARGS funcArgs =
  6310. {
  6311. MAKELONG (LINE_FUNC | SYNC | 3, lHandoff),
  6312. {
  6313. (ULONG_PTR) hCall,
  6314. (ULONG_PTR) lpszFileName,
  6315. dwMediaMode
  6316. },
  6317. {
  6318. Dword,
  6319. lpszW,
  6320. Dword
  6321. }
  6322. };
  6323. if (lpszFileName == (LPCWSTR) NULL)
  6324. {
  6325. //
  6326. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6327. //
  6328. funcArgs.ArgTypes[1] = Dword;
  6329. funcArgs.Args[1] = TAPI_NO_DATA;
  6330. }
  6331. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineHandoff") );
  6332. }
  6333. HRESULT
  6334. LineHold(
  6335. HCALL hCall
  6336. )
  6337. {
  6338. FUNC_ARGS funcArgs =
  6339. {
  6340. MAKELONG (LINE_FUNC | ASYNC | 1, lHold),
  6341. {
  6342. (ULONG_PTR) hCall
  6343. },
  6344. {
  6345. Dword
  6346. }
  6347. };
  6348. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineHold"));
  6349. }
  6350. PWSTR
  6351. PASCAL
  6352. MultiToWide(
  6353. LPCSTR lpStr
  6354. )
  6355. {
  6356. DWORD dwSize;
  6357. PWSTR szTempPtr;
  6358. dwSize = MultiByteToWideChar(
  6359. GetACP(),
  6360. MB_PRECOMPOSED,
  6361. lpStr,
  6362. -1,
  6363. NULL,
  6364. 0
  6365. );
  6366. if ((szTempPtr = (PWSTR) ClientAlloc ((dwSize + 1) * sizeof (WCHAR))))
  6367. {
  6368. MultiByteToWideChar(
  6369. GetACP(),
  6370. MB_PRECOMPOSED,
  6371. lpStr,
  6372. -1,
  6373. szTempPtr,
  6374. dwSize + 1
  6375. );
  6376. }
  6377. return szTempPtr;
  6378. }
  6379. void
  6380. PASCAL
  6381. lineMakeCallPostProcess(
  6382. PASYNCEVENTMSG pMsg
  6383. )
  6384. {
  6385. LOG((TL_TRACE, "lineMakeCallPostProcess: enter"));
  6386. LOG((TL_INFO,
  6387. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  6388. pMsg->Param1,
  6389. pMsg->Param2,
  6390. pMsg->Param3,
  6391. pMsg->Param4
  6392. ));
  6393. if (pMsg->Param2 == 0)
  6394. {
  6395. HCALL hCall = (HCALL) pMsg->Param3;
  6396. LPHCALL lphCall = (LPHCALL)GetHandleTableEntry(pMsg->Param4);
  6397. DeleteHandleTableEntry(pMsg->Param4);
  6398. __try
  6399. {
  6400. {
  6401. *lphCall = NULL;
  6402. *lphCall = hCall;
  6403. }
  6404. }
  6405. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  6406. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  6407. {
  6408. LOG((TL_WARN,
  6409. "lineMakeCallPostProcess: failed to write handle %lx to memory"
  6410. " location %p. returning LINEERR_INVALPOINTER",
  6411. hCall, lphCall));
  6412. pMsg->Param2 = LINEERR_INVALPOINTER;
  6413. //
  6414. // tapisrv has allocated a call handle for us. deallocate it.
  6415. //
  6416. LineDeallocateCall(hCall);
  6417. }
  6418. }
  6419. }
  6420. HRESULT
  6421. LineMakeCall(
  6422. T3LINE * pt3Line,
  6423. HCALL * phCall,
  6424. LPCWSTR lpszDestAddress,
  6425. DWORD dwCountryCode,
  6426. LPLINECALLPARAMS const lpCallParams
  6427. )
  6428. {
  6429. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  6430. FUNC_ARGS funcArgs =
  6431. {
  6432. MAKELONG (LINE_FUNC | ASYNC | 7, lMakeCall),
  6433. {
  6434. GetFunctionIndex(lineMakeCallPostProcess),
  6435. (ULONG_PTR) pt3Line->hLine,
  6436. hpCallHandle,
  6437. (ULONG_PTR) lpszDestAddress,
  6438. (ULONG_PTR) dwCountryCode,
  6439. (ULONG_PTR) lpCallParams,
  6440. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  6441. },
  6442. {
  6443. Dword,
  6444. Dword,
  6445. Dword,
  6446. lpszW,
  6447. Dword,
  6448. lpSet_Struct,
  6449. Dword
  6450. }
  6451. };
  6452. if (!lpszDestAddress)
  6453. {
  6454. //
  6455. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6456. //
  6457. funcArgs.ArgTypes[3] = Dword;
  6458. funcArgs.Args[3] = TAPI_NO_DATA;
  6459. }
  6460. if (!lpCallParams)
  6461. {
  6462. //
  6463. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6464. //
  6465. funcArgs.ArgTypes[5] = Dword;
  6466. funcArgs.Args[5] = TAPI_NO_DATA;
  6467. }
  6468. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMakeCall") );
  6469. if (FAILED(hr))
  6470. {
  6471. DeleteHandleTableEntry(hpCallHandle);
  6472. }
  6473. return hr;
  6474. }
  6475. HRESULT
  6476. LineMonitorDigits(
  6477. HCALL hCall,
  6478. DWORD dwDigitModes
  6479. )
  6480. {
  6481. FUNC_ARGS funcArgs =
  6482. {
  6483. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
  6484. {
  6485. (ULONG_PTR) hCall,
  6486. dwDigitModes
  6487. },
  6488. {
  6489. Dword,
  6490. Dword
  6491. }
  6492. };
  6493. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMonitorDigits") );
  6494. }
  6495. LONG
  6496. WINAPI
  6497. lineMonitorMedia(
  6498. HCALL hCall,
  6499. DWORD dwMediaModes
  6500. )
  6501. {
  6502. FUNC_ARGS funcArgs =
  6503. {
  6504. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
  6505. {
  6506. (ULONG_PTR) hCall,
  6507. dwMediaModes
  6508. },
  6509. {
  6510. Dword,
  6511. Dword
  6512. }
  6513. };
  6514. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMonitorMedia") );
  6515. }
  6516. HRESULT
  6517. LineMonitorTones(
  6518. HCALL hCall,
  6519. LPLINEMONITORTONE const lpToneList,
  6520. DWORD dwNumEntries
  6521. )
  6522. {
  6523. FUNC_ARGS funcArgs =
  6524. {
  6525. MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
  6526. {
  6527. (ULONG_PTR) hCall,
  6528. (ULONG_PTR) lpToneList,
  6529. dwNumEntries * sizeof(LINEMONITORTONE),
  6530. 0 // dwToneListID, remotesp only
  6531. },
  6532. {
  6533. Dword,
  6534. lpSet_SizeToFollow,
  6535. Size,
  6536. Dword
  6537. }
  6538. };
  6539. if (!lpToneList)
  6540. {
  6541. //
  6542. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6543. //
  6544. funcArgs.ArgTypes[1] = Dword;
  6545. funcArgs.Args[1] = TAPI_NO_DATA;
  6546. funcArgs.ArgTypes[2] = Dword;
  6547. }
  6548. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineMonitorTones"));
  6549. }
  6550. HRESULT
  6551. LineNegotiateAPIVersion(
  6552. HLINEAPP hLineApp,
  6553. DWORD dwDeviceID,
  6554. LPDWORD lpdwAPIVersion
  6555. )
  6556. {
  6557. LINEEXTENSIONID LED;
  6558. LOG((TL_INFO, "LineNegotiateAPIVersion: hLineApp %p", hLineApp));
  6559. FUNC_ARGS funcArgs =
  6560. {
  6561. MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
  6562. {
  6563. (ULONG_PTR) hLineApp,
  6564. dwDeviceID,
  6565. TAPI_VERSION1_0,
  6566. TAPI_VERSION_CURRENT,
  6567. (ULONG_PTR) lpdwAPIVersion,
  6568. (ULONG_PTR) &LED,
  6569. (ULONG_PTR) sizeof(LINEEXTENSIONID)
  6570. },
  6571. {
  6572. hXxxApp,
  6573. Dword,
  6574. Dword,
  6575. Dword,
  6576. lpDword,
  6577. lpGet_SizeToFollow,
  6578. Size
  6579. }
  6580. };
  6581. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineNegotiateAPIVersion") );
  6582. }
  6583. LONG
  6584. WINAPI
  6585. lineNegotiateExtVersion(
  6586. HLINEAPP hLineApp,
  6587. DWORD dwDeviceID,
  6588. DWORD dwAPIVersion,
  6589. DWORD dwExtLowVersion,
  6590. DWORD dwExtHighVersion,
  6591. LPDWORD lpdwExtVersion
  6592. )
  6593. {
  6594. FUNC_ARGS funcArgs =
  6595. {
  6596. MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
  6597. {
  6598. (ULONG_PTR) hLineApp,
  6599. dwDeviceID,
  6600. dwAPIVersion,
  6601. dwExtLowVersion,
  6602. dwExtHighVersion,
  6603. (ULONG_PTR) lpdwExtVersion
  6604. },
  6605. {
  6606. hXxxApp,
  6607. Dword,
  6608. Dword,
  6609. Dword,
  6610. Dword,
  6611. lpDword
  6612. }
  6613. };
  6614. return (DOFUNC (&funcArgs, "lineNegotiateExtVersion"));
  6615. }
  6616. HRESULT
  6617. LineOpen(
  6618. HLINEAPP hLineApp,
  6619. DWORD dwDeviceID,
  6620. DWORD dwAddressID,
  6621. T3LINE * pt3Line,
  6622. DWORD dwAPIVersion,
  6623. DWORD dwPrivileges,
  6624. DWORD dwMediaModes,
  6625. AddressLineStruct * pAddressLine,
  6626. LPLINECALLPARAMS const lpCallParams,
  6627. CAddress * pAddress,
  6628. CTAPI * pTapiObj,
  6629. BOOL bAddToHashTable
  6630. )
  6631. {
  6632. LONG lResult;
  6633. LINECALLPARAMS lcp;
  6634. LINECALLPARAMS * plcp;
  6635. if (IsBadReadPtr(pt3Line, sizeof(T3LINE)))
  6636. {
  6637. LOG((TL_ERROR, "LineOpen: pt3Line %p -- invalid ptr ", pt3Line));
  6638. //
  6639. // if we are getting an invalid ptr, we need to see why
  6640. //
  6641. _ASSERTE(FALSE);
  6642. return E_POINTER;
  6643. }
  6644. if (NULL == lpCallParams)
  6645. {
  6646. memset(
  6647. &lcp,
  6648. 0,
  6649. sizeof(lcp)
  6650. );
  6651. lcp.dwTotalSize = sizeof(lcp);
  6652. lcp.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  6653. lcp.dwAddressID = dwAddressID;
  6654. plcp = &lcp;
  6655. }
  6656. else
  6657. {
  6658. plcp = lpCallParams;
  6659. }
  6660. dwPrivileges|= LINEOPENOPTION_SINGLEADDRESS;
  6661. //
  6662. // if we were passed a pAddressLine pointer, create a corresponding
  6663. // DWORD-sized handle, and keep it around in the T3LINE structure.
  6664. // we need this so we can remove the handle table entry on LineClose.
  6665. //
  6666. _ASSERTE(0 == pt3Line->dwAddressLineStructHandle);
  6667. if (NULL != pAddressLine)
  6668. {
  6669. pt3Line->dwAddressLineStructHandle = CreateHandleTableEntry((UINT_PTR)pAddressLine);
  6670. }
  6671. FUNC_ARGS funcArgs =
  6672. {
  6673. MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
  6674. {
  6675. (ULONG_PTR) hLineApp,
  6676. dwDeviceID,
  6677. (ULONG_PTR) &(pt3Line->hLine),
  6678. dwAPIVersion,
  6679. 0,
  6680. pt3Line->dwAddressLineStructHandle,
  6681. dwPrivileges, //| LINEOPENOPTION_SINGLEADDRESS),
  6682. dwMediaModes,
  6683. (ULONG_PTR) plcp,
  6684. (ULONG_PTR) 0xffffffff, // dwAsciiCallParamsCodePage
  6685. 0 // LINEOPEN_PARAMS.hRemoteLine
  6686. },
  6687. {
  6688. hXxxApp,
  6689. Dword,
  6690. lpDword,
  6691. Dword,
  6692. Dword,
  6693. Dword,
  6694. Dword,
  6695. Dword,
  6696. lpSet_Struct,
  6697. Dword,
  6698. Dword
  6699. }
  6700. };
  6701. if (!(dwPrivileges & (LINEOPENOPTION_PROXY|LINEOPENOPTION_SINGLEADDRESS)))
  6702. {
  6703. //
  6704. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6705. //
  6706. funcArgs.ArgTypes[8] = Dword;
  6707. funcArgs.Args[8] = TAPI_NO_DATA;
  6708. }
  6709. gpLineHashTable->Lock();
  6710. lResult = (DOFUNC (&funcArgs, "lineOpen"));
  6711. #if DBG
  6712. LOG((TL_INFO, "Returning from lineOpenW, *lphLine = 0x%08lx", pt3Line->hLine));
  6713. LOG((TL_INFO, "Returning from lineOpenW, retcode = 0x%08lx", lResult));
  6714. #endif
  6715. if ( 0 == lResult && bAddToHashTable)
  6716. {
  6717. gpLineHashTable->Insert( (ULONG_PTR)(pt3Line->hLine), (ULONG_PTR)pAddress, pTapiObj );
  6718. }
  6719. gpLineHashTable->Unlock();
  6720. //
  6721. // if an address line handle was created, but the call failed, remove the
  6722. // entry from the handle table
  6723. //
  6724. if ( (0 != lResult) && (0 != pt3Line->dwAddressLineStructHandle))
  6725. {
  6726. DeleteHandleTableEntry(pt3Line->dwAddressLineStructHandle);
  6727. pt3Line->dwAddressLineStructHandle = 0;
  6728. }
  6729. return mapTAPIErrorCode( lResult );
  6730. }
  6731. HRESULT
  6732. LinePark(
  6733. HCALL hCall,
  6734. DWORD dwParkMode,
  6735. LPCWSTR lpszDirAddress,
  6736. LPVARSTRING * ppNonDirAddress
  6737. )
  6738. {
  6739. HRESULT hr = S_OK;
  6740. long lResult;
  6741. DWORD dwSize = sizeof (VARSTRING) + 500;
  6742. LOG((TL_TRACE, "LinePark - enter"));
  6743. if ( NULL != ppNonDirAddress )
  6744. {
  6745. *ppNonDirAddress = (LPVARSTRING) ClientAlloc(dwSize);
  6746. if (NULL == *ppNonDirAddress)
  6747. {
  6748. return E_OUTOFMEMORY;
  6749. }
  6750. (*ppNonDirAddress)->dwTotalSize = dwSize;
  6751. }
  6752. FUNC_ARGS funcArgs =
  6753. {
  6754. MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
  6755. {
  6756. (ULONG_PTR) 0, // post process proc
  6757. (ULONG_PTR) hCall,
  6758. (ULONG_PTR) dwParkMode,
  6759. (ULONG_PTR) TAPI_NO_DATA, //lpszDirAddress,
  6760. (ULONG_PTR) 0, // pass ptr as Dword for post processing
  6761. (ULONG_PTR) TAPI_NO_DATA, //lpNonDirAddress // pass ptr as lpGet_Xx for IsValPtr chk
  6762. },
  6763. {
  6764. Dword,
  6765. Dword,
  6766. Dword,
  6767. Dword, // lpszW,
  6768. Dword,
  6769. Dword, // lpGet_Struct
  6770. }
  6771. };
  6772. DWORD hpNonDirAddress = 0;
  6773. if (dwParkMode == LINEPARKMODE_DIRECTED)
  6774. {
  6775. funcArgs.ArgTypes[3] = lpszW;
  6776. funcArgs.Args[3] = (ULONG_PTR) lpszDirAddress;
  6777. }
  6778. else if (dwParkMode == LINEPARKMODE_NONDIRECTED)
  6779. {
  6780. if ( NULL == ppNonDirAddress )
  6781. {
  6782. return E_POINTER;
  6783. }
  6784. //
  6785. // Set post process proc
  6786. //
  6787. funcArgs.Args[0] = GetFunctionIndex(lineDevSpecificPostProcess),
  6788. hpNonDirAddress = CreateHandleTableEntry((ULONG_PTR)*ppNonDirAddress);
  6789. funcArgs.ArgTypes[4] = Dword;
  6790. funcArgs.Args[4] = hpNonDirAddress;
  6791. funcArgs.ArgTypes[5] = lpGet_Struct;
  6792. funcArgs.Args[5] = (ULONG_PTR) *ppNonDirAddress;
  6793. }
  6794. while (TRUE)
  6795. {
  6796. lResult = DOFUNC (&funcArgs, "LinePark");
  6797. if (lResult == LINEERR_STRUCTURETOOSMALL)
  6798. {
  6799. // didnt Work , adjust buffer size & try again
  6800. LOG((TL_INFO, "LinePark failed - buffer too small"));
  6801. dwSize = (*ppNonDirAddress)->dwNeededSize;
  6802. //
  6803. // no longer need the handle
  6804. //
  6805. DeleteHandleTableEntry(hpNonDirAddress);
  6806. hpNonDirAddress = 0;
  6807. ClientFree( *ppNonDirAddress );
  6808. *ppNonDirAddress = (LPVARSTRING) ClientAlloc( dwSize );
  6809. if (*ppNonDirAddress == NULL)
  6810. {
  6811. LOG((TL_ERROR, "LinePark - repeat ClientAlloc failed"));
  6812. hr = E_OUTOFMEMORY;
  6813. break;
  6814. }
  6815. else
  6816. {
  6817. //
  6818. // get a handle corresponding to the new *ppNonDirAddress and
  6819. // use it to pass to DoFunc
  6820. //
  6821. hpNonDirAddress = CreateHandleTableEntry((ULONG_PTR)*ppNonDirAddress);
  6822. if (0 == hpNonDirAddress)
  6823. {
  6824. LOG((TL_ERROR, "LinePark - repeat CreateHandleTableEntry failed"));
  6825. hr = E_OUTOFMEMORY;
  6826. ClientFree(*ppNonDirAddress);
  6827. *ppNonDirAddress = NULL;
  6828. break;
  6829. }
  6830. funcArgs.Args[4] = hpNonDirAddress;
  6831. (*ppNonDirAddress)->dwTotalSize = dwSize;
  6832. }
  6833. }
  6834. else if (lResult < 0)
  6835. {
  6836. if ( NULL != ppNonDirAddress )
  6837. {
  6838. ClientFree( *ppNonDirAddress );
  6839. }
  6840. hr = mapTAPIErrorCode( lResult );
  6841. break;
  6842. }
  6843. else
  6844. {
  6845. hr = lResult;
  6846. break;
  6847. }
  6848. } // end while(TRUE)
  6849. //
  6850. // if we failed, remove the handle table entry because it will not be cleared by the callback
  6851. //
  6852. if (FAILED(hr) && (0 != hpNonDirAddress))
  6853. {
  6854. DeleteHandleTableEntry(hpNonDirAddress);
  6855. hpNonDirAddress = 0;
  6856. }
  6857. LOG((TL_TRACE, hr, "LinePark - exit"));
  6858. return hr;
  6859. }
  6860. HRESULT
  6861. LinePickup(
  6862. HLINE hLine,
  6863. DWORD dwAddressID,
  6864. HCALL *phCall,
  6865. LPCWSTR lpszDestAddress,
  6866. LPCWSTR lpszGroupID
  6867. )
  6868. {
  6869. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  6870. FUNC_ARGS funcArgs =
  6871. {
  6872. MAKELONG (LINE_FUNC | ASYNC | 6, lPickup),
  6873. {
  6874. GetFunctionIndex(lineMakeCallPostProcess),
  6875. (ULONG_PTR) hLine,
  6876. (ULONG_PTR) dwAddressID,
  6877. hpCallHandle,
  6878. (ULONG_PTR) lpszDestAddress,
  6879. (ULONG_PTR) lpszGroupID
  6880. },
  6881. {
  6882. Dword,
  6883. Dword,
  6884. Dword,
  6885. Dword,
  6886. lpszW,
  6887. lpszW
  6888. }
  6889. };
  6890. if (!lpszDestAddress)
  6891. {
  6892. //
  6893. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6894. //
  6895. funcArgs.ArgTypes[4] = Dword;
  6896. funcArgs.Args[4] = TAPI_NO_DATA;
  6897. }
  6898. if (!lpszGroupID)
  6899. {
  6900. //
  6901. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6902. //
  6903. funcArgs.ArgTypes[5] = Dword;
  6904. funcArgs.Args[5] = TAPI_NO_DATA;
  6905. }
  6906. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "linePickup") );
  6907. if (FAILED(hr))
  6908. {
  6909. DeleteHandleTableEntry(hpCallHandle);
  6910. hpCallHandle = 0;
  6911. }
  6912. return hr;
  6913. }
  6914. HRESULT
  6915. LinePrepareAddToConference(
  6916. HCALL hConfCall,
  6917. HCALL * phConsultCall,
  6918. LPLINECALLPARAMS const lpCallParams
  6919. )
  6920. {
  6921. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR)phConsultCall);
  6922. FUNC_ARGS funcArgs =
  6923. {
  6924. MAKELONG (LINE_FUNC | ASYNC | 5, lPrepareAddToConference),
  6925. {
  6926. GetFunctionIndex(lineMakeCallPostProcess),
  6927. (ULONG_PTR) hConfCall,
  6928. hpConsultCallHandle,
  6929. (ULONG_PTR) lpCallParams,
  6930. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  6931. },
  6932. {
  6933. Dword,
  6934. Dword,
  6935. Dword,
  6936. lpSet_Struct,
  6937. Dword
  6938. }
  6939. };
  6940. if (!lpCallParams)
  6941. {
  6942. //
  6943. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6944. //
  6945. funcArgs.ArgTypes[3] = Dword;
  6946. funcArgs.Args[3] = TAPI_NO_DATA;
  6947. }
  6948. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LinePrepareAddToConference") );
  6949. if (FAILED(hr))
  6950. {
  6951. DeleteHandleTableEntry(hpConsultCallHandle);
  6952. }
  6953. return hr;
  6954. }
  6955. LONG
  6956. WINAPI
  6957. lineProxyMessage(
  6958. HLINE hLine,
  6959. HCALL hCall,
  6960. DWORD dwMsg,
  6961. DWORD Param1,
  6962. DWORD Param2,
  6963. DWORD Param3
  6964. )
  6965. {
  6966. FUNC_ARGS funcArgs =
  6967. {
  6968. MAKELONG (LINE_FUNC | SYNC | 6, lProxyMessage),
  6969. {
  6970. (ULONG_PTR) hLine,
  6971. (ULONG_PTR) hCall,
  6972. dwMsg,
  6973. Param1,
  6974. Param2,
  6975. Param3
  6976. },
  6977. {
  6978. Dword,
  6979. Dword,
  6980. Dword,
  6981. Dword,
  6982. Dword,
  6983. Dword,
  6984. }
  6985. };
  6986. return (DOFUNC (&funcArgs, "lineProxyMessage"));
  6987. }
  6988. LONG
  6989. WINAPI
  6990. lineProxyResponse(
  6991. HLINE hLine,
  6992. LPLINEPROXYREQUEST lpProxyRequest,
  6993. DWORD dwResult
  6994. )
  6995. {
  6996. LONG lResult = 0;
  6997. FUNC_ARGS funcArgs =
  6998. {
  6999. MAKELONG (LINE_FUNC | SYNC | 4, lProxyResponse),
  7000. {
  7001. (ULONG_PTR) hLine,
  7002. (ULONG_PTR) 0,
  7003. (ULONG_PTR) lpProxyRequest,
  7004. (ULONG_PTR) dwResult
  7005. },
  7006. {
  7007. Dword,
  7008. Dword,
  7009. lpSet_Struct,
  7010. Dword
  7011. }
  7012. };
  7013. PPROXYREQUESTHEADER pProxyRequestHeader;
  7014. //
  7015. // The following is not the most thorough checking, but it's close
  7016. // enough that a client app won't get a totally unexpected value
  7017. // back
  7018. //
  7019. if (dwResult != 0 &&
  7020. (dwResult < LINEERR_ALLOCATED ||
  7021. dwResult > LINEERR_DIALVOICEDETECT))
  7022. {
  7023. return LINEERR_INVALPARAM;
  7024. }
  7025. //
  7026. // Backtrack a little bit to get the pointer to what ought to be
  7027. // the proxy header, and then make sure we're dealing with a valid
  7028. // proxy request
  7029. //
  7030. pProxyRequestHeader = (PPROXYREQUESTHEADER)
  7031. (((LPBYTE) lpProxyRequest) - sizeof (PROXYREQUESTHEADER));
  7032. __try
  7033. {
  7034. //
  7035. // Make sure we've a valid pProxyRequestHeader, then invalidate
  7036. // the key so subsequent attempts to call lineProxyResponse with
  7037. // the same lpProxyRequest fail
  7038. //
  7039. // if ((DWORD) pProxyRequestHeader & 0x7 ||
  7040. if(pProxyRequestHeader->dwKey != TPROXYREQUESTHEADER_KEY)
  7041. {
  7042. lResult = LINEERR_INVALPOINTER;
  7043. }
  7044. pProxyRequestHeader->dwKey = 0xefefefef;
  7045. funcArgs.Args[1] = pProxyRequestHeader->dwInstance;
  7046. //
  7047. // See if this is one of the requests that don't require
  7048. // any data to get passed back & reset the appropriate
  7049. // params if so
  7050. //
  7051. switch (lpProxyRequest->dwRequestType)
  7052. {
  7053. case LINEPROXYREQUEST_SETAGENTGROUP:
  7054. case LINEPROXYREQUEST_SETAGENTSTATE:
  7055. case LINEPROXYREQUEST_SETAGENTACTIVITY:
  7056. case LINEPROXYREQUEST_SETAGENTMEASUREMENTPERIOD:
  7057. case LINEPROXYREQUEST_SETAGENTSESSIONSTATE:
  7058. case LINEPROXYREQUEST_SETQUEUEMEASUREMENTPERIOD:
  7059. case LINEPROXYREQUEST_SETAGENTSTATEEX:
  7060. funcArgs.Args[2] = TAPI_NO_DATA;
  7061. funcArgs.ArgTypes[2] = Dword;
  7062. break;
  7063. }
  7064. }
  7065. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  7066. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  7067. {
  7068. lResult = LINEERR_INVALPOINTER;
  7069. }
  7070. if (lResult == 0)
  7071. {
  7072. lResult = DOFUNC (&funcArgs, "lineProxyResponse");
  7073. //
  7074. // If we've gotten this far we want to free the buffer
  7075. // unconditionally
  7076. //
  7077. ClientFree (pProxyRequestHeader);
  7078. }
  7079. return lResult;
  7080. }
  7081. LONG
  7082. WINAPI
  7083. lineRedirectW(
  7084. HCALL hCall,
  7085. LPCWSTR lpszDestAddress,
  7086. DWORD dwCountryCode
  7087. )
  7088. {
  7089. FUNC_ARGS funcArgs =
  7090. {
  7091. MAKELONG (LINE_FUNC | ASYNC | 3, lRedirect),
  7092. {
  7093. (ULONG_PTR) hCall,
  7094. (ULONG_PTR) lpszDestAddress,
  7095. dwCountryCode
  7096. },
  7097. {
  7098. Dword,
  7099. lpszW,
  7100. Dword
  7101. }
  7102. };
  7103. return (DOFUNC (&funcArgs, "lineRedirect"));
  7104. }
  7105. HRESULT
  7106. LineRegisterRequestRecipient(
  7107. HLINEAPP hLineApp,
  7108. DWORD dwRegistrationInstance,
  7109. DWORD dwRequestMode,
  7110. #ifdef NEWREQUEST
  7111. DWORD dwAddressTypes,
  7112. #endif
  7113. DWORD bEnable
  7114. )
  7115. {
  7116. FUNC_ARGS funcArgs =
  7117. {
  7118. MAKELONG (LINE_FUNC | SYNC | 4, lRegisterRequestRecipient),
  7119. {
  7120. (ULONG_PTR) hLineApp,
  7121. dwRegistrationInstance,
  7122. dwRequestMode,
  7123. bEnable
  7124. },
  7125. {
  7126. hXxxApp,
  7127. Dword,
  7128. Dword,
  7129. Dword
  7130. }
  7131. };
  7132. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineRegisterRequestRecipient"));
  7133. }
  7134. HRESULT
  7135. LineReleaseUserUserInfo(
  7136. HCALL hCall
  7137. )
  7138. {
  7139. if ( !hCall )
  7140. {
  7141. return TAPI_E_INVALCALLSTATE;
  7142. }
  7143. FUNC_ARGS funcArgs =
  7144. {
  7145. MAKELONG (LINE_FUNC | ASYNC | 1, lReleaseUserUserInfo),
  7146. {
  7147. (ULONG_PTR) hCall
  7148. },
  7149. {
  7150. Dword,
  7151. }
  7152. };
  7153. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineReleaseUserUserInfo") );
  7154. }
  7155. HRESULT
  7156. LineRemoveFromConference(
  7157. HCALL hCall
  7158. )
  7159. {
  7160. FUNC_ARGS funcArgs =
  7161. {
  7162. MAKELONG (LINE_FUNC | ASYNC | 1, lRemoveFromConference),
  7163. {
  7164. (ULONG_PTR) hCall
  7165. },
  7166. {
  7167. Dword
  7168. }
  7169. };
  7170. return mapTAPIErrorCode( DOFUNC (&funcArgs, "LineRemoveFromConference") );
  7171. }
  7172. LONG
  7173. WINAPI
  7174. lineRemoveProvider(
  7175. DWORD dwPermanentProviderID,
  7176. HWND hwndOwner
  7177. )
  7178. {
  7179. return (lineXxxProvider(
  7180. gszTUISPI_providerRemove, // func name
  7181. NULL, // lpszProviderFilename
  7182. hwndOwner, // hwndOwner
  7183. dwPermanentProviderID, // dwPermProviderID
  7184. NULL // lpdwPermProviderID
  7185. ));
  7186. }
  7187. LONG
  7188. WINAPI
  7189. lineSecureCall(
  7190. HCALL hCall
  7191. )
  7192. {
  7193. FUNC_ARGS funcArgs =
  7194. {
  7195. MAKELONG (LINE_FUNC | ASYNC | 1, lSecureCall),
  7196. {
  7197. (ULONG_PTR) hCall
  7198. },
  7199. {
  7200. Dword
  7201. }
  7202. };
  7203. return (DOFUNC (&funcArgs, "lineSecureCall"));
  7204. }
  7205. HRESULT
  7206. LineSendUserUserInfo(
  7207. HCALL hCall,
  7208. LPCSTR lpsUserUserInfo,
  7209. DWORD dwSize
  7210. )
  7211. {
  7212. FUNC_ARGS funcArgs =
  7213. {
  7214. MAKELONG (LINE_FUNC | ASYNC | 3, lSendUserUserInfo),
  7215. {
  7216. (ULONG_PTR) hCall,
  7217. (ULONG_PTR) lpsUserUserInfo,
  7218. dwSize
  7219. },
  7220. {
  7221. Dword,
  7222. lpSet_SizeToFollow,
  7223. Size
  7224. }
  7225. };
  7226. if (!lpsUserUserInfo)
  7227. {
  7228. //
  7229. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7230. //
  7231. funcArgs.ArgTypes[1] = Dword;
  7232. funcArgs.Args[1] = TAPI_NO_DATA;
  7233. funcArgs.ArgTypes[2] = Dword;
  7234. }
  7235. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSendUserUserInfo") );
  7236. }
  7237. LONG
  7238. WINAPI
  7239. lineSetAgentActivity(
  7240. HLINE hLine,
  7241. DWORD dwAddressID,
  7242. DWORD dwActivityID
  7243. )
  7244. {
  7245. FUNC_ARGS funcArgs =
  7246. {
  7247. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentActivity),
  7248. {
  7249. (ULONG_PTR) hLine,
  7250. dwAddressID,
  7251. dwActivityID
  7252. },
  7253. {
  7254. Dword,
  7255. Dword,
  7256. Dword
  7257. }
  7258. };
  7259. return (DOFUNC (&funcArgs, "lineSetAgentActivity"));
  7260. }
  7261. LONG
  7262. WINAPI
  7263. lineSetAgentGroup(
  7264. HLINE hLine,
  7265. DWORD dwAddressID,
  7266. LPLINEAGENTGROUPLIST lpAgentGroupList
  7267. )
  7268. {
  7269. static LINEAGENTGROUPLIST EmptyGroupList =
  7270. {
  7271. sizeof (LINEAGENTGROUPLIST), // dwTotalSize
  7272. sizeof (LINEAGENTGROUPLIST), // dwNeededSize
  7273. sizeof (LINEAGENTGROUPLIST), // dwUsedSize
  7274. 0, // dwNumEntries
  7275. 0, // dwListSize
  7276. 0 // dwListOffset
  7277. };
  7278. FUNC_ARGS funcArgs =
  7279. {
  7280. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentGroup),
  7281. {
  7282. (ULONG_PTR) hLine,
  7283. (ULONG_PTR) dwAddressID,
  7284. (ULONG_PTR) lpAgentGroupList
  7285. },
  7286. {
  7287. Dword,
  7288. Dword,
  7289. lpSet_Struct
  7290. }
  7291. };
  7292. if (!lpAgentGroupList)
  7293. {
  7294. funcArgs.Args[2] = (ULONG_PTR) &EmptyGroupList;
  7295. }
  7296. return (DOFUNC (&funcArgs, "lineSetAgentGroup"));
  7297. }
  7298. LONG
  7299. WINAPI
  7300. lineSetAgentState(
  7301. HLINE hLine,
  7302. DWORD dwAddressID,
  7303. DWORD dwAgentState,
  7304. DWORD dwNextAgentState
  7305. )
  7306. {
  7307. FUNC_ARGS funcArgs =
  7308. {
  7309. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentState),
  7310. {
  7311. (ULONG_PTR) hLine,
  7312. dwAddressID,
  7313. dwAgentState,
  7314. dwNextAgentState
  7315. },
  7316. {
  7317. Dword,
  7318. Dword,
  7319. Dword,
  7320. Dword
  7321. }
  7322. };
  7323. return (DOFUNC (&funcArgs, "lineSetAgentState"));
  7324. }
  7325. LONG
  7326. WINAPI
  7327. lineSetAgentStateEx(
  7328. HLINE hLine,
  7329. HAGENT hAgent,
  7330. DWORD dwAgentState,
  7331. DWORD dwNextAgentState
  7332. )
  7333. {
  7334. FUNC_ARGS funcArgs =
  7335. {
  7336. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentStateEx),
  7337. {
  7338. (ULONG_PTR) hLine,
  7339. (ULONG_PTR) hAgent,
  7340. dwAgentState,
  7341. dwNextAgentState
  7342. },
  7343. {
  7344. Dword,
  7345. Dword,
  7346. Dword,
  7347. Dword
  7348. }
  7349. };
  7350. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentStateEx"));
  7351. }
  7352. HRESULT
  7353. LineSetAppPriority(
  7354. LPCWSTR lpszAppName,
  7355. DWORD dwMediaMode,
  7356. DWORD dwRequestMode,
  7357. DWORD dwPriority
  7358. )
  7359. {
  7360. FUNC_ARGS funcArgs =
  7361. {
  7362. MAKELONG (LINE_FUNC | SYNC | 7, lSetAppPriority),
  7363. {
  7364. (ULONG_PTR) lpszAppName,
  7365. dwMediaMode,
  7366. (ULONG_PTR) TAPI_NO_DATA, // (ULONG_PTR) lpExtensionID,
  7367. 0, // (ULONG_PTR) sizeof(LINEEXTENSIONID),
  7368. dwRequestMode,
  7369. (ULONG_PTR) TAPI_NO_DATA, // (ULONG_PTR) lpszExtensionName,
  7370. dwPriority
  7371. },
  7372. {
  7373. lpszW,
  7374. Dword,
  7375. Dword, // lpSet_SizeToFollow,
  7376. Dword, // Size,
  7377. Dword,
  7378. Dword, // lpsz,
  7379. Dword
  7380. }
  7381. };
  7382. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAppPriority"));
  7383. }
  7384. HRESULT
  7385. LineSetAppSpecific(
  7386. HCALL hCall,
  7387. DWORD dwAppSpecific
  7388. )
  7389. {
  7390. FUNC_ARGS funcArgs =
  7391. {
  7392. MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
  7393. {
  7394. (ULONG_PTR) hCall,
  7395. dwAppSpecific
  7396. },
  7397. {
  7398. Dword,
  7399. Dword
  7400. }
  7401. };
  7402. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAppSpecific"));
  7403. }
  7404. HRESULT
  7405. LineSetCallData(
  7406. HCALL hCall,
  7407. LPVOID lpCallData,
  7408. DWORD dwSize
  7409. )
  7410. {
  7411. FUNC_ARGS funcArgs =
  7412. {
  7413. MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallData),
  7414. {
  7415. (ULONG_PTR) hCall,
  7416. (ULONG_PTR) lpCallData,
  7417. dwSize
  7418. },
  7419. {
  7420. Dword,
  7421. lpSet_SizeToFollow,
  7422. Size
  7423. }
  7424. };
  7425. if (dwSize == 0)
  7426. {
  7427. funcArgs.Args[1] = TAPI_NO_DATA;
  7428. funcArgs.ArgTypes[1] =
  7429. funcArgs.ArgTypes[2] = Dword;
  7430. }
  7431. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetCallData"));
  7432. }
  7433. HRESULT
  7434. WINAPI
  7435. LineSetCallHubTracking(
  7436. T3LINE * pt3Line,
  7437. LINECALLHUBTRACKINGINFO * plchti
  7438. )
  7439. {
  7440. FUNC_ARGS funcArgs =
  7441. {
  7442. MAKELONG (LINE_FUNC | SYNC | 2, lSetCallHubTracking),
  7443. {
  7444. (ULONG_PTR) (pt3Line->hLine),
  7445. (ULONG_PTR) plchti
  7446. },
  7447. {
  7448. Dword,
  7449. lpSet_Struct
  7450. }
  7451. };
  7452. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallHubTracking") );
  7453. }
  7454. HRESULT
  7455. LineSetCallParams(
  7456. HCALL hCall,
  7457. DWORD dwBearerMode,
  7458. DWORD dwMinRate,
  7459. DWORD dwMaxRate,
  7460. LPLINEDIALPARAMS const lpDialParams
  7461. )
  7462. {
  7463. FUNC_ARGS funcArgs =
  7464. {
  7465. MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallParams),
  7466. {
  7467. (ULONG_PTR) hCall,
  7468. dwBearerMode,
  7469. dwMinRate,
  7470. dwMaxRate,
  7471. (ULONG_PTR) lpDialParams,
  7472. sizeof(LINEDIALPARAMS)
  7473. },
  7474. {
  7475. Dword,
  7476. Dword,
  7477. Dword,
  7478. Dword,
  7479. lpSet_SizeToFollow,
  7480. Size
  7481. }
  7482. };
  7483. if (!lpDialParams)
  7484. {
  7485. //
  7486. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7487. //
  7488. funcArgs.ArgTypes[4] = Dword;
  7489. funcArgs.Args[4] = TAPI_NO_DATA;
  7490. funcArgs.ArgTypes[5] = Dword;
  7491. }
  7492. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallParams") );
  7493. }
  7494. LONG
  7495. WINAPI
  7496. lineSetCallPrivilege(
  7497. HCALL hCall,
  7498. DWORD dwCallPrivilege
  7499. )
  7500. {
  7501. FUNC_ARGS funcArgs =
  7502. {
  7503. MAKELONG (LINE_FUNC | SYNC | 2, lSetCallPrivilege),
  7504. {
  7505. (ULONG_PTR) hCall,
  7506. dwCallPrivilege
  7507. },
  7508. {
  7509. Dword,
  7510. Dword
  7511. }
  7512. };
  7513. return (DOFUNC (&funcArgs, "lineSetCallPrivilege"));
  7514. }
  7515. HRESULT
  7516. LineSetCallQualityOfService(
  7517. HCALL hCall,
  7518. QOS_SERVICE_LEVEL ServiceLevel,
  7519. DWORD dwMediaType
  7520. )
  7521. {
  7522. LINECALLQOSINFO * plqi;
  7523. DWORD dwSize;
  7524. HRESULT hr;
  7525. dwSize = sizeof(LINECALLQOSINFO);
  7526. plqi = (LINECALLQOSINFO *)ClientAlloc( dwSize );
  7527. if ( NULL == plqi )
  7528. {
  7529. return E_OUTOFMEMORY;
  7530. }
  7531. plqi->dwKey = LINEQOSSTRUCT_KEY;
  7532. plqi->dwTotalSize = dwSize;
  7533. if ( 0 != ServiceLevel )
  7534. {
  7535. plqi->dwQOSRequestType = LINEQOSREQUESTTYPE_SERVICELEVEL;
  7536. plqi->SetQOSServiceLevel.dwNumServiceLevelEntries = 1;
  7537. plqi->SetQOSServiceLevel.LineQOSServiceLevel[0].dwMediaMode = dwMediaType;
  7538. plqi->SetQOSServiceLevel.LineQOSServiceLevel[0].dwQOSServiceLevel = ServiceLevel;
  7539. }
  7540. FUNC_ARGS funcArgs =
  7541. {
  7542. MAKELONG (LINE_FUNC | ASYNC | 5, lSetCallQualityOfService),
  7543. {
  7544. (ULONG_PTR) hCall,
  7545. (ULONG_PTR) TAPI_NO_DATA,
  7546. (ULONG_PTR) 0,
  7547. (ULONG_PTR) plqi,
  7548. (ULONG_PTR) dwSize
  7549. },
  7550. {
  7551. Dword,
  7552. Dword,
  7553. Dword,
  7554. lpSet_SizeToFollow,
  7555. Size
  7556. }
  7557. };
  7558. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallQualityOfService") );
  7559. ClientFree( plqi );
  7560. return hr;
  7561. }
  7562. HRESULT
  7563. LineSetCallTreatment(
  7564. HCALL hCall,
  7565. DWORD dwTreatment
  7566. )
  7567. {
  7568. FUNC_ARGS funcArgs =
  7569. {
  7570. MAKELONG (LINE_FUNC | ASYNC | 2, lSetCallTreatment),
  7571. {
  7572. (ULONG_PTR) hCall,
  7573. (ULONG_PTR) dwTreatment
  7574. },
  7575. {
  7576. Dword,
  7577. Dword
  7578. }
  7579. };
  7580. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallTreatment") );
  7581. }
  7582. LONG
  7583. WINAPI
  7584. lineSetDevConfigW(
  7585. DWORD dwDeviceID,
  7586. LPVOID const lpDeviceConfig,
  7587. DWORD dwSize,
  7588. LPCWSTR lpszDeviceClass
  7589. )
  7590. {
  7591. FUNC_ARGS funcArgs =
  7592. {
  7593. MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
  7594. {
  7595. dwDeviceID,
  7596. (ULONG_PTR) lpDeviceConfig,
  7597. dwSize,
  7598. (ULONG_PTR) lpszDeviceClass
  7599. },
  7600. {
  7601. Dword,
  7602. lpSet_SizeToFollow,
  7603. Size,
  7604. lpszW
  7605. }
  7606. };
  7607. return (DOFUNC (&funcArgs, "lineSetDevConfig"));
  7608. }
  7609. HRESULT
  7610. LineSetLineDevStatus(
  7611. T3LINE *pt3Line,
  7612. DWORD dwStatusToChange,
  7613. DWORD fStatus
  7614. )
  7615. {
  7616. FUNC_ARGS funcArgs =
  7617. {
  7618. MAKELONG (LINE_FUNC | ASYNC | 3, lSetLineDevStatus),
  7619. {
  7620. (ULONG_PTR) pt3Line->hLine,
  7621. dwStatusToChange,
  7622. fStatus
  7623. },
  7624. {
  7625. Dword,
  7626. Dword,
  7627. Dword
  7628. }
  7629. };
  7630. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetLineDevStatus") );
  7631. }
  7632. LONG
  7633. WINAPI
  7634. lineSetMediaControl(
  7635. HLINE hLine,
  7636. DWORD dwAddressID,
  7637. HCALL hCall,
  7638. DWORD dwSelect,
  7639. LPLINEMEDIACONTROLDIGIT const lpDigitList,
  7640. DWORD dwDigitNumEntries,
  7641. LPLINEMEDIACONTROLMEDIA const lpMediaList,
  7642. DWORD dwMediaNumEntries,
  7643. LPLINEMEDIACONTROLTONE const lpToneList,
  7644. DWORD dwToneNumEntries,
  7645. LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
  7646. DWORD dwCallStateNumEntries
  7647. )
  7648. {
  7649. FUNC_ARGS funcArgs =
  7650. {
  7651. MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
  7652. {
  7653. (ULONG_PTR) hLine,
  7654. dwAddressID,
  7655. (ULONG_PTR) hCall,
  7656. dwSelect,
  7657. TAPI_NO_DATA,
  7658. dwDigitNumEntries * sizeof(LINEMEDIACONTROLDIGIT),
  7659. TAPI_NO_DATA,
  7660. dwMediaNumEntries * sizeof(LINEMEDIACONTROLMEDIA),
  7661. TAPI_NO_DATA,
  7662. dwToneNumEntries * sizeof(LINEMEDIACONTROLTONE),
  7663. TAPI_NO_DATA,
  7664. dwCallStateNumEntries * sizeof(LINEMEDIACONTROLCALLSTATE)
  7665. },
  7666. {
  7667. Dword,
  7668. Dword,
  7669. Dword,
  7670. Dword,
  7671. Dword,
  7672. Dword,
  7673. Dword,
  7674. Dword,
  7675. Dword,
  7676. Dword,
  7677. Dword,
  7678. Dword
  7679. }
  7680. };
  7681. //
  7682. // If lpXxxList is non-NULL reset Arg & ArgType, and check
  7683. // to see that dwXxxNumEntries is not unacceptably large
  7684. //
  7685. if (lpDigitList)
  7686. {
  7687. if (dwDigitNumEntries >
  7688. (0x1000000 / sizeof (LINEMEDIACONTROLDIGIT)))
  7689. {
  7690. return LINEERR_INVALPOINTER;
  7691. }
  7692. funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
  7693. funcArgs.Args[4] = (ULONG_PTR) lpDigitList;
  7694. funcArgs.ArgTypes[5] = Size;
  7695. }
  7696. if (lpMediaList)
  7697. {
  7698. if (dwMediaNumEntries >
  7699. (0x1000000 / sizeof (LINEMEDIACONTROLMEDIA)))
  7700. {
  7701. return LINEERR_INVALPOINTER;
  7702. }
  7703. funcArgs.ArgTypes[6] = lpSet_SizeToFollow;
  7704. funcArgs.Args[6] = (ULONG_PTR) lpMediaList;
  7705. funcArgs.ArgTypes[7] = Size;
  7706. }
  7707. if (lpToneList)
  7708. {
  7709. if (dwToneNumEntries >
  7710. (0x1000000 / sizeof (LINEMEDIACONTROLTONE)))
  7711. {
  7712. return LINEERR_INVALPOINTER;
  7713. }
  7714. funcArgs.ArgTypes[8] = lpSet_SizeToFollow;
  7715. funcArgs.Args[8] = (ULONG_PTR) lpToneList;
  7716. funcArgs.ArgTypes[9] = Size;
  7717. }
  7718. if (lpCallStateList)
  7719. {
  7720. if (dwCallStateNumEntries >
  7721. (0x1000000 / sizeof (LINEMEDIACONTROLCALLSTATE)))
  7722. {
  7723. return LINEERR_INVALPOINTER;
  7724. }
  7725. funcArgs.ArgTypes[10] = lpSet_SizeToFollow;
  7726. funcArgs.Args[10] = (ULONG_PTR) lpCallStateList;
  7727. funcArgs.ArgTypes[11] = Size;
  7728. }
  7729. return (DOFUNC (&funcArgs, "lineSetMediaControl"));
  7730. }
  7731. HRESULT
  7732. LineSetMediaMode(
  7733. HCALL hCall,
  7734. DWORD dwMediaModes
  7735. )
  7736. {
  7737. FUNC_ARGS funcArgs =
  7738. {
  7739. MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
  7740. {
  7741. (ULONG_PTR) hCall,
  7742. dwMediaModes
  7743. },
  7744. {
  7745. Dword,
  7746. Dword
  7747. }
  7748. };
  7749. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetMediaMode") );
  7750. }
  7751. LONG
  7752. WINAPI
  7753. lineSetNumRings(
  7754. HLINE hLine,
  7755. DWORD dwAddressID,
  7756. DWORD dwNumRings
  7757. )
  7758. {
  7759. FUNC_ARGS funcArgs =
  7760. {
  7761. MAKELONG (LINE_FUNC | SYNC | 3, lSetNumRings),
  7762. {
  7763. (ULONG_PTR) hLine,
  7764. dwAddressID,
  7765. dwNumRings
  7766. },
  7767. {
  7768. Dword,
  7769. Dword,
  7770. Dword
  7771. }
  7772. };
  7773. return (DOFUNC (&funcArgs, "lineSetNumRings"));
  7774. }
  7775. HRESULT
  7776. LineSetStatusMessages(
  7777. T3LINE * pt3Line,
  7778. DWORD dwLineStates,
  7779. DWORD dwAddressStates
  7780. )
  7781. {
  7782. FUNC_ARGS funcArgs =
  7783. {
  7784. MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
  7785. {
  7786. (ULONG_PTR) pt3Line->hLine,
  7787. dwLineStates,
  7788. dwAddressStates
  7789. },
  7790. {
  7791. Dword,
  7792. Dword,
  7793. Dword
  7794. }
  7795. };
  7796. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetStatusMessages") );
  7797. }
  7798. LONG
  7799. WINAPI
  7800. lineSetTerminal(
  7801. HLINE hLine,
  7802. DWORD dwAddressID,
  7803. HCALL hCall,
  7804. DWORD dwSelect,
  7805. DWORD dwTerminalModes,
  7806. DWORD dwTerminalID,
  7807. DWORD bEnable
  7808. )
  7809. {
  7810. FUNC_ARGS funcArgs =
  7811. {
  7812. MAKELONG (LINE_FUNC | ASYNC | 7, lSetTerminal),
  7813. {
  7814. (ULONG_PTR) hLine,
  7815. dwAddressID,
  7816. (ULONG_PTR) hCall,
  7817. dwSelect,
  7818. dwTerminalModes,
  7819. dwTerminalID,
  7820. bEnable
  7821. },
  7822. {
  7823. Dword,
  7824. Dword,
  7825. Dword,
  7826. Dword,
  7827. Dword,
  7828. Dword,
  7829. Dword
  7830. }
  7831. };
  7832. return (DOFUNC (&funcArgs, "lineSetTerminal"));
  7833. }
  7834. void
  7835. PASCAL
  7836. lineSetupConferencePostProcess(
  7837. PASYNCEVENTMSG pMsg
  7838. )
  7839. {
  7840. LOG((TL_TRACE, "lineSetupConfPostProcess: enter"));
  7841. LOG((TL_INFO,
  7842. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  7843. pMsg->Param1,
  7844. pMsg->Param2,
  7845. pMsg->Param3,
  7846. pMsg->Param4
  7847. ));
  7848. if (pMsg->Param2 == 0)
  7849. {
  7850. HCALL hConfCall = (HCALL) pMsg->Param3,
  7851. hConsultCall = (HCALL) (*(&pMsg->Param4 + 1));
  7852. LPHCALL lphConfCall =
  7853. (LPHCALL) GetHandleTableEntry(pMsg->Param4);
  7854. LPHCALL lphConsultCall =
  7855. (LPHCALL) GetHandleTableEntry(*(&pMsg->Param4 + 2));
  7856. LOG((TL_INFO,
  7857. "lineSetupConfPostProcess: hConfCall [%lx] hConsultCall [%lx] lphConfCall [%p] lphConsultCall [%p]",
  7858. hConfCall, hConsultCall, lphConfCall, lphConsultCall));
  7859. __try
  7860. {
  7861. {
  7862. *lphConfCall = NULL;
  7863. *lphConsultCall = NULL;
  7864. *lphConfCall = hConfCall;
  7865. *lphConsultCall = hConsultCall;
  7866. }
  7867. }
  7868. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  7869. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  7870. {
  7871. pMsg->Param2 = LINEERR_INVALPOINTER;
  7872. LOG((TL_WARN,
  7873. "lineSetupConfPostProcess: failed to set memory at %p or at %p",
  7874. lphConfCall, lphConsultCall));
  7875. //
  7876. // tapisrv has allocated call handles for us. deallocate them.
  7877. //
  7878. LineDeallocateCall(hConfCall);
  7879. LineDeallocateCall(hConsultCall);
  7880. }
  7881. }
  7882. }
  7883. HRESULT
  7884. LineSetupConference(
  7885. HCALL hCall,
  7886. T3LINE * pt3Line,
  7887. HCALL * phConfCall,
  7888. HCALL * phConsultCall,
  7889. DWORD dwNumParties,
  7890. LPLINECALLPARAMS const lpCallParams
  7891. )
  7892. {
  7893. if ( phConfCall == phConsultCall )
  7894. {
  7895. return E_POINTER;
  7896. }
  7897. DWORD hpConfCallHandle = CreateHandleTableEntry((ULONG_PTR) phConfCall);
  7898. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR) phConsultCall);
  7899. FUNC_ARGS funcArgs =
  7900. {
  7901. MAKELONG (LINE_FUNC | ASYNC | 8, lSetupConference),
  7902. {
  7903. GetFunctionIndex(lineSetupConferencePostProcess),
  7904. (ULONG_PTR) hCall,
  7905. (ULONG_PTR) pt3Line->hLine,
  7906. hpConfCallHandle,
  7907. hpConsultCallHandle,
  7908. (ULONG_PTR) dwNumParties,
  7909. (ULONG_PTR) lpCallParams,
  7910. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  7911. },
  7912. {
  7913. Dword,
  7914. Dword,
  7915. Dword,
  7916. Dword,
  7917. Dword,
  7918. Dword,
  7919. lpSet_Struct,
  7920. Dword
  7921. }
  7922. };
  7923. if (!lpCallParams)
  7924. {
  7925. //
  7926. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7927. //
  7928. funcArgs.ArgTypes[6] = Dword;
  7929. funcArgs.Args[6] = TAPI_NO_DATA;
  7930. }
  7931. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LineSetupConference") );
  7932. if (FAILED(hr))
  7933. {
  7934. DeleteHandleTableEntry(hpConfCallHandle);
  7935. DeleteHandleTableEntry(hpConsultCallHandle);
  7936. }
  7937. return hr;
  7938. }
  7939. HRESULT
  7940. LineSetupTransfer(
  7941. HCALL hCall,
  7942. HCALL *phConsultCall,
  7943. LPLINECALLPARAMS const lpCallParams
  7944. )
  7945. {
  7946. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR)phConsultCall);
  7947. FUNC_ARGS funcArgs =
  7948. {
  7949. MAKELONG (LINE_FUNC | ASYNC | 5, lSetupTransfer),
  7950. {
  7951. GetFunctionIndex(lineMakeCallPostProcess),
  7952. (ULONG_PTR) hCall,
  7953. hpConsultCallHandle,
  7954. (ULONG_PTR) lpCallParams,
  7955. 0xffffffff // dwAsciiCallParamsCodePage
  7956. },
  7957. {
  7958. Dword,
  7959. Dword,
  7960. Dword,
  7961. lpSet_Struct,
  7962. Dword
  7963. }
  7964. };
  7965. if (!lpCallParams)
  7966. {
  7967. //
  7968. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7969. //
  7970. funcArgs.ArgTypes[3] = Dword;
  7971. funcArgs.Args[3] = TAPI_NO_DATA;
  7972. }
  7973. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetupTransferW") );
  7974. if (FAILED(hr))
  7975. {
  7976. DeleteHandleTableEntry(hpConsultCallHandle);
  7977. hpConsultCallHandle = 0;
  7978. }
  7979. return hr;
  7980. }
  7981. HRESULT
  7982. LineSwapHold(
  7983. HCALL hActiveCall,
  7984. HCALL hHeldCall
  7985. )
  7986. {
  7987. FUNC_ARGS funcArgs =
  7988. {
  7989. MAKELONG (LINE_FUNC | ASYNC | 2, lSwapHold),
  7990. {
  7991. (ULONG_PTR) hActiveCall,
  7992. (ULONG_PTR) hHeldCall
  7993. },
  7994. {
  7995. Dword,
  7996. Dword
  7997. }
  7998. };
  7999. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSwapHold") );
  8000. }
  8001. LONG
  8002. WINAPI
  8003. lineUncompleteCall(
  8004. HLINE hLine,
  8005. DWORD dwCompletionID
  8006. )
  8007. {
  8008. FUNC_ARGS funcArgs =
  8009. {
  8010. MAKELONG (LINE_FUNC | ASYNC | 2, lUncompleteCall),
  8011. {
  8012. (ULONG_PTR) hLine,
  8013. dwCompletionID
  8014. },
  8015. {
  8016. Dword,
  8017. Dword
  8018. }
  8019. };
  8020. return (DOFUNC (&funcArgs, "lineUncompleteCall"));
  8021. }
  8022. HRESULT
  8023. LineUnhold(
  8024. HCALL hCall
  8025. )
  8026. {
  8027. FUNC_ARGS funcArgs =
  8028. {
  8029. MAKELONG (LINE_FUNC | ASYNC | 1, lUnhold),
  8030. {
  8031. (ULONG_PTR) hCall
  8032. },
  8033. {
  8034. Dword
  8035. }
  8036. };
  8037. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineUnhold") );
  8038. }
  8039. HRESULT
  8040. LineUnpark(
  8041. HLINE hLine,
  8042. DWORD dwAddressID,
  8043. HCALL *phCall,
  8044. LPCWSTR lpszDestAddress
  8045. )
  8046. {
  8047. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  8048. FUNC_ARGS funcArgs =
  8049. {
  8050. MAKELONG (LINE_FUNC | ASYNC | 5, lUnpark),
  8051. {
  8052. GetFunctionIndex(lineMakeCallPostProcess),
  8053. (ULONG_PTR) hLine,
  8054. dwAddressID,
  8055. hpCallHandle,
  8056. (ULONG_PTR) lpszDestAddress
  8057. },
  8058. {
  8059. Dword,
  8060. Dword,
  8061. Dword,
  8062. Dword,
  8063. lpszW
  8064. }
  8065. };
  8066. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LineUnpark") );
  8067. if (FAILED(hr))
  8068. {
  8069. DeleteHandleTableEntry(hpCallHandle);
  8070. }
  8071. return hr;
  8072. }
  8073. //
  8074. // ------------------------------- phoneXxx -----------------------------------
  8075. //
  8076. ///////////////////////////////////////////////////////////////////////////////
  8077. //
  8078. // PhoneClose
  8079. //
  8080. //
  8081. // Closes the phone specified by hPhone, the mode of hash table clean up is
  8082. // described by bCleanHashTableOnFailure
  8083. //
  8084. // Arguments:
  8085. //
  8086. // HPHONE hPhone -- handle of the phone to close
  8087. //
  8088. // BOOL bCleanHashTableOnFailure -- boolean that specifies how phone
  8089. // hash table should be cleaned:
  8090. //
  8091. // FALSE -- remove hash table entry only if the call succeeds. The caller
  8092. // function will then have the opportunity to perform transaction-like
  8093. // error handling -- it could recover the state from before the function
  8094. // was called, so it could return an error which would mean that the state
  8095. // remained unchanged
  8096. //
  8097. // TRUE -- clean table even if tapisrv call fails. The caller will not be
  8098. // able to recover the original state in case of failure. this is ok for
  8099. // the functions that do not provide full error handling for PhoneClose
  8100. //
  8101. HRESULT
  8102. PhoneClose(
  8103. HPHONE hPhone,
  8104. BOOL bCleanHashTableOnFailure // = TRUE
  8105. )
  8106. {
  8107. LOG((TL_INFO, "PhoneClose - enter. hPhone[%p] CleanOnError[%d]",
  8108. hPhone, bCleanHashTableOnFailure));
  8109. LONG lResult;
  8110. FUNC_ARGS funcArgs =
  8111. {
  8112. MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
  8113. {
  8114. (ULONG_PTR) hPhone
  8115. },
  8116. {
  8117. Dword
  8118. }
  8119. };
  8120. gpPhoneHashTable->Lock();
  8121. lResult = (DOFUNC (&funcArgs, "phoneClose"));
  8122. //
  8123. // clean hash table entry if needed
  8124. //
  8125. if ( (0 == lResult) || bCleanHashTableOnFailure )
  8126. {
  8127. LOG((TL_INFO, "PhoneClose - removing phone's hash table entry"));
  8128. gpPhoneHashTable->Remove( (ULONG_PTR)(hPhone) );
  8129. }
  8130. gpPhoneHashTable->Unlock();
  8131. //
  8132. // get hr error code
  8133. //
  8134. HRESULT hr = mapTAPIErrorCode( lResult );
  8135. LOG((TL_INFO, "PhoneClose - exit. hr = %lx", hr));
  8136. return hr;
  8137. }
  8138. LONG
  8139. WINAPI
  8140. phoneConfigDialogW(
  8141. DWORD dwDeviceID,
  8142. HWND hwndOwner,
  8143. LPCWSTR lpszDeviceClass
  8144. )
  8145. {
  8146. LONG lResult;
  8147. HANDLE hDll;
  8148. TUISPIPROC pfnTUISPI_phoneConfigDialog;
  8149. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, (UINT) -1))
  8150. {
  8151. return PHONEERR_INVALPOINTER;
  8152. }
  8153. if ((lResult = LoadUIDll(
  8154. hwndOwner,
  8155. dwDeviceID,
  8156. TUISPIDLL_OBJECT_PHONEID,
  8157. &hDll,
  8158. gszTUISPI_phoneConfigDialog,
  8159. &pfnTUISPI_phoneConfigDialog
  8160. )) == 0)
  8161. {
  8162. LOG((TL_INFO, "Calling TUISPI_phoneConfigDialog..."));
  8163. lResult = ((TUIPHONECONFIGPROC)(*pfnTUISPI_phoneConfigDialog))(
  8164. TUISPIDLLCallback,
  8165. dwDeviceID,
  8166. (HWND)hwndOwner,
  8167. (char *)lpszDeviceClass
  8168. );
  8169. #if DBG
  8170. {
  8171. char szResult[32];
  8172. LOG((TL_INFO,
  8173. "TUISPI_phoneConfigDialog: result = %s",
  8174. MapResultCodeToText (lResult, szResult)
  8175. ));
  8176. }
  8177. #endif
  8178. FreeLibrary ((HINSTANCE)hDll);
  8179. }
  8180. return lResult;
  8181. }
  8182. void
  8183. PASCAL
  8184. phoneDevSpecificPostProcess(
  8185. PASYNCEVENTMSG pMsg
  8186. )
  8187. {
  8188. LOG((TL_TRACE, "phoneDevSpecificPostProcess: enter"));
  8189. LOG((TL_INFO,
  8190. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  8191. pMsg->Param1,
  8192. pMsg->Param2,
  8193. pMsg->Param3,
  8194. pMsg->Param4
  8195. ));
  8196. if (pMsg->Param2 == 0)
  8197. {
  8198. DWORD dwSize = pMsg->Param4;
  8199. LPBYTE pParams =
  8200. (LPBYTE) GetHandleTableEntry(pMsg->Param3);
  8201. __try
  8202. {
  8203. {
  8204. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  8205. }
  8206. }
  8207. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  8208. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  8209. {
  8210. pMsg->Param2 = PHONEERR_INVALPOINTER;
  8211. LOG((TL_WARN,
  8212. "phoneDevSpecificPostProcess: failed to copy %ld(10) bytes, %p -> %p."
  8213. "PHONEERR_INVALPOINTER",
  8214. dwSize, (LPBYTE) (pMsg + 1), pParams));
  8215. }
  8216. }
  8217. }
  8218. HRESULT
  8219. WINAPI
  8220. phoneDevSpecific(
  8221. HPHONE hPhone,
  8222. LPVOID lpParams,
  8223. DWORD dwSize
  8224. )
  8225. {
  8226. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  8227. FUNC_ARGS funcArgs =
  8228. {
  8229. MAKELONG (PHONE_FUNC | ASYNC | 5, pDevSpecific),
  8230. {
  8231. GetFunctionIndex(phoneDevSpecificPostProcess),
  8232. (ULONG_PTR) hPhone,
  8233. hpParams, // passed as Dword for post processing
  8234. (ULONG_PTR) lpParams, // passed as LpSet_Xxx for IsValidPtr chk
  8235. dwSize
  8236. },
  8237. {
  8238. Dword,
  8239. Dword,
  8240. Dword,
  8241. lpSet_SizeToFollow,
  8242. Size
  8243. }
  8244. };
  8245. LONG lResult = DOFUNC (&funcArgs, "phoneDevSpecific");
  8246. //
  8247. // remove the handle table entry if failed. otherwise the LINE_REPLY will
  8248. // do this.
  8249. //
  8250. HRESULT hr = E_FAIL;
  8251. if (lResult <= 0)
  8252. {
  8253. DeleteHandleTableEntry(hpParams);
  8254. hpParams = 0;
  8255. hr = mapTAPIErrorCode(lResult);
  8256. }
  8257. else
  8258. {
  8259. //
  8260. // block to see if the operation succeeds
  8261. //
  8262. hr = WaitForPhoneReply(lResult);
  8263. }
  8264. return hr;
  8265. }
  8266. HRESULT
  8267. PhoneSetStatusMessages(
  8268. T3PHONE * pt3Phone,
  8269. DWORD dwPhoneStates,
  8270. DWORD dwButtonModes,
  8271. DWORD dwButtonStates
  8272. )
  8273. {
  8274. FUNC_ARGS funcArgs =
  8275. {
  8276. MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
  8277. {
  8278. (ULONG_PTR) pt3Phone->hPhone,
  8279. dwPhoneStates,
  8280. dwButtonModes,
  8281. dwButtonStates
  8282. },
  8283. {
  8284. Dword,
  8285. Dword,
  8286. Dword,
  8287. Dword
  8288. }
  8289. };
  8290. return mapTAPIErrorCode( DOFUNC (&funcArgs, "phoneSetStatusMessages") );
  8291. }
  8292. HRESULT
  8293. PhoneGetButtonInfo(
  8294. HPHONE hPhone,
  8295. DWORD dwButtonLampID,
  8296. LPPHONEBUTTONINFO * ppButtonInfo
  8297. )
  8298. {
  8299. LONG lResult;
  8300. *ppButtonInfo = (LPPHONEBUTTONINFO) ClientAlloc( sizeof(PHONEBUTTONINFO) + 500 );
  8301. if (NULL == *ppButtonInfo)
  8302. {
  8303. return E_OUTOFMEMORY;
  8304. }
  8305. (*ppButtonInfo)->dwTotalSize = sizeof(PHONEBUTTONINFO) + 500;
  8306. FUNC_ARGS funcArgs =
  8307. {
  8308. MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
  8309. {
  8310. (ULONG_PTR) hPhone,
  8311. dwButtonLampID,
  8312. (ULONG_PTR) *ppButtonInfo
  8313. },
  8314. {
  8315. Dword,
  8316. Dword,
  8317. lpGet_Struct
  8318. }
  8319. };
  8320. while (TRUE)
  8321. {
  8322. lResult = DOFUNC (&funcArgs, "phoneGetButtonInfo");
  8323. if ((0 == lResult) && ((*ppButtonInfo)->dwNeededSize > (*ppButtonInfo)->dwTotalSize))
  8324. {
  8325. DWORD dwSize = (*ppButtonInfo)->dwNeededSize;
  8326. ClientFree( *ppButtonInfo );
  8327. *ppButtonInfo = (LPPHONEBUTTONINFO) ClientAlloc( dwSize );
  8328. if (NULL == *ppButtonInfo)
  8329. {
  8330. return E_OUTOFMEMORY;
  8331. }
  8332. (*ppButtonInfo)->dwTotalSize = dwSize;
  8333. funcArgs.Args[2] = (ULONG_PTR)*ppButtonInfo;
  8334. }
  8335. else
  8336. {
  8337. break;
  8338. }
  8339. }
  8340. return mapTAPIErrorCode(lResult);
  8341. }
  8342. LONG
  8343. WINAPI
  8344. phoneGetData(
  8345. HPHONE hPhone,
  8346. DWORD dwDataID,
  8347. LPVOID lpData,
  8348. DWORD dwSize
  8349. )
  8350. {
  8351. FUNC_ARGS funcArgs =
  8352. {
  8353. MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
  8354. {
  8355. (ULONG_PTR) hPhone,
  8356. dwDataID,
  8357. (ULONG_PTR) lpData,
  8358. dwSize
  8359. },
  8360. {
  8361. Dword,
  8362. Dword,
  8363. lpGet_SizeToFollow,
  8364. Size
  8365. }
  8366. };
  8367. return (DOFUNC (&funcArgs, "phoneGetData"));
  8368. }
  8369. HRESULT
  8370. PhoneGetDevCapsWithAlloc(
  8371. HPHONEAPP hPhoneApp,
  8372. DWORD dwDeviceID,
  8373. DWORD dwAPIVersion,
  8374. LPPHONECAPS * ppPhoneCaps
  8375. )
  8376. {
  8377. LONG lResult;
  8378. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( sizeof(PHONECAPS) + 500 );
  8379. if (NULL == *ppPhoneCaps)
  8380. {
  8381. return E_OUTOFMEMORY;
  8382. }
  8383. (*ppPhoneCaps)->dwTotalSize = sizeof(PHONECAPS) + 500;
  8384. FUNC_ARGS funcArgs =
  8385. {
  8386. MAKELONG (PHONE_FUNC | SYNC | 5, pGetDevCaps),
  8387. {
  8388. (ULONG_PTR) hPhoneApp,
  8389. dwDeviceID,
  8390. dwAPIVersion,
  8391. 0,
  8392. (ULONG_PTR) *ppPhoneCaps
  8393. },
  8394. {
  8395. hXxxApp,
  8396. Dword,
  8397. Dword,
  8398. Dword,
  8399. lpGet_Struct
  8400. }
  8401. };
  8402. while (TRUE)
  8403. {
  8404. lResult = DOFUNC (&funcArgs, "phoneGetDevCaps");
  8405. if ((0 == lResult) && ((*ppPhoneCaps)->dwNeededSize > (*ppPhoneCaps)->dwTotalSize))
  8406. {
  8407. DWORD dwSize = (*ppPhoneCaps)->dwNeededSize;
  8408. ClientFree( *ppPhoneCaps );
  8409. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( dwSize );
  8410. if (NULL == *ppPhoneCaps)
  8411. {
  8412. return E_OUTOFMEMORY;
  8413. }
  8414. (*ppPhoneCaps)->dwTotalSize = dwSize;
  8415. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneCaps;
  8416. }
  8417. else
  8418. {
  8419. break;
  8420. }
  8421. }
  8422. return mapTAPIErrorCode(lResult);
  8423. }
  8424. HRESULT
  8425. PhoneGetDevCaps(
  8426. HPHONEAPP hPhoneApp,
  8427. DWORD dwDeviceID,
  8428. DWORD dwAPIVersion,
  8429. LPPHONECAPS * ppPhoneCaps
  8430. )
  8431. {
  8432. LONG lResult;
  8433. FUNC_ARGS funcArgs =
  8434. {
  8435. MAKELONG (PHONE_FUNC | SYNC | 5, pGetDevCaps),
  8436. {
  8437. (ULONG_PTR) hPhoneApp,
  8438. dwDeviceID,
  8439. dwAPIVersion,
  8440. 0,
  8441. (ULONG_PTR) *ppPhoneCaps
  8442. },
  8443. {
  8444. hXxxApp,
  8445. Dword,
  8446. Dword,
  8447. Dword,
  8448. lpGet_Struct
  8449. }
  8450. };
  8451. while (TRUE)
  8452. {
  8453. lResult = DOFUNC (&funcArgs, "phoneGetDevCaps");
  8454. if ((0 == lResult) && ((*ppPhoneCaps)->dwNeededSize > (*ppPhoneCaps)->dwTotalSize))
  8455. {
  8456. DWORD dwSize = (*ppPhoneCaps)->dwNeededSize;
  8457. ClientFree( *ppPhoneCaps );
  8458. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( dwSize );
  8459. if (NULL == *ppPhoneCaps)
  8460. {
  8461. return E_OUTOFMEMORY;
  8462. }
  8463. (*ppPhoneCaps)->dwTotalSize = dwSize;
  8464. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneCaps;
  8465. }
  8466. else
  8467. {
  8468. break;
  8469. }
  8470. }
  8471. return mapTAPIErrorCode(lResult);
  8472. }
  8473. HRESULT
  8474. PhoneGetDisplay(
  8475. HPHONE hPhone,
  8476. LPVARSTRING * ppDisplay
  8477. )
  8478. {
  8479. LONG lResult;
  8480. *ppDisplay = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  8481. if (NULL == *ppDisplay)
  8482. {
  8483. return E_OUTOFMEMORY;
  8484. }
  8485. (*ppDisplay)->dwTotalSize = sizeof (VARSTRING) + 500;
  8486. FUNC_ARGS funcArgs =
  8487. {
  8488. MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
  8489. {
  8490. (ULONG_PTR) hPhone,
  8491. (ULONG_PTR) *ppDisplay
  8492. },
  8493. {
  8494. Dword,
  8495. lpGet_Struct
  8496. }
  8497. };
  8498. LOG((TL_TRACE, "PhoneGetDisplay - enter"));
  8499. LOG((TL_INFO, " hPhone ---------->%lx", hPhone));
  8500. LOG((TL_INFO, " ppDisplay ------->%p", ppDisplay));
  8501. while ( TRUE )
  8502. {
  8503. lResult = DOFUNC (&funcArgs, "phoneGetDisplay");
  8504. if ((lResult == 0) && ((*ppDisplay)->dwNeededSize > (*ppDisplay)->dwTotalSize))
  8505. {
  8506. DWORD dwSize = (*ppDisplay)->dwNeededSize;
  8507. ClientFree(*ppDisplay);
  8508. *ppDisplay = (LPVARSTRING)ClientAlloc(dwSize);
  8509. if (NULL == *ppDisplay)
  8510. {
  8511. LOG((TL_ERROR, "PhoneGetDisplay exit - return E_OUTOFMEMORY"));
  8512. return E_OUTOFMEMORY;
  8513. }
  8514. (*ppDisplay)->dwTotalSize = dwSize;
  8515. funcArgs.Args[4] = (ULONG_PTR)*ppDisplay;
  8516. }
  8517. else
  8518. {
  8519. break;
  8520. }
  8521. }
  8522. LOG((TL_TRACE, "PhoneGetDisplay exit"));
  8523. return mapTAPIErrorCode( lResult );
  8524. }
  8525. HRESULT
  8526. PhoneGetGain(
  8527. HPHONE hPhone,
  8528. DWORD dwHookSwitchDev,
  8529. LPDWORD lpdwGain
  8530. )
  8531. {
  8532. FUNC_ARGS funcArgs =
  8533. {
  8534. MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
  8535. {
  8536. (ULONG_PTR) hPhone,
  8537. dwHookSwitchDev,
  8538. (ULONG_PTR) lpdwGain
  8539. },
  8540. {
  8541. Dword,
  8542. Dword,
  8543. lpDword
  8544. }
  8545. };
  8546. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetGain"));
  8547. }
  8548. HRESULT
  8549. PhoneGetHookSwitch(
  8550. HPHONE hPhone,
  8551. LPDWORD lpdwHookSwitchDevs
  8552. )
  8553. {
  8554. FUNC_ARGS funcArgs =
  8555. {
  8556. MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
  8557. {
  8558. (ULONG_PTR) hPhone,
  8559. (ULONG_PTR) lpdwHookSwitchDevs
  8560. },
  8561. {
  8562. Dword,
  8563. lpDword
  8564. }
  8565. };
  8566. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetHookSwitch"));
  8567. }
  8568. LONG
  8569. WINAPI
  8570. phoneGetIconW(
  8571. DWORD dwDeviceID,
  8572. LPCWSTR lpszDeviceClass,
  8573. LPHICON lphIcon
  8574. )
  8575. {
  8576. HICON hIcon;
  8577. FUNC_ARGS funcArgs =
  8578. {
  8579. MAKELONG (PHONE_FUNC | SYNC | 3, pGetIcon),
  8580. {
  8581. dwDeviceID,
  8582. (ULONG_PTR) lpszDeviceClass,
  8583. (ULONG_PTR) &hIcon
  8584. },
  8585. {
  8586. Dword,
  8587. lpszW,
  8588. lpDword
  8589. }
  8590. };
  8591. LONG lResult;
  8592. if (IsBadDwordPtr ((LPDWORD) lphIcon))
  8593. {
  8594. return PHONEERR_INVALPOINTER;
  8595. }
  8596. if (lpszDeviceClass == (LPCWSTR) NULL)
  8597. {
  8598. //
  8599. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  8600. //
  8601. funcArgs.ArgTypes[1] = Dword;
  8602. funcArgs.Args[1] = TAPI_NO_DATA;
  8603. }
  8604. if ((lResult = DOFUNC (&funcArgs, "phoneGetIcon")) == 0)
  8605. {
  8606. *lphIcon = hIcon;
  8607. }
  8608. return lResult;
  8609. }
  8610. HRESULT
  8611. PhoneGetID(
  8612. HPHONE hPhone,
  8613. LPVARSTRING * ppDeviceID,
  8614. LPCWSTR lpszDeviceClass
  8615. )
  8616. {
  8617. LONG lResult;
  8618. DWORD dwNumDevices;
  8619. DWORD dwDeviceId1, dwDeviceId2;
  8620. BOOL bWaveDevice = FALSE;
  8621. *ppDeviceID = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  8622. if (NULL == *ppDeviceID)
  8623. {
  8624. return E_OUTOFMEMORY;
  8625. }
  8626. (*ppDeviceID)->dwTotalSize = sizeof (VARSTRING) + 500;
  8627. FUNC_ARGS funcArgs =
  8628. {
  8629. MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
  8630. {
  8631. (ULONG_PTR) hPhone,
  8632. (ULONG_PTR) *ppDeviceID,
  8633. (ULONG_PTR) lpszDeviceClass
  8634. },
  8635. {
  8636. Dword,
  8637. lpGet_Struct,
  8638. lpszW
  8639. }
  8640. };
  8641. LOG((TL_TRACE, "PhoneGetID - enter"));
  8642. LOG((TL_INFO, " hPhone ---------->%lx", hPhone));
  8643. LOG((TL_INFO, " ppDeviceID ------>%p", ppDeviceID));
  8644. LOG((TL_INFO, " lpszDeviceClass ->%p", lpszDeviceClass));
  8645. //
  8646. // If the request is for a wave device, call PGetIDEx.
  8647. // This will return a device string ID which is guaranteed to be unique across
  8648. // all processes.
  8649. // Then we will convert the string ID to the correct device ID in the client process context.
  8650. //
  8651. if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
  8652. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  8653. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  8654. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  8655. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  8656. )
  8657. {
  8658. bWaveDevice = TRUE;
  8659. dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
  8660. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 3, pGetIDEx);
  8661. }
  8662. while ( TRUE )
  8663. {
  8664. lResult = DOFUNC (&funcArgs, bWaveDevice ? "phoneGetIDEx" : "phoneGetID");
  8665. if ((lResult == 0) && ((*ppDeviceID)->dwNeededSize > (*ppDeviceID)->dwTotalSize))
  8666. {
  8667. DWORD dwSize = (*ppDeviceID)->dwNeededSize;
  8668. ClientFree(*ppDeviceID);
  8669. *ppDeviceID = (LPVARSTRING)ClientAlloc(dwSize);
  8670. if (NULL == *ppDeviceID)
  8671. {
  8672. LOG((TL_ERROR, "PhoneGetID exit - return LINEERR_NOMEM"));
  8673. return E_OUTOFMEMORY;
  8674. }
  8675. (*ppDeviceID)->dwTotalSize = dwSize;
  8676. funcArgs.Args[1] = (ULONG_PTR)*ppDeviceID;
  8677. }
  8678. else
  8679. {
  8680. break;
  8681. }
  8682. }
  8683. if (bWaveDevice && lResult == 0)
  8684. {
  8685. //
  8686. // We got the string ID(s), now we need to convert them to numeric device ID(s)
  8687. //
  8688. BOOL bConversionOk;
  8689. if ( dwNumDevices == 1 )
  8690. {
  8691. bConversionOk = WaveStringIdToDeviceId (
  8692. (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset),
  8693. lpszDeviceClass,
  8694. &dwDeviceId1);
  8695. }
  8696. else
  8697. {
  8698. _ASSERTE(dwNumDevices == 2);
  8699. //
  8700. // for "wave/in/out", we get back two devices from tapisrv -> convert both
  8701. //
  8702. LPWSTR szString1 = (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset);
  8703. // first convert the wave/in device
  8704. bConversionOk = WaveStringIdToDeviceId (
  8705. szString1,
  8706. L"wave/in",
  8707. &dwDeviceId1);
  8708. // next convert the wave/out device
  8709. bConversionOk = bConversionOk && WaveStringIdToDeviceId (
  8710. szString1 + wcslen(szString1),
  8711. L"wave/out",
  8712. &dwDeviceId2);
  8713. }
  8714. if (!bConversionOk)
  8715. {
  8716. LOG((TL_ERROR, "PhoneGetID - WaveStringIdToDeviceId failed"));
  8717. ClientFree(*ppDeviceID);
  8718. *ppDeviceID = NULL;
  8719. lResult = LINEERR_OPERATIONFAILED;
  8720. }
  8721. else
  8722. {
  8723. //
  8724. // conversion succeeded, now fill the VARSTRING to be returned to the caller
  8725. //
  8726. (*ppDeviceID)->dwNeededSize = (*ppDeviceID)->dwUsedSize =
  8727. sizeof(VARSTRING) + sizeof(DWORD) * dwNumDevices;
  8728. (*ppDeviceID)->dwStringFormat = STRINGFORMAT_BINARY;
  8729. (*ppDeviceID)->dwStringSize = sizeof(DWORD) * dwNumDevices;
  8730. (*ppDeviceID)->dwStringOffset = sizeof(VARSTRING);
  8731. *(DWORD *)((*ppDeviceID) + 1) = dwDeviceId1;
  8732. if (dwNumDevices == 2)
  8733. *((DWORD *)((*ppDeviceID) + 1) + 1) = dwDeviceId2;
  8734. }
  8735. }
  8736. LOG((TL_TRACE, "PhoneGetID exit - return %lx", lResult));
  8737. return mapTAPIErrorCode( lResult );
  8738. }
  8739. HRESULT
  8740. PhoneGetLamp(
  8741. HPHONE hPhone,
  8742. DWORD dwButtonLampID,
  8743. LPDWORD lpdwLampMode
  8744. )
  8745. {
  8746. FUNC_ARGS funcArgs =
  8747. {
  8748. MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
  8749. {
  8750. (ULONG_PTR) hPhone,
  8751. dwButtonLampID,
  8752. (ULONG_PTR) lpdwLampMode
  8753. },
  8754. {
  8755. Dword,
  8756. Dword,
  8757. lpDword
  8758. }
  8759. };
  8760. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetLamp"));
  8761. }
  8762. HRESULT
  8763. PhoneGetRing(
  8764. HPHONE hPhone,
  8765. LPDWORD lpdwRingMode,
  8766. LPDWORD lpdwVolume
  8767. )
  8768. {
  8769. FUNC_ARGS funcArgs =
  8770. {
  8771. MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
  8772. {
  8773. (ULONG_PTR) hPhone,
  8774. (ULONG_PTR) lpdwRingMode,
  8775. (ULONG_PTR) lpdwVolume
  8776. },
  8777. {
  8778. Dword,
  8779. lpDword,
  8780. lpDword
  8781. }
  8782. };
  8783. if (lpdwRingMode == lpdwVolume)
  8784. {
  8785. return E_POINTER;
  8786. }
  8787. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetRing"));
  8788. }
  8789. HRESULT
  8790. PhoneGetStatusWithAlloc(
  8791. HPHONE hPhone,
  8792. LPPHONESTATUS *ppPhoneStatus
  8793. )
  8794. {
  8795. LONG lResult;
  8796. *ppPhoneStatus = (LPPHONESTATUS) ClientAlloc( sizeof(PHONESTATUS) + 500 );
  8797. if (NULL == *ppPhoneStatus)
  8798. {
  8799. return E_OUTOFMEMORY;
  8800. }
  8801. (*ppPhoneStatus)->dwTotalSize = sizeof(PHONESTATUS) + 500;
  8802. FUNC_ARGS funcArgs =
  8803. {
  8804. MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
  8805. {
  8806. (ULONG_PTR) hPhone,
  8807. (ULONG_PTR) *ppPhoneStatus
  8808. },
  8809. {
  8810. Dword,
  8811. lpGet_Struct
  8812. }
  8813. };
  8814. while (TRUE)
  8815. {
  8816. lResult = DOFUNC (&funcArgs, "phoneGetStatus");
  8817. if ((0 == lResult) && ((*ppPhoneStatus)->dwNeededSize > (*ppPhoneStatus)->dwTotalSize))
  8818. {
  8819. DWORD dwSize = (*ppPhoneStatus)->dwNeededSize;
  8820. ClientFree( *ppPhoneStatus );
  8821. *ppPhoneStatus = (LPPHONESTATUS) ClientAlloc( dwSize );
  8822. if (NULL == *ppPhoneStatus)
  8823. {
  8824. return E_OUTOFMEMORY;
  8825. }
  8826. (*ppPhoneStatus)->dwTotalSize = dwSize;
  8827. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneStatus;
  8828. }
  8829. else
  8830. {
  8831. break;
  8832. }
  8833. }
  8834. return mapTAPIErrorCode(lResult);
  8835. }
  8836. LONG
  8837. WINAPI
  8838. phoneGetStatusMessages(
  8839. HPHONE hPhone,
  8840. LPDWORD lpdwPhoneStates,
  8841. LPDWORD lpdwButtonModes,
  8842. LPDWORD lpdwButtonStates
  8843. )
  8844. {
  8845. FUNC_ARGS funcArgs =
  8846. {
  8847. MAKELONG (PHONE_FUNC | SYNC | 4, pGetStatusMessages),
  8848. {
  8849. (ULONG_PTR) hPhone,
  8850. (ULONG_PTR) lpdwPhoneStates,
  8851. (ULONG_PTR) lpdwButtonModes,
  8852. (ULONG_PTR) lpdwButtonStates
  8853. },
  8854. {
  8855. Dword,
  8856. lpDword,
  8857. lpDword,
  8858. lpDword
  8859. }
  8860. };
  8861. if (lpdwPhoneStates == lpdwButtonModes ||
  8862. lpdwPhoneStates == lpdwButtonStates ||
  8863. lpdwButtonModes == lpdwButtonStates)
  8864. {
  8865. return PHONEERR_INVALPOINTER;
  8866. }
  8867. return (DOFUNC (&funcArgs, "phoneGetStatusMessages"));
  8868. }
  8869. HRESULT
  8870. PhoneGetVolume(
  8871. HPHONE hPhone,
  8872. DWORD dwHookSwitchDev,
  8873. LPDWORD lpdwVolume
  8874. )
  8875. {
  8876. FUNC_ARGS funcArgs =
  8877. {
  8878. MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
  8879. {
  8880. (ULONG_PTR) hPhone,
  8881. dwHookSwitchDev,
  8882. (ULONG_PTR) lpdwVolume
  8883. },
  8884. {
  8885. Dword,
  8886. Dword,
  8887. lpDword
  8888. }
  8889. };
  8890. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetVolume"));
  8891. }
  8892. HRESULT
  8893. PhoneNegotiateAPIVersion(
  8894. HPHONEAPP hPhoneApp,
  8895. DWORD dwDeviceID,
  8896. LPDWORD lpdwAPIVersion
  8897. )
  8898. {
  8899. PHONEEXTENSIONID PED;
  8900. FUNC_ARGS funcArgs =
  8901. {
  8902. MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
  8903. {
  8904. (ULONG_PTR) hPhoneApp,
  8905. dwDeviceID,
  8906. TAPI_VERSION1_0,
  8907. TAPI_VERSION_CURRENT,
  8908. (ULONG_PTR) lpdwAPIVersion,
  8909. (ULONG_PTR) &PED,
  8910. (ULONG_PTR) sizeof(PHONEEXTENSIONID)
  8911. },
  8912. {
  8913. hXxxApp,
  8914. Dword,
  8915. Dword,
  8916. Dword,
  8917. lpDword,
  8918. lpGet_SizeToFollow,
  8919. Size
  8920. }
  8921. };
  8922. return mapTAPIErrorCode( DOFUNC (&funcArgs, "phoneNegotiateAPIVersion") );
  8923. }
  8924. LONG
  8925. WINAPI
  8926. phoneNegotiateExtVersion(
  8927. HPHONEAPP hPhoneApp,
  8928. DWORD dwDeviceID,
  8929. DWORD dwAPIVersion,
  8930. DWORD dwExtLowVersion,
  8931. DWORD dwExtHighVersion,
  8932. LPDWORD lpdwExtVersion
  8933. )
  8934. {
  8935. FUNC_ARGS funcArgs =
  8936. {
  8937. MAKELONG (PHONE_FUNC | SYNC | 6, pNegotiateExtVersion),
  8938. {
  8939. (ULONG_PTR) hPhoneApp,
  8940. dwDeviceID,
  8941. dwAPIVersion,
  8942. dwExtLowVersion,
  8943. dwExtHighVersion,
  8944. (ULONG_PTR) lpdwExtVersion
  8945. },
  8946. {
  8947. hXxxApp,
  8948. Dword,
  8949. Dword,
  8950. Dword,
  8951. Dword,
  8952. lpDword
  8953. }
  8954. };
  8955. return (DOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
  8956. }
  8957. HRESULT
  8958. PhoneOpen(
  8959. HPHONEAPP hPhoneApp,
  8960. DWORD dwDeviceID,
  8961. T3PHONE * pt3Phone,
  8962. DWORD dwAPIVersion,
  8963. DWORD dwPrivilege
  8964. )
  8965. {
  8966. HRESULT hr;
  8967. FUNC_ARGS funcArgs =
  8968. {
  8969. MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
  8970. {
  8971. (ULONG_PTR) hPhoneApp,
  8972. dwDeviceID,
  8973. (ULONG_PTR) &(pt3Phone->hPhone),
  8974. dwAPIVersion,
  8975. 0,
  8976. 0,
  8977. dwPrivilege,
  8978. 0, // PHONEOPEN_PARAMS.hRemotePhone
  8979. },
  8980. {
  8981. hXxxApp,
  8982. Dword,
  8983. lpDword,
  8984. Dword,
  8985. Dword,
  8986. Dword,
  8987. Dword,
  8988. Dword
  8989. }
  8990. };
  8991. gpPhoneHashTable->Lock();
  8992. hr = ( DOFUNC (&funcArgs, "phoneOpen") );
  8993. if ( 0 == hr )
  8994. {
  8995. #ifdef USE_PHONEMSP
  8996. gpPhoneHashTable->Insert( (ULONG_PTR)(pt3Phone->hPhone), (ULONG_PTR)(pt3Phone->pMSPCall) );
  8997. #else
  8998. gpPhoneHashTable->Insert( (ULONG_PTR)(pt3Phone->hPhone), (ULONG_PTR)(pt3Phone->pPhone) );
  8999. #endif USE_PHONEMSP
  9000. }
  9001. gpPhoneHashTable->Unlock();
  9002. return mapTAPIErrorCode( hr );
  9003. }
  9004. HRESULT
  9005. PhoneSetButtonInfo(
  9006. HPHONE hPhone,
  9007. DWORD dwButtonLampID,
  9008. LPPHONEBUTTONINFO const pButtonInfo
  9009. )
  9010. {
  9011. FUNC_ARGS funcArgs =
  9012. {
  9013. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetButtonInfo),
  9014. {
  9015. (ULONG_PTR) hPhone,
  9016. dwButtonLampID,
  9017. (ULONG_PTR) pButtonInfo
  9018. },
  9019. {
  9020. Dword,
  9021. Dword,
  9022. lpSet_Struct
  9023. }
  9024. };
  9025. LONG lResult = DOFUNC (&funcArgs, "phoneSetButtonInfo");
  9026. if (lResult > 0) // async reply
  9027. {
  9028. return WaitForPhoneReply( lResult );
  9029. }
  9030. else
  9031. {
  9032. return mapTAPIErrorCode( lResult );
  9033. }
  9034. }
  9035. LONG
  9036. WINAPI
  9037. phoneSetData(
  9038. HPHONE hPhone,
  9039. DWORD dwDataID,
  9040. LPVOID const lpData,
  9041. DWORD dwSize
  9042. )
  9043. {
  9044. FUNC_ARGS funcArgs =
  9045. {
  9046. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetData),
  9047. {
  9048. (ULONG_PTR) hPhone,
  9049. dwDataID,
  9050. (ULONG_PTR) lpData,
  9051. dwSize
  9052. },
  9053. {
  9054. Dword,
  9055. Dword,
  9056. lpSet_SizeToFollow,
  9057. Size
  9058. }
  9059. };
  9060. return (DOFUNC (&funcArgs, "phoneSetData"));
  9061. }
  9062. HRESULT
  9063. PhoneSetDisplay(
  9064. HPHONE hPhone,
  9065. DWORD dwRow,
  9066. DWORD dwColumn,
  9067. LPCSTR lpsDisplay,
  9068. DWORD dwSize
  9069. )
  9070. {
  9071. FUNC_ARGS funcArgs =
  9072. {
  9073. MAKELONG (PHONE_FUNC | ASYNC | 5, pSetDisplay),
  9074. {
  9075. (ULONG_PTR) hPhone,
  9076. dwRow,
  9077. dwColumn,
  9078. (ULONG_PTR) lpsDisplay,
  9079. dwSize
  9080. },
  9081. {
  9082. Dword,
  9083. Dword,
  9084. Dword,
  9085. lpSet_SizeToFollow,
  9086. Size
  9087. }
  9088. };
  9089. LONG lResult = DOFUNC (&funcArgs, "phoneSetDisplay");
  9090. if (lResult > 0) // async reply
  9091. {
  9092. return WaitForPhoneReply( lResult );
  9093. }
  9094. else
  9095. {
  9096. return mapTAPIErrorCode( lResult );
  9097. }
  9098. }
  9099. HRESULT
  9100. PhoneSetGain(
  9101. HPHONE hPhone,
  9102. DWORD dwHookSwitchDev,
  9103. DWORD dwGain
  9104. )
  9105. {
  9106. FUNC_ARGS funcArgs =
  9107. {
  9108. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetGain),
  9109. {
  9110. (ULONG_PTR) hPhone,
  9111. dwHookSwitchDev,
  9112. dwGain
  9113. },
  9114. {
  9115. Dword,
  9116. Dword,
  9117. Dword
  9118. }
  9119. };
  9120. LONG lResult = DOFUNC (&funcArgs, "phoneSetGain");
  9121. if (lResult > 0) // async reply
  9122. {
  9123. return WaitForPhoneReply( lResult );
  9124. }
  9125. else
  9126. {
  9127. return mapTAPIErrorCode( lResult );
  9128. }
  9129. }
  9130. HRESULT
  9131. PhoneSetHookSwitch(
  9132. HPHONE hPhone,
  9133. DWORD dwHookSwitchDevs,
  9134. DWORD dwHookSwitchMode
  9135. )
  9136. {
  9137. FUNC_ARGS funcArgs =
  9138. {
  9139. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetHookSwitch),
  9140. {
  9141. (ULONG_PTR) hPhone,
  9142. dwHookSwitchDevs,
  9143. dwHookSwitchMode
  9144. },
  9145. {
  9146. Dword,
  9147. Dword,
  9148. Dword
  9149. }
  9150. };
  9151. if (!(dwHookSwitchDevs & AllHookSwitchDevs) ||
  9152. (dwHookSwitchDevs & (~AllHookSwitchDevs)))
  9153. {
  9154. return mapTAPIErrorCode( PHONEERR_INVALHOOKSWITCHDEV );
  9155. }
  9156. if (!IsOnlyOneBitSetInDWORD (dwHookSwitchMode) ||
  9157. (dwHookSwitchMode & ~AllHookSwitchModes))
  9158. {
  9159. return mapTAPIErrorCode( PHONEERR_INVALHOOKSWITCHMODE );
  9160. }
  9161. LONG lResult = DOFUNC (&funcArgs, "phoneSetHookSwitch");
  9162. if (lResult > 0) // async reply
  9163. {
  9164. return WaitForPhoneReply( lResult );
  9165. }
  9166. else
  9167. {
  9168. return mapTAPIErrorCode( lResult );
  9169. }
  9170. }
  9171. HRESULT
  9172. PhoneSetLamp(
  9173. HPHONE hPhone,
  9174. DWORD dwButtonLampID,
  9175. DWORD dwLampMode
  9176. )
  9177. {
  9178. FUNC_ARGS funcArgs =
  9179. {
  9180. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetLamp),
  9181. {
  9182. (ULONG_PTR) hPhone,
  9183. dwButtonLampID,
  9184. dwLampMode
  9185. },
  9186. {
  9187. Dword,
  9188. Dword,
  9189. Dword
  9190. }
  9191. };
  9192. LONG lResult = DOFUNC (&funcArgs, "phoneSetRing");
  9193. if (lResult > 0) // async reply
  9194. {
  9195. return WaitForPhoneReply( lResult );
  9196. }
  9197. else
  9198. {
  9199. return mapTAPIErrorCode( lResult );
  9200. }
  9201. }
  9202. HRESULT
  9203. PhoneSetRing(
  9204. HPHONE hPhone,
  9205. DWORD dwRingMode,
  9206. DWORD dwVolume
  9207. )
  9208. {
  9209. FUNC_ARGS funcArgs =
  9210. {
  9211. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetRing),
  9212. {
  9213. (ULONG_PTR) hPhone,
  9214. dwRingMode,
  9215. dwVolume
  9216. },
  9217. {
  9218. Dword,
  9219. Dword,
  9220. Dword
  9221. }
  9222. };
  9223. LONG lResult = DOFUNC (&funcArgs, "phoneSetRing");
  9224. if (lResult > 0) // async reply
  9225. {
  9226. return WaitForPhoneReply( lResult );
  9227. }
  9228. else
  9229. {
  9230. return mapTAPIErrorCode( lResult );
  9231. }
  9232. }
  9233. LONG
  9234. WINAPI
  9235. phoneSetStatusMessages(
  9236. HPHONE hPhone,
  9237. DWORD dwPhoneStates,
  9238. DWORD dwButtonModes,
  9239. DWORD dwButtonStates
  9240. )
  9241. {
  9242. FUNC_ARGS funcArgs =
  9243. {
  9244. MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
  9245. {
  9246. (ULONG_PTR) hPhone,
  9247. dwPhoneStates,
  9248. dwButtonModes,
  9249. dwButtonStates
  9250. },
  9251. {
  9252. Dword,
  9253. Dword,
  9254. Dword,
  9255. Dword
  9256. }
  9257. };
  9258. return (DOFUNC (&funcArgs, "phoneSetStatusMessages"));
  9259. }
  9260. HRESULT
  9261. PhoneSetVolume(
  9262. HPHONE hPhone,
  9263. DWORD dwHookSwitchDev,
  9264. DWORD dwVolume
  9265. )
  9266. {
  9267. FUNC_ARGS funcArgs =
  9268. {
  9269. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetVolume),
  9270. {
  9271. (ULONG_PTR) hPhone,
  9272. dwHookSwitchDev,
  9273. dwVolume
  9274. },
  9275. {
  9276. Dword,
  9277. Dword,
  9278. Dword
  9279. }
  9280. };
  9281. LONG lResult = DOFUNC (&funcArgs, "phoneSetVolume");
  9282. if (lResult > 0) // async reply
  9283. {
  9284. return WaitForPhoneReply( lResult );
  9285. }
  9286. else
  9287. {
  9288. return mapTAPIErrorCode( lResult );
  9289. }
  9290. }
  9291. HRESULT
  9292. ProviderPrivateFactoryIdentify(
  9293. DWORD dwDeviceID,
  9294. GUID * pguid
  9295. )
  9296. {
  9297. FUNC_ARGS funcArgs =
  9298. {
  9299. MAKELONG (LINE_FUNC | SYNC | 3, xPrivateFactoryIdentify),
  9300. {
  9301. (ULONG_PTR) dwDeviceID,
  9302. (ULONG_PTR) pguid,
  9303. (ULONG_PTR) sizeof(GUID)
  9304. },
  9305. {
  9306. Dword,
  9307. lpGet_SizeToFollow,
  9308. Size
  9309. }
  9310. };
  9311. return mapTAPIErrorCode( DOFUNC (&funcArgs, "ProviderPrivateFactoryIdentify") );
  9312. }
  9313. HRESULT
  9314. ProviderPrivateChannelData(
  9315. DWORD dwDeviceID,
  9316. DWORD dwAddressID,
  9317. HCALL hCall,
  9318. HCALLHUB hCallHub,
  9319. DWORD dwType,
  9320. BYTE * pBuffer,
  9321. DWORD dwSize
  9322. )
  9323. {
  9324. HRESULT hr;
  9325. FUNC_ARGS funcArgs =
  9326. {
  9327. MAKELONG (LINE_FUNC | SYNC | 7, lDevSpecificEx),
  9328. {
  9329. dwDeviceID,
  9330. dwAddressID,
  9331. (ULONG_PTR)hCall,
  9332. (ULONG_PTR)hCallHub,
  9333. dwType,
  9334. (ULONG_PTR)pBuffer,
  9335. dwSize
  9336. },
  9337. {
  9338. Dword,
  9339. Dword,
  9340. Dword,
  9341. Dword,
  9342. Dword,
  9343. lpSet_SizeToFollow,
  9344. Size
  9345. }
  9346. };
  9347. return mapTAPIErrorCode( DOFUNC (&funcArgs, "ProviderPrivateChannelData") );
  9348. }
  9349. //
  9350. // ----------------------- Private support routines ---------------------------
  9351. //
  9352. void
  9353. FreeInitData(
  9354. PT3INIT_DATA pInitData
  9355. )
  9356. {
  9357. EnterCriticalSection (&gcsTapisrvCommunication);
  9358. if (pInitData && ( pInitData->dwKey != 0xefefefef ) )
  9359. {
  9360. pInitData->dwKey = 0xefefefef;
  9361. LeaveCriticalSection (&gcsTapisrvCommunication);
  9362. ClientFree (pInitData);
  9363. }
  9364. else
  9365. {
  9366. LeaveCriticalSection (&gcsTapisrvCommunication);
  9367. }
  9368. }
  9369. //////////////////////////////////////////////////////////////////
  9370. // Wait for a reply for async stuff
  9371. //
  9372. //////////////////////////////////////////////////////////////////
  9373. HRESULT
  9374. WaitForReply(
  9375. DWORD dwID
  9376. )
  9377. {
  9378. HRESULT hr = S_OK;
  9379. CAsyncRequestReply *pReply;
  9380. // Create a new request entry on the list
  9381. pReply = gpLineAsyncReplyList->addRequest( dwID );
  9382. if( NULL == pReply )
  9383. {
  9384. LOG((TL_INFO, "gpLineAsyncReplyList->addRequest failed"));
  9385. hr = E_OUTOFMEMORY;
  9386. }
  9387. else
  9388. {
  9389. // Now we wait to be signalled
  9390. hr = pReply->wait();
  9391. if (-1 == hr)
  9392. {
  9393. gpLineAsyncReplyList->remove (pReply);
  9394. }
  9395. // Cleanup
  9396. delete pReply;
  9397. // if we we didn't wait long enough for the asycnronous call to succeed.
  9398. if (-1 == hr)
  9399. return TAPI_E_TIMEOUT;
  9400. }
  9401. return mapTAPIErrorCode( hr );
  9402. }
  9403. HRESULT
  9404. WaitForPhoneReply(
  9405. DWORD dwID
  9406. )
  9407. {
  9408. HRESULT hr = S_OK;
  9409. CAsyncRequestReply *pReply;
  9410. // Create a new request entry on the list
  9411. pReply = gpPhoneAsyncReplyList->addRequest( dwID );
  9412. if( NULL == pReply )
  9413. {
  9414. LOG((TL_INFO, "gpPhoneAsyncReplyList->addRequest failed"));
  9415. hr = E_OUTOFMEMORY;
  9416. }
  9417. else
  9418. {
  9419. // Now we wait to be signalled
  9420. hr = pReply->wait();
  9421. if (-1 == hr)
  9422. {
  9423. gpPhoneAsyncReplyList->remove (pReply);
  9424. }
  9425. // Cleanup
  9426. delete pReply;
  9427. // if we we didn't wait long enough for the asycnronous call to succeed.
  9428. if (-1 == hr)
  9429. return TAPI_E_TIMEOUT;
  9430. }
  9431. return mapTAPIErrorCode( hr );
  9432. }
  9433. /////////////////////////////////////////////////////////////////////
  9434. // FindCallObject
  9435. //
  9436. // Finds the call object associated with an HCALL
  9437. //
  9438. // Returns TRUE if the call object is found, FALSE if not.
  9439. //////////////////////////////////////////////////////////////////////
  9440. BOOL
  9441. FindCallObject(
  9442. HCALL hCall,
  9443. CCall ** ppCall
  9444. )
  9445. {
  9446. HRESULT hr;
  9447. gpCallHashTable->Lock();
  9448. hr = gpCallHashTable->Find( (ULONG_PTR)hCall, (ULONG_PTR *)ppCall );
  9449. if (SUCCEEDED(hr))
  9450. {
  9451. (*ppCall)->AddRef();
  9452. gpCallHashTable->Unlock();
  9453. return TRUE;
  9454. }
  9455. gpCallHashTable->Unlock();
  9456. return FALSE;
  9457. }
  9458. /////////////////////////////////////////////////////////////////////
  9459. // FindAddressObject
  9460. //
  9461. // Finds the address object associated with an HLINE
  9462. //
  9463. // Returns TRUE if the line object is found, FALSE if not.
  9464. //////////////////////////////////////////////////////////////////////
  9465. BOOL
  9466. FindAddressObject(
  9467. HLINE hLine,
  9468. CAddress ** ppAddress
  9469. )
  9470. {
  9471. HRESULT hr;
  9472. gpLineHashTable->Lock();
  9473. hr = gpLineHashTable->Find( (ULONG_PTR)hLine, (ULONG_PTR *)ppAddress );
  9474. if ( SUCCEEDED(hr) )
  9475. {
  9476. (*ppAddress)->AddRef();
  9477. gpLineHashTable->Unlock();
  9478. return TRUE;
  9479. }
  9480. gpLineHashTable->Unlock();
  9481. return FALSE;
  9482. }
  9483. BOOL
  9484. FindAddressObjectWithDeviceID(
  9485. HLINE hLine,
  9486. DWORD dwAddressID,
  9487. CAddress ** ppAddress
  9488. )
  9489. {
  9490. HRESULT hr;
  9491. gpLineHashTable->Lock();
  9492. hr = gpLineHashTable->Find( (ULONG_PTR)hLine, (ULONG_PTR *)ppAddress );
  9493. if ( SUCCEEDED(hr) )
  9494. {
  9495. if ((*ppAddress)->GetAddressID() == dwAddressID)
  9496. {
  9497. (*ppAddress)->AddRef();
  9498. gpLineHashTable->Unlock();
  9499. return TRUE;
  9500. }
  9501. }
  9502. gpLineHashTable->Unlock();
  9503. return FALSE;
  9504. }
  9505. /////////////////////////////////////////////////////////////////////
  9506. // FindPhoneObject
  9507. //
  9508. // Finds the phone object associated with an HPHONE
  9509. //
  9510. // Returns TRUE if the phone object is found, FALSE if not.
  9511. //////////////////////////////////////////////////////////////////////
  9512. BOOL
  9513. FindPhoneObject(
  9514. HPHONE hPhone,
  9515. CPhone ** ppPhone
  9516. )
  9517. {
  9518. HRESULT hr;
  9519. gpPhoneHashTable->Lock();
  9520. hr = gpPhoneHashTable->Find( (ULONG_PTR)hPhone, (ULONG_PTR *)ppPhone );
  9521. if ( SUCCEEDED(hr) )
  9522. {
  9523. (*ppPhone)->AddRef();
  9524. gpPhoneHashTable->Unlock();
  9525. return TRUE;
  9526. }
  9527. gpPhoneHashTable->Unlock();
  9528. return FALSE;
  9529. }
  9530. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9531. //
  9532. // FindAgentHandlerObject
  9533. //
  9534. // Finds the Agent Handler object associated with an HLINE
  9535. //
  9536. // Returns TRUE if the line object is found, FALSE if not.
  9537. //
  9538. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9539. BOOL
  9540. FindAgentHandlerObject(
  9541. HLINE hLine,
  9542. CAgentHandler ** ppAgentHandler
  9543. )
  9544. {
  9545. HRESULT hr = FALSE;
  9546. gpAgentHandlerHashTable->Lock();
  9547. hr = gpAgentHandlerHashTable->Find( (ULONG_PTR)hLine, (ULONG_PTR *)ppAgentHandler );
  9548. if ( SUCCEEDED(hr) )
  9549. {
  9550. (*ppAgentHandler)->AddRef();
  9551. hr = TRUE;
  9552. }
  9553. else
  9554. {
  9555. hr = FALSE;
  9556. }
  9557. gpAgentHandlerHashTable->Unlock();
  9558. return hr;
  9559. }
  9560. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9561. //
  9562. // FindCallHubObject
  9563. //
  9564. // Finds the CallHub object based on the hCallHub
  9565. //
  9566. // Returns TRUE if the line object is found, FALSE if not.
  9567. //
  9568. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9569. BOOL
  9570. FindCallHubObject(
  9571. HCALLHUB hCallHub,
  9572. CCallHub ** ppCallHub
  9573. )
  9574. {
  9575. HRESULT hr = FALSE;
  9576. gpCallHubHashTable->Lock();
  9577. hr = gpCallHubHashTable->Find( (ULONG_PTR)hCallHub, (ULONG_PTR *)ppCallHub );
  9578. if ( SUCCEEDED(hr) )
  9579. {
  9580. try
  9581. {
  9582. (*ppCallHub)->AddRef();
  9583. hr = TRUE;
  9584. }
  9585. catch(...)
  9586. {
  9587. hr = FALSE;
  9588. }
  9589. }
  9590. else
  9591. {
  9592. hr = FALSE;
  9593. }
  9594. gpCallHubHashTable->Unlock();
  9595. return hr;
  9596. }
  9597. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9598. //
  9599. // CheckTapisrvCallhub
  9600. //
  9601. // Checks that at least one hCall that TAPISRV supports for a CallHub exists
  9602. // as a Call Objects.
  9603. // This is to ensure that we have one call obect to reference the hub, otherwise
  9604. // it can be released prematurely
  9605. //
  9606. // Returns S_OK if one exists, E_FAIL if all are missing
  9607. //
  9608. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9609. HRESULT
  9610. CheckTapisrvCallhub(HCALLHUB hCallHub)
  9611. {
  9612. LINECALLLIST * pCallHubList;
  9613. HCALL * phCalls;
  9614. DWORD dwCount;
  9615. CCall * pCall = NULL;
  9616. HRESULT hr = E_FAIL;
  9617. LOG((TL_INFO, "CheckTapisrvCallhub - hCallHub: %lx",hCallHub));
  9618. //
  9619. // get the list of hcalls
  9620. // related to this callhub
  9621. //
  9622. hr = LineGetHubRelatedCalls(
  9623. hCallHub,
  9624. 0,
  9625. &pCallHubList
  9626. );
  9627. if ( SUCCEEDED(hr) )
  9628. {
  9629. // Assume the worst..
  9630. hr = E_FAIL;
  9631. //
  9632. // get to the list of calls
  9633. //
  9634. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  9635. //
  9636. // the first call is actually the callhub
  9637. // check it against the handle we gave...
  9638. //
  9639. if (hCallHub == (HCALLHUB)(phCalls[0]))
  9640. {
  9641. //
  9642. // go through the call handles and try to find call objects
  9643. //
  9644. for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++)
  9645. {
  9646. //
  9647. // get the tapi3 call object
  9648. //
  9649. if ( FindCallObject(phCalls[dwCount], &pCall) )
  9650. {
  9651. // Found it - findcallobject addrefs, so release
  9652. pCall->Release();
  9653. LOG((TL_INFO, "CheckTapisrvCallhub - found hCall %lx", phCalls[dwCount]));
  9654. hr = S_OK;
  9655. break;
  9656. }
  9657. }
  9658. }
  9659. else
  9660. {
  9661. LOG((TL_INFO, "CheckTapisrvCallhub - returned callhub doesn't match"));
  9662. _ASSERTE(0);
  9663. hr = E_FAIL;
  9664. }
  9665. ClientFree( pCallHubList ); // Clean up
  9666. }
  9667. else
  9668. {
  9669. LOG((TL_INFO, "CheckTapisrvCallhub - LineGetHubRelatedCallsfailed"));
  9670. }
  9671. LOG((TL_TRACE, hr, "CheckTapisrvCallhub - exit"));
  9672. return hr;
  9673. }
  9674. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  9675. //
  9676. // ProcessEvent
  9677. // This processes messages from tapisrv
  9678. //
  9679. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  9680. HRESULT
  9681. ProcessMessage(
  9682. PT3INIT_DATA pInitData,
  9683. PASYNCEVENTMSG pParams
  9684. )
  9685. {
  9686. HRESULT hResult = S_OK;
  9687. LOG((TL_INFO, "In ProcessMessage - MsgType:%x", pParams->Msg));
  9688. switch( pParams->Msg )
  9689. {
  9690. case LINE_CALLSTATE:
  9691. {
  9692. hResult = HandleCallStateMessage( pParams );
  9693. break;
  9694. }
  9695. case LINE_CALLINFO:
  9696. {
  9697. hResult = HandleCallInfoMessage( pParams );
  9698. break;
  9699. }
  9700. case LINE_MONITORDIGITS:
  9701. {
  9702. hResult = HandleMonitorDigitsMessage( pParams );
  9703. break;
  9704. }
  9705. case LINE_SENDMSPDATA:
  9706. {
  9707. hResult = HandleSendMSPDataMessage( pParams );
  9708. break;
  9709. }
  9710. case LINE_DEVSPECIFICEX:
  9711. {
  9712. //HandlePrivateEventMessage( pParams );
  9713. break;
  9714. }
  9715. case LINE_LINEDEVSTATE:
  9716. {
  9717. CTAPI *pTapi = NULL;
  9718. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9719. {
  9720. pTapi = pInitData->pTAPI;
  9721. }
  9722. HandleLineDevStateMessage( pTapi, pParams );
  9723. break;
  9724. }
  9725. case LINE_ADDRESSSTATE:
  9726. {
  9727. HandleAddressStateMessage( pParams );
  9728. break;
  9729. }
  9730. case LINE_DEVSPECIFIC:
  9731. {
  9732. HandleLineDevSpecificMessage( pParams );
  9733. break;
  9734. }
  9735. case LINE_DEVSPECIFICFEATURE:
  9736. {
  9737. //HandleDevSpecificFeatureMessage( pParams );
  9738. break;
  9739. }
  9740. case LINE_GATHERDIGITS:
  9741. {
  9742. hResult = HandleGatherDigitsMessage( pParams );
  9743. break;
  9744. }
  9745. case LINE_GENERATE:
  9746. {
  9747. hResult = HandleLineGenerateMessage( pParams );
  9748. break;
  9749. }
  9750. case LINE_MONITORMEDIA:
  9751. {
  9752. HandleMonitorMediaMessage( pParams );
  9753. break;
  9754. }
  9755. case LINE_MONITORTONE:
  9756. {
  9757. HandleMonitorToneMessage( pParams );
  9758. break;
  9759. }
  9760. case LINE_CLOSE:
  9761. {
  9762. HandleLineCloseMessage( pParams );
  9763. break;
  9764. }
  9765. case LINE_AGENTSTATUS:
  9766. {
  9767. break;
  9768. }
  9769. case LINE_AGENTSTATUSEX:
  9770. {
  9771. HandleAgentStatusMessage(pParams);
  9772. break;
  9773. }
  9774. case LINE_AGENTSESSIONSTATUS:
  9775. {
  9776. HandleAgentSessionStatusMessage(pParams);
  9777. break;
  9778. }
  9779. case LINE_QUEUESTATUS:
  9780. {
  9781. HandleQueueStatusMessage(pParams);
  9782. break;
  9783. }
  9784. case LINE_QOSINFO:
  9785. {
  9786. hResult = HandleLineQOSInfoMessage( pParams );
  9787. break;
  9788. }
  9789. case LINE_APPNEWCALLHUB:
  9790. {
  9791. HRESULT hr;
  9792. CCallHub * pCallHub;
  9793. BOOL fAllCallsDisconnected;
  9794. hResult = CheckTapisrvCallhub((HCALLHUB)pParams->Param1);
  9795. if (SUCCEEDED(hResult))
  9796. {
  9797. CTAPI *pTapi = NULL;
  9798. //
  9799. // pInitData seems good?
  9800. //
  9801. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9802. {
  9803. //
  9804. // check the tapi object, and get an addref'ed copy if it is
  9805. // valid
  9806. //
  9807. if ( CTAPI::IsValidTapiObject(pInitData->pTAPI) )
  9808. {
  9809. //
  9810. // got a good, addref'ed object. keep it.
  9811. //
  9812. pTapi = pInitData->pTAPI;
  9813. }
  9814. }
  9815. hr = CCallHub::CreateTapisrvCallHub(
  9816. pTapi,
  9817. (HCALLHUB)pParams->Param1,
  9818. &pCallHub
  9819. );
  9820. if (!SUCCEEDED(hr))
  9821. {
  9822. LOG((TL_ERROR, "CreateTapisrvCallHub failed in LINE_APPNEWCALLHUB"));
  9823. }
  9824. else
  9825. {
  9826. //Send CHE_CALLHUBIDLE message if all the calls in the callhub are disconnected.
  9827. hr = pCallHub -> FindCallsDisconnected( &fAllCallsDisconnected );
  9828. if( hr == S_OK )
  9829. {
  9830. if( fAllCallsDisconnected == TRUE )
  9831. {
  9832. //
  9833. // tell the app
  9834. //
  9835. pCallHub -> SetState(CHS_IDLE);
  9836. }
  9837. }
  9838. pCallHub->Release();
  9839. }
  9840. //
  9841. // if we we got a good tapi object, we must release it now.
  9842. //
  9843. if (NULL != pTapi)
  9844. {
  9845. pTapi->Release();
  9846. pTapi = NULL;
  9847. }
  9848. }
  9849. break;
  9850. }
  9851. case LINE_GROUPSTATUS:
  9852. {
  9853. handleGroupStatusMessage(pParams);
  9854. break;
  9855. }
  9856. case LINE_PROXYSTATUS:
  9857. {
  9858. CTAPI *pTapi = NULL;
  9859. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9860. {
  9861. pTapi = pInitData->pTAPI;
  9862. }
  9863. QueueCallbackEvent( pTapi, pParams );
  9864. break;
  9865. }
  9866. case LINE_REPLY:
  9867. {
  9868. CAsyncRequestReply *pReply;
  9869. LOG((TL_INFO, "LINE_REPLY"));
  9870. // Add (or complete existing) response entry on the list
  9871. pReply = gpLineAsyncReplyList->addReply( pParams->Param1, (HRESULT) pParams->Param2 );
  9872. if(pReply==NULL)
  9873. {
  9874. LOG((TL_INFO, "gpLineAsyncReplyList->addReply failed"));
  9875. hResult = E_OUTOFMEMORY;
  9876. }
  9877. else
  9878. {
  9879. // Signal it to say we're done.
  9880. pReply->signal();
  9881. }
  9882. break;
  9883. }
  9884. case PHONE_REPLY:
  9885. {
  9886. CAsyncRequestReply *pReply;
  9887. LOG((TL_INFO, "PHONE_REPLY"));
  9888. // Add (or complete existing) response entry on the list
  9889. pReply = gpPhoneAsyncReplyList->addReply( pParams->Param1, (HRESULT) pParams->Param2 );
  9890. // Signal it to say we're done.
  9891. if(pReply == NULL )
  9892. {
  9893. LOG((TL_INFO, "gpPhoneAsyncReplyList->addReply failed"));
  9894. hResult = E_OUTOFMEMORY;
  9895. }
  9896. else
  9897. {
  9898. pReply->signal();
  9899. }
  9900. break;
  9901. }
  9902. case LINE_APPNEWCALL:
  9903. {
  9904. // LINE_APPNEWCALL is the first notification we get of
  9905. // a new call object. Create the call here, but
  9906. // don't notify the app until we get the first
  9907. // message about it.
  9908. CAddress * pAddress;
  9909. CCall * pCall = NULL;
  9910. if (FindAddressObjectWithDeviceID(
  9911. (HLINE) pParams->hDevice,
  9912. pParams->Param1,
  9913. &pAddress
  9914. ))
  9915. {
  9916. HRESULT hr;
  9917. LINECALLINFO * pCallInfo = NULL;
  9918. hr = LineGetCallInfo(
  9919. pParams->Param2,
  9920. &pCallInfo
  9921. );
  9922. if ( SUCCEEDED(hr) )
  9923. {
  9924. BOOL callExposeAndNotify = TRUE;
  9925. if ( pCallInfo->dwMediaMode & LINEMEDIAMODE_INTERACTIVEVOICE )
  9926. {
  9927. pCallInfo->dwMediaMode |= LINEMEDIAMODE_AUTOMATEDVOICE;
  9928. pCallInfo->dwMediaMode &= ~((DWORD)LINEMEDIAMODE_INTERACTIVEVOICE);
  9929. }
  9930. pCallInfo->dwMediaMode &= ~((DWORD)LINEMEDIAMODE_UNKNOWN);
  9931. //Check if the new call is a conference controller call.
  9932. BOOL fConfContCall = *(&pParams->Param4 + 3);
  9933. //Don't expose if a conference controller call
  9934. LOG(( TL_ERROR, "conference controller call:%d.", *(&pParams->Param4 + 3) ));
  9935. if( fConfContCall == TRUE )
  9936. {
  9937. LOG(( TL_ERROR, "conference controller call." ));
  9938. callExposeAndNotify = FALSE;
  9939. }
  9940. pAddress->InternalCreateCall(
  9941. NULL,
  9942. 0,
  9943. pCallInfo->dwMediaMode,
  9944. (pParams->Param3 == LINECALLPRIVILEGE_OWNER) ? CP_OWNER : CP_MONITOR,
  9945. callExposeAndNotify,
  9946. (HCALL)pParams->Param2,
  9947. callExposeAndNotify,
  9948. &pCall
  9949. );
  9950. }
  9951. if ( NULL != pCallInfo )
  9952. {
  9953. ClientFree( pCallInfo );
  9954. }
  9955. //
  9956. // don't keep a ref
  9957. if(pCall != NULL)
  9958. {
  9959. pCall->Release();
  9960. }
  9961. //
  9962. //FindAddressObject addrefs the address objct
  9963. pAddress->Release();
  9964. }
  9965. else
  9966. {
  9967. LOG((TL_ERROR, "Ignoring call with wrong address id"));
  9968. FUNC_ARGS funcArgs =
  9969. {
  9970. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
  9971. {
  9972. pParams->Param2
  9973. },
  9974. {
  9975. Dword
  9976. }
  9977. };
  9978. LOG((TL_INFO, "lineDeallocateCall - hCall = 0x%08lx", pParams->Param2));
  9979. DOFUNC (&funcArgs, "lineDeallocateCall");
  9980. }
  9981. break;
  9982. }
  9983. case LINE_CREATE:
  9984. {
  9985. QueueCallbackEvent( pParams );
  9986. break;
  9987. }
  9988. case LINE_REMOVE:
  9989. {
  9990. QueueCallbackEvent( pParams );
  9991. break;
  9992. }
  9993. case LINE_REQUEST:
  9994. {
  9995. CTAPI *pTapi = NULL;
  9996. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9997. {
  9998. pTapi = pInitData->pTAPI;
  9999. }
  10000. HandleLineRequest( pTapi, pParams );
  10001. break;
  10002. }
  10003. case LINE_CALLHUBCLOSE:
  10004. {
  10005. gpRetryQueue->RemoveNewCallHub(pParams->Param1);
  10006. HandleCallHubClose( pParams );
  10007. break;
  10008. }
  10009. case PRIVATE_MSPEVENT:
  10010. {
  10011. HandlePrivateMSPEvent( pParams );
  10012. break;
  10013. }
  10014. case PHONE_BUTTON:
  10015. {
  10016. HandlePhoneButtonMessage( pParams );
  10017. break;
  10018. }
  10019. case PHONE_CLOSE:
  10020. {
  10021. HandlePhoneCloseMessage( pParams );
  10022. break;
  10023. }
  10024. case PHONE_DEVSPECIFIC:
  10025. {
  10026. HandlePhoneDevSpecificMessage( pParams );
  10027. break;
  10028. }
  10029. case PHONE_STATE:
  10030. {
  10031. QueueCallbackEvent( pParams );
  10032. break;
  10033. }
  10034. case PHONE_CREATE:
  10035. {
  10036. QueueCallbackEvent( pParams );
  10037. break;
  10038. }
  10039. case PHONE_REMOVE:
  10040. {
  10041. QueueCallbackEvent( pParams );
  10042. break;
  10043. }
  10044. case LINE_AGENTSPECIFIC:
  10045. case LINE_PROXYREQUEST:
  10046. default:
  10047. break;
  10048. }
  10049. return hResult;
  10050. }
  10051. void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
  10052. {
  10053. LOG((TL_TRACE, "midl_user_allocate: enter, size=x%x", len));
  10054. return (ClientAlloc (len));
  10055. }
  10056. void __RPC_API midl_user_free(void __RPC_FAR * ptr)
  10057. {
  10058. LOG((TL_TRACE, "midl_user_free: enter, p=x%p", ptr));
  10059. ClientFree (ptr);
  10060. }
  10061. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10062. //
  10063. // AllocClientResources
  10064. //
  10065. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10066. // only and hence access to it is serialized. Calling this function from some
  10067. // other functionality would need making an alternate arrangement to serialize
  10068. // access to this function
  10069. //
  10070. // Starts tapisrv if it is not started and calls ClientAttach
  10071. //
  10072. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10073. LONG
  10074. WINAPI
  10075. AllocClientResources(
  10076. DWORD dwErrorClass
  10077. )
  10078. {
  10079. LOG((TL_INFO, "AllocClientResources - enter"));
  10080. DWORD dwExceptionCount = 0;
  10081. DWORD dwError = 0;
  10082. LONG lResult = gaOpFailedErrors[dwErrorClass];
  10083. //
  10084. // service handles
  10085. //
  10086. SC_HANDLE hSCMgr = NULL;
  10087. SC_HANDLE hTapiSrv = NULL;
  10088. EnterCriticalSection ( &gcsClientResources );
  10089. //
  10090. // If we're in safeboot mode, tapisrv won't start;
  10091. // fail initialization.
  10092. //
  10093. if (0 != GetSystemMetrics (SM_CLEANBOOT))
  10094. {
  10095. lResult = gaOpFailedErrors[dwErrorClass];
  10096. goto AllocClientResources_return;
  10097. }
  10098. //
  10099. // Start the TAPISRV.EXE service
  10100. //
  10101. if ((hSCMgr = OpenSCManager(
  10102. NULL, // local machine
  10103. NULL, // ServicesActive database
  10104. SC_MANAGER_CONNECT // desired access
  10105. )) == NULL)
  10106. {
  10107. dwError = GetLastError();
  10108. LOG((TL_ERROR, "OpenSCManager failed, err=%d", dwError));
  10109. if ( ERROR_ACCESS_DENIED == dwError ||
  10110. ERROR_NOACCESS == dwError
  10111. )
  10112. {
  10113. // if OpenSCManager fails with ACCESS_DENIED,
  10114. // we still need to try to attach to TAPISRV
  10115. goto AllocClientResources_attachToServer;
  10116. }
  10117. else
  10118. {
  10119. goto AllocClientResources_return;
  10120. }
  10121. }
  10122. if ((hTapiSrv = OpenService(
  10123. hSCMgr, // SC mgr handle
  10124. (LPCTSTR) "TAPISRV", // name of service to open
  10125. //SERVICE_START | // desired access
  10126. SERVICE_QUERY_STATUS
  10127. )) == NULL)
  10128. {
  10129. dwError = GetLastError();
  10130. LOG((TL_ERROR, "OpenService failed, err=%d", dwError));
  10131. if ( ERROR_ACCESS_DENIED == dwError ||
  10132. ERROR_NOACCESS == dwError
  10133. )
  10134. {
  10135. // if OpenService fails with ACCESS_DENIED,
  10136. // we still need to try to attach to TAPISRV
  10137. goto AllocClientResources_attachToServer;
  10138. }
  10139. else
  10140. {
  10141. goto AllocClientResources_cleanup1;
  10142. }
  10143. }
  10144. AllocClientResources_queryServiceStatus:
  10145. {
  10146. #define MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV 180
  10147. DWORD dwNumSecondsSleptStartPending = 0,
  10148. dwNumSecondsSleptStopPending = 0;
  10149. while (1)
  10150. {
  10151. SERVICE_STATUS status;
  10152. QueryServiceStatus (hTapiSrv, &status);
  10153. switch (status.dwCurrentState)
  10154. {
  10155. case SERVICE_RUNNING:
  10156. LOG((TL_INFO, "Tapisrv running"));
  10157. goto AllocClientResources_attachToServer;
  10158. case SERVICE_START_PENDING:
  10159. Sleep (1000);
  10160. if (++dwNumSecondsSleptStartPending >
  10161. MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
  10162. {
  10163. LOG((TL_ERROR,
  10164. "ERROR: Tapisrv stuck SERVICE_START_PENDING"
  10165. ));
  10166. goto AllocClientResources_cleanup2;
  10167. }
  10168. break;
  10169. case SERVICE_STOP_PENDING:
  10170. Sleep (1000);
  10171. if (++dwNumSecondsSleptStopPending >
  10172. MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
  10173. {
  10174. LOG((TL_ERROR,
  10175. "ERROR: Tapisrv stuck SERVICE_STOP_PENDING"
  10176. ));
  10177. goto AllocClientResources_cleanup2;
  10178. }
  10179. break;
  10180. case SERVICE_STOPPED:
  10181. LOG((TL_ERROR, "Starting tapisrv (NT)..."));
  10182. //
  10183. // close service handle that we already have
  10184. //
  10185. if (NULL != hTapiSrv)
  10186. {
  10187. CloseServiceHandle(hTapiSrv);
  10188. hTapiSrv = NULL;
  10189. }
  10190. /*Change: This is done in order to avoid opening service with
  10191. SERVICE_START previleges unless it needs to be started*/
  10192. if ((hTapiSrv = OpenService(
  10193. hSCMgr, // SC mgr handle
  10194. (LPCTSTR) "TAPISRV", // name of service to open
  10195. SERVICE_START | // desired access
  10196. SERVICE_QUERY_STATUS
  10197. )) == NULL)
  10198. {
  10199. LOG((TL_ERROR, "OpenService failed, err=%d", GetLastError()));
  10200. goto AllocClientResources_cleanup2;
  10201. }
  10202. if (!StartService(
  10203. hTapiSrv, // service handle
  10204. 0, // num args
  10205. NULL // args
  10206. ))
  10207. {
  10208. DWORD dwLastError = GetLastError();
  10209. if (dwLastError != ERROR_SERVICE_ALREADY_RUNNING)
  10210. {
  10211. LOG((TL_ERROR,
  10212. "StartService(TapiSrv) failed, err=%d",
  10213. dwLastError
  10214. ));
  10215. goto AllocClientResources_cleanup2;
  10216. }
  10217. }
  10218. break;
  10219. default:
  10220. LOG((TL_ERROR,
  10221. "error, service status=%d",
  10222. status.dwCurrentState
  10223. ));
  10224. goto AllocClientResources_cleanup2;
  10225. }
  10226. }
  10227. }
  10228. //
  10229. // Init the RPC connection
  10230. //
  10231. AllocClientResources_attachToServer:
  10232. {
  10233. #define CNLEN 25 // computer name length
  10234. #define UNCLEN CNLEN+2 // \\computername
  10235. #define PATHLEN 260 // Path
  10236. #define MAXPROTSEQ 20 // protocol sequence "ncacn_np"
  10237. BOOL bException = FALSE;
  10238. RPC_STATUS status;
  10239. unsigned char pszNetworkAddress[UNCLEN+1];
  10240. unsigned char *pszUuid = NULL;
  10241. unsigned char *pszOptions = NULL;
  10242. unsigned char *pszStringBinding = NULL;
  10243. DWORD dwProcessID = GetCurrentProcessId();
  10244. //
  10245. // UNLEN (as documented for GetUserName()) is defined in LMCONS.H
  10246. // to be 256 characters. LMCONS.H cannot be easily included, so we are
  10247. // redefining the value here.
  10248. //
  10249. const DWORD MAXIMUM_USER_NAME_LENGTH = 256;
  10250. //
  10251. // allocate memory for user name
  10252. //
  10253. DWORD dwUserNameSize = MAXIMUM_USER_NAME_LENGTH + 1;
  10254. WCHAR *pszUserName = (WCHAR *) ClientAlloc (dwUserNameSize * sizeof(WCHAR) );
  10255. if (NULL == pszUserName)
  10256. {
  10257. LOG((TL_ERROR,
  10258. "AllocClientResources: failed to allocate 0x%lx characters for pszUserName",
  10259. dwUserNameSize));
  10260. goto AllocClientResources_cleanup2;
  10261. }
  10262. //
  10263. // try to get user name. we are passing in a buffer for the
  10264. // longest possible user name so if the call fails, do not
  10265. // retry with a bigger buffer
  10266. //
  10267. BOOL bResult = GetUserNameW(pszUserName, &dwUserNameSize);
  10268. if ( ! bResult )
  10269. {
  10270. LOG((TL_ERROR,
  10271. "AllocClientResources: GetUserName failed. LastError = 0x%lx", GetLastError()));
  10272. ClientFree(pszUserName);
  10273. pszUserName = NULL;
  10274. goto AllocClientResources_cleanup2;
  10275. }
  10276. LOG((TL_INFO, "AllocClientResources: UserName [%S]", pszUserName));
  10277. //
  10278. // allocate memory for computer name
  10279. //
  10280. DWORD dwComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1 ;
  10281. WCHAR *pszComputerName = (WCHAR *) ClientAlloc (dwComputerNameSize * sizeof(WCHAR) );
  10282. if (NULL == pszComputerName)
  10283. {
  10284. LOG((TL_ERROR,
  10285. "AllocClientResources: failed to allocate 0x%lx characters for pszUserName",
  10286. dwComputerNameSize
  10287. ));
  10288. ClientFree(pszUserName);
  10289. pszUserName = NULL;
  10290. goto AllocClientResources_cleanup2;
  10291. }
  10292. //
  10293. // try to get computer name. we are passing in a buffer for the
  10294. // longest possible computer name so if the call fails, do not
  10295. // retry with a bigger buffer
  10296. //
  10297. bResult = GetComputerNameW(pszComputerName,
  10298. &dwComputerNameSize);
  10299. if ( ! bResult )
  10300. {
  10301. LOG((TL_ERROR,
  10302. "AllocClientResources: GetComputerName failed. LastError = 0x%lx", GetLastError()));
  10303. ClientFree(pszUserName);
  10304. pszUserName = NULL;
  10305. ClientFree(pszComputerName);
  10306. pszComputerName = NULL;
  10307. goto AllocClientResources_cleanup2;
  10308. }
  10309. LOG((TL_INFO, "AllocClientResources: ComputerName [%S]", pszComputerName));
  10310. pszNetworkAddress[0] = '\0';
  10311. status = RpcStringBindingCompose(
  10312. pszUuid,
  10313. (unsigned char *)"ncalrpc",
  10314. pszNetworkAddress,
  10315. (unsigned char *)"tapsrvlpc",
  10316. pszOptions,
  10317. &pszStringBinding
  10318. );
  10319. if (status)
  10320. {
  10321. LOG((TL_ERROR,
  10322. "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
  10323. status,
  10324. pszNetworkAddress
  10325. ));
  10326. }
  10327. status = RpcBindingFromStringBinding(
  10328. pszStringBinding,
  10329. &hTapSrv
  10330. );
  10331. if (status)
  10332. {
  10333. LOG((TL_ERROR,
  10334. "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
  10335. status,
  10336. pszStringBinding
  10337. ));
  10338. }
  10339. RpcTryExcept
  10340. {
  10341. LOG((TL_INFO, "AllocCliRes: calling ClientAttach..."));
  10342. lResult = ClientAttach(
  10343. (PCONTEXT_HANDLE_TYPE *) &gphCx,
  10344. dwProcessID,
  10345. (long *) &ghAsyncEventsEvent,
  10346. pszUserName,
  10347. pszComputerName
  10348. );
  10349. LOG((TL_INFO, "AllocCliRes: ClientAttach returned x%x. ghAsyncEventsEvent[%p]",
  10350. lResult, ghAsyncEventsEvent));
  10351. }
  10352. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  10353. {
  10354. LOG((TL_ERROR,
  10355. "AllocCliRes: ClientAttach caused except=%d",
  10356. RpcExceptionCode()
  10357. ));
  10358. bException = TRUE;
  10359. }
  10360. RpcEndExcept
  10361. ClientFree (pszUserName);
  10362. ClientFree (pszComputerName);
  10363. RpcBindingFree (&hTapSrv);
  10364. // LOG((TL_
  10365. // 3,
  10366. // "AllocCliRes: gphCx=x%x, PID=x%x, hAEEvent=x%x",
  10367. // gphCx,
  10368. // dwProcessID,
  10369. // ghAsyncEventsEvent
  10370. // ));
  10371. RpcStringFree(&pszStringBinding);
  10372. if (bException)
  10373. {
  10374. //
  10375. // If here chances are that we started the service and it's
  10376. // not ready to receive rpc requests. So we'll give it a
  10377. // little time to get rolling and then try again.
  10378. //
  10379. if (dwExceptionCount < gdwMaxNumRequestRetries)
  10380. {
  10381. Sleep ((++dwExceptionCount > 1 ? gdwRequestRetryTimeout : 0));
  10382. if (hTapiSrv) // Win NT && successful OpenService()
  10383. {
  10384. goto AllocClientResources_queryServiceStatus;
  10385. }
  10386. else
  10387. {
  10388. goto AllocClientResources_attachToServer;
  10389. }
  10390. }
  10391. else
  10392. {
  10393. LOG((TL_ERROR,
  10394. "AllocCliRes: ClientAttach failed, result=x%x",
  10395. gaServiceNotRunningErrors[dwErrorClass]
  10396. ));
  10397. lResult = gaServiceNotRunningErrors[dwErrorClass];
  10398. }
  10399. }
  10400. }
  10401. AllocClientResources_cleanup2:
  10402. if (NULL != hTapiSrv)
  10403. {
  10404. CloseServiceHandle (hTapiSrv);
  10405. hTapiSrv = NULL;
  10406. }
  10407. AllocClientResources_cleanup1:
  10408. if (NULL != hSCMgr)
  10409. {
  10410. CloseServiceHandle (hSCMgr);
  10411. hSCMgr = NULL;
  10412. }
  10413. AllocClientResources_return:
  10414. //release the mutex
  10415. LeaveCriticalSection ( &gcsClientResources );
  10416. LOG((TL_TRACE, "AllocClientResources: exit, returning x%x", lResult));
  10417. return lResult;
  10418. }
  10419. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10420. //
  10421. // NewShutdown
  10422. //
  10423. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10424. // only and hence access to it is serialized. Calling this function from some
  10425. // other functionality would need making an alternate arrangement to serialize
  10426. // access to this function
  10427. //
  10428. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10429. HRESULT
  10430. CTAPI::NewShutdown()
  10431. {
  10432. LOG((TL_TRACE, "NewShutdown - enter"));
  10433. FUNC_ARGS funcArgs =
  10434. {
  10435. MAKELONG (LINE_FUNC | SYNC | 1, lShutdown),
  10436. {
  10437. (ULONG_PTR)m_dwLineInitDataHandle
  10438. },
  10439. {
  10440. hXxxApp
  10441. }
  10442. };
  10443. //
  10444. // deallocate line resources
  10445. //
  10446. if (0 != m_dwLineInitDataHandle)
  10447. {
  10448. DOFUNC(
  10449. &funcArgs,
  10450. "lineShutdown"
  10451. );
  10452. FreeInitData (m_pLineInitData);
  10453. m_pLineInitData = NULL;
  10454. DeleteHandleTableEntry(m_dwLineInitDataHandle);
  10455. m_dwLineInitDataHandle = 0;
  10456. }
  10457. //
  10458. // deallocate phone resources
  10459. //
  10460. if (0 != m_dwPhoneInitDataHandle)
  10461. {
  10462. funcArgs.Args[0] = (ULONG_PTR)m_dwPhoneInitDataHandle;
  10463. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 1, pShutdown),
  10464. DOFUNC(
  10465. &funcArgs,
  10466. "phoneShutdown"
  10467. );
  10468. FreeInitData (m_pPhoneInitData);
  10469. m_pPhoneInitData = NULL;
  10470. DeleteHandleTableEntry(m_dwPhoneInitDataHandle);
  10471. m_dwPhoneInitDataHandle = 0;
  10472. }
  10473. LOG((TL_TRACE, "NewShutdown - finish"));
  10474. return S_OK;
  10475. }
  10476. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10477. //
  10478. // CreateThreadsAndStuff
  10479. //
  10480. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10481. // only and hence access to it is serialized. Calling this function from some
  10482. // other functionality would need making an alternate arrangement to serialize
  10483. // access to this function
  10484. //
  10485. // This is called when the last TAPI object has been freed
  10486. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10487. void
  10488. CTAPI::FinalTapiCleanup()
  10489. {
  10490. DWORD dwSignalled;
  10491. STATICLOG((TL_TRACE, "FinalTapiCleanup - enter"));
  10492. //
  10493. // tell our threads that we are shutting down
  10494. //
  10495. if (gpAsyncEventsThreadParams)
  10496. {
  10497. gpAsyncEventsThreadParams->bExitThread = TRUE;
  10498. }
  10499. SetEvent( ghAsyncEventsEvent );
  10500. gbExitThread = TRUE;
  10501. SetEvent( ghCallbackThreadEvent );
  10502. //
  10503. // and wait for them to exit
  10504. //
  10505. STATICLOG((TL_INFO, "FinalTapiCleanup - ghAsyncEventsThread"));
  10506. //WaitForSingleObject( ghAsyncEventsThread, INFINITE );
  10507. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10508. INFINITE,
  10509. 1,
  10510. &ghAsyncEventsThread,
  10511. &dwSignalled);
  10512. STATICLOG((TL_INFO, "FinalTapiCleanup - ghCallbackThread"));
  10513. //WaitForSingleObject( ghCallbackThread, INFINITE );
  10514. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10515. INFINITE,
  10516. 1,
  10517. &ghCallbackThread,
  10518. &dwSignalled);
  10519. //
  10520. // close their handles
  10521. //
  10522. CloseHandle( ghAsyncEventsThread );
  10523. CloseHandle( ghCallbackThread );
  10524. gpAsyncEventsThreadParams = NULL;
  10525. //
  10526. // Safely close any existing generic dialog instances
  10527. //
  10528. EnterCriticalSection (&gcsTapisrvCommunication);
  10529. if (gpUIThreadInstances)
  10530. {
  10531. PUITHREADDATA pUIThreadData, pNextUIThreadData;
  10532. pUIThreadData = gpUIThreadInstances;
  10533. while (pUIThreadData)
  10534. {
  10535. //
  10536. // Grab a ptr to the next UIThreadData while it's still
  10537. // safe, wait until the ui dll has indicated that it
  10538. // is will to receive generic dlg data, then pass it
  10539. // NULL/0 to tell it to shutdown the dlg inst
  10540. //
  10541. pNextUIThreadData = pUIThreadData->pNext;
  10542. // WaitForSingleObject (pUIThreadData->hEvent, INFINITE);
  10543. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10544. INFINITE,
  10545. 1,
  10546. &pUIThreadData->hEvent,
  10547. &dwSignalled
  10548. );
  10549. STATICLOG((TL_INFO,
  10550. "NewShutdown: calling TUISPI_providerGenericDialogData..."
  10551. ));
  10552. ((TUIGDDPROC)(*pUIThreadData->pfnTUISPI_providerGenericDialogData))(
  10553. pUIThreadData->htDlgInst,
  10554. NULL,
  10555. 0
  10556. );
  10557. STATICLOG((TL_INFO,
  10558. "NewShutdown: TUISPI_providerGenericDialogData returned"
  10559. ));
  10560. pUIThreadData = pNextUIThreadData;
  10561. }
  10562. }
  10563. LeaveCriticalSection (&gcsTapisrvCommunication);
  10564. FreeClientResources();
  10565. STATICLOG((TL_TRACE, "FinalTapiCleanup - exit"));
  10566. }
  10567. #if DBG
  10568. LPVOID
  10569. WINAPI
  10570. ClientAllocReal(
  10571. DWORD dwSize,
  10572. DWORD dwLine,
  10573. PSTR pszFile
  10574. )
  10575. #else
  10576. LPVOID
  10577. WINAPI
  10578. ClientAllocReal(
  10579. DWORD dwSize
  10580. )
  10581. #endif
  10582. {
  10583. //
  10584. // Alloc 16 extra bytes so we can make sure the pointer we pass back
  10585. // is 64-bit aligned & have space to store the original pointer
  10586. //
  10587. #if DBG
  10588. PMYMEMINFO pHold;
  10589. PDWORD_PTR pAligned;
  10590. PBYTE p;
  10591. p = (PBYTE)LocalAlloc(LPTR, dwSize + sizeof(MYMEMINFO) + 16);
  10592. if (p == NULL)
  10593. {
  10594. return NULL;
  10595. }
  10596. // note note note - this only works because mymeminfo is
  10597. // a 16 bit multiple in size. if it wasn't, this
  10598. // align stuff would cause problems.
  10599. pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
  10600. *pAligned = (DWORD_PTR) p;
  10601. pHold = (PMYMEMINFO)((DWORD_PTR)pAligned + 8);
  10602. pHold->dwSize = dwSize;
  10603. pHold->dwLine = dwLine;
  10604. pHold->pszFile = pszFile;
  10605. pHold->pPrev = NULL;
  10606. pHold->pNext = NULL;
  10607. EnterCriticalSection(&csMemoryList);
  10608. if (gpMemLast != NULL)
  10609. {
  10610. gpMemLast->pNext = pHold;
  10611. pHold->pPrev = gpMemLast;
  10612. gpMemLast = pHold;
  10613. }
  10614. else
  10615. {
  10616. gpMemFirst = gpMemLast = pHold;
  10617. }
  10618. LeaveCriticalSection(&csMemoryList);
  10619. return (LPVOID)(pHold + 1);
  10620. #else
  10621. LPBYTE p;
  10622. PDWORD_PTR pAligned;
  10623. if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
  10624. {
  10625. pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
  10626. *pAligned = (DWORD_PTR) p;
  10627. pAligned = (PDWORD_PTR)((DWORD_PTR)pAligned + 8);
  10628. }
  10629. else
  10630. {
  10631. LOG((TL_ERROR,
  10632. "ClientAlloc: LocalAlloc (x%lx) failed, err=x%lx",
  10633. dwSize,
  10634. GetLastError())
  10635. );
  10636. pAligned = NULL;
  10637. }
  10638. return ((LPVOID) pAligned);
  10639. #endif
  10640. }
  10641. void
  10642. WINAPI
  10643. ClientFree(
  10644. LPVOID p
  10645. )
  10646. {
  10647. #if DBG
  10648. PMYMEMINFO pHold;
  10649. if (p == NULL)
  10650. {
  10651. return;
  10652. }
  10653. pHold = (PMYMEMINFO)(((LPBYTE)p) - sizeof(MYMEMINFO));
  10654. EnterCriticalSection(&csMemoryList);
  10655. if (pHold->pPrev)
  10656. {
  10657. pHold->pPrev->pNext = pHold->pNext;
  10658. }
  10659. else
  10660. {
  10661. gpMemFirst = pHold->pNext;
  10662. }
  10663. if (pHold->pNext)
  10664. {
  10665. pHold->pNext->pPrev = pHold->pPrev;
  10666. }
  10667. else
  10668. {
  10669. gpMemLast = pHold->pPrev;
  10670. }
  10671. LeaveCriticalSection(&csMemoryList);
  10672. {
  10673. LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)pHold - 8));
  10674. LocalFree (pOrig);
  10675. }
  10676. //LocalFree(pHold);
  10677. return;
  10678. #else
  10679. if (p != NULL)
  10680. {
  10681. LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)p - 8));
  10682. LocalFree (pOrig);
  10683. }
  10684. else
  10685. {
  10686. LOG((TL_INFO,"----- ClientFree: ptr = NULL!"));
  10687. }
  10688. #endif
  10689. }
  10690. SIZE_T
  10691. WINAPI
  10692. ClientSize(
  10693. LPVOID p
  10694. )
  10695. {
  10696. if (p != NULL)
  10697. {
  10698. #if DBG
  10699. p = (LPVOID)(((LPBYTE)p) - sizeof(MYMEMINFO));
  10700. #endif
  10701. p = (LPVOID)*((PDWORD_PTR)((DWORD_PTR)p - 8));
  10702. return (LocalSize (p) - 16);
  10703. }
  10704. LOG((TL_INFO,"----- ClientSize: ptr = NULL!"));
  10705. return 0;
  10706. }
  10707. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10708. //
  10709. // FreeClientResources
  10710. //
  10711. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10712. // only and hence access to it is serialized. Calling this function from some
  10713. // other functionality would need making an alternate arrangement to serialize
  10714. // access to this function
  10715. //
  10716. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10717. LONG
  10718. WINAPI
  10719. FreeClientResources(
  10720. void
  10721. )
  10722. {
  10723. LOG((TL_INFO, "FreeClientResources - enter"));
  10724. //grab the critical section
  10725. EnterCriticalSection ( &gcsClientResources );
  10726. //
  10727. // If ghTapi32 is non-NULL it means the AsyncEventsThread is
  10728. // still running (an ill-behaved app is trying to unload us
  10729. // without calling shutdown) so go thru the motions of getting
  10730. // the thread to terminate (like we do in xxxShutdown)
  10731. //
  10732. // Otherwise close our handle to the shared event
  10733. //
  10734. if (gpAsyncEventsThreadParams)
  10735. {
  10736. gpAsyncEventsThreadParams->bExitThread = TRUE;
  10737. SetEvent (ghAsyncEventsEvent);
  10738. gpAsyncEventsThreadParams = NULL;
  10739. gbExitThread = TRUE;
  10740. SetEvent (ghCallbackThreadEvent);
  10741. }
  10742. else if (gphCx)
  10743. {
  10744. if (NULL != ghAsyncEventsEvent)
  10745. {
  10746. CloseHandle (ghAsyncEventsEvent);
  10747. ghAsyncEventsEvent = NULL;
  10748. }
  10749. if (NULL != ghCallbackThreadEvent)
  10750. {
  10751. CloseHandle (ghCallbackThreadEvent);
  10752. ghCallbackThreadEvent = NULL;
  10753. }
  10754. if (NULL != ghAsyncRetryQueueEvent)
  10755. {
  10756. CloseHandle (ghAsyncRetryQueueEvent);
  10757. ghAsyncRetryQueueEvent = NULL;
  10758. }
  10759. }
  10760. gpLineAsyncReplyList->FreeList();
  10761. gpPhoneAsyncReplyList->FreeList();
  10762. //
  10763. // If we've made an rpc connection with tapisrv then cleanly detach
  10764. //
  10765. if (gphCx)
  10766. {
  10767. RpcTryExcept
  10768. {
  10769. ClientDetach (&gphCx);
  10770. }
  10771. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  10772. {
  10773. // do something?
  10774. }
  10775. RpcEndExcept
  10776. gphCx = NULL;
  10777. }
  10778. //
  10779. // Free up any other resources we were using
  10780. //
  10781. if (ghWow32Dll)
  10782. {
  10783. FreeLibrary (ghWow32Dll);
  10784. ghWow32Dll = NULL;
  10785. }
  10786. //release the mutex
  10787. LeaveCriticalSection ( &gcsClientResources );
  10788. LOG((TL_INFO, "FreeClientResources - exit"));
  10789. return 0;
  10790. }
  10791. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10792. //
  10793. // eventName
  10794. //
  10795. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10796. char *eventName(TAPI_EVENT event)
  10797. {
  10798. switch(event)
  10799. {
  10800. case TE_TAPIOBJECT:
  10801. return "TE_TAPIOBJECT";
  10802. case TE_ADDRESS:
  10803. return "TE_ADDRESS";
  10804. case TE_CALLNOTIFICATION:
  10805. return "TE_CALLNOTIFICATION";
  10806. case TE_CALLSTATE:
  10807. return "TE_CALLSTATE";
  10808. case TE_CALLMEDIA:
  10809. return "TE_CALLMEDIA";
  10810. case TE_CALLHUB:
  10811. return "TE_CALLHUB";
  10812. case TE_CALLINFOCHANGE:
  10813. return "TE_CALLINFOCHANGE";
  10814. case TE_PRIVATE:
  10815. return "TE_PRIVATE";
  10816. case TE_REQUEST:
  10817. return "TE_REQUEST";
  10818. case TE_AGENT:
  10819. return "TE_AGENT";
  10820. case TE_AGENTSESSION:
  10821. return "TE_AGENTSESSION";
  10822. case TE_QOSEVENT:
  10823. return "TE_QOSEVENT";
  10824. case TE_AGENTHANDLER:
  10825. return "TE_AGENTHANDLER";
  10826. case TE_ACDGROUP:
  10827. return "TE_ACDGROUP";
  10828. case TE_QUEUE:
  10829. return "TE_QUEUE";
  10830. case TE_DIGITEVENT:
  10831. return "TE_DIGITEVENT";
  10832. case TE_GENERATEEVENT:
  10833. return "TE_GENERATEEVENT";
  10834. case TE_PHONEEVENT:
  10835. return "TE_PHONEEVENT";
  10836. case TE_PHONEDEVSPECIFIC:
  10837. return "TE_PHONEDEVSPECIFIC";
  10838. case TE_ADDRESSDEVSPECIFIC:
  10839. return "TE_ADDRESSDEVSPECIFIC";
  10840. default:
  10841. return "???";
  10842. }
  10843. }
  10844. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10845. //
  10846. // callStateName
  10847. //
  10848. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10849. char *callStateName(CALL_STATE callState)
  10850. {
  10851. switch(callState)
  10852. {
  10853. case CS_IDLE:
  10854. return "CS_IDLE";
  10855. case CS_INPROGRESS:
  10856. return "CS_INPROGRESS";
  10857. case CS_CONNECTED:
  10858. return "CS_CONNECTED";
  10859. case CS_DISCONNECTED:
  10860. return "CS_DISCONNECTED";
  10861. case CS_OFFERING:
  10862. return "CS_OFFERING";
  10863. case CS_HOLD:
  10864. return "CS_HOLD";
  10865. case CS_QUEUED:
  10866. return "CS_QUEUED";
  10867. default:
  10868. return "???";
  10869. }
  10870. }
  10871. #ifdef TRACELOG
  10872. void TAPIFormatMessage(HRESULT hr, LPVOID lpMsgBuf)
  10873. {
  10874. // Get the error message relating to our HRESULT
  10875. FormatMessage(
  10876. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  10877. FORMAT_MESSAGE_FROM_HMODULE |
  10878. FORMAT_MESSAGE_FROM_SYSTEM |
  10879. FORMAT_MESSAGE_IGNORE_INSERTS,
  10880. (LPCVOID)GetModuleHandle("TAPI3.DLL"),
  10881. hr,
  10882. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  10883. (LPTSTR) lpMsgBuf,
  10884. 0,
  10885. NULL
  10886. );
  10887. }
  10888. #endif
  10889. LONG
  10890. CALLBACK
  10891. TUISPIDLLCallback(
  10892. DWORD_PTR dwObjectID,
  10893. DWORD dwObjectType,
  10894. LPVOID lpParams,
  10895. DWORD dwSize
  10896. )
  10897. {
  10898. FUNC_ARGS funcArgs =
  10899. {
  10900. MAKELONG (LINE_FUNC | SYNC | 6, xUIDLLCallback),
  10901. {
  10902. (ULONG_PTR) dwObjectID,
  10903. (ULONG_PTR) dwObjectType,
  10904. (ULONG_PTR) lpParams,
  10905. (ULONG_PTR) dwSize,
  10906. (ULONG_PTR) lpParams,
  10907. (ULONG_PTR) dwSize
  10908. },
  10909. {
  10910. Dword,
  10911. Dword,
  10912. lpSet_SizeToFollow,
  10913. Size,
  10914. lpGet_SizeToFollow,
  10915. Size
  10916. }
  10917. };
  10918. return (DOFUNC (&funcArgs, "UIDLLCallback"));
  10919. }
  10920. void
  10921. UIThread(
  10922. LPVOID pParams
  10923. )
  10924. {
  10925. DWORD dwThreadID = GetCurrentThreadId();
  10926. HANDLE hTapi32;
  10927. PUITHREADDATA pUIThreadData = (PUITHREADDATA) pParams;
  10928. LOG((TL_TRACE, "UIThread: enter (tid=%d)", dwThreadID));
  10929. //
  10930. // Call LoadLibrary to increment the reference count in case this
  10931. // thread is still running when this dll gets unloaded
  10932. //
  10933. hTapi32 = LoadLibrary ("tapi32.dll");
  10934. LOG((TL_INFO, "UIThread: calling TUISPI_providerGenericDialog..."));
  10935. ((TUIGDPROC)(*pUIThreadData->pfnTUISPI_providerGenericDialog))(
  10936. TUISPIDLLCallback,
  10937. pUIThreadData->htDlgInst,
  10938. pUIThreadData->pParams,
  10939. pUIThreadData->dwSize,
  10940. pUIThreadData->hEvent
  10941. );
  10942. LOG((TL_INFO,
  10943. "UIThread: TUISPI_providerGenericDialog returned (tid=%d)",
  10944. dwThreadID
  10945. ));
  10946. //
  10947. // Remove the ui thread data struct from the global list
  10948. //
  10949. EnterCriticalSection (&gcsTapisrvCommunication);
  10950. if (pUIThreadData->pNext)
  10951. {
  10952. pUIThreadData->pNext->pPrev = pUIThreadData->pPrev;
  10953. }
  10954. if (pUIThreadData->pPrev)
  10955. {
  10956. pUIThreadData->pPrev->pNext = pUIThreadData->pNext;
  10957. }
  10958. else
  10959. {
  10960. gpUIThreadInstances = pUIThreadData->pNext;
  10961. }
  10962. LeaveCriticalSection (&gcsTapisrvCommunication);
  10963. //
  10964. // Free the library & buffers, then alert tapisrv
  10965. //
  10966. FreeLibrary (pUIThreadData->hUIDll);
  10967. CloseHandle (pUIThreadData->hThread);
  10968. CloseHandle (pUIThreadData->hEvent);
  10969. if (pUIThreadData->pParams)
  10970. {
  10971. ClientFree (pUIThreadData->pParams);
  10972. }
  10973. {
  10974. FUNC_ARGS funcArgs =
  10975. {
  10976. MAKELONG (LINE_FUNC | SYNC | 1, xFreeDialogInstance),
  10977. {
  10978. (ULONG_PTR) pUIThreadData->htDlgInst
  10979. },
  10980. {
  10981. Dword
  10982. }
  10983. };
  10984. DOFUNC (&funcArgs, "FreeDialogInstance");
  10985. }
  10986. ClientFree (pUIThreadData);
  10987. LOG((TL_TRACE, "UIThread: exit (tid=%d)", dwThreadID));
  10988. if (hTapi32 != NULL)
  10989. {
  10990. FreeLibraryAndExitThread ((HINSTANCE)hTapi32, 0);
  10991. }
  10992. else
  10993. {
  10994. ExitThread (0);
  10995. }
  10996. }
  10997. LONG
  10998. //WINAPI
  10999. CALLBACK
  11000. LAddrParamsInited(
  11001. LPDWORD lpdwInited
  11002. )
  11003. {
  11004. HKEY hKey;
  11005. HKEY hKey2;
  11006. DWORD dwDataSize;
  11007. DWORD dwDataType;
  11008. //
  11009. // This is called by the modem setup wizard to determine
  11010. // whether they should put up TAPI's Wizard page.
  11011. //
  11012. if (ERROR_SUCCESS !=
  11013. RegOpenKeyEx(
  11014. HKEY_LOCAL_MACHINE,
  11015. gszTelephonyKey,
  11016. 0,
  11017. KEY_READ,
  11018. &hKey2
  11019. ))
  11020. {
  11021. LOG((TL_ERROR, "LAddrParamsInited - failed to open registry key" ));
  11022. return 0;
  11023. }
  11024. if (ERROR_SUCCESS !=
  11025. RegOpenKeyEx(
  11026. hKey2,
  11027. gszLocations,
  11028. 0,
  11029. KEY_READ,
  11030. &hKey
  11031. ))
  11032. {
  11033. RegCloseKey (hKey2);
  11034. LOG((TL_ERROR, "LAddrParamsInited - failed to open registry key" ));
  11035. return 0;
  11036. }
  11037. dwDataSize = sizeof(DWORD);
  11038. *lpdwInited=0;
  11039. RegQueryValueEx(
  11040. hKey,
  11041. gszNumEntries,
  11042. 0,
  11043. &dwDataType,
  11044. (LPBYTE)lpdwInited,
  11045. &dwDataSize
  11046. );
  11047. RegCloseKey( hKey );
  11048. RegCloseKey( hKey2);
  11049. //
  11050. // Return a "proper" code
  11051. //
  11052. if ( *lpdwInited > 1 )
  11053. {
  11054. *lpdwInited = 1;
  11055. }
  11056. return 0;
  11057. }
  11058. LONG
  11059. WINAPI
  11060. lineTranslateDialogA(
  11061. HLINEAPP hLineApp,
  11062. DWORD dwDeviceID,
  11063. DWORD dwAPIVersion,
  11064. HWND hwndOwner,
  11065. LPCSTR lpszAddressIn
  11066. );
  11067. /////////////////////////////////////////////////////////////////////
  11068. // internalPerformance
  11069. // tapiperf.dll calls this function to get performance data
  11070. // this just calls into tapisrv
  11071. /////////////////////////////////////////////////////////////////////
  11072. LONG
  11073. WINAPI
  11074. internalPerformance(PPERFBLOCK pPerfBlock)
  11075. {
  11076. FUNC_ARGS funcArgs =
  11077. {
  11078. MAKELONG (LINE_FUNC | SYNC | 2, tPerformance),
  11079. {
  11080. (ULONG_PTR)pPerfBlock,
  11081. sizeof(PERFBLOCK)
  11082. },
  11083. {
  11084. lpGet_SizeToFollow,
  11085. Size
  11086. }
  11087. };
  11088. return (DOFUNC (&funcArgs, "PerfDataCall"));
  11089. }
  11090. //***************************************************************************
  11091. //***************************************************************************
  11092. //***************************************************************************
  11093. #if DBG
  11094. char *aszLineErrors[] =
  11095. {
  11096. NULL,
  11097. "ALLOCATED",
  11098. "BADDEVICEID",
  11099. "BEARERMODEUNAVAIL",
  11100. "inval err value (0x80000004)", // 0x80000004 isn't valid err code
  11101. "CALLUNAVAIL",
  11102. "COMPLETIONOVERRUN",
  11103. "CONFERENCEFULL",
  11104. "DIALBILLING",
  11105. "DIALDIALTONE",
  11106. "DIALPROMPT",
  11107. "DIALQUIET",
  11108. "INCOMPATIBLEAPIVERSION",
  11109. "INCOMPATIBLEEXTVERSION",
  11110. "INIFILECORRUPT",
  11111. "INUSE",
  11112. "INVALADDRESS", // 0x80000010
  11113. "INVALADDRESSID",
  11114. "INVALADDRESSMODE",
  11115. "INVALADDRESSSTATE",
  11116. "INVALAPPHANDLE",
  11117. "INVALAPPNAME",
  11118. "INVALBEARERMODE",
  11119. "INVALCALLCOMPLMODE",
  11120. "INVALCALLHANDLE",
  11121. "INVALCALLPARAMS",
  11122. "INVALCALLPRIVILEGE",
  11123. "INVALCALLSELECT",
  11124. "INVALCALLSTATE",
  11125. "INVALCALLSTATELIST",
  11126. "INVALCARD",
  11127. "INVALCOMPLETIONID",
  11128. "INVALCONFCALLHANDLE", // 0x80000020
  11129. "INVALCONSULTCALLHANDLE",
  11130. "INVALCOUNTRYCODE",
  11131. "INVALDEVICECLASS",
  11132. "INVALDEVICEHANDLE",
  11133. "INVALDIALPARAMS",
  11134. "INVALDIGITLIST",
  11135. "INVALDIGITMODE",
  11136. "INVALDIGITS",
  11137. "INVALEXTVERSION",
  11138. "INVALGROUPID",
  11139. "INVALLINEHANDLE",
  11140. "INVALLINESTATE",
  11141. "INVALLOCATION",
  11142. "INVALMEDIALIST",
  11143. "INVALMEDIAMODE",
  11144. "INVALMESSAGEID", // 0x80000030
  11145. "inval err value (0x80000031)", // 0x80000031 isn't valid err code
  11146. "INVALPARAM",
  11147. "INVALPARKID",
  11148. "INVALPARKMODE",
  11149. "INVALPOINTER",
  11150. "INVALPRIVSELECT",
  11151. "INVALRATE",
  11152. "INVALREQUESTMODE",
  11153. "INVALTERMINALID",
  11154. "INVALTERMINALMODE",
  11155. "INVALTIMEOUT",
  11156. "INVALTONE",
  11157. "INVALTONELIST",
  11158. "INVALTONEMODE",
  11159. "INVALTRANSFERMODE",
  11160. "LINEMAPPERFAILED", // 0x80000040
  11161. "NOCONFERENCE",
  11162. "NODEVICE",
  11163. "NODRIVER",
  11164. "NOMEM",
  11165. "NOREQUEST",
  11166. "NOTOWNER",
  11167. "NOTREGISTERED",
  11168. "OPERATIONFAILED",
  11169. "OPERATIONUNAVAIL",
  11170. "RATEUNAVAIL",
  11171. "RESOURCEUNAVAIL",
  11172. "REQUESTOVERRUN",
  11173. "STRUCTURETOOSMALL",
  11174. "TARGETNOTFOUND",
  11175. "TARGETSELF",
  11176. "UNINITIALIZED", // 0x80000050
  11177. "USERUSERINFOTOOBIG",
  11178. "REINIT",
  11179. "ADDRESSBLOCKED",
  11180. "BILLINGREJECTED",
  11181. "INVALFEATURE",
  11182. "NOMULTIPLEINSTANCE",
  11183. "INVALAGENTID",
  11184. "INVALAGENTGROUP",
  11185. "INVALPASSWORD",
  11186. "INVALAGENTSTATE",
  11187. "INVALAGENTACTIVITY",
  11188. "DIALVOICEDETECT"
  11189. };
  11190. char *aszPhoneErrors[] =
  11191. {
  11192. "SUCCESS",
  11193. "ALLOCATED",
  11194. "BADDEVICEID",
  11195. "INCOMPATIBLEAPIVERSION",
  11196. "INCOMPATIBLEEXTVERSION",
  11197. "INIFILECORRUPT",
  11198. "INUSE",
  11199. "INVALAPPHANDLE",
  11200. "INVALAPPNAME",
  11201. "INVALBUTTONLAMPID",
  11202. "INVALBUTTONMODE",
  11203. "INVALBUTTONSTATE",
  11204. "INVALDATAID",
  11205. "INVALDEVICECLASS",
  11206. "INVALEXTVERSION",
  11207. "INVALHOOKSWITCHDEV",
  11208. "INVALHOOKSWITCHMODE", // 0x90000010
  11209. "INVALLAMPMODE",
  11210. "INVALPARAM",
  11211. "INVALPHONEHANDLE",
  11212. "INVALPHONESTATE",
  11213. "INVALPOINTER",
  11214. "INVALPRIVILEGE",
  11215. "INVALRINGMODE",
  11216. "NODEVICE",
  11217. "NODRIVER",
  11218. "NOMEM",
  11219. "NOTOWNER",
  11220. "OPERATIONFAILED",
  11221. "OPERATIONUNAVAIL",
  11222. "inval err value (0x9000001e)", // 0x9000001e isn't valid err code
  11223. "RESOURCEUNAVAIL",
  11224. "REQUESTOVERRUN", // 0x90000020
  11225. "STRUCTURETOOSMALL",
  11226. "UNINITIALIZED",
  11227. "REINIT"
  11228. };
  11229. char *aszTapiErrors[] =
  11230. {
  11231. "SUCCESS",
  11232. "DROPPED",
  11233. "NOREQUESTRECIPIENT",
  11234. "REQUESTQUEUEFULL",
  11235. "INVALDESTADDRESS",
  11236. "INVALWINDOWHANDLE",
  11237. "INVALDEVICECLASS",
  11238. "INVALDEVICEID",
  11239. "DEVICECLASSUNAVAIL",
  11240. "DEVICEIDUNAVAIL",
  11241. "DEVICEINUSE",
  11242. "DESTBUSY",
  11243. "DESTNOANSWER",
  11244. "DESTUNAVAIL",
  11245. "UNKNOWNWINHANDLE",
  11246. "UNKNOWNREQUESTID",
  11247. "REQUESTFAILED",
  11248. "REQUESTCANCELLED",
  11249. "INVALPOINTER"
  11250. };
  11251. char *
  11252. PASCAL
  11253. MapResultCodeToText(
  11254. LONG lResult,
  11255. char *pszResult
  11256. )
  11257. {
  11258. if (lResult == 0)
  11259. {
  11260. wsprintf (pszResult, "SUCCESS");
  11261. }
  11262. else if (lResult > 0)
  11263. {
  11264. wsprintf (pszResult, "x%x (completing async)", lResult);
  11265. }
  11266. else if (((DWORD) lResult) <= LINEERR_DIALVOICEDETECT)
  11267. {
  11268. lResult &= 0x0fffffff;
  11269. wsprintf (pszResult, "LINEERR_%s", aszLineErrors[lResult]);
  11270. }
  11271. else if (((DWORD) lResult) <= PHONEERR_REINIT)
  11272. {
  11273. if (((DWORD) lResult) >= PHONEERR_ALLOCATED)
  11274. {
  11275. lResult &= 0x0fffffff;
  11276. wsprintf (pszResult, "PHONEERR_%s", aszPhoneErrors[lResult]);
  11277. }
  11278. else
  11279. {
  11280. goto MapResultCodeToText_badErrorCode;
  11281. }
  11282. }
  11283. else if (((DWORD) lResult) <= ((DWORD) TAPIERR_DROPPED) &&
  11284. ((DWORD) lResult) >= ((DWORD) TAPIERR_INVALPOINTER))
  11285. {
  11286. lResult = ~lResult + 1;
  11287. wsprintf (pszResult, "TAPIERR_%s", aszTapiErrors[lResult]);
  11288. }
  11289. else
  11290. {
  11291. MapResultCodeToText_badErrorCode:
  11292. wsprintf (pszResult, "inval error value (x%x)");
  11293. }
  11294. return pszResult;
  11295. }
  11296. #endif
  11297. #if DBG
  11298. void
  11299. DumpMemoryList()
  11300. {
  11301. PMYMEMINFO pHold;
  11302. if (gpMemFirst == NULL)
  11303. {
  11304. LOG((TL_ERROR, "All memory deallocated"));
  11305. return;
  11306. }
  11307. pHold = gpMemFirst;
  11308. while (pHold)
  11309. {
  11310. LOG((TL_ERROR, "DumpMemoryList: %p not freed - LINE %d FILE %s!", pHold+1, pHold->dwLine, pHold->pszFile));
  11311. pHold = pHold->pNext;
  11312. }
  11313. LOG((TL_ERROR, "MEMORY LEAKS ALMOST ALWAYS INDICATE A REFERENCE COUNT PROBLEM"));
  11314. LOG((TL_ERROR, "...except for the leaks in client.cpp"));
  11315. if (gbBreakOnLeak)
  11316. {
  11317. DebugBreak();
  11318. }
  11319. }
  11320. #endif
  11321. HRESULT
  11322. LineCreateAgent(
  11323. HLINE hLine,
  11324. PWSTR pszAgentID,
  11325. PWSTR pszAgentPIN,
  11326. LPHAGENT lphAgent // Return value
  11327. )
  11328. {
  11329. DWORD hpAgentHandle = CreateHandleTableEntry((ULONG_PTR)lphAgent);
  11330. //
  11331. // the agent handle is filled when callback is called. until then, clear its value
  11332. //
  11333. *lphAgent = 0;
  11334. FUNC_ARGS funcArgs =
  11335. {
  11336. MAKELONG (LINE_FUNC | ASYNC | 5, lCreateAgent),
  11337. {
  11338. GetFunctionIndex(lineDevSpecificPostProcess),
  11339. (ULONG_PTR) hLine,
  11340. (ULONG_PTR) pszAgentID,
  11341. (ULONG_PTR) pszAgentPIN,
  11342. hpAgentHandle,
  11343. },
  11344. {
  11345. Dword,
  11346. Dword,
  11347. lpszW,
  11348. lpszW,
  11349. Dword
  11350. }
  11351. };
  11352. if ( NULL == pszAgentID )
  11353. {
  11354. funcArgs.Args[2] = TAPI_NO_DATA;
  11355. funcArgs.ArgTypes[2] = Dword;
  11356. }
  11357. if ( NULL == pszAgentPIN )
  11358. {
  11359. funcArgs.Args[3] = TAPI_NO_DATA;
  11360. funcArgs.ArgTypes[3] = Dword;
  11361. }
  11362. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineCreateAgent"));
  11363. //
  11364. // if failed, delete the handle table entry now. otherwise it will be deleted by the callback
  11365. //
  11366. if (FAILED(hr))
  11367. {
  11368. DeleteHandleTableEntry(hpAgentHandle);
  11369. }
  11370. return hr;
  11371. }
  11372. LONG
  11373. WINAPI
  11374. lineSetAgentMeasurementPeriod(
  11375. HLINE hLine,
  11376. HAGENT hAgent,
  11377. DWORD dwMeasurementPeriod
  11378. )
  11379. {
  11380. FUNC_ARGS funcArgs =
  11381. {
  11382. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentMeasurementPeriod),
  11383. {
  11384. (ULONG_PTR) hLine,
  11385. (ULONG_PTR) hAgent,
  11386. (ULONG_PTR) dwMeasurementPeriod
  11387. },
  11388. {
  11389. Dword,
  11390. Dword,
  11391. Dword
  11392. }
  11393. };
  11394. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentMeasurementPeriod"));
  11395. }
  11396. LONG
  11397. WINAPI
  11398. lineGetAgentInfo(
  11399. HLINE hLine,
  11400. HAGENT hAgent,
  11401. LPLINEAGENTINFO lpAgentInfo // Returned structure
  11402. )
  11403. {
  11404. DWORD hpAgentInfo = CreateHandleTableEntry((ULONG_PTR)lpAgentInfo);
  11405. FUNC_ARGS funcArgs =
  11406. {
  11407. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentInfo),
  11408. {
  11409. GetFunctionIndex(lineDevSpecificPostProcess),
  11410. (ULONG_PTR) hLine,
  11411. (ULONG_PTR) hAgent,
  11412. hpAgentInfo, // pass the actual ptr (for ppproc)
  11413. (ULONG_PTR) lpAgentInfo // pass data
  11414. },
  11415. {
  11416. Dword,
  11417. Dword,
  11418. Dword,
  11419. Dword,
  11420. lpGet_Struct
  11421. }
  11422. };
  11423. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetAgentInfo"));
  11424. if (FAILED(hr))
  11425. {
  11426. DeleteHandleTableEntry(hpAgentInfo);
  11427. }
  11428. return hr;
  11429. }
  11430. HRESULT
  11431. LineCreateAgentSession(
  11432. HLINE hLine,
  11433. HAGENT hAgent,
  11434. PWSTR pszAgentPIN,
  11435. DWORD dwWorkingAddressID,
  11436. LPGUID lpGroupID,
  11437. HAGENTSESSION *phAgentSession // Return value
  11438. )
  11439. {
  11440. DWORD hpAgentSession = CreateHandleTableEntry((ULONG_PTR)phAgentSession);
  11441. FUNC_ARGS funcArgs =
  11442. {
  11443. MAKELONG (LINE_FUNC | ASYNC | 8, lCreateAgentSession),
  11444. {
  11445. GetFunctionIndex(lineDevSpecificPostProcess),
  11446. (ULONG_PTR) hLine,
  11447. (ULONG_PTR) hAgent,
  11448. (ULONG_PTR) pszAgentPIN,
  11449. (ULONG_PTR) dwWorkingAddressID,
  11450. (ULONG_PTR) lpGroupID, // GroupID GUID
  11451. (ULONG_PTR) sizeof(GUID), // GroupID GUID (size)
  11452. hpAgentSession
  11453. },
  11454. {
  11455. Dword,
  11456. Dword,
  11457. Dword,
  11458. lpszW,
  11459. Dword,
  11460. lpSet_SizeToFollow, // GroupID GUID
  11461. Size, // GroupID GUID
  11462. Dword
  11463. }
  11464. };
  11465. if ( NULL == pszAgentPIN )
  11466. {
  11467. funcArgs.Args[3] = TAPI_NO_DATA;
  11468. funcArgs.ArgTypes[3] = Dword;
  11469. }
  11470. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineCreateAgentSession"));
  11471. //
  11472. // if we failed, remove handle table entry now. otherwise it will be
  11473. // removed by the callback
  11474. //
  11475. if (FAILED(hr))
  11476. {
  11477. DeleteHandleTableEntry(hpAgentSession);
  11478. }
  11479. return hr;
  11480. }
  11481. LONG
  11482. WINAPI
  11483. lineGetAgentSessionInfo(
  11484. HLINE hLine,
  11485. HAGENTSESSION hAgentSession,
  11486. LPLINEAGENTSESSIONINFO lpAgentSessionInfo // Returned structure
  11487. )
  11488. {
  11489. DWORD hpAgentSessionInfo = CreateHandleTableEntry((ULONG_PTR)lpAgentSessionInfo);
  11490. FUNC_ARGS funcArgs =
  11491. {
  11492. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionInfo),
  11493. {
  11494. GetFunctionIndex(lineDevSpecificPostProcess),
  11495. (ULONG_PTR) hLine,
  11496. (ULONG_PTR) hAgentSession,
  11497. hpAgentSessionInfo, // pass the actual ptr (for ppproc)
  11498. (ULONG_PTR) lpAgentSessionInfo // pass data
  11499. },
  11500. {
  11501. Dword,
  11502. Dword,
  11503. Dword,
  11504. Dword,
  11505. lpGet_Struct
  11506. }
  11507. };
  11508. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetAgentSessionInfo"));
  11509. //
  11510. // if failed, clear handle table now. otherwise the callback will do this.
  11511. //
  11512. if (FAILED(hr))
  11513. {
  11514. DeleteHandleTableEntry(hpAgentSessionInfo);
  11515. }
  11516. return hr;
  11517. }
  11518. LONG
  11519. WINAPI
  11520. lineSetAgentSessionState(
  11521. HLINE hLine,
  11522. HAGENTSESSION hAgentSession,
  11523. DWORD dwAgentState,
  11524. DWORD dwNextAgentState
  11525. )
  11526. {
  11527. FUNC_ARGS funcArgs =
  11528. {
  11529. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentSessionState),
  11530. {
  11531. (ULONG_PTR) hLine,
  11532. (ULONG_PTR) hAgentSession,
  11533. dwAgentState,
  11534. dwNextAgentState
  11535. },
  11536. {
  11537. Dword,
  11538. Dword,
  11539. Dword,
  11540. Dword
  11541. }
  11542. };
  11543. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentSessionState"));
  11544. }
  11545. LONG
  11546. WINAPI
  11547. lineSetQueueMeasurementPeriod(
  11548. HLINE hLine,
  11549. DWORD dwQueueID,
  11550. DWORD dwMeasurementPeriod
  11551. )
  11552. {
  11553. FUNC_ARGS funcArgs =
  11554. {
  11555. MAKELONG (LINE_FUNC | ASYNC | 3, lSetQueueMeasurementPeriod),
  11556. {
  11557. (ULONG_PTR) hLine,
  11558. dwQueueID,
  11559. dwMeasurementPeriod
  11560. },
  11561. {
  11562. Dword,
  11563. Dword,
  11564. Dword
  11565. }
  11566. };
  11567. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetQueueMeasurementPeriod"));
  11568. }
  11569. LONG
  11570. WINAPI
  11571. lineGetQueueInfo(
  11572. HLINE hLine,
  11573. DWORD dwQueueID,
  11574. LPLINEQUEUEINFO lpQueueInfo // Returned structure
  11575. )
  11576. {
  11577. DWORD hpQueueInfo = CreateHandleTableEntry((ULONG_PTR)lpQueueInfo);
  11578. FUNC_ARGS funcArgs =
  11579. {
  11580. MAKELONG (LINE_FUNC | ASYNC | 5, lGetQueueInfo),
  11581. {
  11582. GetFunctionIndex(lineDevSpecificPostProcess),
  11583. (ULONG_PTR) hLine,
  11584. dwQueueID,
  11585. hpQueueInfo, // pass the actual ptr (for ppproc)
  11586. (ULONG_PTR) lpQueueInfo // pass data
  11587. },
  11588. {
  11589. Dword,
  11590. Dword,
  11591. Dword,
  11592. Dword,
  11593. lpGet_Struct
  11594. }
  11595. };
  11596. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetQueueInfo"));
  11597. //
  11598. // if we failed, cleanup now. otherwise the callback will.
  11599. //
  11600. if (FAILED(hr))
  11601. {
  11602. DeleteHandleTableEntry(hpQueueInfo);
  11603. }
  11604. return hr;
  11605. }
  11606. // Proxy message - LINEPROXYREQUEST_GETGROUPLIST : struct - GetGroupList
  11607. HRESULT
  11608. LineGetGroupList(
  11609. HLINE hLine,
  11610. LPLINEAGENTGROUPLIST * ppGroupList // Returned structure
  11611. )
  11612. {
  11613. HRESULT hr = S_OK;
  11614. long lResult;
  11615. DWORD dwSize = sizeof(LINEAGENTGROUPLIST) + 500;
  11616. *ppGroupList = (LPLINEAGENTGROUPLIST) ClientAlloc( dwSize );
  11617. if (NULL == *ppGroupList)
  11618. {
  11619. return E_OUTOFMEMORY;
  11620. }
  11621. (*ppGroupList)->dwTotalSize = dwSize;
  11622. DWORD hpGroupList = CreateHandleTableEntry( (ULONG_PTR)*ppGroupList );
  11623. FUNC_ARGS funcArgs =
  11624. {
  11625. MAKELONG (LINE_FUNC | ASYNC | 4, lGetGroupList),
  11626. {
  11627. GetFunctionIndex(lineDevSpecificPostProcess),
  11628. (ULONG_PTR) hLine,
  11629. hpGroupList, // pass the actual ptr (for ppproc)
  11630. (ULONG_PTR) *ppGroupList // pass data
  11631. },
  11632. {
  11633. Dword,
  11634. Dword,
  11635. Dword,
  11636. lpGet_Struct,
  11637. }
  11638. };
  11639. while (TRUE)
  11640. {
  11641. lResult = DOFUNC (&funcArgs, "lineGetGroupList");
  11642. if (lResult > 0) // async reply
  11643. {
  11644. hr = WaitForReply( lResult );
  11645. if ((hr == S_OK))
  11646. {
  11647. if (((*ppGroupList)->dwNeededSize > (*ppGroupList)->dwTotalSize))
  11648. {
  11649. // didnt Work , adjust buffer size & try again
  11650. LOG((TL_INFO, "lineGetGroupList failed - buffer too small"));
  11651. dwSize = (*ppGroupList)->dwNeededSize;
  11652. DeleteHandleTableEntry(hpGroupList);
  11653. hpGroupList = 0;
  11654. ClientFree( *ppGroupList );
  11655. *ppGroupList = NULL;
  11656. *ppGroupList = (LPLINEAGENTGROUPLIST) ClientAlloc( dwSize );
  11657. if (*ppGroupList == NULL)
  11658. {
  11659. LOG((TL_ERROR, "lineGetGroupList - repeat ClientAlloc failed"));
  11660. hr = E_OUTOFMEMORY;
  11661. break;
  11662. }
  11663. else
  11664. {
  11665. (*ppGroupList)->dwTotalSize = dwSize;
  11666. _ASSERTE(0 == hpGroupList);
  11667. hpGroupList = CreateHandleTableEntry((ULONG_PTR)*ppGroupList);
  11668. if (0 == hpGroupList)
  11669. {
  11670. LOG((TL_ERROR, "lineGetGroupList - failed to create a handle"));
  11671. ClientFree( *ppGroupList );
  11672. hr = E_OUTOFMEMORY;
  11673. break;
  11674. }
  11675. funcArgs.Args[2] = hpGroupList;
  11676. funcArgs.Args[3] = (ULONG_PTR)*ppGroupList;
  11677. }
  11678. }
  11679. else
  11680. {
  11681. //
  11682. // WaitForReply succeeded and the buffer was big enough
  11683. //
  11684. break;
  11685. }
  11686. } // WaitforReply succeeded
  11687. else
  11688. {
  11689. //
  11690. // WaitForReply failed
  11691. //
  11692. LOG((TL_ERROR, "lineGetGroupList - WaitForReply failed"));
  11693. break;
  11694. }
  11695. }
  11696. else // failed sync
  11697. {
  11698. LOG((TL_ERROR, "lineGetGroupList - failed sync"));
  11699. hr = mapTAPIErrorCode(lResult);
  11700. break;
  11701. }
  11702. } // end while(TRUE)
  11703. DeleteHandleTableEntry(hpGroupList);
  11704. hpGroupList = 0;
  11705. LOG((TL_ERROR, "lineGetGroupList - completed hr %lx", hr));
  11706. return hr;
  11707. }
  11708. HRESULT
  11709. lineGetQueueList(
  11710. HLINE hLine,
  11711. LPGUID lpGroupID,
  11712. LPLINEQUEUELIST * ppQueueList // Returned structure
  11713. )
  11714. {
  11715. LOG((TL_TRACE, "lineGetQueueList - enter"));
  11716. HRESULT hr = S_OK;
  11717. long lResult;
  11718. DWORD dwSize = sizeof(LINEQUEUELIST) + 500;
  11719. *ppQueueList = (LPLINEQUEUELIST) ClientAlloc( dwSize );
  11720. if (NULL == *ppQueueList)
  11721. {
  11722. return E_OUTOFMEMORY;
  11723. }
  11724. (*ppQueueList)->dwTotalSize = dwSize;
  11725. DWORD hpQueueRequest = CreateHandleTableEntry((ULONG_PTR)*ppQueueList);
  11726. FUNC_ARGS funcArgs =
  11727. {
  11728. MAKELONG (LINE_FUNC | ASYNC | 6, lGetQueueList),
  11729. {
  11730. GetFunctionIndex(lineDevSpecificPostProcess),
  11731. (ULONG_PTR) hLine,
  11732. (ULONG_PTR) lpGroupID, // GroupID GUID
  11733. (ULONG_PTR) sizeof(GUID), // GroupID GUID (size)
  11734. hpQueueRequest, // pass the actual ptr (for ppproc)
  11735. (ULONG_PTR) *ppQueueList // pass data
  11736. },
  11737. {
  11738. Dword,
  11739. Dword,
  11740. lpSet_SizeToFollow, // GroupID GUID
  11741. Size, // GroupID GUID (size)
  11742. Dword,
  11743. lpGet_Struct
  11744. }
  11745. };
  11746. while (TRUE)
  11747. {
  11748. lResult = DOFUNC (&funcArgs, "lineGetQueueList");
  11749. if (lResult > 0)
  11750. {
  11751. hr = WaitForReply( lResult );
  11752. if ((hr == S_OK) )
  11753. {
  11754. if ((*ppQueueList)->dwNeededSize > (*ppQueueList)->dwTotalSize)
  11755. {
  11756. // didnt Work , adjust buffer size & try again
  11757. LOG((TL_INFO, "lineGetQueueList failed - buffer to small"));
  11758. dwSize = (*ppQueueList)->dwNeededSize;
  11759. DeleteHandleTableEntry(hpQueueRequest);
  11760. hpQueueRequest = 0;
  11761. ClientFree( *ppQueueList );
  11762. *ppQueueList = NULL;
  11763. *ppQueueList = (LPLINEQUEUELIST) ClientAlloc( dwSize );
  11764. if (*ppQueueList == NULL)
  11765. {
  11766. LOG((TL_ERROR, "lineGetQueueList - repeat ClientAlloc failed"));
  11767. hr = E_OUTOFMEMORY;
  11768. break;
  11769. }
  11770. else
  11771. {
  11772. hpQueueRequest = CreateHandleTableEntry((ULONG_PTR)*ppQueueList);
  11773. (*ppQueueList)->dwTotalSize = dwSize;
  11774. funcArgs.Args[4] = hpQueueRequest;
  11775. funcArgs.Args[5] = (ULONG_PTR)*ppQueueList;
  11776. }
  11777. } // buffer too small
  11778. else
  11779. {
  11780. //
  11781. // everything is fine and dandy. nothing else left to do.
  11782. //
  11783. break;
  11784. }
  11785. }
  11786. else
  11787. {
  11788. //
  11789. // error case. we have hr, break out. we should really not be
  11790. // here, since we checked lResult > 0 above
  11791. //
  11792. break;
  11793. }
  11794. }
  11795. else // failed sync
  11796. {
  11797. LOG((TL_ERROR, "lineGetQueueList - failed sync"));
  11798. hr = mapTAPIErrorCode(lResult);
  11799. break;
  11800. }
  11801. } // end while(TRUE)
  11802. DeleteHandleTableEntry(hpQueueRequest);
  11803. hpQueueRequest = 0;
  11804. LOG((TL_TRACE, "lineGetQueueList - finished hr = %lx", hr));
  11805. return hr;
  11806. }
  11807. LONG
  11808. WINAPI
  11809. lineGetAgentSessionList(
  11810. HLINE hLine,
  11811. HAGENT hAgent,
  11812. LPLINEAGENTSESSIONLIST * ppSessionList // Returned structure
  11813. )
  11814. {
  11815. HRESULT hr = S_OK;
  11816. long lResult;
  11817. DWORD dwSize = sizeof(LINEAGENTSESSIONLIST) + 500;
  11818. *ppSessionList = (LPLINEAGENTSESSIONLIST) ClientAlloc( dwSize );
  11819. if (NULL == *ppSessionList)
  11820. {
  11821. return E_OUTOFMEMORY;
  11822. }
  11823. (*ppSessionList)->dwTotalSize = dwSize;
  11824. DWORD hpSessionList = CreateHandleTableEntry((ULONG_PTR)*ppSessionList);
  11825. FUNC_ARGS funcArgs =
  11826. {
  11827. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionList),
  11828. {
  11829. GetFunctionIndex(lineDevSpecificPostProcess),
  11830. (ULONG_PTR) hLine,
  11831. (ULONG_PTR) hAgent,
  11832. hpSessionList, // pass the actual ptr (for ppproc)
  11833. (ULONG_PTR) *ppSessionList // pass data
  11834. },
  11835. {
  11836. Dword,
  11837. Dword,
  11838. Dword,
  11839. Dword,
  11840. lpGet_Struct
  11841. }
  11842. };
  11843. while (TRUE)
  11844. {
  11845. lResult = DOFUNC (&funcArgs, "lineGetAgentSessionList");
  11846. if (lResult > 0)
  11847. {
  11848. hr = WaitForReply( lResult );
  11849. if ((hr == S_OK) && ((*ppSessionList)->dwNeededSize > (*ppSessionList)->dwTotalSize))
  11850. {
  11851. // didnt Work , adjust buffer size & try again
  11852. LOG((TL_INFO, "lineGetAgentSessionList failed - buffer to small"));
  11853. dwSize = (*ppSessionList)->dwNeededSize;
  11854. DeleteHandleTableEntry(hpSessionList);
  11855. hpSessionList = 0;
  11856. ClientFree( *ppSessionList );
  11857. *ppSessionList = NULL;
  11858. *ppSessionList = (LPLINEAGENTSESSIONLIST) ClientAlloc( dwSize );
  11859. if (*ppSessionList == NULL)
  11860. {
  11861. LOG((TL_ERROR, "lineGetAgentSessionList - repeat ClientAlloc failed"));
  11862. hr = E_OUTOFMEMORY;
  11863. break;
  11864. }
  11865. else
  11866. {
  11867. hpSessionList = CreateHandleTableEntry((ULONG_PTR)*ppSessionList);
  11868. (*ppSessionList)->dwTotalSize = dwSize;
  11869. funcArgs.Args[3] = hpSessionList;
  11870. funcArgs.Args[4] = (ULONG_PTR)*ppSessionList;
  11871. }
  11872. }
  11873. else
  11874. {
  11875. //
  11876. // either hr is not ok or hr is ok and the buffer was sufficient.
  11877. // in both cases, nothing much we need to do here, so break out
  11878. //
  11879. break;
  11880. }
  11881. }
  11882. else // failed sync
  11883. {
  11884. LOG((TL_ERROR, "lineGetAgentSessionListt - failed sync"));
  11885. hr = mapTAPIErrorCode(lResult);
  11886. break;
  11887. }
  11888. } // end while(TRUE)
  11889. DeleteHandleTableEntry(hpSessionList);
  11890. hpSessionList = 0;
  11891. LOG((TL_TRACE, "lineGetAgentSessionListt - finish. hr = %lx", hr));
  11892. return hr;
  11893. }
  11894. HRESULT
  11895. LineCreateMSPInstance(
  11896. HLINE hLine,
  11897. DWORD dwAddressID
  11898. )
  11899. {
  11900. FUNC_ARGS funcArgs =
  11901. {
  11902. MAKELONG (LINE_FUNC | SYNC | 2, lCreateMSPInstance),
  11903. {
  11904. (ULONG_PTR) hLine,
  11905. dwAddressID
  11906. },
  11907. {
  11908. Dword,
  11909. Dword
  11910. }
  11911. };
  11912. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCreateMSPInstance") );
  11913. }
  11914. HRESULT
  11915. LineCloseMSPInstance(
  11916. HLINE hLine
  11917. )
  11918. {
  11919. FUNC_ARGS funcArgs =
  11920. {
  11921. MAKELONG (LINE_FUNC | SYNC | 1, lCloseMSPInstance),
  11922. {
  11923. (ULONG_PTR) hLine
  11924. },
  11925. {
  11926. Dword
  11927. }
  11928. };
  11929. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCloseMSPInstance") );
  11930. }
  11931. /**/
  11932. HRESULT mapTAPIErrorCode(long lErrorCode)
  11933. {
  11934. HRESULT hr;
  11935. // Check if it's async
  11936. if (lErrorCode > 0)
  11937. {
  11938. hr = lErrorCode;
  11939. }
  11940. else
  11941. {
  11942. switch(lErrorCode)
  11943. {
  11944. //
  11945. // Sucess codes - ie 0
  11946. //
  11947. case TAPI_SUCCESS:
  11948. // case LINEERR_SUCCESS: // The operation completed successfully.
  11949. // case PHONEERR_SUCCESS: // The operation completed successfully
  11950. // case TAPIERR_CONNECTED: // The request was accepted
  11951. hr = S_OK;
  11952. break;
  11953. //
  11954. // Serious errors - Somethings very wrong in TAPI3 !
  11955. //
  11956. // Bad handles !!
  11957. case LINEERR_INVALAPPHANDLE: // Invalid TAPI line application handle
  11958. case LINEERR_INVALCALLHANDLE: // Invalid call handle
  11959. case LINEERR_INVALCONFCALLHANDLE: // Invalid conference call handle
  11960. case LINEERR_INVALCONSULTCALLHANDLE: // Invalid consultation call handle
  11961. case LINEERR_INVALDEVICEHANDLE: // Invalid device handle
  11962. case LINEERR_INVALLINEHANDLE: // Invalid line handle
  11963. case LINEERR_BADDEVICEID: // Invalid line device ID
  11964. case LINEERR_INCOMPATIBLEAPIVERSION: // Incompatible API version
  11965. case LINEERR_INVALADDRESSID: // Invalid address ID
  11966. case LINEERR_INVALADDRESSMODE: // Invalid address mode
  11967. case LINEERR_INVALAPPNAME: // Invalid application name
  11968. case LINEERR_INVALCALLSELECT: // Invalid call select parameter
  11969. case LINEERR_INVALEXTVERSION: // Invalid extension version
  11970. case LINEERR_INVALTERMINALID: // Invalid terminal ID
  11971. case LINEERR_INVALTERMINALMODE: // Invalid terminal mode
  11972. case LINEERR_LINEMAPPERFAILED: // No device matches the specified requirements
  11973. case LINEERR_UNINITIALIZED: // The telephony service has not been initialized
  11974. case LINEERR_NOMULTIPLEINSTANCE: // You cannot have two instances of the same service provider
  11975. case PHONEERR_INVALAPPHANDLE: // Invalid TAPI phone application handle
  11976. case PHONEERR_INVALPHONEHANDLE: // Invalid phone handle
  11977. case PHONEERR_BADDEVICEID: // Invalid phone device ID
  11978. case PHONEERR_INCOMPATIBLEAPIVERSION:// Incompatible API version
  11979. case PHONEERR_INVALEXTVERSION: // Invalid extension version
  11980. case PHONEERR_INVALAPPNAME: // Invalid application name
  11981. case PHONEERR_UNINITIALIZED: // The telephony service has not been initialized
  11982. case TAPIERR_INVALDEVICEID: // Invalid device ID
  11983. case TAPIERR_UNKNOWNWINHANDLE: // Unknown window handle
  11984. case TAPIERR_UNKNOWNREQUESTID: // Unknown request ID
  11985. case TAPIERR_INVALWINDOWHANDLE: // Invalid window handle
  11986. // Memory/ Allocation errors
  11987. case LINEERR_STRUCTURETOOSMALL: // The application failed to allocate sufficient memory for the
  11988. // minimum structure size
  11989. case PHONEERR_STRUCTURETOOSMALL: // The application failed to allocate sufficient memory for the
  11990. // minimum structure size
  11991. //_ASSERTE( 0 );
  11992. hr = E_UNEXPECTED;
  11993. break;
  11994. case PHONEERR_INIFILECORRUPT: // The TAPI configuration information is unusable
  11995. case LINEERR_INIFILECORRUPT: // The TAPI configuration information is unusable
  11996. hr = TAPI_E_REGISTRY_SETTING_CORRUPT;
  11997. break;
  11998. // Bad Pointers
  11999. case LINEERR_INVALPOINTER: // Invalid pointer
  12000. case PHONEERR_INVALPOINTER: // Invalid pointer
  12001. case TAPIERR_INVALPOINTER: // Invalid pointer
  12002. hr = E_POINTER;
  12003. break;
  12004. //
  12005. // Unexpected Errors
  12006. //
  12007. case LINEERR_OPERATIONFAILED: // The operation failed for unspecified reasons
  12008. case PHONEERR_OPERATIONFAILED: // The operation failed for unspecified reasons
  12009. case LINEERR_INCOMPATIBLEEXTVERSION: // Incompatible extension version
  12010. case PHONEERR_INCOMPATIBLEEXTVERSION:// Incompatible extension version
  12011. hr = TAPI_E_OPERATIONFAILED;
  12012. break;
  12013. case LINEERR_ALLOCATED: // The line device is already in use
  12014. case PHONEERR_ALLOCATED: // The phone device is already in use
  12015. hr = TAPI_E_ALLOCATED;
  12016. break;
  12017. case LINEERR_BEARERMODEUNAVAIL: // The requested bearer mode is unavailable
  12018. case LINEERR_INVALBEARERMODE: // Invalid bearer mode
  12019. hr = TAPI_E_INVALMODE;
  12020. break;
  12021. case LINEERR_CALLUNAVAIL: // No call appearance available
  12022. hr = TAPI_E_CALLUNAVAIL;
  12023. break;
  12024. case LINEERR_COMPLETIONOVERRUN: // Too many call completions outstanding
  12025. hr = TAPI_E_COMPLETIONOVERRUN;
  12026. break;
  12027. case LINEERR_CONFERENCEFULL: // The conference is full
  12028. hr = TAPI_E_CONFERENCEFULL;
  12029. break;
  12030. case LINEERR_DIALBILLING: // The '$' dial modifier is not supported
  12031. case LINEERR_DIALDIALTONE: // The 'W' dial modifier is not supported
  12032. case LINEERR_DIALPROMPT: // The '?' dial modifier is not supported
  12033. case LINEERR_DIALQUIET: // The '@' dial modifier is not supported
  12034. case LINEERR_DIALVOICEDETECT: // The ':' dial modifier is not supported
  12035. hr = TAPI_E_DIALMODIFIERNOTSUPPORTED;
  12036. break;
  12037. case LINEERR_RESOURCEUNAVAIL: // A resource needed to fulfill the request is not available
  12038. case PHONEERR_RESOURCEUNAVAIL: // A resource needed to fulfill the request is not available
  12039. hr = TAPI_E_RESOURCEUNAVAIL;
  12040. break;
  12041. case LINEERR_INUSE: // The line device is already in use
  12042. case PHONEERR_INUSE: // The phone device is already in use
  12043. case TAPIERR_DEVICEINUSE: // The device is already in use
  12044. hr = TAPI_E_INUSE;
  12045. break;
  12046. case LINEERR_INVALADDRESS: // The phone number is invalid or not properly formatted
  12047. case TAPIERR_INVALDESTADDRESS: // The phone number is invalid or improperly formatted
  12048. hr = TAPI_E_INVALADDRESS;
  12049. break;
  12050. case LINEERR_INVALADDRESSSTATE: // Operation not permitted in current address state
  12051. case LINEERR_INVALLINESTATE: // Operation not permitted in current line state
  12052. case PHONEERR_INVALPHONESTATE: // Operation not permitted in current phone state
  12053. hr = TAPI_E_INVALADDRESSSTATE;
  12054. break;
  12055. case LINEERR_INVALADDRESSTYPE: // The specified address type is not supported by this address.
  12056. hr = TAPI_E_INVALADDRESSTYPE;
  12057. break;
  12058. case LINEERR_INVALCALLCOMPLMODE: // Invalid call completion mode
  12059. hr = TAPI_E_INVALMODE;
  12060. break;
  12061. case LINEERR_INVALCALLPARAMS: // Invalid LINECALLPARAMS structure
  12062. hr = TAPI_E_INVALCALLPARAMS;
  12063. break;
  12064. case LINEERR_INVALCALLPRIVILEGE: // Invalid call privilege
  12065. case LINEERR_INVALPRIVSELECT: // Invalid call privilege selection
  12066. hr = TAPI_E_INVALCALLPRIVILEGE;
  12067. break;
  12068. case LINEERR_INVALCALLSTATE: // Operation not permitted in current call state
  12069. hr = TAPI_E_INVALCALLSTATE;
  12070. break;
  12071. case LINEERR_INVALCALLSTATELIST: // Invalid call state list
  12072. hr = TAPI_E_INVALLIST;
  12073. break;
  12074. case LINEERR_INVALCARD: // Invalid calling card ID
  12075. hr = TAPI_E_INVALCARD;
  12076. break;
  12077. case LINEERR_INVALCOMPLETIONID: // Invalid call completion ID
  12078. hr = TAPI_E_INVALCOMPLETIONID;
  12079. break;
  12080. case LINEERR_INVALCOUNTRYCODE: // Invalid country code
  12081. hr = TAPI_E_INVALCOUNTRYCODE;
  12082. break;
  12083. case LINEERR_INVALDEVICECLASS: // Invalid device class identifier
  12084. case PHONEERR_INVALDEVICECLASS: // Invalid device class identifier
  12085. case TAPIERR_INVALDEVICECLASS:
  12086. case TAPIERR_DEVICECLASSUNAVAIL: // The device class is unavailable
  12087. case TAPIERR_DEVICEIDUNAVAIL: // The specified device is unavailable
  12088. hr = TAPI_E_INVALDEVICECLASS;
  12089. break;
  12090. case LINEERR_INVALDIALPARAMS: // Invalid dialing parameters
  12091. hr = TAPI_E_INVALDIALPARAMS;
  12092. break;
  12093. case LINEERR_INVALDIGITLIST: // Invalid digit list
  12094. hr = TAPI_E_INVALLIST;
  12095. break;
  12096. case LINEERR_INVALDIGITMODE: // Invalid digit mode
  12097. hr = TAPI_E_INVALMODE;
  12098. break;
  12099. case LINEERR_INVALDIGITS: // Invalid digits
  12100. hr = TAPI_E_INVALDIGITS;
  12101. break;
  12102. case LINEERR_INVALGROUPID: // Invalid group pickup ID
  12103. hr = TAPI_E_INVALGROUPID;
  12104. break;
  12105. case LINEERR_INVALLOCATION: // Invalid location ID
  12106. hr = TAPI_E_INVALLOCATION;
  12107. break;
  12108. case LINEERR_INVALMEDIALIST: // Invalid media list
  12109. hr = TAPI_E_INVALLIST;
  12110. break;
  12111. case LINEERR_INVALMEDIAMODE: // Invalid media mode
  12112. hr = TAPI_E_INVALIDMEDIATYPE;
  12113. break;
  12114. case LINEERR_INVALMESSAGEID: // Invalid message ID
  12115. hr = TAPI_E_INVALMESSAGEID;
  12116. break;
  12117. case LINEERR_INVALPARAM: // Invalid parameter
  12118. hr = E_INVALIDARG;
  12119. break;
  12120. case LINEERR_INVALPARKID: // Invalid park ID
  12121. hr = TAPI_E_INVALPARKID;
  12122. break;
  12123. case LINEERR_INVALPARKMODE: // Invalid park mode
  12124. case PHONEERR_INVALPARAM: // Invalid parameter
  12125. hr = TAPI_E_INVALMODE;
  12126. break;
  12127. case LINEERR_INVALRATE: // Invalid rate
  12128. case LINEERR_RATEUNAVAIL: // The requested data rate is not available
  12129. hr = TAPI_E_INVALRATE;
  12130. break;
  12131. case LINEERR_INVALREQUESTMODE: // Invalid request mode
  12132. hr = TAPI_E_INVALMODE;
  12133. break;
  12134. case LINEERR_INVALTIMEOUT: // Invalid timeout value
  12135. hr = TAPI_E_INVALTIMEOUT;
  12136. break;
  12137. case LINEERR_INVALTONE: // Invalid tone
  12138. hr = TAPI_E_INVALTONE;
  12139. break;
  12140. case LINEERR_INVALTONELIST: // Invalid tone list
  12141. hr = TAPI_E_INVALLIST;
  12142. break;
  12143. case LINEERR_INVALTONEMODE: // Invalid tone mode
  12144. case LINEERR_INVALTRANSFERMODE: // Invalid transfer mode
  12145. case PHONEERR_INVALBUTTONMODE: // Invalid button mode
  12146. case PHONEERR_INVALHOOKSWITCHMODE: // Invalid hookswitch mode
  12147. case PHONEERR_INVALLAMPMODE: // Invalid lamp mode
  12148. case PHONEERR_INVALRINGMODE: // Invalid ring mode
  12149. hr = TAPI_E_INVALMODE;
  12150. break;
  12151. case LINEERR_NOCONFERENCE: // The call is not part of a conference
  12152. hr = TAPI_E_NOCONFERENCE;
  12153. break;
  12154. case LINEERR_NODEVICE: // The device was removed, or the device class is not recognized
  12155. case PHONEERR_NODEVICE: // The device was removed, or the device class is not recognized
  12156. hr = TAPI_E_NODEVICE;
  12157. break;
  12158. case LINEERR_NODRIVER: // The service provider was removed
  12159. case PHONEERR_NODRIVER: // The service provider was removed
  12160. hr = TAPI_E_NODRIVER;
  12161. break;
  12162. case LINEERR_NOMEM: // Insufficient memory available to complete the operation
  12163. case PHONEERR_NOMEM: // Insufficient memory available to complete the operation
  12164. hr = E_OUTOFMEMORY;
  12165. break;
  12166. case LINEERR_NOREQUEST: // No Assisted Telephony requests are pending
  12167. hr = TAPI_E_NOREQUEST;
  12168. break;
  12169. case LINEERR_NOTOWNER: // The application is does not have OWNER privilege on the call
  12170. case PHONEERR_NOTOWNER: // The application is does not have OWNER privilege on the phone
  12171. hr = TAPI_E_NOTOWNER;
  12172. break;
  12173. case LINEERR_NOTREGISTERED: // The application is not registered to handle requests
  12174. hr = TAPI_E_NOTREGISTERED;
  12175. break;
  12176. case LINEERR_OPERATIONUNAVAIL: // The operation is not supported by the underlying service provider
  12177. case PHONEERR_OPERATIONUNAVAIL: // The operation is not supported by the underlying service provider
  12178. hr = TAPI_E_NOTSUPPORTED;
  12179. break;
  12180. case LINEERR_REQUESTOVERRUN: // The request queue is already full
  12181. case PHONEERR_REQUESTOVERRUN: // The request queue is already full
  12182. hr= TAPI_E_REQUESTOVERRUN;
  12183. break;
  12184. case LINEERR_SERVICE_NOT_RUNNING: // The Telephony service could not be contacted
  12185. case PHONEERR_SERVICE_NOT_RUNNING: // The Telephony service could not be contacted
  12186. hr = TAPI_E_SERVICE_NOT_RUNNING;
  12187. break;
  12188. case LINEERR_TARGETNOTFOUND: // The call handoff failed because the specified target was not found
  12189. hr = TAPI_E_TARGETNOTFOUND;
  12190. break;
  12191. case LINEERR_TARGETSELF: // No higher priority target exists for the call handoff
  12192. hr = TAPI_E_TARGETSELF;
  12193. break;
  12194. case LINEERR_USERUSERINFOTOOBIG: // The amount of user-user info exceeds the maximum permitted
  12195. hr = TAPI_E_USERUSERINFOTOOBIG;
  12196. break;
  12197. case LINEERR_REINIT: // The operation cannot be completed until all TAPI applications
  12198. // call lineShutdown
  12199. case PHONEERR_REINIT: // The operation cannot be completed until all TAPI applications
  12200. hr = TAPI_E_REINIT;
  12201. break;
  12202. case LINEERR_ADDRESSBLOCKED: // You are not permitted to call this number
  12203. hr = TAPI_E_ADDRESSBLOCKED;
  12204. break;
  12205. case LINEERR_BILLINGREJECTED: // The calling card number or other billing information was rejected
  12206. hr = TAPI_E_BILLINGREJECTED;
  12207. break;
  12208. case LINEERR_INVALFEATURE: // Invalid device-specific feature
  12209. hr = TAPI_E_INVALFEATURE;
  12210. break;
  12211. case LINEERR_INVALAGENTID: // Invalid agent ID
  12212. hr = TAPI_E_CALLCENTER_INVALAGENTID;
  12213. break;
  12214. case LINEERR_INVALAGENTGROUP: // Invalid agent group
  12215. hr = TAPI_E_CALLCENTER_INVALAGENTGROUP;
  12216. break;
  12217. case LINEERR_INVALPASSWORD: // Invalid agent password
  12218. hr = TAPI_E_CALLCENTER_INVALPASSWORD;
  12219. break;
  12220. case LINEERR_INVALAGENTSTATE: // Invalid agent state
  12221. hr = TAPI_E_CALLCENTER_INVALAGENTSTATE;
  12222. break;
  12223. case LINEERR_INVALAGENTACTIVITY: // Invalid agent activity
  12224. hr = TAPI_E_CALLCENTER_INVALAGENTACTIVITY;
  12225. break;
  12226. case PHONEERR_INVALPRIVILEGE: // Invalid privilege
  12227. hr = TAPI_E_INVALPRIVILEGE;
  12228. break;
  12229. case PHONEERR_INVALBUTTONLAMPID: // Invalid button or lamp ID
  12230. hr = TAPI_E_INVALBUTTONLAMPID;
  12231. break;
  12232. case PHONEERR_INVALBUTTONSTATE: // Invalid button state
  12233. hr = TAPI_E_INVALBUTTONSTATE;
  12234. break;
  12235. case PHONEERR_INVALDATAID: // Invalid data segment ID
  12236. hr = TAPI_E_INVALDATAID;
  12237. break;
  12238. case PHONEERR_INVALHOOKSWITCHDEV: // Invalid hookswitch device ID
  12239. hr = TAPI_E_INVALHOOKSWITCHDEV;
  12240. break;
  12241. case TAPIERR_DROPPED: // The call was disconnected
  12242. hr = TAPI_E_DROPPED;
  12243. break;
  12244. case TAPIERR_NOREQUESTRECIPIENT: // No program is available to handle the request
  12245. hr = TAPI_E_NOREQUESTRECIPIENT;
  12246. break;
  12247. case TAPIERR_REQUESTQUEUEFULL: // The queue of call requests is full
  12248. hr = TAPI_E_REQUESTQUEUEFULL;
  12249. break;
  12250. case TAPIERR_DESTBUSY: // The called number is busy
  12251. hr = TAPI_E_DESTBUSY;
  12252. break;
  12253. case TAPIERR_DESTNOANSWER: // The called party does not answer
  12254. hr = TAPI_E_DESTNOANSWER;
  12255. break;
  12256. case TAPIERR_DESTUNAVAIL: // The called number could not be reached
  12257. hr = TAPI_E_DESTUNAVAIL;
  12258. break;
  12259. case TAPIERR_REQUESTFAILED: // The request failed for unspecified reasons
  12260. hr = TAPI_E_REQUESTFAILED;
  12261. break;
  12262. case TAPIERR_REQUESTCANCELLED: // The request was cancelled
  12263. hr = TAPI_E_REQUESTCANCELLED;
  12264. break;
  12265. default:
  12266. hr = E_FAIL;
  12267. break;
  12268. } // End switch(lErrorCode)
  12269. }
  12270. return hr;
  12271. }
  12272. HRESULT UnloadTapi32( BOOL bShutdown )
  12273. {
  12274. EnterCriticalSection( &gcsTapi32 );
  12275. if ( bShutdown )
  12276. {
  12277. if ( NULL == gpShutdown )
  12278. {
  12279. gpShutdown = (LINESHUTDOWNPROC)GetProcAddress(
  12280. ghTapi32,
  12281. "lineShutdown"
  12282. );
  12283. if ( NULL == gpShutdown )
  12284. {
  12285. LeaveCriticalSection( &gcsTapi32 );
  12286. return E_FAIL;
  12287. }
  12288. (gpShutdown)(ghLineApp);
  12289. }
  12290. }
  12291. ghLineApp = NULL;
  12292. gpShutdown = NULL;
  12293. gpInitialize = NULL;
  12294. if ( NULL != ghTapi32 )
  12295. {
  12296. FreeLibrary( ghTapi32 );
  12297. }
  12298. LeaveCriticalSection( &gcsTapi32 );
  12299. return S_OK;
  12300. }
  12301. HRESULT LoadTapi32( BOOL bInitialize )
  12302. {
  12303. HRESULT hr;
  12304. DWORD dwNumDevs;
  12305. DWORD dwAPIVersion = TAPI_CURRENT_VERSION;
  12306. EnterCriticalSection( &gcsTapi32 );
  12307. ghTapi32 = LoadLibrary("tapi32.dll");
  12308. //
  12309. // ll failed
  12310. //
  12311. if ( NULL == ghTapi32 )
  12312. {
  12313. LeaveCriticalSection( &gcsTapi32 );
  12314. return E_FAIL;
  12315. }
  12316. if ( bInitialize )
  12317. {
  12318. if ( NULL == gpInitialize )
  12319. {
  12320. gpInitialize = (LINEINITIALIZEPROC)GetProcAddress(
  12321. ghTapi32,
  12322. "lineInitializeExW"
  12323. );
  12324. if ( NULL == gpInitialize )
  12325. {
  12326. LOG((TL_ERROR, "LoadTapi32 - getprocaddres failed 1"));
  12327. LeaveCriticalSection( &gcsTapi32 );
  12328. UnloadTapi32( FALSE );
  12329. return E_FAIL;
  12330. }
  12331. }
  12332. LINEINITIALIZEEXPARAMS lei;
  12333. ZeroMemory( &lei, sizeof(lei) );
  12334. lei.dwTotalSize = sizeof(lei);
  12335. lei.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  12336. hr = (gpInitialize)(
  12337. &ghLineApp,
  12338. NULL,
  12339. NULL,
  12340. L"tapi3helper",
  12341. &dwNumDevs,
  12342. &dwAPIVersion,
  12343. &lei
  12344. );
  12345. if ( !SUCCEEDED(hr) )
  12346. {
  12347. ghLineApp = NULL;
  12348. LOG((TL_ERROR, "LoadTapi32 - lineinit failed"));
  12349. LeaveCriticalSection( &gcsTapi32 );
  12350. UnloadTapi32( FALSE );
  12351. return mapTAPIErrorCode( hr );
  12352. }
  12353. }
  12354. LeaveCriticalSection( &gcsTapi32 );
  12355. return S_OK;
  12356. }
  12357. HRESULT TapiMakeCall(
  12358. BSTR pDestAddress,
  12359. BSTR pAppName,
  12360. BSTR pCalledParty,
  12361. BSTR pComment
  12362. )
  12363. {
  12364. HRESULT hr;
  12365. TAPIREQUESTMAKECALLPROC pTapiMakeCall;
  12366. hr = LoadTapi32( FALSE );
  12367. if ( !SUCCEEDED(hr) )
  12368. {
  12369. LOG((TL_ERROR, "Could not load TAPI32.DLL"));
  12370. return hr;
  12371. }
  12372. pTapiMakeCall = (TAPIREQUESTMAKECALLPROC)GetProcAddress( ghTapi32, "tapiRequestMakeCallW" );
  12373. if ( NULL == pTapiMakeCall )
  12374. {
  12375. LOG((TL_ERROR, "Could not get the address of tapimakecall"));
  12376. UnloadTapi32( FALSE );
  12377. return E_FAIL;
  12378. }
  12379. hr = pTapiMakeCall(
  12380. pDestAddress,
  12381. pAppName,
  12382. pCalledParty,
  12383. pComment
  12384. );
  12385. if ( !SUCCEEDED(hr) )
  12386. {
  12387. LOG((TL_ERROR, "tapimakecall failed - %lx", hr));
  12388. }
  12389. UnloadTapi32( FALSE );
  12390. return hr;
  12391. }
  12392. HRESULT
  12393. LineTranslateDialog(
  12394. DWORD dwDeviceID,
  12395. DWORD dwAPIVersion,
  12396. HWND hwndOwner,
  12397. BSTR pAddressIn
  12398. )
  12399. {
  12400. HRESULT hr;
  12401. LINEINITIALIZEPROC pInitialize;
  12402. LINETRANSLATEDIALOGPROC pTranslateDialog;
  12403. hr = LoadTapi32( TRUE );
  12404. if ( !SUCCEEDED(hr) )
  12405. {
  12406. LOG((TL_ERROR, "LineTranslateDialog - load tapi32 failed"));
  12407. return hr;
  12408. }
  12409. pTranslateDialog = (LINETRANSLATEDIALOGPROC)GetProcAddress(
  12410. ghTapi32,
  12411. "lineTranslateDialogW"
  12412. );
  12413. if ( NULL == pTranslateDialog )
  12414. {
  12415. LOG((TL_ERROR, "LineTranslateDialog - getprocaddress failed 2"));
  12416. UnloadTapi32( TRUE );
  12417. return E_FAIL;
  12418. }
  12419. hr = (pTranslateDialog)(
  12420. ghLineApp,
  12421. dwDeviceID,
  12422. dwAPIVersion,
  12423. hwndOwner,
  12424. pAddressIn
  12425. );
  12426. hr = mapTAPIErrorCode( hr );
  12427. if ( !SUCCEEDED(hr) )
  12428. {
  12429. LOG((TL_ERROR, "LineTranslateDialog failed - %lx", hr));
  12430. }
  12431. UnloadTapi32( TRUE );
  12432. return hr;
  12433. }
  12434. typedef LONG (PASCAL *LINETRANSLATEADDRESSPROC)(HLINEAPP,
  12435. DWORD,
  12436. DWORD,
  12437. LPCWSTR,
  12438. DWORD,
  12439. DWORD,
  12440. LPLINETRANSLATEOUTPUT);
  12441. typedef LONG (PASCAL *LINEGETTRANSLATECAPSPROC)(HLINEAPP,
  12442. DWORD,
  12443. LPLINETRANSLATECAPS);
  12444. HRESULT
  12445. LineTranslateAddress(
  12446. HLINEAPP hLineApp,
  12447. DWORD dwDeviceID,
  12448. DWORD dwAPIVersion,
  12449. LPCWSTR lpszAddressIn,
  12450. DWORD dwCard,
  12451. DWORD dwTranslateOptions,
  12452. LPLINETRANSLATEOUTPUT *ppTranslateOutput
  12453. )
  12454. {
  12455. LONG lResult = 0;
  12456. HRESULT hr = S_OK;
  12457. DWORD dwSize = sizeof(LINETRANSLATECAPS ) + 2000;
  12458. LINETRANSLATEADDRESSPROC pTranslateProc;
  12459. LOG((TL_TRACE, "lineTranslateAddress - enter"));
  12460. hr = LoadTapi32( FALSE );
  12461. if ( !SUCCEEDED(hr) )
  12462. {
  12463. LOG((TL_ERROR, "lineTranslateAddress - load tapi32 failed"));
  12464. return hr;
  12465. }
  12466. pTranslateProc = (LINETRANSLATEADDRESSPROC)GetProcAddress(
  12467. ghTapi32,
  12468. "lineTranslateAddressW"
  12469. );
  12470. if ( NULL == pTranslateProc )
  12471. {
  12472. LOG((TL_ERROR, "lineTranslateAddress - getprocaddress failed 2"));
  12473. UnloadTapi32( FALSE );
  12474. return E_FAIL;
  12475. }
  12476. *ppTranslateOutput = (LPLINETRANSLATEOUTPUT) ClientAlloc( dwSize );
  12477. if (*ppTranslateOutput == NULL)
  12478. {
  12479. LOG((TL_ERROR, "lineTranslateAddress - ClientAlloc failed"));
  12480. hr = E_OUTOFMEMORY;
  12481. }
  12482. else
  12483. {
  12484. (*ppTranslateOutput)->dwTotalSize = dwSize;
  12485. while (TRUE)
  12486. {
  12487. lResult = (pTranslateProc)(0,
  12488. dwDeviceID,
  12489. dwAPIVersion,
  12490. lpszAddressIn,
  12491. dwCard,
  12492. dwTranslateOptions,
  12493. *ppTranslateOutput
  12494. );
  12495. if ((lResult == 0) && ((*ppTranslateOutput)->dwNeededSize > (*ppTranslateOutput)->dwTotalSize))
  12496. {
  12497. // didnt Work , adjust buffer size & try again
  12498. LOG((TL_INFO, "LineGetTranslateCaps failed - buffer to small"));
  12499. dwSize = (*ppTranslateOutput)->dwNeededSize;
  12500. ClientFree( *ppTranslateOutput );
  12501. *ppTranslateOutput = (LPLINETRANSLATEOUTPUT) ClientAlloc( dwSize );
  12502. if (*ppTranslateOutput == NULL)
  12503. {
  12504. LOG((TL_ERROR, "lineTranslateAddress - repeat ClientAlloc failed"));
  12505. hr = E_OUTOFMEMORY;
  12506. break;
  12507. }
  12508. else
  12509. {
  12510. (*ppTranslateOutput)->dwTotalSize = dwSize;
  12511. }
  12512. }
  12513. else
  12514. {
  12515. hr = mapTAPIErrorCode( lResult );
  12516. break;
  12517. }
  12518. } // end while(TRUE)
  12519. }
  12520. UnloadTapi32( FALSE );
  12521. LOG((TL_TRACE, hr, "lineTranslateAddress - exit"));
  12522. return hr;
  12523. }
  12524. HRESULT
  12525. LineGetTranslateCaps(
  12526. HLINEAPP hLineApp,
  12527. DWORD dwAPIVersion,
  12528. LPLINETRANSLATECAPS *ppTranslateCaps
  12529. )
  12530. {
  12531. LONG lResult = 0;
  12532. HRESULT hr = S_OK;
  12533. DWORD dwSize = sizeof(LINETRANSLATECAPS ) + 2000;
  12534. LINEGETTRANSLATECAPSPROC pTranslateProc;
  12535. LOG((TL_TRACE, "LineGetTranslateCaps - enter"));
  12536. hr = LoadTapi32( FALSE );
  12537. if ( !SUCCEEDED(hr) )
  12538. {
  12539. LOG((TL_ERROR, "LineGetTranslateCapsg - load tapi32 failed"));
  12540. return hr;
  12541. }
  12542. pTranslateProc = (LINEGETTRANSLATECAPSPROC)GetProcAddress(
  12543. ghTapi32,
  12544. "lineGetTranslateCapsW"
  12545. );
  12546. if ( NULL == pTranslateProc )
  12547. {
  12548. LOG((TL_ERROR, "LineGetTranslateCaps - getprocaddress failed 2"));
  12549. UnloadTapi32( FALSE );
  12550. return E_FAIL;
  12551. }
  12552. *ppTranslateCaps = (LPLINETRANSLATECAPS) ClientAlloc( dwSize );
  12553. if (*ppTranslateCaps == NULL)
  12554. {
  12555. LOG((TL_ERROR, "LineGetTranslateCaps - ClientAlloc failed"));
  12556. hr = E_OUTOFMEMORY;
  12557. }
  12558. else
  12559. {
  12560. (*ppTranslateCaps)->dwTotalSize = dwSize;
  12561. while (TRUE)
  12562. {
  12563. lResult = (pTranslateProc)(0,
  12564. dwAPIVersion,
  12565. *ppTranslateCaps
  12566. );
  12567. if ((lResult == 0) && ((*ppTranslateCaps)->dwNeededSize > (*ppTranslateCaps)->dwTotalSize))
  12568. {
  12569. // didnt Work , adjust buffer size & try again
  12570. LOG((TL_INFO, "LineGetTranslateCaps failed - buffer to small"));
  12571. dwSize = (*ppTranslateCaps)->dwNeededSize;
  12572. ClientFree( *ppTranslateCaps );
  12573. *ppTranslateCaps = (LPLINETRANSLATECAPS) ClientAlloc( dwSize );
  12574. if (*ppTranslateCaps == NULL)
  12575. {
  12576. LOG((TL_ERROR, "LineGetTranslateCaps - repeat ClientAlloc failed"));
  12577. hr = E_OUTOFMEMORY;
  12578. break;
  12579. }
  12580. else
  12581. {
  12582. (*ppTranslateCaps)->dwTotalSize = dwSize;
  12583. }
  12584. }
  12585. else
  12586. {
  12587. hr = mapTAPIErrorCode( lResult );
  12588. break;
  12589. }
  12590. } // end while(TRUE)
  12591. }
  12592. UnloadTapi32( FALSE );
  12593. LOG((TL_TRACE, hr, "LineGetTranslateCaps - exit"));
  12594. return hr;
  12595. }
  12596. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12597. // Function : GenerateHandleAndAddToHashTable
  12598. // Creates a unique ULONG_PTR handle & maps this to the passed in
  12599. // object via a hash table
  12600. // Returns handle
  12601. //
  12602. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12603. ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element)
  12604. {
  12605. static ULONG_PTR gNextHandle = 0;
  12606. ULONG_PTR uptrHandle = 0;
  12607. gpHandleHashTable->Lock();
  12608. gNextHandle = ++gNextHandle % 0x10;
  12609. uptrHandle = (Element << 4) + gNextHandle;
  12610. gpHandleHashTable->Insert( uptrHandle, Element );
  12611. gpHandleHashTable->Unlock();
  12612. return uptrHandle;
  12613. }
  12614. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12615. // Function : RemoveHandleFromHashTable
  12616. // Removes hash table entry, based on passed in handle
  12617. //
  12618. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12619. void RemoveHandleFromHashTable(ULONG_PTR dwHandle)
  12620. {
  12621. gpHandleHashTable->Lock();
  12622. gpHandleHashTable->Remove( (ULONG_PTR)(dwHandle) );
  12623. gpHandleHashTable->Unlock();
  12624. }
  12625. /////////////////////////////////////////////////////////////////////
  12626. //
  12627. // Internal event filtering functions
  12628. //
  12629. /////////////////////////////////////////////////////////////////////
  12630. #define LOWDWORD(ul64) ((DWORD)(ul64 & 0xffffffff))
  12631. #define HIDWORD(ul64) ((DWORD)((ul64 & 0xffffffff00000000) >> 32))
  12632. LONG
  12633. WINAPI
  12634. tapiSetEventFilterMasks (
  12635. DWORD dwObjType,
  12636. LONG_PTR lObjectID,
  12637. ULONG64 ulEventMasks
  12638. )
  12639. {
  12640. FUNC_ARGS funcArgs =
  12641. {
  12642. MAKELONG (TAPI_FUNC | SYNC | 6, tSetEventMasksOrSubMasks),
  12643. {
  12644. (ULONG_PTR) dwObjType, // type of object handle
  12645. (ULONG_PTR) lObjectID, // object handle
  12646. (ULONG_PTR) FALSE, // fSubMask
  12647. (ULONG_PTR) 0, // dwSubMasks
  12648. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasks low
  12649. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasks hi
  12650. },
  12651. {
  12652. Dword,
  12653. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12654. hXxxApp : Dword,
  12655. Dword,
  12656. Dword,
  12657. Dword,
  12658. Dword,
  12659. }
  12660. };
  12661. return (DOFUNC (&funcArgs, "tapiSetEventFilter"));
  12662. }
  12663. LONG
  12664. WINAPI
  12665. tapiSetEventFilterSubMasks (
  12666. DWORD dwObjType,
  12667. LONG_PTR lObjectID,
  12668. ULONG64 ulEventMasks,
  12669. DWORD dwEventSubMasks
  12670. )
  12671. {
  12672. FUNC_ARGS funcArgs =
  12673. {
  12674. MAKELONG (TAPI_FUNC | SYNC | 6, tSetEventMasksOrSubMasks),
  12675. {
  12676. (ULONG_PTR) dwObjType, // type of object handle
  12677. (ULONG_PTR) lObjectID, // object handle
  12678. (ULONG_PTR) TRUE, // fSubMask
  12679. (ULONG_PTR) dwEventSubMasks, // dwSubMasks
  12680. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasks low
  12681. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasks hi
  12682. },
  12683. {
  12684. Dword,
  12685. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12686. hXxxApp : Dword,
  12687. Dword,
  12688. Dword,
  12689. Dword,
  12690. Dword,
  12691. }
  12692. };
  12693. return (DOFUNC (&funcArgs, "tapiSetEventFilter"));
  12694. }
  12695. LONG
  12696. WINAPI
  12697. tapiGetEventFilterMasks (
  12698. DWORD dwObjType,
  12699. LONG_PTR lObjectID,
  12700. ULONG64 * pulEventMasks
  12701. )
  12702. {
  12703. DWORD dwEventSubMasks;
  12704. DWORD dwHiMasks;
  12705. DWORD dwLowMasks;
  12706. LONG lResult;
  12707. FUNC_ARGS funcArgs =
  12708. {
  12709. MAKELONG (TAPI_FUNC | SYNC | 8, tGetEventMasksOrSubMasks),
  12710. {
  12711. (ULONG_PTR) dwObjType, // object type
  12712. (ULONG_PTR) lObjectID, // object handles
  12713. (ULONG_PTR) FALSE, // fSubMask
  12714. (ULONG_PTR) &dwEventSubMasks, // &dwEventSubMasks
  12715. (ULONG_PTR) 0, // ulEventMasksIn low
  12716. (ULONG_PTR) 0, // ulEventMasksIn hi
  12717. (ULONG_PTR) &dwLowMasks, // ulEventMasksOut low
  12718. (ULONG_PTR) &dwHiMasks, // ulEventMasksOut hi
  12719. },
  12720. {
  12721. Dword,
  12722. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12723. hXxxApp : Dword,
  12724. Dword,
  12725. lpDword,
  12726. Dword,
  12727. Dword,
  12728. lpDword,
  12729. lpDword,
  12730. }
  12731. };
  12732. lResult = DOFUNC (&funcArgs, "tapiGetEventFilter");
  12733. if (lResult == 0)
  12734. {
  12735. *pulEventMasks = dwHiMasks;
  12736. (*pulEventMasks) <<= 32;
  12737. *pulEventMasks += dwLowMasks;
  12738. }
  12739. return lResult;
  12740. }
  12741. LONG
  12742. WINAPI
  12743. tapiGetEventFilterSubMasks (
  12744. DWORD dwObjType,
  12745. LONG_PTR lObjectID,
  12746. ULONG64 ulEventMasks,
  12747. DWORD * pdwEventSubMasks
  12748. )
  12749. {
  12750. DWORD dwHiMasks;
  12751. DWORD dwLowMasks;
  12752. FUNC_ARGS funcArgs =
  12753. {
  12754. MAKELONG (TAPI_FUNC | SYNC | 8, tGetEventMasksOrSubMasks),
  12755. {
  12756. (ULONG_PTR) dwObjType, // object type
  12757. (ULONG_PTR) lObjectID, // object handle
  12758. (ULONG_PTR) TRUE, // fSubMask
  12759. (ULONG_PTR) pdwEventSubMasks, // &dwEventSubMasks
  12760. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasksIn low
  12761. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasksIn hi
  12762. (ULONG_PTR) &dwLowMasks, // ulEventMasksOut low
  12763. (ULONG_PTR) &dwHiMasks, // ulEventMasksOut hi
  12764. },
  12765. {
  12766. Dword,
  12767. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12768. hXxxApp : Dword,
  12769. Dword,
  12770. lpDword,
  12771. Dword,
  12772. Dword,
  12773. lpDword,
  12774. lpDword,
  12775. }
  12776. };
  12777. return (DOFUNC (&funcArgs, "tapiGetEventFilter"));
  12778. }
  12779. LONG
  12780. WINAPI
  12781. tapiGetPermissibleMasks (
  12782. ULONG64 * pulPermMasks
  12783. )
  12784. {
  12785. LONG lResult;
  12786. DWORD dwLowMasks;
  12787. DWORD dwHiMasks;
  12788. FUNC_ARGS funcArgs =
  12789. {
  12790. MAKELONG (TAPI_FUNC | SYNC | 2, tGetPermissibleMasks),
  12791. {
  12792. (ULONG_PTR) &dwLowMasks, // ulPermMasks low
  12793. (ULONG_PTR) &dwHiMasks, // ulPermMasks hi
  12794. },
  12795. {
  12796. lpDword,
  12797. lpDword,
  12798. }
  12799. };
  12800. lResult = DOFUNC (&funcArgs, "tapiGetPermissibleMasks");
  12801. if (lResult == 0)
  12802. {
  12803. *pulPermMasks = dwHiMasks;
  12804. (*pulPermMasks) <<= 32;
  12805. *pulPermMasks += dwLowMasks;
  12806. }
  12807. return lResult;
  12808. }
  12809. LONG
  12810. WINAPI
  12811. tapiSetPermissibleMasks (
  12812. ULONG64 ulPermMasks
  12813. )
  12814. {
  12815. FUNC_ARGS funcArgs =
  12816. {
  12817. MAKELONG (TAPI_FUNC | SYNC | 2, tSetPermissibleMasks),
  12818. {
  12819. (ULONG_PTR)LOWDWORD(ulPermMasks), // ulPermMasks low
  12820. (ULONG_PTR)HIDWORD(ulPermMasks), // ulPermMasks hi
  12821. },
  12822. {
  12823. Dword,
  12824. Dword,
  12825. }
  12826. };
  12827. return (DOFUNC (&funcArgs, "tapiGetPermissibleMasks"));
  12828. }
  12829. BOOL
  12830. WaveStringIdToDeviceId(
  12831. LPWSTR pwszStringID,
  12832. LPCWSTR pwszDeviceType,
  12833. LPDWORD pdwDeviceId
  12834. )
  12835. {
  12836. //
  12837. // This function converts a wave device string ID to a numeric device ID
  12838. // The numeric device ID can be used in wave functions (waveOutOpen, etc)
  12839. //
  12840. if (!pwszDeviceType || !pwszStringID)
  12841. return FALSE;
  12842. LOG((TL_TRACE, "WaveStringIdToDeviceId (%S, %S) - enter", pwszStringID, pwszDeviceType));
  12843. // get the device id, based on string id and device class
  12844. if ( !_wcsicmp(pwszDeviceType, L"wave/in") ||
  12845. !_wcsicmp(pwszDeviceType, L"wave/in/out")
  12846. )
  12847. {
  12848. return (MMSYSERR_NOERROR == waveInMessage(
  12849. NULL,
  12850. DRV_QUERYIDFROMSTRINGID,
  12851. (DWORD_PTR)pwszStringID,
  12852. (DWORD_PTR)pdwDeviceId));
  12853. } else if (!_wcsicmp(pwszDeviceType, L"wave/out"))
  12854. {
  12855. return (MMSYSERR_NOERROR == waveOutMessage(
  12856. NULL,
  12857. DRV_QUERYIDFROMSTRINGID,
  12858. (DWORD_PTR)pwszStringID,
  12859. (DWORD_PTR)pdwDeviceId));
  12860. } else if (!_wcsicmp(pwszDeviceType, L"midi/in"))
  12861. {
  12862. return (MMSYSERR_NOERROR == midiInMessage(
  12863. NULL,
  12864. DRV_QUERYIDFROMSTRINGID,
  12865. (DWORD_PTR)pwszStringID,
  12866. (DWORD_PTR)pdwDeviceId));
  12867. } else if (!_wcsicmp(pwszDeviceType, L"midi/out"))
  12868. {
  12869. return (MMSYSERR_NOERROR == midiOutMessage(
  12870. NULL,
  12871. DRV_QUERYIDFROMSTRINGID,
  12872. (DWORD_PTR)pwszStringID,
  12873. (DWORD_PTR)pdwDeviceId));
  12874. }
  12875. LOG((TL_TRACE, "WaveStringIdToDeviceId (%S, %S) - failed", pwszStringID, pwszDeviceType));
  12876. return FALSE;
  12877. }