Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

16594 lines
392 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. #ifdef MEMPHIS
  3445. {
  3446. FARPROC pfn;
  3447. BOOL fResult;
  3448. DWORD dw;
  3449. OVERLAPPED o;
  3450. pfn = GetProcAddress(
  3451. hInst,
  3452. "GetCompletionPortStatus"
  3453. );
  3454. if ( NULL == pfn )
  3455. {
  3456. LOG((TL_ERROR, "It would seem CompletionPorts are not supported on this platform(1)"));
  3457. return (bLine ? LINEERR_INVALFEATURE : PHONEERR_OPERATIONFAILED);
  3458. }
  3459. fResult = pfn( -1, &dw, &dw, &o, 0 );
  3460. }
  3461. if ( ERROR_NOT_SUPPORTED != GetLastError() )
  3462. #endif
  3463. {
  3464. gpPostQueuedCompletionStatus = (PQCSPROC)GetProcAddress(
  3465. hInst,
  3466. "PostQueuedCompletionStatus"
  3467. );
  3468. if ( NULL == gpPostQueuedCompletionStatus )
  3469. {
  3470. LOG((TL_ERROR, "It would seem CompletionPorts are not supported on this platform"));
  3471. return (bLine ? LINEERR_INVALFEATURE : PHONEERR_OPERATIONFAILED);
  3472. }
  3473. }
  3474. }
  3475. break;
  3476. case LINEINITIALIZEEXOPTION_USEEVENT:
  3477. break;
  3478. default:
  3479. if (
  3480. (TAPI_VERSION2_0 == dwAPIVersion)
  3481. ||
  3482. (TAPI_VERSION2_1 == dwAPIVersion)
  3483. )
  3484. {
  3485. //
  3486. // This 2.x app is nuts.
  3487. //
  3488. return (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
  3489. }
  3490. else
  3491. {
  3492. //
  3493. // This >2.0 app is asking for something we can't do.
  3494. //
  3495. return (bLine ? LINEERR_INCOMPATIBLEAPIVERSION :
  3496. PHONEERR_INCOMPATIBLEAPIVERSION);
  3497. }
  3498. }
  3499. pXxxInitExParams->dwNeededSize =
  3500. pXxxInitExParams->dwUsedSize = sizeof (LINEINITIALIZEEXPARAMS);
  3501. }
  3502. __except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
  3503. dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
  3504. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  3505. {
  3506. return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
  3507. }
  3508. return 0;
  3509. }
  3510. LONG
  3511. GetTheModuleFileName( WCHAR ** ppName )
  3512. {
  3513. DWORD dwSize = MAX_PATH, dwLength;
  3514. WCHAR * pszModuleNamePathW;
  3515. alloc_module_name_buf:
  3516. if (!(pszModuleNamePathW = (WCHAR *)ClientAlloc (dwSize*sizeof(WCHAR))))
  3517. {
  3518. return LINEERR_NOMEM;
  3519. }
  3520. if (GetVersion() & 0x80000000)
  3521. {
  3522. PSTR pTemp;
  3523. //
  3524. // We're on Win9x - do ANSI
  3525. //
  3526. pTemp = (PSTR) ClientAlloc( dwSize );
  3527. if ( NULL == pTemp )
  3528. {
  3529. LOG((
  3530. TL_ERROR,
  3531. "Mem alloc failed (for mod name) size:0x%08lx",
  3532. dwSize
  3533. ));
  3534. return LINEERR_NOMEM;
  3535. }
  3536. if ((dwLength = GetModuleFileName(
  3537. NULL,
  3538. pTemp,
  3539. dwSize
  3540. )) == 0)
  3541. {
  3542. LOG((
  3543. TL_ERROR,
  3544. "GetModuleFileNameA failed, err=%d",
  3545. GetLastError()
  3546. ));
  3547. ClientFree( pTemp );
  3548. return LINEERR_INVALPARAM;
  3549. }
  3550. else if (dwLength >= dwSize)
  3551. {
  3552. ClientFree (pTemp);
  3553. ClientFree (pszModuleNamePathW);
  3554. dwSize *= 2;
  3555. goto alloc_module_name_buf;
  3556. }
  3557. MultiByteToWideChar(
  3558. GetACP(),
  3559. MB_PRECOMPOSED,
  3560. pTemp,
  3561. dwLength,
  3562. pszModuleNamePathW,
  3563. dwSize
  3564. );
  3565. ClientFree( pTemp );
  3566. }
  3567. else
  3568. {
  3569. //
  3570. // We're on WinNT - do Unicode
  3571. //
  3572. if ((dwLength = GetModuleFileNameW(
  3573. NULL,
  3574. pszModuleNamePathW,
  3575. dwSize
  3576. )) == 0)
  3577. {
  3578. LOG((
  3579. TL_ERROR,
  3580. "GetModuleFileNameW failed, err=%d",
  3581. GetLastError()
  3582. ));
  3583. return LINEERR_INVALPARAM;
  3584. }
  3585. else if (dwLength >= dwSize)
  3586. {
  3587. ClientFree (pszModuleNamePathW);
  3588. dwSize *= 2;
  3589. goto alloc_module_name_buf;
  3590. }
  3591. }
  3592. *ppName = pszModuleNamePathW;
  3593. return 0;
  3594. }
  3595. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3596. //
  3597. // CreateThreadsAndStuff
  3598. //
  3599. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  3600. // only and hence access to it is serialized. Calling this function from some
  3601. // other functionality would need making an alternate arrangement to serialize
  3602. // access to this function
  3603. //
  3604. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3605. LONG
  3606. CreateThreadsAndStuff()
  3607. {
  3608. DWORD dwThreadID;
  3609. LOG((TL_TRACE, "CreateThreadsAndStuff: enter"));
  3610. //
  3611. // Alloc resources for a new async events thread, then
  3612. // create the thread
  3613. //
  3614. gpAsyncEventsThreadParams = (PASYNC_EVENTS_THREAD_PARAMS) ClientAlloc(
  3615. sizeof (ASYNC_EVENTS_THREAD_PARAMS));
  3616. if (NULL == gpAsyncEventsThreadParams)
  3617. {
  3618. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate gpAsyncEventsThreadParams"));
  3619. return LINEERR_OPERATIONFAILED;
  3620. }
  3621. //
  3622. // we don't want the thread to exit as soon as it starts
  3623. //
  3624. gpAsyncEventsThreadParams->bExitThread = FALSE;
  3625. //
  3626. // Create the initial buffer the thread will use for
  3627. // retreiving async events
  3628. //
  3629. gpAsyncEventsThreadParams->dwBufSize =
  3630. ASNYC_MSG_BUF_SIZE;
  3631. gpAsyncEventsThreadParams->pBuf = (LPBYTE) ClientAlloc(
  3632. gpAsyncEventsThreadParams->dwBufSize);
  3633. if (NULL == gpAsyncEventsThreadParams->pBuf)
  3634. {
  3635. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate gpAsyncEventsThreadParams->pBuf"));
  3636. ClientFree( gpAsyncEventsThreadParams );
  3637. gpAsyncEventsThreadParams = NULL;
  3638. return LINEERR_OPERATIONFAILED;
  3639. }
  3640. ghAsyncRetryQueueEvent = CreateEvent(
  3641. NULL,
  3642. FALSE,
  3643. FALSE,
  3644. NULL
  3645. );
  3646. if (NULL == ghAsyncRetryQueueEvent)
  3647. {
  3648. LOG((TL_ERROR,
  3649. "CreateThreadsAndStuff - failed to create ghAsyncRetryQueueEvent event"));
  3650. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3651. ClientFree( gpAsyncEventsThreadParams );
  3652. gpAsyncEventsThreadParams = NULL;
  3653. return LINEERR_OPERATIONFAILED;
  3654. }
  3655. //
  3656. // create startup event -- the thread will signal it when it is up and
  3657. // ready to do stuff
  3658. //
  3659. gpAsyncEventsThreadParams->hThreadStartupEvent =
  3660. CreateEvent(NULL, FALSE, FALSE, NULL);
  3661. if (NULL == gpAsyncEventsThreadParams->hThreadStartupEvent)
  3662. {
  3663. LOG((TL_ERROR,
  3664. "CreateThreadsAndStuff - failed to create hThreadStartupEvent event. LastError= 0x%lx",
  3665. GetLastError()));
  3666. CloseHandle(ghAsyncRetryQueueEvent);
  3667. ghAsyncRetryQueueEvent = NULL;
  3668. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3669. ClientFree( gpAsyncEventsThreadParams );
  3670. gpAsyncEventsThreadParams = NULL;
  3671. return LINEERR_OPERATIONFAILED;
  3672. }
  3673. //
  3674. // Now that we've allocated all the resources try to exec
  3675. // the thread
  3676. //
  3677. ghAsyncEventsThread = CreateThread(
  3678. NULL,
  3679. 0,
  3680. (LPTHREAD_START_ROUTINE) AsyncEventsThread,
  3681. (LPVOID) gpAsyncEventsThreadParams,
  3682. 0,
  3683. &dwThreadID
  3684. );
  3685. if (NULL == ghAsyncEventsThread)
  3686. {
  3687. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to allocate AsyncEventsThread"));
  3688. CloseHandle(ghAsyncRetryQueueEvent);
  3689. ghAsyncRetryQueueEvent = NULL;
  3690. CloseHandle(gpAsyncEventsThreadParams->hThreadStartupEvent);
  3691. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3692. ClientFree(gpAsyncEventsThreadParams);
  3693. gpAsyncEventsThreadParams = NULL;
  3694. return LINEERR_OPERATIONFAILED;
  3695. }
  3696. //
  3697. // wait for the thread to have completed initialization or for the thread
  3698. // to exit. if the thread exited, it had an error, so return an error.
  3699. //
  3700. // this is needed so msp's do not initialize and start posting events
  3701. // before asynceventsthread opens up RetryQueue to accept these events.
  3702. //
  3703. // it would be more efficient to wait for these events immediately before
  3704. // creating address objects, but the code would be much more complex and
  3705. // the performance gain would be for tapi initialization only, so we won't
  3706. // bother.
  3707. //
  3708. HANDLE ahAsyncThreadEvents[] =
  3709. {
  3710. gpAsyncEventsThreadParams->hThreadStartupEvent,
  3711. ghAsyncEventsThread
  3712. };
  3713. DWORD dwWaitResult = WaitForMultipleObjectsEx(
  3714. sizeof(ahAsyncThreadEvents)/sizeof(HANDLE),
  3715. ahAsyncThreadEvents,
  3716. FALSE,
  3717. INFINITE,
  3718. FALSE);
  3719. //
  3720. // succeeded or failed, this event is no longer needed
  3721. //
  3722. CloseHandle(gpAsyncEventsThreadParams->hThreadStartupEvent);
  3723. gpAsyncEventsThreadParams->hThreadStartupEvent = NULL;
  3724. //
  3725. // did we unblock because the thread exited?
  3726. //
  3727. if (dwWaitResult == WAIT_OBJECT_0 + 1)
  3728. {
  3729. //
  3730. // thread exited
  3731. //
  3732. LOG((TL_ERROR, "CreateThreadsAndStuff: AsyncEventsThread exited"));
  3733. CloseHandle(ghAsyncRetryQueueEvent);
  3734. ghAsyncRetryQueueEvent = NULL;
  3735. CloseHandle(ghAsyncEventsThread);
  3736. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3737. ClientFree(gpAsyncEventsThreadParams);
  3738. gpAsyncEventsThreadParams = NULL;
  3739. return LINEERR_OPERATIONFAILED;
  3740. }
  3741. //
  3742. // did we unblock for any reason other than thread exited or success?
  3743. //
  3744. if (dwWaitResult != WAIT_OBJECT_0)
  3745. {
  3746. LOG((TL_ERROR, "CreateThreadsAndStuff: failed waiting tor AsyncEventsThread initialization"));
  3747. //
  3748. // we had an error waiting for the thread to signal its successful
  3749. // startup.
  3750. //
  3751. //
  3752. // if the thread is still up, tell it to stop.
  3753. //
  3754. gpAsyncEventsThreadParams->bExitThread = TRUE;
  3755. //
  3756. // we could wait for the thread to exit... but we got here because wait
  3757. // failed, so there is little benefit in retrying. so take our chances
  3758. // and clean up.
  3759. //
  3760. CloseHandle(ghAsyncRetryQueueEvent);
  3761. ghAsyncRetryQueueEvent = NULL;
  3762. CloseHandle(ghAsyncEventsThread);
  3763. ghAsyncEventsThread = NULL;
  3764. ClientFree(gpAsyncEventsThreadParams->pBuf);
  3765. ClientFree(gpAsyncEventsThreadParams);
  3766. gpAsyncEventsThreadParams = NULL;
  3767. return LINEERR_OPERATIONFAILED;
  3768. }
  3769. //
  3770. // if we got here, async events thread initialized and is running
  3771. //
  3772. ghCallbackThreadEvent = CreateEvent(
  3773. NULL,
  3774. FALSE,
  3775. FALSE,
  3776. NULL
  3777. );
  3778. gbExitThread = FALSE;
  3779. ghCallbackThread = CreateThread(
  3780. NULL,
  3781. 0,
  3782. (LPTHREAD_START_ROUTINE) CallbackThread,
  3783. (LPVOID) NULL,
  3784. 0,
  3785. &dwThreadID
  3786. );
  3787. if (NULL == ghCallbackThread)
  3788. {
  3789. // don't free these buffers. The other thread
  3790. // is already running at this point, the these
  3791. // buffers will be cleaned up during normal
  3792. // shutdown
  3793. //ClientFree(gpAsyncEventsThreadParams->pBuf);
  3794. //ClientFree(gpAsyncEventsThreadParams);
  3795. LOG((TL_ERROR, "CreateThreadsAndStuff: failed to create CallbackThread"));
  3796. return LINEERR_OPERATIONFAILED;
  3797. }
  3798. LOG((TL_TRACE, "CreateThreadsAndStuff: exit"));
  3799. return 0;
  3800. }
  3801. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3802. //
  3803. // NewInitialize
  3804. //
  3805. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  3806. // only and hence access to it is serialized. Calling this function from some
  3807. // other functionality would need making an alternate arrangement to serialize
  3808. // access to this function
  3809. //
  3810. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  3811. HRESULT
  3812. CTAPI::NewInitialize()
  3813. {
  3814. LOG((TL_INFO, "NewInitialize - enter"));
  3815. FUNC_ARGS funcArgs =
  3816. {
  3817. MAKELONG (LINE_FUNC | SYNC | 7, lInitialize),
  3818. {
  3819. (ULONG_PTR) &m_hLineApp,
  3820. // tapisrv ignores this argument, so pass 0 and save on HINSTANCE<->32bit conversion
  3821. 0,
  3822. 0,
  3823. (ULONG_PTR) gszTAPI3,
  3824. (ULONG_PTR) &m_dwLineDevs,
  3825. 0, // pszModuleName
  3826. TAPI_CURRENT_VERSION
  3827. },
  3828. {
  3829. lpDword,
  3830. Dword,
  3831. Dword,
  3832. lpszW,
  3833. lpDword,
  3834. lpszW,
  3835. Dword
  3836. }
  3837. };
  3838. WCHAR * pszModuleNamePathW = NULL;
  3839. LONG lResult = (LONG)S_OK;
  3840. int tapiObjectArraySize=0;
  3841. lResult = GetTheModuleFileName( &pszModuleNamePathW );
  3842. if ( 0!= lResult )
  3843. {
  3844. goto xxxInitialize_return;
  3845. }
  3846. funcArgs.Args[5] = (ULONG_PTR) wcsrchr (pszModuleNamePathW, '\\') +
  3847. sizeof(WCHAR);
  3848. _ASSERTE(m_pLineInitData == NULL);
  3849. m_pLineInitData = (PT3INIT_DATA) ClientAlloc (sizeof(T3INIT_DATA));
  3850. if (NULL == m_pLineInitData)
  3851. {
  3852. LOG((TL_ERROR, "NewInitialize: failed to allocate m_pLineInitData"));
  3853. lResult = LINEERR_NOMEM;
  3854. goto xxxInitialize_return;
  3855. }
  3856. m_pLineInitData->dwInitOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW |
  3857. LINEINITIALIZEEXOPTION_CALLHUBTRACKING;
  3858. m_pLineInitData->bPendingAsyncEventMsg = FALSE;
  3859. m_pLineInitData->dwKey = INITDATA_KEY;
  3860. m_pLineInitData->pTAPI = this;
  3861. //
  3862. // We want to pass TAPISRV pInitData so that later when it does async
  3863. // completion/event notification it can pass pInitData along too so
  3864. // we know which init instance to talk to
  3865. //
  3866. //
  3867. // convert the pointer into a 32-bit handle, so we don't need to pass a
  3868. // 64-bit value between tapi3.dll and tapisrv
  3869. //
  3870. _ASSERTE(m_dwLineInitDataHandle == 0);
  3871. m_dwLineInitDataHandle = CreateHandleTableEntry((ULONG_PTR)m_pLineInitData);
  3872. LOG((TL_INFO, "NewInitialize: handle for m_pLineInitData = [0x%lx]", m_dwLineInitDataHandle));
  3873. if (0 == m_dwLineInitDataHandle)
  3874. {
  3875. LOG((TL_ERROR, "NewInitialize: failed to create handle"));
  3876. ClientFree(m_pLineInitData);
  3877. m_pLineInitData = NULL;
  3878. lResult = LINEERR_NOMEM;
  3879. goto xxxInitialize_return;
  3880. }
  3881. funcArgs.Args[2] = m_dwLineInitDataHandle;
  3882. //
  3883. // call lineInitialize
  3884. //
  3885. lResult = DOFUNC (&funcArgs, "lineInitialize");
  3886. if (lResult == 0)
  3887. {
  3888. LOG((TL_INFO, "NewInitialize: lineInitialize succeeded. m_hLineApp %p", m_hLineApp));
  3889. }
  3890. else
  3891. {
  3892. LOG((TL_ERROR, "NewInitialize: lineInitialize failed. "));
  3893. //
  3894. // undo the deed
  3895. //
  3896. ClientFree(m_pLineInitData);
  3897. m_pLineInitData = NULL;
  3898. DeleteHandleTableEntry(m_dwLineInitDataHandle);
  3899. m_dwLineInitDataHandle = NULL;
  3900. goto xxxInitialize_return;
  3901. }
  3902. //
  3903. // Save the hLineApp returned by TAPISRV in our InitData struct,
  3904. // and give the app back a pointer to the InitData struct instead
  3905. //
  3906. m_pLineInitData->hXxxApp = m_hLineApp;
  3907. //
  3908. // now setup for phoneinitialize
  3909. //
  3910. funcArgs.Args[0] = (ULONG_PTR)&m_hPhoneApp;
  3911. funcArgs.Args[4] = (ULONG_PTR)&m_dwPhoneDevs;
  3912. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 7, pInitialize);
  3913. _ASSERTE(m_pPhoneInitData == NULL);
  3914. m_pPhoneInitData = (PT3INIT_DATA) ClientAlloc (sizeof(T3INIT_DATA));
  3915. if ( NULL == m_pPhoneInitData )
  3916. {
  3917. LOG((TL_ERROR, "NewInitialize: failed to allocate m_pPhoneInitData"));
  3918. lResult = LINEERR_NOMEM;
  3919. goto xxxInitialize_return;
  3920. }
  3921. m_pPhoneInitData->dwInitOptions = LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
  3922. m_pPhoneInitData->bPendingAsyncEventMsg = FALSE;
  3923. m_pPhoneInitData->dwKey = INITDATA_KEY;
  3924. m_pPhoneInitData ->pTAPI = this;
  3925. //
  3926. // We want to pass TAPISRV pInitData so that later when it does async
  3927. // completion/event notification it can pass pInitData along too so
  3928. // we know which init instance to talk to
  3929. //
  3930. //
  3931. // convert the pointer into a 32-bit handle, so we don't need to pass a
  3932. // 64-bit value between tapi3.dll and tapisrv
  3933. //
  3934. _ASSERTE(m_dwPhoneInitDataHandle == 0);
  3935. m_dwPhoneInitDataHandle = CreateHandleTableEntry((ULONG_PTR)m_pPhoneInitData );
  3936. LOG((TL_INFO, "NewInitialize: handle for m_pPhoneInitData = [0x%lx]", m_dwPhoneInitDataHandle));
  3937. if (0 == m_dwPhoneInitDataHandle)
  3938. {
  3939. LOG((TL_ERROR, "NewInitialize: failed to create handle"));
  3940. //
  3941. // free the phone-related resources that we have already allocated
  3942. //
  3943. ClientFree(m_pPhoneInitData);
  3944. m_pPhoneInitData = NULL;
  3945. lResult = LINEERR_NOMEM;
  3946. goto xxxInitialize_return;
  3947. }
  3948. funcArgs.Args[2] = m_dwPhoneInitDataHandle;
  3949. lResult = DOFUNC (&funcArgs, "phoneInitialize");
  3950. if (lResult == 0)
  3951. {
  3952. LOG((TL_INFO, "NewInitialize: phoneInitialize succeeded. m_hPhoneApp %p", m_hPhoneApp));
  3953. }
  3954. else
  3955. {
  3956. LOG((TL_ERROR, "NewInitialize: phoneInitialize failed. "));
  3957. //
  3958. // deallocate whatever resources we have allocated for the phone
  3959. //
  3960. ClientFree(m_pPhoneInitData);
  3961. m_pPhoneInitData = NULL;
  3962. DeleteHandleTableEntry(m_dwPhoneInitDataHandle);
  3963. m_dwPhoneInitDataHandle = 0;
  3964. goto xxxInitialize_return;
  3965. }
  3966. m_pPhoneInitData ->hXxxApp = m_hPhoneApp;
  3967. //
  3968. // If total number of init instances is 0 we need to start a
  3969. // new async events thread
  3970. //
  3971. EnterCriticalSection( &gcsTapiObjectArray );
  3972. tapiObjectArraySize = m_sTAPIObjectArray.GetSize();
  3973. LeaveCriticalSection ( &gcsTapiObjectArray );
  3974. if ( 0 == tapiObjectArraySize )
  3975. {
  3976. lResult = CreateThreadsAndStuff();
  3977. if ( 0 != lResult )
  3978. {
  3979. goto xxxInitialize_return;
  3980. }
  3981. }
  3982. xxxInitialize_return:
  3983. if (pszModuleNamePathW)
  3984. {
  3985. ClientFree (pszModuleNamePathW);
  3986. }
  3987. if ( 0 != lResult )
  3988. {
  3989. //
  3990. // cleanup all line- and phone-related resources.
  3991. //
  3992. NewShutdown();
  3993. }
  3994. #if DBG
  3995. {
  3996. char szResult[32];
  3997. LOG((
  3998. TL_INFO,
  3999. "Initialize exit, result=%s",
  4000. MapResultCodeToText (lResult, szResult)
  4001. ));
  4002. }
  4003. #else
  4004. //
  4005. // we may want to know what happened even with non-debug build
  4006. //
  4007. LOG((TL_INFO, "NewInitialize - exit, result=0x%lx", lResult));
  4008. #endif
  4009. return mapTAPIErrorCode( lResult );
  4010. }
  4011. //
  4012. // --------------------------------- lineXxx ----------------------------------
  4013. //
  4014. HRESULT
  4015. LineAccept(
  4016. HCALL hCall,
  4017. LPCSTR lpsUserUserInfo,
  4018. DWORD dwSize
  4019. )
  4020. {
  4021. FUNC_ARGS funcArgs =
  4022. {
  4023. MAKELONG (LINE_FUNC | ASYNC | 3, lAccept),
  4024. {
  4025. (ULONG_PTR) hCall,
  4026. (ULONG_PTR) lpsUserUserInfo,
  4027. dwSize
  4028. },
  4029. {
  4030. Dword,
  4031. lpSet_SizeToFollow,
  4032. Size
  4033. }
  4034. };
  4035. if (!lpsUserUserInfo)
  4036. {
  4037. //
  4038. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4039. //
  4040. funcArgs.ArgTypes[1] = Dword;
  4041. funcArgs.Args[1] = TAPI_NO_DATA;
  4042. funcArgs.ArgTypes[2] = Dword;
  4043. }
  4044. return mapTAPIErrorCode( (DOFUNC (&funcArgs, "lineAccept")) );
  4045. }
  4046. HRESULT
  4047. LineAddToConference(
  4048. HCALL hConfCall,
  4049. HCALL hConsultCall
  4050. )
  4051. {
  4052. FUNC_ARGS funcArgs =
  4053. {
  4054. MAKELONG (LINE_FUNC | ASYNC | 2, lAddToConference),
  4055. {
  4056. (ULONG_PTR) hConfCall,
  4057. (ULONG_PTR) hConsultCall
  4058. },
  4059. {
  4060. Dword,
  4061. Dword
  4062. }
  4063. };
  4064. return mapTAPIErrorCode( (DOFUNC (&funcArgs, "LineAddToConference")) );
  4065. }
  4066. LONG
  4067. WINAPI
  4068. lineAgentSpecific(
  4069. HLINE hLine,
  4070. DWORD dwAddressID,
  4071. DWORD dwAgentExtensionIDIndex,
  4072. LPVOID lpParams,
  4073. DWORD dwSize
  4074. )
  4075. {
  4076. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR) lpParams);
  4077. FUNC_ARGS funcArgs =
  4078. {
  4079. MAKELONG (LINE_FUNC | ASYNC | 7, lAgentSpecific),
  4080. {
  4081. GetFunctionIndex(lineDevSpecificPostProcess),
  4082. (ULONG_PTR) hLine,
  4083. (ULONG_PTR) dwAddressID,
  4084. (ULONG_PTR) dwAgentExtensionIDIndex,
  4085. hpParams,
  4086. (ULONG_PTR) lpParams,
  4087. (ULONG_PTR) dwSize
  4088. },
  4089. {
  4090. Dword,
  4091. Dword,
  4092. Dword,
  4093. Dword,
  4094. Dword,
  4095. lpSet_SizeToFollow,
  4096. Size
  4097. }
  4098. };
  4099. LONG lResult = DOFUNC (&funcArgs, "lineAgentSpecific");
  4100. //
  4101. // in case of failure or synchronous call, delete the entry from the table
  4102. // otherwise, the callback will do that
  4103. //
  4104. if (lResult <= 0)
  4105. {
  4106. DeleteHandleTableEntry(hpParams);
  4107. }
  4108. return lResult;
  4109. }
  4110. HRESULT
  4111. LineAnswer(
  4112. HCALL hCall
  4113. )
  4114. {
  4115. FUNC_ARGS funcArgs =
  4116. {
  4117. MAKELONG (LINE_FUNC | ASYNC | 3, lAnswer),
  4118. {
  4119. (ULONG_PTR) hCall,
  4120. (ULONG_PTR) 0,
  4121. 0
  4122. },
  4123. {
  4124. Dword,
  4125. Dword,
  4126. Dword
  4127. }
  4128. };
  4129. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineAnswer") );
  4130. }
  4131. HRESULT
  4132. LineBlindTransfer(
  4133. HCALL hCall,
  4134. LPCWSTR lpszDestAddress,
  4135. DWORD dwCountryCode
  4136. )
  4137. {
  4138. FUNC_ARGS funcArgs =
  4139. {
  4140. MAKELONG (LINE_FUNC | ASYNC | 3, lBlindTransfer),
  4141. {
  4142. (ULONG_PTR) hCall,
  4143. (ULONG_PTR) lpszDestAddress,
  4144. dwCountryCode
  4145. },
  4146. {
  4147. Dword,
  4148. lpszW,
  4149. Dword
  4150. }
  4151. };
  4152. if ( IsBadStringPtrW( lpszDestAddress, (UINT)-1 ) )
  4153. {
  4154. LOG((TL_ERROR, "LineBlindTransfer: bad lpszDestAddress: 0x%p", lpszDestAddress));
  4155. return mapTAPIErrorCode(LINEERR_INVALPOINTER);
  4156. }
  4157. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineBlindTransfer") );
  4158. }
  4159. HRESULT
  4160. LineClose(
  4161. T3LINE * pt3Line
  4162. )
  4163. {
  4164. LONG lResult;
  4165. FUNC_ARGS funcArgs =
  4166. {
  4167. MAKELONG (LINE_FUNC | SYNC | 1, lClose),
  4168. {
  4169. (ULONG_PTR) pt3Line->hLine
  4170. },
  4171. {
  4172. Dword
  4173. }
  4174. };
  4175. gpLineHashTable->Lock();
  4176. lResult = DOFUNC (&funcArgs, "lineClose");
  4177. LOG((TL_INFO, "lineClose: line - %lx lResult %lx", pt3Line->hLine, lResult));
  4178. gpLineHashTable->Remove( (ULONG_PTR)(pt3Line->hLine) );
  4179. gpLineHashTable->Unlock();
  4180. //
  4181. // remove the corresponding entry from the callback instance handle table
  4182. //
  4183. if (0 != pt3Line->dwAddressLineStructHandle)
  4184. {
  4185. LOG((TL_INFO, "lineClose: removing address line handle [%lx] from the handle table",
  4186. pt3Line->dwAddressLineStructHandle));
  4187. DeleteHandleTableEntry(pt3Line->dwAddressLineStructHandle);
  4188. pt3Line->dwAddressLineStructHandle = 0;
  4189. }
  4190. return mapTAPIErrorCode( lResult );
  4191. }
  4192. void
  4193. PASCAL
  4194. lineCompleteCallPostProcess(
  4195. PASYNCEVENTMSG pMsg
  4196. )
  4197. {
  4198. LOG((TL_TRACE, "lineCompleteCallPostProcess: enter"));
  4199. LOG((
  4200. TL_INFO,
  4201. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4202. pMsg->Param1,
  4203. pMsg->Param2,
  4204. pMsg->Param3,
  4205. pMsg->Param4
  4206. ));
  4207. if (pMsg->Param2 == 0)
  4208. {
  4209. DWORD dwCompletionID = pMsg->Param3;
  4210. LPDWORD lpdwCompletionID = (LPDWORD)GetHandleTableEntry(pMsg->Param4);
  4211. DeleteHandleTableEntry(pMsg->Param4);
  4212. __try
  4213. {
  4214. {
  4215. *lpdwCompletionID = dwCompletionID;
  4216. }
  4217. }
  4218. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4219. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4220. {
  4221. LOG((TL_WARN, "lineCompleteCallPostProcess: failed "
  4222. "to write to [%p]: LINEERR_INVALPOINTER",
  4223. lpdwCompletionID));
  4224. pMsg->Param2 = LINEERR_INVALPOINTER;
  4225. }
  4226. }
  4227. }
  4228. LONG
  4229. WINAPI
  4230. lineCompleteCall(
  4231. HCALL hCall,
  4232. LPDWORD lpdwCompletionID,
  4233. DWORD dwCompletionMode,
  4234. DWORD dwMessageID
  4235. )
  4236. {
  4237. DWORD hpdwCompletionID = CreateHandleTableEntry((ULONG_PTR)lpdwCompletionID);
  4238. FUNC_ARGS funcArgs =
  4239. {
  4240. MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteCall),
  4241. {
  4242. GetFunctionIndex(lineCompleteCallPostProcess),
  4243. (ULONG_PTR) hCall,
  4244. hpdwCompletionID,
  4245. dwCompletionMode,
  4246. dwMessageID
  4247. },
  4248. {
  4249. Dword,
  4250. Dword,
  4251. lpDword,
  4252. Dword,
  4253. Dword
  4254. }
  4255. };
  4256. LONG lResult = (DOFUNC (&funcArgs, "lineCompleteCall"));
  4257. //
  4258. // in case of failure or synchronous call, delete the entry from the table
  4259. // otherwise, the callback will do that
  4260. //
  4261. if (lResult <= 0)
  4262. {
  4263. DeleteHandleTableEntry(hpdwCompletionID);
  4264. }
  4265. return lResult;
  4266. }
  4267. HRESULT
  4268. LineCompleteTransfer(
  4269. HCALL hCall,
  4270. HCALL hConsultCall,
  4271. T3CALL * pt3ConfCall,
  4272. DWORD dwTransferMode
  4273. )
  4274. {
  4275. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR) &(pt3ConfCall->hCall));
  4276. FUNC_ARGS funcArgs =
  4277. {
  4278. MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteTransfer),
  4279. {
  4280. GetFunctionIndex(lineMakeCallPostProcess),
  4281. hCall,
  4282. hConsultCall,
  4283. hpCallHandle,
  4284. dwTransferMode,
  4285. },
  4286. {
  4287. Dword,
  4288. Dword,
  4289. Dword,
  4290. Dword,
  4291. Dword,
  4292. }
  4293. };
  4294. if (dwTransferMode == LINETRANSFERMODE_TRANSFER)
  4295. {
  4296. funcArgs.Args[0] = 0;
  4297. //
  4298. // hpCallHandle should be ignored
  4299. //
  4300. funcArgs.Args[3] = 0;
  4301. DeleteHandleTableEntry(hpCallHandle);
  4302. hpCallHandle = 0;
  4303. }
  4304. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCompleteTransfer") );
  4305. if (FAILED(hr))
  4306. {
  4307. DeleteHandleTableEntry(hpCallHandle);
  4308. hpCallHandle = 0;
  4309. }
  4310. return hr ;
  4311. }
  4312. HRESULT
  4313. LineConfigDialogW(
  4314. DWORD dwDeviceID,
  4315. HWND hwndOwner,
  4316. LPCWSTR lpszDeviceClass
  4317. )
  4318. {
  4319. LONG lResult;
  4320. HANDLE hDll;
  4321. TUISPIPROC pfnTUISPI_lineConfigDialog;
  4322. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, 256))
  4323. {
  4324. return E_POINTER;
  4325. }
  4326. if ((lResult = LoadUIDll(
  4327. hwndOwner,
  4328. dwDeviceID,
  4329. TUISPIDLL_OBJECT_LINEID,
  4330. &hDll,
  4331. gszTUISPI_lineConfigDialog,
  4332. &pfnTUISPI_lineConfigDialog
  4333. )) == 0)
  4334. {
  4335. LOG((TL_INFO, "Calling TUISPI_lineConfigDialog..."));
  4336. lResult = ((TUILINECONFIGPROC)(*pfnTUISPI_lineConfigDialog))(
  4337. TUISPIDLLCallback,
  4338. dwDeviceID,
  4339. (HWND)hwndOwner,
  4340. (LPCSTR)lpszDeviceClass
  4341. );
  4342. #if DBG
  4343. {
  4344. char szResult[32];
  4345. LOG((TL_INFO,
  4346. "TUISPI_lineConfigDialog: result = %s",
  4347. MapResultCodeToText (lResult, szResult)
  4348. ));
  4349. }
  4350. #endif
  4351. FreeLibrary ((HINSTANCE)hDll);
  4352. }
  4353. return mapTAPIErrorCode(lResult);
  4354. }
  4355. HRESULT
  4356. LineConfigDialogEditW(
  4357. DWORD dwDeviceID,
  4358. HWND hwndOwner,
  4359. LPCWSTR lpszDeviceClass,
  4360. LPVOID const lpDeviceConfigIn,
  4361. DWORD dwSizeIn,
  4362. LPVARSTRING * ppDeviceConfigOut
  4363. )
  4364. {
  4365. LONG lResult;
  4366. HANDLE hDll;
  4367. TUISPIPROC pfnTUISPI_lineConfigDialogEdit;
  4368. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, (UINT) -1))
  4369. {
  4370. return E_POINTER;
  4371. }
  4372. if (IsBadReadPtr (lpDeviceConfigIn, dwSizeIn))
  4373. {
  4374. return E_POINTER;
  4375. }
  4376. DWORD dwSize = sizeof (VARSTRING) + 500;
  4377. *ppDeviceConfigOut = (LPVARSTRING) ClientAlloc( dwSize );
  4378. if (NULL == *ppDeviceConfigOut)
  4379. {
  4380. LOG((TL_ERROR, "LineConfigDialogEditW exit - return E_OUTOFMEMORY"));
  4381. return E_OUTOFMEMORY;
  4382. }
  4383. (*ppDeviceConfigOut)->dwTotalSize = dwSize;
  4384. if ((lResult = LoadUIDll(
  4385. hwndOwner,
  4386. dwDeviceID,
  4387. TUISPIDLL_OBJECT_LINEID,
  4388. &hDll,
  4389. gszTUISPI_lineConfigDialogEdit,
  4390. &pfnTUISPI_lineConfigDialogEdit
  4391. )) == 0)
  4392. {
  4393. while (TRUE)
  4394. {
  4395. LOG((TL_INFO, "Calling TUISPI_lineConfigDialogEdit..."));
  4396. lResult = ((TUILINECONFIGEDITPROC)(*pfnTUISPI_lineConfigDialogEdit))(
  4397. TUISPIDLLCallback,
  4398. dwDeviceID,
  4399. (HWND)hwndOwner,
  4400. (char *)lpszDeviceClass,
  4401. lpDeviceConfigIn,
  4402. dwSizeIn,
  4403. *ppDeviceConfigOut
  4404. );
  4405. #if DBG
  4406. {
  4407. char szResult[32];
  4408. LOG((TL_INFO,
  4409. "TUISPI_lineConfigDialogEdit: result = %s",
  4410. MapResultCodeToText (lResult, szResult)
  4411. ));
  4412. }
  4413. #endif
  4414. if ((lResult == 0) && ((*ppDeviceConfigOut)->dwNeededSize > (*ppDeviceConfigOut)->dwTotalSize))
  4415. {
  4416. dwSize = (*ppDeviceConfigOut)->dwNeededSize;
  4417. ClientFree(*ppDeviceConfigOut);
  4418. *ppDeviceConfigOut = (LPVARSTRING)ClientAlloc(dwSize);
  4419. if (NULL == *ppDeviceConfigOut)
  4420. {
  4421. LOG((TL_ERROR, "LineConfigDialogEditW exit - return E_OUTOFMEMORY"));
  4422. return E_OUTOFMEMORY;
  4423. }
  4424. (*ppDeviceConfigOut)->dwTotalSize = dwSize;
  4425. }
  4426. else
  4427. {
  4428. break;
  4429. }
  4430. }
  4431. FreeLibrary ((HINSTANCE)hDll);
  4432. }
  4433. return mapTAPIErrorCode(lResult);
  4434. }
  4435. LONG
  4436. WINAPI
  4437. lineConfigProvider(
  4438. HWND hwndOwner,
  4439. DWORD dwPermanentProviderID
  4440. )
  4441. {
  4442. return (lineXxxProvider(
  4443. gszTUISPI_providerConfig, // func name
  4444. NULL, // lpszProviderFilename
  4445. hwndOwner, // hwndOwner
  4446. dwPermanentProviderID, // dwPermProviderID
  4447. NULL // lpdwPermProviderID
  4448. ));
  4449. }
  4450. HRESULT
  4451. LineDeallocateCall(
  4452. HCALL hCall
  4453. )
  4454. {
  4455. HRESULT hr;
  4456. FUNC_ARGS funcArgs =
  4457. {
  4458. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
  4459. {
  4460. (ULONG_PTR) hCall
  4461. },
  4462. {
  4463. Dword
  4464. }
  4465. };
  4466. LOG((TL_INFO, "lineDeallocateCall - hCall = 0x%08lx", hCall));
  4467. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineDeallocateCall") );
  4468. return hr;
  4469. }
  4470. void
  4471. PASCAL
  4472. lineDevSpecificPostProcess(
  4473. PASYNCEVENTMSG pMsg
  4474. )
  4475. {
  4476. LOG((TL_TRACE, "lineDevSpecificPostProcess: enter"));
  4477. LOG((TL_INFO,
  4478. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4479. pMsg->Param1,
  4480. pMsg->Param2,
  4481. pMsg->Param3,
  4482. pMsg->Param4
  4483. ));
  4484. if (pMsg->Param2 == 0)
  4485. {
  4486. DWORD dwSize = pMsg->Param4;
  4487. LPBYTE pParams = (LPBYTE) GetHandleTableEntry(pMsg->Param3);
  4488. //
  4489. // no longer need the handle table entry for this handle
  4490. //
  4491. DeleteHandleTableEntry(pMsg->Param3);
  4492. __try
  4493. {
  4494. {
  4495. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  4496. }
  4497. }
  4498. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4499. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4500. {
  4501. pMsg->Param2 = LINEERR_INVALPOINTER;
  4502. LOG((TL_INFO,
  4503. "lineDevSpecificPostProcess: failed to copy memory to "
  4504. "[%p] from [%p]: LINEERR_INVALPOINTER",
  4505. pParams, (LPBYTE) (pMsg + 1)));
  4506. }
  4507. }
  4508. LOG((TL_TRACE, "lineDevSpecificPostProcess: exit"));
  4509. }
  4510. HRESULT
  4511. WINAPI
  4512. lineDevSpecific(
  4513. HLINE hLine,
  4514. DWORD dwAddressID,
  4515. HCALL hCall,
  4516. LPVOID lpParams,
  4517. DWORD dwSize
  4518. )
  4519. {
  4520. //
  4521. // convert the pointer to a handle. the table entry will be removed in
  4522. // the callback
  4523. //
  4524. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  4525. FUNC_ARGS funcArgs =
  4526. {
  4527. MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecific),
  4528. {
  4529. GetFunctionIndex(lineDevSpecificPostProcess),
  4530. (ULONG_PTR) hLine,
  4531. dwAddressID,
  4532. (ULONG_PTR) hCall,
  4533. hpParams, // pass the handle to actual pointer (for post processing)
  4534. (ULONG_PTR) lpParams, // pass data
  4535. dwSize
  4536. },
  4537. {
  4538. Dword,
  4539. Dword,
  4540. Dword,
  4541. Dword,
  4542. Dword,
  4543. lpSet_SizeToFollow,
  4544. Size
  4545. }
  4546. };
  4547. LONG lResult = DOFUNC (&funcArgs, "lineDevSpecific");
  4548. //
  4549. // if failed, or synchronous call, remove the handle table entry. otherwise
  4550. // the callback will do this.
  4551. //
  4552. HRESULT hr = E_FAIL;
  4553. if (lResult <= 0)
  4554. {
  4555. DeleteHandleTableEntry(hpParams);
  4556. hpParams = 0;
  4557. hr = mapTAPIErrorCode(lResult);
  4558. }
  4559. else
  4560. {
  4561. //
  4562. // block to see if the operation succeeds
  4563. //
  4564. hr = WaitForReply(lResult);
  4565. }
  4566. return hr;
  4567. }
  4568. LONG
  4569. WINAPI
  4570. lineDevSpecificFeature(
  4571. HLINE hLine,
  4572. DWORD dwFeature,
  4573. LPVOID lpParams,
  4574. DWORD dwSize
  4575. )
  4576. {
  4577. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  4578. FUNC_ARGS funcArgs =
  4579. {
  4580. MAKELONG (LINE_FUNC | ASYNC | 6, lDevSpecificFeature),
  4581. {
  4582. GetFunctionIndex(lineDevSpecificPostProcess),
  4583. (ULONG_PTR) hLine,
  4584. dwFeature,
  4585. hpParams, // pass the actual pointer (for post processing)
  4586. (ULONG_PTR) lpParams, // pass data
  4587. dwSize
  4588. },
  4589. {
  4590. Dword,
  4591. Dword,
  4592. Dword,
  4593. Dword,
  4594. lpSet_SizeToFollow,
  4595. Size
  4596. }
  4597. };
  4598. LONG lResult = DOFUNC (&funcArgs, "lineDevSpecificFeature");
  4599. //
  4600. // if failed, or synchronous call, remove the handle table entry.
  4601. // otherwise the callback will do this.
  4602. //
  4603. if (lResult <= 0)
  4604. {
  4605. DeleteHandleTableEntry(hpParams);
  4606. }
  4607. return lResult;
  4608. }
  4609. HRESULT
  4610. LineDial(
  4611. HCALL hCall,
  4612. LPCWSTR lpszDestAddress,
  4613. DWORD dwCountryCode
  4614. )
  4615. {
  4616. FUNC_ARGS funcArgs =
  4617. {
  4618. MAKELONG (LINE_FUNC | ASYNC | 3, lDial),
  4619. {
  4620. (ULONG_PTR) hCall,
  4621. (ULONG_PTR) lpszDestAddress,
  4622. dwCountryCode
  4623. },
  4624. {
  4625. Dword,
  4626. lpszW,
  4627. Dword
  4628. }
  4629. };
  4630. if ( IsBadStringPtrW(lpszDestAddress, (UINT)-1) )
  4631. {
  4632. LOG((TL_ERROR, "Bad lpszDestAddress in lineDial"));
  4633. return mapTAPIErrorCode( LINEERR_INVALPOINTER );
  4634. }
  4635. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineDial") );
  4636. }
  4637. LONG
  4638. LineDrop(
  4639. HCALL hCall,
  4640. LPCSTR lpsUserUserInfo,
  4641. DWORD dwSize
  4642. )
  4643. {
  4644. FUNC_ARGS funcArgs =
  4645. {
  4646. MAKELONG (LINE_FUNC | ASYNC | 3, lDrop),
  4647. {
  4648. (ULONG_PTR) hCall,
  4649. (ULONG_PTR) lpsUserUserInfo,
  4650. dwSize
  4651. },
  4652. {
  4653. Dword,
  4654. lpSet_SizeToFollow,
  4655. Size
  4656. }
  4657. };
  4658. if (!lpsUserUserInfo)
  4659. {
  4660. //
  4661. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4662. //
  4663. funcArgs.ArgTypes[1] = Dword;
  4664. funcArgs.Args[1] = TAPI_NO_DATA;
  4665. funcArgs.ArgTypes[2] = Dword;
  4666. }
  4667. return (DOFUNC (&funcArgs, "lineDrop"));
  4668. }
  4669. HRESULT
  4670. LineForward(
  4671. T3LINE * pt3Line,
  4672. DWORD dwAddressID,
  4673. LPLINEFORWARDLIST const lpForwardList,
  4674. DWORD dwNumRingsNoAnswer,
  4675. LPHCALL lphConsultCall
  4676. )
  4677. {
  4678. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)lphConsultCall);
  4679. FUNC_ARGS funcArgs =
  4680. {
  4681. MAKELONG (LINE_FUNC | ASYNC | 9, lForward),
  4682. {
  4683. GetFunctionIndex(lineMakeCallPostProcess),
  4684. (ULONG_PTR) pt3Line->hLine,
  4685. FALSE,
  4686. dwAddressID,
  4687. (ULONG_PTR) lpForwardList,
  4688. dwNumRingsNoAnswer,
  4689. hpCallHandle,
  4690. TAPI_NO_DATA,
  4691. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  4692. },
  4693. {
  4694. Dword,
  4695. Dword,
  4696. Dword,
  4697. Dword,
  4698. lpSet_Struct,
  4699. Dword,
  4700. Dword,
  4701. Dword,
  4702. Dword
  4703. }
  4704. };
  4705. if (!lpForwardList)
  4706. {
  4707. //
  4708. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4709. //
  4710. funcArgs.ArgTypes[4] = Dword;
  4711. funcArgs.Args[4] = TAPI_NO_DATA;
  4712. }
  4713. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineForwardW") );
  4714. if (FAILED(hr))
  4715. {
  4716. DeleteHandleTableEntry(hpCallHandle);
  4717. }
  4718. return hr;
  4719. }
  4720. void
  4721. PASCAL
  4722. lineGatherDigitsWPostProcess(
  4723. PASYNCEVENTMSG pMsg
  4724. )
  4725. {
  4726. LOG((TL_TRACE, "lineGatherDigitsWPostProcess: enter"));
  4727. LOG((TL_INFO,
  4728. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  4729. pMsg->Param1,
  4730. pMsg->Param2,
  4731. pMsg->Param3,
  4732. pMsg->Param4
  4733. ));
  4734. if (pMsg->Param1 & (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
  4735. LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
  4736. {
  4737. LPSTR lpsDigits = (LPSTR) GetHandleTableEntry(pMsg->Param2);
  4738. //
  4739. // no longer need the handle table entry
  4740. //
  4741. DeleteHandleTableEntry(pMsg->Param2);
  4742. DWORD dwNumDigits = pMsg->Param4;
  4743. LPWSTR pBuffer = (LPWSTR) (((ULONG_PTR *)(pMsg + 1)) + 2);
  4744. __try
  4745. {
  4746. {
  4747. CopyMemory (lpsDigits, pBuffer, dwNumDigits * sizeof(WCHAR));
  4748. }
  4749. }
  4750. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  4751. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  4752. {
  4753. //
  4754. // Don't do anything if we GPF
  4755. //
  4756. LOG((TL_WARN,
  4757. "lineGatherDigitsWPostProcess: "
  4758. "failed to write %lx digits to memory [%p]",
  4759. dwNumDigits, lpsDigits));
  4760. }
  4761. }
  4762. pMsg->Param2 = pMsg->Param3 = 0;
  4763. }
  4764. HRESULT
  4765. LineGatherDigits(
  4766. HCALL hCall,
  4767. DWORD dwDigitModes,
  4768. LPWSTR lpsDigits,
  4769. DWORD dwNumDigits,
  4770. LPCWSTR lpszTerminationDigits,
  4771. DWORD dwFirstDigitTimeout,
  4772. DWORD dwInterDigitTimeout
  4773. )
  4774. {
  4775. //
  4776. // Note: we do the ptr check here rather than in DOFUNC because we're
  4777. // not passing any digits data within the context of this func
  4778. //
  4779. if (lpsDigits && TAPIIsBadWritePtr (lpsDigits, dwNumDigits * sizeof (WCHAR)))
  4780. {
  4781. return LINEERR_INVALPOINTER;
  4782. }
  4783. //
  4784. // this entry will be cleared in the callback (lineGatherDigitsWPostProcess)
  4785. //
  4786. DWORD hpOutputBuffer = CreateHandleTableEntry((ULONG_PTR)lpsDigits);
  4787. FUNC_ARGS funcArgs =
  4788. {
  4789. MAKELONG (LINE_FUNC | SYNC | 9, lGatherDigits),
  4790. {
  4791. GetFunctionIndex(lineGatherDigitsWPostProcess),
  4792. (ULONG_PTR) hCall,
  4793. (ULONG_PTR) 0, // this is the dwendtoendid for remotesp
  4794. dwDigitModes,
  4795. hpOutputBuffer,
  4796. dwNumDigits,
  4797. (ULONG_PTR) lpszTerminationDigits,
  4798. dwFirstDigitTimeout,
  4799. dwInterDigitTimeout
  4800. },
  4801. {
  4802. Dword,
  4803. Dword,
  4804. Dword,
  4805. Dword,
  4806. Dword,
  4807. Dword,
  4808. lpszW,
  4809. Dword,
  4810. Dword
  4811. }
  4812. };
  4813. if (lpszTerminationDigits == (LPCWSTR) NULL)
  4814. {
  4815. //
  4816. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  4817. //
  4818. funcArgs.ArgTypes[6] = Dword;
  4819. funcArgs.Args[6] = TAPI_NO_DATA;
  4820. }
  4821. else
  4822. {
  4823. if ( IsBadStringPtrW(lpszTerminationDigits, (UINT)-1) )
  4824. {
  4825. DeleteHandleTableEntry(hpOutputBuffer);
  4826. hpOutputBuffer = 0;
  4827. LOG((TL_ERROR, "Bad lpszDestAddress in lineGatherDigitsW"));
  4828. return( LINEERR_INVALPOINTER );
  4829. }
  4830. }
  4831. LONG lResult = DOFUNC (&funcArgs, "lineGatherDigits");
  4832. if (lResult < 0)
  4833. {
  4834. DeleteHandleTableEntry(hpOutputBuffer);
  4835. hpOutputBuffer = 0;
  4836. }
  4837. return mapTAPIErrorCode(lResult);
  4838. }
  4839. HRESULT
  4840. LineGenerateDigits(
  4841. HCALL hCall,
  4842. DWORD dwDigitMode,
  4843. LPCWSTR lpszDigits,
  4844. DWORD dwDuration
  4845. )
  4846. {
  4847. FUNC_ARGS funcArgs =
  4848. {
  4849. MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
  4850. {
  4851. (ULONG_PTR) hCall,
  4852. dwDigitMode,
  4853. (ULONG_PTR) lpszDigits,
  4854. dwDuration,
  4855. 0 // dwEndToEndID, remotesp only
  4856. },
  4857. {
  4858. Dword,
  4859. Dword,
  4860. lpszW,
  4861. Dword,
  4862. Dword
  4863. }
  4864. };
  4865. if (!lpszDigits)
  4866. {
  4867. funcArgs.Args[2] = TAPI_NO_DATA;
  4868. funcArgs.ArgTypes[2] = Dword;
  4869. }
  4870. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGenerateDigits") );
  4871. }
  4872. HRESULT
  4873. LineGenerateTone(
  4874. HCALL hCall,
  4875. DWORD dwToneMode,
  4876. DWORD dwDuration,
  4877. DWORD dwNumTones,
  4878. LPLINEGENERATETONE const lpTones
  4879. )
  4880. {
  4881. FUNC_ARGS funcArgs =
  4882. {
  4883. MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
  4884. {
  4885. (ULONG_PTR) hCall,
  4886. dwToneMode,
  4887. dwDuration,
  4888. dwNumTones,
  4889. TAPI_NO_DATA, // (DWORD) lpTones,
  4890. 0, // dwNumTones * sizeof(LINEGENERATETONE)
  4891. 0 // dwEndToEndID, remotesp only
  4892. },
  4893. {
  4894. Dword,
  4895. Dword,
  4896. Dword,
  4897. Dword,
  4898. Dword, // lpSet_SizeToFollow,
  4899. Dword, // Size
  4900. Dword
  4901. }
  4902. };
  4903. if (dwToneMode == LINETONEMODE_CUSTOM)
  4904. {
  4905. //
  4906. // Set lpTones (& following Size arg) since in this case
  4907. // they are valid args
  4908. //
  4909. funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
  4910. funcArgs.Args[4] = (ULONG_PTR) lpTones;
  4911. funcArgs.ArgTypes[5] = Size;
  4912. funcArgs.Args[5] = dwNumTones * sizeof(LINEGENERATETONE);
  4913. }
  4914. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGenerateTone"));
  4915. }
  4916. HRESULT
  4917. LineGetCallHubTracking(
  4918. DWORD dwDeviceID,
  4919. LINECALLHUBTRACKINGINFO ** ppTrackingInfo
  4920. )
  4921. {
  4922. return E_NOTIMPL;
  4923. }
  4924. HRESULT
  4925. LineGetHubRelatedCalls(
  4926. HCALLHUB hCallHub,
  4927. HCALL hCall,
  4928. LINECALLLIST ** ppCallHubList
  4929. )
  4930. {
  4931. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD) * 20;
  4932. HRESULT hr;
  4933. *ppCallHubList = (LINECALLLIST *)ClientAlloc( dwSize );
  4934. if (NULL == *ppCallHubList)
  4935. {
  4936. return E_OUTOFMEMORY;
  4937. }
  4938. (*ppCallHubList)->dwTotalSize = dwSize;
  4939. FUNC_ARGS funcArgs =
  4940. {
  4941. MAKELONG (LINE_FUNC | SYNC | 3, lGetHubRelatedCalls),
  4942. {
  4943. (ULONG_PTR) hCallHub,
  4944. (ULONG_PTR) hCall,
  4945. (ULONG_PTR) *ppCallHubList
  4946. },
  4947. {
  4948. Dword,
  4949. Dword,
  4950. lpGet_Struct
  4951. }
  4952. };
  4953. while (TRUE)
  4954. {
  4955. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetHubRelatedCalls") );
  4956. if (!SUCCEEDED(hr))
  4957. {
  4958. ClientFree( *ppCallHubList );
  4959. *ppCallHubList = NULL;
  4960. return hr;
  4961. }
  4962. if ((*ppCallHubList)->dwNeededSize > (*ppCallHubList)->dwTotalSize)
  4963. {
  4964. dwSize = (*ppCallHubList)->dwNeededSize;
  4965. ClientFree( *ppCallHubList );
  4966. *ppCallHubList = (LINECALLLIST *)ClientAlloc( dwSize );
  4967. if (NULL == *ppCallHubList)
  4968. {
  4969. return E_OUTOFMEMORY;
  4970. }
  4971. (*ppCallHubList)->dwTotalSize = dwSize;
  4972. funcArgs.Args[2] = (ULONG_PTR) *ppCallHubList;
  4973. }
  4974. else
  4975. {
  4976. break;
  4977. }
  4978. }
  4979. return hr;
  4980. }
  4981. HRESULT
  4982. LineGetCallHub(
  4983. HCALL hCall,
  4984. HCALLHUB * pCallHub
  4985. )
  4986. {
  4987. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD);
  4988. HRESULT hr;
  4989. LINECALLLIST * pCallList;
  4990. pCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  4991. if (NULL == pCallList)
  4992. {
  4993. return E_OUTOFMEMORY;
  4994. }
  4995. pCallList->dwTotalSize = dwSize;
  4996. FUNC_ARGS funcArgs =
  4997. {
  4998. MAKELONG (LINE_FUNC | SYNC | 3, lGetHubRelatedCalls),
  4999. {
  5000. (ULONG_PTR) 0,
  5001. (ULONG_PTR) hCall,
  5002. (ULONG_PTR) pCallList
  5003. },
  5004. {
  5005. Dword,
  5006. Dword,
  5007. lpGet_Struct
  5008. }
  5009. };
  5010. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetHubRelatedCalls") );
  5011. if (SUCCEEDED(hr))
  5012. {
  5013. *pCallHub = *(LPHCALLHUB)(((LPBYTE)pCallList) + pCallList->dwCallsOffset);
  5014. }
  5015. ClientFree( pCallList );
  5016. return hr;
  5017. }
  5018. HRESULT
  5019. LineGetAddressCaps(
  5020. HLINEAPP hLineApp,
  5021. DWORD dwDeviceID,
  5022. DWORD dwAddressID,
  5023. DWORD dwAPIVersion,
  5024. LPLINEADDRESSCAPS * ppAddressCaps
  5025. )
  5026. {
  5027. LONG lResult;
  5028. FUNC_ARGS funcArgs =
  5029. {
  5030. MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
  5031. {
  5032. (ULONG_PTR) hLineApp,
  5033. dwDeviceID,
  5034. dwAddressID,
  5035. dwAPIVersion,
  5036. 0,
  5037. (ULONG_PTR) *ppAddressCaps
  5038. },
  5039. {
  5040. hXxxApp,
  5041. Dword,
  5042. Dword,
  5043. Dword,
  5044. Dword,
  5045. lpGet_Struct
  5046. }
  5047. };
  5048. while (TRUE)
  5049. {
  5050. lResult = DOFUNC (&funcArgs, "lineGetAddressCaps");
  5051. if ((0 == lResult) && ((*ppAddressCaps)->dwNeededSize > (*ppAddressCaps)->dwTotalSize))
  5052. {
  5053. DWORD dwSize;
  5054. dwSize = (*ppAddressCaps)->dwNeededSize;
  5055. ClientFree(*ppAddressCaps);
  5056. *ppAddressCaps = (LPLINEADDRESSCAPS) ClientAlloc( dwSize );
  5057. if (NULL == (*ppAddressCaps))
  5058. {
  5059. return E_OUTOFMEMORY;
  5060. }
  5061. (*ppAddressCaps)->dwTotalSize = dwSize;
  5062. funcArgs.Args[5] = (ULONG_PTR) *ppAddressCaps;
  5063. }
  5064. else
  5065. {
  5066. break;
  5067. }
  5068. }
  5069. return mapTAPIErrorCode( lResult );
  5070. }
  5071. LONG
  5072. WINAPI
  5073. lineGetAddressIDW(
  5074. HLINE hLine,
  5075. LPDWORD lpdwAddressID,
  5076. DWORD dwAddressMode,
  5077. LPCWSTR lpsAddress,
  5078. DWORD dwSize
  5079. )
  5080. {
  5081. FUNC_ARGS funcArgs =
  5082. {
  5083. MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
  5084. {
  5085. (ULONG_PTR) hLine,
  5086. (ULONG_PTR) lpdwAddressID,
  5087. dwAddressMode,
  5088. (ULONG_PTR) lpsAddress,
  5089. dwSize
  5090. },
  5091. {
  5092. Dword,
  5093. lpDword,
  5094. Dword,
  5095. lpSet_SizeToFollow,
  5096. Size
  5097. }
  5098. };
  5099. return (DOFUNC (&funcArgs, "lineGetAddressID"));
  5100. }
  5101. HRESULT
  5102. LineGetAddressStatus(
  5103. T3LINE * pt3Line,
  5104. DWORD dwAddressID,
  5105. LPLINEADDRESSSTATUS * ppAddressStatus
  5106. )
  5107. {
  5108. HRESULT hr;
  5109. DWORD dwSize;
  5110. dwSize = sizeof( LINEADDRESSSTATUS ) + 500;
  5111. *ppAddressStatus = (LINEADDRESSSTATUS *)ClientAlloc( dwSize );
  5112. if ( NULL == *ppAddressStatus )
  5113. {
  5114. LOG((TL_ERROR, "Alloc failed in LineGetAddressStatus"));
  5115. return E_OUTOFMEMORY;
  5116. }
  5117. (*ppAddressStatus)->dwTotalSize = dwSize;
  5118. FUNC_ARGS funcArgs =
  5119. {
  5120. MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
  5121. {
  5122. (ULONG_PTR) pt3Line->hLine,
  5123. dwAddressID,
  5124. (ULONG_PTR) *ppAddressStatus
  5125. },
  5126. {
  5127. Dword,
  5128. Dword,
  5129. lpGet_Struct
  5130. }
  5131. };
  5132. while (TRUE)
  5133. {
  5134. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetAddressStatus") );
  5135. if ( 0 != hr )
  5136. {
  5137. ClientFree( *ppAddressStatus );
  5138. *ppAddressStatus = NULL;
  5139. return hr;
  5140. }
  5141. if ((0 == hr) && ((*ppAddressStatus)->dwNeededSize > (*ppAddressStatus)->dwTotalSize))
  5142. {
  5143. dwSize = (*ppAddressStatus)->dwNeededSize;
  5144. ClientFree( *ppAddressStatus );
  5145. *ppAddressStatus = (LPLINEADDRESSSTATUS) ClientAlloc( dwSize );
  5146. if (NULL == *ppAddressStatus)
  5147. {
  5148. LOG((TL_ERROR, "Alloc failed 2 in LineGetAddressStatus"));
  5149. return E_OUTOFMEMORY;
  5150. }
  5151. (*ppAddressStatus)->dwTotalSize = dwSize;
  5152. funcArgs.Args[2] = (ULONG_PTR)*ppAddressStatus;
  5153. }
  5154. else
  5155. {
  5156. break;
  5157. }
  5158. }
  5159. return hr;
  5160. }
  5161. LONG
  5162. WINAPI
  5163. lineGetAgentActivityListW(
  5164. HLINE hLine,
  5165. DWORD dwAddressID,
  5166. LPLINEAGENTACTIVITYLIST lpAgentActivityList
  5167. )
  5168. {
  5169. DWORD hpAgentActivityList = CreateHandleTableEntry((ULONG_PTR)lpAgentActivityList);
  5170. FUNC_ARGS funcArgs =
  5171. {
  5172. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentActivityList),
  5173. {
  5174. GetFunctionIndex(lineDevSpecificPostProcess),
  5175. (ULONG_PTR) hLine,
  5176. (ULONG_PTR) dwAddressID,
  5177. (ULONG_PTR) hpAgentActivityList, // pass the actual ptr (for ppproc)
  5178. (ULONG_PTR) lpAgentActivityList // pass data
  5179. },
  5180. {
  5181. Dword,
  5182. Dword,
  5183. Dword,
  5184. Dword,
  5185. lpGet_Struct,
  5186. }
  5187. };
  5188. LONG lResult = DOFUNC (&funcArgs, "lineGetAgentActivityListW");
  5189. //
  5190. // if failed, or synchronous call, remove the handle table entry.
  5191. // otherwise the callback will do this.
  5192. //
  5193. if (lResult <= 0)
  5194. {
  5195. DeleteHandleTableEntry(hpAgentActivityList);
  5196. }
  5197. return lResult;
  5198. }
  5199. HRESULT
  5200. LineGetAgentCaps(
  5201. HLINEAPP hLineApp,
  5202. DWORD dwDeviceID,
  5203. DWORD dwAddressID,
  5204. DWORD dwAppAPIVersion,
  5205. LPLINEAGENTCAPS *ppAgentCaps
  5206. )
  5207. {
  5208. HRESULT hr = S_OK;
  5209. long lResult;
  5210. DWORD dwSize = sizeof(LINEAGENTCAPS) + 500;
  5211. *ppAgentCaps = (LPLINEAGENTCAPS) ClientAlloc( dwSize );
  5212. if (NULL == *ppAgentCaps)
  5213. {
  5214. return E_OUTOFMEMORY;
  5215. }
  5216. (*ppAgentCaps)->dwTotalSize = dwSize;
  5217. DWORD hpAgentCaps = CreateHandleTableEntry((ULONG_PTR)*ppAgentCaps);
  5218. FUNC_ARGS funcArgs =
  5219. {
  5220. MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
  5221. {
  5222. GetFunctionIndex(lineDevSpecificPostProcess),
  5223. (ULONG_PTR) hLineApp,
  5224. (ULONG_PTR) dwDeviceID,
  5225. (ULONG_PTR) dwAddressID,
  5226. (ULONG_PTR) dwAppAPIVersion,
  5227. hpAgentCaps, // pass the actual ptr (for ppproc)
  5228. (ULONG_PTR) *ppAgentCaps // pass data
  5229. },
  5230. {
  5231. Dword,
  5232. hXxxApp,
  5233. Dword,
  5234. Dword,
  5235. Dword,
  5236. Dword,
  5237. lpGet_Struct,
  5238. }
  5239. };
  5240. while (TRUE)
  5241. {
  5242. lResult = DOFUNC (&funcArgs, "LineGetAgentCaps");
  5243. if (lResult > 0) // async reply
  5244. {
  5245. hr = WaitForReply( lResult );
  5246. if ((hr == S_OK) )
  5247. {
  5248. if (((*ppAgentCaps)->dwNeededSize > (*ppAgentCaps)->dwTotalSize))
  5249. {
  5250. // didnt Work , adjust buffer size & try again
  5251. DeleteHandleTableEntry(hpAgentCaps);
  5252. hpAgentCaps = 0;
  5253. LOG((TL_INFO, "LineGetAgentCaps failed - buffer to small"));
  5254. dwSize = (*ppAgentCaps)->dwNeededSize;
  5255. ClientFree( *ppAgentCaps );
  5256. *ppAgentCaps = NULL;
  5257. *ppAgentCaps = (LPLINEAGENTCAPS) ClientAlloc( dwSize );
  5258. if (*ppAgentCaps == NULL)
  5259. {
  5260. LOG((TL_ERROR, "LineGetAgentCaps - repeat ClientAlloc failed"));
  5261. hr = E_OUTOFMEMORY;
  5262. break;
  5263. }
  5264. else
  5265. {
  5266. (*ppAgentCaps)->dwTotalSize = dwSize;
  5267. hpAgentCaps = CreateHandleTableEntry((ULONG_PTR)*ppAgentCaps);
  5268. funcArgs.Args[5] = hpAgentCaps;
  5269. funcArgs.Args[6] = (ULONG_PTR)*ppAgentCaps;
  5270. }
  5271. } // buffer too small
  5272. else
  5273. {
  5274. // WaitForReply succeeded and the buffer was big enough.
  5275. // break out of the loop
  5276. break;
  5277. }
  5278. } // waitforreply succeeded
  5279. else
  5280. {
  5281. // waitforreply failed. not likely to receive a callback.
  5282. // clear handle table entries.
  5283. LOG((TL_ERROR, "LineGetAgentCaps - WaitForReply failed"));
  5284. DeleteHandleTableEntry(hpAgentCaps);
  5285. hpAgentCaps = 0;
  5286. }
  5287. }
  5288. else // failed sync
  5289. {
  5290. LOG((TL_ERROR, "LineGetAgentCaps - failed sync"));
  5291. DeleteHandleTableEntry(hpAgentCaps);
  5292. hpAgentCaps = 0;
  5293. hr = mapTAPIErrorCode( lResult );
  5294. break;
  5295. }
  5296. } // end while(TRUE)
  5297. return hr;
  5298. }
  5299. LONG
  5300. WINAPI
  5301. lineGetAgentGroupListW(
  5302. HLINE hLine,
  5303. DWORD dwAddressID,
  5304. LPLINEAGENTGROUPLIST lpAgentGroupList
  5305. )
  5306. {
  5307. DWORD hpAgentGroupList = CreateHandleTableEntry((ULONG_PTR)lpAgentGroupList);
  5308. FUNC_ARGS funcArgs =
  5309. {
  5310. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
  5311. {
  5312. GetFunctionIndex(lineDevSpecificPostProcess),
  5313. (ULONG_PTR) hLine,
  5314. (ULONG_PTR) dwAddressID,
  5315. hpAgentGroupList, // pass the actual ptr (for ppproc)
  5316. (ULONG_PTR) lpAgentGroupList // pass data
  5317. },
  5318. {
  5319. Dword,
  5320. Dword,
  5321. Dword,
  5322. Dword,
  5323. lpGet_Struct,
  5324. }
  5325. };
  5326. LONG lResult = DOFUNC (&funcArgs, "lineGetAgentGroupListW");
  5327. //
  5328. // if failed, or synchronous call, remove the handle table entry.
  5329. // otherwise the callback will do this.
  5330. //
  5331. if (lResult <= 0)
  5332. {
  5333. DeleteHandleTableEntry(hpAgentGroupList);
  5334. }
  5335. return lResult;
  5336. }
  5337. LONG
  5338. WINAPI
  5339. lineGetAgentStatusW(
  5340. HLINE hLine,
  5341. DWORD dwAddressID,
  5342. LPLINEAGENTSTATUS lpAgentStatus
  5343. )
  5344. {
  5345. DWORD hpAgentStatus = CreateHandleTableEntry((ULONG_PTR)lpAgentStatus);
  5346. FUNC_ARGS funcArgs =
  5347. {
  5348. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
  5349. {
  5350. GetFunctionIndex(lineDevSpecificPostProcess),
  5351. (ULONG_PTR) hLine,
  5352. (ULONG_PTR) dwAddressID,
  5353. hpAgentStatus, // pass the actual ptr (for ppproc)
  5354. (ULONG_PTR) lpAgentStatus // pass data
  5355. },
  5356. {
  5357. Dword,
  5358. Dword,
  5359. Dword,
  5360. Dword,
  5361. lpGet_Struct,
  5362. }
  5363. };
  5364. LONG lResult = DOFUNC(&funcArgs, "lineGetAgentStatusW");
  5365. if (lResult <= 0)
  5366. {
  5367. DeleteHandleTableEntry(hpAgentStatus);
  5368. }
  5369. return lResult;
  5370. }
  5371. LONG
  5372. WINAPI
  5373. lineGetAppPriorityW(
  5374. LPCWSTR lpszAppName,
  5375. DWORD dwMediaMode,
  5376. LPLINEEXTENSIONID lpExtensionID,
  5377. DWORD dwRequestMode,
  5378. LPVARSTRING lpExtensionName,
  5379. LPDWORD lpdwPriority
  5380. )
  5381. {
  5382. FUNC_ARGS funcArgs =
  5383. {
  5384. MAKELONG (LINE_FUNC | SYNC | 7, lGetAppPriority),
  5385. {
  5386. (ULONG_PTR) lpszAppName,
  5387. dwMediaMode,
  5388. 0,
  5389. 0,
  5390. dwRequestMode,
  5391. 0,
  5392. (ULONG_PTR) lpdwPriority
  5393. },
  5394. {
  5395. lpszW, // app name
  5396. Dword, // media mode
  5397. Dword, // ext id (offset)
  5398. Dword, // ext id (size)
  5399. Dword, // request mode
  5400. Dword, // ext name total size
  5401. lpDword // lp pri
  5402. }
  5403. };
  5404. if (dwMediaMode & 0xff000000)
  5405. {
  5406. if ((LPVOID) lpExtensionName == (LPVOID) lpdwPriority)
  5407. {
  5408. return LINEERR_INVALPOINTER;
  5409. }
  5410. //
  5411. // We have to do some arg list munging here (adding an extra arg)
  5412. //
  5413. //
  5414. // Set lpExtensionID, the following Size arg,
  5415. // lpExtensionName, and the following MinSize
  5416. // Type's and Value appropriately since they're
  5417. // valid args in this case
  5418. //
  5419. funcArgs.ArgTypes[2] = lpSet_SizeToFollow;
  5420. funcArgs.Args[2] = (ULONG_PTR) lpExtensionID;
  5421. funcArgs.ArgTypes[3] = Size;
  5422. funcArgs.Args[3] = sizeof (LINEEXTENSIONID);
  5423. funcArgs.ArgTypes[5] = lpGet_Struct;
  5424. funcArgs.Args[5] = (ULONG_PTR) lpExtensionName;
  5425. }
  5426. if ( IsBadStringPtrW(lpszAppName, (UINT)-1) )
  5427. {
  5428. LOG((TL_ERROR, "Bad lpszDestAddress in lineGetAppPriorityW"));
  5429. return( LINEERR_INVALPOINTER );
  5430. }
  5431. return (DOFUNC (&funcArgs, "lineGetAppPriority"));
  5432. }
  5433. HRESULT
  5434. LineGetCallIDs(
  5435. HCALL hCall,
  5436. LPDWORD lpdwAddressID,
  5437. LPDWORD lpdwCallID,
  5438. LPDWORD lpdwRelatedCallID
  5439. )
  5440. {
  5441. FUNC_ARGS funcArgs =
  5442. {
  5443. MAKELONG (LINE_FUNC | SYNC | 4, lGetCallIDs),
  5444. {
  5445. (ULONG_PTR) hCall,
  5446. (ULONG_PTR) lpdwAddressID,
  5447. (ULONG_PTR) lpdwCallID,
  5448. (ULONG_PTR) lpdwRelatedCallID
  5449. },
  5450. {
  5451. Dword,
  5452. lpDword,
  5453. lpDword,
  5454. lpDword
  5455. }
  5456. };
  5457. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallIDs"));
  5458. }
  5459. HRESULT
  5460. LineGetCallInfo(
  5461. HCALL hCall,
  5462. LPLINECALLINFO * ppCallInfo
  5463. )
  5464. {
  5465. if ( NULL == hCall )
  5466. {
  5467. LOG((TL_WARN, "LineGetCallInfo: NULL hCall"));
  5468. *ppCallInfo = NULL;
  5469. return TAPI_E_INVALCALLSTATE;
  5470. }
  5471. *ppCallInfo = (LPLINECALLINFO) ClientAlloc( sizeof(LINECALLINFO) + 500 );
  5472. if (NULL == *ppCallInfo)
  5473. {
  5474. return E_OUTOFMEMORY;
  5475. }
  5476. (*ppCallInfo)->dwTotalSize = sizeof(LINECALLINFO) + 500;
  5477. FUNC_ARGS funcArgs =
  5478. {
  5479. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
  5480. {
  5481. (ULONG_PTR) hCall,
  5482. (ULONG_PTR) *ppCallInfo
  5483. },
  5484. {
  5485. Dword,
  5486. lpGet_Struct
  5487. }
  5488. };
  5489. HRESULT hr = E_FAIL;
  5490. while (TRUE)
  5491. {
  5492. hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallInfo"));
  5493. //
  5494. // if we fail, free alloc
  5495. //
  5496. if ( FAILED(hr) )
  5497. {
  5498. ClientFree( *ppCallInfo );
  5499. *ppCallInfo = NULL;
  5500. return hr;
  5501. }
  5502. //
  5503. // do we need to realloc?
  5504. //
  5505. if ((*ppCallInfo)->dwNeededSize > (*ppCallInfo)->dwTotalSize)
  5506. {
  5507. DWORD dwSize = (*ppCallInfo)->dwNeededSize;
  5508. ClientFree( *ppCallInfo );
  5509. *ppCallInfo = (LPLINECALLINFO) ClientAlloc( dwSize );
  5510. if (NULL == *ppCallInfo)
  5511. {
  5512. // return LINEERR_NOMEM;
  5513. return E_OUTOFMEMORY;
  5514. }
  5515. (*ppCallInfo)->dwTotalSize = dwSize;
  5516. funcArgs.Args[1] = (ULONG_PTR)*ppCallInfo;
  5517. }
  5518. else
  5519. {
  5520. break;
  5521. }
  5522. }
  5523. return hr;
  5524. }
  5525. HRESULT
  5526. LineGetCallStatus(
  5527. HCALL hCall,
  5528. LPLINECALLSTATUS * ppCallStatus
  5529. )
  5530. {
  5531. *ppCallStatus = (LPLINECALLSTATUS) ClientAlloc( sizeof(LINECALLSTATUS) + 500 );
  5532. if (NULL == *ppCallStatus)
  5533. {
  5534. return E_OUTOFMEMORY;
  5535. }
  5536. (*ppCallStatus)->dwTotalSize = sizeof(LINECALLSTATUS) + 500;
  5537. FUNC_ARGS funcArgs =
  5538. {
  5539. MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
  5540. {
  5541. (ULONG_PTR) hCall,
  5542. (ULONG_PTR) *ppCallStatus
  5543. },
  5544. {
  5545. Dword,
  5546. lpGet_Struct
  5547. }
  5548. };
  5549. HRESULT hr = E_FAIL;
  5550. while (TRUE)
  5551. {
  5552. hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetCallStatus"));
  5553. //
  5554. // if we fail, free alloc
  5555. //
  5556. if ( FAILED(hr) )
  5557. {
  5558. ClientFree( *ppCallStatus );
  5559. *ppCallStatus = NULL;
  5560. return hr;
  5561. }
  5562. //
  5563. // do we need to realloc?
  5564. //
  5565. if ((*ppCallStatus)->dwNeededSize > (*ppCallStatus)->dwTotalSize)
  5566. {
  5567. DWORD dwSize = (*ppCallStatus)->dwNeededSize;
  5568. ClientFree( *ppCallStatus );
  5569. *ppCallStatus = (LPLINECALLSTATUS) ClientAlloc( dwSize );
  5570. if (NULL == *ppCallStatus)
  5571. {
  5572. return mapTAPIErrorCode( LINEERR_NOMEM );
  5573. }
  5574. (*ppCallStatus)->dwTotalSize = dwSize;
  5575. funcArgs.Args[1] = (ULONG_PTR)*ppCallStatus;
  5576. }
  5577. else
  5578. {
  5579. break;
  5580. }
  5581. }
  5582. return hr;
  5583. }
  5584. HRESULT
  5585. LineGetConfRelatedCalls(
  5586. HCALL hCall,
  5587. LINECALLLIST ** ppCallList
  5588. )
  5589. {
  5590. DWORD dwSize = sizeof(LINECALLLIST) + sizeof(DWORD) * 20;
  5591. LONG lResult;
  5592. HRESULT hr;
  5593. *ppCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  5594. if (NULL == *ppCallList)
  5595. {
  5596. return E_OUTOFMEMORY;
  5597. }
  5598. (*ppCallList)->dwTotalSize = dwSize;
  5599. FUNC_ARGS funcArgs =
  5600. {
  5601. MAKELONG (LINE_FUNC | SYNC| 2, lGetConfRelatedCalls),
  5602. {
  5603. (ULONG_PTR) hCall,
  5604. (ULONG_PTR) *ppCallList
  5605. },
  5606. {
  5607. Dword,
  5608. lpGet_Struct
  5609. }
  5610. };
  5611. while (TRUE)
  5612. {
  5613. lResult = DOFUNC (&funcArgs, "lineGetConfRelatedCalls") ;
  5614. if ( (0 == lResult) && ((*ppCallList)->dwNeededSize > (*ppCallList)->dwTotalSize) )
  5615. {
  5616. dwSize = (*ppCallList)->dwNeededSize;
  5617. ClientFree( *ppCallList );
  5618. *ppCallList = (LINECALLLIST *)ClientAlloc( dwSize );
  5619. if (NULL == *ppCallList)
  5620. {
  5621. hr = E_OUTOFMEMORY;
  5622. break;
  5623. }
  5624. (*ppCallList)->dwTotalSize = dwSize;
  5625. funcArgs.Args[1] = (ULONG_PTR) *ppCallList;
  5626. }
  5627. else
  5628. {
  5629. hr = mapTAPIErrorCode( lResult );
  5630. break;
  5631. }
  5632. }
  5633. return hr;
  5634. }
  5635. LONG
  5636. WINAPI
  5637. lineGetCountryW(
  5638. DWORD dwCountryID,
  5639. DWORD dwAPIVersion,
  5640. LPLINECOUNTRYLIST lpLineCountryList
  5641. )
  5642. {
  5643. FUNC_ARGS funcArgs =
  5644. {
  5645. MAKELONG (LINE_FUNC | SYNC | 4, lGetCountry),
  5646. {
  5647. dwCountryID,
  5648. dwAPIVersion,
  5649. 0,
  5650. (ULONG_PTR) lpLineCountryList
  5651. },
  5652. {
  5653. Dword,
  5654. Dword,
  5655. Dword,
  5656. lpGet_Struct
  5657. }
  5658. };
  5659. if (
  5660. ( TAPI_CURRENT_VERSION != dwAPIVersion )
  5661. &&
  5662. ( 0x00020000 != dwAPIVersion )
  5663. &&
  5664. ( 0x00010004 != dwAPIVersion )
  5665. &&
  5666. ( 0x00010003 != dwAPIVersion )
  5667. )
  5668. {
  5669. LOG((TL_ERROR, "lineGetCountryW - bad API version 0x%08lx", dwAPIVersion));
  5670. return LINEERR_INCOMPATIBLEAPIVERSION;
  5671. }
  5672. return (DOFUNC (&funcArgs, "lineGetCountry"));
  5673. }
  5674. HRESULT
  5675. LineGetDevCapsWithAlloc(
  5676. HLINEAPP hLineApp,
  5677. DWORD dwDeviceID,
  5678. DWORD dwAPIVersion,
  5679. LPLINEDEVCAPS * ppLineDevCaps
  5680. )
  5681. {
  5682. LONG lResult;
  5683. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( sizeof(LINEDEVCAPS) + 500 );
  5684. if (NULL == *ppLineDevCaps)
  5685. {
  5686. return E_OUTOFMEMORY;
  5687. }
  5688. (*ppLineDevCaps)->dwTotalSize = sizeof(LINEDEVCAPS) + 500;
  5689. FUNC_ARGS funcArgs =
  5690. {
  5691. MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
  5692. {
  5693. (ULONG_PTR) hLineApp,
  5694. dwDeviceID,
  5695. dwAPIVersion,
  5696. 0,
  5697. (ULONG_PTR) *ppLineDevCaps
  5698. },
  5699. {
  5700. hXxxApp,
  5701. Dword,
  5702. Dword,
  5703. Dword,
  5704. lpGet_Struct
  5705. }
  5706. };
  5707. while (TRUE)
  5708. {
  5709. lResult = DOFUNC (&funcArgs, "lineGetDevCaps");
  5710. if ((0 == lResult) && ((*ppLineDevCaps)->dwNeededSize > (*ppLineDevCaps)->dwTotalSize))
  5711. {
  5712. DWORD dwSize = (*ppLineDevCaps)->dwNeededSize;
  5713. ClientFree( *ppLineDevCaps );
  5714. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( dwSize );
  5715. if (NULL == *ppLineDevCaps)
  5716. {
  5717. // return LINEERR_NOMEM;
  5718. return E_OUTOFMEMORY;
  5719. }
  5720. (*ppLineDevCaps)->dwTotalSize = dwSize;
  5721. funcArgs.Args[4] = (ULONG_PTR)*ppLineDevCaps;
  5722. }
  5723. else
  5724. {
  5725. break;
  5726. }
  5727. }
  5728. return mapTAPIErrorCode( lResult );
  5729. }
  5730. HRESULT
  5731. LineGetDevCaps(
  5732. HLINEAPP hLineApp,
  5733. DWORD dwDeviceID,
  5734. DWORD dwAPIVersion,
  5735. LPLINEDEVCAPS * ppLineDevCaps
  5736. )
  5737. {
  5738. LONG lResult;
  5739. FUNC_ARGS funcArgs =
  5740. {
  5741. MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
  5742. {
  5743. (ULONG_PTR) hLineApp,
  5744. dwDeviceID,
  5745. dwAPIVersion,
  5746. 0,
  5747. (ULONG_PTR) *ppLineDevCaps
  5748. },
  5749. {
  5750. hXxxApp,
  5751. Dword,
  5752. Dword,
  5753. Dword,
  5754. lpGet_Struct
  5755. }
  5756. };
  5757. while (TRUE)
  5758. {
  5759. lResult = DOFUNC (&funcArgs, "lineGetDevCaps");
  5760. if ((0 == lResult) && ((*ppLineDevCaps)->dwNeededSize > (*ppLineDevCaps)->dwTotalSize))
  5761. {
  5762. DWORD dwSize = (*ppLineDevCaps)->dwNeededSize;
  5763. ClientFree( *ppLineDevCaps );
  5764. *ppLineDevCaps = (LPLINEDEVCAPS) ClientAlloc( dwSize );
  5765. if (NULL == *ppLineDevCaps)
  5766. {
  5767. // return LINEERR_NOMEM;
  5768. return E_OUTOFMEMORY;
  5769. }
  5770. (*ppLineDevCaps)->dwTotalSize = dwSize;
  5771. funcArgs.Args[4] = (ULONG_PTR)*ppLineDevCaps;
  5772. }
  5773. else
  5774. {
  5775. break;
  5776. }
  5777. }
  5778. return mapTAPIErrorCode( lResult );
  5779. }
  5780. HRESULT
  5781. LineGetDevConfig(
  5782. DWORD dwDeviceID,
  5783. LPVARSTRING * ppDeviceConfig,
  5784. LPCWSTR lpszDeviceClass
  5785. )
  5786. {
  5787. LONG lResult;
  5788. DWORD dwSize = sizeof (VARSTRING) + 500;
  5789. *ppDeviceConfig = (LPVARSTRING) ClientAlloc( dwSize );
  5790. if (NULL == *ppDeviceConfig)
  5791. {
  5792. return E_OUTOFMEMORY;
  5793. }
  5794. (*ppDeviceConfig)->dwTotalSize = dwSize;
  5795. FUNC_ARGS funcArgs =
  5796. {
  5797. MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
  5798. {
  5799. dwDeviceID,
  5800. (ULONG_PTR) *ppDeviceConfig,
  5801. (ULONG_PTR) lpszDeviceClass
  5802. },
  5803. {
  5804. Dword,
  5805. lpGet_Struct,
  5806. lpszW
  5807. }
  5808. };
  5809. while ( TRUE )
  5810. {
  5811. lResult = DOFUNC (&funcArgs, "lineGetDevConfig");
  5812. if ((lResult == 0) && ((*ppDeviceConfig)->dwNeededSize > (*ppDeviceConfig)->dwTotalSize))
  5813. {
  5814. dwSize = (*ppDeviceConfig)->dwNeededSize;
  5815. ClientFree(*ppDeviceConfig);
  5816. *ppDeviceConfig = (LPVARSTRING)ClientAlloc(dwSize);
  5817. if (NULL == *ppDeviceConfig)
  5818. {
  5819. LOG((TL_ERROR, "LineGetDevConfig exit - return E_OUTOFMEMORY"));
  5820. return E_OUTOFMEMORY;
  5821. }
  5822. (*ppDeviceConfig)->dwTotalSize = dwSize;
  5823. funcArgs.Args[1] = (ULONG_PTR)*ppDeviceConfig;
  5824. }
  5825. else
  5826. {
  5827. break;
  5828. }
  5829. }
  5830. LOG((TL_TRACE, "LineGetDevConfig exit - return %lx", lResult));
  5831. return mapTAPIErrorCode( lResult );
  5832. }
  5833. LONG
  5834. WINAPI
  5835. lineGetIconW(
  5836. DWORD dwDeviceID,
  5837. LPCWSTR lpszDeviceClass,
  5838. LPHICON lphIcon
  5839. )
  5840. {
  5841. HICON hIcon;
  5842. LONG lResult;
  5843. FUNC_ARGS funcArgs =
  5844. {
  5845. MAKELONG (LINE_FUNC | SYNC | 3, lGetIcon),
  5846. {
  5847. dwDeviceID,
  5848. (ULONG_PTR) lpszDeviceClass,
  5849. (ULONG_PTR) &hIcon
  5850. },
  5851. {
  5852. Dword,
  5853. lpszW,
  5854. lpDword
  5855. }
  5856. };
  5857. if (IsBadDwordPtr ((LPDWORD) lphIcon))
  5858. {
  5859. LOG((TL_ERROR, "lphIcon is an invalid pointer!"));
  5860. return LINEERR_INVALPOINTER;
  5861. }
  5862. if (lpszDeviceClass == (LPCWSTR) NULL)
  5863. {
  5864. //
  5865. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  5866. //
  5867. funcArgs.ArgTypes[1] = Dword;
  5868. funcArgs.Args[1] = TAPI_NO_DATA;
  5869. }
  5870. if ((lResult = DOFUNC (&funcArgs, "lineGetIcon")) == 0)
  5871. {
  5872. *lphIcon = hIcon;
  5873. }
  5874. return lResult;
  5875. }
  5876. HRESULT
  5877. LineGetID(
  5878. HLINE hLine,
  5879. DWORD dwID,
  5880. HCALL hCall,
  5881. DWORD dwSelect,
  5882. LPVARSTRING * ppDeviceID,
  5883. LPCWSTR lpszDeviceClass
  5884. )
  5885. {
  5886. LONG lResult;
  5887. DWORD dwNumDevices;
  5888. DWORD dwDeviceId1, dwDeviceId2;
  5889. BOOL bWaveDevice = FALSE;
  5890. *ppDeviceID = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  5891. if (NULL == *ppDeviceID)
  5892. {
  5893. return E_OUTOFMEMORY;
  5894. }
  5895. (*ppDeviceID)->dwTotalSize = sizeof (VARSTRING) + 500;
  5896. FUNC_ARGS funcArgs =
  5897. {
  5898. MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
  5899. {
  5900. (ULONG_PTR) hLine,
  5901. dwID,
  5902. (ULONG_PTR) hCall,
  5903. dwSelect,
  5904. (ULONG_PTR) *ppDeviceID,
  5905. (ULONG_PTR) lpszDeviceClass
  5906. },
  5907. {
  5908. Dword,
  5909. Dword,
  5910. Dword,
  5911. Dword,
  5912. lpGet_Struct,
  5913. lpszW
  5914. }
  5915. };
  5916. LOG((TL_TRACE, "LineGetID - enter"));
  5917. LOG((TL_INFO, " hLine --------->%lx", hLine));
  5918. LOG((TL_INFO, " hCall ----------->%lx", hCall));
  5919. LOG((TL_INFO, " dwSelect -------->%lx", dwSelect));
  5920. LOG((TL_INFO, " ppDeviceID ------>%p", ppDeviceID));
  5921. LOG((TL_INFO, " lpszDeviceClass ->%p", lpszDeviceClass));
  5922. //
  5923. // If the request is for a wave device, call LGetIDEx.
  5924. // This will return a device string ID which is guaranteed to be unique across
  5925. // all processes.
  5926. // Then we will convert the string ID to the correct device ID in the client process context.
  5927. //
  5928. if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
  5929. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  5930. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  5931. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  5932. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  5933. )
  5934. {
  5935. bWaveDevice = TRUE;
  5936. dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
  5937. funcArgs.Flags = MAKELONG (LINE_FUNC | SYNC | 6, lGetIDEx);
  5938. }
  5939. while ( TRUE )
  5940. {
  5941. lResult = DOFUNC (&funcArgs, bWaveDevice ? "lineGetIDEx" : "lineGetID");
  5942. if ((lResult == 0) && ((*ppDeviceID)->dwNeededSize > (*ppDeviceID)->dwTotalSize))
  5943. {
  5944. DWORD dwSize = (*ppDeviceID)->dwNeededSize;
  5945. ClientFree(*ppDeviceID);
  5946. *ppDeviceID = (LPVARSTRING)ClientAlloc(dwSize);
  5947. if (NULL == *ppDeviceID)
  5948. {
  5949. LOG((TL_ERROR, "LineGetID exit - return LINEERR_NOMEM"));
  5950. // return LINEERR_NOMEM;
  5951. return E_OUTOFMEMORY;
  5952. }
  5953. (*ppDeviceID)->dwTotalSize = dwSize;
  5954. funcArgs.Args[4] = (ULONG_PTR)*ppDeviceID;
  5955. }
  5956. else
  5957. {
  5958. if (lResult != 0)
  5959. {
  5960. ClientFree (*ppDeviceID);
  5961. *ppDeviceID = NULL;
  5962. }
  5963. break;
  5964. }
  5965. }
  5966. if (bWaveDevice && lResult == 0)
  5967. {
  5968. //
  5969. // We got the string ID(s), now we need to convert them to numeric device ID(s)
  5970. //
  5971. BOOL bConversionOk;
  5972. if ( dwNumDevices == 1 )
  5973. {
  5974. bConversionOk = WaveStringIdToDeviceId (
  5975. (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset),
  5976. lpszDeviceClass,
  5977. &dwDeviceId1);
  5978. }
  5979. else
  5980. {
  5981. _ASSERTE(dwNumDevices == 2);
  5982. //
  5983. // for "wave/in/out", we get back two devices from tapisrv -> convert both
  5984. //
  5985. LPWSTR szString1 = (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset);
  5986. // first convert the wave/in device
  5987. bConversionOk = WaveStringIdToDeviceId (
  5988. szString1,
  5989. L"wave/in",
  5990. &dwDeviceId1);
  5991. // next convert the wave/out device
  5992. bConversionOk = bConversionOk && WaveStringIdToDeviceId (
  5993. szString1 + wcslen(szString1),
  5994. L"wave/out",
  5995. &dwDeviceId2);
  5996. }
  5997. if (!bConversionOk)
  5998. {
  5999. LOG((TL_ERROR, "LineGetID - WaveStringIdToDeviceId failed"));
  6000. ClientFree(*ppDeviceID);
  6001. *ppDeviceID = NULL;
  6002. lResult = LINEERR_OPERATIONFAILED;
  6003. }
  6004. else
  6005. {
  6006. //
  6007. // conversion succeeded, now fill the VARSTRING to be returned to the caller
  6008. //
  6009. (*ppDeviceID)->dwNeededSize = (*ppDeviceID)->dwUsedSize =
  6010. sizeof(VARSTRING) + sizeof(DWORD) * dwNumDevices;
  6011. (*ppDeviceID)->dwStringFormat = STRINGFORMAT_BINARY;
  6012. (*ppDeviceID)->dwStringSize = sizeof(DWORD) * dwNumDevices;
  6013. (*ppDeviceID)->dwStringOffset = sizeof(VARSTRING);
  6014. *(DWORD *)((*ppDeviceID) + 1) = dwDeviceId1;
  6015. if (dwNumDevices == 2)
  6016. *((DWORD *)((*ppDeviceID) + 1) + 1) = dwDeviceId2;
  6017. }
  6018. }
  6019. LOG((TL_TRACE, "LineGetID exit - return %lx", lResult));
  6020. return mapTAPIErrorCode( lResult );
  6021. }
  6022. HRESULT
  6023. LineGetLineDevStatus(
  6024. HLINE hLine,
  6025. LPLINEDEVSTATUS * ppDevStatus
  6026. )
  6027. {
  6028. HRESULT hr;
  6029. DWORD dwSize = sizeof(LINEDEVSTATUS) + 500;
  6030. *ppDevStatus = ( LPLINEDEVSTATUS ) ClientAlloc( dwSize );
  6031. if ( NULL == *ppDevStatus )
  6032. {
  6033. LOG((TL_ERROR, "LineGetLineDevStatus - alloc failed"));
  6034. return E_OUTOFMEMORY;
  6035. }
  6036. (*ppDevStatus)->dwTotalSize = dwSize;
  6037. FUNC_ARGS funcArgs =
  6038. {
  6039. MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
  6040. {
  6041. (ULONG_PTR) hLine,
  6042. (ULONG_PTR) *ppDevStatus
  6043. },
  6044. {
  6045. Dword,
  6046. lpGet_Struct
  6047. }
  6048. };
  6049. while (TRUE)
  6050. {
  6051. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetLineDevStatus") );
  6052. if ( 0 != hr )
  6053. {
  6054. ClientFree( *ppDevStatus );
  6055. *ppDevStatus = NULL;
  6056. return hr;
  6057. }
  6058. if ((0 == hr) && ((*ppDevStatus)->dwNeededSize > (*ppDevStatus)->dwTotalSize))
  6059. {
  6060. dwSize = (*ppDevStatus)->dwNeededSize;
  6061. ClientFree( *ppDevStatus );
  6062. *ppDevStatus = (LPLINEDEVSTATUS) ClientAlloc( dwSize );
  6063. if (NULL == *ppDevStatus)
  6064. {
  6065. return E_OUTOFMEMORY;
  6066. }
  6067. (*ppDevStatus)->dwTotalSize = dwSize;
  6068. funcArgs.Args[1] = (ULONG_PTR)*ppDevStatus;
  6069. }
  6070. else
  6071. {
  6072. break;
  6073. }
  6074. }
  6075. return hr;
  6076. }
  6077. HRESULT
  6078. LineGetProxyStatus(
  6079. HLINEAPP hLineApp,
  6080. DWORD dwDeviceID,
  6081. DWORD dwAppAPIVersion,
  6082. LPLINEPROXYREQUESTLIST * ppLineProxyReqestList
  6083. )
  6084. {
  6085. HRESULT hr;
  6086. DWORD dwSize = sizeof(LINEPROXYREQUESTLIST) + 100;
  6087. *ppLineProxyReqestList = ( LPLINEPROXYREQUESTLIST ) ClientAlloc( dwSize );
  6088. if ( NULL == *ppLineProxyReqestList )
  6089. {
  6090. LOG((TL_ERROR, "LineGetProxyStatus - alloc failed"));
  6091. return E_OUTOFMEMORY;
  6092. }
  6093. (*ppLineProxyReqestList)->dwTotalSize = dwSize;
  6094. FUNC_ARGS funcArgs =
  6095. {
  6096. MAKELONG (LINE_FUNC | SYNC | 4, lGetProxyStatus),
  6097. {
  6098. (ULONG_PTR)hLineApp,
  6099. dwDeviceID,
  6100. dwAppAPIVersion,
  6101. (ULONG_PTR) *ppLineProxyReqestList
  6102. },
  6103. {
  6104. hXxxApp,
  6105. Dword,
  6106. Dword,
  6107. lpGet_Struct
  6108. }
  6109. };
  6110. while (TRUE)
  6111. {
  6112. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineGetProxyStatus") );
  6113. if ( FAILED(hr) )
  6114. {
  6115. ClientFree( *ppLineProxyReqestList );
  6116. *ppLineProxyReqestList = NULL;
  6117. return hr;
  6118. }
  6119. //
  6120. // succeeded, but need a bigger buffer?
  6121. //
  6122. if ( (*ppLineProxyReqestList)->dwNeededSize > (*ppLineProxyReqestList)->dwTotalSize )
  6123. {
  6124. dwSize = (*ppLineProxyReqestList)->dwNeededSize;
  6125. ClientFree( *ppLineProxyReqestList );
  6126. *ppLineProxyReqestList = (LPLINEPROXYREQUESTLIST) ClientAlloc( dwSize );
  6127. if (NULL == *ppLineProxyReqestList)
  6128. {
  6129. return E_OUTOFMEMORY;
  6130. }
  6131. (*ppLineProxyReqestList)->dwTotalSize = dwSize;
  6132. funcArgs.Args[3] = (ULONG_PTR)*ppLineProxyReqestList;
  6133. }
  6134. else
  6135. {
  6136. //
  6137. // plain success
  6138. //
  6139. break;
  6140. }
  6141. }
  6142. return hr;
  6143. }
  6144. LONG
  6145. WINAPI
  6146. lineGetNewCalls(
  6147. HLINE hLine,
  6148. DWORD dwAddressID,
  6149. DWORD dwSelect,
  6150. LPLINECALLLIST lpCallList
  6151. )
  6152. {
  6153. FUNC_ARGS funcArgs =
  6154. {
  6155. MAKELONG (LINE_FUNC | SYNC | 4, lGetNewCalls),
  6156. {
  6157. (ULONG_PTR) hLine,
  6158. dwAddressID,
  6159. dwSelect,
  6160. (ULONG_PTR) lpCallList
  6161. },
  6162. {
  6163. Dword,
  6164. Dword,
  6165. Dword,
  6166. lpGet_Struct
  6167. }
  6168. };
  6169. return (DOFUNC (&funcArgs, "lineGetNewCalls"));
  6170. }
  6171. LONG
  6172. WINAPI
  6173. lineGetNumRings(
  6174. HLINE hLine,
  6175. DWORD dwAddressID,
  6176. LPDWORD lpdwNumRings
  6177. )
  6178. {
  6179. FUNC_ARGS funcArgs =
  6180. {
  6181. MAKELONG (LINE_FUNC | SYNC | 3, lGetNumRings),
  6182. {
  6183. (ULONG_PTR) hLine,
  6184. dwAddressID,
  6185. (ULONG_PTR) lpdwNumRings
  6186. },
  6187. {
  6188. Dword,
  6189. Dword,
  6190. lpDword
  6191. }
  6192. };
  6193. return (DOFUNC (&funcArgs, "lineGetNumRings"));
  6194. }
  6195. HRESULT
  6196. LineGetProviderList(
  6197. LPLINEPROVIDERLIST * ppProviderList
  6198. )
  6199. {
  6200. LONG lResult;
  6201. *ppProviderList = (LPLINEPROVIDERLIST) ClientAlloc( sizeof (LINEPROVIDERLIST) +
  6202. 5*sizeof(LINEPROVIDERENTRY));
  6203. if (NULL == *ppProviderList)
  6204. {
  6205. return E_OUTOFMEMORY;
  6206. }
  6207. (*ppProviderList)->dwTotalSize = sizeof(LINEPROVIDERLIST) + 5*sizeof(LINEPROVIDERENTRY);
  6208. FUNC_ARGS funcArgs =
  6209. {
  6210. MAKELONG (LINE_FUNC | SYNC | 2, lGetProviderList),
  6211. {
  6212. TAPI_CURRENT_VERSION,
  6213. (ULONG_PTR) *ppProviderList
  6214. },
  6215. {
  6216. Dword,
  6217. lpGet_Struct
  6218. }
  6219. };
  6220. while (TRUE)
  6221. {
  6222. lResult = DOFUNC (&funcArgs, "lineGetProviderList");
  6223. if ((0 == lResult) && ((*ppProviderList)->dwNeededSize > (*ppProviderList)->dwTotalSize))
  6224. {
  6225. DWORD dwSize;
  6226. dwSize = (*ppProviderList)->dwNeededSize;
  6227. ClientFree(*ppProviderList);
  6228. *ppProviderList = (LPLINEPROVIDERLIST) ClientAlloc( dwSize );
  6229. if (NULL == (*ppProviderList))
  6230. {
  6231. return E_OUTOFMEMORY;
  6232. }
  6233. (*ppProviderList)->dwTotalSize = dwSize;
  6234. funcArgs.Args[1] = (ULONG_PTR) *ppProviderList;
  6235. }
  6236. else if ( 0 != lResult )
  6237. {
  6238. ClientFree( *ppProviderList );
  6239. *ppProviderList = NULL;
  6240. break;
  6241. }
  6242. else
  6243. {
  6244. break;
  6245. }
  6246. }
  6247. return mapTAPIErrorCode( lResult );
  6248. }
  6249. HRESULT
  6250. LineGetRequest(
  6251. HLINEAPP hLineApp,
  6252. DWORD dwRequestMode,
  6253. LPLINEREQMAKECALLW * ppReqMakeCall
  6254. )
  6255. {
  6256. *ppReqMakeCall = (LPLINEREQMAKECALLW)ClientAlloc( sizeof(LINEREQMAKECALLW) );
  6257. if ( NULL == *ppReqMakeCall )
  6258. {
  6259. return E_OUTOFMEMORY;
  6260. }
  6261. FUNC_ARGS funcArgs =
  6262. {
  6263. MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
  6264. {
  6265. (ULONG_PTR) hLineApp,
  6266. dwRequestMode,
  6267. (ULONG_PTR) *ppReqMakeCall,
  6268. 0
  6269. },
  6270. {
  6271. hXxxApp,
  6272. Dword,
  6273. lpGet_SizeToFollow,
  6274. Size
  6275. }
  6276. };
  6277. if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
  6278. {
  6279. //
  6280. // Set the size param appropriately
  6281. //
  6282. funcArgs.Args[3] = sizeof(LINEREQMAKECALLW);
  6283. }
  6284. else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
  6285. {
  6286. //
  6287. // Set the size param appropriately
  6288. //
  6289. funcArgs.Args[3] = sizeof(LINEREQMEDIACALLW);
  6290. }
  6291. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetRequest"));
  6292. }
  6293. LONG
  6294. WINAPI
  6295. lineGetStatusMessages(
  6296. HLINE hLine,
  6297. LPDWORD lpdwLineStates,
  6298. LPDWORD lpdwAddressStates
  6299. )
  6300. {
  6301. FUNC_ARGS funcArgs =
  6302. {
  6303. MAKELONG (LINE_FUNC | SYNC | 3, lGetStatusMessages),
  6304. {
  6305. (ULONG_PTR) hLine,
  6306. (ULONG_PTR) lpdwLineStates,
  6307. (ULONG_PTR) lpdwAddressStates
  6308. },
  6309. {
  6310. Dword,
  6311. lpDword,
  6312. lpDword
  6313. }
  6314. };
  6315. if (lpdwLineStates == lpdwAddressStates)
  6316. {
  6317. return LINEERR_INVALPOINTER;
  6318. }
  6319. return (DOFUNC (&funcArgs, "lineGetStatusMessages"));
  6320. }
  6321. HRESULT
  6322. LineHandoff(
  6323. HCALL hCall,
  6324. LPCWSTR lpszFileName,
  6325. DWORD dwMediaMode
  6326. )
  6327. {
  6328. FUNC_ARGS funcArgs =
  6329. {
  6330. MAKELONG (LINE_FUNC | SYNC | 3, lHandoff),
  6331. {
  6332. (ULONG_PTR) hCall,
  6333. (ULONG_PTR) lpszFileName,
  6334. dwMediaMode
  6335. },
  6336. {
  6337. Dword,
  6338. lpszW,
  6339. Dword
  6340. }
  6341. };
  6342. if (lpszFileName == (LPCWSTR) NULL)
  6343. {
  6344. //
  6345. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6346. //
  6347. funcArgs.ArgTypes[1] = Dword;
  6348. funcArgs.Args[1] = TAPI_NO_DATA;
  6349. }
  6350. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineHandoff") );
  6351. }
  6352. HRESULT
  6353. LineHold(
  6354. HCALL hCall
  6355. )
  6356. {
  6357. FUNC_ARGS funcArgs =
  6358. {
  6359. MAKELONG (LINE_FUNC | ASYNC | 1, lHold),
  6360. {
  6361. (ULONG_PTR) hCall
  6362. },
  6363. {
  6364. Dword
  6365. }
  6366. };
  6367. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineHold"));
  6368. }
  6369. PWSTR
  6370. PASCAL
  6371. MultiToWide(
  6372. LPCSTR lpStr
  6373. )
  6374. {
  6375. DWORD dwSize;
  6376. PWSTR szTempPtr;
  6377. dwSize = MultiByteToWideChar(
  6378. GetACP(),
  6379. MB_PRECOMPOSED,
  6380. lpStr,
  6381. -1,
  6382. NULL,
  6383. 0
  6384. );
  6385. if ((szTempPtr = (PWSTR) ClientAlloc ((dwSize + 1) * sizeof (WCHAR))))
  6386. {
  6387. MultiByteToWideChar(
  6388. GetACP(),
  6389. MB_PRECOMPOSED,
  6390. lpStr,
  6391. -1,
  6392. szTempPtr,
  6393. dwSize + 1
  6394. );
  6395. }
  6396. return szTempPtr;
  6397. }
  6398. void
  6399. PASCAL
  6400. lineMakeCallPostProcess(
  6401. PASYNCEVENTMSG pMsg
  6402. )
  6403. {
  6404. LOG((TL_TRACE, "lineMakeCallPostProcess: enter"));
  6405. LOG((TL_INFO,
  6406. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  6407. pMsg->Param1,
  6408. pMsg->Param2,
  6409. pMsg->Param3,
  6410. pMsg->Param4
  6411. ));
  6412. if (pMsg->Param2 == 0)
  6413. {
  6414. HCALL hCall = (HCALL) pMsg->Param3;
  6415. LPHCALL lphCall = (LPHCALL)GetHandleTableEntry(pMsg->Param4);
  6416. DeleteHandleTableEntry(pMsg->Param4);
  6417. __try
  6418. {
  6419. {
  6420. *lphCall = NULL;
  6421. *lphCall = hCall;
  6422. }
  6423. }
  6424. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  6425. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  6426. {
  6427. LOG((TL_WARN,
  6428. "lineMakeCallPostProcess: failed to write handle %lx to memory"
  6429. " location %p. returning LINEERR_INVALPOINTER",
  6430. hCall, lphCall));
  6431. pMsg->Param2 = LINEERR_INVALPOINTER;
  6432. //
  6433. // tapisrv has allocated a call handle for us. deallocate it.
  6434. //
  6435. LineDeallocateCall(hCall);
  6436. }
  6437. }
  6438. }
  6439. HRESULT
  6440. LineMakeCall(
  6441. T3LINE * pt3Line,
  6442. HCALL * phCall,
  6443. LPCWSTR lpszDestAddress,
  6444. DWORD dwCountryCode,
  6445. LPLINECALLPARAMS const lpCallParams
  6446. )
  6447. {
  6448. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  6449. FUNC_ARGS funcArgs =
  6450. {
  6451. MAKELONG (LINE_FUNC | ASYNC | 7, lMakeCall),
  6452. {
  6453. GetFunctionIndex(lineMakeCallPostProcess),
  6454. (ULONG_PTR) pt3Line->hLine,
  6455. hpCallHandle,
  6456. (ULONG_PTR) lpszDestAddress,
  6457. (ULONG_PTR) dwCountryCode,
  6458. (ULONG_PTR) lpCallParams,
  6459. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  6460. },
  6461. {
  6462. Dword,
  6463. Dword,
  6464. Dword,
  6465. lpszW,
  6466. Dword,
  6467. lpSet_Struct,
  6468. Dword
  6469. }
  6470. };
  6471. if (!lpszDestAddress)
  6472. {
  6473. //
  6474. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6475. //
  6476. funcArgs.ArgTypes[3] = Dword;
  6477. funcArgs.Args[3] = TAPI_NO_DATA;
  6478. }
  6479. if (!lpCallParams)
  6480. {
  6481. //
  6482. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6483. //
  6484. funcArgs.ArgTypes[5] = Dword;
  6485. funcArgs.Args[5] = TAPI_NO_DATA;
  6486. }
  6487. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMakeCall") );
  6488. if (FAILED(hr))
  6489. {
  6490. DeleteHandleTableEntry(hpCallHandle);
  6491. }
  6492. return hr;
  6493. }
  6494. HRESULT
  6495. LineMonitorDigits(
  6496. HCALL hCall,
  6497. DWORD dwDigitModes
  6498. )
  6499. {
  6500. FUNC_ARGS funcArgs =
  6501. {
  6502. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
  6503. {
  6504. (ULONG_PTR) hCall,
  6505. dwDigitModes
  6506. },
  6507. {
  6508. Dword,
  6509. Dword
  6510. }
  6511. };
  6512. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMonitorDigits") );
  6513. }
  6514. LONG
  6515. WINAPI
  6516. lineMonitorMedia(
  6517. HCALL hCall,
  6518. DWORD dwMediaModes
  6519. )
  6520. {
  6521. FUNC_ARGS funcArgs =
  6522. {
  6523. MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
  6524. {
  6525. (ULONG_PTR) hCall,
  6526. dwMediaModes
  6527. },
  6528. {
  6529. Dword,
  6530. Dword
  6531. }
  6532. };
  6533. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineMonitorMedia") );
  6534. }
  6535. HRESULT
  6536. LineMonitorTones(
  6537. HCALL hCall,
  6538. LPLINEMONITORTONE const lpToneList,
  6539. DWORD dwNumEntries
  6540. )
  6541. {
  6542. FUNC_ARGS funcArgs =
  6543. {
  6544. MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
  6545. {
  6546. (ULONG_PTR) hCall,
  6547. (ULONG_PTR) lpToneList,
  6548. dwNumEntries * sizeof(LINEMONITORTONE),
  6549. 0 // dwToneListID, remotesp only
  6550. },
  6551. {
  6552. Dword,
  6553. lpSet_SizeToFollow,
  6554. Size,
  6555. Dword
  6556. }
  6557. };
  6558. if (!lpToneList)
  6559. {
  6560. //
  6561. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6562. //
  6563. funcArgs.ArgTypes[1] = Dword;
  6564. funcArgs.Args[1] = TAPI_NO_DATA;
  6565. funcArgs.ArgTypes[2] = Dword;
  6566. }
  6567. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineMonitorTones"));
  6568. }
  6569. HRESULT
  6570. LineNegotiateAPIVersion(
  6571. HLINEAPP hLineApp,
  6572. DWORD dwDeviceID,
  6573. LPDWORD lpdwAPIVersion
  6574. )
  6575. {
  6576. LINEEXTENSIONID LED;
  6577. LOG((TL_INFO, "LineNegotiateAPIVersion: hLineApp %p", hLineApp));
  6578. FUNC_ARGS funcArgs =
  6579. {
  6580. MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
  6581. {
  6582. (ULONG_PTR) hLineApp,
  6583. dwDeviceID,
  6584. TAPI_VERSION1_0,
  6585. TAPI_VERSION_CURRENT,
  6586. (ULONG_PTR) lpdwAPIVersion,
  6587. (ULONG_PTR) &LED,
  6588. (ULONG_PTR) sizeof(LINEEXTENSIONID)
  6589. },
  6590. {
  6591. hXxxApp,
  6592. Dword,
  6593. Dword,
  6594. Dword,
  6595. lpDword,
  6596. lpGet_SizeToFollow,
  6597. Size
  6598. }
  6599. };
  6600. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineNegotiateAPIVersion") );
  6601. }
  6602. LONG
  6603. WINAPI
  6604. lineNegotiateExtVersion(
  6605. HLINEAPP hLineApp,
  6606. DWORD dwDeviceID,
  6607. DWORD dwAPIVersion,
  6608. DWORD dwExtLowVersion,
  6609. DWORD dwExtHighVersion,
  6610. LPDWORD lpdwExtVersion
  6611. )
  6612. {
  6613. FUNC_ARGS funcArgs =
  6614. {
  6615. MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
  6616. {
  6617. (ULONG_PTR) hLineApp,
  6618. dwDeviceID,
  6619. dwAPIVersion,
  6620. dwExtLowVersion,
  6621. dwExtHighVersion,
  6622. (ULONG_PTR) lpdwExtVersion
  6623. },
  6624. {
  6625. hXxxApp,
  6626. Dword,
  6627. Dword,
  6628. Dword,
  6629. Dword,
  6630. lpDword
  6631. }
  6632. };
  6633. return (DOFUNC (&funcArgs, "lineNegotiateExtVersion"));
  6634. }
  6635. HRESULT
  6636. LineOpen(
  6637. HLINEAPP hLineApp,
  6638. DWORD dwDeviceID,
  6639. DWORD dwAddressID,
  6640. T3LINE * pt3Line,
  6641. DWORD dwAPIVersion,
  6642. DWORD dwPrivileges,
  6643. DWORD dwMediaModes,
  6644. AddressLineStruct * pAddressLine,
  6645. LPLINECALLPARAMS const lpCallParams,
  6646. CAddress * pAddress,
  6647. CTAPI * pTapiObj,
  6648. BOOL bAddToHashTable
  6649. )
  6650. {
  6651. LONG lResult;
  6652. LINECALLPARAMS lcp;
  6653. LINECALLPARAMS * plcp;
  6654. if (IsBadReadPtr(pt3Line, sizeof(T3LINE)))
  6655. {
  6656. LOG((TL_ERROR, "LineOpen: pt3Line %p -- invalid ptr ", pt3Line));
  6657. //
  6658. // if we are getting an invalid ptr, we need to see why
  6659. //
  6660. _ASSERTE(FALSE);
  6661. return E_POINTER;
  6662. }
  6663. if (NULL == lpCallParams)
  6664. {
  6665. memset(
  6666. &lcp,
  6667. 0,
  6668. sizeof(lcp)
  6669. );
  6670. lcp.dwTotalSize = sizeof(lcp);
  6671. lcp.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
  6672. lcp.dwAddressID = dwAddressID;
  6673. plcp = &lcp;
  6674. }
  6675. else
  6676. {
  6677. plcp = lpCallParams;
  6678. }
  6679. dwPrivileges|= LINEOPENOPTION_SINGLEADDRESS;
  6680. //
  6681. // if we were passed a pAddressLine pointer, create a corresponding
  6682. // DWORD-sized handle, and keep it around in the T3LINE structure.
  6683. // we need this so we can remove the handle table entry on LineClose.
  6684. //
  6685. _ASSERTE(0 == pt3Line->dwAddressLineStructHandle);
  6686. if (NULL != pAddressLine)
  6687. {
  6688. pt3Line->dwAddressLineStructHandle = CreateHandleTableEntry((UINT_PTR)pAddressLine);
  6689. }
  6690. FUNC_ARGS funcArgs =
  6691. {
  6692. MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
  6693. {
  6694. (ULONG_PTR) hLineApp,
  6695. dwDeviceID,
  6696. (ULONG_PTR) &(pt3Line->hLine),
  6697. dwAPIVersion,
  6698. 0,
  6699. pt3Line->dwAddressLineStructHandle,
  6700. dwPrivileges, //| LINEOPENOPTION_SINGLEADDRESS),
  6701. dwMediaModes,
  6702. (ULONG_PTR) plcp,
  6703. (ULONG_PTR) 0xffffffff, // dwAsciiCallParamsCodePage
  6704. 0 // LINEOPEN_PARAMS.hRemoteLine
  6705. },
  6706. {
  6707. hXxxApp,
  6708. Dword,
  6709. lpDword,
  6710. Dword,
  6711. Dword,
  6712. Dword,
  6713. Dword,
  6714. Dword,
  6715. lpSet_Struct,
  6716. Dword,
  6717. Dword
  6718. }
  6719. };
  6720. if (!(dwPrivileges & (LINEOPENOPTION_PROXY|LINEOPENOPTION_SINGLEADDRESS)))
  6721. {
  6722. //
  6723. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6724. //
  6725. funcArgs.ArgTypes[8] = Dword;
  6726. funcArgs.Args[8] = TAPI_NO_DATA;
  6727. }
  6728. gpLineHashTable->Lock();
  6729. lResult = (DOFUNC (&funcArgs, "lineOpen"));
  6730. #if DBG
  6731. LOG((TL_INFO, "Returning from lineOpenW, *lphLine = 0x%08lx", pt3Line->hLine));
  6732. LOG((TL_INFO, "Returning from lineOpenW, retcode = 0x%08lx", lResult));
  6733. #endif
  6734. if ( 0 == lResult && bAddToHashTable)
  6735. {
  6736. gpLineHashTable->Insert( (ULONG_PTR)(pt3Line->hLine), (ULONG_PTR)pAddress, pTapiObj );
  6737. }
  6738. gpLineHashTable->Unlock();
  6739. //
  6740. // if an address line handle was created, but the call failed, remove the
  6741. // entry from the handle table
  6742. //
  6743. if ( (0 != lResult) && (0 != pt3Line->dwAddressLineStructHandle))
  6744. {
  6745. DeleteHandleTableEntry(pt3Line->dwAddressLineStructHandle);
  6746. pt3Line->dwAddressLineStructHandle = 0;
  6747. }
  6748. return mapTAPIErrorCode( lResult );
  6749. }
  6750. HRESULT
  6751. LinePark(
  6752. HCALL hCall,
  6753. DWORD dwParkMode,
  6754. LPCWSTR lpszDirAddress,
  6755. LPVARSTRING * ppNonDirAddress
  6756. )
  6757. {
  6758. HRESULT hr = S_OK;
  6759. long lResult;
  6760. DWORD dwSize = sizeof (VARSTRING) + 500;
  6761. LOG((TL_TRACE, "LinePark - enter"));
  6762. if ( NULL != ppNonDirAddress )
  6763. {
  6764. *ppNonDirAddress = (LPVARSTRING) ClientAlloc(dwSize);
  6765. if (NULL == *ppNonDirAddress)
  6766. {
  6767. return E_OUTOFMEMORY;
  6768. }
  6769. (*ppNonDirAddress)->dwTotalSize = dwSize;
  6770. }
  6771. FUNC_ARGS funcArgs =
  6772. {
  6773. MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
  6774. {
  6775. (ULONG_PTR) 0, // post process proc
  6776. (ULONG_PTR) hCall,
  6777. (ULONG_PTR) dwParkMode,
  6778. (ULONG_PTR) TAPI_NO_DATA, //lpszDirAddress,
  6779. (ULONG_PTR) 0, // pass ptr as Dword for post processing
  6780. (ULONG_PTR) TAPI_NO_DATA, //lpNonDirAddress // pass ptr as lpGet_Xx for IsValPtr chk
  6781. },
  6782. {
  6783. Dword,
  6784. Dword,
  6785. Dword,
  6786. Dword, // lpszW,
  6787. Dword,
  6788. Dword, // lpGet_Struct
  6789. }
  6790. };
  6791. DWORD hpNonDirAddress = 0;
  6792. if (dwParkMode == LINEPARKMODE_DIRECTED)
  6793. {
  6794. funcArgs.ArgTypes[3] = lpszW;
  6795. funcArgs.Args[3] = (ULONG_PTR) lpszDirAddress;
  6796. }
  6797. else if (dwParkMode == LINEPARKMODE_NONDIRECTED)
  6798. {
  6799. if ( NULL == ppNonDirAddress )
  6800. {
  6801. return E_POINTER;
  6802. }
  6803. //
  6804. // Set post process proc
  6805. //
  6806. funcArgs.Args[0] = GetFunctionIndex(lineDevSpecificPostProcess),
  6807. hpNonDirAddress = CreateHandleTableEntry((ULONG_PTR)*ppNonDirAddress);
  6808. funcArgs.ArgTypes[4] = Dword;
  6809. funcArgs.Args[4] = hpNonDirAddress;
  6810. funcArgs.ArgTypes[5] = lpGet_Struct;
  6811. funcArgs.Args[5] = (ULONG_PTR) *ppNonDirAddress;
  6812. }
  6813. while (TRUE)
  6814. {
  6815. lResult = DOFUNC (&funcArgs, "LinePark");
  6816. if (lResult == LINEERR_STRUCTURETOOSMALL)
  6817. {
  6818. // didnt Work , adjust buffer size & try again
  6819. LOG((TL_INFO, "LinePark failed - buffer too small"));
  6820. dwSize = (*ppNonDirAddress)->dwNeededSize;
  6821. //
  6822. // no longer need the handle
  6823. //
  6824. DeleteHandleTableEntry(hpNonDirAddress);
  6825. hpNonDirAddress = 0;
  6826. ClientFree( *ppNonDirAddress );
  6827. *ppNonDirAddress = (LPVARSTRING) ClientAlloc( dwSize );
  6828. if (*ppNonDirAddress == NULL)
  6829. {
  6830. LOG((TL_ERROR, "LinePark - repeat ClientAlloc failed"));
  6831. hr = E_OUTOFMEMORY;
  6832. break;
  6833. }
  6834. else
  6835. {
  6836. //
  6837. // get a handle corresponding to the new *ppNonDirAddress and
  6838. // use it to pass to DoFunc
  6839. //
  6840. hpNonDirAddress = CreateHandleTableEntry((ULONG_PTR)*ppNonDirAddress);
  6841. if (0 == hpNonDirAddress)
  6842. {
  6843. LOG((TL_ERROR, "LinePark - repeat CreateHandleTableEntry failed"));
  6844. hr = E_OUTOFMEMORY;
  6845. ClientFree(*ppNonDirAddress);
  6846. *ppNonDirAddress = NULL;
  6847. break;
  6848. }
  6849. funcArgs.Args[4] = hpNonDirAddress;
  6850. (*ppNonDirAddress)->dwTotalSize = dwSize;
  6851. }
  6852. }
  6853. else if (lResult < 0)
  6854. {
  6855. if ( NULL != ppNonDirAddress )
  6856. {
  6857. ClientFree( *ppNonDirAddress );
  6858. }
  6859. hr = mapTAPIErrorCode( lResult );
  6860. break;
  6861. }
  6862. else
  6863. {
  6864. hr = lResult;
  6865. break;
  6866. }
  6867. } // end while(TRUE)
  6868. //
  6869. // if we failed, remove the handle table entry because it will not be cleared by the callback
  6870. //
  6871. if (FAILED(hr) && (0 != hpNonDirAddress))
  6872. {
  6873. DeleteHandleTableEntry(hpNonDirAddress);
  6874. hpNonDirAddress = 0;
  6875. }
  6876. LOG((TL_TRACE, hr, "LinePark - exit"));
  6877. return hr;
  6878. }
  6879. HRESULT
  6880. LinePickup(
  6881. HLINE hLine,
  6882. DWORD dwAddressID,
  6883. HCALL *phCall,
  6884. LPCWSTR lpszDestAddress,
  6885. LPCWSTR lpszGroupID
  6886. )
  6887. {
  6888. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  6889. FUNC_ARGS funcArgs =
  6890. {
  6891. MAKELONG (LINE_FUNC | ASYNC | 6, lPickup),
  6892. {
  6893. GetFunctionIndex(lineMakeCallPostProcess),
  6894. (ULONG_PTR) hLine,
  6895. (ULONG_PTR) dwAddressID,
  6896. hpCallHandle,
  6897. (ULONG_PTR) lpszDestAddress,
  6898. (ULONG_PTR) lpszGroupID
  6899. },
  6900. {
  6901. Dword,
  6902. Dword,
  6903. Dword,
  6904. Dword,
  6905. lpszW,
  6906. lpszW
  6907. }
  6908. };
  6909. if (!lpszDestAddress)
  6910. {
  6911. //
  6912. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6913. //
  6914. funcArgs.ArgTypes[4] = Dword;
  6915. funcArgs.Args[4] = TAPI_NO_DATA;
  6916. }
  6917. if (!lpszGroupID)
  6918. {
  6919. //
  6920. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6921. //
  6922. funcArgs.ArgTypes[5] = Dword;
  6923. funcArgs.Args[5] = TAPI_NO_DATA;
  6924. }
  6925. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "linePickup") );
  6926. if (FAILED(hr))
  6927. {
  6928. DeleteHandleTableEntry(hpCallHandle);
  6929. hpCallHandle = 0;
  6930. }
  6931. return hr;
  6932. }
  6933. HRESULT
  6934. LinePrepareAddToConference(
  6935. HCALL hConfCall,
  6936. HCALL * phConsultCall,
  6937. LPLINECALLPARAMS const lpCallParams
  6938. )
  6939. {
  6940. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR)phConsultCall);
  6941. FUNC_ARGS funcArgs =
  6942. {
  6943. MAKELONG (LINE_FUNC | ASYNC | 5, lPrepareAddToConference),
  6944. {
  6945. GetFunctionIndex(lineMakeCallPostProcess),
  6946. (ULONG_PTR) hConfCall,
  6947. hpConsultCallHandle,
  6948. (ULONG_PTR) lpCallParams,
  6949. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  6950. },
  6951. {
  6952. Dword,
  6953. Dword,
  6954. Dword,
  6955. lpSet_Struct,
  6956. Dword
  6957. }
  6958. };
  6959. if (!lpCallParams)
  6960. {
  6961. //
  6962. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  6963. //
  6964. funcArgs.ArgTypes[3] = Dword;
  6965. funcArgs.Args[3] = TAPI_NO_DATA;
  6966. }
  6967. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LinePrepareAddToConference") );
  6968. if (FAILED(hr))
  6969. {
  6970. DeleteHandleTableEntry(hpConsultCallHandle);
  6971. }
  6972. return hr;
  6973. }
  6974. LONG
  6975. WINAPI
  6976. lineProxyMessage(
  6977. HLINE hLine,
  6978. HCALL hCall,
  6979. DWORD dwMsg,
  6980. DWORD Param1,
  6981. DWORD Param2,
  6982. DWORD Param3
  6983. )
  6984. {
  6985. FUNC_ARGS funcArgs =
  6986. {
  6987. MAKELONG (LINE_FUNC | SYNC | 6, lProxyMessage),
  6988. {
  6989. (ULONG_PTR) hLine,
  6990. (ULONG_PTR) hCall,
  6991. dwMsg,
  6992. Param1,
  6993. Param2,
  6994. Param3
  6995. },
  6996. {
  6997. Dword,
  6998. Dword,
  6999. Dword,
  7000. Dword,
  7001. Dword,
  7002. Dword,
  7003. }
  7004. };
  7005. return (DOFUNC (&funcArgs, "lineProxyMessage"));
  7006. }
  7007. LONG
  7008. WINAPI
  7009. lineProxyResponse(
  7010. HLINE hLine,
  7011. LPLINEPROXYREQUEST lpProxyRequest,
  7012. DWORD dwResult
  7013. )
  7014. {
  7015. LONG lResult = 0;
  7016. FUNC_ARGS funcArgs =
  7017. {
  7018. MAKELONG (LINE_FUNC | SYNC | 4, lProxyResponse),
  7019. {
  7020. (ULONG_PTR) hLine,
  7021. (ULONG_PTR) 0,
  7022. (ULONG_PTR) lpProxyRequest,
  7023. (ULONG_PTR) dwResult
  7024. },
  7025. {
  7026. Dword,
  7027. Dword,
  7028. lpSet_Struct,
  7029. Dword
  7030. }
  7031. };
  7032. PPROXYREQUESTHEADER pProxyRequestHeader;
  7033. //
  7034. // The following is not the most thorough checking, but it's close
  7035. // enough that a client app won't get a totally unexpected value
  7036. // back
  7037. //
  7038. if (dwResult != 0 &&
  7039. (dwResult < LINEERR_ALLOCATED ||
  7040. dwResult > LINEERR_DIALVOICEDETECT))
  7041. {
  7042. return LINEERR_INVALPARAM;
  7043. }
  7044. //
  7045. // Backtrack a little bit to get the pointer to what ought to be
  7046. // the proxy header, and then make sure we're dealing with a valid
  7047. // proxy request
  7048. //
  7049. pProxyRequestHeader = (PPROXYREQUESTHEADER)
  7050. (((LPBYTE) lpProxyRequest) - sizeof (PROXYREQUESTHEADER));
  7051. __try
  7052. {
  7053. //
  7054. // Make sure we've a valid pProxyRequestHeader, then invalidate
  7055. // the key so subsequent attempts to call lineProxyResponse with
  7056. // the same lpProxyRequest fail
  7057. //
  7058. // if ((DWORD) pProxyRequestHeader & 0x7 ||
  7059. if(pProxyRequestHeader->dwKey != TPROXYREQUESTHEADER_KEY)
  7060. {
  7061. lResult = LINEERR_INVALPOINTER;
  7062. }
  7063. pProxyRequestHeader->dwKey = 0xefefefef;
  7064. funcArgs.Args[1] = pProxyRequestHeader->dwInstance;
  7065. //
  7066. // See if this is one of the requests that don't require
  7067. // any data to get passed back & reset the appropriate
  7068. // params if so
  7069. //
  7070. switch (lpProxyRequest->dwRequestType)
  7071. {
  7072. case LINEPROXYREQUEST_SETAGENTGROUP:
  7073. case LINEPROXYREQUEST_SETAGENTSTATE:
  7074. case LINEPROXYREQUEST_SETAGENTACTIVITY:
  7075. case LINEPROXYREQUEST_SETAGENTMEASUREMENTPERIOD:
  7076. case LINEPROXYREQUEST_SETAGENTSESSIONSTATE:
  7077. case LINEPROXYREQUEST_SETQUEUEMEASUREMENTPERIOD:
  7078. case LINEPROXYREQUEST_SETAGENTSTATEEX:
  7079. funcArgs.Args[2] = TAPI_NO_DATA;
  7080. funcArgs.ArgTypes[2] = Dword;
  7081. break;
  7082. }
  7083. }
  7084. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  7085. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  7086. {
  7087. lResult = LINEERR_INVALPOINTER;
  7088. }
  7089. if (lResult == 0)
  7090. {
  7091. lResult = DOFUNC (&funcArgs, "lineProxyResponse");
  7092. //
  7093. // If we've gotten this far we want to free the buffer
  7094. // unconditionally
  7095. //
  7096. ClientFree (pProxyRequestHeader);
  7097. }
  7098. return lResult;
  7099. }
  7100. LONG
  7101. WINAPI
  7102. lineRedirectW(
  7103. HCALL hCall,
  7104. LPCWSTR lpszDestAddress,
  7105. DWORD dwCountryCode
  7106. )
  7107. {
  7108. FUNC_ARGS funcArgs =
  7109. {
  7110. MAKELONG (LINE_FUNC | ASYNC | 3, lRedirect),
  7111. {
  7112. (ULONG_PTR) hCall,
  7113. (ULONG_PTR) lpszDestAddress,
  7114. dwCountryCode
  7115. },
  7116. {
  7117. Dword,
  7118. lpszW,
  7119. Dword
  7120. }
  7121. };
  7122. return (DOFUNC (&funcArgs, "lineRedirect"));
  7123. }
  7124. HRESULT
  7125. LineRegisterRequestRecipient(
  7126. HLINEAPP hLineApp,
  7127. DWORD dwRegistrationInstance,
  7128. DWORD dwRequestMode,
  7129. #ifdef NEWREQUEST
  7130. DWORD dwAddressTypes,
  7131. #endif
  7132. DWORD bEnable
  7133. )
  7134. {
  7135. FUNC_ARGS funcArgs =
  7136. {
  7137. MAKELONG (LINE_FUNC | SYNC | 4, lRegisterRequestRecipient),
  7138. {
  7139. (ULONG_PTR) hLineApp,
  7140. dwRegistrationInstance,
  7141. dwRequestMode,
  7142. bEnable
  7143. },
  7144. {
  7145. hXxxApp,
  7146. Dword,
  7147. Dword,
  7148. Dword
  7149. }
  7150. };
  7151. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineRegisterRequestRecipient"));
  7152. }
  7153. HRESULT
  7154. LineReleaseUserUserInfo(
  7155. HCALL hCall
  7156. )
  7157. {
  7158. if ( !hCall )
  7159. {
  7160. return TAPI_E_INVALCALLSTATE;
  7161. }
  7162. FUNC_ARGS funcArgs =
  7163. {
  7164. MAKELONG (LINE_FUNC | ASYNC | 1, lReleaseUserUserInfo),
  7165. {
  7166. (ULONG_PTR) hCall
  7167. },
  7168. {
  7169. Dword,
  7170. }
  7171. };
  7172. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineReleaseUserUserInfo") );
  7173. }
  7174. HRESULT
  7175. LineRemoveFromConference(
  7176. HCALL hCall
  7177. )
  7178. {
  7179. FUNC_ARGS funcArgs =
  7180. {
  7181. MAKELONG (LINE_FUNC | ASYNC | 1, lRemoveFromConference),
  7182. {
  7183. (ULONG_PTR) hCall
  7184. },
  7185. {
  7186. Dword
  7187. }
  7188. };
  7189. return mapTAPIErrorCode( DOFUNC (&funcArgs, "LineRemoveFromConference") );
  7190. }
  7191. LONG
  7192. WINAPI
  7193. lineRemoveProvider(
  7194. DWORD dwPermanentProviderID,
  7195. HWND hwndOwner
  7196. )
  7197. {
  7198. return (lineXxxProvider(
  7199. gszTUISPI_providerRemove, // func name
  7200. NULL, // lpszProviderFilename
  7201. hwndOwner, // hwndOwner
  7202. dwPermanentProviderID, // dwPermProviderID
  7203. NULL // lpdwPermProviderID
  7204. ));
  7205. }
  7206. LONG
  7207. WINAPI
  7208. lineSecureCall(
  7209. HCALL hCall
  7210. )
  7211. {
  7212. FUNC_ARGS funcArgs =
  7213. {
  7214. MAKELONG (LINE_FUNC | ASYNC | 1, lSecureCall),
  7215. {
  7216. (ULONG_PTR) hCall
  7217. },
  7218. {
  7219. Dword
  7220. }
  7221. };
  7222. return (DOFUNC (&funcArgs, "lineSecureCall"));
  7223. }
  7224. HRESULT
  7225. LineSendUserUserInfo(
  7226. HCALL hCall,
  7227. LPCSTR lpsUserUserInfo,
  7228. DWORD dwSize
  7229. )
  7230. {
  7231. FUNC_ARGS funcArgs =
  7232. {
  7233. MAKELONG (LINE_FUNC | ASYNC | 3, lSendUserUserInfo),
  7234. {
  7235. (ULONG_PTR) hCall,
  7236. (ULONG_PTR) lpsUserUserInfo,
  7237. dwSize
  7238. },
  7239. {
  7240. Dword,
  7241. lpSet_SizeToFollow,
  7242. Size
  7243. }
  7244. };
  7245. if (!lpsUserUserInfo)
  7246. {
  7247. //
  7248. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7249. //
  7250. funcArgs.ArgTypes[1] = Dword;
  7251. funcArgs.Args[1] = TAPI_NO_DATA;
  7252. funcArgs.ArgTypes[2] = Dword;
  7253. }
  7254. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSendUserUserInfo") );
  7255. }
  7256. LONG
  7257. WINAPI
  7258. lineSetAgentActivity(
  7259. HLINE hLine,
  7260. DWORD dwAddressID,
  7261. DWORD dwActivityID
  7262. )
  7263. {
  7264. FUNC_ARGS funcArgs =
  7265. {
  7266. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentActivity),
  7267. {
  7268. (ULONG_PTR) hLine,
  7269. dwAddressID,
  7270. dwActivityID
  7271. },
  7272. {
  7273. Dword,
  7274. Dword,
  7275. Dword
  7276. }
  7277. };
  7278. return (DOFUNC (&funcArgs, "lineSetAgentActivity"));
  7279. }
  7280. LONG
  7281. WINAPI
  7282. lineSetAgentGroup(
  7283. HLINE hLine,
  7284. DWORD dwAddressID,
  7285. LPLINEAGENTGROUPLIST lpAgentGroupList
  7286. )
  7287. {
  7288. static LINEAGENTGROUPLIST EmptyGroupList =
  7289. {
  7290. sizeof (LINEAGENTGROUPLIST), // dwTotalSize
  7291. sizeof (LINEAGENTGROUPLIST), // dwNeededSize
  7292. sizeof (LINEAGENTGROUPLIST), // dwUsedSize
  7293. 0, // dwNumEntries
  7294. 0, // dwListSize
  7295. 0 // dwListOffset
  7296. };
  7297. FUNC_ARGS funcArgs =
  7298. {
  7299. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentGroup),
  7300. {
  7301. (ULONG_PTR) hLine,
  7302. (ULONG_PTR) dwAddressID,
  7303. (ULONG_PTR) lpAgentGroupList
  7304. },
  7305. {
  7306. Dword,
  7307. Dword,
  7308. lpSet_Struct
  7309. }
  7310. };
  7311. if (!lpAgentGroupList)
  7312. {
  7313. funcArgs.Args[2] = (ULONG_PTR) &EmptyGroupList;
  7314. }
  7315. return (DOFUNC (&funcArgs, "lineSetAgentGroup"));
  7316. }
  7317. LONG
  7318. WINAPI
  7319. lineSetAgentState(
  7320. HLINE hLine,
  7321. DWORD dwAddressID,
  7322. DWORD dwAgentState,
  7323. DWORD dwNextAgentState
  7324. )
  7325. {
  7326. FUNC_ARGS funcArgs =
  7327. {
  7328. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentState),
  7329. {
  7330. (ULONG_PTR) hLine,
  7331. dwAddressID,
  7332. dwAgentState,
  7333. dwNextAgentState
  7334. },
  7335. {
  7336. Dword,
  7337. Dword,
  7338. Dword,
  7339. Dword
  7340. }
  7341. };
  7342. return (DOFUNC (&funcArgs, "lineSetAgentState"));
  7343. }
  7344. LONG
  7345. WINAPI
  7346. lineSetAgentStateEx(
  7347. HLINE hLine,
  7348. HAGENT hAgent,
  7349. DWORD dwAgentState,
  7350. DWORD dwNextAgentState
  7351. )
  7352. {
  7353. FUNC_ARGS funcArgs =
  7354. {
  7355. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentStateEx),
  7356. {
  7357. (ULONG_PTR) hLine,
  7358. (ULONG_PTR) hAgent,
  7359. dwAgentState,
  7360. dwNextAgentState
  7361. },
  7362. {
  7363. Dword,
  7364. Dword,
  7365. Dword,
  7366. Dword
  7367. }
  7368. };
  7369. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentStateEx"));
  7370. }
  7371. HRESULT
  7372. LineSetAppPriority(
  7373. LPCWSTR lpszAppName,
  7374. DWORD dwMediaMode,
  7375. DWORD dwRequestMode,
  7376. DWORD dwPriority
  7377. )
  7378. {
  7379. FUNC_ARGS funcArgs =
  7380. {
  7381. MAKELONG (LINE_FUNC | SYNC | 7, lSetAppPriority),
  7382. {
  7383. (ULONG_PTR) lpszAppName,
  7384. dwMediaMode,
  7385. (ULONG_PTR) TAPI_NO_DATA, // (ULONG_PTR) lpExtensionID,
  7386. 0, // (ULONG_PTR) sizeof(LINEEXTENSIONID),
  7387. dwRequestMode,
  7388. (ULONG_PTR) TAPI_NO_DATA, // (ULONG_PTR) lpszExtensionName,
  7389. dwPriority
  7390. },
  7391. {
  7392. lpszW,
  7393. Dword,
  7394. Dword, // lpSet_SizeToFollow,
  7395. Dword, // Size,
  7396. Dword,
  7397. Dword, // lpsz,
  7398. Dword
  7399. }
  7400. };
  7401. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAppPriority"));
  7402. }
  7403. HRESULT
  7404. LineSetAppSpecific(
  7405. HCALL hCall,
  7406. DWORD dwAppSpecific
  7407. )
  7408. {
  7409. FUNC_ARGS funcArgs =
  7410. {
  7411. MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
  7412. {
  7413. (ULONG_PTR) hCall,
  7414. dwAppSpecific
  7415. },
  7416. {
  7417. Dword,
  7418. Dword
  7419. }
  7420. };
  7421. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAppSpecific"));
  7422. }
  7423. HRESULT
  7424. LineSetCallData(
  7425. HCALL hCall,
  7426. LPVOID lpCallData,
  7427. DWORD dwSize
  7428. )
  7429. {
  7430. FUNC_ARGS funcArgs =
  7431. {
  7432. MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallData),
  7433. {
  7434. (ULONG_PTR) hCall,
  7435. (ULONG_PTR) lpCallData,
  7436. dwSize
  7437. },
  7438. {
  7439. Dword,
  7440. lpSet_SizeToFollow,
  7441. Size
  7442. }
  7443. };
  7444. if (dwSize == 0)
  7445. {
  7446. funcArgs.Args[1] = TAPI_NO_DATA;
  7447. funcArgs.ArgTypes[1] =
  7448. funcArgs.ArgTypes[2] = Dword;
  7449. }
  7450. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetCallData"));
  7451. }
  7452. HRESULT
  7453. WINAPI
  7454. LineSetCallHubTracking(
  7455. T3LINE * pt3Line,
  7456. LINECALLHUBTRACKINGINFO * plchti
  7457. )
  7458. {
  7459. FUNC_ARGS funcArgs =
  7460. {
  7461. MAKELONG (LINE_FUNC | SYNC | 2, lSetCallHubTracking),
  7462. {
  7463. (ULONG_PTR) (pt3Line->hLine),
  7464. (ULONG_PTR) plchti
  7465. },
  7466. {
  7467. Dword,
  7468. lpSet_Struct
  7469. }
  7470. };
  7471. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallHubTracking") );
  7472. }
  7473. HRESULT
  7474. LineSetCallParams(
  7475. HCALL hCall,
  7476. DWORD dwBearerMode,
  7477. DWORD dwMinRate,
  7478. DWORD dwMaxRate,
  7479. LPLINEDIALPARAMS const lpDialParams
  7480. )
  7481. {
  7482. FUNC_ARGS funcArgs =
  7483. {
  7484. MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallParams),
  7485. {
  7486. (ULONG_PTR) hCall,
  7487. dwBearerMode,
  7488. dwMinRate,
  7489. dwMaxRate,
  7490. (ULONG_PTR) lpDialParams,
  7491. sizeof(LINEDIALPARAMS)
  7492. },
  7493. {
  7494. Dword,
  7495. Dword,
  7496. Dword,
  7497. Dword,
  7498. lpSet_SizeToFollow,
  7499. Size
  7500. }
  7501. };
  7502. if (!lpDialParams)
  7503. {
  7504. //
  7505. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7506. //
  7507. funcArgs.ArgTypes[4] = Dword;
  7508. funcArgs.Args[4] = TAPI_NO_DATA;
  7509. funcArgs.ArgTypes[5] = Dword;
  7510. }
  7511. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallParams") );
  7512. }
  7513. LONG
  7514. WINAPI
  7515. lineSetCallPrivilege(
  7516. HCALL hCall,
  7517. DWORD dwCallPrivilege
  7518. )
  7519. {
  7520. FUNC_ARGS funcArgs =
  7521. {
  7522. MAKELONG (LINE_FUNC | SYNC | 2, lSetCallPrivilege),
  7523. {
  7524. (ULONG_PTR) hCall,
  7525. dwCallPrivilege
  7526. },
  7527. {
  7528. Dword,
  7529. Dword
  7530. }
  7531. };
  7532. return (DOFUNC (&funcArgs, "lineSetCallPrivilege"));
  7533. }
  7534. HRESULT
  7535. LineSetCallQualityOfService(
  7536. HCALL hCall,
  7537. QOS_SERVICE_LEVEL ServiceLevel,
  7538. DWORD dwMediaType
  7539. )
  7540. {
  7541. LINECALLQOSINFO * plqi;
  7542. DWORD dwSize;
  7543. HRESULT hr;
  7544. dwSize = sizeof(LINECALLQOSINFO);
  7545. plqi = (LINECALLQOSINFO *)ClientAlloc( dwSize );
  7546. if ( NULL == plqi )
  7547. {
  7548. return E_OUTOFMEMORY;
  7549. }
  7550. plqi->dwKey = LINEQOSSTRUCT_KEY;
  7551. plqi->dwTotalSize = dwSize;
  7552. if ( 0 != ServiceLevel )
  7553. {
  7554. plqi->dwQOSRequestType = LINEQOSREQUESTTYPE_SERVICELEVEL;
  7555. plqi->SetQOSServiceLevel.dwNumServiceLevelEntries = 1;
  7556. plqi->SetQOSServiceLevel.LineQOSServiceLevel[0].dwMediaMode = dwMediaType;
  7557. plqi->SetQOSServiceLevel.LineQOSServiceLevel[0].dwQOSServiceLevel = ServiceLevel;
  7558. }
  7559. FUNC_ARGS funcArgs =
  7560. {
  7561. MAKELONG (LINE_FUNC | ASYNC | 5, lSetCallQualityOfService),
  7562. {
  7563. (ULONG_PTR) hCall,
  7564. (ULONG_PTR) TAPI_NO_DATA,
  7565. (ULONG_PTR) 0,
  7566. (ULONG_PTR) plqi,
  7567. (ULONG_PTR) dwSize
  7568. },
  7569. {
  7570. Dword,
  7571. Dword,
  7572. Dword,
  7573. lpSet_SizeToFollow,
  7574. Size
  7575. }
  7576. };
  7577. hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallQualityOfService") );
  7578. ClientFree( plqi );
  7579. return hr;
  7580. }
  7581. HRESULT
  7582. LineSetCallTreatment(
  7583. HCALL hCall,
  7584. DWORD dwTreatment
  7585. )
  7586. {
  7587. FUNC_ARGS funcArgs =
  7588. {
  7589. MAKELONG (LINE_FUNC | ASYNC | 2, lSetCallTreatment),
  7590. {
  7591. (ULONG_PTR) hCall,
  7592. (ULONG_PTR) dwTreatment
  7593. },
  7594. {
  7595. Dword,
  7596. Dword
  7597. }
  7598. };
  7599. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetCallTreatment") );
  7600. }
  7601. LONG
  7602. WINAPI
  7603. lineSetDevConfigW(
  7604. DWORD dwDeviceID,
  7605. LPVOID const lpDeviceConfig,
  7606. DWORD dwSize,
  7607. LPCWSTR lpszDeviceClass
  7608. )
  7609. {
  7610. FUNC_ARGS funcArgs =
  7611. {
  7612. MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
  7613. {
  7614. dwDeviceID,
  7615. (ULONG_PTR) lpDeviceConfig,
  7616. dwSize,
  7617. (ULONG_PTR) lpszDeviceClass
  7618. },
  7619. {
  7620. Dword,
  7621. lpSet_SizeToFollow,
  7622. Size,
  7623. lpszW
  7624. }
  7625. };
  7626. return (DOFUNC (&funcArgs, "lineSetDevConfig"));
  7627. }
  7628. HRESULT
  7629. LineSetLineDevStatus(
  7630. T3LINE *pt3Line,
  7631. DWORD dwStatusToChange,
  7632. DWORD fStatus
  7633. )
  7634. {
  7635. FUNC_ARGS funcArgs =
  7636. {
  7637. MAKELONG (LINE_FUNC | ASYNC | 3, lSetLineDevStatus),
  7638. {
  7639. (ULONG_PTR) pt3Line->hLine,
  7640. dwStatusToChange,
  7641. fStatus
  7642. },
  7643. {
  7644. Dword,
  7645. Dword,
  7646. Dword
  7647. }
  7648. };
  7649. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetLineDevStatus") );
  7650. }
  7651. LONG
  7652. WINAPI
  7653. lineSetMediaControl(
  7654. HLINE hLine,
  7655. DWORD dwAddressID,
  7656. HCALL hCall,
  7657. DWORD dwSelect,
  7658. LPLINEMEDIACONTROLDIGIT const lpDigitList,
  7659. DWORD dwDigitNumEntries,
  7660. LPLINEMEDIACONTROLMEDIA const lpMediaList,
  7661. DWORD dwMediaNumEntries,
  7662. LPLINEMEDIACONTROLTONE const lpToneList,
  7663. DWORD dwToneNumEntries,
  7664. LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
  7665. DWORD dwCallStateNumEntries
  7666. )
  7667. {
  7668. FUNC_ARGS funcArgs =
  7669. {
  7670. MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
  7671. {
  7672. (ULONG_PTR) hLine,
  7673. dwAddressID,
  7674. (ULONG_PTR) hCall,
  7675. dwSelect,
  7676. TAPI_NO_DATA,
  7677. dwDigitNumEntries * sizeof(LINEMEDIACONTROLDIGIT),
  7678. TAPI_NO_DATA,
  7679. dwMediaNumEntries * sizeof(LINEMEDIACONTROLMEDIA),
  7680. TAPI_NO_DATA,
  7681. dwToneNumEntries * sizeof(LINEMEDIACONTROLTONE),
  7682. TAPI_NO_DATA,
  7683. dwCallStateNumEntries * sizeof(LINEMEDIACONTROLCALLSTATE)
  7684. },
  7685. {
  7686. Dword,
  7687. Dword,
  7688. Dword,
  7689. Dword,
  7690. Dword,
  7691. Dword,
  7692. Dword,
  7693. Dword,
  7694. Dword,
  7695. Dword,
  7696. Dword,
  7697. Dword
  7698. }
  7699. };
  7700. //
  7701. // If lpXxxList is non-NULL reset Arg & ArgType, and check
  7702. // to see that dwXxxNumEntries is not unacceptably large
  7703. //
  7704. if (lpDigitList)
  7705. {
  7706. if (dwDigitNumEntries >
  7707. (0x1000000 / sizeof (LINEMEDIACONTROLDIGIT)))
  7708. {
  7709. return LINEERR_INVALPOINTER;
  7710. }
  7711. funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
  7712. funcArgs.Args[4] = (ULONG_PTR) lpDigitList;
  7713. funcArgs.ArgTypes[5] = Size;
  7714. }
  7715. if (lpMediaList)
  7716. {
  7717. if (dwMediaNumEntries >
  7718. (0x1000000 / sizeof (LINEMEDIACONTROLMEDIA)))
  7719. {
  7720. return LINEERR_INVALPOINTER;
  7721. }
  7722. funcArgs.ArgTypes[6] = lpSet_SizeToFollow;
  7723. funcArgs.Args[6] = (ULONG_PTR) lpMediaList;
  7724. funcArgs.ArgTypes[7] = Size;
  7725. }
  7726. if (lpToneList)
  7727. {
  7728. if (dwToneNumEntries >
  7729. (0x1000000 / sizeof (LINEMEDIACONTROLTONE)))
  7730. {
  7731. return LINEERR_INVALPOINTER;
  7732. }
  7733. funcArgs.ArgTypes[8] = lpSet_SizeToFollow;
  7734. funcArgs.Args[8] = (ULONG_PTR) lpToneList;
  7735. funcArgs.ArgTypes[9] = Size;
  7736. }
  7737. if (lpCallStateList)
  7738. {
  7739. if (dwCallStateNumEntries >
  7740. (0x1000000 / sizeof (LINEMEDIACONTROLCALLSTATE)))
  7741. {
  7742. return LINEERR_INVALPOINTER;
  7743. }
  7744. funcArgs.ArgTypes[10] = lpSet_SizeToFollow;
  7745. funcArgs.Args[10] = (ULONG_PTR) lpCallStateList;
  7746. funcArgs.ArgTypes[11] = Size;
  7747. }
  7748. return (DOFUNC (&funcArgs, "lineSetMediaControl"));
  7749. }
  7750. HRESULT
  7751. LineSetMediaMode(
  7752. HCALL hCall,
  7753. DWORD dwMediaModes
  7754. )
  7755. {
  7756. FUNC_ARGS funcArgs =
  7757. {
  7758. MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
  7759. {
  7760. (ULONG_PTR) hCall,
  7761. dwMediaModes
  7762. },
  7763. {
  7764. Dword,
  7765. Dword
  7766. }
  7767. };
  7768. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetMediaMode") );
  7769. }
  7770. LONG
  7771. WINAPI
  7772. lineSetNumRings(
  7773. HLINE hLine,
  7774. DWORD dwAddressID,
  7775. DWORD dwNumRings
  7776. )
  7777. {
  7778. FUNC_ARGS funcArgs =
  7779. {
  7780. MAKELONG (LINE_FUNC | SYNC | 3, lSetNumRings),
  7781. {
  7782. (ULONG_PTR) hLine,
  7783. dwAddressID,
  7784. dwNumRings
  7785. },
  7786. {
  7787. Dword,
  7788. Dword,
  7789. Dword
  7790. }
  7791. };
  7792. return (DOFUNC (&funcArgs, "lineSetNumRings"));
  7793. }
  7794. HRESULT
  7795. LineSetStatusMessages(
  7796. T3LINE * pt3Line,
  7797. DWORD dwLineStates,
  7798. DWORD dwAddressStates
  7799. )
  7800. {
  7801. FUNC_ARGS funcArgs =
  7802. {
  7803. MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
  7804. {
  7805. (ULONG_PTR) pt3Line->hLine,
  7806. dwLineStates,
  7807. dwAddressStates
  7808. },
  7809. {
  7810. Dword,
  7811. Dword,
  7812. Dword
  7813. }
  7814. };
  7815. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetStatusMessages") );
  7816. }
  7817. LONG
  7818. WINAPI
  7819. lineSetTerminal(
  7820. HLINE hLine,
  7821. DWORD dwAddressID,
  7822. HCALL hCall,
  7823. DWORD dwSelect,
  7824. DWORD dwTerminalModes,
  7825. DWORD dwTerminalID,
  7826. DWORD bEnable
  7827. )
  7828. {
  7829. FUNC_ARGS funcArgs =
  7830. {
  7831. MAKELONG (LINE_FUNC | ASYNC | 7, lSetTerminal),
  7832. {
  7833. (ULONG_PTR) hLine,
  7834. dwAddressID,
  7835. (ULONG_PTR) hCall,
  7836. dwSelect,
  7837. dwTerminalModes,
  7838. dwTerminalID,
  7839. bEnable
  7840. },
  7841. {
  7842. Dword,
  7843. Dword,
  7844. Dword,
  7845. Dword,
  7846. Dword,
  7847. Dword,
  7848. Dword
  7849. }
  7850. };
  7851. return (DOFUNC (&funcArgs, "lineSetTerminal"));
  7852. }
  7853. void
  7854. PASCAL
  7855. lineSetupConferencePostProcess(
  7856. PASYNCEVENTMSG pMsg
  7857. )
  7858. {
  7859. LOG((TL_TRACE, "lineSetupConfPostProcess: enter"));
  7860. LOG((TL_INFO,
  7861. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  7862. pMsg->Param1,
  7863. pMsg->Param2,
  7864. pMsg->Param3,
  7865. pMsg->Param4
  7866. ));
  7867. if (pMsg->Param2 == 0)
  7868. {
  7869. HCALL hConfCall = (HCALL) pMsg->Param3,
  7870. hConsultCall = (HCALL) (*(&pMsg->Param4 + 1));
  7871. LPHCALL lphConfCall =
  7872. (LPHCALL) GetHandleTableEntry(pMsg->Param4);
  7873. LPHCALL lphConsultCall =
  7874. (LPHCALL) GetHandleTableEntry(*(&pMsg->Param4 + 2));
  7875. LOG((TL_INFO,
  7876. "lineSetupConfPostProcess: hConfCall [%lx] hConsultCall [%lx] lphConfCall [%p] lphConsultCall [%p]",
  7877. hConfCall, hConsultCall, lphConfCall, lphConsultCall));
  7878. __try
  7879. {
  7880. {
  7881. *lphConfCall = NULL;
  7882. *lphConsultCall = NULL;
  7883. *lphConfCall = hConfCall;
  7884. *lphConsultCall = hConsultCall;
  7885. }
  7886. }
  7887. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  7888. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  7889. {
  7890. pMsg->Param2 = LINEERR_INVALPOINTER;
  7891. LOG((TL_WARN,
  7892. "lineSetupConfPostProcess: failed to set memory at %p or at %p",
  7893. lphConfCall, lphConsultCall));
  7894. //
  7895. // tapisrv has allocated call handles for us. deallocate them.
  7896. //
  7897. LineDeallocateCall(hConfCall);
  7898. LineDeallocateCall(hConsultCall);
  7899. }
  7900. }
  7901. }
  7902. HRESULT
  7903. LineSetupConference(
  7904. HCALL hCall,
  7905. T3LINE * pt3Line,
  7906. HCALL * phConfCall,
  7907. HCALL * phConsultCall,
  7908. DWORD dwNumParties,
  7909. LPLINECALLPARAMS const lpCallParams
  7910. )
  7911. {
  7912. if ( phConfCall == phConsultCall )
  7913. {
  7914. return E_POINTER;
  7915. }
  7916. DWORD hpConfCallHandle = CreateHandleTableEntry((ULONG_PTR) phConfCall);
  7917. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR) phConsultCall);
  7918. FUNC_ARGS funcArgs =
  7919. {
  7920. MAKELONG (LINE_FUNC | ASYNC | 8, lSetupConference),
  7921. {
  7922. GetFunctionIndex(lineSetupConferencePostProcess),
  7923. (ULONG_PTR) hCall,
  7924. (ULONG_PTR) pt3Line->hLine,
  7925. hpConfCallHandle,
  7926. hpConsultCallHandle,
  7927. (ULONG_PTR) dwNumParties,
  7928. (ULONG_PTR) lpCallParams,
  7929. (ULONG_PTR) 0xffffffff // dwAsciiCallParamsCodePage
  7930. },
  7931. {
  7932. Dword,
  7933. Dword,
  7934. Dword,
  7935. Dword,
  7936. Dword,
  7937. Dword,
  7938. lpSet_Struct,
  7939. Dword
  7940. }
  7941. };
  7942. if (!lpCallParams)
  7943. {
  7944. //
  7945. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7946. //
  7947. funcArgs.ArgTypes[6] = Dword;
  7948. funcArgs.Args[6] = TAPI_NO_DATA;
  7949. }
  7950. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LineSetupConference") );
  7951. if (FAILED(hr))
  7952. {
  7953. DeleteHandleTableEntry(hpConfCallHandle);
  7954. DeleteHandleTableEntry(hpConsultCallHandle);
  7955. }
  7956. return hr;
  7957. }
  7958. HRESULT
  7959. LineSetupTransfer(
  7960. HCALL hCall,
  7961. HCALL *phConsultCall,
  7962. LPLINECALLPARAMS const lpCallParams
  7963. )
  7964. {
  7965. DWORD hpConsultCallHandle = CreateHandleTableEntry((ULONG_PTR)phConsultCall);
  7966. FUNC_ARGS funcArgs =
  7967. {
  7968. MAKELONG (LINE_FUNC | ASYNC | 5, lSetupTransfer),
  7969. {
  7970. GetFunctionIndex(lineMakeCallPostProcess),
  7971. (ULONG_PTR) hCall,
  7972. hpConsultCallHandle,
  7973. (ULONG_PTR) lpCallParams,
  7974. 0xffffffff // dwAsciiCallParamsCodePage
  7975. },
  7976. {
  7977. Dword,
  7978. Dword,
  7979. Dword,
  7980. lpSet_Struct,
  7981. Dword
  7982. }
  7983. };
  7984. if (!lpCallParams)
  7985. {
  7986. //
  7987. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  7988. //
  7989. funcArgs.ArgTypes[3] = Dword;
  7990. funcArgs.Args[3] = TAPI_NO_DATA;
  7991. }
  7992. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSetupTransferW") );
  7993. if (FAILED(hr))
  7994. {
  7995. DeleteHandleTableEntry(hpConsultCallHandle);
  7996. hpConsultCallHandle = 0;
  7997. }
  7998. return hr;
  7999. }
  8000. HRESULT
  8001. LineSwapHold(
  8002. HCALL hActiveCall,
  8003. HCALL hHeldCall
  8004. )
  8005. {
  8006. FUNC_ARGS funcArgs =
  8007. {
  8008. MAKELONG (LINE_FUNC | ASYNC | 2, lSwapHold),
  8009. {
  8010. (ULONG_PTR) hActiveCall,
  8011. (ULONG_PTR) hHeldCall
  8012. },
  8013. {
  8014. Dword,
  8015. Dword
  8016. }
  8017. };
  8018. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineSwapHold") );
  8019. }
  8020. LONG
  8021. WINAPI
  8022. lineUncompleteCall(
  8023. HLINE hLine,
  8024. DWORD dwCompletionID
  8025. )
  8026. {
  8027. FUNC_ARGS funcArgs =
  8028. {
  8029. MAKELONG (LINE_FUNC | ASYNC | 2, lUncompleteCall),
  8030. {
  8031. (ULONG_PTR) hLine,
  8032. dwCompletionID
  8033. },
  8034. {
  8035. Dword,
  8036. Dword
  8037. }
  8038. };
  8039. return (DOFUNC (&funcArgs, "lineUncompleteCall"));
  8040. }
  8041. HRESULT
  8042. LineUnhold(
  8043. HCALL hCall
  8044. )
  8045. {
  8046. FUNC_ARGS funcArgs =
  8047. {
  8048. MAKELONG (LINE_FUNC | ASYNC | 1, lUnhold),
  8049. {
  8050. (ULONG_PTR) hCall
  8051. },
  8052. {
  8053. Dword
  8054. }
  8055. };
  8056. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineUnhold") );
  8057. }
  8058. HRESULT
  8059. LineUnpark(
  8060. HLINE hLine,
  8061. DWORD dwAddressID,
  8062. HCALL *phCall,
  8063. LPCWSTR lpszDestAddress
  8064. )
  8065. {
  8066. DWORD hpCallHandle = CreateHandleTableEntry((ULONG_PTR)phCall);
  8067. FUNC_ARGS funcArgs =
  8068. {
  8069. MAKELONG (LINE_FUNC | ASYNC | 5, lUnpark),
  8070. {
  8071. GetFunctionIndex(lineMakeCallPostProcess),
  8072. (ULONG_PTR) hLine,
  8073. dwAddressID,
  8074. hpCallHandle,
  8075. (ULONG_PTR) lpszDestAddress
  8076. },
  8077. {
  8078. Dword,
  8079. Dword,
  8080. Dword,
  8081. Dword,
  8082. lpszW
  8083. }
  8084. };
  8085. HRESULT hr = mapTAPIErrorCode( DOFUNC (&funcArgs, "LineUnpark") );
  8086. if (FAILED(hr))
  8087. {
  8088. DeleteHandleTableEntry(hpCallHandle);
  8089. }
  8090. return hr;
  8091. }
  8092. //
  8093. // ------------------------------- phoneXxx -----------------------------------
  8094. //
  8095. ///////////////////////////////////////////////////////////////////////////////
  8096. //
  8097. // PhoneClose
  8098. //
  8099. //
  8100. // Closes the phone specified by hPhone, the mode of hash table clean up is
  8101. // described by bCleanHashTableOnFailure
  8102. //
  8103. // Arguments:
  8104. //
  8105. // HPHONE hPhone -- handle of the phone to close
  8106. //
  8107. // BOOL bCleanHashTableOnFailure -- boolean that specifies how phone
  8108. // hash table should be cleaned:
  8109. //
  8110. // FALSE -- remove hash table entry only if the call succeeds. The caller
  8111. // function will then have the opportunity to perform transaction-like
  8112. // error handling -- it could recover the state from before the function
  8113. // was called, so it could return an error which would mean that the state
  8114. // remained unchanged
  8115. //
  8116. // TRUE -- clean table even if tapisrv call fails. The caller will not be
  8117. // able to recover the original state in case of failure. this is ok for
  8118. // the functions that do not provide full error handling for PhoneClose
  8119. //
  8120. HRESULT
  8121. PhoneClose(
  8122. HPHONE hPhone,
  8123. BOOL bCleanHashTableOnFailure // = TRUE
  8124. )
  8125. {
  8126. LOG((TL_INFO, "PhoneClose - enter. hPhone[%p] CleanOnError[%d]",
  8127. hPhone, bCleanHashTableOnFailure));
  8128. LONG lResult;
  8129. FUNC_ARGS funcArgs =
  8130. {
  8131. MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
  8132. {
  8133. (ULONG_PTR) hPhone
  8134. },
  8135. {
  8136. Dword
  8137. }
  8138. };
  8139. gpPhoneHashTable->Lock();
  8140. lResult = (DOFUNC (&funcArgs, "phoneClose"));
  8141. //
  8142. // clean hash table entry if needed
  8143. //
  8144. if ( (0 == lResult) || bCleanHashTableOnFailure )
  8145. {
  8146. LOG((TL_INFO, "PhoneClose - removing phone's hash table entry"));
  8147. gpPhoneHashTable->Remove( (ULONG_PTR)(hPhone) );
  8148. }
  8149. gpPhoneHashTable->Unlock();
  8150. //
  8151. // get hr error code
  8152. //
  8153. HRESULT hr = mapTAPIErrorCode( lResult );
  8154. LOG((TL_INFO, "PhoneClose - exit. hr = %lx", hr));
  8155. return hr;
  8156. }
  8157. LONG
  8158. WINAPI
  8159. phoneConfigDialogW(
  8160. DWORD dwDeviceID,
  8161. HWND hwndOwner,
  8162. LPCWSTR lpszDeviceClass
  8163. )
  8164. {
  8165. LONG lResult;
  8166. HANDLE hDll;
  8167. TUISPIPROC pfnTUISPI_phoneConfigDialog;
  8168. if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, (UINT) -1))
  8169. {
  8170. return PHONEERR_INVALPOINTER;
  8171. }
  8172. if ((lResult = LoadUIDll(
  8173. hwndOwner,
  8174. dwDeviceID,
  8175. TUISPIDLL_OBJECT_PHONEID,
  8176. &hDll,
  8177. gszTUISPI_phoneConfigDialog,
  8178. &pfnTUISPI_phoneConfigDialog
  8179. )) == 0)
  8180. {
  8181. LOG((TL_INFO, "Calling TUISPI_phoneConfigDialog..."));
  8182. lResult = ((TUIPHONECONFIGPROC)(*pfnTUISPI_phoneConfigDialog))(
  8183. TUISPIDLLCallback,
  8184. dwDeviceID,
  8185. (HWND)hwndOwner,
  8186. (char *)lpszDeviceClass
  8187. );
  8188. #if DBG
  8189. {
  8190. char szResult[32];
  8191. LOG((TL_INFO,
  8192. "TUISPI_phoneConfigDialog: result = %s",
  8193. MapResultCodeToText (lResult, szResult)
  8194. ));
  8195. }
  8196. #endif
  8197. FreeLibrary ((HINSTANCE)hDll);
  8198. }
  8199. return lResult;
  8200. }
  8201. void
  8202. PASCAL
  8203. phoneDevSpecificPostProcess(
  8204. PASYNCEVENTMSG pMsg
  8205. )
  8206. {
  8207. LOG((TL_TRACE, "phoneDevSpecificPostProcess: enter"));
  8208. LOG((TL_INFO,
  8209. "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
  8210. pMsg->Param1,
  8211. pMsg->Param2,
  8212. pMsg->Param3,
  8213. pMsg->Param4
  8214. ));
  8215. if (pMsg->Param2 == 0)
  8216. {
  8217. DWORD dwSize = pMsg->Param4;
  8218. LPBYTE pParams =
  8219. (LPBYTE) GetHandleTableEntry(pMsg->Param3);
  8220. __try
  8221. {
  8222. {
  8223. CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
  8224. }
  8225. }
  8226. __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  8227. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  8228. {
  8229. pMsg->Param2 = PHONEERR_INVALPOINTER;
  8230. LOG((TL_WARN,
  8231. "phoneDevSpecificPostProcess: failed to copy %ld(10) bytes, %p -> %p."
  8232. "PHONEERR_INVALPOINTER",
  8233. dwSize, (LPBYTE) (pMsg + 1), pParams));
  8234. }
  8235. }
  8236. }
  8237. HRESULT
  8238. WINAPI
  8239. phoneDevSpecific(
  8240. HPHONE hPhone,
  8241. LPVOID lpParams,
  8242. DWORD dwSize
  8243. )
  8244. {
  8245. DWORD hpParams = CreateHandleTableEntry((ULONG_PTR)lpParams);
  8246. FUNC_ARGS funcArgs =
  8247. {
  8248. MAKELONG (PHONE_FUNC | ASYNC | 5, pDevSpecific),
  8249. {
  8250. GetFunctionIndex(phoneDevSpecificPostProcess),
  8251. (ULONG_PTR) hPhone,
  8252. hpParams, // passed as Dword for post processing
  8253. (ULONG_PTR) lpParams, // passed as LpSet_Xxx for IsValidPtr chk
  8254. dwSize
  8255. },
  8256. {
  8257. Dword,
  8258. Dword,
  8259. Dword,
  8260. lpSet_SizeToFollow,
  8261. Size
  8262. }
  8263. };
  8264. LONG lResult = DOFUNC (&funcArgs, "phoneDevSpecific");
  8265. //
  8266. // remove the handle table entry if failed. otherwise the LINE_REPLY will
  8267. // do this.
  8268. //
  8269. HRESULT hr = E_FAIL;
  8270. if (lResult <= 0)
  8271. {
  8272. DeleteHandleTableEntry(hpParams);
  8273. hpParams = 0;
  8274. hr = mapTAPIErrorCode(lResult);
  8275. }
  8276. else
  8277. {
  8278. //
  8279. // block to see if the operation succeeds
  8280. //
  8281. hr = WaitForPhoneReply(lResult);
  8282. }
  8283. return hr;
  8284. }
  8285. HRESULT
  8286. PhoneSetStatusMessages(
  8287. T3PHONE * pt3Phone,
  8288. DWORD dwPhoneStates,
  8289. DWORD dwButtonModes,
  8290. DWORD dwButtonStates
  8291. )
  8292. {
  8293. FUNC_ARGS funcArgs =
  8294. {
  8295. MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
  8296. {
  8297. (ULONG_PTR) pt3Phone->hPhone,
  8298. dwPhoneStates,
  8299. dwButtonModes,
  8300. dwButtonStates
  8301. },
  8302. {
  8303. Dword,
  8304. Dword,
  8305. Dword,
  8306. Dword
  8307. }
  8308. };
  8309. return mapTAPIErrorCode( DOFUNC (&funcArgs, "phoneSetStatusMessages") );
  8310. }
  8311. HRESULT
  8312. PhoneGetButtonInfo(
  8313. HPHONE hPhone,
  8314. DWORD dwButtonLampID,
  8315. LPPHONEBUTTONINFO * ppButtonInfo
  8316. )
  8317. {
  8318. LONG lResult;
  8319. *ppButtonInfo = (LPPHONEBUTTONINFO) ClientAlloc( sizeof(PHONEBUTTONINFO) + 500 );
  8320. if (NULL == *ppButtonInfo)
  8321. {
  8322. return E_OUTOFMEMORY;
  8323. }
  8324. (*ppButtonInfo)->dwTotalSize = sizeof(PHONEBUTTONINFO) + 500;
  8325. FUNC_ARGS funcArgs =
  8326. {
  8327. MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
  8328. {
  8329. (ULONG_PTR) hPhone,
  8330. dwButtonLampID,
  8331. (ULONG_PTR) *ppButtonInfo
  8332. },
  8333. {
  8334. Dword,
  8335. Dword,
  8336. lpGet_Struct
  8337. }
  8338. };
  8339. while (TRUE)
  8340. {
  8341. lResult = DOFUNC (&funcArgs, "phoneGetButtonInfo");
  8342. if ((0 == lResult) && ((*ppButtonInfo)->dwNeededSize > (*ppButtonInfo)->dwTotalSize))
  8343. {
  8344. DWORD dwSize = (*ppButtonInfo)->dwNeededSize;
  8345. ClientFree( *ppButtonInfo );
  8346. *ppButtonInfo = (LPPHONEBUTTONINFO) ClientAlloc( dwSize );
  8347. if (NULL == *ppButtonInfo)
  8348. {
  8349. return E_OUTOFMEMORY;
  8350. }
  8351. (*ppButtonInfo)->dwTotalSize = dwSize;
  8352. funcArgs.Args[2] = (ULONG_PTR)*ppButtonInfo;
  8353. }
  8354. else
  8355. {
  8356. break;
  8357. }
  8358. }
  8359. return mapTAPIErrorCode(lResult);
  8360. }
  8361. LONG
  8362. WINAPI
  8363. phoneGetData(
  8364. HPHONE hPhone,
  8365. DWORD dwDataID,
  8366. LPVOID lpData,
  8367. DWORD dwSize
  8368. )
  8369. {
  8370. FUNC_ARGS funcArgs =
  8371. {
  8372. MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
  8373. {
  8374. (ULONG_PTR) hPhone,
  8375. dwDataID,
  8376. (ULONG_PTR) lpData,
  8377. dwSize
  8378. },
  8379. {
  8380. Dword,
  8381. Dword,
  8382. lpGet_SizeToFollow,
  8383. Size
  8384. }
  8385. };
  8386. return (DOFUNC (&funcArgs, "phoneGetData"));
  8387. }
  8388. HRESULT
  8389. PhoneGetDevCapsWithAlloc(
  8390. HPHONEAPP hPhoneApp,
  8391. DWORD dwDeviceID,
  8392. DWORD dwAPIVersion,
  8393. LPPHONECAPS * ppPhoneCaps
  8394. )
  8395. {
  8396. LONG lResult;
  8397. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( sizeof(PHONECAPS) + 500 );
  8398. if (NULL == *ppPhoneCaps)
  8399. {
  8400. return E_OUTOFMEMORY;
  8401. }
  8402. (*ppPhoneCaps)->dwTotalSize = sizeof(PHONECAPS) + 500;
  8403. FUNC_ARGS funcArgs =
  8404. {
  8405. MAKELONG (PHONE_FUNC | SYNC | 5, pGetDevCaps),
  8406. {
  8407. (ULONG_PTR) hPhoneApp,
  8408. dwDeviceID,
  8409. dwAPIVersion,
  8410. 0,
  8411. (ULONG_PTR) *ppPhoneCaps
  8412. },
  8413. {
  8414. hXxxApp,
  8415. Dword,
  8416. Dword,
  8417. Dword,
  8418. lpGet_Struct
  8419. }
  8420. };
  8421. while (TRUE)
  8422. {
  8423. lResult = DOFUNC (&funcArgs, "phoneGetDevCaps");
  8424. if ((0 == lResult) && ((*ppPhoneCaps)->dwNeededSize > (*ppPhoneCaps)->dwTotalSize))
  8425. {
  8426. DWORD dwSize = (*ppPhoneCaps)->dwNeededSize;
  8427. ClientFree( *ppPhoneCaps );
  8428. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( dwSize );
  8429. if (NULL == *ppPhoneCaps)
  8430. {
  8431. return E_OUTOFMEMORY;
  8432. }
  8433. (*ppPhoneCaps)->dwTotalSize = dwSize;
  8434. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneCaps;
  8435. }
  8436. else
  8437. {
  8438. break;
  8439. }
  8440. }
  8441. return mapTAPIErrorCode(lResult);
  8442. }
  8443. HRESULT
  8444. PhoneGetDevCaps(
  8445. HPHONEAPP hPhoneApp,
  8446. DWORD dwDeviceID,
  8447. DWORD dwAPIVersion,
  8448. LPPHONECAPS * ppPhoneCaps
  8449. )
  8450. {
  8451. LONG lResult;
  8452. FUNC_ARGS funcArgs =
  8453. {
  8454. MAKELONG (PHONE_FUNC | SYNC | 5, pGetDevCaps),
  8455. {
  8456. (ULONG_PTR) hPhoneApp,
  8457. dwDeviceID,
  8458. dwAPIVersion,
  8459. 0,
  8460. (ULONG_PTR) *ppPhoneCaps
  8461. },
  8462. {
  8463. hXxxApp,
  8464. Dword,
  8465. Dword,
  8466. Dword,
  8467. lpGet_Struct
  8468. }
  8469. };
  8470. while (TRUE)
  8471. {
  8472. lResult = DOFUNC (&funcArgs, "phoneGetDevCaps");
  8473. if ((0 == lResult) && ((*ppPhoneCaps)->dwNeededSize > (*ppPhoneCaps)->dwTotalSize))
  8474. {
  8475. DWORD dwSize = (*ppPhoneCaps)->dwNeededSize;
  8476. ClientFree( *ppPhoneCaps );
  8477. *ppPhoneCaps = (LPPHONECAPS) ClientAlloc( dwSize );
  8478. if (NULL == *ppPhoneCaps)
  8479. {
  8480. return E_OUTOFMEMORY;
  8481. }
  8482. (*ppPhoneCaps)->dwTotalSize = dwSize;
  8483. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneCaps;
  8484. }
  8485. else
  8486. {
  8487. break;
  8488. }
  8489. }
  8490. return mapTAPIErrorCode(lResult);
  8491. }
  8492. HRESULT
  8493. PhoneGetDisplay(
  8494. HPHONE hPhone,
  8495. LPVARSTRING * ppDisplay
  8496. )
  8497. {
  8498. LONG lResult;
  8499. *ppDisplay = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  8500. if (NULL == *ppDisplay)
  8501. {
  8502. return E_OUTOFMEMORY;
  8503. }
  8504. (*ppDisplay)->dwTotalSize = sizeof (VARSTRING) + 500;
  8505. FUNC_ARGS funcArgs =
  8506. {
  8507. MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
  8508. {
  8509. (ULONG_PTR) hPhone,
  8510. (ULONG_PTR) *ppDisplay
  8511. },
  8512. {
  8513. Dword,
  8514. lpGet_Struct
  8515. }
  8516. };
  8517. LOG((TL_TRACE, "PhoneGetDisplay - enter"));
  8518. LOG((TL_INFO, " hPhone ---------->%lx", hPhone));
  8519. LOG((TL_INFO, " ppDisplay ------->%p", ppDisplay));
  8520. while ( TRUE )
  8521. {
  8522. lResult = DOFUNC (&funcArgs, "phoneGetDisplay");
  8523. if ((lResult == 0) && ((*ppDisplay)->dwNeededSize > (*ppDisplay)->dwTotalSize))
  8524. {
  8525. DWORD dwSize = (*ppDisplay)->dwNeededSize;
  8526. ClientFree(*ppDisplay);
  8527. *ppDisplay = (LPVARSTRING)ClientAlloc(dwSize);
  8528. if (NULL == *ppDisplay)
  8529. {
  8530. LOG((TL_ERROR, "PhoneGetDisplay exit - return E_OUTOFMEMORY"));
  8531. return E_OUTOFMEMORY;
  8532. }
  8533. (*ppDisplay)->dwTotalSize = dwSize;
  8534. funcArgs.Args[4] = (ULONG_PTR)*ppDisplay;
  8535. }
  8536. else
  8537. {
  8538. break;
  8539. }
  8540. }
  8541. LOG((TL_TRACE, "PhoneGetDisplay exit"));
  8542. return mapTAPIErrorCode( lResult );
  8543. }
  8544. HRESULT
  8545. PhoneGetGain(
  8546. HPHONE hPhone,
  8547. DWORD dwHookSwitchDev,
  8548. LPDWORD lpdwGain
  8549. )
  8550. {
  8551. FUNC_ARGS funcArgs =
  8552. {
  8553. MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
  8554. {
  8555. (ULONG_PTR) hPhone,
  8556. dwHookSwitchDev,
  8557. (ULONG_PTR) lpdwGain
  8558. },
  8559. {
  8560. Dword,
  8561. Dword,
  8562. lpDword
  8563. }
  8564. };
  8565. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetGain"));
  8566. }
  8567. HRESULT
  8568. PhoneGetHookSwitch(
  8569. HPHONE hPhone,
  8570. LPDWORD lpdwHookSwitchDevs
  8571. )
  8572. {
  8573. FUNC_ARGS funcArgs =
  8574. {
  8575. MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
  8576. {
  8577. (ULONG_PTR) hPhone,
  8578. (ULONG_PTR) lpdwHookSwitchDevs
  8579. },
  8580. {
  8581. Dword,
  8582. lpDword
  8583. }
  8584. };
  8585. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetHookSwitch"));
  8586. }
  8587. LONG
  8588. WINAPI
  8589. phoneGetIconW(
  8590. DWORD dwDeviceID,
  8591. LPCWSTR lpszDeviceClass,
  8592. LPHICON lphIcon
  8593. )
  8594. {
  8595. HICON hIcon;
  8596. FUNC_ARGS funcArgs =
  8597. {
  8598. MAKELONG (PHONE_FUNC | SYNC | 3, pGetIcon),
  8599. {
  8600. dwDeviceID,
  8601. (ULONG_PTR) lpszDeviceClass,
  8602. (ULONG_PTR) &hIcon
  8603. },
  8604. {
  8605. Dword,
  8606. lpszW,
  8607. lpDword
  8608. }
  8609. };
  8610. LONG lResult;
  8611. if (IsBadDwordPtr ((LPDWORD) lphIcon))
  8612. {
  8613. return PHONEERR_INVALPOINTER;
  8614. }
  8615. if (lpszDeviceClass == (LPCWSTR) NULL)
  8616. {
  8617. //
  8618. // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
  8619. //
  8620. funcArgs.ArgTypes[1] = Dword;
  8621. funcArgs.Args[1] = TAPI_NO_DATA;
  8622. }
  8623. if ((lResult = DOFUNC (&funcArgs, "phoneGetIcon")) == 0)
  8624. {
  8625. *lphIcon = hIcon;
  8626. }
  8627. return lResult;
  8628. }
  8629. HRESULT
  8630. PhoneGetID(
  8631. HPHONE hPhone,
  8632. LPVARSTRING * ppDeviceID,
  8633. LPCWSTR lpszDeviceClass
  8634. )
  8635. {
  8636. LONG lResult;
  8637. DWORD dwNumDevices;
  8638. DWORD dwDeviceId1, dwDeviceId2;
  8639. BOOL bWaveDevice = FALSE;
  8640. *ppDeviceID = (LPVARSTRING) ClientAlloc( sizeof (VARSTRING) + 500 );
  8641. if (NULL == *ppDeviceID)
  8642. {
  8643. return E_OUTOFMEMORY;
  8644. }
  8645. (*ppDeviceID)->dwTotalSize = sizeof (VARSTRING) + 500;
  8646. FUNC_ARGS funcArgs =
  8647. {
  8648. MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
  8649. {
  8650. (ULONG_PTR) hPhone,
  8651. (ULONG_PTR) *ppDeviceID,
  8652. (ULONG_PTR) lpszDeviceClass
  8653. },
  8654. {
  8655. Dword,
  8656. lpGet_Struct,
  8657. lpszW
  8658. }
  8659. };
  8660. LOG((TL_TRACE, "PhoneGetID - enter"));
  8661. LOG((TL_INFO, " hPhone ---------->%lx", hPhone));
  8662. LOG((TL_INFO, " ppDeviceID ------>%p", ppDeviceID));
  8663. LOG((TL_INFO, " lpszDeviceClass ->%p", lpszDeviceClass));
  8664. //
  8665. // If the request is for a wave device, call PGetIDEx.
  8666. // This will return a device string ID which is guaranteed to be unique across
  8667. // all processes.
  8668. // Then we will convert the string ID to the correct device ID in the client process context.
  8669. //
  8670. if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
  8671. !_wcsicmp(lpszDeviceClass, L"wave/out") ||
  8672. !_wcsicmp(lpszDeviceClass, L"midi/in") ||
  8673. !_wcsicmp(lpszDeviceClass, L"midi/out") ||
  8674. !_wcsicmp(lpszDeviceClass, L"wave/in/out")
  8675. )
  8676. {
  8677. bWaveDevice = TRUE;
  8678. dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
  8679. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 3, pGetIDEx);
  8680. }
  8681. while ( TRUE )
  8682. {
  8683. lResult = DOFUNC (&funcArgs, bWaveDevice ? "phoneGetIDEx" : "phoneGetID");
  8684. if ((lResult == 0) && ((*ppDeviceID)->dwNeededSize > (*ppDeviceID)->dwTotalSize))
  8685. {
  8686. DWORD dwSize = (*ppDeviceID)->dwNeededSize;
  8687. ClientFree(*ppDeviceID);
  8688. *ppDeviceID = (LPVARSTRING)ClientAlloc(dwSize);
  8689. if (NULL == *ppDeviceID)
  8690. {
  8691. LOG((TL_ERROR, "PhoneGetID exit - return LINEERR_NOMEM"));
  8692. return E_OUTOFMEMORY;
  8693. }
  8694. (*ppDeviceID)->dwTotalSize = dwSize;
  8695. funcArgs.Args[1] = (ULONG_PTR)*ppDeviceID;
  8696. }
  8697. else
  8698. {
  8699. break;
  8700. }
  8701. }
  8702. if (bWaveDevice && lResult == 0)
  8703. {
  8704. //
  8705. // We got the string ID(s), now we need to convert them to numeric device ID(s)
  8706. //
  8707. BOOL bConversionOk;
  8708. if ( dwNumDevices == 1 )
  8709. {
  8710. bConversionOk = WaveStringIdToDeviceId (
  8711. (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset),
  8712. lpszDeviceClass,
  8713. &dwDeviceId1);
  8714. }
  8715. else
  8716. {
  8717. _ASSERTE(dwNumDevices == 2);
  8718. //
  8719. // for "wave/in/out", we get back two devices from tapisrv -> convert both
  8720. //
  8721. LPWSTR szString1 = (LPWSTR)((LPBYTE)(*ppDeviceID) + (*ppDeviceID)->dwStringOffset);
  8722. // first convert the wave/in device
  8723. bConversionOk = WaveStringIdToDeviceId (
  8724. szString1,
  8725. L"wave/in",
  8726. &dwDeviceId1);
  8727. // next convert the wave/out device
  8728. bConversionOk = bConversionOk && WaveStringIdToDeviceId (
  8729. szString1 + wcslen(szString1),
  8730. L"wave/out",
  8731. &dwDeviceId2);
  8732. }
  8733. if (!bConversionOk)
  8734. {
  8735. LOG((TL_ERROR, "PhoneGetID - WaveStringIdToDeviceId failed"));
  8736. ClientFree(*ppDeviceID);
  8737. *ppDeviceID = NULL;
  8738. lResult = LINEERR_OPERATIONFAILED;
  8739. }
  8740. else
  8741. {
  8742. //
  8743. // conversion succeeded, now fill the VARSTRING to be returned to the caller
  8744. //
  8745. (*ppDeviceID)->dwNeededSize = (*ppDeviceID)->dwUsedSize =
  8746. sizeof(VARSTRING) + sizeof(DWORD) * dwNumDevices;
  8747. (*ppDeviceID)->dwStringFormat = STRINGFORMAT_BINARY;
  8748. (*ppDeviceID)->dwStringSize = sizeof(DWORD) * dwNumDevices;
  8749. (*ppDeviceID)->dwStringOffset = sizeof(VARSTRING);
  8750. *(DWORD *)((*ppDeviceID) + 1) = dwDeviceId1;
  8751. if (dwNumDevices == 2)
  8752. *((DWORD *)((*ppDeviceID) + 1) + 1) = dwDeviceId2;
  8753. }
  8754. }
  8755. LOG((TL_TRACE, "PhoneGetID exit - return %lx", lResult));
  8756. return mapTAPIErrorCode( lResult );
  8757. }
  8758. HRESULT
  8759. PhoneGetLamp(
  8760. HPHONE hPhone,
  8761. DWORD dwButtonLampID,
  8762. LPDWORD lpdwLampMode
  8763. )
  8764. {
  8765. FUNC_ARGS funcArgs =
  8766. {
  8767. MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
  8768. {
  8769. (ULONG_PTR) hPhone,
  8770. dwButtonLampID,
  8771. (ULONG_PTR) lpdwLampMode
  8772. },
  8773. {
  8774. Dword,
  8775. Dword,
  8776. lpDword
  8777. }
  8778. };
  8779. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetLamp"));
  8780. }
  8781. HRESULT
  8782. PhoneGetRing(
  8783. HPHONE hPhone,
  8784. LPDWORD lpdwRingMode,
  8785. LPDWORD lpdwVolume
  8786. )
  8787. {
  8788. FUNC_ARGS funcArgs =
  8789. {
  8790. MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
  8791. {
  8792. (ULONG_PTR) hPhone,
  8793. (ULONG_PTR) lpdwRingMode,
  8794. (ULONG_PTR) lpdwVolume
  8795. },
  8796. {
  8797. Dword,
  8798. lpDword,
  8799. lpDword
  8800. }
  8801. };
  8802. if (lpdwRingMode == lpdwVolume)
  8803. {
  8804. return E_POINTER;
  8805. }
  8806. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetRing"));
  8807. }
  8808. HRESULT
  8809. PhoneGetStatusWithAlloc(
  8810. HPHONE hPhone,
  8811. LPPHONESTATUS *ppPhoneStatus
  8812. )
  8813. {
  8814. LONG lResult;
  8815. *ppPhoneStatus = (LPPHONESTATUS) ClientAlloc( sizeof(PHONESTATUS) + 500 );
  8816. if (NULL == *ppPhoneStatus)
  8817. {
  8818. return E_OUTOFMEMORY;
  8819. }
  8820. (*ppPhoneStatus)->dwTotalSize = sizeof(PHONESTATUS) + 500;
  8821. FUNC_ARGS funcArgs =
  8822. {
  8823. MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
  8824. {
  8825. (ULONG_PTR) hPhone,
  8826. (ULONG_PTR) *ppPhoneStatus
  8827. },
  8828. {
  8829. Dword,
  8830. lpGet_Struct
  8831. }
  8832. };
  8833. while (TRUE)
  8834. {
  8835. lResult = DOFUNC (&funcArgs, "phoneGetStatus");
  8836. if ((0 == lResult) && ((*ppPhoneStatus)->dwNeededSize > (*ppPhoneStatus)->dwTotalSize))
  8837. {
  8838. DWORD dwSize = (*ppPhoneStatus)->dwNeededSize;
  8839. ClientFree( *ppPhoneStatus );
  8840. *ppPhoneStatus = (LPPHONESTATUS) ClientAlloc( dwSize );
  8841. if (NULL == *ppPhoneStatus)
  8842. {
  8843. return E_OUTOFMEMORY;
  8844. }
  8845. (*ppPhoneStatus)->dwTotalSize = dwSize;
  8846. funcArgs.Args[4] = (ULONG_PTR)*ppPhoneStatus;
  8847. }
  8848. else
  8849. {
  8850. break;
  8851. }
  8852. }
  8853. return mapTAPIErrorCode(lResult);
  8854. }
  8855. LONG
  8856. WINAPI
  8857. phoneGetStatusMessages(
  8858. HPHONE hPhone,
  8859. LPDWORD lpdwPhoneStates,
  8860. LPDWORD lpdwButtonModes,
  8861. LPDWORD lpdwButtonStates
  8862. )
  8863. {
  8864. FUNC_ARGS funcArgs =
  8865. {
  8866. MAKELONG (PHONE_FUNC | SYNC | 4, pGetStatusMessages),
  8867. {
  8868. (ULONG_PTR) hPhone,
  8869. (ULONG_PTR) lpdwPhoneStates,
  8870. (ULONG_PTR) lpdwButtonModes,
  8871. (ULONG_PTR) lpdwButtonStates
  8872. },
  8873. {
  8874. Dword,
  8875. lpDword,
  8876. lpDword,
  8877. lpDword
  8878. }
  8879. };
  8880. if (lpdwPhoneStates == lpdwButtonModes ||
  8881. lpdwPhoneStates == lpdwButtonStates ||
  8882. lpdwButtonModes == lpdwButtonStates)
  8883. {
  8884. return PHONEERR_INVALPOINTER;
  8885. }
  8886. return (DOFUNC (&funcArgs, "phoneGetStatusMessages"));
  8887. }
  8888. HRESULT
  8889. PhoneGetVolume(
  8890. HPHONE hPhone,
  8891. DWORD dwHookSwitchDev,
  8892. LPDWORD lpdwVolume
  8893. )
  8894. {
  8895. FUNC_ARGS funcArgs =
  8896. {
  8897. MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
  8898. {
  8899. (ULONG_PTR) hPhone,
  8900. dwHookSwitchDev,
  8901. (ULONG_PTR) lpdwVolume
  8902. },
  8903. {
  8904. Dword,
  8905. Dword,
  8906. lpDword
  8907. }
  8908. };
  8909. return mapTAPIErrorCode(DOFUNC (&funcArgs, "phoneGetVolume"));
  8910. }
  8911. HRESULT
  8912. PhoneNegotiateAPIVersion(
  8913. HPHONEAPP hPhoneApp,
  8914. DWORD dwDeviceID,
  8915. LPDWORD lpdwAPIVersion
  8916. )
  8917. {
  8918. PHONEEXTENSIONID PED;
  8919. FUNC_ARGS funcArgs =
  8920. {
  8921. MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
  8922. {
  8923. (ULONG_PTR) hPhoneApp,
  8924. dwDeviceID,
  8925. TAPI_VERSION1_0,
  8926. TAPI_VERSION_CURRENT,
  8927. (ULONG_PTR) lpdwAPIVersion,
  8928. (ULONG_PTR) &PED,
  8929. (ULONG_PTR) sizeof(PHONEEXTENSIONID)
  8930. },
  8931. {
  8932. hXxxApp,
  8933. Dword,
  8934. Dword,
  8935. Dword,
  8936. lpDword,
  8937. lpGet_SizeToFollow,
  8938. Size
  8939. }
  8940. };
  8941. return mapTAPIErrorCode( DOFUNC (&funcArgs, "phoneNegotiateAPIVersion") );
  8942. }
  8943. LONG
  8944. WINAPI
  8945. phoneNegotiateExtVersion(
  8946. HPHONEAPP hPhoneApp,
  8947. DWORD dwDeviceID,
  8948. DWORD dwAPIVersion,
  8949. DWORD dwExtLowVersion,
  8950. DWORD dwExtHighVersion,
  8951. LPDWORD lpdwExtVersion
  8952. )
  8953. {
  8954. FUNC_ARGS funcArgs =
  8955. {
  8956. MAKELONG (PHONE_FUNC | SYNC | 6, pNegotiateExtVersion),
  8957. {
  8958. (ULONG_PTR) hPhoneApp,
  8959. dwDeviceID,
  8960. dwAPIVersion,
  8961. dwExtLowVersion,
  8962. dwExtHighVersion,
  8963. (ULONG_PTR) lpdwExtVersion
  8964. },
  8965. {
  8966. hXxxApp,
  8967. Dword,
  8968. Dword,
  8969. Dword,
  8970. Dword,
  8971. lpDword
  8972. }
  8973. };
  8974. return (DOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
  8975. }
  8976. HRESULT
  8977. PhoneOpen(
  8978. HPHONEAPP hPhoneApp,
  8979. DWORD dwDeviceID,
  8980. T3PHONE * pt3Phone,
  8981. DWORD dwAPIVersion,
  8982. DWORD dwPrivilege
  8983. )
  8984. {
  8985. HRESULT hr;
  8986. FUNC_ARGS funcArgs =
  8987. {
  8988. MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
  8989. {
  8990. (ULONG_PTR) hPhoneApp,
  8991. dwDeviceID,
  8992. (ULONG_PTR) &(pt3Phone->hPhone),
  8993. dwAPIVersion,
  8994. 0,
  8995. 0,
  8996. dwPrivilege,
  8997. 0, // PHONEOPEN_PARAMS.hRemotePhone
  8998. },
  8999. {
  9000. hXxxApp,
  9001. Dword,
  9002. lpDword,
  9003. Dword,
  9004. Dword,
  9005. Dword,
  9006. Dword,
  9007. Dword
  9008. }
  9009. };
  9010. gpPhoneHashTable->Lock();
  9011. hr = ( DOFUNC (&funcArgs, "phoneOpen") );
  9012. if ( 0 == hr )
  9013. {
  9014. #ifdef USE_PHONEMSP
  9015. gpPhoneHashTable->Insert( (ULONG_PTR)(pt3Phone->hPhone), (ULONG_PTR)(pt3Phone->pMSPCall) );
  9016. #else
  9017. gpPhoneHashTable->Insert( (ULONG_PTR)(pt3Phone->hPhone), (ULONG_PTR)(pt3Phone->pPhone) );
  9018. #endif USE_PHONEMSP
  9019. }
  9020. gpPhoneHashTable->Unlock();
  9021. return mapTAPIErrorCode( hr );
  9022. }
  9023. HRESULT
  9024. PhoneSetButtonInfo(
  9025. HPHONE hPhone,
  9026. DWORD dwButtonLampID,
  9027. LPPHONEBUTTONINFO const pButtonInfo
  9028. )
  9029. {
  9030. FUNC_ARGS funcArgs =
  9031. {
  9032. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetButtonInfo),
  9033. {
  9034. (ULONG_PTR) hPhone,
  9035. dwButtonLampID,
  9036. (ULONG_PTR) pButtonInfo
  9037. },
  9038. {
  9039. Dword,
  9040. Dword,
  9041. lpSet_Struct
  9042. }
  9043. };
  9044. LONG lResult = DOFUNC (&funcArgs, "phoneSetButtonInfo");
  9045. if (lResult > 0) // async reply
  9046. {
  9047. return WaitForPhoneReply( lResult );
  9048. }
  9049. else
  9050. {
  9051. return mapTAPIErrorCode( lResult );
  9052. }
  9053. }
  9054. LONG
  9055. WINAPI
  9056. phoneSetData(
  9057. HPHONE hPhone,
  9058. DWORD dwDataID,
  9059. LPVOID const lpData,
  9060. DWORD dwSize
  9061. )
  9062. {
  9063. FUNC_ARGS funcArgs =
  9064. {
  9065. MAKELONG (PHONE_FUNC | ASYNC | 4, pSetData),
  9066. {
  9067. (ULONG_PTR) hPhone,
  9068. dwDataID,
  9069. (ULONG_PTR) lpData,
  9070. dwSize
  9071. },
  9072. {
  9073. Dword,
  9074. Dword,
  9075. lpSet_SizeToFollow,
  9076. Size
  9077. }
  9078. };
  9079. return (DOFUNC (&funcArgs, "phoneSetData"));
  9080. }
  9081. HRESULT
  9082. PhoneSetDisplay(
  9083. HPHONE hPhone,
  9084. DWORD dwRow,
  9085. DWORD dwColumn,
  9086. LPCSTR lpsDisplay,
  9087. DWORD dwSize
  9088. )
  9089. {
  9090. FUNC_ARGS funcArgs =
  9091. {
  9092. MAKELONG (PHONE_FUNC | ASYNC | 5, pSetDisplay),
  9093. {
  9094. (ULONG_PTR) hPhone,
  9095. dwRow,
  9096. dwColumn,
  9097. (ULONG_PTR) lpsDisplay,
  9098. dwSize
  9099. },
  9100. {
  9101. Dword,
  9102. Dword,
  9103. Dword,
  9104. lpSet_SizeToFollow,
  9105. Size
  9106. }
  9107. };
  9108. LONG lResult = DOFUNC (&funcArgs, "phoneSetDisplay");
  9109. if (lResult > 0) // async reply
  9110. {
  9111. return WaitForPhoneReply( lResult );
  9112. }
  9113. else
  9114. {
  9115. return mapTAPIErrorCode( lResult );
  9116. }
  9117. }
  9118. HRESULT
  9119. PhoneSetGain(
  9120. HPHONE hPhone,
  9121. DWORD dwHookSwitchDev,
  9122. DWORD dwGain
  9123. )
  9124. {
  9125. FUNC_ARGS funcArgs =
  9126. {
  9127. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetGain),
  9128. {
  9129. (ULONG_PTR) hPhone,
  9130. dwHookSwitchDev,
  9131. dwGain
  9132. },
  9133. {
  9134. Dword,
  9135. Dword,
  9136. Dword
  9137. }
  9138. };
  9139. LONG lResult = DOFUNC (&funcArgs, "phoneSetGain");
  9140. if (lResult > 0) // async reply
  9141. {
  9142. return WaitForPhoneReply( lResult );
  9143. }
  9144. else
  9145. {
  9146. return mapTAPIErrorCode( lResult );
  9147. }
  9148. }
  9149. HRESULT
  9150. PhoneSetHookSwitch(
  9151. HPHONE hPhone,
  9152. DWORD dwHookSwitchDevs,
  9153. DWORD dwHookSwitchMode
  9154. )
  9155. {
  9156. FUNC_ARGS funcArgs =
  9157. {
  9158. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetHookSwitch),
  9159. {
  9160. (ULONG_PTR) hPhone,
  9161. dwHookSwitchDevs,
  9162. dwHookSwitchMode
  9163. },
  9164. {
  9165. Dword,
  9166. Dword,
  9167. Dword
  9168. }
  9169. };
  9170. if (!(dwHookSwitchDevs & AllHookSwitchDevs) ||
  9171. (dwHookSwitchDevs & (~AllHookSwitchDevs)))
  9172. {
  9173. return mapTAPIErrorCode( PHONEERR_INVALHOOKSWITCHDEV );
  9174. }
  9175. if (!IsOnlyOneBitSetInDWORD (dwHookSwitchMode) ||
  9176. (dwHookSwitchMode & ~AllHookSwitchModes))
  9177. {
  9178. return mapTAPIErrorCode( PHONEERR_INVALHOOKSWITCHMODE );
  9179. }
  9180. LONG lResult = DOFUNC (&funcArgs, "phoneSetHookSwitch");
  9181. if (lResult > 0) // async reply
  9182. {
  9183. return WaitForPhoneReply( lResult );
  9184. }
  9185. else
  9186. {
  9187. return mapTAPIErrorCode( lResult );
  9188. }
  9189. }
  9190. HRESULT
  9191. PhoneSetLamp(
  9192. HPHONE hPhone,
  9193. DWORD dwButtonLampID,
  9194. DWORD dwLampMode
  9195. )
  9196. {
  9197. FUNC_ARGS funcArgs =
  9198. {
  9199. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetLamp),
  9200. {
  9201. (ULONG_PTR) hPhone,
  9202. dwButtonLampID,
  9203. dwLampMode
  9204. },
  9205. {
  9206. Dword,
  9207. Dword,
  9208. Dword
  9209. }
  9210. };
  9211. LONG lResult = DOFUNC (&funcArgs, "phoneSetRing");
  9212. if (lResult > 0) // async reply
  9213. {
  9214. return WaitForPhoneReply( lResult );
  9215. }
  9216. else
  9217. {
  9218. return mapTAPIErrorCode( lResult );
  9219. }
  9220. }
  9221. HRESULT
  9222. PhoneSetRing(
  9223. HPHONE hPhone,
  9224. DWORD dwRingMode,
  9225. DWORD dwVolume
  9226. )
  9227. {
  9228. FUNC_ARGS funcArgs =
  9229. {
  9230. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetRing),
  9231. {
  9232. (ULONG_PTR) hPhone,
  9233. dwRingMode,
  9234. dwVolume
  9235. },
  9236. {
  9237. Dword,
  9238. Dword,
  9239. Dword
  9240. }
  9241. };
  9242. LONG lResult = DOFUNC (&funcArgs, "phoneSetRing");
  9243. if (lResult > 0) // async reply
  9244. {
  9245. return WaitForPhoneReply( lResult );
  9246. }
  9247. else
  9248. {
  9249. return mapTAPIErrorCode( lResult );
  9250. }
  9251. }
  9252. LONG
  9253. WINAPI
  9254. phoneSetStatusMessages(
  9255. HPHONE hPhone,
  9256. DWORD dwPhoneStates,
  9257. DWORD dwButtonModes,
  9258. DWORD dwButtonStates
  9259. )
  9260. {
  9261. FUNC_ARGS funcArgs =
  9262. {
  9263. MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
  9264. {
  9265. (ULONG_PTR) hPhone,
  9266. dwPhoneStates,
  9267. dwButtonModes,
  9268. dwButtonStates
  9269. },
  9270. {
  9271. Dword,
  9272. Dword,
  9273. Dword,
  9274. Dword
  9275. }
  9276. };
  9277. return (DOFUNC (&funcArgs, "phoneSetStatusMessages"));
  9278. }
  9279. HRESULT
  9280. PhoneSetVolume(
  9281. HPHONE hPhone,
  9282. DWORD dwHookSwitchDev,
  9283. DWORD dwVolume
  9284. )
  9285. {
  9286. FUNC_ARGS funcArgs =
  9287. {
  9288. MAKELONG (PHONE_FUNC | ASYNC | 3, pSetVolume),
  9289. {
  9290. (ULONG_PTR) hPhone,
  9291. dwHookSwitchDev,
  9292. dwVolume
  9293. },
  9294. {
  9295. Dword,
  9296. Dword,
  9297. Dword
  9298. }
  9299. };
  9300. LONG lResult = DOFUNC (&funcArgs, "phoneSetVolume");
  9301. if (lResult > 0) // async reply
  9302. {
  9303. return WaitForPhoneReply( lResult );
  9304. }
  9305. else
  9306. {
  9307. return mapTAPIErrorCode( lResult );
  9308. }
  9309. }
  9310. HRESULT
  9311. ProviderPrivateFactoryIdentify(
  9312. DWORD dwDeviceID,
  9313. GUID * pguid
  9314. )
  9315. {
  9316. FUNC_ARGS funcArgs =
  9317. {
  9318. MAKELONG (LINE_FUNC | SYNC | 3, xPrivateFactoryIdentify),
  9319. {
  9320. (ULONG_PTR) dwDeviceID,
  9321. (ULONG_PTR) pguid,
  9322. (ULONG_PTR) sizeof(GUID)
  9323. },
  9324. {
  9325. Dword,
  9326. lpGet_SizeToFollow,
  9327. Size
  9328. }
  9329. };
  9330. return mapTAPIErrorCode( DOFUNC (&funcArgs, "ProviderPrivateFactoryIdentify") );
  9331. }
  9332. HRESULT
  9333. ProviderPrivateChannelData(
  9334. DWORD dwDeviceID,
  9335. DWORD dwAddressID,
  9336. HCALL hCall,
  9337. HCALLHUB hCallHub,
  9338. DWORD dwType,
  9339. BYTE * pBuffer,
  9340. DWORD dwSize
  9341. )
  9342. {
  9343. HRESULT hr;
  9344. FUNC_ARGS funcArgs =
  9345. {
  9346. MAKELONG (LINE_FUNC | SYNC | 7, lDevSpecificEx),
  9347. {
  9348. dwDeviceID,
  9349. dwAddressID,
  9350. (ULONG_PTR)hCall,
  9351. (ULONG_PTR)hCallHub,
  9352. dwType,
  9353. (ULONG_PTR)pBuffer,
  9354. dwSize
  9355. },
  9356. {
  9357. Dword,
  9358. Dword,
  9359. Dword,
  9360. Dword,
  9361. Dword,
  9362. lpSet_SizeToFollow,
  9363. Size
  9364. }
  9365. };
  9366. return mapTAPIErrorCode( DOFUNC (&funcArgs, "ProviderPrivateChannelData") );
  9367. }
  9368. //
  9369. // ----------------------- Private support routines ---------------------------
  9370. //
  9371. void
  9372. FreeInitData(
  9373. PT3INIT_DATA pInitData
  9374. )
  9375. {
  9376. EnterCriticalSection (&gcsTapisrvCommunication);
  9377. if (pInitData && ( pInitData->dwKey != 0xefefefef ) )
  9378. {
  9379. pInitData->dwKey = 0xefefefef;
  9380. LeaveCriticalSection (&gcsTapisrvCommunication);
  9381. ClientFree (pInitData);
  9382. }
  9383. else
  9384. {
  9385. LeaveCriticalSection (&gcsTapisrvCommunication);
  9386. }
  9387. }
  9388. //////////////////////////////////////////////////////////////////
  9389. // Wait for a reply for async stuff
  9390. //
  9391. //////////////////////////////////////////////////////////////////
  9392. HRESULT
  9393. WaitForReply(
  9394. DWORD dwID
  9395. )
  9396. {
  9397. HRESULT hr = S_OK;
  9398. CAsyncRequestReply *pReply;
  9399. // Create a new request entry on the list
  9400. pReply = gpLineAsyncReplyList->addRequest( dwID );
  9401. if( NULL == pReply )
  9402. {
  9403. LOG((TL_INFO, "gpLineAsyncReplyList->addRequest failed"));
  9404. hr = E_OUTOFMEMORY;
  9405. }
  9406. else
  9407. {
  9408. // Now we wait to be signalled
  9409. hr = pReply->wait();
  9410. if (-1 == hr)
  9411. {
  9412. gpLineAsyncReplyList->remove (pReply);
  9413. }
  9414. // Cleanup
  9415. delete pReply;
  9416. // if we we didn't wait long enough for the asycnronous call to succeed.
  9417. if (-1 == hr)
  9418. return TAPI_E_TIMEOUT;
  9419. }
  9420. return mapTAPIErrorCode( hr );
  9421. }
  9422. HRESULT
  9423. WaitForPhoneReply(
  9424. DWORD dwID
  9425. )
  9426. {
  9427. HRESULT hr = S_OK;
  9428. CAsyncRequestReply *pReply;
  9429. // Create a new request entry on the list
  9430. pReply = gpPhoneAsyncReplyList->addRequest( dwID );
  9431. if( NULL == pReply )
  9432. {
  9433. LOG((TL_INFO, "gpPhoneAsyncReplyList->addRequest failed"));
  9434. hr = E_OUTOFMEMORY;
  9435. }
  9436. else
  9437. {
  9438. // Now we wait to be signalled
  9439. hr = pReply->wait();
  9440. if (-1 == hr)
  9441. {
  9442. gpPhoneAsyncReplyList->remove (pReply);
  9443. }
  9444. // Cleanup
  9445. delete pReply;
  9446. // if we we didn't wait long enough for the asycnronous call to succeed.
  9447. if (-1 == hr)
  9448. return TAPI_E_TIMEOUT;
  9449. }
  9450. return mapTAPIErrorCode( hr );
  9451. }
  9452. /////////////////////////////////////////////////////////////////////
  9453. // FindCallObject
  9454. //
  9455. // Finds the call object associated with an HCALL
  9456. //
  9457. // Returns TRUE if the call object is found, FALSE if not.
  9458. //////////////////////////////////////////////////////////////////////
  9459. BOOL
  9460. FindCallObject(
  9461. HCALL hCall,
  9462. CCall ** ppCall
  9463. )
  9464. {
  9465. HRESULT hr;
  9466. gpCallHashTable->Lock();
  9467. hr = gpCallHashTable->Find( (ULONG_PTR)hCall, (ULONG_PTR *)ppCall );
  9468. if (SUCCEEDED(hr))
  9469. {
  9470. (*ppCall)->AddRef();
  9471. gpCallHashTable->Unlock();
  9472. return TRUE;
  9473. }
  9474. gpCallHashTable->Unlock();
  9475. return FALSE;
  9476. }
  9477. /////////////////////////////////////////////////////////////////////
  9478. // FindAddressObject
  9479. //
  9480. // Finds the address object associated with an HLINE
  9481. //
  9482. // Returns TRUE if the line object is found, FALSE if not.
  9483. //////////////////////////////////////////////////////////////////////
  9484. BOOL
  9485. FindAddressObject(
  9486. HLINE hLine,
  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. (*ppAddress)->AddRef();
  9496. gpLineHashTable->Unlock();
  9497. return TRUE;
  9498. }
  9499. gpLineHashTable->Unlock();
  9500. return FALSE;
  9501. }
  9502. BOOL
  9503. FindAddressObjectWithDeviceID(
  9504. HLINE hLine,
  9505. DWORD dwAddressID,
  9506. CAddress ** ppAddress
  9507. )
  9508. {
  9509. HRESULT hr;
  9510. gpLineHashTable->Lock();
  9511. hr = gpLineHashTable->Find( (ULONG_PTR)hLine, (ULONG_PTR *)ppAddress );
  9512. if ( SUCCEEDED(hr) )
  9513. {
  9514. if ((*ppAddress)->GetAddressID() == dwAddressID)
  9515. {
  9516. (*ppAddress)->AddRef();
  9517. gpLineHashTable->Unlock();
  9518. return TRUE;
  9519. }
  9520. }
  9521. gpLineHashTable->Unlock();
  9522. return FALSE;
  9523. }
  9524. /////////////////////////////////////////////////////////////////////
  9525. // FindPhoneObject
  9526. //
  9527. // Finds the phone object associated with an HPHONE
  9528. //
  9529. // Returns TRUE if the phone object is found, FALSE if not.
  9530. //////////////////////////////////////////////////////////////////////
  9531. BOOL
  9532. FindPhoneObject(
  9533. HPHONE hPhone,
  9534. CPhone ** ppPhone
  9535. )
  9536. {
  9537. HRESULT hr;
  9538. gpPhoneHashTable->Lock();
  9539. hr = gpPhoneHashTable->Find( (ULONG_PTR)hPhone, (ULONG_PTR *)ppPhone );
  9540. if ( SUCCEEDED(hr) )
  9541. {
  9542. (*ppPhone)->AddRef();
  9543. gpPhoneHashTable->Unlock();
  9544. return TRUE;
  9545. }
  9546. gpPhoneHashTable->Unlock();
  9547. return FALSE;
  9548. }
  9549. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9550. //
  9551. // FindAgentHandlerObject
  9552. //
  9553. // Finds the Agent Handler object associated with an HLINE
  9554. //
  9555. // Returns TRUE if the line object is found, FALSE if not.
  9556. //
  9557. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9558. BOOL
  9559. FindAgentHandlerObject(
  9560. HLINE hLine,
  9561. CAgentHandler ** ppAgentHandler
  9562. )
  9563. {
  9564. HRESULT hr = FALSE;
  9565. gpAgentHandlerHashTable->Lock();
  9566. hr = gpAgentHandlerHashTable->Find( (ULONG_PTR)hLine, (ULONG_PTR *)ppAgentHandler );
  9567. if ( SUCCEEDED(hr) )
  9568. {
  9569. (*ppAgentHandler)->AddRef();
  9570. hr = TRUE;
  9571. }
  9572. else
  9573. {
  9574. hr = FALSE;
  9575. }
  9576. gpAgentHandlerHashTable->Unlock();
  9577. return hr;
  9578. }
  9579. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9580. //
  9581. // FindCallHubObject
  9582. //
  9583. // Finds the CallHub object based on the hCallHub
  9584. //
  9585. // Returns TRUE if the line object is found, FALSE if not.
  9586. //
  9587. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9588. BOOL
  9589. FindCallHubObject(
  9590. HCALLHUB hCallHub,
  9591. CCallHub ** ppCallHub
  9592. )
  9593. {
  9594. HRESULT hr = FALSE;
  9595. gpCallHubHashTable->Lock();
  9596. hr = gpCallHubHashTable->Find( (ULONG_PTR)hCallHub, (ULONG_PTR *)ppCallHub );
  9597. if ( SUCCEEDED(hr) )
  9598. {
  9599. try
  9600. {
  9601. (*ppCallHub)->AddRef();
  9602. hr = TRUE;
  9603. }
  9604. catch(...)
  9605. {
  9606. hr = FALSE;
  9607. }
  9608. }
  9609. else
  9610. {
  9611. hr = FALSE;
  9612. }
  9613. gpCallHubHashTable->Unlock();
  9614. return hr;
  9615. }
  9616. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9617. //
  9618. // CheckTapisrvCallhub
  9619. //
  9620. // Checks that at least one hCall that TAPISRV supports for a CallHub exists
  9621. // as a Call Objects.
  9622. // This is to ensure that we have one call obect to reference the hub, otherwise
  9623. // it can be released prematurely
  9624. //
  9625. // Returns S_OK if one exists, E_FAIL if all are missing
  9626. //
  9627. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  9628. HRESULT
  9629. CheckTapisrvCallhub(HCALLHUB hCallHub)
  9630. {
  9631. LINECALLLIST * pCallHubList;
  9632. HCALL * phCalls;
  9633. DWORD dwCount;
  9634. CCall * pCall = NULL;
  9635. HRESULT hr = E_FAIL;
  9636. LOG((TL_INFO, "CheckTapisrvCallhub - hCallHub: %lx",hCallHub));
  9637. //
  9638. // get the list of hcalls
  9639. // related to this callhub
  9640. //
  9641. hr = LineGetHubRelatedCalls(
  9642. hCallHub,
  9643. 0,
  9644. &pCallHubList
  9645. );
  9646. if ( SUCCEEDED(hr) )
  9647. {
  9648. // Assume the worst..
  9649. hr = E_FAIL;
  9650. //
  9651. // get to the list of calls
  9652. //
  9653. phCalls = (HCALL *)(((LPBYTE)pCallHubList) + pCallHubList->dwCallsOffset);
  9654. //
  9655. // the first call is actually the callhub
  9656. // check it against the handle we gave...
  9657. //
  9658. if (hCallHub == (HCALLHUB)(phCalls[0]))
  9659. {
  9660. //
  9661. // go through the call handles and try to find call objects
  9662. //
  9663. for (dwCount = 1; dwCount < pCallHubList->dwCallsNumEntries; dwCount++)
  9664. {
  9665. //
  9666. // get the tapi3 call object
  9667. //
  9668. if ( FindCallObject(phCalls[dwCount], &pCall) )
  9669. {
  9670. // Found it - findcallobject addrefs, so release
  9671. pCall->Release();
  9672. LOG((TL_INFO, "CheckTapisrvCallhub - found hCall %lx", phCalls[dwCount]));
  9673. hr = S_OK;
  9674. break;
  9675. }
  9676. }
  9677. }
  9678. else
  9679. {
  9680. LOG((TL_INFO, "CheckTapisrvCallhub - returned callhub doesn't match"));
  9681. _ASSERTE(0);
  9682. hr = E_FAIL;
  9683. }
  9684. ClientFree( pCallHubList ); // Clean up
  9685. }
  9686. else
  9687. {
  9688. LOG((TL_INFO, "CheckTapisrvCallhub - LineGetHubRelatedCallsfailed"));
  9689. }
  9690. LOG((TL_TRACE, hr, "CheckTapisrvCallhub - exit"));
  9691. return hr;
  9692. }
  9693. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  9694. //
  9695. // ProcessEvent
  9696. // This processes messages from tapisrv
  9697. //
  9698. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
  9699. HRESULT
  9700. ProcessMessage(
  9701. PT3INIT_DATA pInitData,
  9702. PASYNCEVENTMSG pParams
  9703. )
  9704. {
  9705. HRESULT hResult = S_OK;
  9706. LOG((TL_INFO, "In ProcessMessage - MsgType:%x", pParams->Msg));
  9707. switch( pParams->Msg )
  9708. {
  9709. case LINE_CALLSTATE:
  9710. {
  9711. hResult = HandleCallStateMessage( pParams );
  9712. break;
  9713. }
  9714. case LINE_CALLINFO:
  9715. {
  9716. hResult = HandleCallInfoMessage( pParams );
  9717. break;
  9718. }
  9719. case LINE_MONITORDIGITS:
  9720. {
  9721. hResult = HandleMonitorDigitsMessage( pParams );
  9722. break;
  9723. }
  9724. case LINE_SENDMSPDATA:
  9725. {
  9726. hResult = HandleSendMSPDataMessage( pParams );
  9727. break;
  9728. }
  9729. case LINE_DEVSPECIFICEX:
  9730. {
  9731. //HandlePrivateEventMessage( pParams );
  9732. break;
  9733. }
  9734. case LINE_LINEDEVSTATE:
  9735. {
  9736. CTAPI *pTapi = NULL;
  9737. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9738. {
  9739. pTapi = pInitData->pTAPI;
  9740. }
  9741. HandleLineDevStateMessage( pTapi, pParams );
  9742. break;
  9743. }
  9744. case LINE_ADDRESSSTATE:
  9745. {
  9746. HandleAddressStateMessage( pParams );
  9747. break;
  9748. }
  9749. case LINE_DEVSPECIFIC:
  9750. {
  9751. HandleLineDevSpecificMessage( pParams );
  9752. break;
  9753. }
  9754. case LINE_DEVSPECIFICFEATURE:
  9755. {
  9756. //HandleDevSpecificFeatureMessage( pParams );
  9757. break;
  9758. }
  9759. case LINE_GATHERDIGITS:
  9760. {
  9761. hResult = HandleGatherDigitsMessage( pParams );
  9762. break;
  9763. }
  9764. case LINE_GENERATE:
  9765. {
  9766. hResult = HandleLineGenerateMessage( pParams );
  9767. break;
  9768. }
  9769. case LINE_MONITORMEDIA:
  9770. {
  9771. HandleMonitorMediaMessage( pParams );
  9772. break;
  9773. }
  9774. case LINE_MONITORTONE:
  9775. {
  9776. HandleMonitorToneMessage( pParams );
  9777. break;
  9778. }
  9779. case LINE_CLOSE:
  9780. {
  9781. HandleLineCloseMessage( pParams );
  9782. break;
  9783. }
  9784. case LINE_AGENTSTATUS:
  9785. {
  9786. break;
  9787. }
  9788. case LINE_AGENTSTATUSEX:
  9789. {
  9790. HandleAgentStatusMessage(pParams);
  9791. break;
  9792. }
  9793. case LINE_AGENTSESSIONSTATUS:
  9794. {
  9795. HandleAgentSessionStatusMessage(pParams);
  9796. break;
  9797. }
  9798. case LINE_QUEUESTATUS:
  9799. {
  9800. HandleQueueStatusMessage(pParams);
  9801. break;
  9802. }
  9803. case LINE_QOSINFO:
  9804. {
  9805. hResult = HandleLineQOSInfoMessage( pParams );
  9806. break;
  9807. }
  9808. case LINE_APPNEWCALLHUB:
  9809. {
  9810. HRESULT hr;
  9811. CCallHub * pCallHub;
  9812. BOOL fAllCallsDisconnected;
  9813. hResult = CheckTapisrvCallhub((HCALLHUB)pParams->Param1);
  9814. if (SUCCEEDED(hResult))
  9815. {
  9816. CTAPI *pTapi = NULL;
  9817. //
  9818. // pInitData seems good?
  9819. //
  9820. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9821. {
  9822. //
  9823. // check the tapi object, and get an addref'ed copy if it is
  9824. // valid
  9825. //
  9826. if ( CTAPI::IsValidTapiObject(pInitData->pTAPI) )
  9827. {
  9828. //
  9829. // got a good, addref'ed object. keep it.
  9830. //
  9831. pTapi = pInitData->pTAPI;
  9832. }
  9833. }
  9834. hr = CCallHub::CreateTapisrvCallHub(
  9835. pTapi,
  9836. (HCALLHUB)pParams->Param1,
  9837. &pCallHub
  9838. );
  9839. if (!SUCCEEDED(hr))
  9840. {
  9841. LOG((TL_ERROR, "CreateTapisrvCallHub failed in LINE_APPNEWCALLHUB"));
  9842. }
  9843. else
  9844. {
  9845. //Send CHE_CALLHUBIDLE message if all the calls in the callhub are disconnected.
  9846. hr = pCallHub -> FindCallsDisconnected( &fAllCallsDisconnected );
  9847. if( hr == S_OK )
  9848. {
  9849. if( fAllCallsDisconnected == TRUE )
  9850. {
  9851. //
  9852. // tell the app
  9853. //
  9854. pCallHub -> SetState(CHS_IDLE);
  9855. }
  9856. }
  9857. pCallHub->Release();
  9858. }
  9859. //
  9860. // if we we got a good tapi object, we must release it now.
  9861. //
  9862. if (NULL != pTapi)
  9863. {
  9864. pTapi->Release();
  9865. pTapi = NULL;
  9866. }
  9867. }
  9868. break;
  9869. }
  9870. case LINE_GROUPSTATUS:
  9871. {
  9872. handleGroupStatusMessage(pParams);
  9873. break;
  9874. }
  9875. case LINE_PROXYSTATUS:
  9876. {
  9877. CTAPI *pTapi = NULL;
  9878. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  9879. {
  9880. pTapi = pInitData->pTAPI;
  9881. }
  9882. QueueCallbackEvent( pTapi, pParams );
  9883. break;
  9884. }
  9885. case LINE_REPLY:
  9886. {
  9887. CAsyncRequestReply *pReply;
  9888. LOG((TL_INFO, "LINE_REPLY"));
  9889. // Add (or complete existing) response entry on the list
  9890. pReply = gpLineAsyncReplyList->addReply( pParams->Param1, (HRESULT) pParams->Param2 );
  9891. if(pReply==NULL)
  9892. {
  9893. LOG((TL_INFO, "gpLineAsyncReplyList->addReply failed"));
  9894. hResult = E_OUTOFMEMORY;
  9895. }
  9896. else
  9897. {
  9898. // Signal it to say we're done.
  9899. pReply->signal();
  9900. }
  9901. break;
  9902. }
  9903. case PHONE_REPLY:
  9904. {
  9905. CAsyncRequestReply *pReply;
  9906. LOG((TL_INFO, "PHONE_REPLY"));
  9907. // Add (or complete existing) response entry on the list
  9908. pReply = gpPhoneAsyncReplyList->addReply( pParams->Param1, (HRESULT) pParams->Param2 );
  9909. // Signal it to say we're done.
  9910. if(pReply == NULL )
  9911. {
  9912. LOG((TL_INFO, "gpPhoneAsyncReplyList->addReply failed"));
  9913. hResult = E_OUTOFMEMORY;
  9914. }
  9915. else
  9916. {
  9917. pReply->signal();
  9918. }
  9919. break;
  9920. }
  9921. case LINE_APPNEWCALL:
  9922. {
  9923. // LINE_APPNEWCALL is the first notification we get of
  9924. // a new call object. Create the call here, but
  9925. // don't notify the app until we get the first
  9926. // message about it.
  9927. CAddress * pAddress;
  9928. CCall * pCall = NULL;
  9929. if (FindAddressObjectWithDeviceID(
  9930. (HLINE) pParams->hDevice,
  9931. pParams->Param1,
  9932. &pAddress
  9933. ))
  9934. {
  9935. HRESULT hr;
  9936. LINECALLINFO * pCallInfo = NULL;
  9937. hr = LineGetCallInfo(
  9938. pParams->Param2,
  9939. &pCallInfo
  9940. );
  9941. if ( SUCCEEDED(hr) )
  9942. {
  9943. BOOL callExposeAndNotify = TRUE;
  9944. if ( pCallInfo->dwMediaMode & LINEMEDIAMODE_INTERACTIVEVOICE )
  9945. {
  9946. pCallInfo->dwMediaMode |= LINEMEDIAMODE_AUTOMATEDVOICE;
  9947. pCallInfo->dwMediaMode &= ~((DWORD)LINEMEDIAMODE_INTERACTIVEVOICE);
  9948. }
  9949. pCallInfo->dwMediaMode &= ~((DWORD)LINEMEDIAMODE_UNKNOWN);
  9950. //Check if the new call is a conference controller call.
  9951. BOOL fConfContCall = *(&pParams->Param4 + 3);
  9952. //Don't expose if a conference controller call
  9953. LOG(( TL_ERROR, "conference controller call:%d.", *(&pParams->Param4 + 3) ));
  9954. if( fConfContCall == TRUE )
  9955. {
  9956. LOG(( TL_ERROR, "conference controller call." ));
  9957. callExposeAndNotify = FALSE;
  9958. }
  9959. pAddress->InternalCreateCall(
  9960. NULL,
  9961. 0,
  9962. pCallInfo->dwMediaMode,
  9963. (pParams->Param3 == LINECALLPRIVILEGE_OWNER) ? CP_OWNER : CP_MONITOR,
  9964. callExposeAndNotify,
  9965. (HCALL)pParams->Param2,
  9966. callExposeAndNotify,
  9967. &pCall
  9968. );
  9969. }
  9970. if ( NULL != pCallInfo )
  9971. {
  9972. ClientFree( pCallInfo );
  9973. }
  9974. //
  9975. // don't keep a ref
  9976. if(pCall != NULL)
  9977. {
  9978. pCall->Release();
  9979. }
  9980. //
  9981. //FindAddressObject addrefs the address objct
  9982. pAddress->Release();
  9983. }
  9984. else
  9985. {
  9986. LOG((TL_ERROR, "Ignoring call with wrong address id"));
  9987. FUNC_ARGS funcArgs =
  9988. {
  9989. MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
  9990. {
  9991. pParams->Param2
  9992. },
  9993. {
  9994. Dword
  9995. }
  9996. };
  9997. LOG((TL_INFO, "lineDeallocateCall - hCall = 0x%08lx", pParams->Param2));
  9998. DOFUNC (&funcArgs, "lineDeallocateCall");
  9999. }
  10000. break;
  10001. }
  10002. case LINE_CREATE:
  10003. {
  10004. QueueCallbackEvent( pParams );
  10005. break;
  10006. }
  10007. case LINE_REMOVE:
  10008. {
  10009. QueueCallbackEvent( pParams );
  10010. break;
  10011. }
  10012. case LINE_REQUEST:
  10013. {
  10014. CTAPI *pTapi = NULL;
  10015. if (!IsBadReadPtr(pInitData, sizeof(pInitData)))
  10016. {
  10017. pTapi = pInitData->pTAPI;
  10018. }
  10019. HandleLineRequest( pTapi, pParams );
  10020. break;
  10021. }
  10022. case LINE_CALLHUBCLOSE:
  10023. {
  10024. gpRetryQueue->RemoveNewCallHub(pParams->Param1);
  10025. HandleCallHubClose( pParams );
  10026. break;
  10027. }
  10028. case PRIVATE_MSPEVENT:
  10029. {
  10030. HandlePrivateMSPEvent( pParams );
  10031. break;
  10032. }
  10033. case PHONE_BUTTON:
  10034. {
  10035. HandlePhoneButtonMessage( pParams );
  10036. break;
  10037. }
  10038. case PHONE_CLOSE:
  10039. {
  10040. HandlePhoneCloseMessage( pParams );
  10041. break;
  10042. }
  10043. case PHONE_DEVSPECIFIC:
  10044. {
  10045. HandlePhoneDevSpecificMessage( pParams );
  10046. break;
  10047. }
  10048. case PHONE_STATE:
  10049. {
  10050. QueueCallbackEvent( pParams );
  10051. break;
  10052. }
  10053. case PHONE_CREATE:
  10054. {
  10055. QueueCallbackEvent( pParams );
  10056. break;
  10057. }
  10058. case PHONE_REMOVE:
  10059. {
  10060. QueueCallbackEvent( pParams );
  10061. break;
  10062. }
  10063. case LINE_AGENTSPECIFIC:
  10064. case LINE_PROXYREQUEST:
  10065. default:
  10066. break;
  10067. }
  10068. return hResult;
  10069. }
  10070. void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
  10071. {
  10072. LOG((TL_TRACE, "midl_user_allocate: enter, size=x%x", len));
  10073. return (ClientAlloc (len));
  10074. }
  10075. void __RPC_API midl_user_free(void __RPC_FAR * ptr)
  10076. {
  10077. LOG((TL_TRACE, "midl_user_free: enter, p=x%p", ptr));
  10078. ClientFree (ptr);
  10079. }
  10080. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10081. //
  10082. // AllocClientResources
  10083. //
  10084. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10085. // only and hence access to it is serialized. Calling this function from some
  10086. // other functionality would need making an alternate arrangement to serialize
  10087. // access to this function
  10088. //
  10089. // Starts tapisrv if it is not started and calls ClientAttach
  10090. //
  10091. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10092. LONG
  10093. WINAPI
  10094. AllocClientResources(
  10095. DWORD dwErrorClass
  10096. )
  10097. {
  10098. LOG((TL_INFO, "AllocClientResources - enter"));
  10099. DWORD dwExceptionCount = 0;
  10100. DWORD dwError = 0;
  10101. LONG lResult = gaOpFailedErrors[dwErrorClass];
  10102. //
  10103. // service handles
  10104. //
  10105. SC_HANDLE hSCMgr = NULL;
  10106. SC_HANDLE hTapiSrv = NULL;
  10107. EnterCriticalSection ( &gcsClientResources );
  10108. //
  10109. // If we're in safeboot mode, tapisrv won't start;
  10110. // fail initialization.
  10111. //
  10112. if (0 != GetSystemMetrics (SM_CLEANBOOT))
  10113. {
  10114. lResult = gaOpFailedErrors[dwErrorClass];
  10115. goto AllocClientResources_return;
  10116. }
  10117. //
  10118. // Start the TAPISRV.EXE service
  10119. //
  10120. if (!(GetVersion() & 0x80000000)) // Win NT
  10121. {
  10122. if ((hSCMgr = OpenSCManager(
  10123. NULL, // local machine
  10124. NULL, // ServicesActive database
  10125. SC_MANAGER_CONNECT // desired access
  10126. )) == NULL)
  10127. {
  10128. dwError = GetLastError();
  10129. LOG((TL_ERROR, "OpenSCManager failed, err=%d", dwError));
  10130. if ( ERROR_ACCESS_DENIED == dwError ||
  10131. ERROR_NOACCESS == dwError
  10132. )
  10133. {
  10134. // if OpenSCManager fails with ACCESS_DENIED,
  10135. // we still need to try to attach to TAPISRV
  10136. goto AllocClientResources_attachToServer;
  10137. }
  10138. else
  10139. {
  10140. goto AllocClientResources_return;
  10141. }
  10142. }
  10143. if ((hTapiSrv = OpenService(
  10144. hSCMgr, // SC mgr handle
  10145. (LPCTSTR) "TAPISRV", // name of service to open
  10146. //SERVICE_START | // desired access
  10147. SERVICE_QUERY_STATUS
  10148. )) == NULL)
  10149. {
  10150. dwError = GetLastError();
  10151. LOG((TL_ERROR, "OpenService failed, err=%d", dwError));
  10152. if ( ERROR_ACCESS_DENIED == dwError ||
  10153. ERROR_NOACCESS == dwError
  10154. )
  10155. {
  10156. // if OpenService fails with ACCESS_DENIED,
  10157. // we still need to try to attach to TAPISRV
  10158. goto AllocClientResources_attachToServer;
  10159. }
  10160. else
  10161. {
  10162. goto AllocClientResources_cleanup1;
  10163. }
  10164. }
  10165. AllocClientResources_queryServiceStatus:
  10166. {
  10167. #define MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV 180
  10168. DWORD dwNumSecondsSleptStartPending = 0,
  10169. dwNumSecondsSleptStopPending = 0;
  10170. while (1)
  10171. {
  10172. SERVICE_STATUS status;
  10173. QueryServiceStatus (hTapiSrv, &status);
  10174. switch (status.dwCurrentState)
  10175. {
  10176. case SERVICE_RUNNING:
  10177. LOG((TL_INFO, "Tapisrv running"));
  10178. goto AllocClientResources_attachToServer;
  10179. case SERVICE_START_PENDING:
  10180. Sleep (1000);
  10181. if (++dwNumSecondsSleptStartPending >
  10182. MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
  10183. {
  10184. LOG((TL_ERROR,
  10185. "ERROR: Tapisrv stuck SERVICE_START_PENDING"
  10186. ));
  10187. goto AllocClientResources_cleanup2;
  10188. }
  10189. break;
  10190. case SERVICE_STOP_PENDING:
  10191. Sleep (1000);
  10192. if (++dwNumSecondsSleptStopPending >
  10193. MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
  10194. {
  10195. LOG((TL_ERROR,
  10196. "ERROR: Tapisrv stuck SERVICE_STOP_PENDING"
  10197. ));
  10198. goto AllocClientResources_cleanup2;
  10199. }
  10200. break;
  10201. case SERVICE_STOPPED:
  10202. LOG((TL_ERROR, "Starting tapisrv (NT)..."));
  10203. //
  10204. // close service handle that we already have
  10205. //
  10206. if (NULL != hTapiSrv)
  10207. {
  10208. CloseServiceHandle(hTapiSrv);
  10209. hTapiSrv = NULL;
  10210. }
  10211. /*Change: This is done in order to avoid opening service with
  10212. SERVICE_START previleges unless it needs to be started*/
  10213. if ((hTapiSrv = OpenService(
  10214. hSCMgr, // SC mgr handle
  10215. (LPCTSTR) "TAPISRV", // name of service to open
  10216. SERVICE_START | // desired access
  10217. SERVICE_QUERY_STATUS
  10218. )) == NULL)
  10219. {
  10220. LOG((TL_ERROR, "OpenService failed, err=%d", GetLastError()));
  10221. goto AllocClientResources_cleanup2;
  10222. }
  10223. if (!StartService(
  10224. hTapiSrv, // service handle
  10225. 0, // num args
  10226. NULL // args
  10227. ))
  10228. {
  10229. DWORD dwLastError = GetLastError();
  10230. if (dwLastError != ERROR_SERVICE_ALREADY_RUNNING)
  10231. {
  10232. LOG((TL_ERROR,
  10233. "StartService(TapiSrv) failed, err=%d",
  10234. dwLastError
  10235. ));
  10236. goto AllocClientResources_cleanup2;
  10237. }
  10238. }
  10239. break;
  10240. default:
  10241. LOG((TL_ERROR,
  10242. "error, service status=%d",
  10243. status.dwCurrentState
  10244. ));
  10245. goto AllocClientResources_cleanup2;
  10246. }
  10247. }
  10248. }
  10249. }
  10250. else // Win95
  10251. {
  10252. HANDLE hMutex, hEvent;
  10253. //
  10254. // First grab the global mutex that serializes the following
  10255. // across all instances of tapi32.dll
  10256. //
  10257. if (!(hMutex = CreateMutex (NULL, FALSE, "StartTapiSrv")))
  10258. {
  10259. LOG((TL_ERROR,
  10260. "CreateMutex ('StartTapiSrv') failed, err=%d",
  10261. GetLastError()
  10262. ));
  10263. }
  10264. WaitForSingleObject (hMutex, INFINITE);
  10265. //
  10266. // Try to open the event that tells us tapisrv has inited
  10267. //
  10268. if (!(hEvent = OpenEvent (EVENT_ALL_ACCESS, TRUE, "TapiSrvInited")))
  10269. {
  10270. //
  10271. // OpenEvent failed, so tapisrv hasn't been started yet. Start
  10272. // tapisrv, and then get the event handle.
  10273. //
  10274. STARTUPINFO startupInfo;
  10275. PROCESS_INFORMATION processInfo;
  10276. LOG((TL_ERROR,
  10277. "OpenEvent ('TapiSrvInited') failed, err=%d",
  10278. GetLastError()
  10279. ));
  10280. ZeroMemory(&startupInfo, sizeof (STARTUPINFO));
  10281. startupInfo.cb = sizeof (STARTUPINFO);
  10282. LOG((TL_INFO, "Starting tapisrv (Win95)..."));
  10283. if (!CreateProcess(
  10284. NULL, // image name
  10285. "tapisrv.exe", // cmd line
  10286. NULL, // process security attrs
  10287. NULL, // thread security attrs
  10288. FALSE, // inherit handles
  10289. NORMAL_PRIORITY_CLASS, // create opts
  10290. NULL, // environment
  10291. NULL, // curr dir
  10292. &startupInfo,
  10293. &processInfo
  10294. ))
  10295. {
  10296. LOG((TL_ERROR,
  10297. "CreateProcess('tapisrv.exe') failed, err=%d",
  10298. GetLastError()
  10299. ));
  10300. }
  10301. else
  10302. {
  10303. CloseHandle (processInfo.hProcess);
  10304. CloseHandle (processInfo.hThread);
  10305. }
  10306. if (!(hEvent = CreateEvent (NULL, TRUE, FALSE, "TapiSrvInited")))
  10307. {
  10308. LOG((TL_ERROR,
  10309. "CreateEvent ('TapiSrvInited') failed, err=%d",
  10310. GetLastError()
  10311. ));
  10312. }
  10313. }
  10314. //
  10315. // Now wait on the event (it's will be signaled when tapisrv has
  10316. // completed it's initialization). Then clean up.
  10317. //
  10318. WaitForSingleObject (hEvent, INFINITE);
  10319. CloseHandle (hEvent);
  10320. ReleaseMutex (hMutex);
  10321. CloseHandle (hMutex);
  10322. }
  10323. //
  10324. // Init the RPC connection
  10325. //
  10326. AllocClientResources_attachToServer:
  10327. {
  10328. #define CNLEN 25 // computer name length
  10329. #define UNCLEN CNLEN+2 // \\computername
  10330. #define PATHLEN 260 // Path
  10331. #define MAXPROTSEQ 20 // protocol sequence "ncacn_np"
  10332. BOOL bException = FALSE;
  10333. RPC_STATUS status;
  10334. unsigned char pszNetworkAddress[UNCLEN+1];
  10335. unsigned char *pszUuid = NULL;
  10336. unsigned char *pszOptions = NULL;
  10337. unsigned char *pszStringBinding = NULL;
  10338. DWORD dwProcessID = GetCurrentProcessId();
  10339. //
  10340. // UNLEN (as documented for GetUserName()) is defined in LMCONS.H
  10341. // to be 256 characters. LMCONS.H cannot be easily included, so we are
  10342. // redefining the value here.
  10343. //
  10344. const DWORD MAXIMUM_USER_NAME_LENGTH = 256;
  10345. //
  10346. // allocate memory for user name
  10347. //
  10348. DWORD dwUserNameSize = MAXIMUM_USER_NAME_LENGTH + 1;
  10349. WCHAR *pszUserName = (WCHAR *) ClientAlloc (dwUserNameSize * sizeof(WCHAR) );
  10350. if (NULL == pszUserName)
  10351. {
  10352. LOG((TL_ERROR,
  10353. "AllocClientResources: failed to allocate 0x%lx characters for pszUserName",
  10354. dwUserNameSize));
  10355. goto AllocClientResources_cleanup2;
  10356. }
  10357. //
  10358. // try to get user name. we are passing in a buffer for the
  10359. // longest possible user name so if the call fails, do not
  10360. // retry with a bigger buffer
  10361. //
  10362. BOOL bResult = GetUserNameW(pszUserName, &dwUserNameSize);
  10363. if ( ! bResult )
  10364. {
  10365. LOG((TL_ERROR,
  10366. "AllocClientResources: GetUserName failed. LastError = 0x%lx", GetLastError()));
  10367. ClientFree(pszUserName);
  10368. pszUserName = NULL;
  10369. goto AllocClientResources_cleanup2;
  10370. }
  10371. LOG((TL_INFO, "AllocClientResources: UserName [%S]", pszUserName));
  10372. //
  10373. // allocate memory for computer name
  10374. //
  10375. DWORD dwComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1 ;
  10376. WCHAR *pszComputerName = (WCHAR *) ClientAlloc (dwComputerNameSize * sizeof(WCHAR) );
  10377. if (NULL == pszComputerName)
  10378. {
  10379. LOG((TL_ERROR,
  10380. "AllocClientResources: failed to allocate 0x%lx characters for pszUserName",
  10381. dwComputerNameSize
  10382. ));
  10383. ClientFree(pszUserName);
  10384. pszUserName = NULL;
  10385. goto AllocClientResources_cleanup2;
  10386. }
  10387. //
  10388. // try to get computer name. we are passing in a buffer for the
  10389. // longest possible computer name so if the call fails, do not
  10390. // retry with a bigger buffer
  10391. //
  10392. bResult = GetComputerNameW(pszComputerName,
  10393. &dwComputerNameSize);
  10394. if ( ! bResult )
  10395. {
  10396. LOG((TL_ERROR,
  10397. "AllocClientResources: GetComputerName failed. LastError = 0x%lx", GetLastError()));
  10398. ClientFree(pszUserName);
  10399. pszUserName = NULL;
  10400. ClientFree(pszComputerName);
  10401. pszComputerName = NULL;
  10402. goto AllocClientResources_cleanup2;
  10403. }
  10404. LOG((TL_INFO, "AllocClientResources: ComputerName [%S]", pszComputerName));
  10405. pszNetworkAddress[0] = '\0';
  10406. status = RpcStringBindingCompose(
  10407. pszUuid,
  10408. (unsigned char *)"ncalrpc",
  10409. pszNetworkAddress,
  10410. (unsigned char *)"tapsrvlpc",
  10411. pszOptions,
  10412. &pszStringBinding
  10413. );
  10414. if (status)
  10415. {
  10416. LOG((TL_ERROR,
  10417. "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
  10418. status,
  10419. pszNetworkAddress
  10420. ));
  10421. }
  10422. status = RpcBindingFromStringBinding(
  10423. pszStringBinding,
  10424. &hTapSrv
  10425. );
  10426. if (status)
  10427. {
  10428. LOG((TL_ERROR,
  10429. "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
  10430. status,
  10431. pszStringBinding
  10432. ));
  10433. }
  10434. RpcTryExcept
  10435. {
  10436. LOG((TL_INFO, "AllocCliRes: calling ClientAttach..."));
  10437. lResult = ClientAttach(
  10438. (PCONTEXT_HANDLE_TYPE *) &gphCx,
  10439. dwProcessID,
  10440. (long *) &ghAsyncEventsEvent,
  10441. pszUserName,
  10442. pszComputerName
  10443. );
  10444. LOG((TL_INFO, "AllocCliRes: ClientAttach returned x%x. ghAsyncEventsEvent[%p]",
  10445. lResult, ghAsyncEventsEvent));
  10446. }
  10447. RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
  10448. {
  10449. LOG((TL_ERROR,
  10450. "AllocCliRes: ClientAttach caused except=%d",
  10451. RpcExceptionCode()
  10452. ));
  10453. bException = TRUE;
  10454. }
  10455. RpcEndExcept
  10456. ClientFree (pszUserName);
  10457. ClientFree (pszComputerName);
  10458. RpcBindingFree (&hTapSrv);
  10459. // LOG((TL_
  10460. // 3,
  10461. // "AllocCliRes: gphCx=x%x, PID=x%x, hAEEvent=x%x",
  10462. // gphCx,
  10463. // dwProcessID,
  10464. // ghAsyncEventsEvent
  10465. // ));
  10466. RpcStringFree(&pszStringBinding);
  10467. if (bException)
  10468. {
  10469. //
  10470. // If here chances are that we started the service and it's
  10471. // not ready to receive rpc requests. So we'll give it a
  10472. // little time to get rolling and then try again.
  10473. //
  10474. if (dwExceptionCount < gdwMaxNumRequestRetries)
  10475. {
  10476. Sleep ((++dwExceptionCount > 1 ? gdwRequestRetryTimeout : 0));
  10477. if (hTapiSrv) // Win NT && successful OpenService()
  10478. {
  10479. goto AllocClientResources_queryServiceStatus;
  10480. }
  10481. else
  10482. {
  10483. goto AllocClientResources_attachToServer;
  10484. }
  10485. }
  10486. else
  10487. {
  10488. LOG((TL_ERROR,
  10489. "AllocCliRes: ClientAttach failed, result=x%x",
  10490. gaServiceNotRunningErrors[dwErrorClass]
  10491. ));
  10492. lResult = gaServiceNotRunningErrors[dwErrorClass];
  10493. }
  10494. }
  10495. }
  10496. AllocClientResources_cleanup2:
  10497. if (NULL != hTapiSrv)
  10498. {
  10499. CloseServiceHandle (hTapiSrv);
  10500. hTapiSrv = NULL;
  10501. }
  10502. AllocClientResources_cleanup1:
  10503. if (NULL != hSCMgr)
  10504. {
  10505. CloseServiceHandle (hSCMgr);
  10506. hSCMgr = NULL;
  10507. }
  10508. AllocClientResources_return:
  10509. //release the mutex
  10510. LeaveCriticalSection ( &gcsClientResources );
  10511. LOG((TL_TRACE, "AllocClientResources: exit, returning x%x", lResult));
  10512. return lResult;
  10513. }
  10514. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10515. //
  10516. // NewShutdown
  10517. //
  10518. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10519. // only and hence access to it is serialized. Calling this function from some
  10520. // other functionality would need making an alternate arrangement to serialize
  10521. // access to this function
  10522. //
  10523. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10524. HRESULT
  10525. CTAPI::NewShutdown()
  10526. {
  10527. LOG((TL_TRACE, "NewShutdown - enter"));
  10528. FUNC_ARGS funcArgs =
  10529. {
  10530. MAKELONG (LINE_FUNC | SYNC | 1, lShutdown),
  10531. {
  10532. (ULONG_PTR)m_dwLineInitDataHandle
  10533. },
  10534. {
  10535. hXxxApp
  10536. }
  10537. };
  10538. //
  10539. // deallocate line resources
  10540. //
  10541. if (0 != m_dwLineInitDataHandle)
  10542. {
  10543. DOFUNC(
  10544. &funcArgs,
  10545. "lineShutdown"
  10546. );
  10547. FreeInitData (m_pLineInitData);
  10548. m_pLineInitData = NULL;
  10549. DeleteHandleTableEntry(m_dwLineInitDataHandle);
  10550. m_dwLineInitDataHandle = 0;
  10551. }
  10552. //
  10553. // deallocate phone resources
  10554. //
  10555. if (0 != m_dwPhoneInitDataHandle)
  10556. {
  10557. funcArgs.Args[0] = (ULONG_PTR)m_dwPhoneInitDataHandle;
  10558. funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 1, pShutdown),
  10559. DOFUNC(
  10560. &funcArgs,
  10561. "phoneShutdown"
  10562. );
  10563. FreeInitData (m_pPhoneInitData);
  10564. m_pPhoneInitData = NULL;
  10565. DeleteHandleTableEntry(m_dwPhoneInitDataHandle);
  10566. m_dwPhoneInitDataHandle = 0;
  10567. }
  10568. LOG((TL_TRACE, "NewShutdown - finish"));
  10569. return S_OK;
  10570. }
  10571. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10572. //
  10573. // CreateThreadsAndStuff
  10574. //
  10575. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10576. // only and hence access to it is serialized. Calling this function from some
  10577. // other functionality would need making an alternate arrangement to serialize
  10578. // access to this function
  10579. //
  10580. // This is called when the last TAPI object has been freed
  10581. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10582. void
  10583. CTAPI::FinalTapiCleanup()
  10584. {
  10585. DWORD dwSignalled;
  10586. STATICLOG((TL_TRACE, "FinalTapiCleanup - enter"));
  10587. //
  10588. // tell our threads that we are shutting down
  10589. //
  10590. if (gpAsyncEventsThreadParams)
  10591. {
  10592. gpAsyncEventsThreadParams->bExitThread = TRUE;
  10593. }
  10594. SetEvent( ghAsyncEventsEvent );
  10595. gbExitThread = TRUE;
  10596. SetEvent( ghCallbackThreadEvent );
  10597. //
  10598. // and wait for them to exit
  10599. //
  10600. STATICLOG((TL_INFO, "FinalTapiCleanup - ghAsyncEventsThread"));
  10601. //WaitForSingleObject( ghAsyncEventsThread, INFINITE );
  10602. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10603. INFINITE,
  10604. 1,
  10605. &ghAsyncEventsThread,
  10606. &dwSignalled);
  10607. STATICLOG((TL_INFO, "FinalTapiCleanup - ghCallbackThread"));
  10608. //WaitForSingleObject( ghCallbackThread, INFINITE );
  10609. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10610. INFINITE,
  10611. 1,
  10612. &ghCallbackThread,
  10613. &dwSignalled);
  10614. //
  10615. // close their handles
  10616. //
  10617. CloseHandle( ghAsyncEventsThread );
  10618. CloseHandle( ghCallbackThread );
  10619. gpAsyncEventsThreadParams = NULL;
  10620. //
  10621. // Safely close any existing generic dialog instances
  10622. //
  10623. EnterCriticalSection (&gcsTapisrvCommunication);
  10624. if (gpUIThreadInstances)
  10625. {
  10626. PUITHREADDATA pUIThreadData, pNextUIThreadData;
  10627. pUIThreadData = gpUIThreadInstances;
  10628. while (pUIThreadData)
  10629. {
  10630. //
  10631. // Grab a ptr to the next UIThreadData while it's still
  10632. // safe, wait until the ui dll has indicated that it
  10633. // is will to receive generic dlg data, then pass it
  10634. // NULL/0 to tell it to shutdown the dlg inst
  10635. //
  10636. pNextUIThreadData = pUIThreadData->pNext;
  10637. // WaitForSingleObject (pUIThreadData->hEvent, INFINITE);
  10638. CoWaitForMultipleHandles (COWAIT_ALERTABLE,
  10639. INFINITE,
  10640. 1,
  10641. &pUIThreadData->hEvent,
  10642. &dwSignalled
  10643. );
  10644. STATICLOG((TL_INFO,
  10645. "NewShutdown: calling TUISPI_providerGenericDialogData..."
  10646. ));
  10647. ((TUIGDDPROC)(*pUIThreadData->pfnTUISPI_providerGenericDialogData))(
  10648. pUIThreadData->htDlgInst,
  10649. NULL,
  10650. 0
  10651. );
  10652. STATICLOG((TL_INFO,
  10653. "NewShutdown: TUISPI_providerGenericDialogData returned"
  10654. ));
  10655. pUIThreadData = pNextUIThreadData;
  10656. }
  10657. }
  10658. LeaveCriticalSection (&gcsTapisrvCommunication);
  10659. FreeClientResources();
  10660. STATICLOG((TL_TRACE, "FinalTapiCleanup - exit"));
  10661. }
  10662. #if DBG
  10663. LPVOID
  10664. WINAPI
  10665. ClientAllocReal(
  10666. DWORD dwSize,
  10667. DWORD dwLine,
  10668. PSTR pszFile
  10669. )
  10670. #else
  10671. LPVOID
  10672. WINAPI
  10673. ClientAllocReal(
  10674. DWORD dwSize
  10675. )
  10676. #endif
  10677. {
  10678. //
  10679. // Alloc 16 extra bytes so we can make sure the pointer we pass back
  10680. // is 64-bit aligned & have space to store the original pointer
  10681. //
  10682. #if DBG
  10683. PMYMEMINFO pHold;
  10684. PDWORD_PTR pAligned;
  10685. PBYTE p;
  10686. p = (PBYTE)LocalAlloc(LPTR, dwSize + sizeof(MYMEMINFO) + 16);
  10687. if (p == NULL)
  10688. {
  10689. return NULL;
  10690. }
  10691. // note note note - this only works because mymeminfo is
  10692. // a 16 bit multiple in size. if it wasn't, this
  10693. // align stuff would cause problems.
  10694. pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
  10695. *pAligned = (DWORD_PTR) p;
  10696. pHold = (PMYMEMINFO)((DWORD_PTR)pAligned + 8);
  10697. pHold->dwSize = dwSize;
  10698. pHold->dwLine = dwLine;
  10699. pHold->pszFile = pszFile;
  10700. pHold->pPrev = NULL;
  10701. pHold->pNext = NULL;
  10702. EnterCriticalSection(&csMemoryList);
  10703. if (gpMemLast != NULL)
  10704. {
  10705. gpMemLast->pNext = pHold;
  10706. pHold->pPrev = gpMemLast;
  10707. gpMemLast = pHold;
  10708. }
  10709. else
  10710. {
  10711. gpMemFirst = gpMemLast = pHold;
  10712. }
  10713. LeaveCriticalSection(&csMemoryList);
  10714. return (LPVOID)(pHold + 1);
  10715. #else
  10716. LPBYTE p;
  10717. PDWORD_PTR pAligned;
  10718. if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
  10719. {
  10720. pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
  10721. *pAligned = (DWORD_PTR) p;
  10722. pAligned = (PDWORD_PTR)((DWORD_PTR)pAligned + 8);
  10723. }
  10724. else
  10725. {
  10726. LOG((TL_ERROR,
  10727. "ClientAlloc: LocalAlloc (x%lx) failed, err=x%lx",
  10728. dwSize,
  10729. GetLastError())
  10730. );
  10731. pAligned = NULL;
  10732. }
  10733. return ((LPVOID) pAligned);
  10734. #endif
  10735. }
  10736. void
  10737. WINAPI
  10738. ClientFree(
  10739. LPVOID p
  10740. )
  10741. {
  10742. #if DBG
  10743. PMYMEMINFO pHold;
  10744. if (p == NULL)
  10745. {
  10746. return;
  10747. }
  10748. pHold = (PMYMEMINFO)(((LPBYTE)p) - sizeof(MYMEMINFO));
  10749. EnterCriticalSection(&csMemoryList);
  10750. if (pHold->pPrev)
  10751. {
  10752. pHold->pPrev->pNext = pHold->pNext;
  10753. }
  10754. else
  10755. {
  10756. gpMemFirst = pHold->pNext;
  10757. }
  10758. if (pHold->pNext)
  10759. {
  10760. pHold->pNext->pPrev = pHold->pPrev;
  10761. }
  10762. else
  10763. {
  10764. gpMemLast = pHold->pPrev;
  10765. }
  10766. LeaveCriticalSection(&csMemoryList);
  10767. {
  10768. LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)pHold - 8));
  10769. LocalFree (pOrig);
  10770. }
  10771. //LocalFree(pHold);
  10772. return;
  10773. #else
  10774. if (p != NULL)
  10775. {
  10776. LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)p - 8));
  10777. LocalFree (pOrig);
  10778. }
  10779. else
  10780. {
  10781. LOG((TL_INFO,"----- ClientFree: ptr = NULL!"));
  10782. }
  10783. #endif
  10784. }
  10785. SIZE_T
  10786. WINAPI
  10787. ClientSize(
  10788. LPVOID p
  10789. )
  10790. {
  10791. if (p != NULL)
  10792. {
  10793. #if DBG
  10794. p = (LPVOID)(((LPBYTE)p) - sizeof(MYMEMINFO));
  10795. #endif
  10796. p = (LPVOID)*((PDWORD_PTR)((DWORD_PTR)p - 8));
  10797. return (LocalSize (p) - 16);
  10798. }
  10799. LOG((TL_INFO,"----- ClientSize: ptr = NULL!"));
  10800. return 0;
  10801. }
  10802. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10803. //
  10804. // FreeClientResources
  10805. //
  10806. // This function is called from inside CTAPI::Initialize and CTAPI::Shutdown
  10807. // only and hence access to it is serialized. Calling this function from some
  10808. // other functionality would need making an alternate arrangement to serialize
  10809. // access to this function
  10810. //
  10811. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10812. LONG
  10813. WINAPI
  10814. FreeClientResources(
  10815. void
  10816. )
  10817. {
  10818. LOG((TL_INFO, "FreeClientResources - enter"));
  10819. //grab the critical section
  10820. EnterCriticalSection ( &gcsClientResources );
  10821. //
  10822. // If ghTapi32 is non-NULL it means the AsyncEventsThread is
  10823. // still running (an ill-behaved app is trying to unload us
  10824. // without calling shutdown) so go thru the motions of getting
  10825. // the thread to terminate (like we do in xxxShutdown)
  10826. //
  10827. // Otherwise close our handle to the shared event
  10828. //
  10829. if (gpAsyncEventsThreadParams)
  10830. {
  10831. gpAsyncEventsThreadParams->bExitThread = TRUE;
  10832. SetEvent (ghAsyncEventsEvent);
  10833. gpAsyncEventsThreadParams = NULL;
  10834. gbExitThread = TRUE;
  10835. SetEvent (ghCallbackThreadEvent);
  10836. }
  10837. else if (gphCx)
  10838. {
  10839. if (NULL != ghAsyncEventsEvent)
  10840. {
  10841. CloseHandle (ghAsyncEventsEvent);
  10842. ghAsyncEventsEvent = NULL;
  10843. }
  10844. if (NULL != ghCallbackThreadEvent)
  10845. {
  10846. CloseHandle (ghCallbackThreadEvent);
  10847. ghCallbackThreadEvent = NULL;
  10848. }
  10849. if (NULL != ghAsyncRetryQueueEvent)
  10850. {
  10851. CloseHandle (ghAsyncRetryQueueEvent);
  10852. ghAsyncRetryQueueEvent = NULL;
  10853. }
  10854. }
  10855. gpLineAsyncReplyList->FreeList();
  10856. gpPhoneAsyncReplyList->FreeList();
  10857. //
  10858. // If we've made an rpc connection with tapisrv then cleanly detach
  10859. //
  10860. if (gphCx)
  10861. {
  10862. RpcTryExcept
  10863. {
  10864. ClientDetach (&gphCx);
  10865. }
  10866. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  10867. {
  10868. // do something?
  10869. }
  10870. RpcEndExcept
  10871. gphCx = NULL;
  10872. }
  10873. //
  10874. // Free up any other resources we were using
  10875. //
  10876. if (ghWow32Dll)
  10877. {
  10878. FreeLibrary (ghWow32Dll);
  10879. ghWow32Dll = NULL;
  10880. }
  10881. //release the mutex
  10882. LeaveCriticalSection ( &gcsClientResources );
  10883. LOG((TL_INFO, "FreeClientResources - exit"));
  10884. return 0;
  10885. }
  10886. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10887. //
  10888. // eventName
  10889. //
  10890. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10891. char *eventName(TAPI_EVENT event)
  10892. {
  10893. switch(event)
  10894. {
  10895. case TE_TAPIOBJECT:
  10896. return "TE_TAPIOBJECT";
  10897. case TE_ADDRESS:
  10898. return "TE_ADDRESS";
  10899. case TE_CALLNOTIFICATION:
  10900. return "TE_CALLNOTIFICATION";
  10901. case TE_CALLSTATE:
  10902. return "TE_CALLSTATE";
  10903. case TE_CALLMEDIA:
  10904. return "TE_CALLMEDIA";
  10905. case TE_CALLHUB:
  10906. return "TE_CALLHUB";
  10907. case TE_CALLINFOCHANGE:
  10908. return "TE_CALLINFOCHANGE";
  10909. case TE_PRIVATE:
  10910. return "TE_PRIVATE";
  10911. case TE_REQUEST:
  10912. return "TE_REQUEST";
  10913. case TE_AGENT:
  10914. return "TE_AGENT";
  10915. case TE_AGENTSESSION:
  10916. return "TE_AGENTSESSION";
  10917. case TE_QOSEVENT:
  10918. return "TE_QOSEVENT";
  10919. case TE_AGENTHANDLER:
  10920. return "TE_AGENTHANDLER";
  10921. case TE_ACDGROUP:
  10922. return "TE_ACDGROUP";
  10923. case TE_QUEUE:
  10924. return "TE_QUEUE";
  10925. case TE_DIGITEVENT:
  10926. return "TE_DIGITEVENT";
  10927. case TE_GENERATEEVENT:
  10928. return "TE_GENERATEEVENT";
  10929. case TE_PHONEEVENT:
  10930. return "TE_PHONEEVENT";
  10931. case TE_PHONEDEVSPECIFIC:
  10932. return "TE_PHONEDEVSPECIFIC";
  10933. case TE_ADDRESSDEVSPECIFIC:
  10934. return "TE_ADDRESSDEVSPECIFIC";
  10935. default:
  10936. return "???";
  10937. }
  10938. }
  10939. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10940. //
  10941. // callStateName
  10942. //
  10943. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  10944. char *callStateName(CALL_STATE callState)
  10945. {
  10946. switch(callState)
  10947. {
  10948. case CS_IDLE:
  10949. return "CS_IDLE";
  10950. case CS_INPROGRESS:
  10951. return "CS_INPROGRESS";
  10952. case CS_CONNECTED:
  10953. return "CS_CONNECTED";
  10954. case CS_DISCONNECTED:
  10955. return "CS_DISCONNECTED";
  10956. case CS_OFFERING:
  10957. return "CS_OFFERING";
  10958. case CS_HOLD:
  10959. return "CS_HOLD";
  10960. case CS_QUEUED:
  10961. return "CS_QUEUED";
  10962. default:
  10963. return "???";
  10964. }
  10965. }
  10966. #ifdef TRACELOG
  10967. void TAPIFormatMessage(HRESULT hr, LPVOID lpMsgBuf)
  10968. {
  10969. // Get the error message relating to our HRESULT
  10970. FormatMessage(
  10971. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  10972. FORMAT_MESSAGE_FROM_HMODULE |
  10973. FORMAT_MESSAGE_FROM_SYSTEM |
  10974. FORMAT_MESSAGE_IGNORE_INSERTS,
  10975. (LPCVOID)GetModuleHandle("TAPI3.DLL"),
  10976. hr,
  10977. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  10978. (LPTSTR) lpMsgBuf,
  10979. 0,
  10980. NULL
  10981. );
  10982. }
  10983. #endif
  10984. LONG
  10985. CALLBACK
  10986. TUISPIDLLCallback(
  10987. DWORD_PTR dwObjectID,
  10988. DWORD dwObjectType,
  10989. LPVOID lpParams,
  10990. DWORD dwSize
  10991. )
  10992. {
  10993. FUNC_ARGS funcArgs =
  10994. {
  10995. MAKELONG (LINE_FUNC | SYNC | 6, xUIDLLCallback),
  10996. {
  10997. (ULONG_PTR) dwObjectID,
  10998. (ULONG_PTR) dwObjectType,
  10999. (ULONG_PTR) lpParams,
  11000. (ULONG_PTR) dwSize,
  11001. (ULONG_PTR) lpParams,
  11002. (ULONG_PTR) dwSize
  11003. },
  11004. {
  11005. Dword,
  11006. Dword,
  11007. lpSet_SizeToFollow,
  11008. Size,
  11009. lpGet_SizeToFollow,
  11010. Size
  11011. }
  11012. };
  11013. return (DOFUNC (&funcArgs, "UIDLLCallback"));
  11014. }
  11015. void
  11016. UIThread(
  11017. LPVOID pParams
  11018. )
  11019. {
  11020. DWORD dwThreadID = GetCurrentThreadId();
  11021. HANDLE hTapi32;
  11022. PUITHREADDATA pUIThreadData = (PUITHREADDATA) pParams;
  11023. LOG((TL_TRACE, "UIThread: enter (tid=%d)", dwThreadID));
  11024. //
  11025. // Call LoadLibrary to increment the reference count in case this
  11026. // thread is still running when this dll gets unloaded
  11027. //
  11028. hTapi32 = LoadLibrary ("tapi32.dll");
  11029. LOG((TL_INFO, "UIThread: calling TUISPI_providerGenericDialog..."));
  11030. ((TUIGDPROC)(*pUIThreadData->pfnTUISPI_providerGenericDialog))(
  11031. TUISPIDLLCallback,
  11032. pUIThreadData->htDlgInst,
  11033. pUIThreadData->pParams,
  11034. pUIThreadData->dwSize,
  11035. pUIThreadData->hEvent
  11036. );
  11037. LOG((TL_INFO,
  11038. "UIThread: TUISPI_providerGenericDialog returned (tid=%d)",
  11039. dwThreadID
  11040. ));
  11041. //
  11042. // Remove the ui thread data struct from the global list
  11043. //
  11044. EnterCriticalSection (&gcsTapisrvCommunication);
  11045. if (pUIThreadData->pNext)
  11046. {
  11047. pUIThreadData->pNext->pPrev = pUIThreadData->pPrev;
  11048. }
  11049. if (pUIThreadData->pPrev)
  11050. {
  11051. pUIThreadData->pPrev->pNext = pUIThreadData->pNext;
  11052. }
  11053. else
  11054. {
  11055. gpUIThreadInstances = pUIThreadData->pNext;
  11056. }
  11057. LeaveCriticalSection (&gcsTapisrvCommunication);
  11058. //
  11059. // Free the library & buffers, then alert tapisrv
  11060. //
  11061. FreeLibrary (pUIThreadData->hUIDll);
  11062. CloseHandle (pUIThreadData->hThread);
  11063. CloseHandle (pUIThreadData->hEvent);
  11064. if (pUIThreadData->pParams)
  11065. {
  11066. ClientFree (pUIThreadData->pParams);
  11067. }
  11068. {
  11069. FUNC_ARGS funcArgs =
  11070. {
  11071. MAKELONG (LINE_FUNC | SYNC | 1, xFreeDialogInstance),
  11072. {
  11073. (ULONG_PTR) pUIThreadData->htDlgInst
  11074. },
  11075. {
  11076. Dword
  11077. }
  11078. };
  11079. DOFUNC (&funcArgs, "FreeDialogInstance");
  11080. }
  11081. ClientFree (pUIThreadData);
  11082. LOG((TL_TRACE, "UIThread: exit (tid=%d)", dwThreadID));
  11083. if (hTapi32 != NULL)
  11084. {
  11085. FreeLibraryAndExitThread ((HINSTANCE)hTapi32, 0);
  11086. }
  11087. else
  11088. {
  11089. ExitThread (0);
  11090. }
  11091. }
  11092. LONG
  11093. //WINAPI
  11094. CALLBACK
  11095. LAddrParamsInited(
  11096. LPDWORD lpdwInited
  11097. )
  11098. {
  11099. HKEY hKey;
  11100. HKEY hKey2;
  11101. DWORD dwDataSize;
  11102. DWORD dwDataType;
  11103. //
  11104. // This is called by the modem setup wizard to determine
  11105. // whether they should put up TAPI's Wizard page.
  11106. //
  11107. if (ERROR_SUCCESS !=
  11108. RegOpenKeyEx(
  11109. HKEY_LOCAL_MACHINE,
  11110. gszTelephonyKey,
  11111. 0,
  11112. KEY_READ,
  11113. &hKey2
  11114. ))
  11115. {
  11116. LOG((TL_ERROR, "LAddrParamsInited - failed to open registry key" ));
  11117. return 0;
  11118. }
  11119. if (ERROR_SUCCESS !=
  11120. RegOpenKeyEx(
  11121. hKey2,
  11122. gszLocations,
  11123. 0,
  11124. KEY_READ,
  11125. &hKey
  11126. ))
  11127. {
  11128. RegCloseKey (hKey2);
  11129. LOG((TL_ERROR, "LAddrParamsInited - failed to open registry key" ));
  11130. return 0;
  11131. }
  11132. dwDataSize = sizeof(DWORD);
  11133. *lpdwInited=0;
  11134. RegQueryValueEx(
  11135. hKey,
  11136. gszNumEntries,
  11137. 0,
  11138. &dwDataType,
  11139. (LPBYTE)lpdwInited,
  11140. &dwDataSize
  11141. );
  11142. RegCloseKey( hKey );
  11143. RegCloseKey( hKey2);
  11144. //
  11145. // Return a "proper" code
  11146. //
  11147. if ( *lpdwInited > 1 )
  11148. {
  11149. *lpdwInited = 1;
  11150. }
  11151. return 0;
  11152. }
  11153. LONG
  11154. WINAPI
  11155. lineTranslateDialogA(
  11156. HLINEAPP hLineApp,
  11157. DWORD dwDeviceID,
  11158. DWORD dwAPIVersion,
  11159. HWND hwndOwner,
  11160. LPCSTR lpszAddressIn
  11161. );
  11162. /////////////////////////////////////////////////////////////////////
  11163. // internalPerformance
  11164. // tapiperf.dll calls this function to get performance data
  11165. // this just calls into tapisrv
  11166. /////////////////////////////////////////////////////////////////////
  11167. LONG
  11168. WINAPI
  11169. internalPerformance(PPERFBLOCK pPerfBlock)
  11170. {
  11171. FUNC_ARGS funcArgs =
  11172. {
  11173. MAKELONG (LINE_FUNC | SYNC | 2, tPerformance),
  11174. {
  11175. (ULONG_PTR)pPerfBlock,
  11176. sizeof(PERFBLOCK)
  11177. },
  11178. {
  11179. lpGet_SizeToFollow,
  11180. Size
  11181. }
  11182. };
  11183. return (DOFUNC (&funcArgs, "PerfDataCall"));
  11184. }
  11185. //***************************************************************************
  11186. //***************************************************************************
  11187. //***************************************************************************
  11188. #if DBG
  11189. char *aszLineErrors[] =
  11190. {
  11191. NULL,
  11192. "ALLOCATED",
  11193. "BADDEVICEID",
  11194. "BEARERMODEUNAVAIL",
  11195. "inval err value (0x80000004)", // 0x80000004 isn't valid err code
  11196. "CALLUNAVAIL",
  11197. "COMPLETIONOVERRUN",
  11198. "CONFERENCEFULL",
  11199. "DIALBILLING",
  11200. "DIALDIALTONE",
  11201. "DIALPROMPT",
  11202. "DIALQUIET",
  11203. "INCOMPATIBLEAPIVERSION",
  11204. "INCOMPATIBLEEXTVERSION",
  11205. "INIFILECORRUPT",
  11206. "INUSE",
  11207. "INVALADDRESS", // 0x80000010
  11208. "INVALADDRESSID",
  11209. "INVALADDRESSMODE",
  11210. "INVALADDRESSSTATE",
  11211. "INVALAPPHANDLE",
  11212. "INVALAPPNAME",
  11213. "INVALBEARERMODE",
  11214. "INVALCALLCOMPLMODE",
  11215. "INVALCALLHANDLE",
  11216. "INVALCALLPARAMS",
  11217. "INVALCALLPRIVILEGE",
  11218. "INVALCALLSELECT",
  11219. "INVALCALLSTATE",
  11220. "INVALCALLSTATELIST",
  11221. "INVALCARD",
  11222. "INVALCOMPLETIONID",
  11223. "INVALCONFCALLHANDLE", // 0x80000020
  11224. "INVALCONSULTCALLHANDLE",
  11225. "INVALCOUNTRYCODE",
  11226. "INVALDEVICECLASS",
  11227. "INVALDEVICEHANDLE",
  11228. "INVALDIALPARAMS",
  11229. "INVALDIGITLIST",
  11230. "INVALDIGITMODE",
  11231. "INVALDIGITS",
  11232. "INVALEXTVERSION",
  11233. "INVALGROUPID",
  11234. "INVALLINEHANDLE",
  11235. "INVALLINESTATE",
  11236. "INVALLOCATION",
  11237. "INVALMEDIALIST",
  11238. "INVALMEDIAMODE",
  11239. "INVALMESSAGEID", // 0x80000030
  11240. "inval err value (0x80000031)", // 0x80000031 isn't valid err code
  11241. "INVALPARAM",
  11242. "INVALPARKID",
  11243. "INVALPARKMODE",
  11244. "INVALPOINTER",
  11245. "INVALPRIVSELECT",
  11246. "INVALRATE",
  11247. "INVALREQUESTMODE",
  11248. "INVALTERMINALID",
  11249. "INVALTERMINALMODE",
  11250. "INVALTIMEOUT",
  11251. "INVALTONE",
  11252. "INVALTONELIST",
  11253. "INVALTONEMODE",
  11254. "INVALTRANSFERMODE",
  11255. "LINEMAPPERFAILED", // 0x80000040
  11256. "NOCONFERENCE",
  11257. "NODEVICE",
  11258. "NODRIVER",
  11259. "NOMEM",
  11260. "NOREQUEST",
  11261. "NOTOWNER",
  11262. "NOTREGISTERED",
  11263. "OPERATIONFAILED",
  11264. "OPERATIONUNAVAIL",
  11265. "RATEUNAVAIL",
  11266. "RESOURCEUNAVAIL",
  11267. "REQUESTOVERRUN",
  11268. "STRUCTURETOOSMALL",
  11269. "TARGETNOTFOUND",
  11270. "TARGETSELF",
  11271. "UNINITIALIZED", // 0x80000050
  11272. "USERUSERINFOTOOBIG",
  11273. "REINIT",
  11274. "ADDRESSBLOCKED",
  11275. "BILLINGREJECTED",
  11276. "INVALFEATURE",
  11277. "NOMULTIPLEINSTANCE",
  11278. "INVALAGENTID",
  11279. "INVALAGENTGROUP",
  11280. "INVALPASSWORD",
  11281. "INVALAGENTSTATE",
  11282. "INVALAGENTACTIVITY",
  11283. "DIALVOICEDETECT"
  11284. };
  11285. char *aszPhoneErrors[] =
  11286. {
  11287. "SUCCESS",
  11288. "ALLOCATED",
  11289. "BADDEVICEID",
  11290. "INCOMPATIBLEAPIVERSION",
  11291. "INCOMPATIBLEEXTVERSION",
  11292. "INIFILECORRUPT",
  11293. "INUSE",
  11294. "INVALAPPHANDLE",
  11295. "INVALAPPNAME",
  11296. "INVALBUTTONLAMPID",
  11297. "INVALBUTTONMODE",
  11298. "INVALBUTTONSTATE",
  11299. "INVALDATAID",
  11300. "INVALDEVICECLASS",
  11301. "INVALEXTVERSION",
  11302. "INVALHOOKSWITCHDEV",
  11303. "INVALHOOKSWITCHMODE", // 0x90000010
  11304. "INVALLAMPMODE",
  11305. "INVALPARAM",
  11306. "INVALPHONEHANDLE",
  11307. "INVALPHONESTATE",
  11308. "INVALPOINTER",
  11309. "INVALPRIVILEGE",
  11310. "INVALRINGMODE",
  11311. "NODEVICE",
  11312. "NODRIVER",
  11313. "NOMEM",
  11314. "NOTOWNER",
  11315. "OPERATIONFAILED",
  11316. "OPERATIONUNAVAIL",
  11317. "inval err value (0x9000001e)", // 0x9000001e isn't valid err code
  11318. "RESOURCEUNAVAIL",
  11319. "REQUESTOVERRUN", // 0x90000020
  11320. "STRUCTURETOOSMALL",
  11321. "UNINITIALIZED",
  11322. "REINIT"
  11323. };
  11324. char *aszTapiErrors[] =
  11325. {
  11326. "SUCCESS",
  11327. "DROPPED",
  11328. "NOREQUESTRECIPIENT",
  11329. "REQUESTQUEUEFULL",
  11330. "INVALDESTADDRESS",
  11331. "INVALWINDOWHANDLE",
  11332. "INVALDEVICECLASS",
  11333. "INVALDEVICEID",
  11334. "DEVICECLASSUNAVAIL",
  11335. "DEVICEIDUNAVAIL",
  11336. "DEVICEINUSE",
  11337. "DESTBUSY",
  11338. "DESTNOANSWER",
  11339. "DESTUNAVAIL",
  11340. "UNKNOWNWINHANDLE",
  11341. "UNKNOWNREQUESTID",
  11342. "REQUESTFAILED",
  11343. "REQUESTCANCELLED",
  11344. "INVALPOINTER"
  11345. };
  11346. char *
  11347. PASCAL
  11348. MapResultCodeToText(
  11349. LONG lResult,
  11350. char *pszResult
  11351. )
  11352. {
  11353. if (lResult == 0)
  11354. {
  11355. wsprintf (pszResult, "SUCCESS");
  11356. }
  11357. else if (lResult > 0)
  11358. {
  11359. wsprintf (pszResult, "x%x (completing async)", lResult);
  11360. }
  11361. else if (((DWORD) lResult) <= LINEERR_DIALVOICEDETECT)
  11362. {
  11363. lResult &= 0x0fffffff;
  11364. wsprintf (pszResult, "LINEERR_%s", aszLineErrors[lResult]);
  11365. }
  11366. else if (((DWORD) lResult) <= PHONEERR_REINIT)
  11367. {
  11368. if (((DWORD) lResult) >= PHONEERR_ALLOCATED)
  11369. {
  11370. lResult &= 0x0fffffff;
  11371. wsprintf (pszResult, "PHONEERR_%s", aszPhoneErrors[lResult]);
  11372. }
  11373. else
  11374. {
  11375. goto MapResultCodeToText_badErrorCode;
  11376. }
  11377. }
  11378. else if (((DWORD) lResult) <= ((DWORD) TAPIERR_DROPPED) &&
  11379. ((DWORD) lResult) >= ((DWORD) TAPIERR_INVALPOINTER))
  11380. {
  11381. lResult = ~lResult + 1;
  11382. wsprintf (pszResult, "TAPIERR_%s", aszTapiErrors[lResult]);
  11383. }
  11384. else
  11385. {
  11386. MapResultCodeToText_badErrorCode:
  11387. wsprintf (pszResult, "inval error value (x%x)");
  11388. }
  11389. return pszResult;
  11390. }
  11391. #endif
  11392. #if DBG
  11393. void
  11394. DumpMemoryList()
  11395. {
  11396. PMYMEMINFO pHold;
  11397. if (gpMemFirst == NULL)
  11398. {
  11399. LOG((TL_ERROR, "All memory deallocated"));
  11400. return;
  11401. }
  11402. pHold = gpMemFirst;
  11403. while (pHold)
  11404. {
  11405. LOG((TL_ERROR, "DumpMemoryList: %p not freed - LINE %d FILE %s!", pHold+1, pHold->dwLine, pHold->pszFile));
  11406. pHold = pHold->pNext;
  11407. }
  11408. LOG((TL_ERROR, "MEMORY LEAKS ALMOST ALWAYS INDICATE A REFERENCE COUNT PROBLEM"));
  11409. LOG((TL_ERROR, "...except for the leaks in client.cpp"));
  11410. if (gbBreakOnLeak)
  11411. {
  11412. DebugBreak();
  11413. }
  11414. }
  11415. #endif
  11416. HRESULT
  11417. LineCreateAgent(
  11418. HLINE hLine,
  11419. PWSTR pszAgentID,
  11420. PWSTR pszAgentPIN,
  11421. LPHAGENT lphAgent // Return value
  11422. )
  11423. {
  11424. DWORD hpAgentHandle = CreateHandleTableEntry((ULONG_PTR)lphAgent);
  11425. //
  11426. // the agent handle is filled when callback is called. until then, clear its value
  11427. //
  11428. *lphAgent = 0;
  11429. FUNC_ARGS funcArgs =
  11430. {
  11431. MAKELONG (LINE_FUNC | ASYNC | 5, lCreateAgent),
  11432. {
  11433. GetFunctionIndex(lineDevSpecificPostProcess),
  11434. (ULONG_PTR) hLine,
  11435. (ULONG_PTR) pszAgentID,
  11436. (ULONG_PTR) pszAgentPIN,
  11437. hpAgentHandle,
  11438. },
  11439. {
  11440. Dword,
  11441. Dword,
  11442. lpszW,
  11443. lpszW,
  11444. Dword
  11445. }
  11446. };
  11447. if ( NULL == pszAgentID )
  11448. {
  11449. funcArgs.Args[2] = TAPI_NO_DATA;
  11450. funcArgs.ArgTypes[2] = Dword;
  11451. }
  11452. if ( NULL == pszAgentPIN )
  11453. {
  11454. funcArgs.Args[3] = TAPI_NO_DATA;
  11455. funcArgs.ArgTypes[3] = Dword;
  11456. }
  11457. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineCreateAgent"));
  11458. //
  11459. // if failed, delete the handle table entry now. otherwise it will be deleted by the callback
  11460. //
  11461. if (FAILED(hr))
  11462. {
  11463. DeleteHandleTableEntry(hpAgentHandle);
  11464. }
  11465. return hr;
  11466. }
  11467. LONG
  11468. WINAPI
  11469. lineSetAgentMeasurementPeriod(
  11470. HLINE hLine,
  11471. HAGENT hAgent,
  11472. DWORD dwMeasurementPeriod
  11473. )
  11474. {
  11475. FUNC_ARGS funcArgs =
  11476. {
  11477. MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentMeasurementPeriod),
  11478. {
  11479. (ULONG_PTR) hLine,
  11480. (ULONG_PTR) hAgent,
  11481. (ULONG_PTR) dwMeasurementPeriod
  11482. },
  11483. {
  11484. Dword,
  11485. Dword,
  11486. Dword
  11487. }
  11488. };
  11489. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentMeasurementPeriod"));
  11490. }
  11491. LONG
  11492. WINAPI
  11493. lineGetAgentInfo(
  11494. HLINE hLine,
  11495. HAGENT hAgent,
  11496. LPLINEAGENTINFO lpAgentInfo // Returned structure
  11497. )
  11498. {
  11499. DWORD hpAgentInfo = CreateHandleTableEntry((ULONG_PTR)lpAgentInfo);
  11500. FUNC_ARGS funcArgs =
  11501. {
  11502. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentInfo),
  11503. {
  11504. GetFunctionIndex(lineDevSpecificPostProcess),
  11505. (ULONG_PTR) hLine,
  11506. (ULONG_PTR) hAgent,
  11507. hpAgentInfo, // pass the actual ptr (for ppproc)
  11508. (ULONG_PTR) lpAgentInfo // pass data
  11509. },
  11510. {
  11511. Dword,
  11512. Dword,
  11513. Dword,
  11514. Dword,
  11515. lpGet_Struct
  11516. }
  11517. };
  11518. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetAgentInfo"));
  11519. if (FAILED(hr))
  11520. {
  11521. DeleteHandleTableEntry(hpAgentInfo);
  11522. }
  11523. return hr;
  11524. }
  11525. HRESULT
  11526. LineCreateAgentSession(
  11527. HLINE hLine,
  11528. HAGENT hAgent,
  11529. PWSTR pszAgentPIN,
  11530. DWORD dwWorkingAddressID,
  11531. LPGUID lpGroupID,
  11532. HAGENTSESSION *phAgentSession // Return value
  11533. )
  11534. {
  11535. DWORD hpAgentSession = CreateHandleTableEntry((ULONG_PTR)phAgentSession);
  11536. FUNC_ARGS funcArgs =
  11537. {
  11538. MAKELONG (LINE_FUNC | ASYNC | 8, lCreateAgentSession),
  11539. {
  11540. GetFunctionIndex(lineDevSpecificPostProcess),
  11541. (ULONG_PTR) hLine,
  11542. (ULONG_PTR) hAgent,
  11543. (ULONG_PTR) pszAgentPIN,
  11544. (ULONG_PTR) dwWorkingAddressID,
  11545. (ULONG_PTR) lpGroupID, // GroupID GUID
  11546. (ULONG_PTR) sizeof(GUID), // GroupID GUID (size)
  11547. hpAgentSession
  11548. },
  11549. {
  11550. Dword,
  11551. Dword,
  11552. Dword,
  11553. lpszW,
  11554. Dword,
  11555. lpSet_SizeToFollow, // GroupID GUID
  11556. Size, // GroupID GUID
  11557. Dword
  11558. }
  11559. };
  11560. if ( NULL == pszAgentPIN )
  11561. {
  11562. funcArgs.Args[3] = TAPI_NO_DATA;
  11563. funcArgs.ArgTypes[3] = Dword;
  11564. }
  11565. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineCreateAgentSession"));
  11566. //
  11567. // if we failed, remove handle table entry now. otherwise it will be
  11568. // removed by the callback
  11569. //
  11570. if (FAILED(hr))
  11571. {
  11572. DeleteHandleTableEntry(hpAgentSession);
  11573. }
  11574. return hr;
  11575. }
  11576. LONG
  11577. WINAPI
  11578. lineGetAgentSessionInfo(
  11579. HLINE hLine,
  11580. HAGENTSESSION hAgentSession,
  11581. LPLINEAGENTSESSIONINFO lpAgentSessionInfo // Returned structure
  11582. )
  11583. {
  11584. DWORD hpAgentSessionInfo = CreateHandleTableEntry((ULONG_PTR)lpAgentSessionInfo);
  11585. FUNC_ARGS funcArgs =
  11586. {
  11587. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionInfo),
  11588. {
  11589. GetFunctionIndex(lineDevSpecificPostProcess),
  11590. (ULONG_PTR) hLine,
  11591. (ULONG_PTR) hAgentSession,
  11592. hpAgentSessionInfo, // pass the actual ptr (for ppproc)
  11593. (ULONG_PTR) lpAgentSessionInfo // pass data
  11594. },
  11595. {
  11596. Dword,
  11597. Dword,
  11598. Dword,
  11599. Dword,
  11600. lpGet_Struct
  11601. }
  11602. };
  11603. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetAgentSessionInfo"));
  11604. //
  11605. // if failed, clear handle table now. otherwise the callback will do this.
  11606. //
  11607. if (FAILED(hr))
  11608. {
  11609. DeleteHandleTableEntry(hpAgentSessionInfo);
  11610. }
  11611. return hr;
  11612. }
  11613. LONG
  11614. WINAPI
  11615. lineSetAgentSessionState(
  11616. HLINE hLine,
  11617. HAGENTSESSION hAgentSession,
  11618. DWORD dwAgentState,
  11619. DWORD dwNextAgentState
  11620. )
  11621. {
  11622. FUNC_ARGS funcArgs =
  11623. {
  11624. MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentSessionState),
  11625. {
  11626. (ULONG_PTR) hLine,
  11627. (ULONG_PTR) hAgentSession,
  11628. dwAgentState,
  11629. dwNextAgentState
  11630. },
  11631. {
  11632. Dword,
  11633. Dword,
  11634. Dword,
  11635. Dword
  11636. }
  11637. };
  11638. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetAgentSessionState"));
  11639. }
  11640. LONG
  11641. WINAPI
  11642. lineSetQueueMeasurementPeriod(
  11643. HLINE hLine,
  11644. DWORD dwQueueID,
  11645. DWORD dwMeasurementPeriod
  11646. )
  11647. {
  11648. FUNC_ARGS funcArgs =
  11649. {
  11650. MAKELONG (LINE_FUNC | ASYNC | 3, lSetQueueMeasurementPeriod),
  11651. {
  11652. (ULONG_PTR) hLine,
  11653. dwQueueID,
  11654. dwMeasurementPeriod
  11655. },
  11656. {
  11657. Dword,
  11658. Dword,
  11659. Dword
  11660. }
  11661. };
  11662. return mapTAPIErrorCode(DOFUNC (&funcArgs, "lineSetQueueMeasurementPeriod"));
  11663. }
  11664. LONG
  11665. WINAPI
  11666. lineGetQueueInfo(
  11667. HLINE hLine,
  11668. DWORD dwQueueID,
  11669. LPLINEQUEUEINFO lpQueueInfo // Returned structure
  11670. )
  11671. {
  11672. DWORD hpQueueInfo = CreateHandleTableEntry((ULONG_PTR)lpQueueInfo);
  11673. FUNC_ARGS funcArgs =
  11674. {
  11675. MAKELONG (LINE_FUNC | ASYNC | 5, lGetQueueInfo),
  11676. {
  11677. GetFunctionIndex(lineDevSpecificPostProcess),
  11678. (ULONG_PTR) hLine,
  11679. dwQueueID,
  11680. hpQueueInfo, // pass the actual ptr (for ppproc)
  11681. (ULONG_PTR) lpQueueInfo // pass data
  11682. },
  11683. {
  11684. Dword,
  11685. Dword,
  11686. Dword,
  11687. Dword,
  11688. lpGet_Struct
  11689. }
  11690. };
  11691. HRESULT hr = mapTAPIErrorCode(DOFUNC (&funcArgs, "lineGetQueueInfo"));
  11692. //
  11693. // if we failed, cleanup now. otherwise the callback will.
  11694. //
  11695. if (FAILED(hr))
  11696. {
  11697. DeleteHandleTableEntry(hpQueueInfo);
  11698. }
  11699. return hr;
  11700. }
  11701. // Proxy message - LINEPROXYREQUEST_GETGROUPLIST : struct - GetGroupList
  11702. HRESULT
  11703. LineGetGroupList(
  11704. HLINE hLine,
  11705. LPLINEAGENTGROUPLIST * ppGroupList // Returned structure
  11706. )
  11707. {
  11708. HRESULT hr = S_OK;
  11709. long lResult;
  11710. DWORD dwSize = sizeof(LINEAGENTGROUPLIST) + 500;
  11711. *ppGroupList = (LPLINEAGENTGROUPLIST) ClientAlloc( dwSize );
  11712. if (NULL == *ppGroupList)
  11713. {
  11714. return E_OUTOFMEMORY;
  11715. }
  11716. (*ppGroupList)->dwTotalSize = dwSize;
  11717. DWORD hpGroupList = CreateHandleTableEntry( (ULONG_PTR)*ppGroupList );
  11718. FUNC_ARGS funcArgs =
  11719. {
  11720. MAKELONG (LINE_FUNC | ASYNC | 4, lGetGroupList),
  11721. {
  11722. GetFunctionIndex(lineDevSpecificPostProcess),
  11723. (ULONG_PTR) hLine,
  11724. hpGroupList, // pass the actual ptr (for ppproc)
  11725. (ULONG_PTR) *ppGroupList // pass data
  11726. },
  11727. {
  11728. Dword,
  11729. Dword,
  11730. Dword,
  11731. lpGet_Struct,
  11732. }
  11733. };
  11734. while (TRUE)
  11735. {
  11736. lResult = DOFUNC (&funcArgs, "lineGetGroupList");
  11737. if (lResult > 0) // async reply
  11738. {
  11739. hr = WaitForReply( lResult );
  11740. if ((hr == S_OK))
  11741. {
  11742. if (((*ppGroupList)->dwNeededSize > (*ppGroupList)->dwTotalSize))
  11743. {
  11744. // didnt Work , adjust buffer size & try again
  11745. LOG((TL_INFO, "lineGetGroupList failed - buffer too small"));
  11746. dwSize = (*ppGroupList)->dwNeededSize;
  11747. DeleteHandleTableEntry(hpGroupList);
  11748. hpGroupList = 0;
  11749. ClientFree( *ppGroupList );
  11750. *ppGroupList = NULL;
  11751. *ppGroupList = (LPLINEAGENTGROUPLIST) ClientAlloc( dwSize );
  11752. if (*ppGroupList == NULL)
  11753. {
  11754. LOG((TL_ERROR, "lineGetGroupList - repeat ClientAlloc failed"));
  11755. hr = E_OUTOFMEMORY;
  11756. break;
  11757. }
  11758. else
  11759. {
  11760. (*ppGroupList)->dwTotalSize = dwSize;
  11761. _ASSERTE(0 == hpGroupList);
  11762. hpGroupList = CreateHandleTableEntry((ULONG_PTR)*ppGroupList);
  11763. if (0 == hpGroupList)
  11764. {
  11765. LOG((TL_ERROR, "lineGetGroupList - failed to create a handle"));
  11766. ClientFree( *ppGroupList );
  11767. hr = E_OUTOFMEMORY;
  11768. break;
  11769. }
  11770. funcArgs.Args[2] = hpGroupList;
  11771. funcArgs.Args[3] = (ULONG_PTR)*ppGroupList;
  11772. }
  11773. }
  11774. else
  11775. {
  11776. //
  11777. // WaitForReply succeeded and the buffer was big enough
  11778. //
  11779. break;
  11780. }
  11781. } // WaitforReply succeeded
  11782. else
  11783. {
  11784. //
  11785. // WaitForReply failed
  11786. //
  11787. LOG((TL_ERROR, "lineGetGroupList - WaitForReply failed"));
  11788. break;
  11789. }
  11790. }
  11791. else // failed sync
  11792. {
  11793. LOG((TL_ERROR, "lineGetGroupList - failed sync"));
  11794. hr = mapTAPIErrorCode(lResult);
  11795. break;
  11796. }
  11797. } // end while(TRUE)
  11798. DeleteHandleTableEntry(hpGroupList);
  11799. hpGroupList = 0;
  11800. LOG((TL_ERROR, "lineGetGroupList - completed hr %lx", hr));
  11801. return hr;
  11802. }
  11803. HRESULT
  11804. lineGetQueueList(
  11805. HLINE hLine,
  11806. LPGUID lpGroupID,
  11807. LPLINEQUEUELIST * ppQueueList // Returned structure
  11808. )
  11809. {
  11810. LOG((TL_TRACE, "lineGetQueueList - enter"));
  11811. HRESULT hr = S_OK;
  11812. long lResult;
  11813. DWORD dwSize = sizeof(LINEQUEUELIST) + 500;
  11814. *ppQueueList = (LPLINEQUEUELIST) ClientAlloc( dwSize );
  11815. if (NULL == *ppQueueList)
  11816. {
  11817. return E_OUTOFMEMORY;
  11818. }
  11819. (*ppQueueList)->dwTotalSize = dwSize;
  11820. DWORD hpQueueRequest = CreateHandleTableEntry((ULONG_PTR)*ppQueueList);
  11821. FUNC_ARGS funcArgs =
  11822. {
  11823. MAKELONG (LINE_FUNC | ASYNC | 6, lGetQueueList),
  11824. {
  11825. GetFunctionIndex(lineDevSpecificPostProcess),
  11826. (ULONG_PTR) hLine,
  11827. (ULONG_PTR) lpGroupID, // GroupID GUID
  11828. (ULONG_PTR) sizeof(GUID), // GroupID GUID (size)
  11829. hpQueueRequest, // pass the actual ptr (for ppproc)
  11830. (ULONG_PTR) *ppQueueList // pass data
  11831. },
  11832. {
  11833. Dword,
  11834. Dword,
  11835. lpSet_SizeToFollow, // GroupID GUID
  11836. Size, // GroupID GUID (size)
  11837. Dword,
  11838. lpGet_Struct
  11839. }
  11840. };
  11841. while (TRUE)
  11842. {
  11843. lResult = DOFUNC (&funcArgs, "lineGetQueueList");
  11844. if (lResult > 0)
  11845. {
  11846. hr = WaitForReply( lResult );
  11847. if ((hr == S_OK) )
  11848. {
  11849. if ((*ppQueueList)->dwNeededSize > (*ppQueueList)->dwTotalSize)
  11850. {
  11851. // didnt Work , adjust buffer size & try again
  11852. LOG((TL_INFO, "lineGetQueueList failed - buffer to small"));
  11853. dwSize = (*ppQueueList)->dwNeededSize;
  11854. DeleteHandleTableEntry(hpQueueRequest);
  11855. hpQueueRequest = 0;
  11856. ClientFree( *ppQueueList );
  11857. *ppQueueList = NULL;
  11858. *ppQueueList = (LPLINEQUEUELIST) ClientAlloc( dwSize );
  11859. if (*ppQueueList == NULL)
  11860. {
  11861. LOG((TL_ERROR, "lineGetQueueList - repeat ClientAlloc failed"));
  11862. hr = E_OUTOFMEMORY;
  11863. break;
  11864. }
  11865. else
  11866. {
  11867. hpQueueRequest = CreateHandleTableEntry((ULONG_PTR)*ppQueueList);
  11868. (*ppQueueList)->dwTotalSize = dwSize;
  11869. funcArgs.Args[4] = hpQueueRequest;
  11870. funcArgs.Args[5] = (ULONG_PTR)*ppQueueList;
  11871. }
  11872. } // buffer too small
  11873. else
  11874. {
  11875. //
  11876. // everything is fine and dandy. nothing else left to do.
  11877. //
  11878. break;
  11879. }
  11880. }
  11881. else
  11882. {
  11883. //
  11884. // error case. we have hr, break out. we should really not be
  11885. // here, since we checked lResult > 0 above
  11886. //
  11887. break;
  11888. }
  11889. }
  11890. else // failed sync
  11891. {
  11892. LOG((TL_ERROR, "lineGetQueueList - failed sync"));
  11893. hr = mapTAPIErrorCode(lResult);
  11894. break;
  11895. }
  11896. } // end while(TRUE)
  11897. DeleteHandleTableEntry(hpQueueRequest);
  11898. hpQueueRequest = 0;
  11899. LOG((TL_TRACE, "lineGetQueueList - finished hr = %lx", hr));
  11900. return hr;
  11901. }
  11902. LONG
  11903. WINAPI
  11904. lineGetAgentSessionList(
  11905. HLINE hLine,
  11906. HAGENT hAgent,
  11907. LPLINEAGENTSESSIONLIST * ppSessionList // Returned structure
  11908. )
  11909. {
  11910. HRESULT hr = S_OK;
  11911. long lResult;
  11912. DWORD dwSize = sizeof(LINEAGENTSESSIONLIST) + 500;
  11913. *ppSessionList = (LPLINEAGENTSESSIONLIST) ClientAlloc( dwSize );
  11914. if (NULL == *ppSessionList)
  11915. {
  11916. return E_OUTOFMEMORY;
  11917. }
  11918. (*ppSessionList)->dwTotalSize = dwSize;
  11919. DWORD hpSessionList = CreateHandleTableEntry((ULONG_PTR)*ppSessionList);
  11920. FUNC_ARGS funcArgs =
  11921. {
  11922. MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionList),
  11923. {
  11924. GetFunctionIndex(lineDevSpecificPostProcess),
  11925. (ULONG_PTR) hLine,
  11926. (ULONG_PTR) hAgent,
  11927. hpSessionList, // pass the actual ptr (for ppproc)
  11928. (ULONG_PTR) *ppSessionList // pass data
  11929. },
  11930. {
  11931. Dword,
  11932. Dword,
  11933. Dword,
  11934. Dword,
  11935. lpGet_Struct
  11936. }
  11937. };
  11938. while (TRUE)
  11939. {
  11940. lResult = DOFUNC (&funcArgs, "lineGetAgentSessionList");
  11941. if (lResult > 0)
  11942. {
  11943. hr = WaitForReply( lResult );
  11944. if ((hr == S_OK) && ((*ppSessionList)->dwNeededSize > (*ppSessionList)->dwTotalSize))
  11945. {
  11946. // didnt Work , adjust buffer size & try again
  11947. LOG((TL_INFO, "lineGetAgentSessionList failed - buffer to small"));
  11948. dwSize = (*ppSessionList)->dwNeededSize;
  11949. DeleteHandleTableEntry(hpSessionList);
  11950. hpSessionList = 0;
  11951. ClientFree( *ppSessionList );
  11952. *ppSessionList = NULL;
  11953. *ppSessionList = (LPLINEAGENTSESSIONLIST) ClientAlloc( dwSize );
  11954. if (*ppSessionList == NULL)
  11955. {
  11956. LOG((TL_ERROR, "lineGetAgentSessionList - repeat ClientAlloc failed"));
  11957. hr = E_OUTOFMEMORY;
  11958. break;
  11959. }
  11960. else
  11961. {
  11962. hpSessionList = CreateHandleTableEntry((ULONG_PTR)*ppSessionList);
  11963. (*ppSessionList)->dwTotalSize = dwSize;
  11964. funcArgs.Args[3] = hpSessionList;
  11965. funcArgs.Args[4] = (ULONG_PTR)*ppSessionList;
  11966. }
  11967. }
  11968. else
  11969. {
  11970. //
  11971. // either hr is not ok or hr is ok and the buffer was sufficient.
  11972. // in both cases, nothing much we need to do here, so break out
  11973. //
  11974. break;
  11975. }
  11976. }
  11977. else // failed sync
  11978. {
  11979. LOG((TL_ERROR, "lineGetAgentSessionListt - failed sync"));
  11980. hr = mapTAPIErrorCode(lResult);
  11981. break;
  11982. }
  11983. } // end while(TRUE)
  11984. DeleteHandleTableEntry(hpSessionList);
  11985. hpSessionList = 0;
  11986. LOG((TL_TRACE, "lineGetAgentSessionListt - finish. hr = %lx", hr));
  11987. return hr;
  11988. }
  11989. HRESULT
  11990. LineCreateMSPInstance(
  11991. HLINE hLine,
  11992. DWORD dwAddressID
  11993. )
  11994. {
  11995. FUNC_ARGS funcArgs =
  11996. {
  11997. MAKELONG (LINE_FUNC | SYNC | 2, lCreateMSPInstance),
  11998. {
  11999. (ULONG_PTR) hLine,
  12000. dwAddressID
  12001. },
  12002. {
  12003. Dword,
  12004. Dword
  12005. }
  12006. };
  12007. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCreateMSPInstance") );
  12008. }
  12009. HRESULT
  12010. LineCloseMSPInstance(
  12011. HLINE hLine
  12012. )
  12013. {
  12014. FUNC_ARGS funcArgs =
  12015. {
  12016. MAKELONG (LINE_FUNC | SYNC | 1, lCloseMSPInstance),
  12017. {
  12018. (ULONG_PTR) hLine
  12019. },
  12020. {
  12021. Dword
  12022. }
  12023. };
  12024. return mapTAPIErrorCode( DOFUNC (&funcArgs, "lineCloseMSPInstance") );
  12025. }
  12026. /**/
  12027. HRESULT mapTAPIErrorCode(long lErrorCode)
  12028. {
  12029. HRESULT hr;
  12030. // Check if it's async
  12031. if (lErrorCode > 0)
  12032. {
  12033. hr = lErrorCode;
  12034. }
  12035. else
  12036. {
  12037. switch(lErrorCode)
  12038. {
  12039. //
  12040. // Sucess codes - ie 0
  12041. //
  12042. case TAPI_SUCCESS:
  12043. // case LINEERR_SUCCESS: // The operation completed successfully.
  12044. // case PHONEERR_SUCCESS: // The operation completed successfully
  12045. // case TAPIERR_CONNECTED: // The request was accepted
  12046. hr = S_OK;
  12047. break;
  12048. //
  12049. // Serious errors - Somethings very wrong in TAPI3 !
  12050. //
  12051. // Bad handles !!
  12052. case LINEERR_INVALAPPHANDLE: // Invalid TAPI line application handle
  12053. case LINEERR_INVALCALLHANDLE: // Invalid call handle
  12054. case LINEERR_INVALCONFCALLHANDLE: // Invalid conference call handle
  12055. case LINEERR_INVALCONSULTCALLHANDLE: // Invalid consultation call handle
  12056. case LINEERR_INVALDEVICEHANDLE: // Invalid device handle
  12057. case LINEERR_INVALLINEHANDLE: // Invalid line handle
  12058. case LINEERR_BADDEVICEID: // Invalid line device ID
  12059. case LINEERR_INCOMPATIBLEAPIVERSION: // Incompatible API version
  12060. case LINEERR_INVALADDRESSID: // Invalid address ID
  12061. case LINEERR_INVALADDRESSMODE: // Invalid address mode
  12062. case LINEERR_INVALAPPNAME: // Invalid application name
  12063. case LINEERR_INVALCALLSELECT: // Invalid call select parameter
  12064. case LINEERR_INVALEXTVERSION: // Invalid extension version
  12065. case LINEERR_INVALTERMINALID: // Invalid terminal ID
  12066. case LINEERR_INVALTERMINALMODE: // Invalid terminal mode
  12067. case LINEERR_LINEMAPPERFAILED: // No device matches the specified requirements
  12068. case LINEERR_UNINITIALIZED: // The telephony service has not been initialized
  12069. case LINEERR_NOMULTIPLEINSTANCE: // You cannot have two instances of the same service provider
  12070. case PHONEERR_INVALAPPHANDLE: // Invalid TAPI phone application handle
  12071. case PHONEERR_INVALPHONEHANDLE: // Invalid phone handle
  12072. case PHONEERR_BADDEVICEID: // Invalid phone device ID
  12073. case PHONEERR_INCOMPATIBLEAPIVERSION:// Incompatible API version
  12074. case PHONEERR_INVALEXTVERSION: // Invalid extension version
  12075. case PHONEERR_INVALAPPNAME: // Invalid application name
  12076. case PHONEERR_UNINITIALIZED: // The telephony service has not been initialized
  12077. case TAPIERR_INVALDEVICEID: // Invalid device ID
  12078. case TAPIERR_UNKNOWNWINHANDLE: // Unknown window handle
  12079. case TAPIERR_UNKNOWNREQUESTID: // Unknown request ID
  12080. case TAPIERR_INVALWINDOWHANDLE: // Invalid window handle
  12081. // Memory/ Allocation errors
  12082. case LINEERR_STRUCTURETOOSMALL: // The application failed to allocate sufficient memory for the
  12083. // minimum structure size
  12084. case PHONEERR_STRUCTURETOOSMALL: // The application failed to allocate sufficient memory for the
  12085. // minimum structure size
  12086. //_ASSERTE( 0 );
  12087. hr = E_UNEXPECTED;
  12088. break;
  12089. case PHONEERR_INIFILECORRUPT: // The TAPI configuration information is unusable
  12090. case LINEERR_INIFILECORRUPT: // The TAPI configuration information is unusable
  12091. hr = TAPI_E_REGISTRY_SETTING_CORRUPT;
  12092. break;
  12093. // Bad Pointers
  12094. case LINEERR_INVALPOINTER: // Invalid pointer
  12095. case PHONEERR_INVALPOINTER: // Invalid pointer
  12096. case TAPIERR_INVALPOINTER: // Invalid pointer
  12097. hr = E_POINTER;
  12098. break;
  12099. //
  12100. // Unexpected Errors
  12101. //
  12102. case LINEERR_OPERATIONFAILED: // The operation failed for unspecified reasons
  12103. case PHONEERR_OPERATIONFAILED: // The operation failed for unspecified reasons
  12104. case LINEERR_INCOMPATIBLEEXTVERSION: // Incompatible extension version
  12105. case PHONEERR_INCOMPATIBLEEXTVERSION:// Incompatible extension version
  12106. hr = TAPI_E_OPERATIONFAILED;
  12107. break;
  12108. case LINEERR_ALLOCATED: // The line device is already in use
  12109. case PHONEERR_ALLOCATED: // The phone device is already in use
  12110. hr = TAPI_E_ALLOCATED;
  12111. break;
  12112. case LINEERR_BEARERMODEUNAVAIL: // The requested bearer mode is unavailable
  12113. case LINEERR_INVALBEARERMODE: // Invalid bearer mode
  12114. hr = TAPI_E_INVALMODE;
  12115. break;
  12116. case LINEERR_CALLUNAVAIL: // No call appearance available
  12117. hr = TAPI_E_CALLUNAVAIL;
  12118. break;
  12119. case LINEERR_COMPLETIONOVERRUN: // Too many call completions outstanding
  12120. hr = TAPI_E_COMPLETIONOVERRUN;
  12121. break;
  12122. case LINEERR_CONFERENCEFULL: // The conference is full
  12123. hr = TAPI_E_CONFERENCEFULL;
  12124. break;
  12125. case LINEERR_DIALBILLING: // The '$' dial modifier is not supported
  12126. case LINEERR_DIALDIALTONE: // The 'W' dial modifier is not supported
  12127. case LINEERR_DIALPROMPT: // The '?' dial modifier is not supported
  12128. case LINEERR_DIALQUIET: // The '@' dial modifier is not supported
  12129. case LINEERR_DIALVOICEDETECT: // The ':' dial modifier is not supported
  12130. hr = TAPI_E_DIALMODIFIERNOTSUPPORTED;
  12131. break;
  12132. case LINEERR_RESOURCEUNAVAIL: // A resource needed to fulfill the request is not available
  12133. case PHONEERR_RESOURCEUNAVAIL: // A resource needed to fulfill the request is not available
  12134. hr = TAPI_E_RESOURCEUNAVAIL;
  12135. break;
  12136. case LINEERR_INUSE: // The line device is already in use
  12137. case PHONEERR_INUSE: // The phone device is already in use
  12138. case TAPIERR_DEVICEINUSE: // The device is already in use
  12139. hr = TAPI_E_INUSE;
  12140. break;
  12141. case LINEERR_INVALADDRESS: // The phone number is invalid or not properly formatted
  12142. case TAPIERR_INVALDESTADDRESS: // The phone number is invalid or improperly formatted
  12143. hr = TAPI_E_INVALADDRESS;
  12144. break;
  12145. case LINEERR_INVALADDRESSSTATE: // Operation not permitted in current address state
  12146. case LINEERR_INVALLINESTATE: // Operation not permitted in current line state
  12147. case PHONEERR_INVALPHONESTATE: // Operation not permitted in current phone state
  12148. hr = TAPI_E_INVALADDRESSSTATE;
  12149. break;
  12150. case LINEERR_INVALADDRESSTYPE: // The specified address type is not supported by this address.
  12151. hr = TAPI_E_INVALADDRESSTYPE;
  12152. break;
  12153. case LINEERR_INVALCALLCOMPLMODE: // Invalid call completion mode
  12154. hr = TAPI_E_INVALMODE;
  12155. break;
  12156. case LINEERR_INVALCALLPARAMS: // Invalid LINECALLPARAMS structure
  12157. hr = TAPI_E_INVALCALLPARAMS;
  12158. break;
  12159. case LINEERR_INVALCALLPRIVILEGE: // Invalid call privilege
  12160. case LINEERR_INVALPRIVSELECT: // Invalid call privilege selection
  12161. hr = TAPI_E_INVALCALLPRIVILEGE;
  12162. break;
  12163. case LINEERR_INVALCALLSTATE: // Operation not permitted in current call state
  12164. hr = TAPI_E_INVALCALLSTATE;
  12165. break;
  12166. case LINEERR_INVALCALLSTATELIST: // Invalid call state list
  12167. hr = TAPI_E_INVALLIST;
  12168. break;
  12169. case LINEERR_INVALCARD: // Invalid calling card ID
  12170. hr = TAPI_E_INVALCARD;
  12171. break;
  12172. case LINEERR_INVALCOMPLETIONID: // Invalid call completion ID
  12173. hr = TAPI_E_INVALCOMPLETIONID;
  12174. break;
  12175. case LINEERR_INVALCOUNTRYCODE: // Invalid country code
  12176. hr = TAPI_E_INVALCOUNTRYCODE;
  12177. break;
  12178. case LINEERR_INVALDEVICECLASS: // Invalid device class identifier
  12179. case PHONEERR_INVALDEVICECLASS: // Invalid device class identifier
  12180. case TAPIERR_INVALDEVICECLASS:
  12181. case TAPIERR_DEVICECLASSUNAVAIL: // The device class is unavailable
  12182. case TAPIERR_DEVICEIDUNAVAIL: // The specified device is unavailable
  12183. hr = TAPI_E_INVALDEVICECLASS;
  12184. break;
  12185. case LINEERR_INVALDIALPARAMS: // Invalid dialing parameters
  12186. hr = TAPI_E_INVALDIALPARAMS;
  12187. break;
  12188. case LINEERR_INVALDIGITLIST: // Invalid digit list
  12189. hr = TAPI_E_INVALLIST;
  12190. break;
  12191. case LINEERR_INVALDIGITMODE: // Invalid digit mode
  12192. hr = TAPI_E_INVALMODE;
  12193. break;
  12194. case LINEERR_INVALDIGITS: // Invalid digits
  12195. hr = TAPI_E_INVALDIGITS;
  12196. break;
  12197. case LINEERR_INVALGROUPID: // Invalid group pickup ID
  12198. hr = TAPI_E_INVALGROUPID;
  12199. break;
  12200. case LINEERR_INVALLOCATION: // Invalid location ID
  12201. hr = TAPI_E_INVALLOCATION;
  12202. break;
  12203. case LINEERR_INVALMEDIALIST: // Invalid media list
  12204. hr = TAPI_E_INVALLIST;
  12205. break;
  12206. case LINEERR_INVALMEDIAMODE: // Invalid media mode
  12207. hr = TAPI_E_INVALIDMEDIATYPE;
  12208. break;
  12209. case LINEERR_INVALMESSAGEID: // Invalid message ID
  12210. hr = TAPI_E_INVALMESSAGEID;
  12211. break;
  12212. case LINEERR_INVALPARAM: // Invalid parameter
  12213. hr = E_INVALIDARG;
  12214. break;
  12215. case LINEERR_INVALPARKID: // Invalid park ID
  12216. hr = TAPI_E_INVALPARKID;
  12217. break;
  12218. case LINEERR_INVALPARKMODE: // Invalid park mode
  12219. case PHONEERR_INVALPARAM: // Invalid parameter
  12220. hr = TAPI_E_INVALMODE;
  12221. break;
  12222. case LINEERR_INVALRATE: // Invalid rate
  12223. case LINEERR_RATEUNAVAIL: // The requested data rate is not available
  12224. hr = TAPI_E_INVALRATE;
  12225. break;
  12226. case LINEERR_INVALREQUESTMODE: // Invalid request mode
  12227. hr = TAPI_E_INVALMODE;
  12228. break;
  12229. case LINEERR_INVALTIMEOUT: // Invalid timeout value
  12230. hr = TAPI_E_INVALTIMEOUT;
  12231. break;
  12232. case LINEERR_INVALTONE: // Invalid tone
  12233. hr = TAPI_E_INVALTONE;
  12234. break;
  12235. case LINEERR_INVALTONELIST: // Invalid tone list
  12236. hr = TAPI_E_INVALLIST;
  12237. break;
  12238. case LINEERR_INVALTONEMODE: // Invalid tone mode
  12239. case LINEERR_INVALTRANSFERMODE: // Invalid transfer mode
  12240. case PHONEERR_INVALBUTTONMODE: // Invalid button mode
  12241. case PHONEERR_INVALHOOKSWITCHMODE: // Invalid hookswitch mode
  12242. case PHONEERR_INVALLAMPMODE: // Invalid lamp mode
  12243. case PHONEERR_INVALRINGMODE: // Invalid ring mode
  12244. hr = TAPI_E_INVALMODE;
  12245. break;
  12246. case LINEERR_NOCONFERENCE: // The call is not part of a conference
  12247. hr = TAPI_E_NOCONFERENCE;
  12248. break;
  12249. case LINEERR_NODEVICE: // The device was removed, or the device class is not recognized
  12250. case PHONEERR_NODEVICE: // The device was removed, or the device class is not recognized
  12251. hr = TAPI_E_NODEVICE;
  12252. break;
  12253. case LINEERR_NODRIVER: // The service provider was removed
  12254. case PHONEERR_NODRIVER: // The service provider was removed
  12255. hr = TAPI_E_NODRIVER;
  12256. break;
  12257. case LINEERR_NOMEM: // Insufficient memory available to complete the operation
  12258. case PHONEERR_NOMEM: // Insufficient memory available to complete the operation
  12259. hr = E_OUTOFMEMORY;
  12260. break;
  12261. case LINEERR_NOREQUEST: // No Assisted Telephony requests are pending
  12262. hr = TAPI_E_NOREQUEST;
  12263. break;
  12264. case LINEERR_NOTOWNER: // The application is does not have OWNER privilege on the call
  12265. case PHONEERR_NOTOWNER: // The application is does not have OWNER privilege on the phone
  12266. hr = TAPI_E_NOTOWNER;
  12267. break;
  12268. case LINEERR_NOTREGISTERED: // The application is not registered to handle requests
  12269. hr = TAPI_E_NOTREGISTERED;
  12270. break;
  12271. case LINEERR_OPERATIONUNAVAIL: // The operation is not supported by the underlying service provider
  12272. case PHONEERR_OPERATIONUNAVAIL: // The operation is not supported by the underlying service provider
  12273. hr = TAPI_E_NOTSUPPORTED;
  12274. break;
  12275. case LINEERR_REQUESTOVERRUN: // The request queue is already full
  12276. case PHONEERR_REQUESTOVERRUN: // The request queue is already full
  12277. hr= TAPI_E_REQUESTOVERRUN;
  12278. break;
  12279. case LINEERR_SERVICE_NOT_RUNNING: // The Telephony service could not be contacted
  12280. case PHONEERR_SERVICE_NOT_RUNNING: // The Telephony service could not be contacted
  12281. hr = TAPI_E_SERVICE_NOT_RUNNING;
  12282. break;
  12283. case LINEERR_TARGETNOTFOUND: // The call handoff failed because the specified target was not found
  12284. hr = TAPI_E_TARGETNOTFOUND;
  12285. break;
  12286. case LINEERR_TARGETSELF: // No higher priority target exists for the call handoff
  12287. hr = TAPI_E_TARGETSELF;
  12288. break;
  12289. case LINEERR_USERUSERINFOTOOBIG: // The amount of user-user info exceeds the maximum permitted
  12290. hr = TAPI_E_USERUSERINFOTOOBIG;
  12291. break;
  12292. case LINEERR_REINIT: // The operation cannot be completed until all TAPI applications
  12293. // call lineShutdown
  12294. case PHONEERR_REINIT: // The operation cannot be completed until all TAPI applications
  12295. hr = TAPI_E_REINIT;
  12296. break;
  12297. case LINEERR_ADDRESSBLOCKED: // You are not permitted to call this number
  12298. hr = TAPI_E_ADDRESSBLOCKED;
  12299. break;
  12300. case LINEERR_BILLINGREJECTED: // The calling card number or other billing information was rejected
  12301. hr = TAPI_E_BILLINGREJECTED;
  12302. break;
  12303. case LINEERR_INVALFEATURE: // Invalid device-specific feature
  12304. hr = TAPI_E_INVALFEATURE;
  12305. break;
  12306. case LINEERR_INVALAGENTID: // Invalid agent ID
  12307. hr = TAPI_E_CALLCENTER_INVALAGENTID;
  12308. break;
  12309. case LINEERR_INVALAGENTGROUP: // Invalid agent group
  12310. hr = TAPI_E_CALLCENTER_INVALAGENTGROUP;
  12311. break;
  12312. case LINEERR_INVALPASSWORD: // Invalid agent password
  12313. hr = TAPI_E_CALLCENTER_INVALPASSWORD;
  12314. break;
  12315. case LINEERR_INVALAGENTSTATE: // Invalid agent state
  12316. hr = TAPI_E_CALLCENTER_INVALAGENTSTATE;
  12317. break;
  12318. case LINEERR_INVALAGENTACTIVITY: // Invalid agent activity
  12319. hr = TAPI_E_CALLCENTER_INVALAGENTACTIVITY;
  12320. break;
  12321. case PHONEERR_INVALPRIVILEGE: // Invalid privilege
  12322. hr = TAPI_E_INVALPRIVILEGE;
  12323. break;
  12324. case PHONEERR_INVALBUTTONLAMPID: // Invalid button or lamp ID
  12325. hr = TAPI_E_INVALBUTTONLAMPID;
  12326. break;
  12327. case PHONEERR_INVALBUTTONSTATE: // Invalid button state
  12328. hr = TAPI_E_INVALBUTTONSTATE;
  12329. break;
  12330. case PHONEERR_INVALDATAID: // Invalid data segment ID
  12331. hr = TAPI_E_INVALDATAID;
  12332. break;
  12333. case PHONEERR_INVALHOOKSWITCHDEV: // Invalid hookswitch device ID
  12334. hr = TAPI_E_INVALHOOKSWITCHDEV;
  12335. break;
  12336. case TAPIERR_DROPPED: // The call was disconnected
  12337. hr = TAPI_E_DROPPED;
  12338. break;
  12339. case TAPIERR_NOREQUESTRECIPIENT: // No program is available to handle the request
  12340. hr = TAPI_E_NOREQUESTRECIPIENT;
  12341. break;
  12342. case TAPIERR_REQUESTQUEUEFULL: // The queue of call requests is full
  12343. hr = TAPI_E_REQUESTQUEUEFULL;
  12344. break;
  12345. case TAPIERR_DESTBUSY: // The called number is busy
  12346. hr = TAPI_E_DESTBUSY;
  12347. break;
  12348. case TAPIERR_DESTNOANSWER: // The called party does not answer
  12349. hr = TAPI_E_DESTNOANSWER;
  12350. break;
  12351. case TAPIERR_DESTUNAVAIL: // The called number could not be reached
  12352. hr = TAPI_E_DESTUNAVAIL;
  12353. break;
  12354. case TAPIERR_REQUESTFAILED: // The request failed for unspecified reasons
  12355. hr = TAPI_E_REQUESTFAILED;
  12356. break;
  12357. case TAPIERR_REQUESTCANCELLED: // The request was cancelled
  12358. hr = TAPI_E_REQUESTCANCELLED;
  12359. break;
  12360. default:
  12361. hr = E_FAIL;
  12362. break;
  12363. } // End switch(lErrorCode)
  12364. }
  12365. return hr;
  12366. }
  12367. HRESULT UnloadTapi32( BOOL bShutdown )
  12368. {
  12369. EnterCriticalSection( &gcsTapi32 );
  12370. if ( bShutdown )
  12371. {
  12372. if ( NULL == gpShutdown )
  12373. {
  12374. gpShutdown = (LINESHUTDOWNPROC)GetProcAddress(
  12375. ghTapi32,
  12376. "lineShutdown"
  12377. );
  12378. if ( NULL == gpShutdown )
  12379. {
  12380. LeaveCriticalSection( &gcsTapi32 );
  12381. return E_FAIL;
  12382. }
  12383. (gpShutdown)(ghLineApp);
  12384. }
  12385. }
  12386. ghLineApp = NULL;
  12387. gpShutdown = NULL;
  12388. gpInitialize = NULL;
  12389. if ( NULL != ghTapi32 )
  12390. {
  12391. FreeLibrary( ghTapi32 );
  12392. }
  12393. LeaveCriticalSection( &gcsTapi32 );
  12394. return S_OK;
  12395. }
  12396. HRESULT LoadTapi32( BOOL bInitialize )
  12397. {
  12398. HRESULT hr;
  12399. DWORD dwNumDevs;
  12400. DWORD dwAPIVersion = TAPI_CURRENT_VERSION;
  12401. EnterCriticalSection( &gcsTapi32 );
  12402. ghTapi32 = LoadLibrary("tapi32.dll");
  12403. //
  12404. // ll failed
  12405. //
  12406. if ( NULL == ghTapi32 )
  12407. {
  12408. LeaveCriticalSection( &gcsTapi32 );
  12409. return E_FAIL;
  12410. }
  12411. if ( bInitialize )
  12412. {
  12413. if ( NULL == gpInitialize )
  12414. {
  12415. gpInitialize = (LINEINITIALIZEPROC)GetProcAddress(
  12416. ghTapi32,
  12417. "lineInitializeExW"
  12418. );
  12419. if ( NULL == gpInitialize )
  12420. {
  12421. LOG((TL_ERROR, "LoadTapi32 - getprocaddres failed 1"));
  12422. LeaveCriticalSection( &gcsTapi32 );
  12423. UnloadTapi32( FALSE );
  12424. return E_FAIL;
  12425. }
  12426. }
  12427. LINEINITIALIZEEXPARAMS lei;
  12428. ZeroMemory( &lei, sizeof(lei) );
  12429. lei.dwTotalSize = sizeof(lei);
  12430. lei.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
  12431. hr = (gpInitialize)(
  12432. &ghLineApp,
  12433. NULL,
  12434. NULL,
  12435. L"tapi3helper",
  12436. &dwNumDevs,
  12437. &dwAPIVersion,
  12438. &lei
  12439. );
  12440. if ( !SUCCEEDED(hr) )
  12441. {
  12442. ghLineApp = NULL;
  12443. LOG((TL_ERROR, "LoadTapi32 - lineinit failed"));
  12444. LeaveCriticalSection( &gcsTapi32 );
  12445. UnloadTapi32( FALSE );
  12446. return mapTAPIErrorCode( hr );
  12447. }
  12448. }
  12449. LeaveCriticalSection( &gcsTapi32 );
  12450. return S_OK;
  12451. }
  12452. HRESULT TapiMakeCall(
  12453. BSTR pDestAddress,
  12454. BSTR pAppName,
  12455. BSTR pCalledParty,
  12456. BSTR pComment
  12457. )
  12458. {
  12459. HRESULT hr;
  12460. TAPIREQUESTMAKECALLPROC pTapiMakeCall;
  12461. hr = LoadTapi32( FALSE );
  12462. if ( !SUCCEEDED(hr) )
  12463. {
  12464. LOG((TL_ERROR, "Could not load TAPI32.DLL"));
  12465. return hr;
  12466. }
  12467. pTapiMakeCall = (TAPIREQUESTMAKECALLPROC)GetProcAddress( ghTapi32, "tapiRequestMakeCallW" );
  12468. if ( NULL == pTapiMakeCall )
  12469. {
  12470. LOG((TL_ERROR, "Could not get the address of tapimakecall"));
  12471. UnloadTapi32( FALSE );
  12472. return E_FAIL;
  12473. }
  12474. hr = pTapiMakeCall(
  12475. pDestAddress,
  12476. pAppName,
  12477. pCalledParty,
  12478. pComment
  12479. );
  12480. if ( !SUCCEEDED(hr) )
  12481. {
  12482. LOG((TL_ERROR, "tapimakecall failed - %lx", hr));
  12483. }
  12484. UnloadTapi32( FALSE );
  12485. return hr;
  12486. }
  12487. HRESULT
  12488. LineTranslateDialog(
  12489. DWORD dwDeviceID,
  12490. DWORD dwAPIVersion,
  12491. HWND hwndOwner,
  12492. BSTR pAddressIn
  12493. )
  12494. {
  12495. HRESULT hr;
  12496. LINEINITIALIZEPROC pInitialize;
  12497. LINETRANSLATEDIALOGPROC pTranslateDialog;
  12498. hr = LoadTapi32( TRUE );
  12499. if ( !SUCCEEDED(hr) )
  12500. {
  12501. LOG((TL_ERROR, "LineTranslateDialog - load tapi32 failed"));
  12502. return hr;
  12503. }
  12504. pTranslateDialog = (LINETRANSLATEDIALOGPROC)GetProcAddress(
  12505. ghTapi32,
  12506. "lineTranslateDialogW"
  12507. );
  12508. if ( NULL == pTranslateDialog )
  12509. {
  12510. LOG((TL_ERROR, "LineTranslateDialog - getprocaddress failed 2"));
  12511. UnloadTapi32( TRUE );
  12512. return E_FAIL;
  12513. }
  12514. hr = (pTranslateDialog)(
  12515. ghLineApp,
  12516. dwDeviceID,
  12517. dwAPIVersion,
  12518. hwndOwner,
  12519. pAddressIn
  12520. );
  12521. hr = mapTAPIErrorCode( hr );
  12522. if ( !SUCCEEDED(hr) )
  12523. {
  12524. LOG((TL_ERROR, "LineTranslateDialog failed - %lx", hr));
  12525. }
  12526. UnloadTapi32( TRUE );
  12527. return hr;
  12528. }
  12529. typedef LONG (PASCAL *LINETRANSLATEADDRESSPROC)(HLINEAPP,
  12530. DWORD,
  12531. DWORD,
  12532. LPCWSTR,
  12533. DWORD,
  12534. DWORD,
  12535. LPLINETRANSLATEOUTPUT);
  12536. typedef LONG (PASCAL *LINEGETTRANSLATECAPSPROC)(HLINEAPP,
  12537. DWORD,
  12538. LPLINETRANSLATECAPS);
  12539. HRESULT
  12540. LineTranslateAddress(
  12541. HLINEAPP hLineApp,
  12542. DWORD dwDeviceID,
  12543. DWORD dwAPIVersion,
  12544. LPCWSTR lpszAddressIn,
  12545. DWORD dwCard,
  12546. DWORD dwTranslateOptions,
  12547. LPLINETRANSLATEOUTPUT *ppTranslateOutput
  12548. )
  12549. {
  12550. LONG lResult = 0;
  12551. HRESULT hr = S_OK;
  12552. DWORD dwSize = sizeof(LINETRANSLATECAPS ) + 2000;
  12553. LINETRANSLATEADDRESSPROC pTranslateProc;
  12554. LOG((TL_TRACE, "lineTranslateAddress - enter"));
  12555. hr = LoadTapi32( FALSE );
  12556. if ( !SUCCEEDED(hr) )
  12557. {
  12558. LOG((TL_ERROR, "lineTranslateAddress - load tapi32 failed"));
  12559. return hr;
  12560. }
  12561. pTranslateProc = (LINETRANSLATEADDRESSPROC)GetProcAddress(
  12562. ghTapi32,
  12563. "lineTranslateAddressW"
  12564. );
  12565. if ( NULL == pTranslateProc )
  12566. {
  12567. LOG((TL_ERROR, "lineTranslateAddress - getprocaddress failed 2"));
  12568. UnloadTapi32( FALSE );
  12569. return E_FAIL;
  12570. }
  12571. *ppTranslateOutput = (LPLINETRANSLATEOUTPUT) ClientAlloc( dwSize );
  12572. if (*ppTranslateOutput == NULL)
  12573. {
  12574. LOG((TL_ERROR, "lineTranslateAddress - ClientAlloc failed"));
  12575. hr = E_OUTOFMEMORY;
  12576. }
  12577. else
  12578. {
  12579. (*ppTranslateOutput)->dwTotalSize = dwSize;
  12580. while (TRUE)
  12581. {
  12582. lResult = (pTranslateProc)(0,
  12583. dwDeviceID,
  12584. dwAPIVersion,
  12585. lpszAddressIn,
  12586. dwCard,
  12587. dwTranslateOptions,
  12588. *ppTranslateOutput
  12589. );
  12590. if ((lResult == 0) && ((*ppTranslateOutput)->dwNeededSize > (*ppTranslateOutput)->dwTotalSize))
  12591. {
  12592. // didnt Work , adjust buffer size & try again
  12593. LOG((TL_INFO, "LineGetTranslateCaps failed - buffer to small"));
  12594. dwSize = (*ppTranslateOutput)->dwNeededSize;
  12595. ClientFree( *ppTranslateOutput );
  12596. *ppTranslateOutput = (LPLINETRANSLATEOUTPUT) ClientAlloc( dwSize );
  12597. if (*ppTranslateOutput == NULL)
  12598. {
  12599. LOG((TL_ERROR, "lineTranslateAddress - repeat ClientAlloc failed"));
  12600. hr = E_OUTOFMEMORY;
  12601. break;
  12602. }
  12603. else
  12604. {
  12605. (*ppTranslateOutput)->dwTotalSize = dwSize;
  12606. }
  12607. }
  12608. else
  12609. {
  12610. hr = mapTAPIErrorCode( lResult );
  12611. break;
  12612. }
  12613. } // end while(TRUE)
  12614. }
  12615. UnloadTapi32( FALSE );
  12616. LOG((TL_TRACE, hr, "lineTranslateAddress - exit"));
  12617. return hr;
  12618. }
  12619. HRESULT
  12620. LineGetTranslateCaps(
  12621. HLINEAPP hLineApp,
  12622. DWORD dwAPIVersion,
  12623. LPLINETRANSLATECAPS *ppTranslateCaps
  12624. )
  12625. {
  12626. LONG lResult = 0;
  12627. HRESULT hr = S_OK;
  12628. DWORD dwSize = sizeof(LINETRANSLATECAPS ) + 2000;
  12629. LINEGETTRANSLATECAPSPROC pTranslateProc;
  12630. LOG((TL_TRACE, "LineGetTranslateCaps - enter"));
  12631. hr = LoadTapi32( FALSE );
  12632. if ( !SUCCEEDED(hr) )
  12633. {
  12634. LOG((TL_ERROR, "LineGetTranslateCapsg - load tapi32 failed"));
  12635. return hr;
  12636. }
  12637. pTranslateProc = (LINEGETTRANSLATECAPSPROC)GetProcAddress(
  12638. ghTapi32,
  12639. "lineGetTranslateCapsW"
  12640. );
  12641. if ( NULL == pTranslateProc )
  12642. {
  12643. LOG((TL_ERROR, "LineGetTranslateCaps - getprocaddress failed 2"));
  12644. UnloadTapi32( FALSE );
  12645. return E_FAIL;
  12646. }
  12647. *ppTranslateCaps = (LPLINETRANSLATECAPS) ClientAlloc( dwSize );
  12648. if (*ppTranslateCaps == NULL)
  12649. {
  12650. LOG((TL_ERROR, "LineGetTranslateCaps - ClientAlloc failed"));
  12651. hr = E_OUTOFMEMORY;
  12652. }
  12653. else
  12654. {
  12655. (*ppTranslateCaps)->dwTotalSize = dwSize;
  12656. while (TRUE)
  12657. {
  12658. lResult = (pTranslateProc)(0,
  12659. dwAPIVersion,
  12660. *ppTranslateCaps
  12661. );
  12662. if ((lResult == 0) && ((*ppTranslateCaps)->dwNeededSize > (*ppTranslateCaps)->dwTotalSize))
  12663. {
  12664. // didnt Work , adjust buffer size & try again
  12665. LOG((TL_INFO, "LineGetTranslateCaps failed - buffer to small"));
  12666. dwSize = (*ppTranslateCaps)->dwNeededSize;
  12667. ClientFree( *ppTranslateCaps );
  12668. *ppTranslateCaps = (LPLINETRANSLATECAPS) ClientAlloc( dwSize );
  12669. if (*ppTranslateCaps == NULL)
  12670. {
  12671. LOG((TL_ERROR, "LineGetTranslateCaps - repeat ClientAlloc failed"));
  12672. hr = E_OUTOFMEMORY;
  12673. break;
  12674. }
  12675. else
  12676. {
  12677. (*ppTranslateCaps)->dwTotalSize = dwSize;
  12678. }
  12679. }
  12680. else
  12681. {
  12682. hr = mapTAPIErrorCode( lResult );
  12683. break;
  12684. }
  12685. } // end while(TRUE)
  12686. }
  12687. UnloadTapi32( FALSE );
  12688. LOG((TL_TRACE, hr, "LineGetTranslateCaps - exit"));
  12689. return hr;
  12690. }
  12691. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12692. // Function : GenerateHandleAndAddToHashTable
  12693. // Creates a unique ULONG_PTR handle & maps this to the passed in
  12694. // object via a hash table
  12695. // Returns handle
  12696. //
  12697. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12698. ULONG_PTR GenerateHandleAndAddToHashTable( ULONG_PTR Element)
  12699. {
  12700. static ULONG_PTR gNextHandle = 0;
  12701. ULONG_PTR uptrHandle = 0;
  12702. gpHandleHashTable->Lock();
  12703. gNextHandle = ++gNextHandle % 0x10;
  12704. uptrHandle = (Element << 4) + gNextHandle;
  12705. gpHandleHashTable->Insert( uptrHandle, Element );
  12706. gpHandleHashTable->Unlock();
  12707. return uptrHandle;
  12708. }
  12709. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12710. // Function : RemoveHandleFromHashTable
  12711. // Removes hash table entry, based on passed in handle
  12712. //
  12713. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12714. void RemoveHandleFromHashTable(ULONG_PTR dwHandle)
  12715. {
  12716. gpHandleHashTable->Lock();
  12717. gpHandleHashTable->Remove( (ULONG_PTR)(dwHandle) );
  12718. gpHandleHashTable->Unlock();
  12719. }
  12720. /////////////////////////////////////////////////////////////////////
  12721. //
  12722. // Internal event filtering functions
  12723. //
  12724. /////////////////////////////////////////////////////////////////////
  12725. #define LOWDWORD(ul64) ((DWORD)(ul64 & 0xffffffff))
  12726. #define HIDWORD(ul64) ((DWORD)((ul64 & 0xffffffff00000000) >> 32))
  12727. LONG
  12728. WINAPI
  12729. tapiSetEventFilterMasks (
  12730. DWORD dwObjType,
  12731. LONG_PTR lObjectID,
  12732. ULONG64 ulEventMasks
  12733. )
  12734. {
  12735. FUNC_ARGS funcArgs =
  12736. {
  12737. MAKELONG (TAPI_FUNC | SYNC | 6, tSetEventMasksOrSubMasks),
  12738. {
  12739. (ULONG_PTR) dwObjType, // type of object handle
  12740. (ULONG_PTR) lObjectID, // object handle
  12741. (ULONG_PTR) FALSE, // fSubMask
  12742. (ULONG_PTR) 0, // dwSubMasks
  12743. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasks low
  12744. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasks hi
  12745. },
  12746. {
  12747. Dword,
  12748. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12749. hXxxApp : Dword,
  12750. Dword,
  12751. Dword,
  12752. Dword,
  12753. Dword,
  12754. }
  12755. };
  12756. return (DOFUNC (&funcArgs, "tapiSetEventFilter"));
  12757. }
  12758. LONG
  12759. WINAPI
  12760. tapiSetEventFilterSubMasks (
  12761. DWORD dwObjType,
  12762. LONG_PTR lObjectID,
  12763. ULONG64 ulEventMasks,
  12764. DWORD dwEventSubMasks
  12765. )
  12766. {
  12767. FUNC_ARGS funcArgs =
  12768. {
  12769. MAKELONG (TAPI_FUNC | SYNC | 6, tSetEventMasksOrSubMasks),
  12770. {
  12771. (ULONG_PTR) dwObjType, // type of object handle
  12772. (ULONG_PTR) lObjectID, // object handle
  12773. (ULONG_PTR) TRUE, // fSubMask
  12774. (ULONG_PTR) dwEventSubMasks, // dwSubMasks
  12775. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasks low
  12776. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasks hi
  12777. },
  12778. {
  12779. Dword,
  12780. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12781. hXxxApp : Dword,
  12782. Dword,
  12783. Dword,
  12784. Dword,
  12785. Dword,
  12786. }
  12787. };
  12788. return (DOFUNC (&funcArgs, "tapiSetEventFilter"));
  12789. }
  12790. LONG
  12791. WINAPI
  12792. tapiGetEventFilterMasks (
  12793. DWORD dwObjType,
  12794. LONG_PTR lObjectID,
  12795. ULONG64 * pulEventMasks
  12796. )
  12797. {
  12798. DWORD dwEventSubMasks;
  12799. DWORD dwHiMasks;
  12800. DWORD dwLowMasks;
  12801. LONG lResult;
  12802. FUNC_ARGS funcArgs =
  12803. {
  12804. MAKELONG (TAPI_FUNC | SYNC | 8, tGetEventMasksOrSubMasks),
  12805. {
  12806. (ULONG_PTR) dwObjType, // object type
  12807. (ULONG_PTR) lObjectID, // object handles
  12808. (ULONG_PTR) FALSE, // fSubMask
  12809. (ULONG_PTR) &dwEventSubMasks, // &dwEventSubMasks
  12810. (ULONG_PTR) 0, // ulEventMasksIn low
  12811. (ULONG_PTR) 0, // ulEventMasksIn hi
  12812. (ULONG_PTR) &dwLowMasks, // ulEventMasksOut low
  12813. (ULONG_PTR) &dwHiMasks, // ulEventMasksOut hi
  12814. },
  12815. {
  12816. Dword,
  12817. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12818. hXxxApp : Dword,
  12819. Dword,
  12820. lpDword,
  12821. Dword,
  12822. Dword,
  12823. lpDword,
  12824. lpDword,
  12825. }
  12826. };
  12827. lResult = DOFUNC (&funcArgs, "tapiGetEventFilter");
  12828. if (lResult == 0)
  12829. {
  12830. *pulEventMasks = dwHiMasks;
  12831. (*pulEventMasks) <<= 32;
  12832. *pulEventMasks += dwLowMasks;
  12833. }
  12834. return lResult;
  12835. }
  12836. LONG
  12837. WINAPI
  12838. tapiGetEventFilterSubMasks (
  12839. DWORD dwObjType,
  12840. LONG_PTR lObjectID,
  12841. ULONG64 ulEventMasks,
  12842. DWORD * pdwEventSubMasks
  12843. )
  12844. {
  12845. DWORD dwHiMasks;
  12846. DWORD dwLowMasks;
  12847. FUNC_ARGS funcArgs =
  12848. {
  12849. MAKELONG (TAPI_FUNC | SYNC | 8, tGetEventMasksOrSubMasks),
  12850. {
  12851. (ULONG_PTR) dwObjType, // object type
  12852. (ULONG_PTR) lObjectID, // object handle
  12853. (ULONG_PTR) TRUE, // fSubMask
  12854. (ULONG_PTR) pdwEventSubMasks, // &dwEventSubMasks
  12855. (ULONG_PTR) LOWDWORD(ulEventMasks), // ulEventMasksIn low
  12856. (ULONG_PTR) HIDWORD(ulEventMasks), // ulEventMasksIn hi
  12857. (ULONG_PTR) &dwLowMasks, // ulEventMasksOut low
  12858. (ULONG_PTR) &dwHiMasks, // ulEventMasksOut hi
  12859. },
  12860. {
  12861. Dword,
  12862. (dwObjType == TAPIOBJ_HLINEAPP || dwObjType == TAPIOBJ_HPHONEAPP)?\
  12863. hXxxApp : Dword,
  12864. Dword,
  12865. lpDword,
  12866. Dword,
  12867. Dword,
  12868. lpDword,
  12869. lpDword,
  12870. }
  12871. };
  12872. return (DOFUNC (&funcArgs, "tapiGetEventFilter"));
  12873. }
  12874. LONG
  12875. WINAPI
  12876. tapiGetPermissibleMasks (
  12877. ULONG64 * pulPermMasks
  12878. )
  12879. {
  12880. LONG lResult;
  12881. DWORD dwLowMasks;
  12882. DWORD dwHiMasks;
  12883. FUNC_ARGS funcArgs =
  12884. {
  12885. MAKELONG (TAPI_FUNC | SYNC | 2, tGetPermissibleMasks),
  12886. {
  12887. (ULONG_PTR) &dwLowMasks, // ulPermMasks low
  12888. (ULONG_PTR) &dwHiMasks, // ulPermMasks hi
  12889. },
  12890. {
  12891. lpDword,
  12892. lpDword,
  12893. }
  12894. };
  12895. lResult = DOFUNC (&funcArgs, "tapiGetPermissibleMasks");
  12896. if (lResult == 0)
  12897. {
  12898. *pulPermMasks = dwHiMasks;
  12899. (*pulPermMasks) <<= 32;
  12900. *pulPermMasks += dwLowMasks;
  12901. }
  12902. return lResult;
  12903. }
  12904. LONG
  12905. WINAPI
  12906. tapiSetPermissibleMasks (
  12907. ULONG64 ulPermMasks
  12908. )
  12909. {
  12910. FUNC_ARGS funcArgs =
  12911. {
  12912. MAKELONG (TAPI_FUNC | SYNC | 2, tSetPermissibleMasks),
  12913. {
  12914. (ULONG_PTR)LOWDWORD(ulPermMasks), // ulPermMasks low
  12915. (ULONG_PTR)HIDWORD(ulPermMasks), // ulPermMasks hi
  12916. },
  12917. {
  12918. Dword,
  12919. Dword,
  12920. }
  12921. };
  12922. return (DOFUNC (&funcArgs, "tapiGetPermissibleMasks"));
  12923. }
  12924. BOOL
  12925. WaveStringIdToDeviceId(
  12926. LPWSTR pwszStringID,
  12927. LPCWSTR pwszDeviceType,
  12928. LPDWORD pdwDeviceId
  12929. )
  12930. {
  12931. //
  12932. // This function converts a wave device string ID to a numeric device ID
  12933. // The numeric device ID can be used in wave functions (waveOutOpen, etc)
  12934. //
  12935. if (!pwszDeviceType || !pwszStringID)
  12936. return FALSE;
  12937. LOG((TL_TRACE, "WaveStringIdToDeviceId (%S, %S) - enter", pwszStringID, pwszDeviceType));
  12938. // get the device id, based on string id and device class
  12939. if ( !_wcsicmp(pwszDeviceType, L"wave/in") ||
  12940. !_wcsicmp(pwszDeviceType, L"wave/in/out")
  12941. )
  12942. {
  12943. return (MMSYSERR_NOERROR == waveInMessage(
  12944. NULL,
  12945. DRV_QUERYIDFROMSTRINGID,
  12946. (DWORD_PTR)pwszStringID,
  12947. (DWORD_PTR)pdwDeviceId));
  12948. } else if (!_wcsicmp(pwszDeviceType, L"wave/out"))
  12949. {
  12950. return (MMSYSERR_NOERROR == waveOutMessage(
  12951. NULL,
  12952. DRV_QUERYIDFROMSTRINGID,
  12953. (DWORD_PTR)pwszStringID,
  12954. (DWORD_PTR)pdwDeviceId));
  12955. } else if (!_wcsicmp(pwszDeviceType, L"midi/in"))
  12956. {
  12957. return (MMSYSERR_NOERROR == midiInMessage(
  12958. NULL,
  12959. DRV_QUERYIDFROMSTRINGID,
  12960. (DWORD_PTR)pwszStringID,
  12961. (DWORD_PTR)pdwDeviceId));
  12962. } else if (!_wcsicmp(pwszDeviceType, L"midi/out"))
  12963. {
  12964. return (MMSYSERR_NOERROR == midiOutMessage(
  12965. NULL,
  12966. DRV_QUERYIDFROMSTRINGID,
  12967. (DWORD_PTR)pwszStringID,
  12968. (DWORD_PTR)pdwDeviceId));
  12969. }
  12970. LOG((TL_TRACE, "WaveStringIdToDeviceId (%S, %S) - failed", pwszStringID, pwszDeviceType));
  12971. return FALSE;
  12972. }