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.

529 lines
14 KiB

  1. /*******************************************************************************
  2. Module Name:
  3. work.cpp
  4. Abstract:
  5. Implements main function of the bridge test application
  6. Author:
  7. Qianbo Huai (qhuai) Jan 27 2000
  8. *******************************************************************************/
  9. #include "stdafx.h"
  10. // command line
  11. LPSTR glpCmdLine = NULL;
  12. // dialog
  13. HWND ghDlg = NULL;
  14. // true: exit button on dialog was clicked
  15. bool gfExitButton = false;
  16. // bridge
  17. CBridgeApp *gpBridgeApp = NULL;
  18. // callback func in dialog
  19. BOOL
  20. CALLBACK
  21. MainDialogProc (
  22. HWND hDlg,
  23. UINT uMsg,
  24. WPARAM wParam,
  25. LPARAM lParam
  26. );
  27. // func to deal with TAPI events
  28. HRESULT
  29. OnTapiEvent (
  30. TAPI_EVENT TapiEvent,
  31. IDispatch *pEvent
  32. );
  33. HRESULT
  34. OnPrivateEvent (IDispatch *pEvent);
  35. // set status message on dialog
  36. void SetStatusMessage (LPWSTR pszMessage);
  37. void DoMessage (LPWSTR pszMessage);
  38. void EnableDisconnectButton (BOOL fYes);
  39. /*//////////////////////////////////////////////////////////////////////////////
  40. WinMain
  41. ////*/
  42. int
  43. WINAPI
  44. WinMain (
  45. HINSTANCE hInst,
  46. HINSTANCE hPrevInst,
  47. LPSTR lpCmdLine,
  48. int nShowCmd
  49. )
  50. {
  51. // init com
  52. if (FAILED (CoInitializeEx(NULL, COINIT_MULTITHREADED)))
  53. return 0;
  54. // init debug
  55. BGLOGREGISTER (L"work");
  56. // keep command line which determines which SDP to join
  57. glpCmdLine = lpCmdLine;
  58. // init CBridgeApp
  59. HRESULT hr;
  60. gpBridgeApp = new CBridgeApp (&hr);
  61. if (gpBridgeApp==NULL || FAILED (hr))
  62. {
  63. LOG ((BG_ERROR, "Failed to init CBridgeApp"));
  64. return 0;
  65. }
  66. // start dialog box
  67. if (!DialogBox (hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, MainDialogProc))
  68. {
  69. LOG ((BG_TRACE, "Dialog ends"));
  70. }
  71. // dialog finished
  72. delete gpBridgeApp;
  73. BGLOGDEREGISTER ();
  74. CoUninitialize ();
  75. return 1;
  76. }
  77. /*//////////////////////////////////////////////////////////////////////////////
  78. Callback for dialog
  79. ////*/
  80. BOOL
  81. CALLBACK
  82. MainDialogProc (
  83. HWND hDlg,
  84. UINT uMsg,
  85. WPARAM wParam,
  86. LPARAM lParam
  87. )
  88. {
  89. switch (uMsg)
  90. {
  91. case WM_INITDIALOG:
  92. {
  93. ghDlg = hDlg;
  94. EnableDisconnectButton (false);
  95. return 0;
  96. }
  97. case WM_PRIVATETAPIEVENT:
  98. {
  99. OnTapiEvent ((TAPI_EVENT)wParam, (IDispatch *)lParam);
  100. return 0;
  101. }
  102. case WM_COMMAND:
  103. {
  104. switch (LOWORD(wParam))
  105. {
  106. case IDC_EXIT:
  107. {
  108. gfExitButton = true;
  109. gpBridgeApp->DisconnectAllCalls (DC_NORMAL);
  110. // check if in connection
  111. if (!IsWindowEnabled (GetDlgItem (ghDlg, IDC_DISCONNECT)))
  112. {
  113. // not in connection
  114. EndDialog (ghDlg, 0);
  115. }
  116. // else
  117. // remember exit button is clicked
  118. // do not call EndDialog because a disconnected event is to come
  119. return 1;
  120. }
  121. case IDC_DISCONNECT:
  122. {
  123. gpBridgeApp->DisconnectAllCalls (DC_NORMAL);
  124. // disable disconnect button
  125. EnableDisconnectButton (false);
  126. return 1;
  127. }
  128. }
  129. case IDC_NEXTSUBSTREAM:
  130. {
  131. gpBridgeApp->NextSubStream ();
  132. return 1;
  133. }
  134. return 0;
  135. }
  136. default:
  137. return 0;
  138. }
  139. }
  140. /*//////////////////////////////////////////////////////////////////////////////
  141. Deals with TAPI events
  142. ////*/
  143. HRESULT OnTapiEvent (
  144. TAPI_EVENT TapiEvent,
  145. IDispatch *pEvent
  146. )
  147. {
  148. HRESULT hr = S_OK;
  149. // LOGEvent ((BG_TE, TapiEvent));
  150. switch (TapiEvent)
  151. {
  152. case TE_CALLNOTIFICATION:
  153. {
  154. if (BST_CHECKED != IsDlgButtonChecked (ghDlg, IDC_REJECT))
  155. {
  156. // if h323 call and to us, init h323 call
  157. if (FAILED (hr = gpBridgeApp->CreateH323Call (pEvent)));
  158. LOG ((BG_ERROR, "Failed to create h323 call, %x", hr));
  159. }
  160. break;
  161. }
  162. case TE_CALLSTATE:
  163. {
  164. CALL_STATE cs;
  165. ITCallStateEvent *pCallStateEvent = NULL;
  166. // get call state event
  167. hr = pEvent->QueryInterface (
  168. IID_ITCallStateEvent,
  169. (void **)&pCallStateEvent
  170. );
  171. if (FAILED(hr)) break;
  172. // get call state
  173. hr = pCallStateEvent->get_State (&cs);
  174. pCallStateEvent->Release ();
  175. if (FAILED(hr)) break;
  176. // LOGEvent ((BG_CS, cs));
  177. // if offering, connect
  178. if (CS_OFFERING == cs)
  179. {
  180. CBridgeItem *pItem = NULL;
  181. // check if h323 call created successful
  182. hr = gpBridgeApp->HasH323Call (pEvent, &pItem);
  183. if (S_OK != hr || NULL == pItem)
  184. {
  185. LOG ((BG_ERROR, "Failed to check h323 call, %x", hr));
  186. hr = S_OK;
  187. break;
  188. }
  189. // create sdp call
  190. if (FAILED (hr = gpBridgeApp->CreateSDPCall (pItem)))
  191. {
  192. gpBridgeApp->DisconnectCall (pItem, DC_REJECTED);
  193. // delete pItem;
  194. LOG ((BG_ERROR, "Failed to create SDP call, %x", hr));
  195. break;
  196. }
  197. // bridge call
  198. if (FAILED (hr = gpBridgeApp->BridgeCalls (pItem)))
  199. {
  200. gpBridgeApp->DisconnectCall (pItem, DC_REJECTED);
  201. // delete pItem;
  202. LOG ((BG_ERROR, "Failed to bridge calls, %x", hr));
  203. break;
  204. }
  205. // enable disconnect button
  206. EnableDisconnectButton (true);
  207. }
  208. // if disconnect
  209. else if (CS_DISCONNECTED == cs)
  210. {
  211. CBridgeItem *pItem = NULL;
  212. // check if h323 call created successful
  213. hr = gpBridgeApp->HasH323Call (pEvent, &pItem);
  214. if (S_OK == hr && NULL != pItem)
  215. {
  216. // the call already disconnected
  217. // call disconnect here only to remove pItem from the list
  218. gpBridgeApp->RemoveCall (pItem);
  219. delete pItem;
  220. }
  221. // if exit button is clicked and all call disconnected
  222. if (gfExitButton)
  223. {
  224. if (S_OK != gpBridgeApp->HasCalls ())
  225. EndDialog (ghDlg, 0);
  226. }
  227. else
  228. {
  229. if (S_OK != gpBridgeApp->HasCalls ())
  230. EnableDisconnectButton (false);
  231. }
  232. }
  233. break;
  234. }
  235. case TE_CALLMEDIA:
  236. {
  237. CALL_MEDIA_EVENT cme;
  238. ITCallMediaEvent *pCallMediaEvent;
  239. // get call media event
  240. hr = pEvent->QueryInterface (
  241. IID_ITCallMediaEvent,
  242. (void **)&pCallMediaEvent
  243. );
  244. if (FAILED(hr)) break;
  245. // get the event
  246. hr = pCallMediaEvent->get_Event (&cme);
  247. if (FAILED(hr)) break;
  248. // LOGEvent ((BG_CME, cme));
  249. // check media event
  250. switch (cme)
  251. {
  252. case CME_STREAM_FAIL:
  253. hr = E_FAIL;
  254. LOG ((BG_ERROR, "Stream failed"));
  255. break;
  256. case CME_TERMINAL_FAIL:
  257. hr = E_FAIL;
  258. LOG ((BG_ERROR, "Terminal failed"));
  259. break;
  260. default:
  261. break;
  262. }
  263. // we no longer need this interface.
  264. pCallMediaEvent->Release();
  265. break;
  266. }
  267. case TE_PRIVATE:
  268. hr = OnPrivateEvent (pEvent);
  269. break;
  270. default:
  271. break;
  272. }
  273. pEvent->Release(); // we addrefed it CTAPIEventNotification::Event()
  274. return hr;
  275. }
  276. /*//////////////////////////////////////////////////////////////////////////////
  277. ////*/
  278. HRESULT OnPrivateEvent (
  279. IDispatch *pEvent
  280. )
  281. {
  282. ENTER_FUNCTION ("OnPrivateEvent");
  283. // LOG ((BG_TRACE, "%s entered", __fxName));
  284. HRESULT hr = S_OK;
  285. ITPrivateEvent *pPrivateEvent = NULL;
  286. IDispatch *pDispatch = NULL;
  287. ITParticipantEvent *pPartEvent = NULL;
  288. ITParticipant *pParticipant = NULL;
  289. PARTICIPANT_EVENT event;
  290. ITCallInfo *pCallInfo = NULL;
  291. ITBasicCallControl *pCallControl = NULL;
  292. // get private event interface
  293. if (FAILED (hr = pEvent->QueryInterface (&pPrivateEvent)))
  294. {
  295. LOG ((BG_ERROR, "%s failed to query ITPrivateEvent", __fxName));
  296. return hr;
  297. }
  298. // get event interface
  299. if (FAILED (hr = pPrivateEvent->get_EventInterface (&pDispatch)))
  300. {
  301. LOG ((BG_ERROR, "%s failed to query event interface", __fxName));
  302. goto Error;
  303. }
  304. // get participant event interface
  305. hr = pDispatch->QueryInterface (&pPartEvent);
  306. pDispatch->Release ();
  307. pDispatch = NULL;
  308. if (FAILED (hr))
  309. {
  310. LOG ((BG_ERROR, "%s failed to query participant interface", __fxName));
  311. goto Error;
  312. }
  313. // get event
  314. if (FAILED (hr = pPartEvent->get_Event (&event)))
  315. {
  316. LOG ((BG_ERROR, "%s failed to get event", __fxName));
  317. goto Error;
  318. }
  319. // LOGEvent ((BG_PE, event));
  320. // check the event
  321. switch (event)
  322. {
  323. case PE_PARTICIPANT_ACTIVE:
  324. {
  325. // get call info
  326. if (FAILED (hr = pPrivateEvent->get_Call (&pCallInfo)))
  327. {
  328. LOG ((BG_ERROR, "%s failed to get call info", __fxName));
  329. goto Error;
  330. }
  331. // get call control
  332. if (FAILED (hr = pCallInfo->QueryInterface (&pCallControl)))
  333. {
  334. LOG ((BG_ERROR, "%s failed to get call control", __fxName));
  335. goto Error;
  336. }
  337. // get participant interface
  338. if (FAILED (hr = pPartEvent->get_Participant (&pParticipant)))
  339. {
  340. LOG ((BG_ERROR, "%s failed to get participant", __fxName));
  341. goto Error;
  342. }
  343. // show participant
  344. hr = gpBridgeApp->ShowParticipant (pCallControl, pParticipant);
  345. if (FAILED (hr))
  346. {
  347. LOG ((BG_ERROR, "%s failed to show participant, %x", __fxName, hr));
  348. }
  349. if (S_FALSE == hr)
  350. {
  351. hr = S_OK;
  352. // *ppszMessage = L"Participant active but call not found in list";
  353. // or no substream found on the stream
  354. }
  355. }
  356. break;
  357. default:
  358. break;
  359. }
  360. Cleanup:
  361. if (pCallInfo) pCallInfo->Release ();
  362. if (pCallControl) pCallControl->Release ();
  363. if (pPrivateEvent) pPrivateEvent->Release ();
  364. if (pPartEvent) pPartEvent->Release ();
  365. if (pParticipant) pParticipant->Release ();
  366. // LOG ((BG_TRACE, "%s exits", __fxName));
  367. return hr;
  368. Error:
  369. goto Cleanup;
  370. }
  371. /*//////////////////////////////////////////////////////////////////////////////
  372. Popup message box
  373. ////*/
  374. WCHAR gMsgBoxTitle[] = L"TAPI 3.0 Bridge Test Application";
  375. void
  376. DoMessage (LPWSTR pszMessage)
  377. {
  378. #if POPUP_MESSAGE
  379. MessageBox (
  380. ghDlg,
  381. pszMessage,
  382. gMsgBoxTitle,
  383. MB_OK
  384. );
  385. #endif
  386. }
  387. /*//////////////////////////////////////////////////////////////////////////////
  388. Status message
  389. ////*/
  390. void
  391. SetStatusMessage (LPWSTR pszMessage)
  392. {
  393. SetDlgItemText (ghDlg, IDC_STATUS, pszMessage);
  394. }
  395. /*//////////////////////////////////////////////////////////////////////////////
  396. ////*/
  397. void
  398. EnableDisconnectButton (BOOL fYes)
  399. {
  400. if (fYes)
  401. {
  402. // enable
  403. SetStatusMessage (L"Bridging calls ...");
  404. SendDlgItemMessage (
  405. ghDlg,
  406. IDC_NEXTSUBSTREAM,
  407. BM_SETSTYLE,
  408. BS_DEFPUSHBUTTON,
  409. 0
  410. );
  411. SendDlgItemMessage (
  412. ghDlg,
  413. IDC_DISCONNECT,
  414. BM_SETSTYLE,
  415. BS_DEFPUSHBUTTON,
  416. 0
  417. );
  418. EnableWindow (
  419. GetDlgItem (ghDlg, IDC_NEXTSUBSTREAM),
  420. TRUE
  421. );
  422. EnableWindow (
  423. GetDlgItem (ghDlg, IDC_DISCONNECT),
  424. TRUE
  425. );
  426. SetFocus (GetDlgItem (ghDlg, IDC_DISCONNECT));
  427. }
  428. else
  429. {
  430. // disable
  431. SetStatusMessage (L"Waiting for calls ...");
  432. SendDlgItemMessage (
  433. ghDlg,
  434. IDC_NEXTSUBSTREAM,
  435. BM_SETSTYLE,
  436. BS_PUSHBUTTON,
  437. 0
  438. );
  439. SendDlgItemMessage (
  440. ghDlg,
  441. IDC_DISCONNECT,
  442. BM_SETSTYLE,
  443. BS_PUSHBUTTON,
  444. 0
  445. );
  446. EnableWindow (
  447. GetDlgItem (ghDlg, IDC_NEXTSUBSTREAM),
  448. FALSE
  449. );
  450. EnableWindow (
  451. GetDlgItem (ghDlg, IDC_DISCONNECT),
  452. FALSE
  453. );
  454. }
  455. }