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.

764 lines
20 KiB

  1. /* Copyright (c) 1999 Microsoft Corporation */
  2. #include "phonemgr.h"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <wxdebug.h>
  6. #ifdef _DBG
  7. #define DEBUG(_x_) OutputDebugString(_x_)
  8. #else
  9. #define DEBUG(_x_)
  10. #endif
  11. ITRequest * g_pITRequest = NULL;
  12. HRESULT InitAssistedTelephony(void)
  13. {
  14. HRESULT hr;
  15. //
  16. // Initialize COM.
  17. //
  18. printf("Initializing COM...\n");
  19. hr = CoInitializeEx(
  20. NULL,
  21. COINIT_MULTITHREADED
  22. );
  23. if ( FAILED(hr) )
  24. {
  25. printf("CoInitialize failed - 0x%08x\n", hr);
  26. return hr;
  27. }
  28. //
  29. // Cocreate the assisted telephony object.
  30. //
  31. printf("Creating RequestMakeCall object...\n");
  32. hr = CoCreateInstance(
  33. CLSID_RequestMakeCall,
  34. NULL,
  35. CLSCTX_INPROC_SERVER,
  36. IID_ITRequest,
  37. (void **) & g_pITRequest
  38. );
  39. if ( FAILED(hr) )
  40. {
  41. printf("CoCreateInstance failed - 0x%08x\n", hr);
  42. return hr;
  43. }
  44. return S_OK;
  45. }
  46. HRESULT MakeAssistedTelephonyCall(WCHAR * wszDestAddress)
  47. {
  48. HRESULT hr;
  49. BSTR bstrDestAddress = NULL;
  50. BSTR bstrAppName = NULL;
  51. BSTR bstrCalledParty = NULL;
  52. BSTR bstrComment = NULL;
  53. bstrDestAddress = SysAllocString(
  54. wszDestAddress
  55. );
  56. if ( bstrDestAddress == NULL )
  57. {
  58. printf("SysAllocString failed");
  59. return E_OUTOFMEMORY;
  60. }
  61. //
  62. // Make a call.
  63. //
  64. printf("Calling ITRequest::MakeCall...\n");
  65. hr = g_pITRequest->MakeCall(
  66. bstrDestAddress,
  67. bstrAppName,
  68. bstrCalledParty,
  69. bstrComment
  70. );
  71. SysFreeString(
  72. bstrDestAddress
  73. );
  74. if ( FAILED(hr) )
  75. {
  76. printf("ITRequest::MakeCall failed - 0x%08x\n", hr);
  77. return hr;
  78. }
  79. return S_OK;
  80. }
  81. int
  82. WINAPI
  83. WinMain(
  84. HINSTANCE hInstance,
  85. HINSTANCE hPrevInstance,
  86. LPSTR lpCmdLine,
  87. int nCmdShow
  88. )
  89. {
  90. MSG msg;
  91. HWND hwnd, hwndEdit;
  92. ghInst = hInstance;
  93. DialogBox(
  94. ghInst,
  95. MAKEINTRESOURCE(IDD_MAINDLG),
  96. NULL,
  97. MainWndProc
  98. );
  99. return 0;
  100. }
  101. INT_PTR
  102. CALLBACK
  103. MainWndProc(
  104. HWND hDlg,
  105. UINT uMsg,
  106. WPARAM wParam,
  107. LPARAM lParam
  108. )
  109. {
  110. LPCTSTR lszAppName = _T("Generate DialTone");
  111. DWORD dwNumDevs, i;
  112. LONG lResult;
  113. PHONEINITIALIZEEXPARAMS initExParams;
  114. PMYPHONE pNextPhone;
  115. PWCHAR szAddressToCall;
  116. ghDlg = hDlg;
  117. switch (uMsg)
  118. {
  119. case WM_INITDIALOG:
  120. initExParams.dwTotalSize = sizeof (PHONEINITIALIZEEXPARAMS);
  121. initExParams.dwOptions = (DWORD) PHONEINITIALIZEEXOPTION_USEHIDDENWINDOW;
  122. lResult = phoneInitializeEx(
  123. (LPHPHONEAPP) &ghPhoneApp,
  124. (HINSTANCE) ghInst,
  125. (PHONECALLBACK) tapiCallback,
  126. lszAppName,
  127. (LPDWORD) &dwNumDevs,
  128. (LPDWORD) &gdwAPIVersion,
  129. (LPPHONEINITIALIZEEXPARAMS) &initExParams
  130. );
  131. if (lResult == 0)
  132. {
  133. gdwNumPhoneDevs = dwNumDevs;
  134. }
  135. gpPhone = (PMYPHONE) LocalAlloc(LPTR,gdwNumPhoneDevs * sizeof(MYPHONE));
  136. g_wszMsg = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 100 );
  137. g_wszDest = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 100 );
  138. // Opening all the phones
  139. for(i = 0, pNextPhone = gpPhone; i < gdwNumPhoneDevs; i++, pNextPhone++)
  140. {
  141. CreatePhone(pNextPhone, i);
  142. }
  143. SetStatusMessage(TEXT("Waiting for input from Phones"));
  144. g_szDialStr = (LPWSTR) LocalAlloc(LPTR, 20 * sizeof(WCHAR));
  145. lstrcpy(g_szDialStr, TEXT("Dial Number: "));
  146. break;
  147. case WM_COMMAND:
  148. if ( LOWORD(wParam) == IDCANCEL )
  149. {
  150. //
  151. // The close box or Exit button was pressed.
  152. //
  153. SetStatusMessage(TEXT("End Application"));
  154. if(ghPhoneApp)
  155. {
  156. phoneShutdown(ghPhoneApp);
  157. }
  158. EndDialog( hDlg, 0 );
  159. LocalFree(g_szDialStr);
  160. LocalFree(g_wszMsg);
  161. LocalFree(g_wszDest);
  162. for( i=0; i<gdwNumPhoneDevs; i++ )
  163. {
  164. FreePhone(&gpPhone[i]);
  165. }
  166. LocalFree(gpPhone);
  167. }
  168. else if ( LOWORD(wParam) == IDC_MAKECALL )
  169. {
  170. //
  171. // The Make Call button was pressed.
  172. //
  173. //
  174. // Stop dialtone.
  175. // this only works for one phone.
  176. // Should be fine as we don't have
  177. // the window visible unless you have the phone off hook.
  178. //
  179. gpPhone[0].pTonePlayer->StopDialtone();
  180. //
  181. // Dial the dest address in the edit box.
  182. //
  183. const int ciMaxPhoneNumberSize = 400;
  184. WCHAR wszPhoneNumber[ciMaxPhoneNumberSize];
  185. UINT uiResult;
  186. uiResult = GetDlgItemText(
  187. ghDlg, // handle to dialog box
  188. IDC_DESTADDRESS, // identifier of control
  189. wszPhoneNumber, // pointer to buffer for text (unicode)
  190. ciMaxPhoneNumberSize // maximum size of string (in our buffer)
  191. );
  192. if ( uiResult == 0 )
  193. {
  194. DoMessage(L"Could not get dialog item text; not making call");
  195. }
  196. else
  197. {
  198. MakeAssistedTelephonyCall(wszPhoneNumber);
  199. }
  200. }
  201. break;
  202. default:
  203. break;
  204. }
  205. return 0;
  206. }
  207. VOID
  208. CALLBACK
  209. tapiCallback(
  210. DWORD hDevice,
  211. DWORD dwMsg,
  212. ULONG_PTR CallbackInstance,
  213. ULONG_PTR Param1,
  214. ULONG_PTR Param2,
  215. ULONG_PTR Param3
  216. )
  217. {
  218. PMYPHONE pPhone;
  219. DWORD i;
  220. BOOL bDialtone = FALSE;
  221. if (hDevice != NULL)
  222. {
  223. pPhone = GetPhone((HPHONE) hDevice);
  224. if (pPhone == NULL)
  225. {
  226. DEBUG(L"tapiCallback - phone not found\n");
  227. return;
  228. }
  229. }
  230. switch (dwMsg)
  231. {
  232. case PHONE_STATE:
  233. DEBUG(L"PHONE_STATE\n");
  234. if (pPhone != NULL)
  235. {
  236. EnterCriticalSection(&pPhone->csdial);
  237. if ( Param1 == PHONESTATE_HANDSETHOOKSWITCH )
  238. {
  239. if ( Param2 != PHONEHOOKSWITCHMODE_ONHOOK ) // if off hook
  240. {
  241. if ( FAILED(pPhone->pTonePlayer->StartDialtone()) )
  242. {
  243. DoMessage(L"StartDialTone Failed");
  244. }
  245. // ZoltanS: show the window now
  246. ShowWindow(ghDlg, SW_SHOWNORMAL);
  247. pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_MICSPEAKER;
  248. lstrcpy(pPhone->wszDialStr,TEXT(""));
  249. lstrcpy(g_wszMsg,TEXT("Generating Dialtone for phones: "));
  250. for( i=0 ; i < gdwNumPhoneDevs; i++)
  251. {
  252. if ( gpPhone[i].pTonePlayer->IsInUse() )
  253. {
  254. wsprintf(g_wszDest,TEXT("%d"),i);
  255. lstrcat(g_wszMsg,g_wszDest);
  256. }
  257. }
  258. SetStatusMessage(g_wszMsg);
  259. }
  260. else // on hook
  261. {
  262. pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_ONHOOK;
  263. lstrcpy(pPhone->wszDialStr,TEXT(""));
  264. if ( pPhone->pTonePlayer->IsInUse() )
  265. {
  266. pPhone->pTonePlayer->StopDialtone();
  267. }
  268. // ZoltanS: hide the window now
  269. ShowWindow(ghDlg, SW_HIDE);
  270. bDialtone = FALSE;
  271. lstrcpy(g_wszMsg,TEXT("Generating Dialtone for phones: "));
  272. for( i = 0 ; i < gdwNumPhoneDevs; i++ )
  273. {
  274. if ( gpPhone[i].pTonePlayer->DialtonePlaying() )
  275. {
  276. wsprintf(g_wszDest,TEXT("%d"),i);
  277. lstrcat(g_wszMsg,g_wszDest);
  278. bDialtone = TRUE;
  279. }
  280. }
  281. if(!bDialtone)
  282. {
  283. SetStatusMessage(TEXT("Waiting for input from Phones"));
  284. }
  285. else
  286. {
  287. SetStatusMessage(g_wszMsg);
  288. }
  289. }
  290. }
  291. LeaveCriticalSection(&pPhone->csdial);
  292. }
  293. break;
  294. case PHONE_BUTTON:
  295. DEBUG(L"PHONE_BUTTON\n");
  296. if (pPhone != NULL)
  297. {
  298. EnterCriticalSection(&pPhone->csdial);
  299. if ( Param2 == PHONEBUTTONMODE_KEYPAD )
  300. {
  301. if (pPhone->dwHandsetMode != PHONEHOOKSWITCHMODE_ONHOOK)
  302. {
  303. if ( Param3 == PHONEBUTTONSTATE_DOWN )
  304. {
  305. if ( pPhone->pTonePlayer->IsInUse() )
  306. {
  307. if ( ( (int)Param1 >= 0 ) && ( (int)Param1 <= 9 ) )
  308. {
  309. //
  310. // We have a dialed digit. Append it to the phone
  311. // number we have so far.
  312. //
  313. wsprintf(g_wszDest, TEXT("%d"), Param1);
  314. lstrcat(pPhone->wszDialStr, g_wszDest);
  315. //
  316. // Append the phone number so far to a standard prefix
  317. // ("Phone number: ") and update the UI.
  318. //
  319. lstrcpy(g_wszMsg, g_szDialStr);
  320. lstrcat(g_wszMsg,pPhone->wszDialStr);
  321. SetStatusMessage(g_wszMsg);
  322. //
  323. // Generate a DTMF tone for this digit.
  324. //
  325. pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
  326. }
  327. else if ( Param1 == 10 )
  328. {
  329. //
  330. // Generate a DTMF tone for "*". This will not count
  331. // as part of the dialed number.
  332. //
  333. pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
  334. }
  335. else if ( Param1 == 11 )
  336. {
  337. //
  338. // Generate a DTMF tone for "#". This will not count
  339. // as part of the dialed number but it will tell us
  340. // to make the call immediately.
  341. //
  342. pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
  343. //
  344. // Make the call.
  345. //
  346. if ( S_OK == MakeAssistedTelephonyCall(pPhone->wszDialStr) )
  347. {
  348. SetStatusMessage(L"Call created");
  349. }
  350. else
  351. {
  352. SetStatusMessage(L"Failed to create the call");
  353. }
  354. }
  355. } // if in use
  356. } // if button down
  357. } // if off hook
  358. } // if keypad
  359. LeaveCriticalSection(&pPhone->csdial);
  360. }
  361. break; // case phone_button
  362. case PHONE_CLOSE:
  363. DEBUG(L"PHONE_CLOSE\n");
  364. if (pPhone != NULL)
  365. {
  366. EnterCriticalSection(&pPhone->csdial);
  367. phoneClose(pPhone->hPhone);
  368. LeaveCriticalSection(&pPhone->csdial);
  369. }
  370. break;
  371. case PHONE_REMOVE:
  372. DEBUG(L"PHONE_REMOVE\n");
  373. pPhone = GetPhoneByID( (DWORD)Param1);
  374. if (pPhone != NULL)
  375. {
  376. FreePhone(pPhone);
  377. RemovePhone(pPhone);
  378. }
  379. break;
  380. case PHONE_CREATE:
  381. DEBUG(L"PHONE_CREATE\n");
  382. pPhone = AddPhone();
  383. CreatePhone(pPhone, (DWORD)Param1);
  384. break;
  385. default:
  386. break;
  387. }
  388. }
  389. //////////////////////////////////////////////////////////////////
  390. // SetStatusMessage
  391. //////////////////////////////////////////////////////////////////
  392. void
  393. SetStatusMessage(
  394. LPWSTR pszMessage
  395. )
  396. {
  397. SetDlgItemText(
  398. ghDlg,
  399. IDC_STATUS,
  400. pszMessage
  401. );
  402. }
  403. //////////////////////////////////////////////////////////////////
  404. // CreatePhone
  405. //////////////////////////////////////////////////////////////////
  406. void
  407. CreatePhone(
  408. PMYPHONE pPhone,
  409. DWORD dwDevID
  410. )
  411. {
  412. LRESULT lResult;
  413. pPhone->hPhoneApp = ghPhoneApp;
  414. InitializeCriticalSection(&pPhone->csdial);
  415. // won't detect overrun if dialing more than 100 digits
  416. pPhone->wszDialStr = (LPWSTR) LocalAlloc(LPTR, 100 * sizeof(WCHAR));
  417. pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_ONHOOK;
  418. lResult = phoneOpen(
  419. ghPhoneApp,
  420. dwDevID,
  421. &pPhone->hPhone,
  422. gdwAPIVersion,
  423. 0,
  424. (DWORD_PTR) NULL,
  425. PHONEPRIVILEGE_OWNER
  426. );
  427. //
  428. // Save info about this phone that we can display later
  429. //
  430. pPhone->dwDevID = dwDevID;
  431. pPhone->dwAPIVersion = gdwAPIVersion;
  432. pPhone->dwPrivilege = PHONEPRIVILEGE_OWNER;
  433. DWORD dwBigBuffSize = sizeof(VARSTRING) +
  434. sizeof(DWORD) * 5;
  435. LPVOID pBuffer = LocalAlloc(LPTR,dwBigBuffSize);
  436. LPVARSTRING lpDeviceID = (LPVARSTRING) pBuffer;
  437. lpDeviceID->dwTotalSize = dwBigBuffSize;
  438. LPWSTR lpszDeviceClass;
  439. lpszDeviceClass = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 20);
  440. lstrcpy(lpszDeviceClass, TEXT("wave/in"));
  441. lResult = phoneGetID(
  442. pPhone->hPhone,
  443. lpDeviceID,
  444. lpszDeviceClass
  445. );
  446. if(lResult != 0)
  447. {
  448. pPhone->lCaptureID = WAVE_MAPPER;
  449. }
  450. else
  451. {
  452. CopyMemory(
  453. &pPhone->lCaptureID,
  454. (LPBYTE) lpDeviceID + lpDeviceID->dwStringOffset,
  455. lpDeviceID->dwStringSize
  456. );
  457. }
  458. lstrcpy(lpszDeviceClass, TEXT("wave/out"));
  459. lResult = phoneGetID(
  460. pPhone->hPhone,
  461. lpDeviceID,
  462. lpszDeviceClass
  463. );
  464. if(lResult != 0)
  465. {
  466. pPhone->lRenderID = WAVE_MAPPER;
  467. }
  468. else
  469. {
  470. CopyMemory(
  471. &pPhone->lRenderID,
  472. (LPBYTE) lpDeviceID + lpDeviceID->dwStringOffset,
  473. lpDeviceID->dwStringSize
  474. );
  475. }
  476. LocalFree(lpszDeviceClass);
  477. LocalFree(pBuffer);
  478. lResult = phoneSetStatusMessages(
  479. pPhone->hPhone,
  480. PHONESTATE_HANDSETHOOKSWITCH,
  481. PHONEBUTTONMODE_FEATURE | PHONEBUTTONMODE_KEYPAD,
  482. PHONEBUTTONSTATE_UP | PHONEBUTTONSTATE_DOWN
  483. );
  484. pPhone->pTonePlayer = new CTonePlayer;
  485. if ( (pPhone->pTonePlayer == NULL) ||
  486. FAILED(pPhone->pTonePlayer->Initialize()) )
  487. {
  488. DoMessage(L"Tone Player Initialization Failed");
  489. }
  490. else if ( FAILED(pPhone->pTonePlayer->OpenWaveDevice( pPhone->lRenderID )) )
  491. {
  492. DoMessage(L"OpenWaveDevice Failed");
  493. }
  494. if ( FAILED( InitAssistedTelephony() ) )
  495. {
  496. DoMessage(L"InitAssistedTelephony Failed");
  497. }
  498. }
  499. //////////////////////////////////////////////////////////////////
  500. // FreePhone
  501. //////////////////////////////////////////////////////////////////
  502. void
  503. FreePhone(
  504. PMYPHONE pPhone
  505. )
  506. {
  507. EnterCriticalSection(&pPhone->csdial);
  508. if ( pPhone->pTonePlayer->IsInUse() )
  509. {
  510. pPhone->pTonePlayer->StopDialtone();
  511. pPhone->pTonePlayer->CloseWaveDevice();
  512. }
  513. LocalFree(pPhone->wszDialStr);
  514. LeaveCriticalSection(&pPhone->csdial);
  515. DeleteCriticalSection(&pPhone->csdial);
  516. }
  517. ///////////////////////////////////////////////////////////////////
  518. // GetPhone
  519. ///////////////////////////////////////////////////////////////////
  520. PMYPHONE
  521. GetPhone (HPHONE hPhone )
  522. {
  523. DWORD i;
  524. for(i = 0; i < gdwNumPhoneDevs; i++)
  525. {
  526. if(gpPhone[i].hPhone == hPhone)
  527. {
  528. return &gpPhone[i];
  529. }
  530. }
  531. return (PMYPHONE) NULL;
  532. }
  533. ///////////////////////////////////////////////////////////////////
  534. // GetPhoneByID
  535. ///////////////////////////////////////////////////////////////////
  536. PMYPHONE
  537. GetPhoneByID (DWORD dwDevID )
  538. {
  539. DWORD i;
  540. for(i = 0; i < gdwNumPhoneDevs; i++)
  541. {
  542. if(gpPhone[i].dwDevID == dwDevID)
  543. {
  544. return &gpPhone[i];
  545. }
  546. }
  547. return (PMYPHONE) NULL;
  548. }
  549. ///////////////////////////////////////////////////////////////////
  550. // RemovePhone
  551. ///////////////////////////////////////////////////////////////////
  552. void
  553. RemovePhone (PMYPHONE pPhone)
  554. {
  555. DWORD i,j;
  556. PMYPHONE pNewPhones;
  557. pNewPhones = (PMYPHONE) LocalAlloc(LPTR,(gdwNumPhoneDevs-1) * sizeof(MYPHONE));
  558. for(i = 0, j = 0; i < gdwNumPhoneDevs; i++)
  559. {
  560. if(&gpPhone[i] != pPhone)
  561. {
  562. CopyMemory( &pNewPhones[j], &gpPhone[i], sizeof(MYPHONE));
  563. j++;
  564. }
  565. }
  566. LocalFree(gpPhone);
  567. gpPhone = pNewPhones;
  568. gdwNumPhoneDevs--;
  569. }
  570. ///////////////////////////////////////////////////////////////////
  571. // AddPhone
  572. ///////////////////////////////////////////////////////////////////
  573. PMYPHONE
  574. AddPhone ()
  575. {
  576. PMYPHONE pNewPhones;
  577. pNewPhones = (PMYPHONE) LocalAlloc(LPTR,(gdwNumPhoneDevs+1) * sizeof(MYPHONE));
  578. CopyMemory( pNewPhones, gpPhone, gdwNumPhoneDevs * sizeof(MYPHONE));
  579. LocalFree(gpPhone);
  580. gpPhone = pNewPhones;
  581. gdwNumPhoneDevs++;
  582. return &gpPhone[gdwNumPhoneDevs-1];
  583. }
  584. ///////////////////////////////////////////////////////////////////
  585. // DoMessage
  586. ///////////////////////////////////////////////////////////////////
  587. void
  588. DoMessage(
  589. LPWSTR pszMessage
  590. )
  591. {
  592. MessageBox(
  593. ghDlg,
  594. pszMessage,
  595. gszTapi30,
  596. MB_OK
  597. );
  598. }