windows-nt/Source/XPSP1/NT/termsrv/admtools/winutils/tscfg/atdlg.cpp
2020-09-26 16:20:57 +08:00

1443 lines
40 KiB
C++

//Copyright (c) 1998 - 1999 Microsoft Corporation
/*******************************************************************************
*
* atdlg.cpp
*
* implementation of WINCFG CAsyncTestDlg, CEchoEditControl, and CLed classes
*
* copyright notice: Copyright 1995, Citrix Systems Inc.
*
* $Author: butchd $ Butch Davis
*
* $Log: M:\nt\private\utils\citrix\winutils\wincfg\VCS\atdlg.cpp $
*
* Rev 1.18 12 Sep 1997 16:22:28 butchd
* better async test auto-disable/enable
*
* Rev 1.17 19 Jun 1997 19:21:14 kurtp
* update
*
* Rev 1.16 30 Sep 1996 12:11:22 butchd
* update
*
* Rev 1.15 20 Sep 1996 20:36:56 butchd
* update
*
* Rev 1.14 19 Sep 1996 15:57:56 butchd
* update
*
* Rev 1.13 12 Sep 1996 16:15:56 butchd
* update
*
*******************************************************************************/
/*
* include files
*/
#include "stdafx.h"
#include "wincfg.h"
#include "atdlg.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
extern CWincfgApp *pApp;
extern "C" LPCTSTR WinUtilsAppName;
extern "C" HWND WinUtilsAppWindow;
extern "C" HINSTANCE WinUtilsAppInstance;
static int LedIds[NUM_LEDS] = {
IDC_ATDLG_DTR,
IDC_ATDLG_RTS,
IDC_ATDLG_CTS,
IDC_ATDLG_DSR,
IDC_ATDLG_DCD,
IDC_ATDLG_RI };
///////////////////////////////////////////////////////////////////////////////
// CEchoEditControl class construction / destruction, implementation
////////////////////////////////////////////////////////////////////////////////
// CEchoEditControl message map
BEGIN_MESSAGE_MAP(CEchoEditControl, CEdit)
//{{AFX_MSG_MAP(CEchoEditControl)
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////
// CEchoEditControl commands
void
CEchoEditControl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
/*
* Tell dialog to write the character to the device unless we're
* currently processing edit control output. This flag check is needed
* because the CEdit::Cut() member function will generate an OnChar()
* event, which we need to ignore ('\b' processing).
*/
if ( !m_bProcessingOutput )
::SendMessage(m_hDlg, WM_ASYNCTESTWRITECHAR, nChar, 0);
/*
* Pass character on to the edit control. This will do nothing if
* the edit control is 'read only'. To cause a 'local echo' effect,
* set the edit control to 'read/write'.
*/
CEdit::OnChar(nChar, nRepCnt, nFlags);
} // end CEchoEditControl::OnChar
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg class construction / destruction, implementation
/*******************************************************************************
*
* CAsyncTestDlg - CAsyncTestDlg constructor
*
* ENTRY:
* EXIT:
* (Refer to MFC CDialog::CDialog documentation)
*
******************************************************************************/
CAsyncTestDlg::CAsyncTestDlg()
: CBaseDialog(CAsyncTestDlg::IDD),
m_hDevice(INVALID_HANDLE_VALUE),
m_hRedBrush(NULL),
m_LEDToggleTimer(0),
m_pATDlgInputThread(NULL),
m_CurrentPos(0),
m_hModem(NULL),
m_bDeletedWinStation(FALSE)
{
//{{AFX_DATA_INIT(CAsyncTestDlg)
//}}AFX_DATA_INIT
int i;
/*
* Create a solid RED brush for painting the 'LED's when 'on'.
*/
VERIFY( m_hRedBrush = CreateSolidBrush(RGB(255,0,0)) );
/*
* Initialize member variables.
*/
memset(&m_Status, 0, sizeof(PROTOCOLSTATUS));
memset(&m_OverlapWrite, 0, sizeof(OVERLAPPED));
/*
* Create the led objects.
*/
for ( i = 0; i < NUM_LEDS; i++ )
m_pLeds[i] = new CLed(m_hRedBrush);
} // end CAsyncTestDlg::CAsyncTestDlg
/*******************************************************************************
*
* ~CAsyncTestDlg - CAsyncTestDlg destructor
*
* ENTRY:
* EXIT:
* (Refer to MFC CDialog::~CDialog documentation)
*
******************************************************************************/
CAsyncTestDlg::~CAsyncTestDlg()
{
int i;
/*
* Zap our led objects.
*/
for ( i = 0; i < NUM_LEDS; i++ )
if ( m_pLeds[i] )
delete m_pLeds[i];
} // end CAsyncTestDlg::~CAsyncTestDlg
////////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg operations
/*******************************************************************************
*
* NotifyAbort - CAsyncTestDlg member function: private operation
*
* Post a WM_ASYNCTESTABORT message to notify the dialog of
* abort and reason.
*
* ENTRY:
* idError (input)
* Resource id for error message.
* EXIT:
*
******************************************************************************/
void
CAsyncTestDlg::NotifyAbort( UINT idError )
{
PostMessage(WM_ASYNCTESTABORT, idError, GetLastError());
} // end CAsyncTestDlg::NotifyAbort
/*******************************************************************************
*
* DeviceSetParams - CAsyncTestDlg member function: private operation
*
* Set device parameters for opened device.
*
* ENTRY:
* EXIT:
* TRUE - no error; FALSE error.
*
******************************************************************************/
BOOL
CAsyncTestDlg::DeviceSetParams()
{
PASYNCCONFIG pAsync;
PFLOWCONTROLCONFIG pFlow;
DCB Dcb;
/*
* Get pointer to async parameters
*/
pAsync = &m_PdConfig0.Params.Async;
/*
* Get current DCB
*/
if ( !GetCommState( m_hDevice, &Dcb ) )
return(FALSE);
/*
* Set defaults
*/
Dcb.fOutxCtsFlow = FALSE;
Dcb.fOutxDsrFlow = FALSE;
Dcb.fTXContinueOnXoff = TRUE;
Dcb.fOutX = FALSE;
Dcb.fInX = FALSE;
Dcb.fErrorChar = FALSE;
Dcb.fNull = FALSE;
Dcb.fAbortOnError = FALSE;
/*
* Set Communication parameters
*/
Dcb.BaudRate = pAsync->BaudRate;
Dcb.Parity = (BYTE) pAsync->Parity;
Dcb.StopBits = (BYTE) pAsync->StopBits;
Dcb.ByteSize = (BYTE) pAsync->ByteSize;
Dcb.fDsrSensitivity = pAsync->fEnableDsrSensitivity;
pFlow = &pAsync->FlowControl;
/*
* Initialize default DTR state
*/
if ( pFlow->fEnableDTR )
Dcb.fDtrControl = DTR_CONTROL_ENABLE;
else
Dcb.fDtrControl = DTR_CONTROL_DISABLE;
/*
* Initialize default RTS state
*/
if ( pFlow->fEnableRTS )
Dcb.fRtsControl = RTS_CONTROL_ENABLE;
else
Dcb.fRtsControl = RTS_CONTROL_DISABLE;
/*
* Initialize flow control
*/
switch ( pFlow->Type ) {
/*
* Initialize hardware flow control
*/
case FlowControl_Hardware :
switch ( pFlow->HardwareReceive ) {
case ReceiveFlowControl_RTS :
Dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
break;
case ReceiveFlowControl_DTR :
Dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
break;
}
switch ( pFlow->HardwareTransmit ) {
case TransmitFlowControl_CTS :
Dcb.fOutxCtsFlow = TRUE;
break;
case TransmitFlowControl_DSR :
Dcb.fOutxDsrFlow = TRUE;
break;
}
break;
/*
* Initialize software flow control
*/
case FlowControl_Software :
Dcb.fOutX = pFlow->fEnableSoftwareTx;
Dcb.fInX = pFlow->fEnableSoftwareRx;
Dcb.XonChar = (char) pFlow->XonChar;
Dcb.XoffChar = (char) pFlow->XoffChar;
break;
case FlowControl_None :
break;
default :
ASSERT( FALSE );
break;
}
/*
* Set new DCB
*/
if ( !SetCommState( m_hDevice, &Dcb ) )
return(FALSE);
return( TRUE );
} // end CAsyncTestDlg::DeviceSetParams
/*******************************************************************************
*
* DeviceWrite - CAsyncTestDlg member function: private operation
*
* Write out m_Buffer contents (m_BufferBytes length) to the m_hDevice.
*
* ENTRY:
* EXIT:
* TRUE - no error; FALSE error.
*
******************************************************************************/
BOOL
CAsyncTestDlg::DeviceWrite()
{
DWORD Error, BytesWritten;
/*
* Write data
*/
if ( !WriteFile( m_hDevice, m_Buffer, m_BufferBytes,
&BytesWritten, &m_OverlapWrite ) ) {
if ( (Error = GetLastError()) == ERROR_IO_PENDING ) {
/*
* Wait for write to complete (this may block till timeout)
*/
if ( !GetOverlappedResult( m_hDevice, &m_OverlapWrite,
&BytesWritten, TRUE ) ) {
OnAsyncTestError(IDP_ERROR_GET_OVERLAPPED_RESULT_WRITE, Error);
return(FALSE);
}
} else {
OnAsyncTestError(IDP_ERROR_WRITE_FILE, Error);
return(FALSE);
}
}
return(TRUE);
} // end CAsyncTestDlg::DeviceWrite
/*******************************************************************************
*
* SetInfoFields - CAsyncTestDlg member function: private operation
*
* Update the fields in the dialog with new data, if necessary.
*
* ENTRY:
* pCurrent (input)
* points to COMMINFO structure containing the current Comm Input data.
* pNew (input)
* points to COMMINFO structure containing the new Comm Input data.
*
* EXIT:
*
******************************************************************************/
void
CAsyncTestDlg::SetInfoFields( PPROTOCOLSTATUS pCurrent,
PPROTOCOLSTATUS pNew )
{
BOOL bSetTimer = FALSE;
/*
* Set new LED states if state change, or set up for quick toggle if
* no state changed, but change(s) were detected since last query.
*/
if ( (pCurrent->AsyncSignal & MS_DTR_ON) !=
(pNew->AsyncSignal & MS_DTR_ON) ) {
pNew->AsyncSignalMask &= ~EV_DTR;
((CLed *)GetDlgItem(IDC_ATDLG_DTR))->
Update(pNew->AsyncSignal & MS_DTR_ON);
} else if ( pNew->AsyncSignalMask & EV_DTR ) {
pCurrent->AsyncSignal ^= MS_DTR_ON;
((CLed *)GetDlgItem(IDC_ATDLG_DTR))->Toggle();
bSetTimer = TRUE;
}
if ( (pCurrent->AsyncSignal & MS_RTS_ON) !=
(pNew->AsyncSignal & MS_RTS_ON) ) {
pNew->AsyncSignalMask &= ~EV_RTS;
((CLed *)GetDlgItem(IDC_ATDLG_RTS))->
Update(pNew->AsyncSignal & MS_RTS_ON);
} else if ( pNew->AsyncSignalMask & EV_RTS ) {
pCurrent->AsyncSignal ^= MS_RTS_ON;
((CLed *)GetDlgItem(IDC_ATDLG_RTS))->Toggle();
bSetTimer = TRUE;
}
if ( (pCurrent->AsyncSignal & MS_CTS_ON) !=
(pNew->AsyncSignal & MS_CTS_ON) ) {
pNew->AsyncSignalMask &= ~EV_CTS;
((CLed *)GetDlgItem(IDC_ATDLG_CTS))->
Update(pNew->AsyncSignal & MS_CTS_ON);
} else if ( pNew->AsyncSignalMask & EV_CTS ) {
pCurrent->AsyncSignal ^= MS_CTS_ON;
((CLed *)GetDlgItem(IDC_ATDLG_CTS))->Toggle();
bSetTimer = TRUE;
}
if ( (pCurrent->AsyncSignal & MS_RLSD_ON) !=
(pNew->AsyncSignal & MS_RLSD_ON) ) {
pNew->AsyncSignalMask &= ~EV_RLSD;
((CLed *)GetDlgItem(IDC_ATDLG_DCD))->
Update(pNew->AsyncSignal & MS_RLSD_ON);
} else if ( pNew->AsyncSignalMask & EV_RLSD ) {
pCurrent->AsyncSignal ^= MS_RLSD_ON;
((CLed *)GetDlgItem(IDC_ATDLG_DCD))->Toggle();
bSetTimer = TRUE;
}
if ( (pCurrent->AsyncSignal & MS_DSR_ON) !=
(pNew->AsyncSignal & MS_DSR_ON) ) {
pNew->AsyncSignalMask &= ~EV_DSR;
((CLed *)GetDlgItem(IDC_ATDLG_DSR))->
Update(pNew->AsyncSignal & MS_DSR_ON);
} else if ( pNew->AsyncSignalMask & EV_DSR ) {
pCurrent->AsyncSignal ^= MS_DSR_ON;
((CLed *)GetDlgItem(IDC_ATDLG_DSR))->Toggle();
bSetTimer = TRUE;
}
if ( (pCurrent->AsyncSignal & MS_RING_ON) !=
(pNew->AsyncSignal & MS_RING_ON) ) {
pNew->AsyncSignalMask &= ~EV_RING;
((CLed *)GetDlgItem(IDC_ATDLG_RI))->
Update(pNew->AsyncSignal & MS_RING_ON);
} else if ( pNew->AsyncSignalMask & EV_RING ) {
pCurrent->AsyncSignal ^= MS_RING_ON;
((CLed *)GetDlgItem(IDC_ATDLG_RI))->Toggle();
bSetTimer = TRUE;
}
/*
* Create our led toggle timer if needed.
*/
if ( bSetTimer && !m_LEDToggleTimer )
m_LEDToggleTimer = SetTimer( IDD_ASYNC_TEST,
ASYNC_LED_TOGGLE_MSEC, NULL );
} // end CAsyncTestDlg::SetInfoFields
////////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg message map
BEGIN_MESSAGE_MAP(CAsyncTestDlg, CBaseDialog)
//{{AFX_MSG_MAP(CAsyncTestDlg)
ON_WM_TIMER()
ON_MESSAGE(WM_ASYNCTESTERROR, OnAsyncTestError)
ON_MESSAGE(WM_ASYNCTESTABORT, OnAsyncTestAbort)
ON_MESSAGE(WM_ASYNCTESTSTATUSREADY, OnAsyncTestStatusReady)
ON_MESSAGE(WM_ASYNCTESTINPUTREADY, OnAsyncTestInputReady)
ON_MESSAGE(WM_ASYNCTESTWRITECHAR, OnAsyncTestWriteChar)
ON_BN_CLICKED(IDC_ATDLG_MODEM_DIAL, OnClickedAtdlgModemDial)
ON_BN_CLICKED(IDC_ATDLG_MODEM_INIT, OnClickedAtdlgModemInit)
ON_BN_CLICKED(IDC_ATDLG_MODEM_LISTEN, OnClickedAtdlgModemListen)
ON_WM_NCDESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg commands
/*******************************************************************************
*
* OnInitDialog - CAsyncTestDlg member function: command (override)
*
* Performs the dialog intialization.
*
* ENTRY:
* EXIT:
* (Refer to CDialog::OnInitDialog documentation)
* WM_ASYNCTESTABORT message(s) will have been posted on error.
*
******************************************************************************/
BOOL CAsyncTestDlg::OnInitDialog()
{
int i;
DEVICENAME DeviceName;
COMMTIMEOUTS CommTimeouts;
BOOL bModemInit = TRUE;
BOOL bModemDial = TRUE;
BOOL bModemListen = TRUE;
#ifdef WINSTA
ULONG LogonId;
#endif // WINSTA
/*
* Call the parent classes' OnInitDialog to perform default dialog
* initialization.
*/
CBaseDialog::OnInitDialog();
/*
* Fill in the device and baud fields.
*/
SetDlgItemText( IDL_ATDLG_DEVICE,
m_PdConfig0.Params.Async.DeviceName );
SetDlgItemInt( IDL_ATDLG_BAUD,
m_PdConfig0.Params.Async.BaudRate,
FALSE );
/*
* If a WinStation memory object is currently present, reset it.
*/
#ifdef WINSTA
if ( m_pWSName &&
LogonIdFromWinStationName(SERVERNAME_CURRENT, m_pWSName, &LogonId) ) {
LONG Status;
ULONG Length;
if ( QueryLoggedOnCount(m_pWSName) ) {
if ( QuestionMessage( MB_YESNO | MB_ICONEXCLAMATION,
IDP_CONFIRM_ASYNCTESTDISABLE,
m_pWSName ) == IDNO ) {
PostMessage( WM_COMMAND, MAKEWPARAM( IDOK, BN_CLICKED ),
(LPARAM)(GetDlgItem(IDOK)->m_hWnd) );
return(TRUE); // exit dialog via posted 'OK' click
}
}
if ( (Status = RegWinStationQuery( SERVERNAME_CURRENT,
m_pWSName,
&m_WSConfig,
sizeof(WINSTATIONCONFIG2),
&Length )) ) {
NotifyAbort(IDP_ERROR_DISABLE);
return(TRUE);
}
m_WSConfig.Create.fEnableWinStation = FALSE;
if ( (Status = RegWinStationCreate( SERVERNAME_CURRENT,
m_pWSName,
FALSE,
&m_WSConfig,
sizeof(WINSTATIONCONFIG2) )) ) {
NotifyAbort(IDP_ERROR_DISABLE);
return(TRUE);
}
/*
* Do the reset. If, for some reason, the reset was unsucessful,
* the device open will fail (below).
*/
CWaitCursor wait;
WinStationReset(SERVERNAME_CURRENT, LogonId, TRUE);
m_bDeletedWinStation = TRUE;
}
#endif // WINSTA
/*
* Open the specified device.
*/
lstrcpy( DeviceName, TEXT("\\\\.\\") );
lstrcat( DeviceName, m_PdConfig0.Params.Async.DeviceName );
if ( (m_hDevice = CreateFile( DeviceName,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attr
OPEN_EXISTING, // must exist
FILE_FLAG_OVERLAPPED,
NULL // no template
)) == INVALID_HANDLE_VALUE ) {
NotifyAbort(IDP_ERROR_CANT_OPEN_DEVICE);
return(TRUE);
}
/*
* Set device timeouts & communication parameters and create an event
* for overlapped writes.
*/
memset(&CommTimeouts, 0, sizeof(COMMTIMEOUTS));
CommTimeouts.ReadIntervalTimeout = 1; // 1 msec
CommTimeouts.WriteTotalTimeoutConstant = 1000; // 1 second
if ( !SetCommTimeouts(m_hDevice, &CommTimeouts) ||
!DeviceSetParams() ||
!(m_OverlapWrite.hEvent = CreateEvent( NULL, TRUE,
FALSE, NULL )) ) {
NotifyAbort(IDP_ERROR_CANT_INITIALIZE_DEVICE);
return(TRUE);
}
/*
* Create the input thread object and initialize it's member variables.
*/
m_pATDlgInputThread = new CATDlgInputThread;
m_pATDlgInputThread->m_hDlg = m_hWnd;
m_pATDlgInputThread->m_hDevice = m_hDevice;
m_pATDlgInputThread->m_PdConfig = m_PdConfig0;
if ( !m_pATDlgInputThread->CreateThread() ) {
NotifyAbort(IDP_ERROR_CANT_CREATE_INPUT_THREAD);
return(TRUE);
}
#ifdef WF1x
/*
* If a modem is configured, get command strings for current configuration.
*/
if ( m_PdConfig1.Create.SdClass == PdModem ) {
ULONG dRC, fCapability, cbCommand;
if ( (dRC = ModemOpen( &m_hModem,
(BYTE *)m_PdConfig1.Params.Modem.ModemName,
&fCapability )) != ERROR_SUCCESS ) {
OnAsyncTestError(IDP_ERROR_MODEMOPEN_CONFIG, dRC);
bModemInit = bModemDial = bModemListen = FALSE;
m_hModem = NULL;
}
if ( m_hModem ) {
/*
* Set configured capability.
*/
fCapability = 0 ;
fCapability |= m_PdConfig1.Params.Modem.fHwFlowControl ?
MODEM_CAPABILITY_HW_FLOWCONTROL_ON :
MODEM_CAPABILITY_HW_FLOWCONTROL_OFF;
fCapability |= m_PdConfig1.Params.Modem.fProtocol ?
MODEM_CAPABILITY_ERROR_CORRECTION_ON :
MODEM_CAPABILITY_ERROR_CORRECTION_OFF;
fCapability |= m_PdConfig1.Params.Modem.fCompression ?
MODEM_CAPABILITY_COMPRESSION_ON :
MODEM_CAPABILITY_COMPRESSION_OFF;
fCapability |= m_PdConfig1.Params.Modem.fSpeaker ?
MODEM_CAPABILITY_SPEAKER_ON :
MODEM_CAPABILITY_SPEAKER_OFF;
fCapability |= m_PdConfig1.Params.Modem.fAutoBaud ?
MODEM_CAPABILITY_AUTOBAUD_ON :
MODEM_CAPABILITY_AUTOBAUD_OFF;
if ( (dRC = ModemSetInfo(m_hModem, &fCapability)) != ERROR_SUCCESS ) {
OnAsyncTestError(IDP_ERROR_MODEM_SET_INFO, dRC);
bModemInit = bModemDial = bModemListen = FALSE;
ModemClose(m_hModem);
m_hModem = NULL;
}
}
cbCommand = MAX_COMMAND_LEN;
if ( (dRC == ERROR_SUCCESS) &&
((dRC = ModemGetCommand( m_hModem, CT_LISTEN, FALSE,
(BYTE *)m_szModemListen,
&cbCommand)) != ERROR_SUCCESS) ) {
OnAsyncTestError(IDP_ERROR_MODEM_GET_LISTEN, dRC);
bModemListen = FALSE;
cbCommand = 0;
}
m_szModemListen[cbCommand] = TCHAR('\0');
}
#endif // WF1x
/*
* Hide the modem string buttons if a modem is not configured, or disable
* buttons that are not valid.
*/
#ifdef WF1x
if ( m_PdConfig1.Create.SdClass != PdModem ) {
#endif // WF1x
int id;
for ( id=IDC_ATDLG_MODEM_INIT; id <= IDC_ATDLG_PHONE_NUMBER; id++ ) {
GetDlgItem(id)->EnableWindow(FALSE);
GetDlgItem(id)->ShowWindow(SW_HIDE);
}
#ifdef WF1x
} else {
if ( !bModemInit )
GetDlgItem(IDC_ATDLG_MODEM_INIT)->EnableWindow(FALSE);
if ( !bModemListen )
GetDlgItem(IDC_ATDLG_MODEM_LISTEN)->EnableWindow(FALSE);
}
#endif // WF1x
/*
* Subclass the edit field to pass messages to dialog first.
*/
m_EditControl.m_hDlg = m_hWnd;
m_EditControl.m_bProcessingOutput = FALSE;
m_EditControl.SubclassDlgItem(IDC_ATDLG_EDIT, this);
/*
* Determine the edit control's font and format offset metrics.
*/
{
TEXTMETRIC tm;
RECT Rect;
CDC *pDC;
CFont *pFont, *pOldFont;
pDC = m_EditControl.GetDC();
pFont = m_EditControl.GetFont();
pOldFont = pDC->SelectObject(pFont);
pDC->GetTextMetrics(&tm);
pDC->SelectObject(pOldFont);
m_EditControl.ReleaseDC(pDC);
m_EditControl.m_FontHeight = tm.tmHeight;
m_EditControl.m_FontWidth = tm.tmMaxCharWidth;
m_EditControl.GetRect(&Rect);
m_EditControl.m_FormatOffsetY = Rect.top;
m_EditControl.m_FormatOffsetX = Rect.left;
}
/*
* Subclass the led controls and default to 'off'.
*/
for ( i = 0; i < NUM_LEDS; i++ ) {
m_pLeds[i]->Subclass( (CStatic *)GetDlgItem(LedIds[i]) );
m_pLeds[i]->Update(0);
}
return ( TRUE );
} // end CAsyncTestDlg::OnInitDialog
/*******************************************************************************
*
* OnTimer - CAsyncTestDlg member function: command (override)
*
* Used for quick 'LED toggle'.
*
* ENTRY:
* EXIT:
* (Refer to CWnd::OnTimer documentation)
*
******************************************************************************/
void
CAsyncTestDlg::OnTimer(UINT nIDEvent)
{
/*
* Process this timer event if it it our 'LED toggle' event.
*/
if ( nIDEvent == m_LEDToggleTimer ) {
/*
* Toggle each LED that is flagged as 'changed'.
*/
if ( m_Status.AsyncSignalMask & EV_DTR )
((CLed *)GetDlgItem(IDC_ATDLG_DTR))->Toggle();
if ( m_Status.AsyncSignalMask & EV_RTS )
((CLed *)GetDlgItem(IDC_ATDLG_RTS))->Toggle();
if ( m_Status.AsyncSignalMask & EV_CTS )
((CLed *)GetDlgItem(IDC_ATDLG_CTS))->Toggle();
if ( m_Status.AsyncSignalMask & EV_RLSD )
((CLed *)GetDlgItem(IDC_ATDLG_DCD))->Toggle();
if ( m_Status.AsyncSignalMask & EV_DSR )
((CLed *)GetDlgItem(IDC_ATDLG_DSR))->Toggle();
if ( m_Status.AsyncSignalMask & EV_RING )
((CLed *)GetDlgItem(IDC_ATDLG_RI))->Toggle();
/*
* Kill this timer event and indicate so.
*/
KillTimer(m_LEDToggleTimer);
m_LEDToggleTimer = 0;
} else
CBaseDialog::OnTimer(nIDEvent);
} // end CAsyncTestDlg::OnTimer
/*******************************************************************************
*
* OnAsyncTestError - CAsyncTestDlg member function: command
*
* Handle the Async Test Dialog error conditions.
*
* ENTRY:
* wParam (input)
* Contains message ID for error.
* wLparam (input)
* Contains error code (GetLastError or API-specific return code)
* EXIT:
* (LRESULT) always returns 0 to indicate error handling complete.
*
******************************************************************************/
LRESULT
CAsyncTestDlg::OnAsyncTestError( WPARAM wParam, LPARAM lParam )
{
/*
* Handle special and default errors.
*/
switch ( wParam ) {
#ifdef WF1x
case IDP_ERROR_MODEMOPEN_CONFIG:
#endif // WF1x
case IDP_ERROR_MODEM_SET_INFO:
case IDP_ERROR_MODEM_GET_DIAL:
case IDP_ERROR_MODEM_GET_INIT:
case IDP_ERROR_MODEM_GET_LISTEN:
#ifdef WF1x
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, lParam,
wParam, m_PdConfig1.Params.Modem.ModemName ))
#endif // WF1x
break;
case IDP_ERROR_DISABLE:
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, lParam,
wParam, m_pWSName ))
break;
default:
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, lParam, wParam, lParam ))
break;
}
return(0);
} // end CAsyncTestDlg::OnAsyncTestError
/*******************************************************************************
*
* OnAsyncTestAbort - CAsyncTestDlg member function: command
*
* Handle the Async Test Dialog abort conditions.
*
* ENTRY:
* wParam (input)
* Contains message ID for error.
* wLparam (input)
* Contains error code (GetLastError)
* EXIT:
* (LRESULT) always returns 0 to indicate error handling complete. Will
* have posted an 'Ok' (Exit) button click to cause exit.
*
******************************************************************************/
LRESULT
CAsyncTestDlg::OnAsyncTestAbort( WPARAM wParam, LPARAM lParam )
{
/*
* Call OnAsyncTestError() to output message.
*/
OnAsyncTestError(wParam, lParam);
/*
* Post a click for 'OK' (Exit) button to exit dialog.
*/
PostMessage( WM_COMMAND, MAKEWPARAM( IDOK, BN_CLICKED ),
(LPARAM)(GetDlgItem(IDOK)->m_hWnd) );
return(0);
} // end CAsyncTestDlg::OnAsyncTestAbort
/*******************************************************************************
*
* OnAsyncTestStatusReady - CAsyncTestDlg member function: command
*
* Update dialog with comm status information.
*
* ENTRY:
* wParam (input)
* not used (0)
* wLparam (input)
* not used (0)
* EXIT:
* (LRESULT) always returns 0.
*
******************************************************************************/
LRESULT
CAsyncTestDlg::OnAsyncTestStatusReady( WPARAM wParam, LPARAM lParam )
{
/*
* Update dialog fields with information from the input thread's
* PROTOCOLSTATUS structure.
*/
SetInfoFields( &m_Status, &(m_pATDlgInputThread->m_Status) );
/*
* Set our working PROTOCOLSTATUS structure to the new one and signal
* the thread that we're done.
*/
m_Status = m_pATDlgInputThread->m_Status;
m_pATDlgInputThread->SignalConsumed();
return(0);
} // end CAsyncTestDlg::OnAsyncTestStatusReady
/*******************************************************************************
*
* OnAsyncTestInputReady - CAsyncTestDlg member function: command
*
* Update dialog with comm input data.
*
* ENTRY:
* wParam (input)
* not used (0)
* wLparam (input)
* not used (0)
* EXIT:
* (LRESULT) always returns 0.
*
******************************************************************************/
LRESULT
CAsyncTestDlg::OnAsyncTestInputReady( WPARAM wParam, LPARAM lParam )
{
BYTE OutBuf[MAX_COMMAND_LEN+2];
int i, j;
/*
* Copy the thread's buffer and count locally.
*/
m_BufferBytes = m_pATDlgInputThread->m_BufferBytes;
memcpy(m_Buffer, m_pATDlgInputThread->m_Buffer, m_BufferBytes);
/*
* Always return caret to the current position before processing, and set
* edit control to 'read/write' so that character overwrites can occur
* properly. Finally, flag control for no redraw until all updates are completed,
* and flag 'processing output' to avoid OnChar() recursion during '\b' processing.
*/
m_EditControl.SetSel(m_CurrentPos, m_CurrentPos);
m_EditControl.SetReadOnly(FALSE);
m_EditControl.SetRedraw(FALSE);
/*
* Loop to traverse the buffer, with special processing for certain
* control characters.
*/
for ( i = 0, j = 0; m_BufferBytes; i++, m_BufferBytes-- ) {
switch ( m_Buffer[i] ) {
case '\b':
/*
* If there is data in the output buffer, write it now.
*/
if ( j )
OutputToEditControl(OutBuf, &j);
/*
* Output the '\b' (will actually cut current character from buffer)
*/
OutBuf[j++] = '\b';
OutputToEditControl(OutBuf, &j);
continue;
case '\r':
/*
* If there is data in the output buffer, write it now.
*/
if ( j )
OutputToEditControl(OutBuf, &j);
/*
* Output the '\r' (will not actually output, but will special case
* for caret positioning and screen update).
*/
OutBuf[j++] = '\r';
OutputToEditControl(OutBuf, &j);
continue;
case '\n':
/*
* If there is data in the output buffer, write it now.
*/
if ( j )
OutputToEditControl(OutBuf, &j);
/*
* Output the '\n' (will actually quietly output the '\r' and take
* care of scolling).
*/
OutBuf[j++] = '\n';
OutputToEditControl(OutBuf, &j);
continue;
default:
break;
}
/*
* Add this character to the output buffer.
*/
OutBuf[j++] = m_Buffer[i];
}
/*
* If there is anything remaining in the output buffer, output it now.
*/
if ( j )
OutputToEditControl(OutBuf, &j);
/*
* Place edit control back in 'read only' mode, flag 'not processing output',
* set redraw flag for control, and validate the entire control (updates have
* already taken place).
*/
m_EditControl.SetReadOnly(TRUE);
m_EditControl.SetRedraw(TRUE);
m_EditControl.ValidateRect(NULL);
/*
* Signal thread that we're done with input so that it can continue.
* NOTE: we don't do this at the beginning of the routine even though
* we could (for more parallelism), since a constantly chatty async
* line would cause WM_ASYNCTESTINPUTREADY messages to always be posted
* to our message queue, effectively blocking any other message processing
* (like telling the dialog to exit!).
*/
m_pATDlgInputThread->SignalConsumed();
return(0);
} // end CAsyncTestDlg::OnAsyncTestInputReady
void
CAsyncTestDlg::OutputToEditControl( BYTE *pBuffer, int *pIndex )
{
RECT Rect, ClientRect;
BOOL bScroll = FALSE;
int CurrentLine = m_EditControl.LineFromChar(m_CurrentPos);
int FirstVisibleLine = m_EditControl.GetFirstVisibleLine();
int CurrentLineIndex = m_EditControl.LineIndex(CurrentLine);
/*
* Calculate clip rectangle.
*/
Rect.top = ((CurrentLine - FirstVisibleLine) * m_EditControl.m_FontHeight)
+ m_EditControl.m_FormatOffsetY;
Rect.bottom = Rect.top + m_EditControl.m_FontHeight;
Rect.left = m_EditControl.m_FormatOffsetX +
((m_CurrentPos - CurrentLineIndex) * m_EditControl.m_FontWidth);
Rect.right = Rect.left + (*pIndex * m_EditControl.m_FontWidth);
/*
* Handle special cases.
*/
if ( pBuffer[0] == '\b' ) {
/*
* If we're already at the beginning of the line, clear buffer index
* and return (don't do anything).
*/
if ( m_CurrentPos == CurrentLineIndex ) {
*pIndex = 0;
return;
}
/*
* Position the caret back one character and select through current character.
*/
m_EditControl.SetSel(m_CurrentPos - 1, m_CurrentPos);
/*
* Cut the character out of the edit buffer.
*/
m_EditControl.m_bProcessingOutput = TRUE;
m_EditControl.Cut();
m_EditControl.m_bProcessingOutput = FALSE;
/*
* Decrement current position and zero index to suppress further output. Also,
* widen the clipping rectangle back one character.
*/
Rect.left -= m_EditControl.m_FontWidth;
m_CurrentPos--;
*pIndex = 0;
} else if ( pBuffer[0] == '\r' ) {
/*
* Position the caret at the beginning of the current line.
*/
m_CurrentPos = CurrentLineIndex;
m_EditControl.SetSel(m_CurrentPos, m_CurrentPos);
/*
* Zero index to keep from actually outputing to edit buffer.
*/
*pIndex = 0;
} else if ( pBuffer[0] == '\n' ) {
/*
* Position selection point at end of the current edit buffer.
*/
m_EditControl.SetSel(m_CurrentPos = m_EditControl.GetWindowTextLength(), -1 );
/*
* Cause '\r' '\n' pair to be output to edit buffer.
*/
pBuffer[0] = '\r';
pBuffer[1] = '\n';
*pIndex = 2;
/*
* See if scrolling needed.
*/
m_EditControl.GetClientRect(&ClientRect);
if ( (Rect.bottom + m_EditControl.m_FontHeight) > ClientRect.bottom )
bScroll = TRUE;
} else {
/*
* Set selection from current position through *pIndex characters. This
* will perform desired 'overwrite' function if current position is not at
* the end of the edit buffer.
*/
m_EditControl.SetSel(m_CurrentPos, m_CurrentPos + *pIndex);
}
/*
* If necessary, update the dialog's edit box with the buffer data.
*/
if ( *pIndex ) {
#ifdef UNICODE
TCHAR OutBuffer[MAX_COMMAND_LEN+1];
mbstowcs(OutBuffer, (PCHAR)pBuffer, *pIndex);
OutBuffer[*pIndex] = TEXT('\0');
m_EditControl.ReplaceSel(OutBuffer);
#else
pBuffer[*pIndex] = BYTE('\0');
m_EditControl.ReplaceSel((LPCSTR)pBuffer);
#endif // UNICODE
}
/*
* Update the current line.
*/
m_EditControl.SetRedraw(TRUE);
m_EditControl.ValidateRect(NULL);
m_EditControl.InvalidateRect(&Rect, FALSE);
m_EditControl.UpdateWindow();
/*
* If scrolling is required to see the new line, do so.
*/
if ( bScroll )
m_EditControl.LineScroll(1);
m_EditControl.SetRedraw(FALSE);
/*
* Update current position and clear buffer index.
*/
m_CurrentPos += *pIndex;
*pIndex = 0;
} // end CAsyncTestDlg::OutputToEditControl
/*******************************************************************************
*
* OnAsyncTestWriteChar - CAsyncTestDlg member function: command
*
* Place the specified character in m_Buffer, set m_BufferBytes to 1,
* and call DeviceWrite() to output the character to the device.
*
* ENTRY:
* wParam (input)
* Character to write.
* lParam (input)
* not used (0)
* EXIT:
* (LRESULT) always returns 0.
*
******************************************************************************/
LRESULT
CAsyncTestDlg::OnAsyncTestWriteChar( WPARAM wParam, LPARAM lParam )
{
/*
* Write the byte to the device.
*/
m_Buffer[0] = (BYTE)wParam;
m_BufferBytes = 1;
DeviceWrite();
return(0);
} // end CAsyncTestDlg::OnAsyncTestWriteChar
/*******************************************************************************
*
* OnClickedAtdlgModemDial - CAsyncTestDlg member function: command
*
* Send the modem dial string.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CAsyncTestDlg::OnClickedAtdlgModemDial()
{
#ifdef WF1x
TCHAR PhoneNumber[CALLBACK_LENGTH + 1];
ULONG dRC, cbCommand;
GetDlgItemText(IDC_ATDLG_PHONE_NUMBER, PhoneNumber, lengthof(PhoneNumber));
if ( (dRC = ModemSetCallback(m_hModem, (BYTE *)PhoneNumber)) != ERROR_SUCCESS ) {
OnAsyncTestError(IDP_ERROR_MODEM_SET_INFO, dRC);
return;
}
cbCommand = MAX_COMMAND_LEN;
if ( ((dRC = ModemGetCommand( m_hModem, CT_DIAL, TRUE,
(BYTE *)m_szModemDial,
&cbCommand)) != ERROR_SUCCESS) ) {
OnAsyncTestError(IDP_ERROR_MODEM_GET_DIAL, dRC);
return;
}
m_szModemDial[cbCommand] = TCHAR('\0');
lstrcpy((TCHAR *)m_Buffer, m_szModemDial);
m_BufferBytes = lstrlen((TCHAR *)m_Buffer);
DeviceWrite();
#endif // WF1x
} // end CAsyncTestDlg::OnClickedAtdlgModemDial
/*******************************************************************************
*
* OnClickedAtdlgModemInit - CAsyncTestDlg member function: command
*
* Send the modem init string.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CAsyncTestDlg::OnClickedAtdlgModemInit()
{
#ifdef WF1x
ULONG cbCommand;
ULONG fFirst = TRUE;
CWaitCursor Wait;
for ( ;; ) {
cbCommand = MAX_COMMAND_LEN;
if ( !m_hModem || (ModemGetCommand( m_hModem, CT_INIT, fFirst,
(BYTE *)m_szModemInit,
&cbCommand) != ERROR_SUCCESS) ) {
return;
}
fFirst = FALSE;
m_szModemInit[cbCommand] = TCHAR('\0');
lstrcpy((TCHAR *)m_Buffer, m_szModemInit);
m_BufferBytes = lstrlen((TCHAR *)m_Buffer);
DeviceWrite();
Sleep( 2000 );
}
#endif // WF1x
} // end CAsyncTestDlg::OnClickedAtdlgModemInit
/*******************************************************************************
*
* OnClickedAtdlgModemListen - CAsyncTestDlg member function: command
*
* Send the modem listen string.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CAsyncTestDlg::OnClickedAtdlgModemListen()
{
lstrcpy((TCHAR *)m_Buffer, m_szModemListen);
m_BufferBytes = lstrlen((TCHAR *)m_Buffer);
DeviceWrite();
} // end CAsyncTestDlg::OnClickedAtdlgModemListen
/*******************************************************************************
*
* OnNcDestroy - CAsyncTestDlg member function: command
*
* Clean up before deleting dialog object.
*
* ENTRY:
* EXIT:
* (Refer to CWnd::OnNcDestroy documentation)
*
******************************************************************************/
void
CAsyncTestDlg::OnNcDestroy()
{
if ( m_LEDToggleTimer )
KillTimer(m_LEDToggleTimer);
#ifdef WF1x
if ( m_hModem )
ModemClose(m_hModem);
#endif // WF1x
if ( m_pATDlgInputThread )
m_pATDlgInputThread->ExitThread();
if ( m_hDevice != INVALID_HANDLE_VALUE )
PurgeComm(m_hDevice, PURGE_TXABORT | PURGE_TXCLEAR);
if ( m_OverlapWrite.hEvent )
CloseHandle(m_OverlapWrite.hEvent);
if ( m_hDevice != INVALID_HANDLE_VALUE )
CloseHandle(m_hDevice);
if ( m_bDeletedWinStation && m_pWSName ) {
LONG Status;
m_WSConfig.Create.fEnableWinStation = TRUE;
if ( !(Status = RegWinStationCreate( SERVERNAME_CURRENT,
m_pWSName,
FALSE,
&m_WSConfig,
sizeof(WINSTATIONCONFIG2) )) ) {
#ifdef WINSTA
_WinStationReadRegistry(SERVERNAME_CURRENT);
#endif // WINSTA
}
}
DeleteObject(m_hRedBrush);
/*
* Call parent after we've cleaned up.
*/
CBaseDialog::OnNcDestroy();
} // end CAsyncTestDlg::OnNcDestroy
////////////////////////////////////////////////////////////////////////////////