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.

1003 lines
23 KiB

  1. #include <windows.h>
  2. #include <commctrl.h>
  3. #include <shellapi.h>
  4. #include <limits.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <tchar.h>
  9. #include <winfax.h>
  10. #include <faxutil.h>
  11. #include <mmsystem.h>
  12. #include <winspool.h>
  13. #include "resource.h"
  14. #include "faxstat.h"
  15. #include "faxreg.h"
  16. #include "faxcfg.h"
  17. #include "faxhelp.h"
  18. #define ValidString( String ) ((String) ? (String) : TEXT( "" ))
  19. // global variables
  20. BOOL IsShowing = FALSE;
  21. BOOL IsOnTaskBar = FALSE;
  22. NOTIFYICONDATA IconData; // icon data
  23. DWORD Seconds;
  24. LPTSTR TimeSeparator = NULL;
  25. LIST_ENTRY EventListHead;
  26. DWORD EventCount;
  27. // configuration options and their defaults
  28. CONFIG_OPTIONS Config = {
  29. BST_CHECKED, // OnTop
  30. BST_CHECKED, // TaskBar
  31. BST_CHECKED, // VisualNotification
  32. BST_UNCHECKED, // SoundNotification
  33. BST_UNCHECKED, // AnswerNextCall
  34. BST_UNCHECKED // ManualAnswerEnabled
  35. };
  36. extern HANDLE FaxPortHandle;
  37. extern HANDLE hFax;
  38. INSTANCE_DATA FaxStat;
  39. int
  40. WINAPI
  41. #ifdef UNICODE
  42. wWinMain(
  43. #else
  44. WinMain(
  45. #endif
  46. HINSTANCE hInstance,
  47. HINSTANCE hPrevInstance,
  48. LPTSTR lpCmdLine,
  49. int nShowCmd
  50. )
  51. {
  52. //
  53. // szAppname must match the window class in the resource file
  54. //
  55. static TCHAR szAppName[] = FAXSTAT_WINCLASS;
  56. MSG msg;
  57. WNDCLASSEX wndclass;
  58. HWND hWnd;
  59. HACCEL hAccel;
  60. //
  61. // if we are already running, then activate the window and exit
  62. //
  63. hWnd = FindWindow( szAppName, NULL );
  64. if (hWnd) {
  65. PostMessage( hWnd, ACTIVATE, 0, 0 );
  66. ExitProcess( 1 );
  67. }
  68. FaxStat.hInstance = hInstance;
  69. InitCommonControls();
  70. HeapInitialize(NULL,NULL,NULL,0);
  71. InitializeEventList();
  72. hAccel = LoadAccelerators( hInstance, TEXT( "MyAccelerators" ) );
  73. wndclass.cbSize = sizeof(wndclass);
  74. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  75. wndclass.lpfnWndProc = WndProc;
  76. wndclass.cbClsExtra = 0;
  77. wndclass.cbWndExtra = DLGWINDOWEXTRA;
  78. wndclass.hInstance = hInstance;
  79. wndclass.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON1 ) );
  80. wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
  81. wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW);
  82. wndclass.lpszMenuName = NULL;
  83. wndclass.lpszClassName = szAppName;
  84. wndclass.hIconSm = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_ICON1 ) );
  85. RegisterClassEx( &wndclass );
  86. hWnd = FaxStat.hWnd = CreateDialog( hInstance, MAKEINTRESOURCE( IDD_FAXSTATUS ), 0, NULL);
  87. MyShowWindow( hWnd, FALSE );
  88. SetWindowLong( hWnd, GWL_USERDATA, (LONG) &FaxStat );
  89. FaxStat.ServerName = lpCmdLine[0] ? lpCmdLine : NULL;
  90. WorkerThreadInitialize( &FaxStat );
  91. PostMessage( hWnd, CONFIGUPDATE, 0, 0 );
  92. PostMessage( hWnd, INITANIMATION, 0, 0 );
  93. while (GetMessage( &msg, NULL, 0, 0 )) {
  94. if (!TranslateAccelerator( hWnd, hAccel, &msg )) {
  95. TranslateMessage( &msg );
  96. DispatchMessage(&msg);
  97. }
  98. }
  99. return msg.wParam;
  100. }
  101. VOID
  102. CALLBACK
  103. TimerProc(
  104. HWND hWnd,
  105. UINT iMsg,
  106. UINT iTimerID,
  107. DWORD dwTime
  108. )
  109. {
  110. TCHAR StrBuf[STR_SIZE];
  111. Seconds++;
  112. _stprintf(
  113. StrBuf,
  114. TEXT( "%d%s%02d" ),
  115. Seconds / 60,
  116. TimeSeparator,
  117. Seconds % 60
  118. );
  119. SetDlgItemText( hWnd, IDC_TIME, StrBuf );
  120. }
  121. VOID
  122. StatusUpdate(
  123. HWND hWnd,
  124. DWORD EventId,
  125. DWORD LastEventId,
  126. PFAX_DEVICE_STATUS fds
  127. )
  128. {
  129. TCHAR FormatBuf[STR_SIZE];
  130. TCHAR StrBuf[STR_SIZE];
  131. INT FromTo = -1;
  132. static int CurrentPage;
  133. static BOOL FaxActive = FALSE; // this is TRUE when sending or receiving
  134. PEVENT_RECORD NewEvent;
  135. PINSTANCE_DATA pInst = (PINSTANCE_DATA) GetWindowLong( hWnd, GWL_USERDATA );
  136. if (EventId == FEI_ABORTING && LastEventId == FEI_ABORTING) {
  137. return;
  138. }
  139. if (TimeSeparator == NULL) {
  140. INT BytesNeeded;
  141. BytesNeeded = GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_STIME, NULL, 0 );
  142. TimeSeparator = MemAlloc( BytesNeeded + 4);
  143. BytesNeeded = GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_STIME, TimeSeparator, BytesNeeded );
  144. }
  145. LoadString( pInst->hInstance, EventId, FormatBuf, STR_SIZE );
  146. if (fds && EventId != LastEventId) {
  147. CurrentPage = fds->CurrentPage;
  148. //pInst->JobId = fds->JobId;
  149. } else {
  150. CurrentPage++;
  151. }
  152. if (EventId == FEI_DIALING) {
  153. _stprintf( StrBuf, FormatBuf, ValidString( fds->PhoneNumber ) );
  154. EnableWindow( GetDlgItem( hWnd, IDC_FAXEND ), TRUE );
  155. } else if (EventId == FEI_SENDING || EventId == FEI_RECEIVING) {
  156. FromTo = EventId == FEI_SENDING ? IDS_TO : IDS_FROM;
  157. _stprintf( StrBuf, FormatBuf, CurrentPage );
  158. EnableWindow( GetDlgItem( hWnd, IDC_FAXEND ), TRUE );
  159. } else {
  160. _tcscpy( StrBuf, FormatBuf );
  161. EnableWindow( GetDlgItem( hWnd, IDC_FAXEND ), FALSE );
  162. }
  163. NewEvent = InsertEventRecord( EventId, StrBuf );
  164. if (pInst->hEventDlg != NULL) {
  165. InsertEventDialog( pInst->hEventDlg, NewEvent );
  166. }
  167. SetDlgItemText( pInst->hWnd, IDC_STATUS, StrBuf );
  168. if (IsOnTaskBar) {
  169. IconData.uFlags = NIF_TIP;
  170. _tcscpy( IconData.szTip, StrBuf );
  171. Shell_NotifyIcon( NIM_MODIFY, &IconData );
  172. }
  173. switch(FromTo) {
  174. case IDS_FROM:
  175. case IDS_TO:
  176. if (!FaxActive) {
  177. PlayAnimation( GetDlgItem( pInst->hWnd, IDC_ANIMATE1 ), FromTo == IDS_FROM ? IDR_RECEIVE : IDR_SEND );
  178. LoadString( pInst->hInstance, FromTo, StrBuf, STR_SIZE );
  179. _tcscat( StrBuf, ValidString( fds->Tsid ) );
  180. SetDlgItemText( pInst->hWnd, IDC_FROMTO, StrBuf );
  181. LoadString( pInst->hInstance, IDS_ETIME, StrBuf, STR_SIZE );
  182. SetDlgItemText( pInst->hWnd, IDC_STATICTIME, StrBuf );
  183. Seconds = 0;
  184. _stprintf(
  185. StrBuf,
  186. TEXT( "%d%s%02d" ),
  187. 0,
  188. TimeSeparator,
  189. 0
  190. );
  191. SetDlgItemText( pInst->hWnd, IDC_TIME, StrBuf );
  192. SetTimer( pInst->hWnd, ID_TIMER, 1000, (TIMERPROC) TimerProc );
  193. FaxActive = TRUE;
  194. }
  195. break;
  196. default:
  197. SetDlgItemText( pInst->hWnd, IDC_FROMTO, TEXT( "" ) );
  198. SetDlgItemText( pInst->hWnd, IDC_STATICTIME, TEXT( "" ) );
  199. SetDlgItemText( pInst->hWnd, IDC_TIME, TEXT( "" ) );
  200. StrBuf[0] = 0;
  201. if (FaxActive) {
  202. PlayAnimation( GetDlgItem( pInst->hWnd, IDC_ANIMATE1 ), IDR_IDLE );
  203. KillTimer( pInst->hWnd, ID_TIMER );
  204. FaxActive = FALSE;
  205. }
  206. }
  207. if (EventId == FEI_DIALING || (EventId == FEI_RINGING && LastEventId != FEI_RINGING)) {
  208. if (IsOptionOn( Config.VisualNotification )) {
  209. MyShowWindow( pInst->hWnd, TRUE );
  210. }
  211. if (IsOptionOn( Config.SoundNotification )) {
  212. PlaySound( TEXT( "Incoming-Fax" ), NULL, SND_ASYNC | SND_APPLICATION );
  213. }
  214. if (EventId == FEI_RINGING && IsOptionOn( Config.ManualAnswerEnabled )) {
  215. HANDLE FaxJobHandle;
  216. TCHAR FileName[256];
  217. DWORD rVal;
  218. if (IsOptionOn( Config.AnswerNextCall )) {
  219. rVal = IDYES;
  220. } else {
  221. rVal = DialogBoxParam(
  222. FaxStat.hInstance,
  223. MAKEINTRESOURCE( IDD_ANSWER ),
  224. hWnd,
  225. AnswerDlgProc,
  226. (LPARAM) &FaxStat
  227. );
  228. }
  229. if ( rVal == IDYES ) {
  230. FaxReceiveDocument( hFax, FileName, 256, &FaxJobHandle );
  231. CheckDlgButton( hWnd, IDC_ANSWER_NEXT_CALL, BST_UNCHECKED );
  232. Config.AnswerNextCall = BST_UNCHECKED;
  233. }
  234. }
  235. }
  236. if (pInst->hAnswerDlg && EventId != FEI_RINGING) {
  237. PostMessage( pInst->hAnswerDlg, WM_COMMAND, IDNO, 0 );
  238. }
  239. }
  240. BOOL
  241. CALLBACK
  242. AnswerDlgProc(
  243. HWND hDlg,
  244. UINT iMsg,
  245. WPARAM wParam,
  246. LPARAM lParam
  247. )
  248. {
  249. static PINSTANCE_DATA pInst;
  250. switch(iMsg) {
  251. case WM_INITDIALOG:
  252. pInst = (PINSTANCE_DATA) lParam;
  253. pInst->hAnswerDlg = hDlg;
  254. return TRUE;
  255. case WM_COMMAND:
  256. switch(LOWORD( wParam )) {
  257. case IDYES:
  258. case IDNO:
  259. EndDialog( hDlg, LOWORD( wParam ) );
  260. pInst->hAnswerDlg = NULL;
  261. return TRUE;
  262. }
  263. break;
  264. }
  265. return FALSE;
  266. }
  267. BOOL
  268. CALLBACK
  269. EventDlgProc(
  270. HWND hDlg,
  271. UINT iMsg,
  272. WPARAM wParam,
  273. LPARAM lParam
  274. )
  275. {
  276. LV_COLUMN lvc = {0};
  277. HWND hWndCtrl = GetDlgItem( hDlg, IDC_LIST1 );
  278. PLIST_ENTRY Next;
  279. TCHAR StrBuf[STR_SIZE];
  280. static PINSTANCE_DATA pInst;
  281. switch(iMsg) {
  282. case WM_INITDIALOG:
  283. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  284. pInst = (PINSTANCE_DATA) lParam;
  285. LoadString( pInst->hInstance, IDS_TIMELABEL, StrBuf, STR_SIZE );
  286. lvc.pszText = StrBuf;
  287. lvc.iSubItem = 0;
  288. lvc.cx = 70;
  289. lvc.fmt = LVCFMT_LEFT;
  290. ListView_InsertColumn( hWndCtrl, 0, &lvc );
  291. LoadString( pInst->hInstance, IDS_EVENTLABEL, StrBuf, STR_SIZE );
  292. lvc.pszText = StrBuf;
  293. lvc.iSubItem = 1;
  294. lvc.cx = 180;
  295. lvc.fmt = LVCFMT_LEFT;
  296. ListView_InsertColumn( hWndCtrl, 1, &lvc );
  297. if (!IsListEmpty( &EventListHead )) {
  298. PEVENT_RECORD EventRecord;
  299. for (Next = EventListHead.Flink; Next != &EventListHead; Next = Next->Flink) {
  300. EventRecord = CONTAINING_RECORD( Next, EVENT_RECORD, ListEntry );
  301. InsertEventDialog( hDlg, EventRecord );
  302. }
  303. }
  304. pInst->hEventDlg = hDlg;
  305. return TRUE;
  306. case WM_COMMAND:
  307. switch(LOWORD( wParam )) {
  308. case IDOK:
  309. case IDCANCEL:
  310. EndDialog( hDlg, 0 );
  311. pInst->hEventDlg = NULL;
  312. return TRUE;
  313. }
  314. break;
  315. }
  316. return FALSE;
  317. }
  318. VOID
  319. InsertEventDialog(
  320. HWND hDlg,
  321. PEVENT_RECORD pEventRecord
  322. )
  323. {
  324. LV_ITEM lvi = {0};
  325. HWND hWndCtrl = GetDlgItem( hDlg, IDC_LIST1 );
  326. INT iItem;
  327. TCHAR TimeBuf[STR_SIZE];
  328. GetTimeFormat(
  329. LOCALE_USER_DEFAULT,
  330. 0,
  331. &pEventRecord->Time,
  332. NULL,
  333. TimeBuf,
  334. STR_SIZE
  335. );
  336. lvi.pszText = TimeBuf;
  337. lvi.iItem = ListView_GetItemCount( hWndCtrl );
  338. lvi.iSubItem = 0;
  339. lvi.mask = LVIF_TEXT;
  340. iItem = ListView_InsertItem( hWndCtrl, &lvi );
  341. lvi.pszText = pEventRecord->StrBuf;
  342. lvi.iItem = iItem;
  343. lvi.iSubItem = 1;
  344. lvi.mask = LVIF_TEXT;
  345. ListView_SetItem( hWndCtrl, &lvi );
  346. ListView_Scroll( hWndCtrl, 0, iItem );
  347. }
  348. LRESULT
  349. CALLBACK
  350. WndProc(
  351. HWND hWnd,
  352. UINT iMsg,
  353. WPARAM wParam,
  354. LPARAM lParam
  355. )
  356. {
  357. static DWORD EventId;
  358. static DWORD LastEventId = 0;
  359. static const DWORD monitorHelpIDs[] = {
  360. IDC_FAXEND, IDH_FAXMONITOR_END_CALL,
  361. IDC_DETAILS, IDH_FAXMONITOR_DETAILS,
  362. IDC_STATUS, IDH_FAXMONITOR_STATUS,
  363. IDC_ANSWER_NEXT_CALL, IDH_FAXMONITOR_ANSWER_NEXT_CALL,
  364. 0, 0
  365. };
  366. PFAX_DEVICE_STATUS FaxDeviceStatus;
  367. switch(iMsg)
  368. {
  369. case WM_CREATE:
  370. CenterWindow( hWnd, GetDesktopWindow() );
  371. return 0;
  372. case TRAYCALLBACK:
  373. switch (lParam) {
  374. case WM_LBUTTONDOWN:
  375. MyShowWindow( hWnd, TRUE );
  376. return 0;
  377. case WM_RBUTTONDOWN:
  378. //
  379. // execute the control panel applet
  380. // if the property page number ever changes, it must be changed
  381. // here also
  382. //
  383. ShellExecute(
  384. hWnd,
  385. TEXT( "open" ),
  386. TEXT( "rundll32" ),
  387. TEXT( "shell32.dll,Control_RunDLL faxcfg.cpl,Fax,7" ),
  388. TEXT( "." ),
  389. SW_SHOWNORMAL
  390. );
  391. return 0;
  392. }
  393. break;
  394. case CONFIGUPDATE:
  395. GetConfiguration();
  396. if (IsOptionOn( Config.ManualAnswerEnabled )) {
  397. EnableWindow( GetDlgItem( hWnd, IDC_ANSWER_NEXT_CALL ), TRUE );
  398. } else {
  399. CheckDlgButton( hWnd, IDC_ANSWER_NEXT_CALL, BST_UNCHECKED );
  400. EnableWindow( GetDlgItem( hWnd, IDC_ANSWER_NEXT_CALL ), FALSE );
  401. }
  402. MyShowWindow( hWnd, IsShowing );
  403. return 0;
  404. case ACTIVATE:
  405. MyShowWindow( hWnd, TRUE );
  406. return 0;
  407. case INITANIMATION:
  408. PlayAnimation( GetDlgItem( hWnd, IDC_ANIMATE1 ), IDR_IDLE );
  409. return 0;
  410. case STATUSUPDATE:
  411. LastEventId = EventId;
  412. EventId = wParam;
  413. FaxDeviceStatus = (PFAX_DEVICE_STATUS) lParam;
  414. StatusUpdate( hWnd, EventId, LastEventId, FaxDeviceStatus );
  415. return 0;
  416. case WM_SYSCOMMAND:
  417. if (wParam == SC_CLOSE) {
  418. MyShowWindow( hWnd, FALSE );
  419. return 0;
  420. } else {
  421. break;
  422. }
  423. case WM_COMMAND:
  424. SetFocus( hWnd );
  425. switch (LOWORD(wParam)) {
  426. BOOL rVal;
  427. HANDLE PrinterHandle;
  428. HWND hButton;
  429. case IDC_FAXEND:
  430. hButton = GetDlgItem( hWnd, LOWORD(wParam));
  431. if (IsWindowEnabled( hButton )) {
  432. if (HIWORD(wParam)) { // accelerator key
  433. SendMessage( hButton, BM_SETSTATE, 1, 0 );
  434. SendMessage( hButton, BM_SETSTATE, 0, 0 );
  435. }
  436. rVal = OpenPrinter( FaxStat.PrinterName, &PrinterHandle, NULL );
  437. rVal = SetJob( PrinterHandle, FaxStat.JobId, 0, NULL, JOB_CONTROL_CANCEL );
  438. ClosePrinter( PrinterHandle );
  439. EnableWindow( hButton, FALSE);
  440. SendMessage( hWnd, STATUSUPDATE, FEI_ABORTING, 0 );
  441. }
  442. break;
  443. case IDC_DETAILS:
  444. if (HIWORD(wParam)) { // accelerator key
  445. SendMessage( GetDlgItem( hWnd, LOWORD(wParam)), BM_SETSTATE, 1, 0 );
  446. SendMessage( GetDlgItem( hWnd, LOWORD(wParam)), BM_SETSTATE, 0, 0 );
  447. }
  448. DialogBoxParam(
  449. FaxStat.hInstance,
  450. MAKEINTRESOURCE( IDD_DETAILS ),
  451. hWnd,
  452. EventDlgProc,
  453. (LPARAM) &FaxStat
  454. );
  455. break;
  456. case IDC_EXIT:
  457. if (IsOnTaskBar) {
  458. Shell_NotifyIcon( NIM_DELETE, &IconData );
  459. }
  460. Disconnect();
  461. PostQuitMessage( 0 );
  462. break;
  463. case IDC_ANSWER_NEXT_CALL:
  464. if (IsWindowEnabled( GetDlgItem( hWnd, IDC_ANSWER_NEXT_CALL ))) {
  465. CheckDlgButton(
  466. hWnd,
  467. IDC_ANSWER_NEXT_CALL,
  468. IsDlgButtonChecked( hWnd, IDC_ANSWER_NEXT_CALL ) == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED
  469. );
  470. Config.AnswerNextCall = IsDlgButtonChecked( hWnd, IDC_ANSWER_NEXT_CALL );
  471. }
  472. break;
  473. }
  474. return 0;
  475. case WM_DESTROY:
  476. PostQuitMessage( 0 );
  477. return 0;
  478. case WM_HELP:
  479. case WM_CONTEXTMENU:
  480. FAXWINHELP( iMsg, wParam, lParam, monitorHelpIDs );
  481. return 0;
  482. }
  483. return DefWindowProc( hWnd, iMsg, wParam, lParam );
  484. }
  485. VOID
  486. InitializeEventList(
  487. VOID
  488. )
  489. {
  490. InitializeListHead( &EventListHead );
  491. EventCount = 0;
  492. }
  493. PEVENT_RECORD
  494. InsertEventRecord(
  495. DWORD EventId,
  496. LPTSTR String
  497. )
  498. {
  499. PEVENT_RECORD NewEvent;
  500. PLIST_ENTRY pListEntry;
  501. if (EventCount == MAX_EVENTS) {
  502. pListEntry = RemoveHeadList( &EventListHead );
  503. NewEvent = CONTAINING_RECORD( pListEntry, EVENT_RECORD, ListEntry );
  504. } else {
  505. NewEvent = MemAlloc( sizeof(EVENT_RECORD) );
  506. EventCount++;
  507. }
  508. GetLocalTime( &NewEvent->Time );
  509. NewEvent->EventId= EventId;
  510. _tcscpy( NewEvent->StrBuf, String );
  511. InsertTailList( &EventListHead, &NewEvent->ListEntry );
  512. return NewEvent;
  513. }
  514. DWORD
  515. MapStatusIdToEventId(
  516. DWORD StatusId
  517. )
  518. {
  519. DWORD EventId = 0;
  520. if (StatusId & FPS_AVAILABLE) {
  521. StatusId &= FPS_AVAILABLE;
  522. }
  523. switch( StatusId ) {
  524. case FPS_DIALING:
  525. EventId = FEI_DIALING;
  526. break;
  527. case FPS_SENDING:
  528. EventId = FEI_SENDING;
  529. break;
  530. case FPS_RECEIVING:
  531. EventId = FEI_RECEIVING;
  532. break;
  533. case FPS_COMPLETED:
  534. EventId = FEI_COMPLETED;
  535. break;
  536. case FPS_BUSY:
  537. EventId = FEI_BUSY;
  538. break;
  539. case FPS_NO_ANSWER:
  540. EventId = FEI_NO_ANSWER;
  541. break;
  542. case FPS_BAD_ADDRESS:
  543. EventId = FEI_BAD_ADDRESS;
  544. break;
  545. case FPS_NO_DIAL_TONE:
  546. EventId = FEI_NO_DIAL_TONE;
  547. break;
  548. case FPS_DISCONNECTED:
  549. EventId = FEI_DISCONNECTED;
  550. break;
  551. case FPS_FATAL_ERROR:
  552. EventId = FEI_FATAL_ERROR;
  553. break;
  554. case FPS_NOT_FAX_CALL:
  555. EventId = FEI_NOT_FAX_CALL;
  556. break;
  557. case FPS_CALL_DELAYED:
  558. EventId = FEI_CALL_DELAYED;
  559. break;
  560. case FPS_CALL_BLACKLISTED:
  561. EventId = FEI_CALL_BLACKLISTED;
  562. break;
  563. case FPS_RINGING:
  564. EventId = FEI_RINGING;
  565. break;
  566. case FPS_ABORTING:
  567. EventId = FEI_ABORTING;
  568. break;
  569. case FPS_ROUTING:
  570. EventId = FEI_ROUTING;
  571. break;
  572. case FPS_AVAILABLE:
  573. EventId = FEI_IDLE;
  574. break;
  575. case FPS_ANSWERED:
  576. EventId = FEI_ANSWERED;
  577. break;
  578. }
  579. return EventId;
  580. }
  581. VOID
  582. FitRectToScreen(
  583. PRECT prc
  584. )
  585. {
  586. INT cxScreen;
  587. INT cyScreen;
  588. INT delta;
  589. cxScreen = GetSystemMetrics(SM_CXSCREEN);
  590. cyScreen = GetSystemMetrics(SM_CYSCREEN);
  591. if (prc->right > cxScreen) {
  592. delta = prc->right - prc->left;
  593. prc->right = cxScreen;
  594. prc->left = prc->right - delta;
  595. }
  596. if (prc->left < 0) {
  597. delta = prc->right - prc->left;
  598. prc->left = 0;
  599. prc->right = prc->left + delta;
  600. }
  601. if (prc->bottom > cyScreen) {
  602. delta = prc->bottom - prc->top;
  603. prc->bottom = cyScreen;
  604. prc->top = prc->bottom - delta;
  605. }
  606. if (prc->top < 0) {
  607. delta = prc->bottom - prc->top;
  608. prc->top = 0;
  609. prc->bottom = prc->top + delta;
  610. }
  611. }
  612. VOID
  613. CenterWindow(
  614. HWND hWnd,
  615. HWND hwndToCenterOver
  616. )
  617. {
  618. RECT rc;
  619. RECT rcOwner;
  620. RECT rcCenter;
  621. HWND hwndOwner;
  622. GetWindowRect( hWnd, &rc );
  623. if (hwndToCenterOver) {
  624. hwndOwner = hwndToCenterOver;
  625. GetClientRect( hwndOwner, &rcOwner );
  626. } else {
  627. hwndOwner = GetWindow( hWnd, GW_OWNER );
  628. if (!hwndOwner) {
  629. hwndOwner = GetDesktopWindow();
  630. }
  631. GetWindowRect( hwndOwner, &rcOwner );
  632. }
  633. //
  634. // Calculate the starting x,y for the new
  635. // window so that it would be centered.
  636. //
  637. rcCenter.left = rcOwner.left +
  638. (((rcOwner.right - rcOwner.left) -
  639. (rc.right - rc.left))
  640. / 2);
  641. rcCenter.top = rcOwner.top +
  642. (((rcOwner.bottom - rcOwner.top) -
  643. (rc.bottom - rc.top))
  644. / 2);
  645. rcCenter.right = rcCenter.left + (rc.right - rc.left);
  646. rcCenter.bottom = rcCenter.top + (rc.bottom - rc.top);
  647. FitRectToScreen( &rcCenter );
  648. SetWindowPos(hWnd, NULL, rcCenter.left, rcCenter.top, 0, 0,
  649. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  650. }
  651. VOID
  652. MyShowWindow(
  653. HWND hWnd,
  654. BOOL visible
  655. )
  656. {
  657. HWND hWndInsertAfter;
  658. DWORD Flags;
  659. Flags = SWP_NOSIZE | SWP_NOMOVE;
  660. hWndInsertAfter = IsOptionOn( Config.OnTop ) ? HWND_TOPMOST : HWND_NOTOPMOST;
  661. Flags |= visible ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  662. SetWindowPos( hWnd, hWndInsertAfter, 0, 0, 0, 0, Flags );
  663. if (visible) {
  664. SetForegroundWindow( hWnd );
  665. } else {
  666. SetProcessWorkingSetSize( GetCurrentProcess(), 0xffffffff, 0xffffffff );
  667. }
  668. IsShowing = visible;
  669. if (IsOptionOn( Config.TaskBar ) && !IsOnTaskBar) {
  670. IconData.uID = (UINT) IDI_ICON1;
  671. IconData.cbSize = sizeof(NOTIFYICONDATA);
  672. IconData.hWnd = FaxStat.hWnd;
  673. IconData.uCallbackMessage = TRAYCALLBACK;
  674. IconData.hIcon = LoadIcon( FaxStat.hInstance, MAKEINTRESOURCE( IDI_ICON1 ) );
  675. IconData.uFlags = NIF_ICON | NIF_MESSAGE;
  676. Shell_NotifyIcon( NIM_ADD, &IconData );
  677. IsOnTaskBar = TRUE;
  678. } else if (!IsOptionOn( Config.TaskBar ) && IsOnTaskBar) {
  679. Shell_NotifyIcon( NIM_DELETE, &IconData );
  680. IsOnTaskBar = FALSE;
  681. }
  682. }
  683. VOID
  684. GetConfiguration(
  685. VOID
  686. )
  687. {
  688. HKEY HKey;
  689. HKey = OpenRegistryKey( HKEY_CURRENT_USER, REGKEY_FAX_USERINFO, FALSE, KEY_READ );
  690. if (HKey == NULL) {
  691. DebugPrint(( TEXT("Cannot open HKEY_CURRENT_USER") ));
  692. return;
  693. }
  694. Config.OnTop = GetRegistryDword( HKey, REGVAL_ALWAYS_ON_TOP );
  695. Config.TaskBar = GetRegistryDword( HKey, REGVAL_TASKBAR );
  696. Config.VisualNotification = GetRegistryDword( HKey, REGVAL_VISUAL_NOTIFICATION );
  697. Config.SoundNotification = GetRegistryDword( HKey, REGVAL_SOUND_NOTIFICATION );
  698. Config.ManualAnswerEnabled = GetRegistryDword( HKey, REGVAL_ENABLE_MANUAL_ANSWER );
  699. RegCloseKey( HKey );
  700. }
  701. VOID
  702. PlayAnimation(
  703. HWND hWnd,
  704. DWORD Animation
  705. )
  706. {
  707. static DWORD AnimationPlaying = 0;
  708. if (Animation == AnimationPlaying) {
  709. return;
  710. }
  711. if (AnimationPlaying == 0) {
  712. Animate_Close( hWnd );
  713. }
  714. Animate_Open( hWnd, MAKEINTRESOURCE( Animation ) );
  715. Animate_Play( hWnd, 0, -1, -1 );
  716. AnimationPlaying = Animation;
  717. }