windows-nt/Source/XPSP1/NT/net/unimodem/lights/lights.c
2020-09-26 16:20:57 +08:00

1516 lines
37 KiB
C

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 1993-1994
*
* TITLE: LIGHTS.C
*
* VERSION: 1.0
*
* AUTHOR: Nick Manson
*
* DATE: 25 May 1994
*
********************************************************************************
*
* CHANGE LOG:
*
* DATE REV DESCRIPTION
* ----------- --- -------------------------------------------------------------
* 19 Aug 1994 NRM Added IsDialogMessage processing to message loop.
* 04 Aug 1994 NRM Removed all TAPI code (ifdefed out) and changed code to rely
* on VXD connection flag as shutdown event.
* 14 Jul 1994 NRM Fixed Code Review issues.
* 29 Jun 1994 NRM Minor Revisions including internationalization issues and
* addition of code to WM_TIMER to prevent infinite searching
* for comm port address. Major Revision of TAPI line handling
* procedures -- all moved to linefunc.c
* 19 Jun 1994 NRM Minor Revision to remove invalid message sent to dialog
* after its destruction ( moved event detection to WS_TIMER
* section ). Also, replaced several LoadDynamicString calls
* with LoadString calls in order to remove inefficiencies
* and avoid string bug for single parameter calls of this
* routine.
* 25 May 1994 NRM Original implementation.
*
*******************************************************************************/
#include "lights.h"
// Global instance handle of this application.
static HINSTANCE g_hInstance;
// Global handle to the dialog box window.
static HWND g_hWnd;
// Global status of dialog window ( hidden or unhidden )
static BOOL g_DlgHidden;
// Global status of timer.
static UINT_PTR g_fTimerOn = 0;
// Global Command line parameters and information.
static char g_szModemName[MAX_PATH]; // Modem Name string.
static HANDLE g_hShutDownEvent = NULL; // Modem lights shut down event.
static HANDLE g_hCommDevice = NULL;
// Modem Tray Icon tip information string.
static char g_szTipStr[MAXRCSTRING];
// ID of the current icons being displayed on the tray.
static UINT g_TrayIconID = NUMBER_OF_ICONS;
static HICON g_hTrayIcon[NUMBER_OF_ICONS] = { NULL, NULL, NULL, NULL };
// ID of the current dialog string being displayed in dialog box.
static UINT g_ModemTimeStringID = 0;
static PSTR g_pModemTimeString = NULL;
// ID and storage for current Dialog Lights.
static UINT g_ModemRXLightID = 0;
static UINT g_ModemTXLightID = 0;
static HBITMAP g_hModemLight[NUMBER_OF_LIGHTS];
// storage for modem image.
static HANDLE g_hModemImage = NULL;
VOID
WINAPI
AdjustControlPosition(
HWND hWnd
);
LRESULT
WINAPI
ModemMonitorWndProc(
HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
);
VOID
WINAPI
LoadResources(
VOID
);
VOID
WINAPI
UnLoadResources(
VOID
);
VOID
WINAPI
ResetModemBitMap(
HWND hWnd
);
BOOL
WINAPI
ModemMonitor_UpdateModemStatus(
HWND hWnd,
DWORD NotifyIconMessage,
BOOL fForceUpdate
);
VOID
WINAPI
ModemMonitor_NotifyIcon(
HWND hWnd,
DWORD Message,
HICON hIcon,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
);
BOOL
WINAPI
GetSystemModemStatus(
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
);
VOID
WINAPI
UpdateTrayIcon(
HWND hWnd,
DWORD NotifyIconMessage,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
);
VOID
WINAPI
UpdateTRXText(
HWND hWnd,
UINT idc,
LPSTR pStr
);
VOID
WINAPI
UpdateDialogBox(
HWND hWnd,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
BOOL fForceUpdate
);
VOID
WINAPI
UpdateDialogTimer(
HWND hWnd,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
BOOL fForceUpdate
);
PSTR
NEAR CDECL
LoadDynamicString(
UINT StringID,
...
);
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
VOID
WINAPI
CloseExternalResources(
HWND hWnd
);
LONG __cdecl atol(const char *s)
{
LONG i, n;
n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
{
n = 10 * n + (s[i] - '0');
}
return n;
}
LPTSTR ScanForChar(
LPTSTR String,
TCHAR CharToFind
)
{
static LPTSTR CurrentPos;
LPTSTR ReturnValue;
if (String != NULL) {
CurrentPos=String;
} else {
String=CurrentPos;
}
while (*String != TEXT('\0')) {
if (*String == CharToFind) {
*String=TEXT('\0');
ReturnValue=CurrentPos;
CurrentPos=String+1;
return ReturnValue;
}
String++;
}
if (String != CurrentPos) {
ReturnValue=CurrentPos;
return ReturnValue;
}
return NULL;
}
VOID
WinMainCRTStartup(
VOID
)
{
int mainret;
LPTSTR lpszCommandLine=GetCommandLine();
if ( *lpszCommandLine == TEXT('""') ) {
/*
* Scan, and skip over, subsequent characters until
* another double-quote or a null is encountered.
*/
while ( (*(++lpszCommandLine) != TEXT('""'))
&& (*lpszCommandLine != TEXT('\0')) ) {
}
/*
* If we stopped on a double-quote (usual case), skip
* over it.
*/
if ( *lpszCommandLine == TEXT('""') )
lpszCommandLine++;
}
else {
while (*lpszCommandLine > TEXT(' '))
lpszCommandLine++;
}
/*
* Skip past any white space preceeding the second token.
*/
while (*lpszCommandLine && (*lpszCommandLine <= TEXT(' '))) {
lpszCommandLine++;
}
/* now call the main program, and then exit with the return value
we get back */
// try {
mainret = WinMain( GetModuleHandle( NULL ),
NULL,
lpszCommandLine,
SW_SHOWDEFAULT
);
// }
// except (UnhandledExceptionFilter( GetExceptionInformation() )) {
// ExitProcess( (DWORD)GetExceptionCode() );
// }
ExitProcess(mainret);
}
// Wrapper for LocalFree to make the code a little easier to read.
#define DeleteDynamicString(x) LocalFree((HLOCAL) (x))
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
LPSTR lpToken;
WNDCLASS WndClass;
MSG Msg;
DWORD pidSrc;
HANDLE hSrc, hSrcProc, hDstProc;
g_hInstance = hInstance;
// The command line format is:
// "tapisrv_process_id Stopevent_handle comm_handle modem_name"
//
// Get the source process id.
// if ( lpToken = strtok(lpCmdLine," ") )
if ( lpToken = ScanForChar(lpCmdLine,TEXT(' ')) )
{
pidSrc = atol(lpToken);
}
else
{
// Too few parameters ...
ASSERT(0);
return 0;
}
hSrcProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pidSrc);
hDstProc = GetCurrentProcess();
// Get the global shut down event handle.
// if ( lpToken = strtok(NULL," ") )
if ( lpToken = ScanForChar(NULL,TEXT(' ')) )
{
hSrc = (HANDLE)LongToHandle(atol(lpToken));
DuplicateHandle(hSrcProc, hSrc,
hDstProc, &g_hShutDownEvent,
0L, FALSE, DUPLICATE_SAME_ACCESS);
}
else
{
// Too few parameters ...
ASSERT(0);
return 0;
}
// Get a copy of the global device handle.
// if ( lpToken = strtok(NULL," ") )
if ( lpToken = ScanForChar(NULL,TEXT(' ')) )
{
hSrc = (HANDLE)LongToHandle(atol(lpToken));
DuplicateHandle(hSrcProc, hSrc,
hDstProc, &g_hCommDevice,
0L, FALSE, DUPLICATE_SAME_ACCESS);
}
else
{
// Too few parameters ...
if (g_hShutDownEvent)
{
CloseHandle(g_hShutDownEvent);
g_hShutDownEvent = NULL;
}
ASSERT(0);
return 0;
}
// Get the name of the modem device.
// if ( lpToken = strtok(NULL,"") )
if ( lpToken = ScanForChar(NULL,TEXT('\0')) )
{
// Get modem name ...
lstrcpy( g_szModemName, lpToken );
}
else
{
// Too few parameters ...
if (g_hShutDownEvent)
{
CloseHandle(g_hShutDownEvent);
g_hShutDownEvent = NULL;
}
if (g_hCommDevice)
{
CloseHandle(g_hCommDevice);
g_hCommDevice = NULL;
}
ASSERT(0);
return 0;
}
CloseHandle(hSrcProc);
//
// Register a window class for the Modem Monitor. This is done so that
// the power control panel applet has the ability to detect us and turn us
// off if we're running.
//
WndClass.style = CS_GLOBALCLASS;
WndClass.lpfnWndProc = ModemMonitorWndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = DLGWINDOWEXTRA;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CD));
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = MODEMMONITOR_CLASSNAME;
if (RegisterClass(&WndClass))
{
g_hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MODEMMONITOR), NULL, NULL);
if ( g_hWnd )
{
SendMessage(g_hWnd, MMWM_INITDIALOG, 0, 0);
while (GetMessage(&Msg, NULL, 0, 0))
{
if ( !IsDialogMessage( g_hWnd, &Msg ) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
UnregisterClass(WndClass.lpszClassName, WndClass.hInstance);
}
if (g_hShutDownEvent)
{
CloseHandle(g_hShutDownEvent);
g_hShutDownEvent = NULL;
}
if (g_hCommDevice)
{
CloseHandle(g_hCommDevice);
g_hCommDevice = NULL;
}
return 0;
}
VOID
WINAPI
LoadResources(
VOID
)
{
// Load tray icons.
DWORD i;
for (i=0; i<4; i++) {
g_hTrayIcon[i] = LoadImage(
g_hInstance,
MAKEINTRESOURCE(IDI_CD+i),
IMAGE_ICON,
16,
16,
0
);
}
#if 0
g_hTrayIcon[0] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_CD),
IMAGE_ICON, 16, 16, 0);
g_hTrayIcon[1] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_TX),
IMAGE_ICON, 16, 16, 0);
g_hTrayIcon[2] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_RX),
IMAGE_ICON, 16, 16, 0);
g_hTrayIcon[3] = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_RXTX),
IMAGE_ICON, 16, 16, 0);
#endif
for (i=0; i<2; i++) {
g_hModemLight[i] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_OFF+i));
}
#if 0
// Load Modem light bitmaps.
g_hModemLight[0] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_OFF));
g_hModemLight[1] = LoadBitmap( g_hInstance, MAKEINTRESOURCE(IDB_ON));
#endif
}
VOID
WINAPI
UnLoadResources(
VOID
)
{
UINT i;
// Unload tray icons.
for ( i = 0; i < NUMBER_OF_ICONS; i++ )
{
if ( g_hTrayIcon[i] )
DestroyIcon(g_hTrayIcon[i]);
}
// Unload modem light bitmaps.
for ( i = 0; i < NUMBER_OF_LIGHTS; i++ )
{
if ( g_hModemLight[i] )
DeleteObject(g_hModemLight[i]);
}
}
VOID
WINAPI
ResetModemBitMap(
HWND hWnd
)
{
// Clean up any old bitmaps.
if ( g_hModemImage )
DestroyIcon( g_hModemImage );
// Load the window bitmap.
g_hModemImage = LoadImage( g_hInstance, MAKEINTRESOURCE(IDI_LIGHTS),
IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR);
if ( g_hModemImage )
{
// Set the window bitmap.
SendDlgItemMessage( hWnd, IDC_MODEM_FRAME, STM_SETIMAGE,
(WPARAM)IMAGE_ICON, (LPARAM)g_hModemImage );
// Set the current lights.
SendDlgItemMessage( hWnd, IDC_MODEM_RX_FRAME, STM_SETIMAGE,
(WPARAM)IMAGE_BITMAP,
(LPARAM)g_hModemLight[g_ModemRXLightID] );
SendDlgItemMessage( hWnd, IDC_MODEM_TX_FRAME, STM_SETIMAGE,
(WPARAM)IMAGE_BITMAP,
(LPARAM)g_hModemLight[g_ModemTXLightID] );
}
}
/*******************************************************************************
*
* AdjustControlPosition
*
* DESCRIPTION:
* Adjust all the control positions based on the dialog resolution
*
* PARAMETERS:
* hWnd, handle of ModemMonitor window.
*
*******************************************************************************/
VOID
WINAPI
AdjustControlPosition(
HWND hWnd
)
{
HWND hwndImage, hCtrl;
RECT rect;
POINT ptOrg;
char szText[MAX_PATH+1];
// Find the anchor point of the image
// The modem image is centered
//
hwndImage = GetDlgItem(hWnd, IDC_MODEM_FRAME);
GetWindowRect(hwndImage, &rect);
ptOrg.x = (rect.left+rect.right-MODEM_BITMAP_WIDTH)/2;
ptOrg.y = (rect.top+rect.bottom-MODEM_BITMAP_HEIGHT)/2;
ScreenToClient(hWnd, &ptOrg);
// Adjust the lights
SetWindowPos(GetDlgItem(hWnd, IDC_MODEM_TX_FRAME), hwndImage,
ptOrg.x+TXL_X_OFFSET, ptOrg.y+TXL_Y_OFFSET,
0, 0, SWP_NOSIZE);
SetWindowPos(GetDlgItem(hWnd, IDC_MODEM_RX_FRAME), hwndImage,
ptOrg.x+RXL_X_OFFSET, ptOrg.y+RXL_Y_OFFSET,
0, 0, SWP_NOSIZE);
// Adjust the TRX text
hCtrl = GetDlgItem(hWnd, IDC_MODEMTXSTRING);
ptOrg.x -= (rect.right-rect.left-MODEM_BITMAP_WIDTH)/2;
GetWindowRect(hCtrl, &rect);
SetWindowPos(hCtrl, hwndImage, ptOrg.x+TXT_X_OFFSET,
ptOrg.y+TXT_Y_OFFSET-(rect.bottom-rect.top),
0, 0, SWP_NOSIZE);
GetWindowText(hCtrl, szText, sizeof(szText));
ASSERT(*szText != '\0');
UpdateTRXText(hWnd, IDC_MODEMTXSTRING, szText);
hCtrl = GetDlgItem(hWnd, IDC_MODEMRXSTRING);
SetWindowPos(hCtrl, hwndImage,
ptOrg.x+RXT_X_OFFSET, ptOrg.y+RXT_Y_OFFSET,
0, 0, SWP_NOSIZE);
GetWindowText(hCtrl, szText, sizeof(szText));
ASSERT(*szText != '\0');
UpdateTRXText(hWnd, IDC_MODEMRXSTRING, szText);
}
/*******************************************************************************
*
* ModemMonitorWndProc
*
* DESCRIPTION:
* Callback procedure for the ModemMonitor window.
*
* PARAMETERS:
* hWnd, handle of ModemMonitor window.
* Message,
* wParam,
* lParam,
* (returns),
*
*******************************************************************************/
LRESULT
WINAPI
ModemMonitorWndProc(
HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
switch (Message) {
case MMWM_INITDIALOG:
// Mark the dialog box as currently being hidden.
g_DlgHidden = TRUE;
// Load the tip string and icons for the modem monitor icon
if ( !LoadString(g_hInstance, IDS_MODEMTIP, g_szTipStr, MAXRCSTRING) )
lstrcpy( g_szTipStr, "" );
// Load modem icons
LoadResources();
// Update the modem's status.
if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_ADD, FALSE) )
{
#if 0
if (g_hShutDownEvent)
{
CloseHandle(g_hShutDownEvent);
g_hShutDownEvent = NULL;
}
if (g_hCommDevice)
{
CloseHandle(g_hCommDevice);
g_hCommDevice = NULL;
}
UnLoadResources();
#endif
DestroyWindow(hWnd);
break;
}
// Change window title.
SetWindowText(hWnd, g_szModemName);
// Set timer for minimum period between updates of modem status.
g_fTimerOn = SetTimer(
hWnd,
MDMSTATUS_UPDATE_TIMER_ID,
MDMSTATUS_UPDATE_TIMER_TIMEOUT,
NULL
);
// Load modem bitmap
ResetModemBitMap(hWnd);
// Adjust control position
AdjustControlPosition(hWnd);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
g_DlgHidden = TRUE;
ShowWindow(hWnd, SW_HIDE);
break;
}
break;
case MMWM_NOTIFYICON:
switch (lParam)
{
case WM_LBUTTONDBLCLK:
g_DlgHidden = FALSE;
if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_MODIFY, TRUE) )
{
CloseExternalResources(hWnd);
DestroyWindow(hWnd);
break;
}
SetForegroundWindow(hWnd);
ShowWindow(hWnd, SW_SHOWNORMAL);
break;
}
break;
case WM_TIMER:
// Update the modem status
if ( ModemMonitor_UpdateModemStatus(hWnd, NIM_MODIFY, FALSE) )
{
CloseExternalResources(hWnd);
DestroyWindow(hWnd);
}
break;
case WM_SYSCOLORCHANGE:
ResetModemBitMap(hWnd);
break;
case WM_CLOSE:
g_DlgHidden = TRUE;
ShowWindow(hWnd, SW_HIDE);
break;
case WM_DESTROY:
// Kill notification event
if (g_hShutDownEvent)
{
CloseHandle(g_hShutDownEvent);
g_hShutDownEvent = NULL;
}
if (g_hCommDevice)
{
CloseHandle(g_hCommDevice);
g_hCommDevice = NULL;
}
// Clean up modem bitmap.
if ( g_hModemImage )
DestroyIcon( g_hModemImage );
// Unload Icons
UnLoadResources();
PostQuitMessage(0);
break;
#ifdef HELP_WORKS
case WM_HELP:
case WM_CONTEXTMENU:
ContextHelp(gaLights, Message, wParam, lParam);
break;
#endif // HELP_WORKS
default:
return DefWindowProc(hWnd, Message, wParam, lParam);
}
return 0;
}
/*******************************************************************************
*
* ModemMonitor_UpdateControls
*
* DESCRIPTION:
*
* This procedure updates the tray icon and all dialog box strings.
*
* PARAMETERS:
* hWnd, handle of ModemMonitor window.
* NotifyIconMessage, either NIM_ADD or NIM_MODIFY depending on whether the
* tray icon needs to be added to the tray or modified in the tray.
*
*******************************************************************************/
BOOL
WINAPI
ModemMonitor_UpdateModemStatus(
HWND hWnd,
DWORD NotifyIconMessage,
BOOL fForceUpdate
)
{
SYSTEM_MODEM_STATUS SystemModemStatus;
BOOL fClosed = FALSE;
// Get the system modem status.
fClosed = GetSystemModemStatus(&SystemModemStatus);
if ( !fClosed )
{
// Display appropriate ICON in tray based on statistics received.
UpdateTrayIcon(hWnd, NotifyIconMessage, &SystemModemStatus);
// If the dialog box is not currently hidden, update the dialog box
// text strings and bitmaps.
if ( (!g_DlgHidden) || fForceUpdate ) {
// Update the dialog box time string.
UpdateDialogTimer(hWnd, &SystemModemStatus, fForceUpdate);
UpdateDialogBox(hWnd, &SystemModemStatus, fForceUpdate);
}
#if 0
// Update the dialog box time string.
UpdateDialogTimer(hWnd, &SystemModemStatus, fForceUpdate);
#endif
}
return fClosed;
}
/*******************************************************************************
*
* ModemMonitor_NotifyIcon
*
* DESCRIPTION:
*
* Modified from source found in BATMETER.C.
*
* This routine is a wrapper for Shell_NotifyIcon with has been modified to
* use a global string (g_pTipStr) for its Tip window.
*
* PARAMETERS:
* hWnd, handle of ModemMonitor window.
* Message,
* hIcon
*
*******************************************************************************/
VOID
WINAPI
ModemMonitor_NotifyIcon(
HWND hWnd,
DWORD Message,
HICON hIcon,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
)
{
NOTIFYICONDATA NotifyIconData;
NotifyIconData.cbSize = sizeof(NOTIFYICONDATA);
NotifyIconData.uID = 0;
NotifyIconData.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
NotifyIconData.uCallbackMessage = MMWM_NOTIFYICON;
NotifyIconData.hWnd = hWnd;
NotifyIconData.hIcon = hIcon;
if (lpSystemModemStatus)
wsprintf(NotifyIconData.szTip, g_szTipStr, lpSystemModemStatus->dwPerfRead,
lpSystemModemStatus->dwPerfWrite);
else
lstrcpy(NotifyIconData.szTip, "");
Shell_NotifyIcon(Message, &NotifyIconData);
}
/*******************************************************************************
*
* GetSystemModemStatus
*
* DESCRIPTION:
*
* This procedure consists of three stages.
*
* The first stage attempts to obtain a valid device handle for the modem.
*
* The second stage involves setting default modem status values for the case
* where the modem is not connected.
*
* The third stage only executes if a valid device handle which can be acted
* upon is obtained. This stage involves placing a DeviceIOControl to
* UNIMODEM and interpretting the statistics returned by the VXD.
*
* PARAMETERS:
*
* lpSystemModemStatus - A pointer to a modem statistics buffer.
*
*******************************************************************************/
#define COMMCONFIG_AND_MODEMSETTINGS_LEN (60*3)
BOOL
WINAPI
GetSystemModemStatus(
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
)
{
static DWORD dwPerfRead = 0;
static DWORD dwPerfWrite = 0;
DWORD dwRet;
BYTE byteTmp[COMMCONFIG_AND_MODEMSETTINGS_LEN];
LPCOMMCONFIG lpCC = (LPCOMMCONFIG)byteTmp;
DWORD dwSize;
OVERLAPPED ov ;
BOOL bResult=TRUE;
static DWORD BaudRate=0;
ZeroMemory(&ov,sizeof(ov));
ov.hEvent = CreateEvent(
NULL,
FALSE,
FALSE,
NULL
);
if (ov.hEvent == NULL) {
goto End;
}
//
// Make it so it doesn't hit unimdm.tsp's completion port.
//
ov.hEvent = (HANDLE)((ULONG_PTR)ov.hEvent | 1);
//
// Initialize Modem statistics to show no connection (the default case).
//
lpSystemModemStatus->DCERate = 0;
lpSystemModemStatus->Connected = FALSE;
lpSystemModemStatus->Reading = FALSE;
lpSystemModemStatus->Writing = FALSE;
lpSystemModemStatus->dwPerfRead = 0;
lpSystemModemStatus->dwPerfWrite = 0;
// Check the shut down event
if ( WaitForSingleObject( g_hShutDownEvent, 0 ) != WAIT_TIMEOUT )
{
goto End;
}
if (g_hCommDevice != NULL)
{
DWORD dwPassthroughState;
SERIALPERF_STATS serialstats;
DWORD dwWaitResult;
if (!DeviceIoControl(g_hCommDevice,
IOCTL_MODEM_GET_PASSTHROUGH,
&dwPassthroughState,
sizeof(dwPassthroughState),
&dwPassthroughState,
sizeof(dwPassthroughState),
&dwRet,
&ov))
{
if (ERROR_IO_PENDING != GetLastError())
{
ASSERT(0);
goto End;
}
if (!GetOverlappedResult(g_hCommDevice,
&ov,
&dwRet,
TRUE))
{
ASSERT(0);
goto End;
}
}
switch (dwPassthroughState)
{
case MODEM_PASSTHROUGH:
case MODEM_DCDSNIFF:
lpSystemModemStatus->Connected = TRUE;
break;
case MODEM_NOPASSTHROUGH:
default:
lpSystemModemStatus->Connected = FALSE;
goto End;
}
if (!DeviceIoControl(g_hCommDevice,
IOCTL_SERIAL_GET_STATS,
&serialstats,
sizeof(SERIALPERF_STATS),
&serialstats,
sizeof(SERIALPERF_STATS),
&dwRet,
&ov))
{
if (ERROR_IO_PENDING != GetLastError())
{
ASSERT(0);
goto End;
}
if (!GetOverlappedResult(g_hCommDevice,
&ov,
&dwRet,
TRUE))
{
ASSERT(0);
goto End;
}
}
// Set Modem connection rate, connection, data transmission and
// data reception flags.
lpSystemModemStatus->Reading = ( serialstats.ReceivedCount != dwPerfRead );
lpSystemModemStatus->Writing = ( serialstats.TransmittedCount != dwPerfWrite );
// Update bytes read and written history values for the next call
// call to this function.
dwPerfRead = serialstats.ReceivedCount;
dwPerfWrite = serialstats.TransmittedCount;
lpSystemModemStatus->dwPerfRead = serialstats.ReceivedCount;
lpSystemModemStatus->dwPerfWrite = serialstats.TransmittedCount;
if (BaudRate == 0) {
dwSize = sizeof(byteTmp);
if (GetCommConfig(g_hCommDevice,
lpCC,
&dwSize)) {
lpSystemModemStatus->DCERate =
((PMODEMSETTINGS)&lpCC->wcProviderData[0])->dwNegotiatedDCERate;
BaudRate=lpSystemModemStatus->DCERate;
} else {
ASSERT(0);
goto End;
}
} else {
lpSystemModemStatus->DCERate=BaudRate;
}
}
bResult=FALSE;
End:
CloseHandle((HANDLE)((DWORD_PTR)ov.hEvent & (~1)));
return bResult;
}
/*******************************************************************************
*
* UpdateTrayIcon
*
* DESCRIPTION:
*
* This procedure reads the modem status structure and updates the Modem
* Monitor tray icon. This is done by comparing the new status (NewIconID)
* with the old status (a global variable - g_TrayIconID) and updating the
* icon using ModemMonitor_NotifyIcon only if there has been a change.
*
* PARAMETERS:
* hWnd, handle to the modem monitor dialog box
* NotifyIconMessage, passed through from caller to ModemMonitor_NotifyIcon
* lpSystemModemStatus, modem status structure.
*
*******************************************************************************/
VOID
WINAPI
UpdateTrayIcon(
HWND hWnd,
DWORD NotifyIconMessage,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus
)
{
UINT NewIconID;
NewIconID = 0;
if ( lpSystemModemStatus->Reading )
NewIconID += ICON_RX_ON;
if ( lpSystemModemStatus->Writing )
NewIconID += ICON_TX_ON;
if ( g_TrayIconID != NewIconID )
{
// Update the tray by setting its icon appropriately and notifying
// the system to update the display.
g_TrayIconID = NewIconID;
ModemMonitor_NotifyIcon(hWnd, NotifyIconMessage,
g_hTrayIcon[g_TrayIconID],
lpSystemModemStatus);
}
}
/*******************************************************************************
*
* UpdateTRXText
*
* DESCRIPTION:
*
* This procedure adjusts the Tx/Rx text width
*
* PARAMETERS:
* hWnd, handle to the dialog window.
* idc, Resource ID of Tx or Rx text control
* pStr, new text
*
*******************************************************************************/
VOID
WINAPI
UpdateTRXText(
HWND hWnd,
UINT idc,
LPSTR pStr
)
{
HDC hDC;
HFONT hFont;
HWND hwndCtrl;
SIZE size;
RECT rect;
POINT ptOrg;
// Find the exact dimension of the TRX text which will appear
// on the screen
//
hwndCtrl = GetDlgItem(hWnd, idc);
GetWindowRect(hwndCtrl, &rect);
hDC = GetDC(hwndCtrl);
// Bail if we can't get a device context
if (!hDC) return;
hFont = SelectObject(hDC, (HFONT)SendMessage(hwndCtrl, WM_GETFONT, 0, 0));
GetTextExtentPoint32 (hDC, pStr, lstrlen(pStr), &size);
SelectObject(hDC, hFont);
ReleaseDC(hwndCtrl, hDC);
// If it is the transmitted line, align the bottom with the
// current position
//
if (idc == IDC_MODEMTXSTRING)
rect.top = rect.bottom-size.cy;
// Adjust the text control to exactly fit the displayed text
//
ptOrg = *(POINT *)((RECT *)&rect);
ScreenToClient(hWnd, &ptOrg);
SetWindowPos(hwndCtrl, GetDlgItem(hWnd, IDC_MODEM_FRAME),
ptOrg.x, ptOrg.y, size.cx, size.cy, 0);
SetWindowText(hwndCtrl, pStr);
}
/*******************************************************************************
*
* UpdateDialogBox
*
* DESCRIPTION:
*
* This procedure reads the modem status structure and updates the Modem
* Monitor Dialog box.
*
* PARAMETERS:
* hWnd, handle to the dialog window.
* lpSystemModemStatus, pointer to modem status structure.
*
*******************************************************************************/
VOID
WINAPI
UpdateDialogBox(
HWND hWnd,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
BOOL fForceUpdate
)
{
UINT NewModemRXLightID = 0;
UINT NewModemTXLightID = 0;
PSTR pRxTx;
// Obtain resource id numbers for the RX and TX lights.
if ( lpSystemModemStatus->Reading )
NewModemRXLightID += LIGHT_ON;
if ( lpSystemModemStatus->Writing )
NewModemTXLightID += LIGHT_ON;
// Update the modem lights if necessary.
if (( g_ModemRXLightID != NewModemRXLightID ) || fForceUpdate)
{
g_ModemRXLightID = NewModemRXLightID;
if ( g_hModemImage )
{
SendDlgItemMessage( hWnd, IDC_MODEM_RX_FRAME, STM_SETIMAGE,
(WPARAM)IMAGE_BITMAP,
(LPARAM)g_hModemLight[g_ModemRXLightID] );
};
}
if (( g_ModemTXLightID != NewModemTXLightID ) || fForceUpdate)
{
g_ModemTXLightID = NewModemTXLightID;
if ( g_hModemImage )
{
SendDlgItemMessage( hWnd, IDC_MODEM_TX_FRAME, STM_SETIMAGE,
(WPARAM)IMAGE_BITMAP,
(LPARAM)g_hModemLight[g_ModemTXLightID] );
};
}
if ( lpSystemModemStatus->Reading || fForceUpdate )
{
// Display the new byte-received count
//
pRxTx = LoadDynamicString(IDS_RXSTRING,
lpSystemModemStatus->dwPerfRead);
UpdateTRXText(hWnd, IDC_MODEMRXSTRING, pRxTx);
DeleteDynamicString(pRxTx);
}
if ( lpSystemModemStatus->Writing || fForceUpdate )
{
// Display the new byte-sent count
//
pRxTx = LoadDynamicString(IDS_TXSTRING,
lpSystemModemStatus->dwPerfWrite);
UpdateTRXText(hWnd, IDC_MODEMTXSTRING, pRxTx);
DeleteDynamicString(pRxTx);
}
}
/*******************************************************************************
*
* UpdateDialogTimer
*
* DESCRIPTION:
*
* This procedure sets the modem time since connection string.
* The string will change under any one of the three following conditions:
* i) The modem's connection status has changed.
* ii) A forced update was indicated.
* iii) The timer count for update has expired.
*
* PARAMETERS:
* hWnd, handle to the dialog window.
* lpSystemModemStatus, pointer to modem status structure.
* fForceUpdate, boolean for whether window update is necessary.
*
*******************************************************************************/
VOID
WINAPI
UpdateDialogTimer(
HWND hWnd,
LPSYSTEM_MODEM_STATUS lpSystemModemStatus,
BOOL fForceUpdate
)
{
static BOOL ModemConnected = FALSE;
static DWORD cTimer = 0;
static DWORD ConnectionStart = 0;
static DWORD dwPrevTime = 0;
DWORD dwTime;
UINT uHr, uMin;
PSTR pStr, pSubStr1, pSubStr2;
UINT NewStringID;
BOOL fBuildString;
fBuildString = FALSE;
if ( fForceUpdate )
fBuildString = TRUE;
if ( (lpSystemModemStatus->Connected) != (ModemConnected) )
{
fBuildString = TRUE;
ModemConnected = lpSystemModemStatus->Connected;
ConnectionStart = GetTickCount();
cTimer = 0;
}
if ( cTimer >= MDMSTATUS_UPDATE_TIMER_COUNT )
{
fBuildString = TRUE;
cTimer = 0;
}
// Build the string if necessary.
if ( fBuildString )
{
dwTime = (GetTickCount()-ConnectionStart)/1000L;
dwTime /= 60;
// If the time value has changed by at least one minute
if ( ( dwTime != dwPrevTime ) || ( dwPrevTime == 0 ) )
{
dwPrevTime = dwTime;
uMin = (UINT)(dwTime % 60);
uHr = (UINT)(dwTime / 60);
pSubStr1 = LoadDynamicString(IDS_CD, lpSystemModemStatus->DCERate);
pSubStr2 = NULL;
if ( uHr || uMin )
{
if ( uMin )
{
if ( uHr )
{
if ( uHr > 1 )
{
// Hours and at least one minute
if ( uMin > 1 )
NewStringID = IDS_HOURSMINS;
else
NewStringID = IDS_HOURSMIN;
}
else
{
// One hour and at least one minute
if ( uMin > 1 )
NewStringID = IDS_HOURMINS;
else
NewStringID = IDS_HOURMIN;
}
}
else
{
// Minutes only
if ( uMin > 1 )
NewStringID = IDS_MINS;
else
NewStringID = IDS_MIN;
}
}
else
{
// Hours only
if ( uHr > 1 )
NewStringID = IDS_HOURS;
else
NewStringID = IDS_HOUR;
}
pSubStr2 = LoadDynamicString(NewStringID, uHr, uMin);
pStr = LoadDynamicString(IDS_TIMESTRING, pSubStr1, pSubStr2);
}
else
{
pStr = LoadDynamicString(IDS_TIMESTRING, pSubStr1, "");
}
if ( pSubStr1 )
DeleteDynamicString(pSubStr1);
if ( pSubStr2 )
DeleteDynamicString(pSubStr2);
SetDlgItemText(hWnd, IDC_MODEMTIMESTRING, pStr);
if (g_pModemTimeString)
DeleteDynamicString(g_pModemTimeString);
g_pModemTimeString = pStr;
} // endif - time has changed by at least one minute.
}
// Increment the global timer string interval counter.
cTimer++;
}
/*******************************************************************************
*
* LoadDynamicString
*
* DESCRIPTION:
*
* From source found in BATMETER.C
*
* Wrapper for the FormatMessage function that loads a string from our
* resource table into a dynamically allocated buffer, optionally filling
* it with the variable arguments passed.
*
* BE CAREFUL in 16-bit code to pass 32-bit quantities for the variable
* arguments.
*
* PARAMETERS:
* StringID, resource identifier of the string to use.
* (optional), parameters to use to format the string message.
*
*******************************************************************************/
PSTR
NEAR CDECL
LoadDynamicString(
UINT StringID,
...
)
{
char Buffer[256];
PSTR pStr = NULL;
va_list Marker;
va_start(Marker, StringID);
LoadString(g_hInstance, StringID, Buffer, sizeof(Buffer));
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
(LPVOID) (LPSTR) Buffer, 0, 0, (LPSTR) (PSTR FAR *) &pStr, 0, &Marker);
return pStr;
}
/*******************************************************************************
*
* CloseExternalResources
*
* DESCRIPTION:
*
* This routine kills the timer and removes the tray icon associated
* with this application. This is done here (as opposed to in the
* WM_TIMER message) in order to meet the criterion that no calls using
* the window's handle may be made in the WM_DESTROY message handler
* excepting those involving memory de-allocation.
*
* PARAMETERS: none.
*
*******************************************************************************/
VOID
WINAPI
CloseExternalResources( HWND hWnd )
{
// Kill the timer
if ( g_fTimerOn )
{
KillTimer(hWnd, MDMSTATUS_UPDATE_TIMER_ID);
g_fTimerOn = FALSE;
}
// Remove ICON from tray.
ModemMonitor_NotifyIcon(hWnd, NIM_DELETE, g_hTrayIcon[g_TrayIconID], NULL);
}