mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1963 lines
60 KiB
1963 lines
60 KiB
/** FILE: ports.c ********** Module Header ********************************
|
|
*
|
|
* Control panel applet for configuring COM ports. This file contains
|
|
* the dialog and utility functions for managing the UI for setting COM
|
|
* port parameters
|
|
*
|
|
* History:
|
|
* 12:30 on Tues 23 Apr 1991 -by- Steve Cathcart [stevecat]
|
|
* Took base code from Win 3.1 source
|
|
* 10:30 on Tues 04 Feb 1992 -by- Steve Cathcart [stevecat]
|
|
* Updated code to latest Win 3.1 sources
|
|
* 16:30 on Fri 27 Mar 1992 -by- Steve Cathcart [stevecat]
|
|
* Changed to allow for unlimited number of NT COM ports
|
|
* 18:00 on Tue 06 Apr 1993 -by- Steve Cathcart [stevecat]
|
|
* Updated to work seamlessly with NT serial driver
|
|
* 19:00 on Wed 05 Jan 1994 -by- Steve Cathcart [stevecat]
|
|
* Allow setting COM1 - COM4 advanced parameters
|
|
*
|
|
* Copyright (C) 1990-1994 Microsoft Corporation
|
|
*
|
|
*************************************************************************/
|
|
//==========================================================================
|
|
// Include files
|
|
//==========================================================================
|
|
// C Runtime
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
// Application specific
|
|
#include "main.h"
|
|
|
|
//==========================================================================
|
|
// Local Definitions
|
|
//==========================================================================
|
|
#define PORTS 4
|
|
#define MAXPORTS 32
|
|
#define KEYBZ 4096
|
|
|
|
#define DEF_BAUD 3 /* 1200 */
|
|
#define DEF_WORD 4 /* 8 bits */
|
|
#define DEF_PARITY 2 /* None */
|
|
#define DEF_STOP 0 /* 1 */
|
|
#define DEF_PORT 0 /* Null Port */
|
|
#define DEF_SHAKE 2 /* None */
|
|
#define PAR_EVEN 0
|
|
#define PAR_ODD 1
|
|
#define PAR_NONE 2
|
|
#define PAR_MARK 3
|
|
#define PAR_SPACE 4
|
|
#define STOP_1 0
|
|
#define STOP_15 1
|
|
#define STOP_2 2
|
|
#define FLOW_XON 0
|
|
#define FLOW_HARD 1
|
|
#define FLOW_NONE 2
|
|
|
|
#define CURRENT_SET 1 // TRUE if Registry key CurrentControlSet works
|
|
|
|
#define MAX_COM_PORT 256 // Maximum number of COM ports NT supports
|
|
#define MIN_COM 1 // Minimum new COM port number
|
|
#define MIN_SERIAL 10000 // Minimum new registry "Serial" value
|
|
|
|
|
|
//==========================================================================
|
|
// External Declarations
|
|
//==========================================================================
|
|
|
|
|
|
//==========================================================================
|
|
// Local Data Declarations
|
|
//==========================================================================
|
|
|
|
#ifdef LATER
|
|
HICON hNinePinIcon;
|
|
HICON hiconPorts;
|
|
|
|
HWND hPortDlg;
|
|
HFONT hIconFont;
|
|
WORD fSetPorts;
|
|
LPRECT lpCRects[PORTS];
|
|
RECT CaptureRect;
|
|
RECT rCom1, rCom2, rCom3, rCom4;
|
|
HWND hCom1, hCom2, hCom3, hCom4;
|
|
HWND hBaudEdit;
|
|
BOOL bGrayBaudEdit;
|
|
BOOL bMouseCapture;
|
|
BOOL bCursorChanged;
|
|
short currentBaud;
|
|
|
|
HANDLE hOldCursor;
|
|
int iSetupPort = 1;
|
|
#endif
|
|
|
|
BOOL bNewPort = FALSE;
|
|
BOOL bResetTitle = FALSE;
|
|
BOOL bResetLB = FALSE;
|
|
|
|
int errno;
|
|
|
|
TCHAR sz386Enh[] = TEXT("386Enh");
|
|
TCHAR szBase[] = TEXT("Base");
|
|
TCHAR szIrq[] = TEXT("Irq");
|
|
TCHAR szCOM[] = TEXT("COM");
|
|
TCHAR szCOLON[] = TEXT(":");
|
|
TCHAR szComPort[20];
|
|
TCHAR szSerialKey[40];
|
|
TCHAR szSERIAL[] = TEXT("Serial");
|
|
|
|
// NT Registry keys to find COM port to Serial Device mapping
|
|
|
|
TCHAR szRegSerialMap[] = TEXT("Hardware\\DeviceMap\\SerialComm");
|
|
|
|
// Registry Serial Port Advanced I/O settings key and valuenames
|
|
|
|
TCHAR szRegSerialParam[] =
|
|
TEXT("System\\CurrentControlSet\\Services\\Serial\\Parameters");
|
|
|
|
TCHAR szRegSerialIO[] =
|
|
TEXT("System\\CurrentControlSet\\Services\\Serial\\Parameters\\%s");
|
|
|
|
TCHAR szRegPortAddress[] = TEXT("PortAddress");
|
|
TCHAR szRegPortIRQ[] = TEXT("Interrupt");
|
|
TCHAR szFIFO[] = TEXT("ForceFifoEnable");
|
|
TCHAR szDosDev[] = TEXT("DosDevices");
|
|
|
|
|
|
// static short nBaudRates[] = { 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 0};
|
|
static int nBaudRates[] = { 75, 110, 134, 150, 300, 600, 1200, 1800, 2400,
|
|
4800, 7200, 9600, 14400, 19200, 38400, 57600,
|
|
115200, 128000, 0};
|
|
|
|
static TCHAR sz9600[] = TEXT("9600");
|
|
static TCHAR szDefParams[] = TEXT("9600,n,8,1");
|
|
|
|
static short nDataBits[] = { 4, 5, 6, 7, 8, 0};
|
|
|
|
static TCHAR *pszParityOpts[] = { TEXT("Even"), TEXT("Odd"), TEXT("None"), TEXT("Mark"), TEXT("Space"), TEXT("\0")};
|
|
|
|
static TCHAR *pszStopBits[] = { TEXT("1"), TEXT("1.5"), TEXT("2"), TEXT("\0")};
|
|
|
|
static TCHAR *pszFlowCtl[] = { TEXT("Xon / Xoff"), TEXT("Hardware"), TEXT("None"), TEXT("\0")};
|
|
|
|
|
|
TCHAR *pszParitySuf[] = { TEXT(",e"), TEXT(",o"), TEXT(",n"), TEXT(",m"), TEXT(",s")};
|
|
|
|
TCHAR *pszLenSuf[] = { TEXT(",4"), TEXT(",5"), TEXT(",6"), TEXT(",7"), TEXT(",8")};
|
|
|
|
TCHAR *pszStopSuf[] = { TEXT(",1"), TEXT(",1.5"), TEXT(",2")};
|
|
|
|
TCHAR *pszFlowSuf[] = { TEXT(",x"), TEXT(",p"), TEXT(" ")};
|
|
|
|
//==========================================================================
|
|
// Local Function Prototypes
|
|
//==========================================================================
|
|
BOOL AdvancedPortDlg (HWND hDlg, UINT message, DWORD wParam, LONG lParam);
|
|
BOOL CheckBaseIOSetting (LPTSTR);
|
|
BOOL CommDlg (HWND hDlg, UINT message, DWORD wParam, LONG lParam);
|
|
BOOL RestartDlg (HWND hDlg, UINT message, DWORD wParam, LONG lParam);
|
|
|
|
|
|
//==========================================================================
|
|
// Functions
|
|
//==========================================================================
|
|
|
|
BOOL ChkCommSettings(HWND hDlg)
|
|
{
|
|
TCHAR szTest[133];
|
|
TCHAR *pszVerify;
|
|
|
|
SendDlgItemMessage(hDlg, PORT_BAUDRATE, WM_GETTEXT, 80, (LPARAM)szTest);
|
|
for (pszVerify = szTest; *pszVerify != TEXT('\0'); pszVerify++)
|
|
{
|
|
if ((*pszVerify < TEXT('0')) || (*pszVerify > TEXT('9')))
|
|
{
|
|
if (!LoadString(hModule, ERRORS, szTest, CharSizeOf(szTest)))
|
|
ErrMemDlg(hDlg);
|
|
else
|
|
MessageBox (hDlg, szTest, szCtlPanel,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
return(FALSE); // ERROR EXIT
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL CheckBaseIOSetting (LPTSTR lpszBaseIO)
|
|
{
|
|
LPTSTR lpch;
|
|
BOOL bRet = TRUE;
|
|
|
|
CharUpper (lpszBaseIO);
|
|
|
|
for (lpch = lpszBaseIO; *lpch; lpch++)
|
|
if ((*lpch < TEXT('0') || *lpch > TEXT('9')) && (*lpch < TEXT('A') || *lpch > TEXT('F')))
|
|
{
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
//
|
|
// Set dialog items to defaults from win.ini for given port
|
|
// Port is zero based, 0 = com1, 1 = com2, etc.
|
|
//
|
|
// void SetFromWin(HWND hDlg, int Port)
|
|
//
|
|
|
|
void SetFromWin (HWND hDlg)
|
|
{
|
|
TCHAR szParms[81]; // parms from win.ini for port
|
|
TCHAR *pszCur, *pszNext;
|
|
int nIndex;
|
|
int baud;
|
|
|
|
// szComPort[3] = (TCHAR) (TEXT('1') + Port);
|
|
GetProfileString(szPorts, szComPort, MYNUL, szParms, 81);
|
|
|
|
StripBlanks(szParms);
|
|
pszCur = szParms;
|
|
|
|
//
|
|
// baud rate
|
|
//
|
|
|
|
pszNext = strscan(pszCur, szComma);
|
|
|
|
if (*pszNext)
|
|
*pszNext++ = 0;
|
|
|
|
#ifdef OLDWAY
|
|
if (*pszCur)
|
|
{
|
|
baud = myatoi (pszCur);
|
|
for (nIndex = 0; nBaudRates[nIndex]; nIndex++)
|
|
{
|
|
if (baud == nBaudRates[nIndex])
|
|
break;
|
|
}
|
|
if (nBaudRates[nIndex] == 0)
|
|
nIndex = SendDlgItemMessage(hDlg, PORT_BAUDRATE, CB_ADDSTRING, 0, (LPARAM)pszCur);
|
|
|
|
SendDlgItemMessage(hDlg, PORT_BAUDRATE, CB_SETCURSEL, nIndex, 0L);
|
|
}
|
|
#else
|
|
//
|
|
// Find current Baud Rate selection
|
|
//
|
|
|
|
nIndex = (short) SendDlgItemMessage (hDlg, PORT_BAUDRATE,
|
|
CB_FINDSTRING,
|
|
(WPARAM) -1,
|
|
(LPARAM) pszCur);
|
|
|
|
nIndex = (nIndex == CB_ERR) ? 0 : nIndex;
|
|
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_SETCURSEL, nIndex, 0L);
|
|
|
|
#endif // OLDWAY
|
|
|
|
pszCur = pszNext;
|
|
|
|
//
|
|
// parity
|
|
//
|
|
|
|
pszNext = strscan(pszCur, szComma);
|
|
|
|
if (*pszNext)
|
|
*pszNext++ = 0;
|
|
|
|
StripBlanks(pszCur);
|
|
|
|
switch (*pszCur)
|
|
{
|
|
case TEXT('o'):
|
|
nIndex = PAR_ODD;
|
|
break;
|
|
case TEXT('e'):
|
|
nIndex = PAR_EVEN;
|
|
break;
|
|
case TEXT('n'):
|
|
nIndex = PAR_NONE;
|
|
break;
|
|
case TEXT('m'):
|
|
nIndex = PAR_MARK;
|
|
break;
|
|
case TEXT('s'):
|
|
nIndex = PAR_SPACE;
|
|
break;
|
|
default:
|
|
nIndex = DEF_PARITY;
|
|
break;
|
|
}
|
|
|
|
SendDlgItemMessage (hDlg, PORT_PARITY, CB_SETCURSEL, nIndex, 0L);
|
|
pszCur = pszNext;
|
|
|
|
//
|
|
// word length
|
|
//
|
|
|
|
pszNext = strscan(pszCur, szComma);
|
|
|
|
if (*pszNext)
|
|
*pszNext++ = 0;
|
|
|
|
StripBlanks(pszCur);
|
|
nIndex = (*pszCur - TEXT('4'));
|
|
|
|
if ( (nIndex >= 0) && (nIndex <= 4) )
|
|
SendDlgItemMessage (hDlg, PORT_DATABITS, CB_SETCURSEL, nIndex, 0L);
|
|
else
|
|
SendDlgItemMessage (hDlg, PORT_DATABITS, CB_SETCURSEL, DEF_WORD, 0L);
|
|
|
|
pszCur = pszNext;
|
|
|
|
//
|
|
// stop bits
|
|
//
|
|
|
|
pszNext = strscan(pszCur, szComma);
|
|
|
|
if (*pszNext)
|
|
*pszNext++ = 0;
|
|
|
|
StripBlanks(pszCur);
|
|
|
|
if (!lstrcmp(pszCur, TEXT("1")))
|
|
SendDlgItemMessage (hDlg, PORT_STOPBITS, CB_SETCURSEL, STOP_1, 0L);
|
|
else if (!lstrcmp(pszCur, TEXT("1.5")))
|
|
SendDlgItemMessage (hDlg, PORT_STOPBITS, CB_SETCURSEL, STOP_15, 0L);
|
|
else if (!lstrcmp(pszCur, TEXT("2")))
|
|
SendDlgItemMessage (hDlg, PORT_STOPBITS, CB_SETCURSEL, STOP_2, 0L);
|
|
else
|
|
SendDlgItemMessage (hDlg, PORT_STOPBITS, CB_SETCURSEL, DEF_STOP, 0L);
|
|
|
|
pszCur = pszNext;
|
|
|
|
//
|
|
// handshaking: Hardware, xon/xoff, or none
|
|
//
|
|
|
|
pszNext = strscan(pszCur, szComma);
|
|
|
|
if (*pszNext)
|
|
*pszNext++ = 0;
|
|
|
|
StripBlanks(pszCur);
|
|
|
|
if (*pszCur == TEXT('p'))
|
|
SendDlgItemMessage (hDlg, PORT_FLOWCTL, CB_SETCURSEL, FLOW_HARD, 0L);
|
|
else if (*pszCur == TEXT('x'))
|
|
SendDlgItemMessage (hDlg, PORT_FLOWCTL, CB_SETCURSEL, FLOW_XON, 0L);
|
|
else
|
|
SendDlgItemMessage (hDlg, PORT_FLOWCTL, CB_SETCURSEL, FLOW_NONE, 0L);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// This routine reads off the settings from the dialog and writes them
|
|
// out to win.ini
|
|
//
|
|
// This routine was completely overhauled to work with the new 3.1 Dialog
|
|
// box. Modified by C. Stevens, Oct. 90
|
|
//
|
|
|
|
void CommPortsToWin (HWND hDlg)
|
|
{
|
|
TCHAR szBuild[PATHMAX];
|
|
int i;
|
|
|
|
//
|
|
// Get the baud rate
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_BAUDRATE, WM_GETTEXT, 18, (LPARAM)szBuild);
|
|
|
|
if (i == 0)
|
|
return;
|
|
|
|
//
|
|
// Get the parity setting
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_PARITY, CB_GETCURSEL, 0, 0L);
|
|
|
|
if ((i == CB_ERR) || (i == CB_ERRSPACE))
|
|
return;
|
|
|
|
lstrcat (szBuild, pszParitySuf[i]);
|
|
|
|
//
|
|
// Get the word length
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_DATABITS, CB_GETCURSEL, 0, 0L);
|
|
|
|
if ((i == CB_ERR) || (i == CB_ERRSPACE))
|
|
return;
|
|
|
|
lstrcat (szBuild, pszLenSuf[i]);
|
|
|
|
//
|
|
// Get the stop bits
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_STOPBITS, CB_GETCURSEL, 0, 0L);
|
|
|
|
if ((i == CB_ERR) || (i == CB_ERRSPACE))
|
|
return;
|
|
|
|
lstrcat (szBuild, pszStopSuf[i]);
|
|
|
|
//
|
|
// Get the flow control
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_FLOWCTL, CB_GETCURSEL, 0, 0L);
|
|
|
|
if ((i == CB_ERR) || (i == CB_ERRSPACE))
|
|
return;
|
|
|
|
lstrcat (szBuild, pszFlowSuf[i]);
|
|
|
|
// szComPort[3] = (char) ('0' + iSetupPort);
|
|
|
|
//
|
|
// Write settings string to [ports] section in win.ini
|
|
//
|
|
|
|
WriteProfileString (szPorts, szComPort, szBuild);
|
|
|
|
SendWinIniChange ((LPTSTR)szPorts);
|
|
}
|
|
|
|
#ifdef OLDWAY
|
|
// iPort is a 1 based COM port number (1 == COM1:)
|
|
|
|
int SetupCommPort(HWND hDlg, int iPort)
|
|
{
|
|
iSetupPort = iPort;
|
|
|
|
return(DoDialogBoxParam(DLG_PORTS2, hDlg, CommDlg, IDH_DLG_PORTS2, 0L));
|
|
// return(DialogBox (hModule, MAKEINTRESOURCE(DLG_PORTS2), hDlg,(DLGPROC) CommDlg));
|
|
}
|
|
|
|
void ChangePortSelection(HWND hDlg, int iNewPort, BOOL bOldOnly)
|
|
{
|
|
HWND hwnd;
|
|
|
|
hwnd = GetDlgItem(hDlg, iSetupPort + PORT_COM1RECT - 1);
|
|
iSetupPort = iNewPort;
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
if (!bOldOnly)
|
|
InvalidateRect(GetDlgItem(hDlg, iNewPort + PORT_COM1RECT - 1), NULL, TRUE);
|
|
}
|
|
|
|
|
|
void DrawPortButton(HWND hDlg, LPDRAWITEMSTRUCT lpdis)
|
|
{
|
|
int x, y;
|
|
RECT rc;
|
|
HBRUSH hbr;
|
|
|
|
x = (lpdis->rcItem.left + (lpdis->rcItem.right - (int)GSM(SM_CXICON))) / 2;
|
|
y = (lpdis->rcItem.top + (lpdis->rcItem.bottom - (int)GSM(SM_CYICON))) / 2;
|
|
rc.left = x;
|
|
rc.right = x + (int)GSM(SM_CXICON);
|
|
rc.top = y;
|
|
rc.bottom = y + (int)GSM(SM_CYICON);
|
|
|
|
DrawIcon(lpdis->hDC, x, y, hiconPorts);
|
|
|
|
if (lpdis->itemAction == ODA_FOCUS)
|
|
ChangePortSelection(hDlg, lpdis->CtlID - PORT_COM1RECT + 1, TRUE);
|
|
|
|
if (lpdis->CtlID == (WORD)(PORT_COM1RECT + iSetupPort - 1))
|
|
hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
|
else
|
|
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
|
|
|
|
if (hbr)
|
|
{
|
|
InflateRect(&rc, 2, 2);
|
|
FrameRect(lpdis->hDC, &rc, hbr);
|
|
DeleteObject(hbr);
|
|
}
|
|
}
|
|
#endif // OLDWAY
|
|
|
|
|
|
BOOL ShortCommDlg (HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|
{
|
|
int i, j, nEntries;
|
|
DWORD dwSize, dwBufz;
|
|
DWORD dwType;
|
|
HKEY hkey, hkeySub;
|
|
TCHAR szSerial[40];
|
|
TCHAR szCom[40];
|
|
BOOL bPorts[MAX_COM_PORT+1]; // 1 based array of all allowable COM ports
|
|
|
|
switch (message)
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
HourGlass (TRUE);
|
|
|
|
// Init globals
|
|
bResetTitle = FALSE;
|
|
bResetLB = FALSE;
|
|
|
|
bNewPort = FALSE;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Create a MERGED listing of COM ports between DeviceMap and
|
|
// Services node.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Always clear BOOL array
|
|
for (i = 0; i <= MAX_COM_PORT; bPorts[i++] = FALSE)
|
|
;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Get list of valid COM ports from DEVICEMAP in registry
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Reset list box before display.
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_RESETCONTENT, 0, 0L);
|
|
|
|
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegSerialMap,
|
|
0L, KEY_READ, &hkey))
|
|
{
|
|
dwBufz = sizeof(szSerial);
|
|
dwSize = sizeof(szCom);
|
|
nEntries = i = 0;
|
|
|
|
while (!RegEnumValue (hkey, i++, szSerial, &dwBufz,
|
|
NULL, &dwType, (LPBYTE) szCom, &dwSize))
|
|
{
|
|
if (dwType != REG_SZ)
|
|
continue;
|
|
|
|
// Append ":" char to end of szCom string
|
|
|
|
lstrcat (szCom, TEXT(":"));
|
|
|
|
// Get number of COM port (go past "COM" in string)
|
|
j = myatoi (&szCom[3]);
|
|
|
|
if (j <= MAX_COM_PORT)
|
|
bPorts[j] = TRUE;
|
|
else
|
|
continue;
|
|
|
|
// Put Port name string in ListBox
|
|
|
|
if ((j = (int)SendDlgItemMessage (hDlg, PORT_LB, LB_INSERTSTRING,
|
|
(WPARAM)(LONG)-1, (LPARAM) szCom)) >= 0)
|
|
{
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_INSERTSTRING,
|
|
j, (LPARAM) szSerial);
|
|
++nEntries;
|
|
}
|
|
|
|
dwSize = sizeof(szCom);
|
|
dwBufz = sizeof(szSerial);
|
|
}
|
|
RegCloseKey (hkey);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Get list of valid COM ports from Services Node in registry
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
hkey = NULL;
|
|
|
|
// Read Serial keys at Services Node
|
|
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szRegSerialParam, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ, // SAM
|
|
&hkey)) // return handle
|
|
{
|
|
// Enumerate all keys under Serial\Parameters
|
|
i = 0;
|
|
|
|
while (RegEnumKey (hkey, i++, szSerial, CharSizeOf(szSerial))
|
|
!= ERROR_NO_MORE_ITEMS)
|
|
{
|
|
hkeySub = NULL;
|
|
|
|
if (!RegOpenKeyEx (hkey, // Root key
|
|
szSerial, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ, // SAM
|
|
&hkeySub)) // return handle
|
|
{
|
|
// Get DosDevices value for this Serial key
|
|
|
|
dwSize = sizeof(szCom);
|
|
|
|
if (!RegQueryValueEx (hkeySub, szDosDev, NULL, &dwType,
|
|
(LPBYTE) szCom, &dwSize))
|
|
{
|
|
if (dwType != REG_SZ)
|
|
goto TryNextSubKey;
|
|
|
|
// Append ":" char to end of szCom string
|
|
|
|
lstrcat (szCom, TEXT(":"));
|
|
|
|
// Get number of COM port (go past "COM" in string)
|
|
j = myatoi (&szCom[3]);
|
|
|
|
// Ignore if this port already found in DeviceMap
|
|
if ((j <= MAX_COM_PORT) && (!bPorts[j]))
|
|
bPorts[j] = TRUE;
|
|
else
|
|
goto TryNextSubKey;
|
|
|
|
// Put Port name string in ListBox
|
|
if ((j = (int)SendDlgItemMessage (hDlg,
|
|
PORT_LB,
|
|
LB_INSERTSTRING,
|
|
(WPARAM) -1,
|
|
(LPARAM) szCom)) >= 0)
|
|
{
|
|
SendDlgItemMessage (hDlg,
|
|
SERIAL_DBASE,
|
|
LB_INSERTSTRING,
|
|
j,
|
|
(LPARAM) szSerial);
|
|
++nEntries;
|
|
}
|
|
}
|
|
TryNextSubKey:
|
|
RegCloseKey (hkeySub);
|
|
}
|
|
}
|
|
RegCloseKey (hkey);
|
|
}
|
|
|
|
// By default, select the first item in the Listbox
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_SETCURSEL, 0, 0L);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Check for Greying out ADD and DELETE buttons
|
|
/////////////////////////////////////////////////////////////////
|
|
#ifdef OLD
|
|
// Check for registry access to both the DeviceMap and
|
|
// Services nodes
|
|
|
|
if ((RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szRegSerialMap, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ | KEY_WRITE, // SAM
|
|
&hkeySub) // return handle
|
|
!= ERROR_SUCCESS)
|
|
||
|
|
|
|
RegCloseKey (hkeySub);
|
|
|
|
#endif // OLD
|
|
|
|
//
|
|
// Check for registry access to the Services nodes for
|
|
// adding new ports.
|
|
//
|
|
|
|
if ((RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szRegSerialParam, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ | KEY_WRITE, // SAM
|
|
&hkey) // return handle
|
|
!= ERROR_SUCCESS))
|
|
{
|
|
EnableWindow (GetDlgItem (hDlg, PORT_ADD), FALSE);
|
|
EnableWindow (GetDlgItem (hDlg, PORT_DELETE), FALSE);
|
|
RegCloseKey (hkey);
|
|
}
|
|
|
|
HourGlass (FALSE);
|
|
return TRUE;
|
|
|
|
|
|
#ifdef OLDWAY
|
|
case WM_DRAWITEM:
|
|
DrawPortButton(hDlg, (LPDRAWITEMSTRUCT)lParam);
|
|
break;
|
|
#endif // OLDWAY
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDD_HELP:
|
|
goto DoHelp;
|
|
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
break;
|
|
|
|
#ifdef OLDWAY
|
|
case PORT_COM1RECT:
|
|
case PORT_COM2RECT:
|
|
case PORT_COM3RECT:
|
|
case PORT_COM4RECT:
|
|
ChangePortSelection(hDlg, LOWORD(wParam) - PORT_COM1RECT + 1, FALSE);
|
|
SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem(hDlg, PORT_SETTING), 1L);
|
|
|
|
if (HIWORD(wParam) != BN_DOUBLECLICKED)
|
|
break;
|
|
|
|
// fall through...
|
|
#endif // OLDWAY
|
|
|
|
|
|
case PORT_LB:
|
|
// If user Double Clicks on listbox item, react as though they
|
|
// clicked on "Settings" button
|
|
if (HIWORD(wParam) != LBN_DBLCLK)
|
|
break;
|
|
|
|
// fall through...
|
|
|
|
case PORT_SETTING:
|
|
#ifdef OLDWAY
|
|
if (SetupCommPort(hDlg, iSetupPort) == IDOK)
|
|
SetDlgItemText(hDlg, IDOK, pszClose);
|
|
#endif //OLDWAY
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_LB, LB_GETCURSEL, 0, 0L);
|
|
|
|
if (i != LB_ERR)
|
|
{
|
|
//
|
|
// Set the global COM PORT string for later use
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_GETTEXT, i, (LPARAM)szComPort);
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_GETTEXT, i, (LPARAM)szSerialKey);
|
|
|
|
if (DoDialogBoxParam(DLG_PORTS2, hDlg, (DLGPROC)CommDlg,
|
|
IDH_DLG_PORTS2, 0L) == IDOK)
|
|
{
|
|
SetDlgItemText(hDlg, IDOK, pszClose);
|
|
}
|
|
|
|
if (bResetLB)
|
|
{
|
|
//
|
|
// User changed COM Port Number, delete old, add new
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_DELETESTRING, i, 0L);
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_DELETESTRING, i, 0L);
|
|
|
|
//
|
|
// Put New Port and Serial name strings in ListBoxes
|
|
//
|
|
|
|
if ((j = (int)SendDlgItemMessage (hDlg, PORT_LB, LB_INSERTSTRING,
|
|
(WPARAM)(LONG)-1, (LPARAM) szComPort)) >= 0)
|
|
{
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_INSERTSTRING,
|
|
j, (LPARAM) szSerialKey);
|
|
}
|
|
|
|
j = (j > 0) ? j : 0;
|
|
|
|
//
|
|
// Select an item in the Listbox
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_SETCURSEL, j, 0L);
|
|
|
|
//
|
|
// Reset globals
|
|
//
|
|
|
|
bResetTitle = FALSE;
|
|
bResetLB = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PORT_ADD:
|
|
{
|
|
DWORD dwSave;
|
|
|
|
//
|
|
// Set global flag for Advanced Dialog
|
|
//
|
|
|
|
bNewPort = TRUE;
|
|
|
|
dwSave = dwContext;
|
|
dwContext = IDH_DLG_PORTS3;
|
|
|
|
//
|
|
// Setup some Advanced parameters for this port now
|
|
//
|
|
|
|
if (DialogBox (hModule, (LPTSTR) MAKEINTRESOURCE(DLG_PORTS3), hDlg,
|
|
(DLGPROC) AdvancedPortDlg) == 1)
|
|
{
|
|
SetDlgItemText (hDlg, IDOK, pszClose);
|
|
|
|
//
|
|
// Add new port name to listbox
|
|
// Add new serial value to SERIAL_DBASE listbox
|
|
//
|
|
|
|
if ((j = (int)SendDlgItemMessage (hDlg, PORT_LB, LB_ADDSTRING,
|
|
(WPARAM)(LONG)-1, (LPARAM) szComPort)) >= 0)
|
|
{
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_INSERTSTRING,
|
|
j, (LPARAM) szSerialKey);
|
|
|
|
//
|
|
// Select an item in the Listbox
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_SETCURSEL, j, 0L);
|
|
|
|
SendWinIniChange (szPorts);
|
|
}
|
|
}
|
|
|
|
bNewPort = FALSE;
|
|
dwContext = dwSave;
|
|
|
|
break;
|
|
}
|
|
|
|
case PORT_DELETE:
|
|
{
|
|
/////////////////////////////////////////////////////////////////
|
|
// Check for registry access to both the DeviceMap and
|
|
// Services nodes
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
if ((RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szRegSerialMap, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ | KEY_WRITE, // SAM
|
|
&hkey) // return handle
|
|
!= ERROR_SUCCESS)
|
|
||
|
|
(RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szRegSerialParam, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ | KEY_WRITE, // SAM
|
|
&hkeySub) // return handle
|
|
!= ERROR_SUCCESS))
|
|
{
|
|
MyMessageBox (hDlg, MYPORT+7, INITS+1,
|
|
MB_OKCANCEL | MB_ICONEXCLAMATION);
|
|
break;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Confirm deletion
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
i = MyMessageBox (hDlg, MYPORT+6, INITS+1,
|
|
MB_OKCANCEL | MB_ICONEXCLAMATION);
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Delete everything associated with COM port
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
if (i == IDOK)
|
|
{
|
|
SetDlgItemText (hDlg, IDOK, pszClose);
|
|
|
|
//
|
|
// Get current selection
|
|
//
|
|
|
|
i = SendDlgItemMessage (hDlg, PORT_LB, LB_GETCURSEL, 0, 0L);
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_GETTEXT, i, (LPARAM)szSerial);
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_GETTEXT, i, (LPARAM)szCom);
|
|
|
|
//
|
|
// Delete Registry entries for this COM port
|
|
//
|
|
// Delete Value entry in DeviceMap\SERIALCOMM key
|
|
// Delete entire key under Services\Serial\Parameters node
|
|
//
|
|
|
|
RegDeleteValue (hkey, szSerial);
|
|
RegDeleteKey (hkeySub, szSerial);
|
|
|
|
RegCloseKey (hkey);
|
|
RegCloseKey (hkeySub);
|
|
|
|
//
|
|
// Delete WIN.INI entry - write NULL string to [ports] section
|
|
//
|
|
|
|
WriteProfileString (szPorts, szCom, (LPTSTR) NULL);
|
|
|
|
//
|
|
// Delete ListBox items
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_DELETESTRING, i, 0L);
|
|
SendDlgItemMessage (hDlg, SERIAL_DBASE, LB_DELETESTRING, i, 0L);
|
|
|
|
//
|
|
// Selection next item in ListBox
|
|
//
|
|
|
|
j = SendDlgItemMessage (hDlg, PORT_LB, LB_GETCOUNT, 0, 0L);
|
|
|
|
j = (j > i) ? i : j;
|
|
|
|
//
|
|
// Select an item in the Listbox
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_LB, LB_SETCURSEL, j, 0L);
|
|
|
|
//
|
|
// Let the rest of the world know also
|
|
//
|
|
|
|
SendWinIniChange (szPorts);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
if (message == wHelpMessage)
|
|
{
|
|
DoHelp:
|
|
CPHelp(hDlg);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
VOID SetCBFromRes(HWND hCB, DWORD wRes, DWORD wDef)
|
|
{
|
|
TCHAR szTemp[258], cSep;
|
|
LPTSTR pThis, pThat;
|
|
|
|
if (!LoadString(hModule, wRes, szTemp, CharSizeOf(szTemp)))
|
|
return;
|
|
|
|
for (pThis = szTemp, cSep = *pThis++; pThis; pThis = pThat)
|
|
{
|
|
if (pThat = _tcschr(pThis, cSep))
|
|
*pThat++ = TEXT('\0');
|
|
SendMessage(hCB, CB_ADDSTRING, 0, (LPARAM)pThis);
|
|
}
|
|
SendMessage(hCB, CB_SETCURSEL, wDef, 0L);
|
|
}
|
|
|
|
/* CommDlg
|
|
This is the communications ports setup dialog. It just reads all the
|
|
items, munges them all together into a string, and then writes it out
|
|
to win.ini. This routine does not interact with the comm driver. It
|
|
is the responsibility of each app that uses the comm ports to go first
|
|
to win.ini, read the appropriate line, and then set up the comm port
|
|
accordingly
|
|
*/
|
|
|
|
BOOL CommDlg(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|
{
|
|
TCHAR szTitle[81];
|
|
TCHAR szTitleFormat[81];
|
|
short nIndex;
|
|
HWND hParent;
|
|
DWORD dwMask;
|
|
HANDLE hComm;
|
|
COMMPROP cpComm;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
/* init to defaults */
|
|
|
|
// Get info about COM port from Serial driver
|
|
hComm = CreateFile (szComPort,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if ((hComm != INVALID_HANDLE_VALUE) &&
|
|
GetCommProperties (hComm, &cpComm))
|
|
{
|
|
// Check baud rate bitmask and only display settable rates
|
|
for (dwMask = 1, nIndex = 0; nBaudRates[nIndex]; nIndex++)
|
|
{
|
|
// BAUD_128K comes before 115200 in bitmask, special checks
|
|
if ((cpComm.dwSettableBaud & dwMask) == BAUD_128K)
|
|
{
|
|
// Check for BAUD_115200 first and put it in before this one
|
|
if (cpComm.dwSettableBaud & BAUD_115200)
|
|
{
|
|
MyItoa(nBaudRates[nIndex], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_ADDSTRING,
|
|
0, (LPARAM) szTitle);
|
|
}
|
|
// Now increment to 128K baud rate value
|
|
nIndex++;
|
|
|
|
MyItoa(nBaudRates[nIndex], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_ADDSTRING,
|
|
0, (LPARAM) szTitle);
|
|
|
|
// Move mask over another bit since we have checked
|
|
// for the 115200 value
|
|
dwMask <<= 1;
|
|
}
|
|
else if ((cpComm.dwSettableBaud & dwMask) == BAUD_115200)
|
|
{
|
|
MyItoa(nBaudRates[nIndex-1], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_ADDSTRING,
|
|
0, (LPARAM) szTitle);
|
|
}
|
|
else if (cpComm.dwSettableBaud & dwMask)
|
|
{
|
|
MyItoa(nBaudRates[nIndex], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_ADDSTRING,
|
|
0, (LPARAM) szTitle);
|
|
}
|
|
|
|
dwMask <<= 1;
|
|
}
|
|
CloseHandle (hComm);
|
|
}
|
|
else // Open failure, just list all of the baud rates
|
|
{
|
|
for (nIndex = 0; nBaudRates[nIndex]; nIndex++)
|
|
{
|
|
MyItoa(nBaudRates[nIndex], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_ADDSTRING, 0,
|
|
(LPARAM) szTitle);
|
|
}
|
|
}
|
|
|
|
// Set 9600 as default baud selection
|
|
nIndex = (short) SendDlgItemMessage (hDlg, PORT_BAUDRATE,
|
|
CB_FINDSTRING,
|
|
(WPARAM) -1,
|
|
(LPARAM) sz9600);
|
|
|
|
nIndex = (nIndex == CB_ERR) ? 0 : nIndex;
|
|
|
|
SendDlgItemMessage (hDlg, PORT_BAUDRATE, CB_SETCURSEL, nIndex, 0L);
|
|
|
|
for (nIndex = 0; nDataBits[nIndex]; nIndex++)
|
|
{
|
|
MyItoa(nDataBits[nIndex], szTitle, 10);
|
|
SendDlgItemMessage (hDlg, PORT_DATABITS, CB_ADDSTRING, 0,
|
|
(LPARAM) szTitle);
|
|
}
|
|
SendDlgItemMessage (hDlg, PORT_DATABITS, CB_SETCURSEL, DEF_WORD, 0L);
|
|
|
|
SetCBFromRes(GetDlgItem(hDlg, PORT_PARITY), MYPORT+1, DEF_PARITY);
|
|
SetCBFromRes(GetDlgItem(hDlg, PORT_STOPBITS), MYPORT+2, DEF_STOP);
|
|
SetCBFromRes(GetDlgItem(hDlg, PORT_FLOWCTL), MYPORT+3, DEF_SHAKE);
|
|
|
|
LoadString(hModule, MYPORT + 5, szTitleFormat, CharSizeOf(szTitleFormat));
|
|
wsprintf(szTitle, szTitleFormat, szComPort);
|
|
SetWindowText(hDlg, szTitle);
|
|
|
|
SetFromWin(hDlg);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Test code to determine if this is a "Serial" port or "Digiboard" port
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Test global szSerialKey string to determine if this is a Serial
|
|
// driver port or a 3rd party (i.e OEM) port. If it is a 3rd party
|
|
// port, we do not attempt to Setup Advanced parameters for it.
|
|
//
|
|
|
|
if (!_tcsstr (szSerialKey, szSERIAL))
|
|
EnableWindow (GetDlgItem (hDlg, PORT_ADVANCED), FALSE);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// center and make visible
|
|
//
|
|
|
|
ShowWindow(hDlg, SHOW_OPENWINDOW);
|
|
|
|
return(TRUE);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDD_HELP:
|
|
goto DoHelp;
|
|
|
|
case PORT_ADVANCED:
|
|
{
|
|
DWORD dwSave;
|
|
|
|
dwSave = dwContext;
|
|
dwContext = IDH_DLG_PORTS3;
|
|
|
|
if (DialogBox (hModule, (LPTSTR) MAKEINTRESOURCE(DLG_PORTS3), hDlg,
|
|
(DLGPROC) AdvancedPortDlg) == 1)
|
|
{
|
|
SetDlgItemText (hDlg, PUSH_CANCEL, pszClose);
|
|
hParent = GetParent (hDlg);
|
|
SetDlgItemText (hParent, IDOK, pszClose);
|
|
|
|
// COM Port Number changed, change our title, tell parent also
|
|
if (bResetTitle)
|
|
{
|
|
LoadString(hModule, MYPORT + 5, szTitleFormat,
|
|
CharSizeOf(szTitleFormat));
|
|
wsprintf(szTitle, szTitleFormat, szComPort);
|
|
SetWindowText(hDlg, szTitle);
|
|
bResetTitle = FALSE;
|
|
|
|
// Tell parent dlg to reset when we get there
|
|
bResetLB = TRUE;
|
|
}
|
|
}
|
|
|
|
dwContext = dwSave;
|
|
|
|
break;
|
|
}
|
|
|
|
case PUSH_OK:
|
|
if (ChkCommSettings(hDlg))
|
|
{
|
|
/* change cursor to hourglass */
|
|
HourGlass(TRUE);
|
|
|
|
/* store changes to win.ini; broadcast changes to apps */
|
|
CommPortsToWin(hDlg);
|
|
|
|
/* change cursor back to arrow */
|
|
HourGlass(FALSE);
|
|
}
|
|
else
|
|
{
|
|
SetFocus(GetDlgItem(hDlg, PORT_BAUDRATE));
|
|
SendDlgItemMessage(hDlg, PORT_BAUDRATE, EM_SETSEL, 0, 32767);
|
|
break;
|
|
}
|
|
/* fall through */
|
|
|
|
case PUSH_CANCEL:
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (message == wHelpMessage)
|
|
{
|
|
DoHelp:
|
|
CPHelp(hDlg);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// AdvancedPortDlg
|
|
//
|
|
// Note: This dlg uses the global strings szComPort and szSerialKey.
|
|
// and sets the global BOOL bResetTitle.
|
|
//
|
|
// The global BOOL bNewPort is used to modify behavoir of this
|
|
// dialog slightly when creating new COM ports.
|
|
//
|
|
// DEFAULT values in Base I/O and IRQ controls are only valid for
|
|
// COM1 - COM4 if nothing currently exists for these ports. For all
|
|
// other COM ports, the DEFAULT selection basically means just leaving
|
|
// the current configured value for that port as it is.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define IRQMIN 2
|
|
#define IRQMAX 15
|
|
#define IRQDEF 2
|
|
#define BASEIODEF 1 /* A000 */
|
|
|
|
TCHAR *pszBaseIO[] = { TEXT("03F8"), TEXT("02F8"), TEXT("03E8"), TEXT("02E8"), TEXT("02E0"), TEXT("\0")};
|
|
|
|
BOOL AdvancedPortDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam)
|
|
{
|
|
TCHAR szFormat[200];
|
|
TCHAR szBaseIO[8];
|
|
TCHAR szTitle[120];
|
|
TCHAR szDef[20];
|
|
TCHAR szCom[40];
|
|
TCHAR *pszTemp;
|
|
int nVal;
|
|
int nIndex;
|
|
DWORD dwSize, dwBaseIO, dwFIFO;
|
|
DWORD dwType, dwBaseIRQ;
|
|
BOOL bNone, bWroteToSerialKey;
|
|
HWND hParent;
|
|
int LastCom, NewCom;
|
|
int i, nEntries;
|
|
HKEY hkey;
|
|
|
|
static int nStartIndex;
|
|
static DWORD nFifo;
|
|
static int nPortNumber;
|
|
static TCHAR szStartString[10];
|
|
static HKEY hkeySerial = NULL;
|
|
static DWORD dwDisposition;
|
|
|
|
|
|
switch (nMsg)
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
TCHAR szSerial[40];
|
|
int LastSerial, NewSerial;
|
|
|
|
HourGlass (TRUE);
|
|
|
|
dwDisposition = 0;
|
|
|
|
if (bNewPort)
|
|
{
|
|
//////////////////////////////////////////////////////////////////
|
|
// Determine new "Serial" and "Com" values
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
hParent = GetParent (hDlg);
|
|
|
|
//
|
|
// Determine the last "Serial" and "Com" values
|
|
//
|
|
|
|
nEntries = SendDlgItemMessage (hParent, PORT_LB, LB_GETCOUNT, 0, 0);
|
|
|
|
//
|
|
// Since BIOS usually detects COM1 - COM2
|
|
// New "COMx" port value cannot be less than COM3
|
|
// [stevecat] - for Win NT 3.11 we allow this to be COM1 & COM2
|
|
//
|
|
|
|
NewCom = MIN_COM;
|
|
|
|
//
|
|
// New "Serialxx" value cannot be less than 10,000
|
|
//
|
|
|
|
NewSerial = MIN_SERIAL;
|
|
|
|
//
|
|
// Find last (largest) numbers for COM and SERIAL port numbers
|
|
//
|
|
|
|
for (i = 0; i < nEntries; i++)
|
|
{
|
|
SendDlgItemMessage (hParent, PORT_LB, LB_GETTEXT, i, (LPARAM)szCom);
|
|
|
|
//
|
|
// Get number of Last COM port (go past "COM" in string)
|
|
//
|
|
|
|
LastCom = myatoi (&szCom[3]);
|
|
|
|
NewCom = max(LastCom+1, NewCom);
|
|
|
|
SendDlgItemMessage (hParent, SERIAL_DBASE, LB_GETTEXT, i,
|
|
(LPARAM)szSerial);
|
|
|
|
//
|
|
// Get number of Last Serial entry (go past "Serial" in string)
|
|
//
|
|
|
|
LastSerial = myatoi (&szSerial[6]);
|
|
|
|
NewSerial = max(LastSerial+1, NewSerial);
|
|
}
|
|
|
|
//
|
|
// Use NewCom as the recommendation (only) for new COM port number
|
|
//
|
|
|
|
NewCom = (NewCom > MAX_COM_PORT) ? MIN_COM : NewCom;
|
|
|
|
//
|
|
// Setup new global registry SerialKey value
|
|
//
|
|
|
|
wsprintf (szSerialKey, TEXT("%s%d"), szSERIAL, NewSerial);
|
|
|
|
//
|
|
// Set up window title
|
|
//
|
|
|
|
LoadString(hModule, MYPORT + 9, szFormat, CharSizeOf(szFormat));
|
|
LoadString(hModule, MYPORT + 4, szCom, CharSizeOf(szCom));
|
|
|
|
wsprintf(szTitle, szFormat, szCom);
|
|
SetWindowText(hDlg, szTitle);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Determine current COM port number
|
|
//
|
|
// NOTE: szSerialKey and szComPort global vlaues are already set
|
|
//
|
|
// Get number of Last COM port (go past "COM" in string)
|
|
//
|
|
|
|
NewCom = myatoi (&szComPort[3]);
|
|
|
|
//
|
|
// Set up window title
|
|
//
|
|
|
|
LoadString(hModule, MYPORT + 9, szFormat, CharSizeOf(szFormat));
|
|
wsprintf(szTitle, szFormat, szComPort);
|
|
SetWindowText(hDlg, szTitle);
|
|
}
|
|
|
|
//
|
|
// Init values for "COM port number" combobox
|
|
//
|
|
|
|
for (i = MIN_COM; i <= MAX_COM_PORT; i++)
|
|
{
|
|
wsprintf (szCom, TEXT("%d"), i);
|
|
SendDlgItemMessage (hDlg, PORT_NUMBER, CB_ADDSTRING, 0,
|
|
(LPARAM)szCom);
|
|
}
|
|
|
|
SendDlgItemMessage (hDlg, PORT_NUMBER, CB_SETCURSEL,
|
|
NewCom-MIN_COM, 0L);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Put selections for Port Base I/O address in combobox
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Limit length of edit boxes
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg,PORT_BASEIO, CB_LIMITTEXT,4,0L);
|
|
|
|
//
|
|
// Fill combo box; add "(None)" and numbers
|
|
//
|
|
|
|
if (!bNewPort)
|
|
{
|
|
//
|
|
// "Default" not allowed for new ports
|
|
//
|
|
|
|
LoadString (hModule, MYPORT, szDef, CharSizeOf(szDef));
|
|
|
|
SendDlgItemMessage (hDlg, PORT_BASEIO, CB_ADDSTRING, 0, (LPARAM)szDef);
|
|
}
|
|
|
|
for (nIndex = 0; *pszBaseIO[nIndex]; nIndex++)
|
|
SendDlgItemMessage (hDlg, PORT_BASEIO, CB_ADDSTRING, 0,
|
|
(LPARAM) pszBaseIO[nIndex]);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Put selections for Port IRQ level in combobox
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
if (!bNewPort)
|
|
{
|
|
//
|
|
// "Default" not allowed for new ports
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_IRQ, CB_ADDSTRING, 0, (LPARAM)szDef);
|
|
}
|
|
|
|
for (nIndex = IRQMAX; nIndex >= IRQMIN; --nIndex)
|
|
{
|
|
wsprintf (szTitle, TEXT("%d"), nIndex);
|
|
SendDlgItemMessage (hDlg, PORT_IRQ, CB_ADDSTRING, 0, (LPARAM)szTitle);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Get configured values for options from Registry
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Put initial values in edit boxes; note that szDef still
|
|
// contains "Default"
|
|
//
|
|
// NT: The NT serial driver doesn't support the EscapeCommFunction
|
|
// api. We try to get this value from the Registry.
|
|
//
|
|
// Make registry key for this Serial Port to get Advanced I/O
|
|
// settings. And save hkey around for later use on exit
|
|
//
|
|
|
|
hkeySerial = NULL;
|
|
wsprintf (szFormat, szRegSerialIO, szSerialKey);
|
|
|
|
//
|
|
// For New Ports this will create a new serial key entry
|
|
//
|
|
|
|
if (!RegCreateKeyEx (HKEY_LOCAL_MACHINE, // Root key
|
|
szFormat, // Subkey to open/create
|
|
0L, // Reserved
|
|
NULL, // Class string
|
|
0L, // Options
|
|
KEY_ALL_ACCESS, // SAM
|
|
NULL, // ptr to Security struct
|
|
&hkeySerial, // return handle
|
|
&dwDisposition)) // return disposition
|
|
{
|
|
//
|
|
// Try to get the configured Port Base I/O address from Registry
|
|
//
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
if (!RegQueryValueEx (hkeySerial, szRegPortAddress, NULL, &dwType,
|
|
(LPBYTE) &dwBaseIO, &dwSize))
|
|
{
|
|
if (dwType == REG_DWORD)
|
|
{
|
|
MyUltoa (dwBaseIO, szBaseIO, 16);
|
|
SetDlgItemText (hDlg, PORT_BASEIO, szBaseIO);
|
|
}
|
|
else
|
|
goto SetDefaultIO;
|
|
}
|
|
else
|
|
{
|
|
SetDefaultIO:
|
|
if (bNewPort)
|
|
{
|
|
//
|
|
// Choose first item in combobox for new ports
|
|
//
|
|
|
|
SendDlgItemMessage (hDlg, PORT_BASEIO, CB_SETCURSEL, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If this is port COM1, 2, 3 or 4 allow open to continue
|
|
// and set all controls for with default values.
|
|
//
|
|
|
|
if (NewCom <= 4)
|
|
{
|
|
SetDlgItemText(hDlg, PORT_BASEIO, szDef);
|
|
goto SpecialCom1to4;
|
|
}
|
|
|
|
//
|
|
// Put up a message box error stating that the USER does
|
|
// not have the Advanced Serial I/O parameters configured
|
|
// in the registry and just continue for now.
|
|
//
|
|
|
|
RegCloseKey (hkeySerial);
|
|
|
|
if (dwDisposition == REG_CREATED_NEW_KEY)
|
|
{
|
|
RegDeleteKey (HKEY_LOCAL_MACHINE, szFormat);
|
|
}
|
|
|
|
MyMessageBox (hDlg, MYPORT+13, INITS+1,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
|
|
HourGlass (FALSE);
|
|
EndDialog (hDlg, 0);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
SpecialCom1to4:
|
|
|
|
//
|
|
// Try to get the configured Port IRQ Level from Registry
|
|
//
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwBaseIRQ = 0;
|
|
|
|
if (!RegQueryValueEx (hkeySerial, szRegPortIRQ, NULL, &dwType,
|
|
(LPBYTE) &dwBaseIRQ, &dwSize))
|
|
{
|
|
if (dwType != REG_DWORD)
|
|
dwBaseIRQ = 0;
|
|
}
|
|
|
|
//
|
|
// Try to get the configured FIFO state from Registry
|
|
//
|
|
|
|
dwSize = sizeof(DWORD);
|
|
dwFIFO = 0;
|
|
|
|
if (!RegQueryValueEx (hkeySerial, szFIFO, NULL, &dwType,
|
|
(LPBYTE) &dwFIFO, &dwSize))
|
|
{
|
|
if (dwType != REG_DWORD)
|
|
dwFIFO = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MyMessageBox (hDlg, (bNewPort) ? MYPORT+15 : MYPORT+14, INITS+1,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
HourGlass (FALSE);
|
|
EndDialog (hDlg, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make a PORT_IRQ and PORT_FIFO selection
|
|
//
|
|
|
|
SendDlgItemMessage(hDlg, PORT_IRQ, CB_SETCURSEL,
|
|
(dwBaseIRQ >= IRQMIN && dwBaseIRQ <= IRQMAX) ?
|
|
IRQMAX+1 - dwBaseIRQ : 0, 0L);
|
|
|
|
CheckDlgButton (hDlg, PORT_FIFO, dwFIFO);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Store away the initial settings so we can warn the user if
|
|
// they need to reboot
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
nFifo = dwFIFO;
|
|
nPortNumber = NewCom;
|
|
nStartIndex = SendDlgItemMessage (hDlg,PORT_IRQ,CB_GETCURSEL, 0, 0L);
|
|
GetDlgItemText (hDlg, PORT_BASEIO, szStartString, CharSizeOf(szStartString));
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Show the window and reset the cursor
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
ShowWindow (hDlg, SW_SHOW);
|
|
UpdateWindow (hDlg);
|
|
HourGlass (FALSE);
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
|
|
case IDD_HELP:
|
|
goto DoHelp;
|
|
|
|
case IDOK:
|
|
HourGlass (TRUE);
|
|
|
|
bWroteToSerialKey = FALSE;
|
|
|
|
//
|
|
// Check IRQ line is valid
|
|
//
|
|
|
|
nVal = (int)SendDlgItemMessage(hDlg, PORT_IRQ, CB_GETCURSEL, 0, 0L);
|
|
|
|
if ((nVal == CB_ERR) || (nVal == CB_ERRSPACE))
|
|
nVal = nStartIndex;
|
|
|
|
//
|
|
// Check Base I/O Address is valid
|
|
//
|
|
|
|
i = GetDlgItemText (hDlg, PORT_BASEIO, szBaseIO, CharSizeOf(szBaseIO));
|
|
LoadString (hModule, MYPORT, szDef, CharSizeOf(szDef));
|
|
|
|
if (i == 0)
|
|
lstrcpy (szBaseIO, szStartString);
|
|
|
|
bNone = !_tcsnicmp (szDef, szBaseIO, CharSizeOf(szBaseIO)-1);
|
|
|
|
if (!bNone && !CheckBaseIOSetting (szBaseIO))
|
|
{
|
|
LoadString (hModule, MYPORT + 11, szFormat, CharSizeOf(szFormat));
|
|
GetWindowText (hDlg, szTitle, CharSizeOf(szTitle));
|
|
MessageBox (hDlg, szFormat, szTitle, MB_OK | MB_ICONINFORMATION);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get FIFO selection
|
|
//
|
|
|
|
dwFIFO = IsDlgButtonChecked (hDlg, PORT_FIFO);
|
|
|
|
//
|
|
// Get the COM port number from the edit box
|
|
//
|
|
|
|
i = GetDlgItemText (hDlg, PORT_NUMBER, szCom, CharSizeOf(szCom));
|
|
|
|
NewCom = (i == 0) ? nPortNumber : myatoi (szCom);
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Check to see if we've changed anything. If so,
|
|
// - Output new values to registry
|
|
// - check and save the stuff in the parent dialog,
|
|
// - and issue a restart warning.
|
|
//
|
|
|
|
// ASSERT(hkeySerial != NULL);
|
|
|
|
if (bNewPort ||
|
|
nVal != nStartIndex ||
|
|
nPortNumber != NewCom ||
|
|
nFifo != dwFIFO ||
|
|
_tcsnicmp (szStartString, szBaseIO, CharSizeOf(szBaseIO)-1))
|
|
{
|
|
//
|
|
// Output Base I/O to Registry
|
|
//
|
|
// If I write anything out to registry for this port
|
|
// I must also, always write the Port Address, IRQ and
|
|
// DosDevices name. For COM1-COM4 this means converting
|
|
// from the "default" value to the real default Base I/O
|
|
// address.
|
|
//
|
|
|
|
if (bNone)
|
|
{
|
|
//
|
|
// Convert "Default" value to a real I/O address for
|
|
// storage in registry - failsafe case uses COM1 I/O
|
|
//
|
|
|
|
if ((NewCom > 0) && (NewCom < 5))
|
|
dwBaseIO = _tcstoul (pszBaseIO[NewCom-1], &pszTemp, 16);
|
|
else
|
|
dwBaseIO = _tcstoul (pszBaseIO[4], &pszTemp, 16);
|
|
}
|
|
else
|
|
{
|
|
dwBaseIO = _tcstoul (szBaseIO, &pszTemp, 16);
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
if (RegSetValueEx (hkeySerial, szRegPortAddress, 0L,
|
|
REG_DWORD, (LPBYTE) &dwBaseIO, dwSize))
|
|
goto RegistryError;
|
|
|
|
bWroteToSerialKey = TRUE;
|
|
|
|
//
|
|
// Set FIFO value
|
|
//
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
if (RegSetValueEx (hkeySerial, szFIFO, 0L, REG_DWORD,
|
|
(LPBYTE) &dwFIFO, dwSize))
|
|
goto RegistryError;
|
|
|
|
//
|
|
// Create global string from new port (without ":")
|
|
//
|
|
|
|
wsprintf (szComPort, TEXT("%s%d"), szCOM, NewCom);
|
|
|
|
//
|
|
// Set "DosDevices" entry while we are here
|
|
//
|
|
|
|
if (RegSetValueEx (hkeySerial, szDosDev, 0L, REG_SZ,
|
|
(LPBYTE) szComPort, ByteCountOf(lstrlen(szComPort)+1)))
|
|
{
|
|
//
|
|
// Append ":" char to end of szComPort string
|
|
//
|
|
|
|
lstrcat (szComPort, TEXT(":"));
|
|
|
|
goto RegistryError;
|
|
}
|
|
|
|
//
|
|
// Try to create registry Devicemap entry
|
|
//
|
|
|
|
if (RegCreateKey (HKEY_LOCAL_MACHINE, szRegSerialMap,
|
|
&hkey) == ERROR_SUCCESS)
|
|
{
|
|
if (RegSetValueEx (hkey, szSerialKey, 0L, REG_SZ,
|
|
(LPBYTE) szComPort, ByteCountOf(lstrlen (szComPort)+1)) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey (hkey);
|
|
goto ComCreateError;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ComCreateError:
|
|
//
|
|
// Append ":" char to end of szComPort string
|
|
//
|
|
|
|
lstrcat (szComPort, TEXT(":"));
|
|
MyMessageBox (hDlg, MYPORT+17, INITS+1,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Append ":" char to end of szComPort string
|
|
//
|
|
|
|
lstrcat (szComPort, TEXT(":"));
|
|
RegCloseKey (hkey);
|
|
|
|
//
|
|
// Output IRQ line to Registry
|
|
//
|
|
|
|
if (bNewPort || nVal > 0)
|
|
{
|
|
//
|
|
// Since we don't display "Default" string at NewPort time
|
|
// the equation for IRQ is different
|
|
//
|
|
|
|
dwBaseIRQ = (bNewPort ? IRQMAX : IRQMAX+1) - nVal;
|
|
}
|
|
else if (nVal == 0)
|
|
{
|
|
//
|
|
// Replace the Default setting with correct IRQ for port
|
|
//
|
|
|
|
switch (NewCom)
|
|
{
|
|
case 1:
|
|
case 3:
|
|
dwBaseIRQ = 4;
|
|
break;
|
|
|
|
case 2:
|
|
case 4:
|
|
dwBaseIRQ = 3;
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Failsafe
|
|
//
|
|
|
|
dwBaseIRQ = 15;
|
|
break;
|
|
}
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
|
|
if (RegSetValueEx (hkeySerial, szRegPortIRQ, 0L,
|
|
REG_DWORD, (LPBYTE) &dwBaseIRQ, dwSize))
|
|
{
|
|
RegistryError:
|
|
//
|
|
// ERROR - Cannot set Registry value
|
|
//
|
|
|
|
MyMessageBox (hDlg, MYPORT+18, INITS+1,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
goto AdvancedFailure;
|
|
}
|
|
|
|
if (bNewPort)
|
|
{
|
|
//
|
|
// Write default Baud rate string to registry "9600,n,8,1"
|
|
//
|
|
|
|
WriteProfileString (szPorts, szComPort, szDefParams);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check params in "Baud rate" dlg
|
|
//
|
|
|
|
hParent = GetParent (hDlg);
|
|
|
|
if (!ChkCommSettings (hParent))
|
|
{
|
|
SetFocus (hDlg);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Output normal comm settings to WIN.INI
|
|
//
|
|
|
|
CommPortsToWin (hParent);
|
|
|
|
//
|
|
// Change titlebar in parent dlg if COM Port Number changed
|
|
//
|
|
|
|
if (nPortNumber != NewCom)
|
|
bResetTitle = TRUE;
|
|
}
|
|
|
|
//
|
|
// Issue a restart warning
|
|
//
|
|
|
|
DialogBoxParam (hModule,(LPTSTR) MAKEINTRESOURCE(DLG_RESTART),hDlg,
|
|
(DLGPROC) RestartDlg, MAKELONG(IDS_COMCHANGE, 0));
|
|
}
|
|
|
|
RegCloseKey (hkeySerial);
|
|
|
|
//
|
|
// Delete the Serial Key entry I created at InitDlg time in the
|
|
// Services\Parameters\Serial registry node only if I really
|
|
// created it AND I did not write anything to it at ID_OK time.
|
|
//
|
|
// Note: This is for the brain dead serial driver that doesn't
|
|
// know how to ignore a key that has no value entries
|
|
// and instead reports bogus EventLog ERRORS.
|
|
//
|
|
|
|
if ((dwDisposition == REG_CREATED_NEW_KEY) && !bWroteToSerialKey)
|
|
{
|
|
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
szRegSerialParam,
|
|
0L,
|
|
KEY_ALL_ACCESS,
|
|
&hkey))
|
|
{
|
|
RegDeleteKey (hkey, szSerialKey);
|
|
RegCloseKey (hkey);
|
|
}
|
|
}
|
|
|
|
|
|
HourGlass (FALSE);
|
|
|
|
EndDialog (hDlg, 1);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
AdvancedFailure:
|
|
if (bNewPort)
|
|
{
|
|
//
|
|
// "Cancel" btn selected, delete Parameters entry
|
|
//
|
|
|
|
if (hkeySerial != NULL)
|
|
{
|
|
RegCloseKey (hkeySerial);
|
|
|
|
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
szRegSerialParam,
|
|
0L,
|
|
KEY_ALL_ACCESS,
|
|
&hkey))
|
|
{
|
|
RegDeleteKey (hkey, szSerialKey);
|
|
RegCloseKey (hkey);
|
|
}
|
|
}
|
|
}
|
|
else if (hkeySerial != NULL)
|
|
{
|
|
RegCloseKey (hkeySerial);
|
|
|
|
//
|
|
// Delete Parameters entry in other cases only if I initially
|
|
// created the key at InitDlg time.
|
|
//
|
|
|
|
if (dwDisposition == REG_CREATED_NEW_KEY)
|
|
{
|
|
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
szRegSerialParam,
|
|
0L,
|
|
KEY_ALL_ACCESS,
|
|
&hkey))
|
|
{
|
|
RegDeleteKey (hkey, szSerialKey);
|
|
RegCloseKey (hkey);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
HourGlass (FALSE);
|
|
|
|
EndDialog (hDlg, 0);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (nMsg == wHelpMessage)
|
|
{
|
|
DoHelp:
|
|
CPHelp(hDlg);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|