1443 lines
40 KiB
C++
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
|
||
|
////////////////////////////////////////////////////////////////////////////////
|