windows-nt/Source/XPSP1/NT/termsrv/admtools/tscc/snapin/asyncdlg.cpp
2020-09-26 16:20:57 +08:00

4672 lines
123 KiB
C++

//Copyright (c) 1998 - 1999 Microsoft Corporation
#include "stdafx.h"
#include <winsta.h>
#include "resource.h"
#include "asyncdlg.h"
#include <utildll.h>
//Most of the code for this has been borrowed from tscfg.
extern void ErrMessage( HWND hwndOwner , INT_PTR iResourceID );
static int LedIds[NUM_LEDS] =
{
IDC_ATDLG_DTR,
IDC_ATDLG_RTS,
IDC_ATDLG_CTS,
IDC_ATDLG_DSR,
IDC_ATDLG_DCD,
IDC_ATDLG_RI
};
INT_PTR CBInsertInstancedName( LPCTSTR pName , HWND hCombo );
void ParseRootAndInstance( LPCTSTR pString, LPTSTR pRoot, long *pInstance );
//---------------------------------------------------------------------------------------------------
CAsyncDlg::CAsyncDlg( )
{
m_hDlg = NULL;
m_pCfgcomp = NULL;
m_nHexBase = 0;
m_szWinstation[ 0 ] = 0;
m_szWDName[ 0 ] = 0;
ZeroMemory( &m_ac , sizeof( ASYNCCONFIG ) );
ZeroMemory( &m_uc , sizeof( USERCONFIG ) );
ZeroMemory( &m_oldAC , sizeof( ASYNCCONFIG ) );
m_nOldAsyncDeviceNameSelection = ( INT )-1;
m_nOldAsyncConnectType = ( INT )-1;
m_nOldBaudRate = ( INT )-1;
m_nOldModemCallBack = ( INT )-1;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnInitDialog( HWND hDlg , LPTSTR szWDName , LPTSTR szWinstationName , ICfgComp *pCfgcomp )
{
TCHAR tchName[ 80 ];
TCHAR tchErrTitle[ 80 ];
TCHAR tchErrMsg[ 256 ];
TCHAR szDecoratedName[ DEVICENAME_LENGTH + MODEMNAME_LENGTH + 1 ];
ASSERT( pCfgcomp != NULL );
if( m_pCfgcomp == NULL )
{
m_pCfgcomp = pCfgcomp;
m_pCfgcomp->AddRef( );
}
m_hDlg = hDlg;
m_oldAC = m_ac;
if( szWinstationName != NULL )
{
lstrcpyn( m_szWinstation , szWinstationName , SIZE_OF_BUFFER( m_szWinstation ) - sizeof( TCHAR ) );
}
if( szWDName != NULL )
{
lstrcpyn( m_szWDName , szWDName , SIZE_OF_BUFFER( m_szWDName ) - sizeof( TCHAR ) );
}
// initialize controls
int idx = 0;
HRESULT hr;
SendMessage( GetDlgItem( hDlg , IDC_ASYNC_CONNECT ) , CB_RESETCONTENT , 0 , 0 );
while( SUCCEEDED( ( hr = pCfgcomp->GetConnTypeName( idx , tchName ) ) ) )
{
if( hr == S_FALSE )
{
break;
}
SendMessage( GetDlgItem( hDlg , IDC_ASYNC_CONNECT ) , CB_ADDSTRING , 0 , ( LPARAM )tchName );
idx++;
}
idx = 0;
SendMessage( GetDlgItem( hDlg , IDC_ASYNC_MODEMCALLBACK ) , CB_RESETCONTENT , 0 , 0 );
while( SUCCEEDED( ( hr = pCfgcomp->GetModemCallbackString( idx , tchName ) ) ) )
{
if( hr == S_FALSE )
{
break;
}
SendMessage( GetDlgItem( hDlg , IDC_ASYNC_MODEMCALLBACK ) , CB_ADDSTRING , 0 , ( LPARAM )tchName );
idx++;
}
// fill in device list
ULONG ulItems = 0;
LPBYTE pBuffer = NULL;
HWND hCombo = GetDlgItem( hDlg , IDC_ASYNC_DEVICENAME );
SendMessage( hCombo , CB_RESETCONTENT , 0 , 0 );
// szWDname is used for creating a new connection
// szWinstaionName is used if we're editing an existing connection
TCHAR *pszName = NULL;
NameType type = WdName;
if( szWDName == NULL )
{
pszName = szWinstationName;
type = WsName;
}
else
{
pszName = szWDName;
}
ASSERT( pszName != NULL );
hr = pCfgcomp->GetDeviceList( pszName , type , &ulItems , &pBuffer );
if( SUCCEEDED( hr ) )
{
PPDPARAMS pPdParams = NULL;
DBGMSG( L"TSCC : GetDeviceList returned %d devices that are available\n" , ulItems );
for( idx = 0 , pPdParams = ( PPDPARAMS )pBuffer; idx < ( int )ulItems ; idx++, pPdParams++ )
{
// Form decorated name.
#ifdef DBG
TCHAR temsg[ 128 ];
wsprintf( temsg , L"TSCC : %d ) %s is a device\n" , idx , pPdParams->Async.DeviceName );
ODS( temsg );
#endif
FormDecoratedAsyncDeviceName( szDecoratedName, &( pPdParams->Async ) );
if( pCfgcomp->IsAsyncDeviceAvailable( pPdParams->Async.DeviceName ) )
{
CBInsertInstancedName( szDecoratedName , hCombo );
}
#if 0 // this block was taken from tscfg and to this date it still does not make any sense
/*
Don't add this device to the list if it is already in use by a
WinStation other than the current one.
*/
if (FALSE == pCfgcomp->IsAsyncDeviceAvailable(pPdParams->Async.DeviceName))
continue;
// Insert the name into the combo-box if it's not a TAPI modem
// or it is a TAPI modem that's not being used by RAS and it's
// port is currently available.
INT_PTR nRet = SendMessage( hCombo , CB_FINDSTRINGEXACT , ( WPARAM )-1 , ( LPARAM )pPdParams->Async.DeviceName );
if( !*( pPdParams->Async.ModemName ) || ( /*!pPdParams->Async.Parity &&*/ ( nRet != ( INT_PTR )CB_ERR ) ) )
{
CBInsertInstancedName( szDecoratedName , hCombo );
}
#endif
// If this device is a modem, make sure that the raw port this
// device is configured on is not present in the list. This will
// also take care of removing the raw port for TAPI modems that are
// configured for use by RAS, in which case neither the configured.
// TAPI modem(s) or raw port will be present in the list.
INT_PTR nRet = SendMessage( hCombo , CB_FINDSTRINGEXACT , ( WPARAM )-1 , ( LPARAM )pPdParams->Async.DeviceName );
if( *( pPdParams->Async.ModemName ) && ( nRet != CB_ERR ) )
{
ODS(L"Deleting item\n");
SendMessage( hCombo , CB_DELETESTRING , ( WPARAM )nRet , 0 );
}
}
LocalFree( pBuffer );
}
// Always make sure that the currently configured device is in
if( m_ac.DeviceName[0] != 0 )
{
FormDecoratedAsyncDeviceName( szDecoratedName , &m_ac );
INT_PTR nRet = SendMessage( hCombo , CB_FINDSTRINGEXACT , ( WPARAM )-1 , ( LPARAM )szDecoratedName );
if( nRet == CB_ERR )
{
nRet = CBInsertInstancedName( szDecoratedName , hCombo );
}
SendMessage( hCombo , CB_SETCURSEL , ( WPARAM )nRet , 0 );
m_nOldAsyncDeviceNameSelection = (int)nRet;
}
else
{
SendMessage( hCombo , CB_SETCURSEL , ( WPARAM )0, 0 );
m_nOldAsyncDeviceNameSelection = 0;
}
INT_PTR iitem = SendMessage( hCombo , CB_GETCOUNT , ( WPARAM )0 , ( LPARAM )0);
if(0 == iitem || CB_ERR == iitem)
{
LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , SIZE_OF_BUFFER( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_NODEVICES , tchErrMsg , SIZE_OF_BUFFER( tchErrMsg ) );
MessageBox( hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );
return FALSE;
}
// Set the BAUDRATE combo-box selection (in it's edit field) and limit the
// edit field text.
TCHAR string[ULONG_DIGIT_MAX];
wsprintf( string, TEXT("%lu"), m_ac.BaudRate );
m_nOldBaudRate = ( INT )m_ac.BaudRate;
HWND hBaud = GetDlgItem( hDlg , IDC_ASYNC_BAUDRATE );
SendMessage( hBaud , CB_RESETCONTENT , 0 , 0 );
SetDlgItemText( hDlg , IDC_ASYNC_BAUDRATE , string );
SendMessage(hBaud , CB_LIMITTEXT , ULONG_DIGIT_MAX - 1 , 0 );
//The Baud rate field should contain only numbers
HWND hEdit = GetWindow(hBaud,GW_CHILD);
if(hEdit)
{
LONG Style = GetWindowLong(hEdit, GWL_STYLE);
SetWindowLong(hEdit,GWL_STYLE, Style | ES_NUMBER);
}
TCHAR TempString[100]; // Number enough to hold the baud rate values
//Add the default strings to the BaudRate Field
lstrcpy(TempString, L"9600");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
lstrcpy(TempString, L"19200");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
lstrcpy(TempString, L"38400");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
lstrcpy(TempString, L"57600");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
lstrcpy(TempString, L"115200");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
lstrcpy(TempString, L"230400");
SendMessage(hBaud , CB_ADDSTRING ,(WPARAM)0 ,(LPARAM)(LPCTSTR)TempString );
// Set the CONNECT combo-box selection.
SendMessage( GetDlgItem( hDlg , IDC_ASYNC_CONNECT ) , CB_SETCURSEL , m_ac.Connect.Type , 0 );
m_nOldAsyncConnectType = ( INT )m_ac.Connect.Type;
// CoTaskMemFree( pac );
HWND hCbxModemCallback = GetDlgItem( hDlg , IDC_ASYNC_MODEMCALLBACK );
// Set the MODEMCALLBACK combo-box selection, phone number, and 'inherit'
// checkboxes, based on the current UserConfig settings.
SendMessage( hCbxModemCallback , CB_SETCURSEL , ( WPARAM )m_uc.Callback , 0 );
m_nOldModemCallBack = ( INT )m_uc.Callback;
SetDlgItemText( hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER , m_uc.CallbackNumber );
CheckDlgButton( hDlg , IDC_ASYNC_MODEMCALLBACK_INHERIT , m_uc.fInheritCallback );
CheckDlgButton( hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT , m_uc.fInheritCallbackNumber );
OnSelchangeAsyncDevicename( );
return TRUE;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnSelchangeAsyncModemcallback()
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK);
/*
* Ignore this notification if the combo box is in a dropped-down
* state.
*/
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return FALSE;
}
/*
* Fetch current callback selection.
*/
INT index = (INT)SendMessage(hCbx,CB_GETCURSEL,0,0);
if( index != m_nOldModemCallBack )
{
m_uc.Callback = (CALLBACKCLASS)index;
m_nOldModemCallBack = index;
if( index == 0 ) // disabled
{
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , FALSE );
//EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , FALSE );
}
else
{
// inusre that these controls are in the proper state
OnClickedAsyncModemcallbackPhonenumberInherit();
}
return TRUE;
}
return FALSE;
} // end OnSelchangeAsyncModemcallback
//---------------------------------------------------------------------------------------------------
void CAsyncDlg::OnSelchangeAsyncModemcallbackPhoneNumber()
{
GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER);
/*
* Fetch current callback Phone number.
*/
GetDlgItemText(m_hDlg, IDC_ASYNC_MODEMCALLBACK_PHONENUMBER, m_uc.CallbackNumber,SIZE_OF_BUFFER(m_uc.CallbackNumber));
return;
} // end OnSelchangeAsyncModemcallback
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnSelchangeAsyncConnect()
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_CONNECT );
/*
* Ignore this notification if the combo box is in a dropped-down
* state.
*/
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return FALSE;
}
INT index = ( INT )SendMessage(hCbx,CB_GETCURSEL,0,0);
if( index != m_nOldAsyncConnectType )
{
m_ac.Connect.Type = (ASYNCCONNECTCLASS)index;
m_nOldAsyncConnectType = index;
return TRUE;
}
return FALSE;
} // end CAsyncDlg::OnSelchangeAsyncConnect
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnSelchangeAsyncBaudrate()
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_BAUDRATE );
ODS( L"TSCC : OnSelchangeAsyncBaudrate\n" );
TCHAR string[ULONG_DIGIT_MAX], *endptr = NULL;
/*
* Ignore this notification if the combo box is in a dropped-down
* state.
*/
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return FALSE;
}
//GetDlgItemText(m_hDlg, IDC_ASYNC_BAUDRATE, string,ULONG_DIGIT_MAX);
int idx = ( int )SendMessage( hCbx , CB_GETCURSEL , 0 , 0 );
SendMessage( hCbx , CB_GETLBTEXT , ( WPARAM )idx , ( LPARAM )&string[ 0 ] );
INT nBaudRate = ( INT )wcstoul(string, &endptr, 10);
if( m_nOldBaudRate != nBaudRate )
{
m_ac.BaudRate = nBaudRate;
m_nOldBaudRate = nBaudRate;
return TRUE;
}
return FALSE;
} // end CAsyncDlg::OnSelchangeAsyncBaudrate
//---------------------------------------------------------------------------------------------------
void CAsyncDlg::OnClickedModemProperties()
{
if ( !ConfigureModem( m_ac.ModemName, m_hDlg) )
{
ErrMessage(m_hDlg,IDP_ERROR_MODEM_PROPERTIES_NOT_AVAILABLE);
}
return;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnSelchangeAsyncDevicename( )
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_DEVICENAME );
BOOL bModemEnableFlag, bDirectEnableFlag;
INT_PTR index;
int nModemCmdShow, nDirectCmdShow;
// Ignore this notification if the combo box is in a dropped-down state.
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return TRUE;
}
if( ( index = SendMessage( hCbx , CB_GETCURSEL , 0 , 0 ) ) != CB_ERR )
{
if( m_nOldAsyncDeviceNameSelection != index )
{
TCHAR szDeviceName[DEVICENAME_LENGTH+MODEMNAME_LENGTH+1];
// Fetch current selection and parse into device and modem names.
TCHAR tchErrMsg[ 512 ];
TCHAR tchbuf[ 356 ];
TCHAR tchErrTitle[ 80 ];
LONG lCount = 0;
if( m_pCfgcomp != NULL )
{
m_pCfgcomp->QueryLoggedOnCount( m_szWinstation , &lCount );
if( lCount > 0 )
{
if( *m_ac.ModemName != 0 )
{
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_CHANGE_ASYNC , tchbuf , SIZE_OF_BUFFER( tchbuf ) ) );
}
else
{
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_CHANGE_MODEM , tchbuf , SIZE_OF_BUFFER( tchbuf ) ) );
}
wsprintf( tchErrMsg , tchbuf , m_szWinstation );
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_WARN_TITLE , tchErrTitle , SIZE_OF_BUFFER( tchErrTitle ) ) );
if( MessageBox( m_hDlg , tchErrMsg , tchErrTitle , MB_YESNO | MB_ICONEXCLAMATION ) == IDNO )
{
SendMessage( hCbx , CB_SETCURSEL , ( WPARAM )m_nOldAsyncDeviceNameSelection , 0 );
return FALSE;
}
}
}
SendMessage( hCbx , CB_GETLBTEXT , ( WPARAM )index , ( LPARAM )&szDeviceName[0] );
ParseDecoratedAsyncDeviceName( szDeviceName , &m_ac );
m_nOldAsyncDeviceNameSelection = (INT)index;
}
else
{
return FALSE;
}
}
/*
* The SetDefaults, Advanced, and Test buttons and Device Connect
* and Baud fields are enabled if the configuration is non-modem.
* Otherwise, the Configure Modem button and modem callback fields
* are enabled. (The Install Modems buttons is always enabled).
*/
if( ( *m_ac.ModemName != 0 ) )
{
bModemEnableFlag = TRUE;
nModemCmdShow = SW_SHOW;
bDirectEnableFlag = FALSE;
nDirectCmdShow = SW_HIDE;
} else {
bModemEnableFlag = FALSE;
nModemCmdShow = SW_HIDE;
bDirectEnableFlag = TRUE;
nDirectCmdShow = SW_SHOW;
}
ShowWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_MODEM_PROP_PROP) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_MODEM_PROP_PROP ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_MODEM_PROP_WIZ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_MODEM_PROP_WIZ ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK1 ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK1 ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_INHERIT ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_INHERIT ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK_PHONENUMBER ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDL_ASYNC_MODEMCALLBACK_PHONENUMBER ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , nModemCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , bModemEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDL_ASYNC_CONNECT ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDL_ASYNC_CONNECT ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_CONNECT ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_CONNECT ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDL_ASYNC_BAUDRATE ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDL_ASYNC_BAUDRATE ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_BAUDRATE ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_BAUDRATE ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_DEFAULTS ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_DEFAULTS ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_ADVANCED ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_ADVANCED ) , bDirectEnableFlag );
ShowWindow( GetDlgItem( m_hDlg, IDC_ASYNC_TEST ) , nDirectCmdShow );
EnableWindow( GetDlgItem( m_hDlg, IDC_ASYNC_TEST ) , bDirectEnableFlag );
// If this is a modem device, properly set the callback fields.
if( ( *m_ac.ModemName != 0 ) )
{
OnClickedAsyncModemcallbackInherit( );
OnClickedAsyncModemcallbackPhonenumberInherit( );
}
return TRUE;
}
//---------------------------------------------------------------------------------------------------
void CAsyncDlg::OnClickedAsyncModemcallbackInherit( )
{
BOOL bChecked = ( BOOL )SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_INHERIT ) , BM_GETCHECK , 0 , 0 );
BOOL bEnable = !bChecked;
m_uc.fInheritCallback = bChecked;
EnableWindow( GetDlgItem( m_hDlg , IDL_ASYNC_MODEMCALLBACK1 ) , bEnable );
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK ) , bEnable );
// now check to see if we need to enable the modem callback number
if( bChecked )
{
if( SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK) , CB_GETCURSEL , 0 , 0 ) == 0 )
{
if( !( BOOL )SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , BM_GETCHECK , 0 , 0 ) )
{
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , TRUE );
// EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , TRUE );
}
}
}
else
{
if( (INT)SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK) , CB_GETCURSEL , 0 , 0 ) == 0 )
{
if( !( BOOL )SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , BM_GETCHECK , 0 , 0 ) )
{
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , FALSE );
// EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , FALSE );
}
}
}
return;
}
//---------------------------------------------------------------------------------------------------
void CAsyncDlg::OnClickedAsyncModemcallbackPhonenumberInherit( )
{
BOOL bChecked = ( BOOL )SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT ) , BM_GETCHECK , 0 , 0 );
BOOL bEnable = !bChecked;
m_uc.fInheritCallbackNumber = bChecked;
if( !bChecked )
{
if( !( BOOL )SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_INHERIT ) , BM_GETCHECK , 0 , 0 ) )
{
if( SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK) , CB_GETCURSEL , 0 , 0 ) == 0 )
{
EnableWindow( GetDlgItem( m_hDlg , IDL_ASYNC_MODEMCALLBACK_PHONENUMBER ) , FALSE );
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , FALSE );
return;
}
}
}
EnableWindow( GetDlgItem( m_hDlg , IDL_ASYNC_MODEMCALLBACK_PHONENUMBER ) , bEnable );
EnableWindow( GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER ) , bEnable );
return;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::OnCommand( WORD wNotifyCode , WORD wID , HWND hwndCtrl , PBOOL pfPersisted )
{
UNREFERENCED_PARAMETER( hwndCtrl );
if( wNotifyCode == BN_CLICKED )
{
if( wID == IDC_ASYNC_DEFAULTS )
{
if( SetDefaults( ) == S_OK )
{
*pfPersisted = FALSE;
}
}
else if( wID == IDC_ASYNC_ADVANCED )
{
if( DoAsyncAdvance( ) == S_OK )
{
*pfPersisted = FALSE;
}
}
else if( wID == IDC_ASYNC_TEST )
{
DoAsyncTest( );
}
else if( wID == IDC_ASYNC_MODEMCALLBACK_INHERIT )
{
OnClickedAsyncModemcallbackInherit();
*pfPersisted = FALSE;
}
else if( wID == IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT )
{
OnClickedAsyncModemcallbackPhonenumberInherit();
*pfPersisted = FALSE;
}
else if(wID == IDC_MODEM_PROP_PROP || wID == IDC_MODEM_PROP_WIZ)
{
OnClickedModemProperties();
}
}
else if( wNotifyCode == CBN_SELCHANGE )
{
if(wID == IDC_ASYNC_DEVICENAME)
{
if( OnSelchangeAsyncDevicename( ) )
{
*pfPersisted = FALSE;
}
}
else if(wID == IDC_ASYNC_CONNECT)
{
if( OnSelchangeAsyncConnect() )
{
*pfPersisted = FALSE;
}
}
else if(wID == IDC_ASYNC_BAUDRATE)
{
if( OnSelchangeAsyncBaudrate() )
{
*pfPersisted = FALSE;
}
}
else if(wID == IDC_ASYNC_MODEMCALLBACK)
{
if( OnSelchangeAsyncModemcallback() )
{
*pfPersisted = FALSE;
}
}
}
/*else if( wNotifyCode == CBN_KILLFOCUS)
{
if(wID == IDC_ASYNC_BAUDRATE)
{
OnSelchangeAsyncBaudrate();
}
}*/
else if(wNotifyCode == EN_CHANGE )
{
if(wID == IDC_ASYNC_MODEMCALLBACK_PHONENUMBER)
{
OnSelchangeAsyncModemcallbackPhoneNumber();
*pfPersisted = FALSE;
}
}
return TRUE;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::AsyncRelease( )
{
if( m_pCfgcomp != NULL )
{
m_pCfgcomp->Release( );
}
return TRUE;
}
//---------------------------------------------------------------------------------------------------
HRESULT CAsyncDlg::SetAsyncFields(ASYNCCONFIG& AsyncConfig , PUSERCONFIG pUc)
{
HRESULT hres = S_OK;
if( pUc == NULL )
{
return E_INVALIDARG;
}
// check for variation
lstrcpy( AsyncConfig.DeviceName , m_ac.DeviceName );
if( memcmp( ( PVOID )&AsyncConfig , ( PVOID )&m_ac , sizeof( ASYNCCONFIG ) ) == 0 )
{
if( memcmp( pUc->CallbackNumber , m_uc.CallbackNumber , sizeof( m_uc.CallbackNumber ) ) == 0 &&
pUc->fInheritCallback == m_uc.fInheritCallback &&
pUc->fInheritCallbackNumber == m_uc.fInheritCallbackNumber )
{
return S_FALSE;
}
}
BOOL bSelectDefault = !( *AsyncConfig.DeviceName);
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_DEVICENAME );
HWND hCbxCallback = GetDlgItem( m_hDlg , IDC_ASYNC_MODEMCALLBACK );
TCHAR szDeviceName[DEVICENAME_LENGTH+MODEMNAME_LENGTH+1];
/*
* Set the DEVICE combo-box selection from the current selection.
*/
FormDecoratedAsyncDeviceName( szDeviceName, &AsyncConfig );
if( SendMessage( hCbx , CB_SELECTSTRING , ( WPARAM )-1 , ( LPARAM )szDeviceName ) == CB_ERR )
{
/*
* Can't select current async DeviceName in combo-box. If this is
* because we're supposed to select a default device name, select
* the first device in the list.
*/
if( bSelectDefault )
{
SendMessage( hCbx , CB_SETCURSEL , 0 , 0 );
}
else
{
hres = E_FAIL;
}
}
/*
* Set the MODEMCALLBACK combo-box selection, phone number, and 'inherit'
* checkboxes, based on the current UserConfig settings.
*/
SendMessage( hCbxCallback , CB_SETCURSEL , m_uc.Callback , 0 );
SetDlgItemText( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER, m_uc.CallbackNumber );
CheckDlgButton( m_hDlg , IDC_ASYNC_MODEMCALLBACK_INHERIT , m_uc.fInheritCallback );
CheckDlgButton( m_hDlg , IDC_ASYNC_MODEMCALLBACK_PHONENUMBER_INHERIT , m_uc.fInheritCallbackNumber );
/*
* Set the BAUDRATE combo-box selection (in it's edit field) and limit the
* edit field text.
*/
TCHAR string[ULONG_DIGIT_MAX];
wsprintf( string, TEXT("%lu"), AsyncConfig.BaudRate );
SetDlgItemText( m_hDlg , IDC_ASYNC_BAUDRATE, string );
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_BAUDRATE ) , CB_LIMITTEXT , ULONG_DIGIT_MAX-1 , 0);
HWND hEdit = GetWindow(GetDlgItem( m_hDlg , IDC_ASYNC_BAUDRATE ),GW_CHILD);
if(hEdit)
{
LONG Style = GetWindowLong(hEdit, GWL_STYLE);
SetWindowLong(hEdit,GWL_STYLE, Style | ES_NUMBER);
}
/*
* Set the CONNECT combo-box selection.
*/
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_CONNECT) , CB_SETCURSEL , AsyncConfig.Connect.Type , 0 );
// copy over default values
CopyMemory( ( PVOID )&m_ac , ( PVOID )&AsyncConfig , sizeof( ASYNCCONFIGW ) );
return hres;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::GetAsyncFields(ASYNCCONFIG& AsyncConfig, USERCONFIG UsrCfg)
{
/*
* Fetch the currently selected DEVICENAME string.
*/
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_DEVICENAME );
ASSERT( hCbx != NULL );
if( !SendMessage( hCbx , CB_GETCOUNT , 0 , 0 ) || SendMessage( hCbx , CB_GETCURSEL , 0 , 0 ) == CB_ERR )
{
ErrMessage( m_hDlg , IDS_INVALID_DEVICE );
return FALSE;
}
/*
* Get the MODEMCALLBACK phone number (callback state and 'user specified'
* flags are already gotten).
*/
GetDlgItemText(m_hDlg,IDC_ASYNC_MODEMCALLBACK_PHONENUMBER,
UsrCfg.CallbackNumber,
SIZE_OF_BUFFER(UsrCfg.CallbackNumber) );
/*
* Fetch and convert the BAUDRATE combo-box selection (in it's edit field).
*/
{
TCHAR string[ULONG_DIGIT_MAX], *endptr;
ULONG ul;
GetDlgItemText(m_hDlg,IDC_ASYNC_BAUDRATE, string, ULONG_DIGIT_MAX);
ul = wcstoul( string, &endptr, 10 );
if ( *endptr != TEXT('\0') )
{
/*
* Invalid character in Baud Rate field.
*/
ErrMessage( m_hDlg , IDS_INVALID_DEVICE );
return FALSE;
}
else
{
AsyncConfig.BaudRate = ul;
}
}
/*
* Fetch the CONNECT combo-box selection and set/reset the break
* disconnect flag.
*/
AsyncConfig.Connect.Type = (ASYNCCONNECTCLASS)SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_CONNECT ) , CB_GETCURSEL , 0 , 0 );
if(AsyncConfig.Connect.Type == Connect_FirstChar)
{
AsyncConfig.Connect.fEnableBreakDisconnect = 1;
}
else
{
AsyncConfig.Connect.fEnableBreakDisconnect = 0;
}
return(TRUE);
} // end CAsyncDlg::GetAsyncFields
//---------------------------------------------------------------------------------------------------
// returns E_FAIL for general error
// S_OK for default values saved
// S_FALSE for default values have not been changed
//---------------------------------------------------------------------------------------------------
HRESULT CAsyncDlg::SetDefaults()
{
ASYNCCONFIG AsyncConfig;
PUSERCONFIG pUserConfig = NULL;
HRESULT hResult;
hResult = m_pCfgcomp->GetAsyncConfig(m_szWDName,WdName,&AsyncConfig);
if( SUCCEEDED( hResult ) )
{
LONG lsz;
hResult = m_pCfgcomp->GetUserConfig( m_szWinstation , &lsz , &pUserConfig, TRUE );
}
if( SUCCEEDED( hResult ) )
{
hResult = SetAsyncFields( AsyncConfig , pUserConfig );
}
if( pUserConfig != NULL )
{
CoTaskMemFree( pUserConfig );
}
return hResult;
}
//---------------------------------------------------------------------------------------------------
HRESULT CAsyncDlg::DoAsyncAdvance( )
{
CAdvancedAsyncDlg AADlg;
//Initialize the dialog's member variables.
AADlg.m_Async = m_ac;
AADlg.m_bReadOnly = FALSE;
AADlg.m_bModem = FALSE;
AADlg.m_nHexBase = m_nHexBase;
PWS pWs = NULL;
LONG lSize = 0;
if( m_szWDName[ 0 ] != 0 )
{
ODS( L"CAsyncDlg::DoAsyncAdvance m_pCfgcomp->GetWdType\n" );
VERIFY_S( S_OK , m_pCfgcomp->GetWdType( m_szWDName , ( ULONG *)&AADlg.m_nWdFlag ) );
}
else if( SUCCEEDED( m_pCfgcomp->GetWSInfo( m_szWinstation , &lSize , &pWs ) ) )
{
ODS( L"CAsyncDlg::DoAsyncAdvance with m_szWinstation -- m_pCfgcomp->GetWdType\n" );
VERIFY_S( S_OK , m_pCfgcomp->GetWdType( pWs->wdName , ( ULONG *)&AADlg.m_nWdFlag ) ) ;
CoTaskMemFree( pWs );
}
AADlg.m_pCfgcomp = m_pCfgcomp; // addref here
// Invoke dialog
INT_PTR nRet = ::DialogBoxParam( _Module.GetResourceInstance( ) , MAKEINTRESOURCE( IDD_ASYNC_ADVANCED ) , m_hDlg , CAdvancedAsyncDlg::DlgProc , ( LPARAM )&AADlg );
if( nRet == IDOK )
{
// Fetch the dialog's member variables.
if( memcmp( ( PVOID )&m_ac ,( PVOID )&AADlg.m_Async , sizeof( ASYNCCONFIG ) ) != 0 )
{
m_ac = AADlg.m_Async;
m_nHexBase = AADlg.m_nHexBase;
return S_OK;
}
}
return S_FALSE;
}
//---------------------------------------------------------------------------------------------------
BOOL CAsyncDlg::DoAsyncTest( )
{
CAsyncTestDlg ATDlg( m_pCfgcomp );
// WINSTATIONCONFIG2W wsconfig;
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_DEVICENAME );
ASSERT( hCbx != NULL );
if( !SendMessage( hCbx , CB_GETCOUNT , 0 , 0 ) || SendMessage( hCbx , CB_GETCURSEL , 0 , 0 ) == CB_ERR )
{
ErrMessage( m_hDlg , IDS_INVALID_DEVICE );
return FALSE;
}
ATDlg.m_ac = m_ac;
ATDlg.m_pWSName = m_szWinstation;
// Invoke the dialog.
INT_PTR nRet = ::DialogBoxParam( _Module.GetResourceInstance( ) , MAKEINTRESOURCE( IDD_ASYNC_TEST ) , m_hDlg , CAsyncTestDlg::DlgProc , ( LPARAM )&ATDlg);
if( nRet == IDOK )
{
m_ac = ATDlg.m_ac;
}
return TRUE;
}
//*******************************************************************************
//
// Help functions from Citrix
//
/*******************************************************************************
*
* CBInsertInstancedName - helper function
*
* Insert the specified 'instanced' name into the specified combo box,
* using a special sort based on the 'root' name and 'instance' count.
*
* ENTRY:
* pName (input)
* Pointer to name string to insert.
* pComboBox (input)
* Pointer to CComboBox object to insert name string into.
*
* EXIT:
* (int) Combo box list index of name after insertion, or error code.
*
******************************************************************************/
INT_PTR CBInsertInstancedName( LPCTSTR pName, HWND hCombo )
{
INT_PTR i, count, result;
TCHAR NameRoot[64], ListRoot[64];
if( pName == NULL || *pName == 0 )
{
ODS( L"TSCC: Invalid Arg @ CBInsertInstancedName\n" );
return -1;
}
LPTSTR ListString = NULL;
long NameInstance, ListInstance;
/*
* Form the root and instance for this name
*/
ParseRootAndInstance( pName, NameRoot, &NameInstance );
/*
* Traverse combo box to perform insert.
*/
for ( i = 0, count = SendMessage( hCombo , CB_GETCOUNT , 0 , 0 ); i < count; i++ ) {
/*
* Fetch current combo (list) box string.
*/
if( ListString != NULL )
{
SendMessage( hCombo , CB_GETLBTEXT , ( WPARAM )i , ( LPARAM )ListString );
}
/*
* Parse the root and instance of the list box string.
*/
ParseRootAndInstance( ListString, ListRoot, &ListInstance );
/*
* If the list box string's root is greater than the our name string's
* root, or the root strings are the same but the list instance is
* greater than the name string's instance, or the root strings are
* the same and the instances are the same but the entire list string
* is greater than the entire name string, the name string belongs
* at the current list position: insert it there.
*/
if ( ((result = lstrcmpi( ListRoot, NameRoot )) > 0) ||
((result == 0) &&
(ListInstance > NameInstance)) ||
((result == 0) &&
(ListInstance == NameInstance) &&
( ListString != NULL && lstrcmpi(ListString, pName) > 0) ) )
{
return SendMessage( hCombo , CB_INSERTSTRING , ( WPARAM )i , ( LPARAM )pName );
}
}
/*
* Insert this name at the end of the list.
*/
return SendMessage( hCombo , CB_INSERTSTRING , ( WPARAM )-1 , ( LPARAM )pName );
} // end CBInsertInstancedName
/*******************************************************************************
*
* ParseRootAndInstance - helper function
*
* Parse the 'root' string and instance count for a specified string.
*
* ENTRY:
* pString (input)
* Points to the string to parse.
* pRoot (output)
* Points to the buffer to store the parsed 'root' string.
* pInstance (output)
* Points to the int variable to store the parsed instance count.
*
* EXIT:
* ParseRootAndInstance will parse only up to the first blank character
* of the string (if a blank exists).
* If the string contains no 'instance' count (no trailing digits), the
* pInstance variable will contain -1. If the string consists entirely
* of digits, the pInstance variable will contain the conversion of those
* digits and pRoot will contain a null string.
*
******************************************************************************/
void
ParseRootAndInstance( LPCTSTR pString,
LPTSTR pRoot,
long *pInstance )
{
LPCTSTR end, p;
TCHAR szString[256];
if( pString == NULL || pString[ 0 ] == 0 )
{
ODS( L"TSCC: Invalid arg @ ParseRootAndInstance\n" );
return;
}
/*
* Make a copy of the string and terminate at first blank (if present).
*/
lstrcpyn(szString, pString, SIZE_OF_BUFFER( szString ) );
// szString[ lstrlen(szString) - 1 ] = TEXT('\0');
TCHAR *pTemp = szString;
while( *pTemp && *pTemp != L' ' )
{
pTemp++;
}
p = &(pTemp[lstrlen(pTemp)-1]);
/*
* Parse the instance portion of the string.
*/
end = p;
while( (p >= pTemp) && !IsCharAlpha(*p) )
p--;
if ( p == end ) {
/*
* No trailing digits: indicate no 'instance' and make the 'root'
* the whole string.
*/
*pInstance = -1;
lstrcpy( pRoot, pTemp );
} else {
/*
* Trailing digits found (or entire string was digits): calculate
* 'instance' and copy the 'root' string (null if all digits).
*/
end = p;
*pInstance = (int)_tcstol( p+1, NULL, 10 );
/*
* Copy 'root' string.
*/
for ( p = szString; p <= end; pRoot++, p++ )
*pRoot = *p;
/*
* Terminate 'root' string.
*/
*pRoot = TEXT('\0');
}
} // end ParseRootAndInstance
////////////////////////////////////////////////////////////////////////////////
CAdvancedAsyncDlg::CAdvancedAsyncDlg()
{
m_hDlg = NULL;
} // end CAdvancedAsyncDlg::CAdvancedAsyncDlg
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::HandleEnterEscKey(int nID)
{
/*
* Check HW Flow Receive and Transmit combo boxes.
*/
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWRX );
ASSERT( hCbx != NULL );
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
if( nID == IDCANCEL )
{
// select original selection
SendMessage( hCbx , CB_SETCURSEL , ( WPARAM )m_Async.FlowControl.HardwareReceive , 0 );
}
SendMessage( hCbx , CB_SHOWDROPDOWN , ( WPARAM )FALSE , 0 );
return FALSE;
}
hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWTX );
ASSERT( hCbx != NULL );
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
if( nID == IDCANCEL )
{
// select original selection
SendMessage( hCbx , CB_SETCURSEL , ( WPARAM )m_Async.FlowControl.HardwareTransmit , 0 );
}
SendMessage( hCbx , CB_SHOWDROPDOWN , ( WPARAM )FALSE , 0 );
return FALSE;
}
/*
* No combo boxes are down; process Enter/Esc.
*/
return TRUE;
} // end CAdvancedAsyncDlg::HandleEnterEscKey
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::SetFields()
{
int nId = 0;
/*
* Set the FLOWCONTROL radio buttons.
*/
switch( m_Async.FlowControl.Type ) {
case FlowControl_None:
nId = IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE;
break;
case FlowControl_Hardware:
nId = IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE;
break;
case FlowControl_Software:
nId = IDC_ASYNC_ADVANCED_FLOWCONTROL_SOFTWARE;
break;
}
CheckRadioButton( m_hDlg ,
IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE,
IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE,
nId );
/*
* Set the text of the Hardware flowcontrol button.
*/
SetHWFlowText();
/*
* If a modem is defined, disable the Flow Control fields, since they cannot
* be modified (must match modem's flow control established in Modem dialog).
*/
if( m_bModem )
{
for ( nId = IDL_ASYNC_ADVANCED_FLOWCONTROL; nId <= IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE; nId++ )
{
EnableWindow( GetDlgItem( m_hDlg , nId ) , FALSE);
}
}
/*
* Call member functions to set the Global, Hardware, and Software fields.
*/
SetGlobalFields();
SetHWFields();
SetSWFields();
} // end CAdvancedAsyncDlg::SetFields
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::SetHWFlowText( )
{
TCHAR tchStr[ 256 ];
LoadString( _Module.GetResourceInstance( ) , IDS_HARDWARE , tchStr , SIZE_OF_BUFFER( tchStr ) );
switch ( m_Async.FlowControl.HardwareReceive )
{
case ReceiveFlowControl_None:
lstrcat( tchStr , TEXT(" (.../") );
break;
case ReceiveFlowControl_RTS:
lstrcat( tchStr , TEXT(" (RTS/") );
break;
case ReceiveFlowControl_DTR:
lstrcat( tchStr , TEXT(" (DTR/") ) ;
break;
}
switch ( m_Async.FlowControl.HardwareTransmit )
{
case TransmitFlowControl_None:
lstrcat( tchStr , TEXT("...)" ) );
break;
case TransmitFlowControl_CTS:
lstrcat( tchStr , TEXT("CTS)") );
break;
case TransmitFlowControl_DSR:
lstrcat( tchStr , TEXT("DSR)") );
break;
}
SetDlgItemText( m_hDlg , IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE , tchStr );
} // end CAdvancedAsyncDlg::SetHWFlowText
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::SetGlobalFields()
{
/*
* Select proper DTR radio button.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_DTROFF, IDC_ASYNC_ADVANCED_DTRON,
IDC_ASYNC_ADVANCED_DTROFF +
(int)m_Async.FlowControl.fEnableDTR );
/*
* Select proper RTS radio button.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_RTSOFF, IDC_ASYNC_ADVANCED_RTSON,
IDC_ASYNC_ADVANCED_RTSOFF +
(int)m_Async.FlowControl.fEnableRTS );
/*
* Set the PARITY radio buttons.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_PARITY_NONE,
IDC_ASYNC_ADVANCED_PARITY_SPACE,
IDC_ASYNC_ADVANCED_PARITY_NONE +
(int)m_Async.Parity );
/*
* Set the STOPBITS radio buttons.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_STOPBITS_1,
IDC_ASYNC_ADVANCED_STOPBITS_2,
IDC_ASYNC_ADVANCED_STOPBITS_1 +
(int)m_Async.StopBits );
/*
* Set the BYTESIZE radio buttons.
*
* NOTE: the constant '7' that is subtracted from the stored ByteSize
* must track the lowest allowed byte size / BYTESIZE radio button.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_BYTESIZE_7,
IDC_ASYNC_ADVANCED_BYTESIZE_8,
IDC_ASYNC_ADVANCED_BYTESIZE_7 +
((int)m_Async.ByteSize - 7) );
/*
* If the currently selected Wd is an ICA type, disable the BYTESIZE
* group box and buttons - user can't change from default.
*/
if ( m_nWdFlag & WDF_ICA )
{
int i;
for( i = IDL_ASYNC_ADVANCED_BYTESIZE ; i <= IDC_ASYNC_ADVANCED_BYTESIZE_8; i++ )
{
EnableWindow( GetDlgItem( m_hDlg , i ) , FALSE );
}
}
} // end CAdvancedAsyncDlg::SetGlobalFields
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::SetHWFields()
{
int i;
/*
* Initialize HW Receive class combo-box
*/
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWRX );
ASSERT( hCbx != NULL );
SendMessage( hCbx , CB_SETCURSEL , ( WPARAM )m_Async.FlowControl.HardwareReceive , 0 );
/*
* If HW flow control is selected AND the HW Receive class is set to
* ReceiveFlowControl_DTR, disable the DTR controls & labels.
* Otherwise, enable the DTR control & labels.
*/
for( i = IDL_ASYNC_ADVANCED_DTRSTATE ; i <= IDC_ASYNC_ADVANCED_DTRON ; i++ )
{
EnableWindow( GetDlgItem( m_hDlg , i ) , ( ( m_Async.FlowControl.Type == FlowControl_Hardware) &&
(m_Async.FlowControl.HardwareReceive == ReceiveFlowControl_DTR) ) ? FALSE : TRUE );
}
/*
* Initialize HW Transmit class combo-box.
*/
hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWTX);
SendMessage( hCbx , CB_SETCURSEL , ( WPARAM )m_Async.FlowControl.HardwareTransmit , 0 );
/*
* If HW flow control is selected AND the HW Receive class is set to
* ReceiveFlowControl_RTS, disable the RTS controls & labels.
* Otherwise, enable the RTS control & labels.
*/
for( i = IDL_ASYNC_ADVANCED_RTSSTATE ; i <= IDC_ASYNC_ADVANCED_RTSON ; i++ )
{
EnableWindow( GetDlgItem( m_hDlg , i ) , ( ( m_Async.FlowControl.Type == FlowControl_Hardware) &&
( m_Async.FlowControl.HardwareReceive == ReceiveFlowControl_RTS ) ) ? FALSE : TRUE );
}
/*
* Enable or disable all HW fields.
*/
for( i = IDL_ASYNC_ADVANCED_HARDWARE ; i <= IDC_ASYNC_ADVANCED_HWTX ; i++ )
{
EnableWindow( GetDlgItem( m_hDlg , i ) , m_Async.FlowControl.Type == FlowControl_Hardware );
}
} // end CAdvancedAsyncDlg::SetHWFields
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::SetSWFields()
{
TCHAR string[UCHAR_DIGIT_MAX];
/*
* Initialize Xon character edit control.
*/
wsprintf( string, ( m_nHexBase ? TEXT("0x%02X") : TEXT("%d")) , (UCHAR)m_Async.FlowControl.XonChar );
SetDlgItemText( m_hDlg , IDC_ASYNC_ADVANCED_XON , string );
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XON ) , EM_SETMODIFY , ( WPARAM )FALSE , 0 );
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XON ) , EM_LIMITTEXT , ( WPARAM )UCHAR_DIGIT_MAX-1 , 0 );
/*
* Initialize Xoff character edit control.
*/
wsprintf( string, ( m_nHexBase ? TEXT( "0x%02X" ) : TEXT( "%d" ) ) , ( UCHAR )m_Async.FlowControl.XoffChar );
SetDlgItemText( m_hDlg , IDC_ASYNC_ADVANCED_XOFF, string );
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XOFF ) , EM_SETMODIFY , ( WPARAM )FALSE , 0 );
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XOFF ) , EM_LIMITTEXT , ( WPARAM )UCHAR_DIGIT_MAX-1 , 0 );
/*
* Initialize the Xon/Xoff base control.
*/
CheckRadioButton( m_hDlg , IDC_ASYNC_ADVANCED_BASEDEC, IDC_ASYNC_ADVANCED_BASEHEX,
( int )( IDC_ASYNC_ADVANCED_BASEDEC + m_nHexBase ) );
/*
* Enable or disable all SW fields.
*/
for( int i = IDL_ASYNC_ADVANCED_SOFTWARE ; i <= IDC_ASYNC_ADVANCED_BASEHEX ; i++ )
{
EnableWindow( GetDlgItem( m_hDlg , i ) , m_Async.FlowControl.Type == FlowControl_Software );
}
} // end CAdvancedAsyncDlg::SetSWFields
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::GetFields()
{
/*
* Call member functions to get the Flow Control, Global, Hardware, and
* Software fields.
*/
GetFlowControlFields();
if ( !GetGlobalFields() )
return(FALSE);
if ( !GetHWFields() )
return(FALSE);
if ( !GetSWFields(TRUE) )
return(FALSE);
return(TRUE);
} // end CAdvancedAsyncDlg::GetFields
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::GetFlowControlFields()
{
switch( GetCheckedRadioButton( IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE , IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE ) )
{
case IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE:
m_Async.FlowControl.Type = FlowControl_None;
break;
case IDC_ASYNC_ADVANCED_FLOWCONTROL_SOFTWARE:
m_Async.FlowControl.Type = FlowControl_Software;
break;
case IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE:
m_Async.FlowControl.Type = FlowControl_Hardware;
break;
}
} // end CAdvancedAsyncDlg::GetFlowControlFields
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::GetGlobalFields()
{
/*
* Fetch DTR state.
*/
m_Async.FlowControl.fEnableDTR =
(GetCheckedRadioButton( IDC_ASYNC_ADVANCED_DTROFF,
IDC_ASYNC_ADVANCED_DTRON )
- IDC_ASYNC_ADVANCED_DTROFF);
/*
* Fetch RTS state.
*/
m_Async.FlowControl.fEnableRTS =
(GetCheckedRadioButton( IDC_ASYNC_ADVANCED_RTSOFF,
IDC_ASYNC_ADVANCED_RTSON )
- IDC_ASYNC_ADVANCED_RTSOFF);
/*
* Fetch the selected PARITY.
*/
m_Async.Parity = (ULONG)
(GetCheckedRadioButton( IDC_ASYNC_ADVANCED_PARITY_NONE,
IDC_ASYNC_ADVANCED_PARITY_SPACE )
- IDC_ASYNC_ADVANCED_PARITY_NONE);
/*
* Fetch the selected STOPBITS.
*/
m_Async.StopBits = (ULONG)
(GetCheckedRadioButton( IDC_ASYNC_ADVANCED_STOPBITS_1,
IDC_ASYNC_ADVANCED_STOPBITS_2 )
- IDC_ASYNC_ADVANCED_STOPBITS_1);
/*
* Fetch the selected BYTESIZE.
*
* NOTE: the constant '7' that is added to the stored ByteSize
* must track the lowest allowed byte size / BYTESIZE radio button.
*/
m_Async.ByteSize = (ULONG)
(GetCheckedRadioButton( IDC_ASYNC_ADVANCED_BYTESIZE_7,
IDC_ASYNC_ADVANCED_BYTESIZE_8 )
- IDC_ASYNC_ADVANCED_BYTESIZE_7 + 7);
return(TRUE);
} // end CAdvancedAsyncDlg::GetGlobalFields
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::GetHWFields()
{
/*
* Fetch the HW receive flow class.
*/
m_Async.FlowControl.HardwareReceive = ( RECEIVEFLOWCONTROLCLASS )
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWRX ) , CB_GETCURSEL , 0 , 0 );
/*
* Fetch the HW transmit flow class.
*/
m_Async.FlowControl.HardwareTransmit = ( TRANSMITFLOWCONTROLCLASS )
SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWTX ) , CB_GETCURSEL , 0 , 0 );
return TRUE;
} // end CAdvancedAsyncDlg::GetHWFields
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::GetSWFields( BOOL bValidate )
{
TCHAR string[UCHAR_DIGIT_MAX], *endptr;
ULONG ul;
INT_PTR nNewHexBase, base;
/*
* Determine the current state of the base controls and save.
*/
nNewHexBase = (GetCheckedRadioButton( IDC_ASYNC_ADVANCED_BASEDEC,
IDC_ASYNC_ADVANCED_BASEHEX )
- IDC_ASYNC_ADVANCED_BASEDEC);
/*
* Fetch and convert XON character.
*/
GetDlgItemText( m_hDlg , IDC_ASYNC_ADVANCED_XON , string , SIZE_OF_BUFFER( string ) );
/*
* If the edit box is modified, use the 'new' base for conversion.
*/
base = SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XON ) , EM_GETMODIFY , 0 , 0 ) ? nNewHexBase : m_nHexBase ;
ul = _tcstoul( string, &endptr, (base ? 16 : 10) );
/*
* If validation is requested and there is a problem with the input,
* complain and allow user to fix.
*/
if( bValidate && ( (*endptr != TEXT('\0') ) || ( ul > 255 ) ) )
{
/*
* Invalid character in field or invalid value.
*/
// ERROR_MESSAGE((IDP_INVALID_XONXOFF))
/*
* Set focus to the control so that it can be fixed.
*/
SetFocus( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XON ) );
return FALSE;
}
/*
* Save the Xon character.
*/
m_Async.FlowControl.XonChar = (UCHAR)ul;
/*
* Fetch and convert XOFF character.
*/
GetDlgItemText( m_hDlg , IDC_ASYNC_ADVANCED_XOFF , string , SIZE_OF_BUFFER( string ) );
/*
* If the edit box is modified, use the 'new' base for conversion.
*/
base = SendMessage( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XOFF ) , EM_GETMODIFY , 0 , 0 ) ? nNewHexBase : m_nHexBase ;
ul = _tcstoul( string, &endptr, (base ? 16 : 10) );
/*
* If validation is requested and there is a problem with the input,
* complain and allow user to fix.
*/
if( bValidate && ( (*endptr != TEXT('\0' )) || ( ul > 255 ) ) )
{
/*
* Invalid character in field or invalid value.
*/
// ERROR_MESSAGE((IDP_INVALID_XONXOFF))
/*
* Set focus to the control so that it can be fixed.
*/
SetFocus( GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_XOFF ) );
return FALSE;
}
/*
* Save the Xoff character.
*/
m_Async.FlowControl.XoffChar = (UCHAR)ul;
/*
* Save the current base state.
*/
m_nHexBase = nNewHexBase;
return TRUE;
} // end CAdvancedAsyncDlg::GetSWFields
////////////////////////////////////////////////////////////////////////////////
// CAdvancedAsyncDlg message map
BOOL CAdvancedAsyncDlg::OnCommand( WORD wNotifyCode , WORD wID , HWND hwndCtrl )
{
switch( wNotifyCode )
{
case BN_CLICKED:
if( wID == IDC_ASYNC_ADVANCED_BASEDEC )
{
OnClickedAsyncAdvancedBasedec( );
}
else if( wID == IDC_ASYNC_ADVANCED_BASEHEX )
{
OnClickedAsyncAdvancedBasehex( );
}
else if( wID == IDC_ASYNC_ADVANCED_FLOWCONTROL_HARDWARE )
{
OnClickedAsyncAdvancedFlowcontrolHardware( );
}
else if( wID == IDC_ASYNC_ADVANCED_FLOWCONTROL_SOFTWARE )
{
OnClickedAsyncAdvancedFlowcontrolSoftware( );
}
else if( wID == IDC_ASYNC_ADVANCED_FLOWCONTROL_NONE )
{
OnClickedAsyncAdvancedFlowcontrolNone( );
}
else if( wID == IDOK )
{
OnOK( );
return EndDialog( m_hDlg , IDOK );
}
else if( wID == IDCANCEL )
{
OnCancel( );
return EndDialog( m_hDlg , IDCANCEL );
}
else if( wID == ID_HELP )
{
TCHAR tchHelpFile[ MAX_PATH ];
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_ASYNC_HELPFILE , tchHelpFile , SIZE_OF_BUFFER( tchHelpFile ) ) );
WinHelp( GetParent( hwndCtrl ) , tchHelpFile , HELP_CONTEXT , HID_ASYNCADVANCE );
}
break;
case CBN_CLOSEUP:
if( wID == IDC_ASYNC_ADVANCED_HWRX )
{
OnCloseupAsyncAdvancedHwrx( );
}
else if( wID == IDC_ASYNC_ADVANCED_HWTX )
{
OnCloseupAsyncAdvancedHwtx( );
}
break;
case CBN_SELCHANGE:
if( wID == IDC_ASYNC_ADVANCED_HWRX )
{
OnSelchangeAsyncAdvancedHwrx( );
}
else if( wID == IDC_ASYNC_ADVANCED_HWTX )
{
OnSelchangeAsyncAdvancedHwtx( );
}
break;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// CAdvancedAsyncDlg commands
//---------------------------------------------------------------------------------------------------
BOOL CAdvancedAsyncDlg::OnInitDialog( HWND hDlg , WPARAM wp , LPARAM lp )
{
UNREFERENCED_PARAMETER( wp );
UNREFERENCED_PARAMETER( lp );
// int i;
TCHAR tchString[ 80 ];
HWND hCbx = GetDlgItem( hDlg , IDC_ASYNC_ADVANCED_HWRX );
ASSERT( hCbx != NULL );
// Load up combo boxes with strings.
m_hDlg = hDlg;
int idx = 0;
HRESULT hr;
while( SUCCEEDED( ( hr = m_pCfgcomp->GetHWReceiveName( idx , tchString ) ) ) )
{
if( hr == S_FALSE )
{
break;
}
SendMessage( hCbx , CB_ADDSTRING , 0 , ( LPARAM )tchString );
idx++;
}
hCbx = GetDlgItem( hDlg , IDC_ASYNC_ADVANCED_HWTX);
ASSERT( hCbx != NULL );
idx = 0;
while( SUCCEEDED( ( hr = m_pCfgcomp->GetHWTransmitName( idx , tchString ) ) ) )
{
if( hr == S_FALSE )
{
break;
}
SendMessage( hCbx , CB_ADDSTRING , 0 , ( LPARAM )tchString );
idx++;
}
// Initalize all dialog fields.
SetFields();
/*
if ( m_bReadOnly ) {
/*
* Document is 'read-only': disable all dialog controls and labels
* except for CANCEL & HELP buttons.
for ( i=IDL_ASYNC_ADVANCED_FLOWCONTROL;
i <=IDC_ASYNC_ADVANCED_BYTESIZE_8; i++ )
GetDlgItem(i)->EnableWindow(FALSE);
GetDlgItem(IDOK)->EnableWindow(FALSE);
}
*/
return(TRUE);
} // end CAdvancedAsyncDlg::OnInitDialog
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolHardware()
{
GetFlowControlFields();
SetFields();
} // end CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolHardware
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolSoftware()
{
GetFlowControlFields();
SetFields();
} // end CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolSoftware
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolNone()
{
GetFlowControlFields();
SetFields();
} // end CAdvancedAsyncDlg::OnClickedAsyncAdvancedFlowcontrolNone
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnCloseupAsyncAdvancedHwrx()
{
OnSelchangeAsyncAdvancedHwrx();
} // end CAdvancedAsyncDlg::OnCloseupAsyncAdvancedHwrx
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnSelchangeAsyncAdvancedHwrx()
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWRX );
ASSERT( hCbx != NULL );
/*
* Ignore this notification if the combo box is in a dropped-down
* state.
*/
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return;
}
/*
* Fetch and Set the Hardware fields to update.
*/
GetHWFields();
SetHWFields();
SetHWFlowText();
} // end CAdvancedAsyncDlg::OnSelchangeAsyncAdvancedHwrx
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnCloseupAsyncAdvancedHwtx()
{
OnSelchangeAsyncAdvancedHwtx();
} // end CAdvancedAsyncDlg::OnCloseupAsyncAdvancedHwtx
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnSelchangeAsyncAdvancedHwtx()
{
HWND hCbx = GetDlgItem( m_hDlg , IDC_ASYNC_ADVANCED_HWTX );
ASSERT( hCbx != NULL );
/*
* Ignore this notification if the combo box is in a dropped-down
* state.
*/
if( SendMessage( hCbx , CB_GETDROPPEDSTATE , 0 , 0 ) )
{
return;
}
/*
* Fetch and Set the Hardware fields to update.
*/
GetHWFields();
SetHWFields();
SetHWFlowText();
} // end CAdvancedAsyncDlg::OnSelchangeAsyncAdvancedHwtx
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnClickedAsyncAdvancedBasedec()
{
/*
* Get/Set the SW fields to display in decimal base.
*/
GetSWFields(FALSE);
SetSWFields();
} // end CAdvancedAsyncDlg::OnClickedAsyncAdvancedBasedec
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnClickedAsyncAdvancedBasehex()
{
/*
* Get/Set the SW fields to display in hexadecimal base.
*/
GetSWFields(FALSE);
SetSWFields();
} // end CAdvancedAsyncDlg::OnClickedAsyncAdvancedBasehex
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnOK()
{
/*
* If the Enter key was pressed while a combo box was dropped down, ignore
* it (treat as combo list selection only).
*/
if ( !HandleEnterEscKey(IDOK) )
return;
/*
* Fetch the field contents. Return (don't close dialog) if a problem
* was found.
*/
GetFields();
} // end CAdvancedAsyncDlg::OnOK
//---------------------------------------------------------------------------------------------------
void CAdvancedAsyncDlg::OnCancel()
{
/*
* If the Esc key was pressed while a combo box was dropped down, ignore
* it (treat as combo close-up and cancel only).
*/
HandleEnterEscKey( IDCANCEL );
} // end CAdvancedAsyncDlg::OnCancel
//---------------------------------------------------------------------------------------------------
int CAdvancedAsyncDlg::GetCheckedRadioButton( int nIDFirstButton, int nIDLastButton )
{
for (int nID = nIDFirstButton; nID <= nIDLastButton; nID++)
{
if( IsDlgButtonChecked( m_hDlg , nID ) )
{
return nID; // id that matched
}
}
return 0; // invalid ID
}
//---------------------------------------------------------------------------------------------------
INT_PTR CALLBACK CAdvancedAsyncDlg::DlgProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
{
CAdvancedAsyncDlg *pDlg;
if( msg == WM_INITDIALOG )
{
CAdvancedAsyncDlg *pDlg = ( CAdvancedAsyncDlg * )lp;
SetWindowLongPtr( hwnd , DWLP_USER, ( LONG_PTR )pDlg );
if( !IsBadReadPtr( pDlg , sizeof( CAdvancedAsyncDlg ) ) )
{
pDlg->OnInitDialog( hwnd , wp , lp );
}
return 0;
}
else
{
pDlg = ( CAdvancedAsyncDlg * )GetWindowLongPtr( hwnd , DWLP_USER);
if( IsBadReadPtr( pDlg , sizeof( CAdvancedAsyncDlg ) ) )
{
return 0;
}
}
switch( msg )
{
/*case WM_DESTROY:
pDlg->OnDestroy( );
break;*/
case WM_COMMAND:
pDlg->OnCommand( HIWORD( wp ) , LOWORD( wp ) , ( HWND )lp );
break;
case WM_CONTEXTMENU:
{
POINT pt;
pt.x = LOWORD( lp );
pt.y = HIWORD( lp );
// pDlg->OnContextMenu( ( HWND )wp , pt );
}
break;
case WM_HELP:
// pDlg->OnHelp( hwnd , ( LPHELPINFO )lp );
break;
/*case WM_NOTIFY:
return pDlg->OnNotify( ( int )wp , ( LPNMHDR )lp , hwnd );*/
}
return 0;
}
/***********************************************************************************************************/
//---------------------------------------------------------------------------------------------------
void CEchoEditControl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
UNREFERENCED_PARAMETER( nRepCnt );
UNREFERENCED_PARAMETER( 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 )
{
ODS( L"CEchoEditControl::OnChar -- WM_ASYNCTESTWRITECHAR( S )\n" );
::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'.
*/
}
//---------------------------------------------------------------------------------------------------
void CEchoEditControl::SubclassDlgItem( HWND hDlg , int nRes )
{
HWND hCtrl = GetDlgItem( hDlg , nRes );
ASSERT( hCtrl != NULL );
m_oldproc = ( WNDPROC )SetWindowLongPtr( hCtrl , GWLP_WNDPROC , ( LONG_PTR )CEchoEditControl::WndProc );
SetWindowLongPtr( hCtrl , GWLP_USERDATA , ( LONG_PTR )this );
}
//---------------------------------------------------------------------------------------------------
LRESULT CALLBACK CEchoEditControl::WndProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
{
CEchoEditControl *pEdit = ( CEchoEditControl * )GetWindowLongPtr( hwnd , GWLP_USERDATA );
if( pEdit == NULL )
{
ODS( L"CEchoEditControl static object not set\n" );
return 0;
}
switch( msg )
{
case WM_CHAR:
pEdit->OnChar( ( TCHAR )wp , LOWORD( lp ) , HIWORD( lp ) );
break;
}
if( pEdit->m_oldproc != NULL )
{
return ::CallWindowProc( pEdit->m_oldproc , hwnd , msg ,wp , lp ) ;
}
return DefWindowProc( hwnd , msg ,wp , lp );
}
//---------------------------------------------------------------------------------------------------
CLed::CLed( HBRUSH hBrush )
{
m_hBrush = hBrush;
m_bOn = FALSE;
}
//---------------------------------------------------------------------------------------------------
void CLed::Subclass( HWND hDlg , int nRes )
{
HWND hCtrl = GetDlgItem( hDlg , nRes );
ASSERT( hCtrl != NULL );
m_hWnd = hCtrl;
m_oldproc = ( WNDPROC )SetWindowLongPtr( hCtrl , GWLP_WNDPROC , ( LONG_PTR )CLed::WndProc );
SetWindowLongPtr( hCtrl , GWLP_USERDATA , ( LONG_PTR )this );
}
//---------------------------------------------------------------------------------------------------
void CLed::Update(int nOn)
{
m_bOn = nOn ? TRUE : FALSE;
InvalidateRect( m_hWnd , NULL , FALSE );
UpdateWindow( m_hWnd );
}
//---------------------------------------------------------------------------------------------------
void CLed::Toggle()
{
ODS(L"CLed::Toggle\n");
m_bOn = !m_bOn;
InvalidateRect( m_hWnd , NULL , FALSE );
// UpdateWindow( m_hWnd );
}
void CLed::OnPaint( HWND hwnd )
{
RECT rect;
PAINTSTRUCT ps;
ODS(L"CLed::OnPaint\n");
HDC dc = BeginPaint( hwnd , &ps );
HBRUSH brush;
GetClientRect( hwnd , &rect );
#ifdef USING_3DCONTROLS
(rect.right)--;
(rect.bottom)--;
brush = ( HBRUSH )GetStockObject( GRAY_BRUSH );
FrameRect( dc , &rect, brush );
(rect.top)++;
(rect.left)++;
(rect.right)++;
(rect.bottom)++;
brush = ( HBRUSH )GetStockObject( WHITE_BRUSH );
FrameRect( dc , &rect, brush );
(rect.top)++;
(rect.left)++;
(rect.right) -= 2;
(rect.bottom) -= 2;
#else
brush = ( HBRUSH )GetStockObject( BLACK_BRUSH );
FrameRect( dc , &rect , brush );
(rect.top)++;
(rect.left)++;
(rect.right)--;
(rect.bottom)--;
#endif
DBGMSG( L"led should be %s\n" , m_bOn ? L"red" : L"grey" );
brush = m_bOn ? m_hBrush : ( HBRUSH )GetStockObject( LTGRAY_BRUSH );
FillRect( dc , &rect , brush );
EndPaint( hwnd , &ps );
}
//---------------------------------------------------------------------------------------------------
LRESULT CALLBACK CLed::WndProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
{
CLed *pWnd = ( CLed * )GetWindowLongPtr( hwnd , GWLP_USERDATA );
if( pWnd == NULL )
{
ODS( L"CLed is not available\n" );
return 0;
}
switch( msg )
{
case WM_PAINT:
pWnd->OnPaint( hwnd );
break;
}
if( pWnd->m_oldproc != NULL )
{
return ::CallWindowProc( pWnd->m_oldproc , hwnd , msg ,wp , lp ) ;
}
return DefWindowProc( hwnd , msg ,wp , lp );
}
//---------------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
// CThread class construction / destruction, implementation
/*******************************************************************************
*
* CThread - CThread constructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CThread::CThread()
{
m_hThread = NULL;
m_dwThreadID = 0;
} // end CThread::CThread
/*******************************************************************************
*
* ~CThread - CThread destructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CThread::~CThread()
{
} // end CThread::~CThread
////////////////////////////////////////////////////////////////////////////////
// CThread operations: primary thread
/*******************************************************************************
*
* CreateThread - CThread implementation function
*
* Class wrapper for the Win32 CreateThread API.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
HANDLE CThread::CreateThread( DWORD cbStack , DWORD fdwCreate )
{
/*
* Simple wrapper for Win32 CreateThread API.
*/
return( m_hThread = ::CreateThread( NULL, cbStack, ThreadEntryPoint , ( LPVOID ) this, fdwCreate, &m_dwThreadID ) );
} // end CThread::CreateThread
////////////////////////////////////////////////////////////////////////////////
// CThread operations: secondary thread
/*******************************************************************************
*
* ThreadEntryPoint - CThread implementation function
* (SECONDARY THREAD)
*
* ENTRY:
* EXIT:
*
******************************************************************************/
DWORD __stdcall CThread::ThreadEntryPoint( LPVOID lpParam )
{
CThread *pThread;
DWORD dwResult = ( DWORD )-1;
/*
* (lpParam is actually the 'this' pointer)
*/
pThread = (CThread*)lpParam;
/*
* Run the thread.
*/
if( pThread != NULL )
{
dwResult = pThread->RunThread();
}
/*
* Return the result.
*/
return(dwResult);
} // end CThread::ThreadEntryPoint
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// CATDlgInputThread class construction / destruction, implementation
/*******************************************************************************
*
* CATDlgInputThread - CATDlgInputThread constructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CATDlgInputThread::CATDlgInputThread()
{
/*
* Initialize member variables.
*/
m_bExit = FALSE;
m_ErrorStatus = ERROR_SUCCESS;
m_hConsumed = NULL;
ZeroMemory( &m_OverlapSignal , sizeof( OVERLAPPED ) );
ZeroMemory( &m_OverlapRead , sizeof( OVERLAPPED ) );
//m_OverlapSignal.hEvent = NULL;
//m_OverlapRead.hEvent = NULL;
m_BufferBytes = 0;
} // end CATDlgInputThread::CATDlgInputThread
/*******************************************************************************
*
* ~CATDlgInputThread - CATDlgInputThread destructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CATDlgInputThread::~CATDlgInputThread()
{
/*
* Close the semaphore and events when the CATDlgInputThread
* object is destroyed.
*/
if ( m_hConsumed )
CloseHandle(m_hConsumed);
if ( m_OverlapRead.hEvent )
CloseHandle(m_OverlapRead.hEvent);
if ( m_OverlapSignal.hEvent )
CloseHandle(m_OverlapSignal.hEvent);
} // end CATDlgInputThread::~CATDlgInputThread
/*******************************************************************************
*
* RunThread - CATDlgInputThread secondary thread main function loop
* (SECONDARY THREAD)
*
* ENTRY:
* EXIT:
* (DWORD) exit status for the secondary thread.
*
******************************************************************************/
DWORD
CATDlgInputThread::RunThread()
{
HANDLE hWait[2];
DWORD Status;
int iStat;
/*
* Initialize for overlapped status and read input.
*/
m_hConsumed = CreateSemaphore( NULL , 0 , MAX_STATUS_SEMAPHORE_COUNT , NULL );
m_OverlapRead.hEvent = CreateEvent( NULL , TRUE , FALSE , NULL );
m_OverlapSignal.hEvent = CreateEvent( NULL , TRUE , FALSE , NULL );
if ( m_hConsumed == NULL || m_OverlapRead.hEvent == NULL || m_OverlapSignal.hEvent == NULL ||
!SetCommMask( m_hDevice , EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_BREAK ) )
{
NotifyAbort(IDP_ERROR_CANT_INITIALIZE_INPUT_THREAD);
return(1);
}
/*
* Query initial comm status to initialize dialog with (return if error).
*/
if ( (iStat = CommStatusAndNotify()) != -1 )
return(iStat);
/*
* Post Read for input data.
*/
if ( (iStat = PostInputRead()) != -1 )
return(iStat);
/*
* Post Read for status.
*/
if ( (iStat = PostStatusRead()) != -1 )
return(iStat);
/*
* Loop till exit requested.
*/
for ( ; ; ) {
/*
* Wait for either input data or an comm status event.
*/
hWait[0] = m_OverlapRead.hEvent;
hWait[1] = m_OverlapSignal.hEvent;
ODS( L"CATDlgInputThread::RunThread waiting on either event to be signaled\n");
Status = WaitForMultipleObjects(2, hWait, FALSE, INFINITE);
/*
* Check for exit.
*/
if ( m_bExit )
{
ODS( L"CATDlgInputThread::RunThread exiting\n" );
return(0);
}
if ( Status == WAIT_OBJECT_0 ) {
/*
* Read event:
* Get result of overlapped read.
*/
ODS(L"CATDlgInputThread::RunThread Read event signaled\n" );
if ( !GetOverlappedResult( m_hDevice,
&m_OverlapRead,
&m_BufferBytes,
TRUE ) ) {
NotifyAbort(IDP_ERROR_GET_OVERLAPPED_RESULT_READ);
return(1);
}
/*
* Notify dialog.
*/
if ( (iStat = CommInputNotify()) != -1 )
return(iStat);
/*
* Post Read for input data.
*/
if ( (iStat = PostInputRead()) != -1 )
return(iStat);
} else if ( Status == WAIT_OBJECT_0+1 ) {
ODS(L"CATDlgInputThread::RunThread Signal event signaled\n" );
/*
* Comm status event:
* Query comm status and notify dialog.
*/
if ( (iStat = CommStatusAndNotify()) != -1 )
return(iStat);
/*
* Post Read for status.
*/
if ( (iStat = PostStatusRead()) != -1 )
return(iStat);
} else {
/*
* Unknown event: Abort.
*/
NotifyAbort(IDP_ERROR_WAIT_FOR_MULTIPLE_OBJECTS);
return(1);
}
}
} // end CATDlgInputThread::RunThread
////////////////////////////////////////////////////////////////////////////////
// CATDlgInputThread operations: primary thread
/*******************************************************************************
*
* SignalConsumed - CATDlgInputThread member function: public operation
*
* Release the m_hConsumed semaphore to allow secondary thread to continue
* running.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CATDlgInputThread::SignalConsumed()
{
ReleaseSemaphore( m_hConsumed, 1, NULL );
} // end CATDlgInputThread::SignalConsumed
/*******************************************************************************
*
* ExitThread - CATDlgInputThread member function: public operation
*
* Tell the secondary thread to exit and cleanup after.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CATDlgInputThread::ExitThread()
{
DWORD dwReturnCode;
int i;
// CWaitCursor wait;
/*
* If the thread was not created properly, just delete object and return.
*/
if ( !m_hThread ) {
delete this;
return;
}
/*
* Set the m_bExit flag to TRUE, wake up the run thread's WaitCommEvent() by
* resetting device's Comm mask, and bump the consumed semaphore to assure exit.
*/
m_bExit = TRUE;
SetCommMask(m_hDevice, 0);
SignalConsumed();
/*
* Purge the recieve buffer and any pending read.
*/
PurgeComm(m_hDevice, PURGE_RXABORT | PURGE_RXCLEAR);
/*
* Wait a while for the thread to exit.
*/
for ( i = 0, GetExitCodeThread( m_hThread, &dwReturnCode );
(i < MAX_SLEEP_COUNT) && (dwReturnCode == STILL_ACTIVE); i++ ) {
Sleep(100);
GetExitCodeThread( m_hThread, &dwReturnCode );
}
/*
* If the thread has still not exited, terminate it.
*/
if( dwReturnCode == STILL_ACTIVE )
{
TerminateThread( m_hThread, 1 );
ODS( L"Thread terminated irregularly\n" );
}
/*
* Close the thread handle and delete this CATDlgInputThread object
*/
CloseHandle( m_hThread );
delete this;
} // end CATDlgInputThread::ExitThread
////////////////////////////////////////////////////////////////////////////////
// CATDlgInputThread operations: secondary thread
/*******************************************************************************
*
* NotifyAbort - CATDlgInputThread member function: private operation
* (SECONDARY THREAD)
*
* Notify the dialog of thread abort and reason.
*
* ENTRY:
* idError (input)
* Resource id for error message.
* EXIT:
*
******************************************************************************/
void
CATDlgInputThread::NotifyAbort(UINT idError )
{
TCHAR tchErrTitle[ 80 ];
TCHAR tchErrMsg[ 256 ];
//::PostMessage(m_hDlg, WM_ASYNCTESTABORT, idError, GetLastError());
LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , SIZE_OF_BUFFER( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , idError , tchErrMsg , SIZE_OF_BUFFER( tchErrMsg ) );
MessageBox( m_hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );
} // end CATDlgInputThread::NotifyAbort
/*******************************************************************************
*
* CommInputNotify - CATDlgInputThread member function: private operation
* (SECONDARY THREAD)
*
* Notify the dialog of comm input.
*
* ENTRY:
* EXIT:
* -1 no error and continue thread
* 0 if ExitThread was requested by parent
*
******************************************************************************/
int
CATDlgInputThread::CommInputNotify()
{
/*
* Tell the dialog that we've got some new input.
*/
::PostMessage(m_hDlg, WM_ASYNCTESTINPUTREADY, 0, 0);
ODS( L"TSCC:CATDlgInputThread::CommInputNotify WM_ASYNCTESTINPUTREADY (P)\n" );
ODS( L"TSCC:CATDlgInputThread::CommInputNotify waiting on semaphore\n" );
WaitForSingleObject(m_hConsumed, INFINITE);
ODS( L"TSCC:CATDlgInputThread::CommInputNotify semaphore signaled\n" );
/*
* Check for thread exit request.
*/
if ( m_bExit )
return(0);
else
return(-1);
} // end CATDlgInputThread::CommInputNotify
/*******************************************************************************
*
* CommStatusAndNotify - CATDlgInputThread member function: private operation
* (SECONDARY THREAD)
*
* Read the comm port status and notify dialog.
*
* ENTRY:
* EXIT:
* -1 no error and continue thread
* 0 if ExitThread was requested by parent
* 1 error condition
*
******************************************************************************/
int
CATDlgInputThread::CommStatusAndNotify()
{
PFLOWCONTROLCONFIG pFlow = NULL;
DWORD ModemStatus = 0;
DWORD Error = 0;
if ( !GetCommModemStatus(m_hDevice, &ModemStatus) ) {
/*
* We can't query the comm information; tell the primary thread
* that we've aborted, and return error (will exit thread).
*/
NotifyAbort(IDP_ERROR_GET_COMM_MODEM_STATUS);
return(1);
}
/*
* Update modem status
*/
m_Status.AsyncSignal = ModemStatus;
/*
* Or in status of DTR and RTS
*/
// pFlow = &m_PdConfig.Params.Async.FlowControl;
pFlow = &m_ac.FlowControl;
if ( pFlow->fEnableDTR )
m_Status.AsyncSignal |= MS_DTR_ON;
if ( pFlow->fEnableRTS )
m_Status.AsyncSignal |= MS_RTS_ON;
/*
* OR in new event mask
*/
m_Status.AsyncSignalMask |= m_EventMask;
/*
* Update async error counters
*/
if ( m_EventMask & EV_ERR ) {
(VOID) ClearCommError( m_hDevice, &Error, NULL );
if ( Error & CE_OVERRUN )
m_Status.Output.AsyncOverrunError++;
if ( Error & CE_FRAME )
m_Status.Input.AsyncFramingError++;
if ( Error & CE_RXOVER )
m_Status.Input.AsyncOverflowError++;
if ( Error & CE_RXPARITY )
m_Status.Input.AsyncParityError++;
}
/*
* Tell the dialog that we've got some new status information.
*/
::PostMessage(m_hDlg, WM_ASYNCTESTSTATUSREADY, 0, 0);
ODS( L"TSCC:CATDlgInputThread::CommStatusAndNotify WM_ASYNCTESTSTATUSREADY( P )\n");
ODS( L"TSCC:CATDlgInputThread::CommStatusAndNotify waiting on semaphore\n" );
WaitForSingleObject(m_hConsumed, INFINITE);
ODS( L"TSCC:CATDlgInputThread::CommStatusAndNotify semaphore signaled\n" );
/*
* Check for thread exit request.
*/
if ( m_bExit )
return(0);
else
return(-1);
} // end CATDlgInputThread::CommStatusAndNotify
/*******************************************************************************
*
* PostInputRead - CATDlgInputThread member function: private operation
* (SECONDARY THREAD)
*
* Post a ReadFile operation for the device, processing as long as data
* is present.
*
* ENTRY:
* EXIT:
* -1 if read operation posted sucessfully
* 0 if ExitThread was requested by parent
* 1 if error condition
*
******************************************************************************/
int
CATDlgInputThread::PostInputRead()
{
int iStat;
// TCHAR tchErrTitle[ 80 ];
// TCHAR tchErrMsg[ 256 ];
ODS(L"TSCC:CATDlgInputThread::PostInputRead\n");
/*
* Post read for input data, processing immediataly if not 'pending'.
*/
while ( ReadFile( m_hDevice, m_Buffer, MAX_COMMAND_LEN,
&m_BufferBytes, &m_OverlapRead ) )
{
DBGMSG( L"Buffer received %s\n",m_Buffer );
if ( (iStat = CommInputNotify()) != -1 )
return(iStat);
}
/*
* Make sure read is pending (not some other error).
*/
if ( GetLastError() != ERROR_IO_PENDING )
{
DBGMSG( L"ReadFile returned 0x%x\n" , GetLastError() );
NotifyAbort(IDP_ERROR_READ_FILE);
/* LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , sizeof( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , IDP_ERROR_READ_FILE , tchErrMsg , sizeof( tchErrMsg ) );
MessageBox( m_hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );*/
EndDialog(m_hDlg, IDCANCEL);
return(1);
}
/*
* Return 'posted sucessfully' status.
*/
return(-1);
} // end CATDlgInputThread::PostInputRead
/*******************************************************************************
*
* PostStatusRead - CATDlgInputThread member function: private operation
* (SECONDARY THREAD)
*
* Post a WaitCommStatus operation for the device.
*
* ENTRY:
* EXIT:
* -1 if status operation posted sucessfully
* 1 if error condition
*
******************************************************************************/
int
CATDlgInputThread::PostStatusRead()
{
/*
* Post read for comm status.
*/
ODS( L"CATDlgInputThread::PostStatusRead\n");
if ( !WaitCommEvent(m_hDevice, &m_EventMask, &m_OverlapSignal) ) {
/*
* Make sure comm status read is pending (not some other error).
*/
if ( GetLastError() != ERROR_IO_PENDING ) {
NotifyAbort(IDP_ERROR_WAIT_COMM_EVENT);
return(1);
}
}
/*
* Return 'posted sucessfully' status.
*/
return(-1);
} // end CATDlgInputThread::PostStatusRead
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg class construction / destruction, implementation
/*******************************************************************************
*
* CAsyncTestDlg - CAsyncTestDlg constructor
*
* ENTRY:
* EXIT:
* (Refer to MFC CDialog::CDialog documentation)
*
******************************************************************************/
CAsyncTestDlg::CAsyncTestDlg(ICfgComp * pCfgComp) :
m_hDevice(INVALID_HANDLE_VALUE),
m_hRedBrush(NULL),
m_LEDToggleTimer(0),
m_pATDlgInputThread(NULL),
m_CurrentPos(0),
m_hModem(NULL),
m_bDeletedWinStation(FALSE)
{
/*
* Create a solid RED brush for painting the 'LED's when 'on'.
*/
m_hRedBrush = CreateSolidBrush( RGB( 255 , 0 , 0 ) );
/*
* Initialize member variables.
*/
FillMemory( &m_Status , sizeof( PROTOCOLSTATUS ) , 0 );
FillMemory( &m_OverlapWrite , sizeof( OVERLAPPED ) , 0 );
/*
* Create the led objects.
*/
for( int i = 0 ; i < NUM_LEDS ; i++ )
{
m_pLeds[i] = new CLed(m_hRedBrush);
}
m_pCfgComp = pCfgComp;
if( pCfgComp != NULL )
{
m_pCfgComp->AddRef();
}
} // end CAsyncTestDlg::CAsyncTestDlg
/*******************************************************************************
*
* ~CAsyncTestDlg - CAsyncTestDlg destructor
*
* ENTRY:
* EXIT:
* (Refer to MFC CDialog::~CDialog documentation)
*
******************************************************************************/
CAsyncTestDlg::~CAsyncTestDlg()
{
/*
* Zap our led objects.
*/
for( int i = 0; i < NUM_LEDS; i++ )
{
if( m_pLeds[i] != NULL )
{
delete m_pLeds[i];
}
}
if(m_pCfgComp != NULL )
{
m_pCfgComp->Release();
}
} // 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 )
{
TCHAR tchErrTitle[ 80 ];
TCHAR tchErrMsg[ 256 ];
LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , SIZE_OF_BUFFER( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , idError , tchErrMsg , SIZE_OF_BUFFER( tchErrMsg ) );
MessageBox( m_hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );
} // 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;
pAsync = &m_ac;
/*
* 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;
}
/*
* 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
*/
ODS( L"TSCC:CAsyncTestDlg::DeviceWrite Writing out to buffer\n" );
if ( !WriteFile( m_hDevice, m_Buffer, m_BufferBytes,
&BytesWritten, &m_OverlapWrite ) )
{
DBGMSG( L"TSCC:CAsyncTestDlg::DeviceWrite WriteFile returned 0x%x\n" , GetLastError() );
if ( (Error = GetLastError()) == ERROR_IO_PENDING )
{
/*
* Wait for write to complete (this may block till timeout)
*/
if ( !GetOverlappedResult( m_hDevice, &m_OverlapWrite,
&BytesWritten, TRUE ) )
{
CancelIo( m_hDevice );
NotifyAbort(IDP_ERROR_GET_OVERLAPPED_RESULT_WRITE);
return(FALSE);
}
} else {
NotifyAbort(IDP_ERROR_WRITE_FILE);
return(FALSE);
}
}
return(TRUE);
} // end CAsyncTestDlg::DeviceWrite
//---------------------------------------------------------------------
cwnd * CAsyncTestDlg::GetDlgItem( int nRes )
{
HWND hCtrl = ::GetDlgItem( m_hDlg , nRes );
for( int i = 0; i < NUM_LEDS; i++ )
{
if( m_pLeds[ i ] != NULL )
{
if( m_pLeds[ i ]->m_hWnd == hCtrl )
{
return m_pLeds[ i ];
}
}
}
return 0;
}
/*******************************************************************************
*
* 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( m_hDlg , IDD_ASYNC_TEST , ASYNC_LED_TOGGLE_MSEC, NULL );
}
} // end CAsyncTestDlg::SetInfoFields
////////////////////////////////////////////////////////////////////////////////
// CAsyncTestDlg message map
BOOL CAsyncTestDlg::OnCommand( WORD wNotifyCode , WORD wID , HWND hwndCtrl )
{
if( wNotifyCode == BN_CLICKED )
{
if( wID == IDC_ATDLG_MODEM_DIAL )
{
OnClickedAtdlgModemDial( );
}
else if( wID == IDC_ATDLG_MODEM_INIT )
{
OnClickedAtdlgModemInit( );
}
else if( wID == IDC_ATDLG_MODEM_LISTEN )
{
OnClickedAtdlgModemListen( );
}
else if( wID == IDOK )
{
EndDialog( m_hDlg , IDOK );
}
else if( wID == IDCANCEL )
{
EndDialog( m_hDlg , IDCANCEL );
}
else if( wID == ID_HELP )
{
TCHAR tchHelpFile[ MAX_PATH ];
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_ASYNC_HELPFILE , tchHelpFile , SIZE_OF_BUFFER( tchHelpFile ) ) );
WinHelp( GetParent( hwndCtrl ) , tchHelpFile , HELP_CONTEXT , HID_ASYNCTEST );
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
// 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( HWND hDlg , WPARAM wp , LPARAM lp )
{
UNREFERENCED_PARAMETER( wp );
UNREFERENCED_PARAMETER( lp );
int i;
DEVICENAME DeviceName;
COMMTIMEOUTS CommTimeouts;
TCHAR tchErrTitle[ 80 ];
TCHAR tchErrMsg[ 256 ];
m_hDlg = hDlg;
//#ifdef WINSTA
ULONG LogonId;
//#endif // WINSTA
/*
* Fill in the device and baud fields.
*/
SetDlgItemText( hDlg , IDL_ATDLG_DEVICE , m_ac.DeviceName );
SetDlgItemInt( hDlg , IDL_ATDLG_BAUD , m_ac.BaudRate , FALSE );
/*
* If a WinStation memory object is currently present, reset it.
*/
//#ifdef WINSTA
if ( m_pWSName != NULL ) //&& LogonIdFromWinStationName( SERVERNAME_CURRENT , m_pWSName , &LogonId ) )
{
LONG Status;
ULONG Length;
LONG lCount = 0;
TCHAR tchbuf[ 256 ];
if( m_pCfgComp != NULL )
{
ODS( L"TSCC : Testing for live connections\n" );
m_pCfgComp->QueryLoggedOnCount( m_pWSName,&lCount);
if( lCount )
{
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_WRN_TSTCON , tchbuf , SIZE_OF_BUFFER( tchbuf ) ) );
wsprintf( tchErrMsg , tchbuf , m_pWSName);
VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_WARN_TITLE , tchErrTitle , SIZE_OF_BUFFER( tchErrTitle ) ) );
if( MessageBox( hDlg , tchbuf , tchErrTitle , MB_YESNO | MB_ICONEXCLAMATION ) == IDNO )
{
PostMessage( hDlg , WM_COMMAND , MAKEWPARAM( IDOK, BN_CLICKED ) , (LPARAM)(::GetDlgItem( hDlg , IDOK ) ) );
return(TRUE); // exit dialog via posted 'OK' click
}
}
}
Status = RegWinStationQuery( SERVERNAME_CURRENT,
m_pWSName,
&m_WSConfig,
sizeof(WINSTATIONCONFIG2),
&Length );
if(Status)
{
NotifyAbort(IDP_ERROR_DISABLE);
return(TRUE);
}
m_WSConfig.Create.fEnableWinStation = FALSE;
Status = RegWinStationCreate( SERVERNAME_CURRENT,
m_pWSName,
FALSE,
&m_WSConfig,
sizeof(WINSTATIONCONFIG2 ) ) ;
if(Status)
{
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;
if( LogonIdFromWinStationName( SERVERNAME_CURRENT , m_pWSName , &LogonId ) )
{
BOOL b = ( BOOL )WinStationReset(SERVERNAME_CURRENT, LogonId, TRUE);
DBGMSG( L"TSCC:CAsyncTestDlg::OnInitDialog WinStationReset returned %s\n", b ? L"TRUE" : L"FALSE" );
//m_bDeletedWinStation = TRUE;
}
m_bDeletedWinStation = TRUE;
}
//#endif // WINSTA
/*
* Open the specified device.
*/
lstrcpy( DeviceName, TEXT("\\\\.\\") );
// lstrcat( DeviceName, m_PdConfig0.Params.Async.DeviceName );
lstrcat( DeviceName, m_ac.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);
/* LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , sizeof( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , IDP_ERROR_CANT_OPEN_DEVICE , tchErrMsg , sizeof( tchErrMsg ) );
MessageBox( hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );*/
return(FALSE);
}
/*
* Set device timeouts & communication parameters and create an event
* for overlapped writes.
*/
FillMemory( &CommTimeouts , sizeof( COMMTIMEOUTS ) , 0 );
CommTimeouts.ReadIntervalTimeout = 1; // 1 msec
CommTimeouts.WriteTotalTimeoutConstant = 1000; // 1 second
m_OverlapWrite.hEvent = CreateEvent( NULL , TRUE , FALSE, NULL );
if( !SetCommTimeouts(m_hDevice, &CommTimeouts) || !DeviceSetParams() || m_OverlapWrite.hEvent == NULL )
{
NotifyAbort(IDP_ERROR_CANT_INITIALIZE_DEVICE);
ODS( L"IDP_ERROR_CANT_INITIALIZE_DEVICE\n" );
/* LoadString( _Module.GetResourceInstance( ) , IDS_ERROR_TITLE , tchErrTitle , sizeof( tchErrTitle ) );
LoadString( _Module.GetResourceInstance( ) , IDP_ERROR_CANT_INITIALIZE_DEVICE , tchErrMsg , sizeof( tchErrMsg ) );
MessageBox( hDlg , tchErrMsg , tchErrTitle , MB_OK | MB_ICONERROR );*/
return(TRUE);
}
/*
* Create the input thread object and initialize it's member variables.
*/
m_pATDlgInputThread = new CATDlgInputThread;
m_pATDlgInputThread->m_hDlg = m_hDlg;
m_pATDlgInputThread->m_hDevice = m_hDevice;
// m_pATDlgInputThread->m_PdConfig = m_PdConfig0;
m_pATDlgInputThread->m_ac = m_ac;
if( !m_pATDlgInputThread->CreateThread() )
{
NotifyAbort(IDP_ERROR_CANT_CREATE_INPUT_THREAD);
ODS( L"IDP_ERROR_CANT_CREATE_INPUT_THREAD\n" );
return(TRUE);
}
/*
* Hide the modem string buttons if a modem is not configured, or disable
* buttons that are not valid.
*/
for( int id = IDC_ATDLG_MODEM_INIT ; id <= IDC_ATDLG_PHONE_NUMBER ; id++ )
{
EnableWindow( ::GetDlgItem( hDlg , id) , FALSE);
ShowWindow( ::GetDlgItem( hDlg , id) , SW_HIDE);
}
/*
* Subclass the edit field to pass messages to dialog first.
*/
m_EditControl.m_hDlg = m_hDlg;
m_EditControl.m_bProcessingOutput = FALSE;
m_EditControl.SubclassDlgItem( hDlg , IDC_ATDLG_EDIT );
/*
* Determine the edit control's font and format offset metrics.
*/
TEXTMETRIC tm;
RECT Rect;
HDC dc;
HFONT hFont , hOldFont;
dc = GetDC( m_EditControl.m_hWnd );
hFont = ( HFONT )SendMessage( m_EditControl.m_hWnd , WM_GETFONT , 0 , 0 );
hOldFont = ( HFONT )SelectObject( dc , hFont);
GetTextMetrics( dc , &tm );
SelectObject( dc , hOldFont);
ReleaseDC( m_EditControl.m_hWnd , dc );
m_EditControl.m_FontHeight = tm.tmHeight;
m_EditControl.m_FontWidth = tm.tmMaxCharWidth;
SendMessage( m_EditControl.m_hWnd , EM_GETRECT , 0 , ( LPARAM )&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( hDlg , 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.
*/
ODS( L"TSCC:CAsyncTestDlg::OnTimer \n" );
if( nIDEvent == m_LEDToggleTimer )
{
ODS( L"TSCC:CAsyncTestDlg::OnTimer hit event\n" );
/*
* Toggle each LED that is flagged as 'changed'.
*/
ODS( L"TSCC:led toggle " );
if( m_Status.AsyncSignalMask & EV_DTR )
{
ODS( L"dtr\n");
( ( CLed * )GetDlgItem( IDC_ATDLG_DTR ) )->Toggle();
}
if( m_Status.AsyncSignalMask & EV_RTS )
{
ODS(L"rts\n");
( ( CLed * )GetDlgItem( IDC_ATDLG_RTS ) )->Toggle();
}
if( m_Status.AsyncSignalMask & EV_CTS )
{
ODS(L"cts\n");
( ( CLed * )GetDlgItem( IDC_ATDLG_CTS ) )->Toggle();
}
if( m_Status.AsyncSignalMask & EV_RLSD )
{
ODS(L"rlsd\n");
( ( CLed * )GetDlgItem( IDC_ATDLG_DCD ) )->Toggle();
}
if( m_Status.AsyncSignalMask & EV_DSR )
{
ODS(L"dsr\n");
( ( CLed * )GetDlgItem( IDC_ATDLG_DSR ) )->Toggle();
}
if( m_Status.AsyncSignalMask & EV_RING )
{
ODS(L"ring\n" );
( ( CLed * )GetDlgItem( IDC_ATDLG_RI ) )->Toggle();
}
/*
* Kill this timer event and indicate so.
*/
KillTimer( m_hDlg , m_LEDToggleTimer );
m_LEDToggleTimer = 0;
}
} // 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.
*
******************************************************************************/
/*#define STANDARD_ERROR_MESSAGE(x) { if ( 1 ) StandardErrorMessage x ; }
LRESULT
CAsyncTestDlg::OnAsyncTestError( WPARAM wParam, LPARAM lParam )
{
/*
* Handle special and default errors.
*/
/*switch ( wParam )
{
case IDP_ERROR_MODEM_SET_INFO:
case IDP_ERROR_MODEM_GET_DIAL:
case IDP_ERROR_MODEM_GET_INIT:
case IDP_ERROR_MODEM_GET_LISTEN:
break;
case IDP_ERROR_DISABLE:
StandardErrorMessage( L"Test", (HWND)LOGONID_NONE, (HINSTANCE)lParam,
wParam, (UINT)m_pWSName,0 );
break;
default:
StandardErrorMessage( L"Test",(HWND) LOGONID_NONE, (HINSTANCE)lParam, (UINT)wParam, lParam,0);
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 )
{
UNREFERENCED_PARAMETER( lParam );
/*
* Call OnAsyncTestError() to output message.
*/
//OnAsyncTestError(wParam, lParam);
NotifyAbort((UINT)wParam);
/*
* Post a click for 'OK' (Exit) button to exit dialog.
*/
PostMessage( m_hDlg , WM_COMMAND , MAKEWPARAM( IDOK, BN_CLICKED ) , (LPARAM)::GetDlgItem( m_hDlg , IDOK ) );
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 )
{
UNREFERENCED_PARAMETER( wParam );
UNREFERENCED_PARAMETER( 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 )
{
UNREFERENCED_PARAMETER( wParam );
UNREFERENCED_PARAMETER( lParam );
BYTE OutBuf[MAX_COMMAND_LEN+2];
int i, j;
/*
* Copy the thread's buffer and count locally.
*/
m_BufferBytes = m_pATDlgInputThread->m_BufferBytes;
CopyMemory( 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.
*/
SendMessage( m_EditControl.m_hWnd , EM_SETSEL , m_CurrentPos , m_CurrentPos );
SendMessage( m_EditControl.m_hWnd , EM_SETREADONLY , ( WPARAM )FALSE , 0 );
SendMessage( m_EditControl.m_hWnd , WM_SETREDRAW , ( WPARAM )FALSE , 0 );
/*
* 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;
}
/*
* 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).
*/
SendMessage( m_EditControl.m_hWnd , EM_SETREADONLY , ( WPARAM )TRUE , 0 );
SendMessage( m_EditControl.m_hWnd , WM_SETREDRAW , ( WPARAM )TRUE , 0 );
ValidateRect( m_EditControl.m_hWnd , 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_PTR CurrentLine = SendMessage( m_EditControl.m_hWnd , EM_LINEFROMCHAR , ( WPARAM )m_CurrentPos , 0 );
INT_PTR FirstVisibleLine = SendMessage( m_EditControl.m_hWnd , EM_GETFIRSTVISIBLELINE , 0 , 0 );
INT_PTR CurrentLineIndex = SendMessage( m_EditControl.m_hWnd , EM_LINEINDEX , ( WPARAM )CurrentLine , 0 );
/*
* Calculate clip rectangle.
*/
Rect.top = ( ( int )( CurrentLine - FirstVisibleLine ) * m_EditControl.m_FontHeight )
+ m_EditControl.m_FormatOffsetY;
Rect.bottom = Rect.top + m_EditControl.m_FontHeight;
Rect.left = m_EditControl.m_FormatOffsetX +( ( int )( 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.
*/
SendMessage( m_EditControl.m_hWnd , EM_SETSEL , m_CurrentPos - 1 , m_CurrentPos );
/*
* Cut the character out of the edit buffer.
*/
m_EditControl.m_bProcessingOutput = TRUE;
SendMessage( m_EditControl.m_hWnd , WM_CUT , 0 , 0 );
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;
SendMessage( m_EditControl.m_hWnd , EM_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_CurrentPos = GetWindowTextLength( m_EditControl.m_hWnd );
SendMessage( m_EditControl.m_hWnd , EM_SETSEL , m_CurrentPos , -1 );
/*
* Cause '\r' '\n' pair to be output to edit buffer.
*/
pBuffer[0] = '\r';
pBuffer[1] = '\n';
*pIndex = 2;
/*
* See if scrolling needed.
*/
GetClientRect( m_EditControl.m_hWnd , &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.
*/
SendMessage( m_EditControl.m_hWnd , EM_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');
SendMessage( m_EditControl.m_hWnd , EM_REPLACESEL , ( WPARAM )FALSE , ( LPARAM )OutBuffer );
#else
pBuffer[*pIndex] = BYTE('\0');
SendMessage( m_EditControl.m_hWnd , EM_REPLACESEL , ( WPARAM )FALSE , ( LPARAM )pBuffer );
#endif // UNICODE
}
/*
* Update the current line.
*/
SendMessage( m_EditControl.m_hWnd , WM_SETREDRAW , ( WPARAM )TRUE , 0 );
ValidateRect( m_EditControl.m_hWnd , NULL );
InvalidateRect( m_EditControl.m_hWnd , &Rect , FALSE );
UpdateWindow( m_EditControl.m_hWnd );
/*
* If scrolling is required to see the new line, do so.
*/
if( bScroll )
{
SendMessage( m_EditControl.m_hWnd , EM_LINESCROLL , 0 , 1 );
}
SendMessage( m_EditControl.m_hWnd , WM_SETREDRAW , ( WPARAM )FALSE , 0 );
/*
* 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 )
{
UNREFERENCED_PARAMETER( wParam );
UNREFERENCED_PARAMETER( 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()
{
} // end CAsyncTestDlg::OnClickedAtdlgModemDial
/*******************************************************************************
*
* OnClickedAtdlgModemInit - CAsyncTestDlg member function: command
*
* Send the modem init string.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void CAsyncTestDlg::OnClickedAtdlgModemInit()
{
} // 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_hDlg , m_LEDToggleTimer );
}
if( m_pATDlgInputThread )
{
m_pATDlgInputThread->ExitThread();
}
if( m_hDevice != INVALID_HANDLE_VALUE )
{
PurgeComm(m_hDevice, PURGE_TXABORT | PURGE_TXCLEAR);
}
if( m_OverlapWrite.hEvent != NULL )
{
CloseHandle(m_OverlapWrite.hEvent);
}
if( m_hDevice != INVALID_HANDLE_VALUE )
{
CloseHandle(m_hDevice);
}
if( m_bDeletedWinStation && m_pWSName )
{
m_WSConfig.Create.fEnableWinStation = TRUE;
if( RegWinStationCreate( SERVERNAME_CURRENT , m_pWSName , FALSE , &m_WSConfig , sizeof(WINSTATIONCONFIG2) ) != ERROR_SUCCESS )
{
_WinStationReadRegistry(SERVERNAME_CURRENT);
}
}
DeleteObject(m_hRedBrush);
} // end CAsyncTestDlg::OnNcDestroy
////////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK CAsyncTestDlg::DlgProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
{
CAsyncTestDlg *pDlg;
if( msg == WM_INITDIALOG )
{
CAsyncTestDlg *pDlg = ( CAsyncTestDlg * )lp;
SetWindowLongPtr( hwnd , DWLP_USER, ( LONG_PTR )pDlg );
if( !IsBadReadPtr( pDlg , sizeof( CAsyncTestDlg ) ) )
{
if(FALSE == pDlg->OnInitDialog( hwnd , wp , lp ))
PostMessage(hwnd,WM_CLOSE,0,0);
}
return 0;
}
else
{
pDlg = ( CAsyncTestDlg * )GetWindowLongPtr( hwnd , DWLP_USER);
if( IsBadReadPtr( pDlg , sizeof( CAsyncTestDlg ) ) )
{
return 0;
}
}
switch( msg )
{
case WM_NCDESTROY:
pDlg->OnNcDestroy( );
break;
case WM_COMMAND:
pDlg->OnCommand( HIWORD( wp ) , LOWORD( wp ) , ( HWND )lp );
break;
case WM_TIMER:
pDlg->OnTimer( ( UINT )wp );
break;
case WM_ASYNCTESTERROR:
ODS(L"TSCC:CAsyncTestDlg WM_ASYNCTESTERROR (R)\n" );
pDlg->NotifyAbort((UINT)wp);
break;
case WM_ASYNCTESTABORT:
ODS(L"TSCC:CAsyncTestDlg WM_ASYNCTESTABORT (R)\n" );
pDlg->OnAsyncTestAbort( wp , lp );
break;
case WM_ASYNCTESTSTATUSREADY:
ODS(L"TSCC:CAsyncTestDlg WM_ASYNCTESTSTATUSREADY (R)\n" );
pDlg->OnAsyncTestStatusReady( wp , lp );
break;
case WM_ASYNCTESTINPUTREADY:
ODS(L"TSCC:CAsyncTestDlg WM_ASYNCTESTINPUTREADY (R)\n" );
pDlg->OnAsyncTestInputReady( wp , lp );
break;
case WM_ASYNCTESTWRITECHAR:
ODS(L"TSCC:CAsyncTestDlg WM_ASYNCTESTWRITECHAR (R)\n" );
pDlg->OnAsyncTestWriteChar( wp , lp );
break;
}
return 0;
}