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

460 lines
18 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. /////////////////////////////////////////////////////////
  23. // ThreadDialing.cpp
  24. //
  25. #include "stdafx.h"
  26. #include "TapiDialer.h"
  27. #include "ThreadDial.h"
  28. #include "AVTapi.h"
  29. #include "AVTapiCall.h"
  30. #include "ConfExp.h"
  31. #include "ThreadPub.h"
  32. CThreadDialingInfo::CThreadDialingInfo()
  33. {
  34. m_pITAddress = NULL;
  35. m_bstrName = NULL;
  36. m_bstrAddress = NULL;
  37. m_bstrOriginalAddress = NULL;
  38. m_bstrDisplayableAddress = NULL;
  39. m_bstrUser1 = NULL;
  40. m_bstrUser2 = NULL;
  41. m_dwAddressType = 0;
  42. m_bResolved = false;
  43. m_nCallType = AV_VOICE_CALL;
  44. m_lCallID = 0;
  45. m_hMem = NULL;
  46. }
  47. CThreadDialingInfo::~CThreadDialingInfo()
  48. {
  49. SysFreeString( m_bstrName );
  50. SysFreeString( m_bstrAddress );
  51. SysFreeString( m_bstrOriginalAddress );
  52. SysFreeString( m_bstrDisplayableAddress );
  53. SysFreeString( m_bstrUser1 );
  54. SysFreeString( m_bstrUser2 );
  55. if ( m_hMem ) GlobalFree( m_hMem );
  56. RELEASE( m_pITAddress );
  57. }
  58. HRESULT CThreadDialingInfo::set_ITAddress( ITAddress *pITAddress )
  59. {
  60. RELEASE( m_pITAddress );
  61. if ( pITAddress )
  62. return pITAddress->QueryInterface( IID_ITAddress, (void **) &m_pITAddress );
  63. return E_POINTER;
  64. }
  65. HRESULT CThreadDialingInfo::TranslateAddress()
  66. {
  67. // Only valid for dialing POTS, with a valid string that doesn't start with "x"
  68. if ( !m_pITAddress ||
  69. (m_dwAddressType != LINEADDRESSTYPE_PHONENUMBER) ||
  70. !m_bstrAddress ||
  71. (SysStringLen(m_bstrAddress) == 0) )
  72. {
  73. return S_OK;
  74. }
  75. ITAddressTranslation *pXlat;
  76. CErrorInfo er( IDS_ER_TRANSLATE_ADDRESS, IDS_ER_CREATE_TAPI_OBJECT );
  77. if ( SUCCEEDED(er.set_hr(m_pITAddress->QueryInterface(IID_ITAddressTranslation, (void **) &pXlat))) )
  78. {
  79. er.set_Details( IDS_ER_TRANSLATING_ADDRESS );
  80. ITAddressTranslationInfo *pXlatInfo = NULL;
  81. // Translate the address
  82. int nTryCount = 0;
  83. while ( SUCCEEDED(er.m_hr) && (nTryCount < 2) )
  84. {
  85. if ( SUCCEEDED(er.set_hr( pXlat->TranslateAddress( m_bstrAddress, 0, 0, &pXlatInfo) )) && pXlatInfo )
  86. {
  87. BSTR bstrTemp = NULL;
  88. pXlatInfo->get_DialableString( &bstrTemp );
  89. if ( bstrTemp && SysStringLen(bstrTemp) )
  90. {
  91. #ifdef _DEBUG
  92. USES_CONVERSION;
  93. ATLTRACE(_T(".1.CThreadDialingProc::TranslateAddress() -- from %s to %s.\n"), OLE2CT(m_bstrAddress), OLE2CT(bstrTemp) );
  94. #endif
  95. SysReAllocString( &m_bstrAddress, bstrTemp );
  96. }
  97. SysFreeString( bstrTemp );
  98. bstrTemp = NULL;
  99. // Displayable address as well
  100. pXlatInfo->get_DisplayableString( &bstrTemp );
  101. if ( bstrTemp && SysStringLen(bstrTemp) )
  102. SysReAllocString( &m_bstrDisplayableAddress, bstrTemp );
  103. SysFreeString( bstrTemp );
  104. // Clean up
  105. RELEASE( pXlatInfo );
  106. break;
  107. }
  108. else if ( er.m_hr == TAPI_E_REGISTRY_SETTING_CORRUPT )
  109. {
  110. HWND hWndParent = NULL;
  111. CComPtr<IAVTapi> pAVTapi;
  112. if ( SUCCEEDED(_Module.get_AVTapi(&pAVTapi)) )
  113. pAVTapi->get_hWndParent( &hWndParent );
  114. // Show translate address dialog
  115. pXlat->TranslateDialog( (TAPIHWND)hWndParent, m_bstrAddress );
  116. er.set_hr( S_OK );
  117. }
  118. nTryCount++;
  119. }
  120. pXlat->Release();
  121. }
  122. return er.m_hr;
  123. }
  124. HRESULT CThreadDialingInfo::PutAllInfo( IAVTapiCall *pAVCall )
  125. {
  126. _ASSERT( pAVCall );
  127. pAVCall->put_dwAddressType( m_dwAddressType );
  128. pAVCall->put_bstrOriginalAddress( m_bstrOriginalAddress );
  129. pAVCall->put_bstrDisplayableAddress( m_bstrDisplayableAddress );
  130. pAVCall->put_bstrName( m_bstrName );
  131. pAVCall->put_dwThreadID( GetCurrentThreadId() );
  132. pAVCall->put_bstrUser( 0, m_bstrUser1 );
  133. pAVCall->put_bstrUser( 1, m_bstrUser2 );
  134. pAVCall->put_bResolved( m_bResolved );
  135. return S_OK;
  136. }
  137. void CThreadDialingInfo::FixupAddress()
  138. {
  139. if ( m_dwAddressType == LINEADDRESSTYPE_DOMAINNAME )
  140. {
  141. if ( (SysStringLen(m_bstrAddress) > 2) && !wcsncmp(m_bstrAddress, L"\\\\", 2) )
  142. {
  143. BSTR bstrTemp = SysAllocString( &m_bstrAddress[2] );
  144. //
  145. // We have to verify the string allocation
  146. //
  147. if( IsBadStringPtr( bstrTemp, (UINT)-1) )
  148. {
  149. return;
  150. }
  151. SysReAllocString( &m_bstrAddress, bstrTemp );
  152. SysFreeString( bstrTemp );
  153. }
  154. }
  155. }
  156. /////////////////////////////////////////////////////////////////////////////////
  157. // ThreadDialingProc
  158. //
  159. DWORD WINAPI ThreadDialingProc( LPVOID lpInfo )
  160. {
  161. #define FETCH_STRING( _CMS_, _IDS_ ) \
  162. if ( bSliders ) { \
  163. if ( LoadString(_Module.GetResourceInstance(), _IDS_, szText, ARRAYSIZE(szText)) > 0 ) { \
  164. if ( SUCCEEDED(SysReAllocString(&bstrText, T2COLE(szText))) ) \
  165. pAVTapi->fire_SetCallState_CMS( lCallID, _CMS_, bstrText ); \
  166. } \
  167. }
  168. ATLTRACE(_T(".enter.ThreadDialingProc().\n") );
  169. HANDLE hThread = NULL;
  170. BOOL bDup = DuplicateHandle( GetCurrentProcess(),
  171. GetCurrentThread(),
  172. GetCurrentProcess(),
  173. &hThread,
  174. THREAD_ALL_ACCESS,
  175. TRUE,
  176. 0 );
  177. _ASSERT( bDup );
  178. _Module.AddThread( hThread );
  179. // Data passed into thread
  180. USES_CONVERSION;
  181. _ASSERT( lpInfo );
  182. CThreadDialingInfo *pInfo = (CThreadDialingInfo *) lpInfo;
  183. long lCallID;
  184. // Error info information
  185. CErrorInfo er;
  186. er.set_Operation( IDS_ER_PLACECALL );
  187. er.set_Details( IDS_ER_COINITIALIZE );
  188. HRESULT hr = er.set_hr( CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY) );
  189. if ( SUCCEEDED(hr) )
  190. {
  191. ATLTRACE(_T(".1.ThreadDialingProc() -- thread up and running.\n") );
  192. CAVTapi *pAVTapi = NULL;
  193. IConfRoom *pConfRoom = NULL;
  194. IAVTapiCall *pAVCall = NULL;
  195. bool bSliders = (bool) (pInfo->m_dwAddressType != LINEADDRESSTYPE_SDP);
  196. if ( SUCCEEDED(hr = er.set_hr(_Module.GetAVTapi(&pAVTapi))) &&
  197. SUCCEEDED(hr = er.set_hr(pAVTapi->get_ConfRoom(&pConfRoom))) )
  198. {
  199. TCHAR szText[255];
  200. BSTR bstrText = NULL;
  201. er.set_Details( IDS_ER_FIRE_NEW_CALL );
  202. if ( bSliders )
  203. {
  204. if ( SUCCEEDED(hr = er.set_hr(pAVTapi->fire_NewCall(pInfo->m_pITAddress, pInfo->m_dwAddressType, pInfo->m_lCallID, NULL, pInfo->m_nCallType, &pAVCall))) )
  205. {
  206. // Retrieve call ID for convienence and set up called address info
  207. pAVCall->get_lCallID( &lCallID );
  208. pInfo->PutAllInfo( pAVCall );
  209. // Set the caller ID for the call
  210. pAVCall->ResolveAddress();
  211. pAVCall->ForceCallerIDUpdate();
  212. // Setting up media terminals
  213. pAVTapi->fire_ClearCurrentActions( lCallID );
  214. pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_DISCONNECT, NULL );
  215. FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_FETCH_ADDRESS );
  216. }
  217. }
  218. else
  219. {
  220. // Joining a conference...
  221. hr = er.set_hr(pAVTapi->CreateNewCall(pInfo->m_pITAddress, &pAVCall) );
  222. if ( SUCCEEDED(hr) )
  223. {
  224. pInfo->PutAllInfo( pAVCall );
  225. pAVTapi->fire_ActionSelected( CC_ACTIONS_SHOWCONFROOM );
  226. hr = pConfRoom->EnterConfRoom( pAVCall );
  227. }
  228. }
  229. if ( SUCCEEDED(hr) )
  230. {
  231. // Did we make the address okay (in the case of a conference )
  232. if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
  233. {
  234. // Create the call and then dial
  235. ITBasicCallControl *pITControl = NULL;
  236. er.set_Details( IDS_ER_CREATE_CALL );
  237. pInfo->FixupAddress();
  238. // What kind of media types does the address support?
  239. long lSupportedMediaModes = 0;
  240. ITMediaSupport *pITMediaSupport;
  241. if ( SUCCEEDED(pInfo->m_pITAddress->QueryInterface(IID_ITMediaSupport, (void **) &pITMediaSupport)) )
  242. {
  243. pITMediaSupport->get_MediaTypes( &lSupportedMediaModes );
  244. pITMediaSupport->Release();
  245. }
  246. lSupportedMediaModes &= (TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO);
  247. ////////////////////////
  248. // Create the call object
  249. //
  250. if ( SUCCEEDED(hr = er.set_hr(pInfo->m_pITAddress->
  251. CreateCall( pInfo->m_bstrAddress,
  252. pInfo->m_dwAddressType,
  253. lSupportedMediaModes,
  254. &pITControl))) )
  255. {
  256. // Set more call parameters
  257. pAVCall->put_ITBasicCallControl( pITControl );
  258. ///////////////////////////////////
  259. // Set caller/calling ID
  260. // Set the terminals up for the call
  261. //
  262. ITCallInfo *pCallInfo;
  263. if ( SUCCEEDED(pITControl->QueryInterface(IID_ITCallInfo, (void **) &pCallInfo)) )
  264. {
  265. // Set user user info if requested
  266. if ( pInfo->m_hMem )
  267. {
  268. void *pbUU = GlobalLock( pInfo->m_hMem );
  269. if ( pbUU )
  270. {
  271. pCallInfo->SetCallInfoBuffer( CIB_USERUSERINFO, GlobalSize(pInfo->m_hMem), (BYTE *) pbUU );
  272. GlobalUnlock( pInfo->m_hMem );
  273. }
  274. }
  275. // Identify who it is that's calling!
  276. CComBSTR bstrName;
  277. MyGetUserName( &bstrName );
  278. if ( bstrName )
  279. {
  280. // Add the computer name to the end
  281. BSTR bstrIP = NULL, bstrComputer = NULL;
  282. GetIPAddress( &bstrIP, &bstrComputer );
  283. if ( bstrComputer && SysStringLen(bstrComputer) )
  284. {
  285. bstrName.Append( _T("\n") );
  286. bstrName.Append( bstrComputer );
  287. }
  288. SysFreeString( bstrIP );
  289. SysFreeString( bstrComputer );
  290. pCallInfo->put_CallInfoString( CIS_CALLINGPARTYID, bstrName );
  291. }
  292. // Identify who it is that we think we're calling
  293. if ( pInfo->m_bstrName && (SysStringLen(pInfo->m_bstrName) > 0) )
  294. pCallInfo->put_CallInfoString( CIS_CALLEDPARTYFRIENDLYNAME, pInfo->m_bstrName );
  295. else
  296. pCallInfo->put_CallInfoString( CIS_CALLEDPARTYFRIENDLYNAME, pInfo->m_bstrAddress );
  297. ///////////////////////////////////
  298. // Setting up media terminals
  299. //
  300. pAVTapi->fire_ClearCurrentActions( lCallID );
  301. pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_DISCONNECT, NULL );
  302. FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_FETCH_ADDRESS );
  303. // Don't create terminals for data calls
  304. if ( pInfo->m_nCallType != AV_DATA_CALL )
  305. {
  306. er.set_Details( IDS_ER_CREATETERMINALS );
  307. hr = er.set_hr( pAVTapi->CreateTerminalArray(pInfo->m_pITAddress, pAVCall, pCallInfo) );
  308. }
  309. pCallInfo->Release();
  310. }
  311. ////////////////////////////////
  312. // Do the dialing
  313. //
  314. if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
  315. {
  316. FETCH_STRING( CM_STATES_DIALING, IDS_PLACECALL_DIALING );
  317. // Register the callback object and connect call
  318. if ( SUCCEEDED(hr) && SUCCEEDED(hr = pAVCall->CheckKillMe()) )
  319. {
  320. er.set_Details( IDS_ER_CONNECT_CALL );
  321. if ( bSliders && (pInfo->m_nCallType != AV_DATA_CALL) )
  322. {
  323. pAVTapi->ShowMedia( lCallID, NULL, FALSE );
  324. pAVTapi->ShowMediaPreview( lCallID, NULL, FALSE );
  325. }
  326. hr = er.set_hr( pITControl->Connect(false) );
  327. }
  328. else if ( bSliders )
  329. {
  330. pConfRoom->Cancel();
  331. }
  332. }
  333. else if ( bSliders )
  334. {
  335. pConfRoom->Cancel();
  336. }
  337. SAFE_DELETE( pInfo )
  338. RELEASE( pAVCall );
  339. pITControl->Release();
  340. // Spin
  341. if ( SUCCEEDED(hr) )
  342. CAVTapiCall::WaitWithMessageLoop();
  343. }
  344. }
  345. // Failed to make the call, update the call control window
  346. if ( FAILED(hr) )
  347. {
  348. if ( bSliders )
  349. {
  350. pAVTapi->fire_ClearCurrentActions( lCallID );
  351. pAVTapi->fire_AddCurrentAction( lCallID, CM_ACTIONS_CLOSE, NULL );
  352. }
  353. else
  354. {
  355. pConfRoom->Cancel();
  356. }
  357. // what was the problem?
  358. switch ( hr )
  359. {
  360. case LINEERR_OPERATIONUNAVAIL:
  361. FETCH_STRING( CM_STATES_UNAVAILABLE, IDS_PLACECALL_DISCONNECT_UNAVAIL );
  362. hr = er.set_hr( S_OK );
  363. break;
  364. case LINEERR_INVALADDRESS:
  365. FETCH_STRING( CM_STATES_UNAVAILABLE, IDS_PLACECALL_DISCONNECT_BADADDRESS);
  366. hr = er.set_hr( S_OK );
  367. break;
  368. default:
  369. if ( bSliders )
  370. pAVTapi->fire_SetCallState_CMS( lCallID, CM_STATES_DISCONNECTED, NULL );
  371. break;
  372. }
  373. }
  374. }
  375. // Release the string
  376. SysFreeString( bstrText );
  377. }
  378. // Clean-up
  379. RELEASE( pConfRoom );
  380. if ( pAVTapi )
  381. (dynamic_cast<IUnknown *> (pAVTapi))->Release();
  382. CoUninitialize();
  383. }
  384. SAFE_DELETE( pInfo );
  385. // Notify module of shutdown
  386. _Module.RemoveThread( hThread );
  387. SetEvent( _Module.m_hEventThread );
  388. ATLTRACE(_T(".exit.ThreadDialingProc(0x%08lx).\n"), hr );
  389. return hr;
  390. }