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.

1515 lines
37 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1994
  4. *
  5. * TITLE: LIGHTS.C
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: Nick Manson
  10. *
  11. * DATE: 25 May 1994
  12. *
  13. ********************************************************************************
  14. *
  15. * CHANGE LOG:
  16. *
  17. * DATE REV DESCRIPTION
  18. * ----------- --- -------------------------------------------------------------
  19. * 19 Aug 1994 NRM Added IsDialogMessage processing to message loop.
  20. * 04 Aug 1994 NRM Removed all TAPI code (ifdefed out) and changed code to rely
  21. * on VXD connection flag as shutdown event.
  22. * 14 Jul 1994 NRM Fixed Code Review issues.
  23. * 29 Jun 1994 NRM Minor Revisions including internationalization issues and
  24. * addition of code to WM_TIMER to prevent infinite searching
  25. * for comm port address. Major Revision of TAPI line handling
  26. * procedures -- all moved to linefunc.c
  27. * 19 Jun 1994 NRM Minor Revision to remove invalid message sent to dialog
  28. * after its destruction ( moved event detection to WS_TIMER
  29. * section ). Also, replaced several LoadDynamicString calls
  30. * with LoadString calls in order to remove inefficiencies
  31. * and avoid string bug for single parameter calls of this
  32. * routine.
  33. * 25 May 1994 NRM Original implementation.
  34. *
  35. *******************************************************************************/
  36. #include "lights.h"
  37. // Global instance handle of this application.
  38. static HINSTANCE g_hInstance;
  39. // Global handle to the dialog box window.
  40. static HWND g_hWnd;
  41. // Global status of dialog window ( hidden or unhidden )
  42. static BOOL g_DlgHidden;
  43. // Global status of timer.
  44. static UINT_PTR g_fTimerOn = 0;
  45. // Global Command line parameters and information.
  46. static char g_szModemName[MAX_PATH]; // Modem Name string.
  47. static HANDLE g_hShutDownEvent = NULL; // Modem lights shut down event.
  48. static HANDLE g_hCommDevice = NULL;
  49. // Modem Tray Icon tip information string.
  50. static char g_szTipStr[MAXRCSTRING];
  51. // ID of the current icons being displayed on the tray.
  52. static UINT g_TrayIconID = NUMBER_OF_ICONS;
  53. static HICON g_hTrayIcon[NUMBER_OF_ICONS] = { NULL, NULL, NULL, NULL };
  54. // ID of the current dialog string being displayed in dialog box.
  55. static UINT g_ModemTimeStringID = 0;
  56. static PSTR g_pModemTimeString = NULL;
  57. // ID and storage for current Dialog Lights.
  58. static UINT g_ModemRXLightID = 0;
  59. static UINT g_ModemTXLightID = 0;
  60. static HBITMAP g_hModemLight[NUMBER_OF_LIGHTS];
  61. // storage for modem image.
  62. static HANDLE g_hModemImage = NULL;
  63. VOID
  64. WINAPI
  65. AdjustControlPosition(
  66. HWND hWnd
  67. );
  68. LRESULT
  69. WINAPI
  70. ModemMonitorWndProc(
  71. HWND hWnd,
  72. UINT Message,
  73. WPARAM wParam,
  74. LPARAM lParam
  75. );
  76. VOID
  77. WINAPI
  78. LoadResources(
  79. VOID
  80. );
  81. VOID
  82. WINAPI
  83. UnLoadResources(
  84. VOID
  85. );
  86. VOID
  87. WINAPI
  88. ResetModemBitMap(
  89. HWND hWnd
  90. );
  91. BOOL
  92. WINAPI
  93. ModemMonitor_UpdateModemStatus(
  94. HWND hWnd,
  95. DWORD NotifyIconMessage,
  96. BOOL fForceUpdate
  97. );
  98. VOID
  99. WINAPI
  100. ModemMonitor_NotifyIcon(
  101. HWND hWnd,
  102. DWORD Message,
  103. HICON hIcon,
  104. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  105. );
  106. BOOL
  107. WINAPI
  108. GetSystemModemStatus(
  109. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  110. );
  111. VOID
  112. WINAPI
  113. UpdateTrayIcon(
  114. HWND hWnd,
  115. DWORD NotifyIconMessage,
  116. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  117. );
  118. VOID
  119. WINAPI
  120. UpdateTRXText(
  121. HWND hWnd,
  122. UINT idc,
  123. LPSTR pStr
  124. );
  125. VOID
  126. WINAPI
  127. UpdateDialogBox(
  128. HWND hWnd,
  129. LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
  130. BOOL fForceUpdate
  131. );
  132. VOID
  133. WINAPI
  134. UpdateDialogTimer(
  135. HWND hWnd,
  136. LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
  137. BOOL fForceUpdate
  138. );
  139. PSTR
  140. NEAR CDECL
  141. LoadDynamicString(
  142. UINT StringID,
  143. ...
  144. );
  145. int
  146. WINAPI
  147. WinMain(
  148. HINSTANCE hInstance,
  149. HINSTANCE hPrevInstance,
  150. LPSTR lpCmdLine,
  151. int nCmdShow
  152. );
  153. VOID
  154. WINAPI
  155. CloseExternalResources(
  156. HWND hWnd
  157. );
  158. LONG __cdecl atol(const char *s)
  159. {
  160. LONG i, n;
  161. n = 0;
  162. for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
  163. {
  164. n = 10 * n + (s[i] - '0');
  165. }
  166. return n;
  167. }
  168. LPTSTR ScanForChar(
  169. LPTSTR String,
  170. TCHAR CharToFind
  171. )
  172. {
  173. static LPTSTR CurrentPos;
  174. LPTSTR ReturnValue;
  175. if (String != NULL) {
  176. CurrentPos=String;
  177. } else {
  178. String=CurrentPos;
  179. }
  180. while (*String != TEXT('\0')) {
  181. if (*String == CharToFind) {
  182. *String=TEXT('\0');
  183. ReturnValue=CurrentPos;
  184. CurrentPos=String+1;
  185. return ReturnValue;
  186. }
  187. String++;
  188. }
  189. if (String != CurrentPos) {
  190. ReturnValue=CurrentPos;
  191. return ReturnValue;
  192. }
  193. return NULL;
  194. }
  195. VOID
  196. WinMainCRTStartup(
  197. VOID
  198. )
  199. {
  200. int mainret;
  201. LPTSTR lpszCommandLine=GetCommandLine();
  202. if ( *lpszCommandLine == TEXT('""') ) {
  203. /*
  204. * Scan, and skip over, subsequent characters until
  205. * another double-quote or a null is encountered.
  206. */
  207. while ( (*(++lpszCommandLine) != TEXT('""'))
  208. && (*lpszCommandLine != TEXT('\0')) ) {
  209. }
  210. /*
  211. * If we stopped on a double-quote (usual case), skip
  212. * over it.
  213. */
  214. if ( *lpszCommandLine == TEXT('""') )
  215. lpszCommandLine++;
  216. }
  217. else {
  218. while (*lpszCommandLine > TEXT(' '))
  219. lpszCommandLine++;
  220. }
  221. /*
  222. * Skip past any white space preceeding the second token.
  223. */
  224. while (*lpszCommandLine && (*lpszCommandLine <= TEXT(' '))) {
  225. lpszCommandLine++;
  226. }
  227. /* now call the main program, and then exit with the return value
  228. we get back */
  229. // try {
  230. mainret = WinMain( GetModuleHandle( NULL ),
  231. NULL,
  232. lpszCommandLine,
  233. SW_SHOWDEFAULT
  234. );
  235. // }
  236. // except (UnhandledExceptionFilter( GetExceptionInformation() )) {
  237. // ExitProcess( (DWORD)GetExceptionCode() );
  238. // }
  239. ExitProcess(mainret);
  240. }
  241. // Wrapper for LocalFree to make the code a little easier to read.
  242. #define DeleteDynamicString(x) LocalFree((HLOCAL) (x))
  243. int
  244. WINAPI
  245. WinMain(
  246. HINSTANCE hInstance,
  247. HINSTANCE hPrevInstance,
  248. LPSTR lpCmdLine,
  249. int nCmdShow
  250. )
  251. {
  252. LPSTR lpToken;
  253. WNDCLASS WndClass;
  254. MSG Msg;
  255. DWORD pidSrc;
  256. HANDLE hSrc, hSrcProc, hDstProc;
  257. g_hInstance = hInstance;
  258. // The command line format is:
  259. // "tapisrv_process_id Stopevent_handle comm_handle modem_name"
  260. //
  261. // Get the source process id.
  262. // if ( lpToken = strtok(lpCmdLine," ") )
  263. if ( lpToken = ScanForChar(lpCmdLine,TEXT(' ')) )
  264. {
  265. pidSrc = atol(lpToken);
  266. }
  267. else
  268. {
  269. // Too few parameters ...
  270. ASSERT(0);
  271. return 0;
  272. }
  273. hSrcProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pidSrc);
  274. hDstProc = GetCurrentProcess();
  275. // Get the global shut down event handle.
  276. // if ( lpToken = strtok(NULL," ") )
  277. if ( lpToken = ScanForChar(NULL,TEXT(' ')) )
  278. {
  279. hSrc = (HANDLE)LongToHandle(atol(lpToken));
  280. DuplicateHandle(hSrcProc, hSrc,
  281. hDstProc, &g_hShutDownEvent,
  282. 0L, FALSE, DUPLICATE_SAME_ACCESS);
  283. }
  284. else
  285. {
  286. // Too few parameters ...
  287. ASSERT(0);
  288. return 0;
  289. }
  290. // Get a copy of the global device handle.
  291. // if ( lpToken = strtok(NULL," ") )
  292. if ( lpToken = ScanForChar(NULL,TEXT(' ')) )
  293. {
  294. hSrc = (HANDLE)LongToHandle(atol(lpToken));
  295. DuplicateHandle(hSrcProc, hSrc,
  296. hDstProc, &g_hCommDevice,
  297. 0L, FALSE, DUPLICATE_SAME_ACCESS);
  298. }
  299. else
  300. {
  301. // Too few parameters ...
  302. if (g_hShutDownEvent)
  303. {
  304. CloseHandle(g_hShutDownEvent);
  305. g_hShutDownEvent = NULL;
  306. }
  307. ASSERT(0);
  308. return 0;
  309. }
  310. // Get the name of the modem device.
  311. // if ( lpToken = strtok(NULL,"") )
  312. if ( lpToken = ScanForChar(NULL,TEXT('\0')) )
  313. {
  314. // Get modem name ...
  315. lstrcpy( g_szModemName, lpToken );
  316. }
  317. else
  318. {
  319. // Too few parameters ...
  320. if (g_hShutDownEvent)
  321. {
  322. CloseHandle(g_hShutDownEvent);
  323. g_hShutDownEvent = NULL;
  324. }
  325. if (g_hCommDevice)
  326. {
  327. CloseHandle(g_hCommDevice);
  328. g_hCommDevice = NULL;
  329. }
  330. ASSERT(0);
  331. return 0;
  332. }
  333. CloseHandle(hSrcProc);
  334. //
  335. // Register a window class for the Modem Monitor. This is done so that
  336. // the power control panel applet has the ability to detect us and turn us
  337. // off if we're running.
  338. //
  339. WndClass.style = CS_GLOBALCLASS;
  340. WndClass.lpfnWndProc = ModemMonitorWndProc;
  341. WndClass.cbClsExtra = 0;
  342. WndClass.cbWndExtra = DLGWINDOWEXTRA;
  343. WndClass.hInstance = hInstance;
  344. WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CD));
  345. WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  346. WndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
  347. WndClass.lpszMenuName = NULL;
  348. WndClass.lpszClassName = MODEMMONITOR_CLASSNAME;
  349. if (RegisterClass(&WndClass))
  350. {
  351. g_hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MODEMMONITOR), NULL, NULL);
  352. if ( g_hWnd )
  353. {
  354. SendMessage(g_hWnd, MMWM_INITDIALOG, 0, 0);
  355. while (GetMessage(&Msg, NULL, 0, 0))
  356. {
  357. if ( !IsDialogMessage( g_hWnd, &Msg ) )
  358. {
  359. TranslateMessage(&Msg);
  360. DispatchMessage(&Msg);
  361. }
  362. }
  363. }
  364. UnregisterClass(WndClass.lpszClassName, WndClass.hInstance);
  365. }
  366. if (g_hShutDownEvent)
  367. {
  368. CloseHandle(g_hShutDownEvent);
  369. g_hShutDownEvent = NULL;
  370. }
  371. if (g_hCommDevice)
  372. {
  373. CloseHandle(g_hCommDevice);
  374. g_hCommDevice = NULL;
  375. }
  376. return 0;
  377. }
  378. VOID
  379. WINAPI
  380. LoadResources(
  381. VOID
  382. )
  383. {
  384. // Load tray icons.
  385. DWORD i;
  386. for (i=0; i<4; i++) {
  387. g_hTrayIcon[i] = LoadImage(
  388. g_hInstance,
  389. MAKEINTRESOURCE(IDI_CD+i),
  390. IMAGE_ICON,
  391. 16,
  392. 16,
  393. 0
  394. );
  395. }
  396. #if 0
  397. g_hTrayIcon[0] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_CD),
  398. IMAGE_ICON, 16, 16, 0);
  399. g_hTrayIcon[1] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_TX),
  400. IMAGE_ICON, 16, 16, 0);
  401. g_hTrayIcon[2] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_RX),
  402. IMAGE_ICON, 16, 16, 0);
  403. g_hTrayIcon[3] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_RXTX),
  404. IMAGE_ICON, 16, 16, 0);
  405. #endif
  406. for (i=0; i<2; i++) {
  407. g_hModemLight[i] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_OFF+i));
  408. }
  409. #if 0
  410. // Load Modem light bitmaps.
  411. g_hModemLight[0] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_OFF));
  412. g_hModemLight[1] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_ON));
  413. #endif
  414. }
  415. VOID
  416. WINAPI
  417. UnLoadResources(
  418. VOID
  419. )
  420. {
  421. UINT i;
  422. // Unload tray icons.
  423. for ( i = 0; i < NUMBER_OF_ICONS; i++ )
  424. {
  425. if ( g_hTrayIcon[i] )
  426. DestroyIcon(g_hTrayIcon[i]);
  427. }
  428. // Unload modem light bitmaps.
  429. for ( i = 0; i < NUMBER_OF_LIGHTS; i++ )
  430. {
  431. if ( g_hModemLight[i] )
  432. DeleteObject(g_hModemLight[i]);
  433. }
  434. }
  435. VOID
  436. WINAPI
  437. ResetModemBitMap(
  438. HWND hWnd
  439. )
  440. {
  441. // Clean up any old bitmaps.
  442. if ( g_hModemImage )
  443. DestroyIcon( g_hModemImage );
  444. // Load the window bitmap.
  445. g_hModemImage = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_LIGHTS),
  446. IMAGE_ICON, 0, 0,
  447. LR_DEFAULTCOLOR);
  448. if ( g_hModemImage )
  449. {
  450. // Set the window bitmap.
  451. SendDlgItemMessage( hWnd, IDC_MODEM_FRAME, STM_SETIMAGE,
  452. (WPARAM)IMAGE_ICON, (LPARAM)g_hModemImage );
  453. // Set the current lights.
  454. SendDlgItemMessage( hWnd, IDC_MODEM_RX_FRAME, STM_SETIMAGE,
  455. (WPARAM)IMAGE_BITMAP,
  456. (LPARAM)g_hModemLight[g_ModemRXLightID] );
  457. SendDlgItemMessage( hWnd, IDC_MODEM_TX_FRAME, STM_SETIMAGE,
  458. (WPARAM)IMAGE_BITMAP,
  459. (LPARAM)g_hModemLight[g_ModemTXLightID] );
  460. }
  461. }
  462. /*******************************************************************************
  463. *
  464. * AdjustControlPosition
  465. *
  466. * DESCRIPTION:
  467. * Adjust all the control positions based on the dialog resolution
  468. *
  469. * PARAMETERS:
  470. * hWnd, handle of ModemMonitor window.
  471. *
  472. *******************************************************************************/
  473. VOID
  474. WINAPI
  475. AdjustControlPosition(
  476. HWND hWnd
  477. )
  478. {
  479. HWND hwndImage, hCtrl;
  480. RECT rect;
  481. POINT ptOrg;
  482. char szText[MAX_PATH+1];
  483. // Find the anchor point of the image
  484. // The modem image is centered
  485. //
  486. hwndImage = GetDlgItem(hWnd, IDC_MODEM_FRAME);
  487. GetWindowRect(hwndImage, &rect);
  488. ptOrg.x = (rect.left+rect.right-MODEM_BITMAP_WIDTH)/2;
  489. ptOrg.y = (rect.top+rect.bottom-MODEM_BITMAP_HEIGHT)/2;
  490. ScreenToClient(hWnd, &ptOrg);
  491. // Adjust the lights
  492. SetWindowPos(GetDlgItem(hWnd, IDC_MODEM_TX_FRAME), hwndImage,
  493. ptOrg.x+TXL_X_OFFSET, ptOrg.y+TXL_Y_OFFSET,
  494. 0, 0, SWP_NOSIZE);
  495. SetWindowPos(GetDlgItem(hWnd, IDC_MODEM_RX_FRAME), hwndImage,
  496. ptOrg.x+RXL_X_OFFSET, ptOrg.y+RXL_Y_OFFSET,
  497. 0, 0, SWP_NOSIZE);
  498. // Adjust the TRX text
  499. hCtrl = GetDlgItem(hWnd, IDC_MODEMTXSTRING);
  500. ptOrg.x -= (rect.right-rect.left-MODEM_BITMAP_WIDTH)/2;
  501. GetWindowRect(hCtrl, &rect);
  502. SetWindowPos(hCtrl, hwndImage, ptOrg.x+TXT_X_OFFSET,
  503. ptOrg.y+TXT_Y_OFFSET-(rect.bottom-rect.top),
  504. 0, 0, SWP_NOSIZE);
  505. GetWindowText(hCtrl, szText, sizeof(szText));
  506. ASSERT(*szText != '\0');
  507. UpdateTRXText(hWnd, IDC_MODEMTXSTRING, szText);
  508. hCtrl = GetDlgItem(hWnd, IDC_MODEMRXSTRING);
  509. SetWindowPos(hCtrl, hwndImage,
  510. ptOrg.x+RXT_X_OFFSET, ptOrg.y+RXT_Y_OFFSET,
  511. 0, 0, SWP_NOSIZE);
  512. GetWindowText(hCtrl, szText, sizeof(szText));
  513. ASSERT(*szText != '\0');
  514. UpdateTRXText(hWnd, IDC_MODEMRXSTRING, szText);
  515. }
  516. /*******************************************************************************
  517. *
  518. * ModemMonitorWndProc
  519. *
  520. * DESCRIPTION:
  521. * Callback procedure for the ModemMonitor window.
  522. *
  523. * PARAMETERS:
  524. * hWnd, handle of ModemMonitor window.
  525. * Message,
  526. * wParam,
  527. * lParam,
  528. * (returns),
  529. *
  530. *******************************************************************************/
  531. LRESULT
  532. WINAPI
  533. ModemMonitorWndProc(
  534. HWND hWnd,
  535. UINT Message,
  536. WPARAM wParam,
  537. LPARAM lParam
  538. )
  539. {
  540. switch (Message) {
  541. case MMWM_INITDIALOG:
  542. // Mark the dialog box as currently being hidden.
  543. g_DlgHidden = TRUE;
  544. // Load the tip string and icons for the modem monitor icon
  545. if ( !LoadString(g_hInstance, IDS_MODEMTIP, g_szTipStr, MAXRCSTRING) )
  546. lstrcpy( g_szTipStr, "" );
  547. // Load modem icons
  548. LoadResources();
  549. // Update the modem's status.
  550. if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_ADD, FALSE) )
  551. {
  552. #if 0
  553. if (g_hShutDownEvent)
  554. {
  555. CloseHandle(g_hShutDownEvent);
  556. g_hShutDownEvent = NULL;
  557. }
  558. if (g_hCommDevice)
  559. {
  560. CloseHandle(g_hCommDevice);
  561. g_hCommDevice = NULL;
  562. }
  563. UnLoadResources();
  564. #endif
  565. DestroyWindow(hWnd);
  566. break;
  567. }
  568. // Change window title.
  569. SetWindowText(hWnd, g_szModemName);
  570. // Set timer for minimum period between updates of modem status.
  571. g_fTimerOn = SetTimer(
  572. hWnd,
  573. MDMSTATUS_UPDATE_TIMER_ID,
  574. MDMSTATUS_UPDATE_TIMER_TIMEOUT,
  575. NULL
  576. );
  577. // Load modem bitmap
  578. ResetModemBitMap(hWnd);
  579. // Adjust control position
  580. AdjustControlPosition(hWnd);
  581. break;
  582. case WM_COMMAND:
  583. switch (GET_WM_COMMAND_ID(wParam, lParam))
  584. {
  585. case IDOK:
  586. g_DlgHidden = TRUE;
  587. ShowWindow(hWnd, SW_HIDE);
  588. break;
  589. }
  590. break;
  591. case MMWM_NOTIFYICON:
  592. switch (lParam)
  593. {
  594. case WM_LBUTTONDBLCLK:
  595. g_DlgHidden = FALSE;
  596. if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_MODIFY, TRUE) )
  597. {
  598. CloseExternalResources(hWnd);
  599. DestroyWindow(hWnd);
  600. break;
  601. }
  602. SetForegroundWindow(hWnd);
  603. ShowWindow(hWnd, SW_SHOWNORMAL);
  604. break;
  605. }
  606. break;
  607. case WM_TIMER:
  608. // Update the modem status
  609. if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_MODIFY, FALSE) )
  610. {
  611. CloseExternalResources(hWnd);
  612. DestroyWindow(hWnd);
  613. }
  614. break;
  615. case WM_SYSCOLORCHANGE:
  616. ResetModemBitMap(hWnd);
  617. break;
  618. case WM_CLOSE:
  619. g_DlgHidden = TRUE;
  620. ShowWindow(hWnd, SW_HIDE);
  621. break;
  622. case WM_DESTROY:
  623. // Kill notification event
  624. if (g_hShutDownEvent)
  625. {
  626. CloseHandle(g_hShutDownEvent);
  627. g_hShutDownEvent = NULL;
  628. }
  629. if (g_hCommDevice)
  630. {
  631. CloseHandle(g_hCommDevice);
  632. g_hCommDevice = NULL;
  633. }
  634. // Clean up modem bitmap.
  635. if ( g_hModemImage )
  636. DestroyIcon( g_hModemImage );
  637. // Unload Icons
  638. UnLoadResources();
  639. PostQuitMessage(0);
  640. break;
  641. #ifdef HELP_WORKS
  642. case WM_HELP:
  643. case WM_CONTEXTMENU:
  644. ContextHelp(gaLights, Message, wParam, lParam);
  645. break;
  646. #endif // HELP_WORKS
  647. default:
  648. return DefWindowProc(hWnd, Message, wParam, lParam);
  649. }
  650. return 0;
  651. }
  652. /*******************************************************************************
  653. *
  654. * ModemMonitor_UpdateControls
  655. *
  656. * DESCRIPTION:
  657. *
  658. * This procedure updates the tray icon and all dialog box strings.
  659. *
  660. * PARAMETERS:
  661. * hWnd, handle of ModemMonitor window.
  662. * NotifyIconMessage, either NIM_ADD or NIM_MODIFY depending on whether the
  663. * tray icon needs to be added to the tray or modified in the tray.
  664. *
  665. *******************************************************************************/
  666. BOOL
  667. WINAPI
  668. ModemMonitor_UpdateModemStatus(
  669. HWND hWnd,
  670. DWORD NotifyIconMessage,
  671. BOOL fForceUpdate
  672. )
  673. {
  674. SYSTEM_MODEM_STATUS SystemModemStatus;
  675. BOOL fClosed = FALSE;
  676. // Get the system modem status.
  677. fClosed = GetSystemModemStatus(&SystemModemStatus);
  678. if ( !fClosed )
  679. {
  680. // Display appropriate ICON in tray based on statistics received.
  681. UpdateTrayIcon(hWnd, NotifyIconMessage, &SystemModemStatus);
  682. // If the dialog box is not currently hidden, update the dialog box
  683. // text strings and bitmaps.
  684. if ( (!g_DlgHidden) || fForceUpdate ) {
  685. // Update the dialog box time string.
  686. UpdateDialogTimer(hWnd, &SystemModemStatus, fForceUpdate);
  687. UpdateDialogBox(hWnd, &SystemModemStatus, fForceUpdate);
  688. }
  689. #if 0
  690. // Update the dialog box time string.
  691. UpdateDialogTimer(hWnd, &SystemModemStatus, fForceUpdate);
  692. #endif
  693. }
  694. return fClosed;
  695. }
  696. /*******************************************************************************
  697. *
  698. * ModemMonitor_NotifyIcon
  699. *
  700. * DESCRIPTION:
  701. *
  702. * Modified from source found in BATMETER.C.
  703. *
  704. * This routine is a wrapper for Shell_NotifyIcon with has been modified to
  705. * use a global string (g_pTipStr) for its Tip window.
  706. *
  707. * PARAMETERS:
  708. * hWnd, handle of ModemMonitor window.
  709. * Message,
  710. * hIcon
  711. *
  712. *******************************************************************************/
  713. VOID
  714. WINAPI
  715. ModemMonitor_NotifyIcon(
  716. HWND hWnd,
  717. DWORD Message,
  718. HICON hIcon,
  719. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  720. )
  721. {
  722. NOTIFYICONDATA NotifyIconData;
  723. NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
  724. NotifyIconData.uID = 0;
  725. NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  726. NotifyIconData.uCallbackMessage = MMWM_NOTIFYICON;
  727. NotifyIconData.hWnd = hWnd;
  728. NotifyIconData.hIcon = hIcon;
  729. if (lpSystemModemStatus)
  730. wsprintf(NotifyIconData.szTip, g_szTipStr, lpSystemModemStatus->dwPerfRead,
  731. lpSystemModemStatus->dwPerfWrite);
  732. else
  733. lstrcpy(NotifyIconData.szTip, "");
  734. Shell_NotifyIcon(Message, &NotifyIconData);
  735. }
  736. /*******************************************************************************
  737. *
  738. * GetSystemModemStatus
  739. *
  740. * DESCRIPTION:
  741. *
  742. * This procedure consists of three stages.
  743. *
  744. * The first stage attempts to obtain a valid device handle for the modem.
  745. *
  746. * The second stage involves setting default modem status values for the case
  747. * where the modem is not connected.
  748. *
  749. * The third stage only executes if a valid device handle which can be acted
  750. * upon is obtained. This stage involves placing a DeviceIOControl to
  751. * UNIMODEM and interpretting the statistics returned by the VXD.
  752. *
  753. * PARAMETERS:
  754. *
  755. * lpSystemModemStatus - A pointer to a modem statistics buffer.
  756. *
  757. *******************************************************************************/
  758. #define COMMCONFIG_AND_MODEMSETTINGS_LEN (60*3)
  759. BOOL
  760. WINAPI
  761. GetSystemModemStatus(
  762. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  763. )
  764. {
  765. static DWORD dwPerfRead = 0;
  766. static DWORD dwPerfWrite = 0;
  767. DWORD dwRet;
  768. BYTE byteTmp[COMMCONFIG_AND_MODEMSETTINGS_LEN];
  769. LPCOMMCONFIG lpCC = (LPCOMMCONFIG)byteTmp;
  770. DWORD dwSize;
  771. OVERLAPPED ov ;
  772. BOOL bResult=TRUE;
  773. static DWORD BaudRate=0;
  774. ZeroMemory(&ov,sizeof(ov));
  775. ov.hEvent = CreateEvent(
  776. NULL,
  777. FALSE,
  778. FALSE,
  779. NULL
  780. );
  781. if (ov.hEvent == NULL) {
  782. goto End;
  783. }
  784. //
  785. // Make it so it doesn't hit unimdm.tsp's completion port.
  786. //
  787. ov.hEvent = (HANDLE)((ULONG_PTR)ov.hEvent | 1);
  788. //
  789. // Initialize Modem statistics to show no connection (the default case).
  790. //
  791. lpSystemModemStatus->DCERate = 0;
  792. lpSystemModemStatus->Connected = FALSE;
  793. lpSystemModemStatus->Reading = FALSE;
  794. lpSystemModemStatus->Writing = FALSE;
  795. lpSystemModemStatus->dwPerfRead = 0;
  796. lpSystemModemStatus->dwPerfWrite = 0;
  797. // Check the shut down event
  798. if ( WaitForSingleObject( g_hShutDownEvent, 0 ) != WAIT_TIMEOUT )
  799. {
  800. goto End;
  801. }
  802. if (g_hCommDevice != NULL)
  803. {
  804. DWORD dwPassthroughState;
  805. SERIALPERF_STATS serialstats;
  806. DWORD dwWaitResult;
  807. if (!DeviceIoControl(g_hCommDevice,
  808. IOCTL_MODEM_GET_PASSTHROUGH,
  809. &dwPassthroughState,
  810. sizeof(dwPassthroughState),
  811. &dwPassthroughState,
  812. sizeof(dwPassthroughState),
  813. &dwRet,
  814. &ov))
  815. {
  816. if (ERROR_IO_PENDING != GetLastError())
  817. {
  818. ASSERT(0);
  819. goto End;
  820. }
  821. if (!GetOverlappedResult(g_hCommDevice,
  822. &ov,
  823. &dwRet,
  824. TRUE))
  825. {
  826. ASSERT(0);
  827. goto End;
  828. }
  829. }
  830. switch (dwPassthroughState)
  831. {
  832. case MODEM_PASSTHROUGH:
  833. case MODEM_DCDSNIFF:
  834. lpSystemModemStatus->Connected = TRUE;
  835. break;
  836. case MODEM_NOPASSTHROUGH:
  837. default:
  838. lpSystemModemStatus->Connected = FALSE;
  839. goto End;
  840. }
  841. if (!DeviceIoControl(g_hCommDevice,
  842. IOCTL_SERIAL_GET_STATS,
  843. &serialstats,
  844. sizeof(SERIALPERF_STATS),
  845. &serialstats,
  846. sizeof(SERIALPERF_STATS),
  847. &dwRet,
  848. &ov))
  849. {
  850. if (ERROR_IO_PENDING != GetLastError())
  851. {
  852. ASSERT(0);
  853. goto End;
  854. }
  855. if (!GetOverlappedResult(g_hCommDevice,
  856. &ov,
  857. &dwRet,
  858. TRUE))
  859. {
  860. ASSERT(0);
  861. goto End;
  862. }
  863. }
  864. // Set Modem connection rate, connection, data transmission and
  865. // data reception flags.
  866. lpSystemModemStatus->Reading = ( serialstats.ReceivedCount != dwPerfRead );
  867. lpSystemModemStatus->Writing = ( serialstats.TransmittedCount != dwPerfWrite );
  868. // Update bytes read and written history values for the next call
  869. // call to this function.
  870. dwPerfRead = serialstats.ReceivedCount;
  871. dwPerfWrite = serialstats.TransmittedCount;
  872. lpSystemModemStatus->dwPerfRead = serialstats.ReceivedCount;
  873. lpSystemModemStatus->dwPerfWrite = serialstats.TransmittedCount;
  874. if (BaudRate == 0) {
  875. dwSize = sizeof(byteTmp);
  876. if (GetCommConfig(g_hCommDevice,
  877. lpCC,
  878. &dwSize)) {
  879. lpSystemModemStatus->DCERate =
  880. ((PMODEMSETTINGS)&lpCC->wcProviderData[0])->dwNegotiatedDCERate;
  881. BaudRate=lpSystemModemStatus->DCERate;
  882. } else {
  883. ASSERT(0);
  884. goto End;
  885. }
  886. } else {
  887. lpSystemModemStatus->DCERate=BaudRate;
  888. }
  889. }
  890. bResult=FALSE;
  891. End:
  892. CloseHandle((HANDLE)((DWORD_PTR)ov.hEvent & (~1)));
  893. return bResult;
  894. }
  895. /*******************************************************************************
  896. *
  897. * UpdateTrayIcon
  898. *
  899. * DESCRIPTION:
  900. *
  901. * This procedure reads the modem status structure and updates the Modem
  902. * Monitor tray icon. This is done by comparing the new status (NewIconID)
  903. * with the old status (a global variable - g_TrayIconID) and updating the
  904. * icon using ModemMonitor_NotifyIcon only if there has been a change.
  905. *
  906. * PARAMETERS:
  907. * hWnd, handle to the modem monitor dialog box
  908. * NotifyIconMessage, passed through from caller to ModemMonitor_NotifyIcon
  909. * lpSystemModemStatus, modem status structure.
  910. *
  911. *******************************************************************************/
  912. VOID
  913. WINAPI
  914. UpdateTrayIcon(
  915. HWND hWnd,
  916. DWORD NotifyIconMessage,
  917. LPSYSTEM_MODEM_STATUS lpSystemModemStatus
  918. )
  919. {
  920. UINT NewIconID;
  921. NewIconID = 0;
  922. if ( lpSystemModemStatus->Reading )
  923. NewIconID += ICON_RX_ON;
  924. if ( lpSystemModemStatus->Writing )
  925. NewIconID += ICON_TX_ON;
  926. if ( g_TrayIconID != NewIconID )
  927. {
  928. // Update the tray by setting its icon appropriately and notifying
  929. // the system to update the display.
  930. g_TrayIconID = NewIconID;
  931. ModemMonitor_NotifyIcon(hWnd, NotifyIconMessage,
  932. g_hTrayIcon[g_TrayIconID],
  933. lpSystemModemStatus);
  934. }
  935. }
  936. /*******************************************************************************
  937. *
  938. * UpdateTRXText
  939. *
  940. * DESCRIPTION:
  941. *
  942. * This procedure adjusts the Tx/Rx text width
  943. *
  944. * PARAMETERS:
  945. * hWnd, handle to the dialog window.
  946. * idc, Resource ID of Tx or Rx text control
  947. * pStr, new text
  948. *
  949. *******************************************************************************/
  950. VOID
  951. WINAPI
  952. UpdateTRXText(
  953. HWND hWnd,
  954. UINT idc,
  955. LPSTR pStr
  956. )
  957. {
  958. HDC hDC;
  959. HFONT hFont;
  960. HWND hwndCtrl;
  961. SIZE size;
  962. RECT rect;
  963. POINT ptOrg;
  964. // Find the exact dimension of the TRX text which will appear
  965. // on the screen
  966. //
  967. hwndCtrl = GetDlgItem(hWnd, idc);
  968. GetWindowRect(hwndCtrl, &rect);
  969. hDC = GetDC(hwndCtrl);
  970. // Bail if we can't get a device context
  971. if (!hDC) return;
  972. hFont = SelectObject(hDC, (HFONT)SendMessage(hwndCtrl, WM_GETFONT, 0, 0));
  973. GetTextExtentPoint32 (hDC, pStr, lstrlen(pStr), &size);
  974. SelectObject(hDC, hFont);
  975. ReleaseDC(hwndCtrl, hDC);
  976. // If it is the transmitted line, align the bottom with the
  977. // current position
  978. //
  979. if (idc == IDC_MODEMTXSTRING)
  980. rect.top = rect.bottom-size.cy;
  981. // Adjust the text control to exactly fit the displayed text
  982. //
  983. ptOrg = *(POINT *)((RECT *)&rect);
  984. ScreenToClient(hWnd, &ptOrg);
  985. SetWindowPos(hwndCtrl, GetDlgItem(hWnd, IDC_MODEM_FRAME),
  986. ptOrg.x, ptOrg.y, size.cx, size.cy, 0);
  987. SetWindowText(hwndCtrl, pStr);
  988. }
  989. /*******************************************************************************
  990. *
  991. * UpdateDialogBox
  992. *
  993. * DESCRIPTION:
  994. *
  995. * This procedure reads the modem status structure and updates the Modem
  996. * Monitor Dialog box.
  997. *
  998. * PARAMETERS:
  999. * hWnd, handle to the dialog window.
  1000. * lpSystemModemStatus, pointer to modem status structure.
  1001. *
  1002. *******************************************************************************/
  1003. VOID
  1004. WINAPI
  1005. UpdateDialogBox(
  1006. HWND hWnd,
  1007. LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
  1008. BOOL fForceUpdate
  1009. )
  1010. {
  1011. UINT NewModemRXLightID = 0;
  1012. UINT NewModemTXLightID = 0;
  1013. PSTR pRxTx;
  1014. // Obtain resource id numbers for the RX and TX lights.
  1015. if ( lpSystemModemStatus->Reading )
  1016. NewModemRXLightID += LIGHT_ON;
  1017. if ( lpSystemModemStatus->Writing )
  1018. NewModemTXLightID += LIGHT_ON;
  1019. // Update the modem lights if necessary.
  1020. if (( g_ModemRXLightID != NewModemRXLightID ) || fForceUpdate)
  1021. {
  1022. g_ModemRXLightID = NewModemRXLightID;
  1023. if ( g_hModemImage )
  1024. {
  1025. SendDlgItemMessage( hWnd, IDC_MODEM_RX_FRAME, STM_SETIMAGE,
  1026. (WPARAM)IMAGE_BITMAP,
  1027. (LPARAM)g_hModemLight[g_ModemRXLightID] );
  1028. };
  1029. }
  1030. if (( g_ModemTXLightID != NewModemTXLightID ) || fForceUpdate)
  1031. {
  1032. g_ModemTXLightID = NewModemTXLightID;
  1033. if ( g_hModemImage )
  1034. {
  1035. SendDlgItemMessage( hWnd, IDC_MODEM_TX_FRAME, STM_SETIMAGE,
  1036. (WPARAM)IMAGE_BITMAP,
  1037. (LPARAM)g_hModemLight[g_ModemTXLightID] );
  1038. };
  1039. }
  1040. if ( lpSystemModemStatus->Reading || fForceUpdate )
  1041. {
  1042. // Display the new byte-received count
  1043. //
  1044. pRxTx = LoadDynamicString(IDS_RXSTRING,
  1045. lpSystemModemStatus->dwPerfRead);
  1046. UpdateTRXText(hWnd, IDC_MODEMRXSTRING, pRxTx);
  1047. DeleteDynamicString(pRxTx);
  1048. }
  1049. if ( lpSystemModemStatus->Writing || fForceUpdate )
  1050. {
  1051. // Display the new byte-sent count
  1052. //
  1053. pRxTx = LoadDynamicString(IDS_TXSTRING,
  1054. lpSystemModemStatus->dwPerfWrite);
  1055. UpdateTRXText(hWnd, IDC_MODEMTXSTRING, pRxTx);
  1056. DeleteDynamicString(pRxTx);
  1057. }
  1058. }
  1059. /*******************************************************************************
  1060. *
  1061. * UpdateDialogTimer
  1062. *
  1063. * DESCRIPTION:
  1064. *
  1065. * This procedure sets the modem time since connection string.
  1066. * The string will change under any one of the three following conditions:
  1067. * i) The modem's connection status has changed.
  1068. * ii) A forced update was indicated.
  1069. * iii) The timer count for update has expired.
  1070. *
  1071. * PARAMETERS:
  1072. * hWnd, handle to the dialog window.
  1073. * lpSystemModemStatus, pointer to modem status structure.
  1074. * fForceUpdate, boolean for whether window update is necessary.
  1075. *
  1076. *******************************************************************************/
  1077. VOID
  1078. WINAPI
  1079. UpdateDialogTimer(
  1080. HWND hWnd,
  1081. LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
  1082. BOOL fForceUpdate
  1083. )
  1084. {
  1085. static BOOL ModemConnected = FALSE;
  1086. static DWORD cTimer = 0;
  1087. static DWORD ConnectionStart = 0;
  1088. static DWORD dwPrevTime = 0;
  1089. DWORD dwTime;
  1090. UINT uHr, uMin;
  1091. PSTR pStr, pSubStr1, pSubStr2;
  1092. UINT NewStringID;
  1093. BOOL fBuildString;
  1094. fBuildString = FALSE;
  1095. if ( fForceUpdate )
  1096. fBuildString = TRUE;
  1097. if ( (lpSystemModemStatus->Connected) != (ModemConnected) )
  1098. {
  1099. fBuildString = TRUE;
  1100. ModemConnected = lpSystemModemStatus->Connected;
  1101. ConnectionStart = GetTickCount();
  1102. cTimer = 0;
  1103. }
  1104. if ( cTimer >= MDMSTATUS_UPDATE_TIMER_COUNT )
  1105. {
  1106. fBuildString = TRUE;
  1107. cTimer = 0;
  1108. }
  1109. // Build the string if necessary.
  1110. if ( fBuildString )
  1111. {
  1112. dwTime = (GetTickCount()-ConnectionStart)/1000L;
  1113. dwTime /= 60;
  1114. // If the time value has changed by at least one minute
  1115. if ( ( dwTime != dwPrevTime ) || ( dwPrevTime == 0 ) )
  1116. {
  1117. dwPrevTime = dwTime;
  1118. uMin = (UINT)(dwTime % 60);
  1119. uHr = (UINT)(dwTime / 60);
  1120. pSubStr1 = LoadDynamicString(IDS_CD, lpSystemModemStatus->DCERate);
  1121. pSubStr2 = NULL;
  1122. if ( uHr || uMin )
  1123. {
  1124. if ( uMin )
  1125. {
  1126. if ( uHr )
  1127. {
  1128. if ( uHr > 1 )
  1129. {
  1130. // Hours and at least one minute
  1131. if ( uMin > 1 )
  1132. NewStringID = IDS_HOURSMINS;
  1133. else
  1134. NewStringID = IDS_HOURSMIN;
  1135. }
  1136. else
  1137. {
  1138. // One hour and at least one minute
  1139. if ( uMin > 1 )
  1140. NewStringID = IDS_HOURMINS;
  1141. else
  1142. NewStringID = IDS_HOURMIN;
  1143. }
  1144. }
  1145. else
  1146. {
  1147. // Minutes only
  1148. if ( uMin > 1 )
  1149. NewStringID = IDS_MINS;
  1150. else
  1151. NewStringID = IDS_MIN;
  1152. }
  1153. }
  1154. else
  1155. {
  1156. // Hours only
  1157. if ( uHr > 1 )
  1158. NewStringID = IDS_HOURS;
  1159. else
  1160. NewStringID = IDS_HOUR;
  1161. }
  1162. pSubStr2 = LoadDynamicString(NewStringID, uHr, uMin);
  1163. pStr = LoadDynamicString(IDS_TIMESTRING, pSubStr1, pSubStr2);
  1164. }
  1165. else
  1166. {
  1167. pStr = LoadDynamicString(IDS_TIMESTRING, pSubStr1, "");
  1168. }
  1169. if ( pSubStr1 )
  1170. DeleteDynamicString(pSubStr1);
  1171. if ( pSubStr2 )
  1172. DeleteDynamicString(pSubStr2);
  1173. SetDlgItemText(hWnd, IDC_MODEMTIMESTRING, pStr);
  1174. if (g_pModemTimeString)
  1175. DeleteDynamicString(g_pModemTimeString);
  1176. g_pModemTimeString = pStr;
  1177. } // endif - time has changed by at least one minute.
  1178. }
  1179. // Increment the global timer string interval counter.
  1180. cTimer++;
  1181. }
  1182. /*******************************************************************************
  1183. *
  1184. * LoadDynamicString
  1185. *
  1186. * DESCRIPTION:
  1187. *
  1188. * From source found in BATMETER.C
  1189. *
  1190. * Wrapper for the FormatMessage function that loads a string from our
  1191. * resource table into a dynamically allocated buffer, optionally filling
  1192. * it with the variable arguments passed.
  1193. *
  1194. * BE CAREFUL in 16-bit code to pass 32-bit quantities for the variable
  1195. * arguments.
  1196. *
  1197. * PARAMETERS:
  1198. * StringID, resource identifier of the string to use.
  1199. * (optional), parameters to use to format the string message.
  1200. *
  1201. *******************************************************************************/
  1202. PSTR
  1203. NEAR CDECL
  1204. LoadDynamicString(
  1205. UINT StringID,
  1206. ...
  1207. )
  1208. {
  1209. char Buffer[256];
  1210. PSTR pStr = NULL;
  1211. va_list Marker;
  1212. va_start(Marker, StringID);
  1213. LoadString(g_hInstance, StringID, Buffer, sizeof(Buffer));
  1214. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1215. (LPVOID) (LPSTR) Buffer, 0, 0, (LPSTR) (PSTR FAR *) &pStr, 0, &Marker);
  1216. return pStr;
  1217. }
  1218. /*******************************************************************************
  1219. *
  1220. * CloseExternalResources
  1221. *
  1222. * DESCRIPTION:
  1223. *
  1224. * This routine kills the timer and removes the tray icon associated
  1225. * with this application. This is done here (as opposed to in the
  1226. * WM_TIMER message) in order to meet the criterion that no calls using
  1227. * the window's handle may be made in the WM_DESTROY message handler
  1228. * excepting those involving memory de-allocation.
  1229. *
  1230. * PARAMETERS: none.
  1231. *
  1232. *******************************************************************************/
  1233. VOID
  1234. WINAPI
  1235. CloseExternalResources( HWND hWnd )
  1236. {
  1237. // Kill the timer
  1238. if ( g_fTimerOn )
  1239. {
  1240. KillTimer(hWnd, MDMSTATUS_UPDATE_TIMER_ID);
  1241. g_fTimerOn = FALSE;
  1242. }
  1243. // Remove ICON from tray.
  1244. ModemMonitor_NotifyIcon(hWnd, NIM_DELETE, g_hTrayIcon[g_TrayIconID], NULL);
  1245. }