1900 lines
51 KiB
C
1900 lines
51 KiB
C
///////////////////////////////////////////////////////////////////////////
|
|
// Advanced Dialog Functions
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "ports.h"
|
|
#include "pp.h"
|
|
|
|
#include <windowsx.h>
|
|
|
|
#define COBJMACROS 1
|
|
|
|
#include <ole2.h>
|
|
#include <initguid.h>
|
|
#include <oleacc.h>
|
|
#include <winable.h>
|
|
|
|
//
|
|
// write out values in tenths of a sec
|
|
//
|
|
#define SECONDS_CONVERSION_FACTOR (10)
|
|
#define NUM_POLLING_PERIODS 7
|
|
|
|
DWORD PollingPeriods[NUM_POLLING_PERIODS] = {
|
|
-1,
|
|
0,
|
|
1 * SECONDS_CONVERSION_FACTOR,
|
|
5 * SECONDS_CONVERSION_FACTOR,
|
|
10 * SECONDS_CONVERSION_FACTOR,
|
|
30 * SECONDS_CONVERSION_FACTOR,
|
|
60 * SECONDS_CONVERSION_FACTOR
|
|
};
|
|
|
|
TCHAR PeriodDescription[NUM_POLLING_PERIODS+1][40] = {
|
|
{ _T("Disabled") },
|
|
{ _T("Manually") },
|
|
{ _T("Every second") },
|
|
{ _T("Every 5 seconds") },
|
|
{ _T("Every 10 seconds") },
|
|
{ _T("Every 30 seconds") },
|
|
{ _T("Every minute") },
|
|
{ _T("Other (every %d sec)") }
|
|
};
|
|
|
|
ULONG RxValues[4] = { 1, 4, 8, 14};
|
|
|
|
WCHAR RxValuesStringMap[] = L"A:0:1:1:2:4:3:8:4:14:";
|
|
WCHAR TxValuesStringMap[] = L"use_raw";
|
|
|
|
TCHAR m_szRxFIFO[] = _T("RxFIFO");
|
|
TCHAR m_szTxFIFO[] = _T("TxFIFO");
|
|
TCHAR m_szFifoRxMax[] = _T("FifoRxMax");
|
|
TCHAR m_szFifoTxMax[] = _T("FifoTxMax");
|
|
|
|
const DWORD AdvanHelpIDs[] =
|
|
{
|
|
IDC_DESC_1, IDH_NOHELP,
|
|
IDC_DESC_2, IDH_NOHELP,
|
|
|
|
IDC_FIFO, IDH_DEVMGR_PORTSET_ADV_USEFIFO, // "Use FIFO buffers (requires 16550 compatible UART)" (Button)
|
|
|
|
IDC_RECEIVE_TEXT, IDH_NOHELP, // "&Receive Buffer:" (Static)
|
|
IDC_RECEIVE_SLIDER, IDH_DEVMGR_PORTSET_ADV_RECV, // "" (msctls_trackbar32)
|
|
IDC_RECEIVE_LOW, IDH_NOHELP, // "Low (%d)" (Static)
|
|
IDC_RECEIVE_HIGH, IDH_NOHELP, // "High (%d)" (Static)
|
|
IDC_RXVALUE, IDH_NOHELP,
|
|
|
|
IDC_TRANSMIT_TEXT, IDH_NOHELP, // "&Transmit Buffer:" (Static)
|
|
IDC_TRANSMIT_SLIDER, IDH_DEVMGR_PORTSET_ADV_TRANS, // "" (msctls_trackbar32)
|
|
IDC_TRANSMIT_LOW, IDH_NOHELP, // "Low (%d)" (Static)
|
|
IDC_TRANSMIT_HIGH, IDH_NOHELP, // "High (%d)" (Static)
|
|
IDC_TXVALUE, IDH_NOHELP,
|
|
|
|
IDC_POLL_DESC, IDH_NOHELP,
|
|
IDC_POLL_PERIOD, IDH_DEVMGR_PORTSET_ADV_DEVICES, // "" (ComboBox)
|
|
|
|
PP_PORT_NUMBER, IDH_DEVMGR_PORTSET_ADV_NUMBER, // "" (ComboBox)
|
|
IDC_COMNUMTEXT, IDH_NOHELP, // "COM &Port Number:" (Static)
|
|
|
|
IDC_RESTORE, IDH_DEVMGR_PORTSET_ADV_DEFAULTS,// "&Restore Defaults" (Button)
|
|
0, 0
|
|
};
|
|
|
|
#define Trackbar_SetPos(hwndTb, Redraw, Position)\
|
|
(VOID) SendMessage(hwndTb, TBM_SETPOS, (WPARAM) Redraw, (LPARAM) Position)
|
|
|
|
#define Trackbar_SetRange(hwndTb, Redraw, MinVal, MaxVal)\
|
|
(VOID) SendMessage(hwndTb, TBM_SETRANGE, (WPARAM) Redraw, (LPARAM) MAKELONG(MinVal, MaxVal))
|
|
|
|
#define Trackbar_SetTic(hwndTb, Tic)\
|
|
(VOID) SendMessage(hwndTb, TBM_SETTIC, (WPARAM) 0, (LPARAM) Tic)
|
|
|
|
#define Trackbar_GetPos(hwndTb)\
|
|
(DWORD) SendMessage(hwndTb, TBM_GETPOS, (WPARAM) 0, (LPARAM) 0)
|
|
|
|
|
|
|
|
BOOL
|
|
Advanced_OnCommand(
|
|
HWND ParentHwnd,
|
|
int ControlId,
|
|
HWND ControlHwnd,
|
|
UINT NotifyCode
|
|
);
|
|
|
|
|
|
BOOL
|
|
Advanced_OnContextMenu(
|
|
HWND HwndControl,
|
|
WORD Xpos,
|
|
WORD Ypos
|
|
);
|
|
|
|
void
|
|
Advanced_OnHelp(
|
|
HWND ParentHwnd,
|
|
LPHELPINFO HelpInfo
|
|
);
|
|
|
|
BOOL
|
|
Advanced_OnInitDialog(
|
|
HWND ParentHwnd,
|
|
HWND FocusHwnd,
|
|
LPARAM Lparam
|
|
);
|
|
|
|
/*++
|
|
|
|
Routine Description: AdvancedPortsDlgProc
|
|
|
|
The windows proc for the Advanced properties window
|
|
|
|
Arguments:
|
|
|
|
hDlg, uMessage, wParam, lParam: standard windows DlgProc parameters
|
|
|
|
Return Value:
|
|
|
|
BOOL: FALSE if the page could not be created
|
|
|
|
--*/
|
|
INT_PTR APIENTRY
|
|
AdvancedPortsDlgProc(
|
|
IN HWND hDlg,
|
|
IN UINT uMessage,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
switch(uMessage) {
|
|
case WM_COMMAND:
|
|
return Advanced_OnCommand(hDlg,
|
|
(int) LOWORD(wParam),
|
|
(HWND)lParam,
|
|
(UINT) HIWORD(wParam));
|
|
|
|
case WM_CONTEXTMENU:
|
|
return Advanced_OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
|
|
|
|
case WM_HELP:
|
|
Advanced_OnHelp(hDlg, (LPHELPINFO) lParam);
|
|
break;
|
|
|
|
case WM_HSCROLL:
|
|
HandleTrackbarChange(hDlg, (HWND) lParam);
|
|
return TRUE;
|
|
|
|
case WM_INITDIALOG:
|
|
return Advanced_OnInitDialog(hDlg, (HWND) wParam, lParam);
|
|
}
|
|
|
|
return FALSE;
|
|
} /* AdvancedPortsDlgProc */
|
|
|
|
BOOL
|
|
Advanced_OnCommand(
|
|
HWND ParentHwnd,
|
|
int ControlId,
|
|
HWND ControlHwnd,
|
|
UINT NotifyCode
|
|
)
|
|
{
|
|
PADVANCED_DATA advancedData =
|
|
(PADVANCED_DATA) GetWindowLongPtr(ParentHwnd, DWLP_USER);
|
|
|
|
switch(ControlId) {
|
|
|
|
case IDC_FIFO:
|
|
//
|
|
// Disable or enable the sliders
|
|
//
|
|
EnableFifoControls(ParentHwnd, IsDlgButtonChecked(ParentHwnd, IDC_FIFO));
|
|
return TRUE;
|
|
|
|
case IDOK:
|
|
SaveAdvancedSettings(ParentHwnd, advancedData);
|
|
// fall through
|
|
|
|
case IDCANCEL:
|
|
EndDialog(ParentHwnd, ControlId);
|
|
return TRUE;
|
|
|
|
case IDC_RESTORE:
|
|
RestoreAdvancedDefaultState(ParentHwnd, advancedData);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
Advanced_OnContextMenu(
|
|
HWND HwndControl,
|
|
WORD Xpos,
|
|
WORD Ypos
|
|
)
|
|
{
|
|
WinHelp(HwndControl,
|
|
m_szDevMgrHelp,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR) AdvanHelpIDs);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
Advanced_OnHelp(
|
|
HWND ParentHwnd,
|
|
LPHELPINFO HelpInfo
|
|
)
|
|
{
|
|
if (HelpInfo->iContextType == HELPINFO_WINDOW) {
|
|
WinHelp((HWND) HelpInfo->hItemHandle,
|
|
m_szDevMgrHelp,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR) AdvanHelpIDs);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
Advanced_OnInitDialog(
|
|
HWND ParentHwnd,
|
|
HWND FocusHwnd,
|
|
LPARAM Lparam
|
|
)
|
|
{
|
|
PADVANCED_DATA advancedData;
|
|
TCHAR szFormat[200];
|
|
TCHAR szBuffer[200];
|
|
|
|
advancedData = (PADVANCED_DATA) Lparam;
|
|
|
|
//
|
|
// Initialize the dialog box parameters
|
|
//
|
|
FillAdvancedDlg(ParentHwnd, advancedData);
|
|
SetWindowLongPtr(ParentHwnd, DWLP_USER, (ULONG_PTR) advancedData);
|
|
|
|
//
|
|
// Set up the dialog box with these initialized parameters
|
|
//
|
|
InitializeControls(ParentHwnd, advancedData);
|
|
|
|
LoadString(g_hInst, IDS_ADVANCED_SETTINGS_FOR, szFormat, CharSizeOf(szFormat));
|
|
wsprintf(szBuffer, szFormat, advancedData->szComName);
|
|
SetWindowText(ParentHwnd, szBuffer);
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
LONG
|
|
SerialDisplayAdvancedSettings(
|
|
IN HWND ParentHwnd,
|
|
IN HDEVINFO DeviceInfoSet,
|
|
IN PSP_DEVINFO_DATA DeviceInfoData
|
|
)
|
|
{
|
|
ADVANCED_DATA advancedData;
|
|
HKEY hDeviceKey;
|
|
DWORD dwPortNameSize;
|
|
|
|
if (!DeviceInfoSet) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
advancedData.HidePolling = TRUE;
|
|
advancedData.DeviceInfoSet = DeviceInfoSet;
|
|
advancedData.DeviceInfoData = DeviceInfoData;
|
|
|
|
//
|
|
// Open the device key for the source device instance, and retrieve its
|
|
// "PortName" value.
|
|
//
|
|
hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet,
|
|
DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DEV,
|
|
KEY_READ);
|
|
|
|
if (INVALID_HANDLE_VALUE == hDeviceKey)
|
|
return ERROR_ACCESS_DENIED;
|
|
|
|
dwPortNameSize = sizeof(advancedData.szComName);
|
|
if (RegQueryValueEx(hDeviceKey,
|
|
m_szPortName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE) advancedData.szComName,
|
|
&dwPortNameSize) != ERROR_SUCCESS) {
|
|
RegCloseKey(hDeviceKey);
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
RegCloseKey(hDeviceKey);
|
|
|
|
return DisplayAdvancedDialog(ParentHwnd, &advancedData) ? ERROR_SUCCESS
|
|
: ERROR_ACCESS_DENIED;
|
|
}
|
|
// @@END_DDKSPLIT
|
|
|
|
BOOL InternalAdvancedDialog(
|
|
IN HWND ParentHwnd,
|
|
IN OUT PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
AdvancedData->hComDB = HCOMDB_INVALID_HANDLE_VALUE;
|
|
ComDBOpen(&AdvancedData->hComDB);
|
|
|
|
DialogBoxParam(g_hInst,
|
|
MAKEINTRESOURCE(DLG_PP_ADVPORTS),
|
|
ParentHwnd,
|
|
AdvancedPortsDlgProc,
|
|
(DWORD_PTR) AdvancedData);
|
|
|
|
ComDBClose(AdvancedData->hComDB);
|
|
AdvancedData->hComDB = HCOMDB_INVALID_HANDLE_VALUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
BOOL
|
|
FindAdvancedDialogOverride(
|
|
IN HDEVINFO DeviceInfoSet,
|
|
IN PSP_DEVINFO_DATA DeviceInfoData,
|
|
IN PTCHAR Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks the driver key in the devnode for the override value.
|
|
|
|
Arguments:
|
|
|
|
DeviceInfoSet - Supplies a handle to the device information
|
|
|
|
DeviceInfoData - Supplies the address of the device information element
|
|
|
|
Value - Value read in from the registry
|
|
|
|
Return Value:
|
|
|
|
If found TRUE, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szLine[LINE_LEN];
|
|
DWORD dwDataType, dwSize;
|
|
TCHAR szOverrideName[] = _T("EnumAdvancedDialog");
|
|
|
|
//
|
|
// Open up the driver key for this device so we can run our INF registry mods
|
|
// against it.
|
|
//
|
|
hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
|
|
DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DRV,
|
|
KEY_READ);
|
|
|
|
dwSize = sizeof(szLine);
|
|
if (RegQueryValueEx(hKey,
|
|
szOverrideName,
|
|
NULL,
|
|
&dwDataType,
|
|
(PBYTE) &szLine,
|
|
&dwSize) != ERROR_SUCCESS ||
|
|
dwDataType != REG_SZ) {
|
|
RegCloseKey(hKey);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(Value, szLine);
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CallAdvancedDialogOverride(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData,
|
|
PTCHAR Override,
|
|
PBOOL Success
|
|
)
|
|
{
|
|
PTCHAR szProc = NULL;
|
|
HINSTANCE hInst = NULL;
|
|
PPORT_ADVANCED_DIALOG pfnAdvanced = NULL;
|
|
TCHAR szNewComName[50];
|
|
HKEY hDeviceKey;
|
|
DWORD dwSize;
|
|
TCHAR szMfg[LINE_LEN];
|
|
|
|
#ifdef UNICODE
|
|
CHAR szFunction[LINE_LEN];
|
|
#endif
|
|
|
|
szProc = _tcschr(Override, _T(','));
|
|
if (!szProc) {
|
|
return FALSE;
|
|
}
|
|
|
|
*szProc = _T('\0');
|
|
szProc++;
|
|
|
|
hInst = LoadLibrary(Override);
|
|
if (!hInst) {
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
szProc,
|
|
lstrlen(szProc) + 1,
|
|
szFunction,
|
|
sizeof(szFunction),
|
|
NULL,
|
|
NULL);
|
|
|
|
pfnAdvanced = (PPORT_ADVANCED_DIALOG) GetProcAddress(hInst, szFunction);
|
|
#else
|
|
pfnAdvanced = (PPORT_ADVANCED_DIALOG) GetProcAddress(hInst, szProc);
|
|
#endif
|
|
if (!pfnAdvanced) {
|
|
FreeLibrary(hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
_try
|
|
{
|
|
*Success = (*pfnAdvanced) (ParentHwnd,
|
|
AdvancedData->HidePolling,
|
|
AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
NULL);
|
|
|
|
}
|
|
_except(UnhandledExceptionFilter(GetExceptionInformation()))
|
|
{
|
|
*Success = FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure the new com name is zero terminated in case of error
|
|
//
|
|
AdvancedData->szComName[0] = TEXT('\0');
|
|
|
|
//
|
|
// Open the device key for the source device instance, and retrieve its
|
|
// "PortName" value in case the override dialog changed it.
|
|
//
|
|
hDeviceKey = SetupDiOpenDevRegKey(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DEV,
|
|
KEY_READ);
|
|
|
|
if (INVALID_HANDLE_VALUE != hDeviceKey) {
|
|
dwSize = sizeof(szNewComName);
|
|
if (RegQueryValueEx(hDeviceKey,
|
|
m_szPortName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE) szNewComName,
|
|
&dwSize) == ERROR_SUCCESS) {
|
|
lstrcpy(AdvancedData->szComName, szNewComName);
|
|
}
|
|
RegCloseKey(hDeviceKey);
|
|
}
|
|
|
|
FreeLibrary(hInst);
|
|
return TRUE;
|
|
}
|
|
// @@END_DDKSPLIT
|
|
|
|
/*++
|
|
|
|
Routine Description: DisplayAdvancedDialog
|
|
|
|
Opens the devices instance and checks to see if it is valid. If so, then the advanced
|
|
dialog is displayed. Otherwise a message is displayed to the user stating that the user
|
|
does not have write access to this particular key.
|
|
|
|
Arguments:
|
|
|
|
ParentHwnd - Handle to the parent dialog (Port Settings Property Sheet)
|
|
AdvancedData - hDeviceKey will be set with the device's key in the registry upon success,
|
|
INVALID_HANDLE_VALUE upon error
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
BOOL DisplayAdvancedDialog(
|
|
IN HWND ParentHwnd,
|
|
IN OUT PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
AdvancedData->hDeviceKey =
|
|
SetupDiOpenDevRegKey(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DEV,
|
|
KEY_ALL_ACCESS);
|
|
|
|
if (AdvancedData->hDeviceKey == INVALID_HANDLE_VALUE) {
|
|
MyMessageBox(ParentHwnd,
|
|
IDS_NO_WRITE_PRVILEGE,
|
|
IDS_NAME_PROPERTIES,
|
|
MB_OK | MB_ICONINFORMATION);
|
|
return FALSE;
|
|
}
|
|
else {
|
|
// @@BEGIN_DDKSPLIT
|
|
TCHAR szOverride[LINE_LEN];
|
|
BOOL success = FALSE;
|
|
|
|
if (FindAdvancedDialogOverride(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
szOverride) &&
|
|
CallAdvancedDialogOverride(ParentHwnd,
|
|
AdvancedData,
|
|
szOverride,
|
|
&success)) {
|
|
RegCloseKey(AdvancedData->hDeviceKey);
|
|
return success;
|
|
}
|
|
else {
|
|
// @@END_DDKSPLIT
|
|
return InternalAdvancedDialog(ParentHwnd, AdvancedData);
|
|
// @@BEGIN_DDKSPLIT
|
|
}
|
|
// @@END_DDKSPLIT
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: EnableFifoControls
|
|
|
|
Enables/Disables all of the controls bounded by the rectangle with the Use Fifo
|
|
checkbox.
|
|
|
|
Arguments:
|
|
|
|
hDlg - Handle to the dialog
|
|
enabled - flag to either enable/disable the controls
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void EnableFifoControls(IN HWND hDlg,
|
|
IN BOOL enabled)
|
|
{
|
|
// The actual trackbar/slider
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RECEIVE_SLIDER), enabled);
|
|
|
|
// "Low (xxx)" (Receive)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RECEIVE_LOW), enabled);
|
|
|
|
// "High (xxx)" (Receive)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RECEIVE_HIGH), enabled);
|
|
|
|
// "Receive Buffer: "
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RECEIVE_TEXT), enabled);
|
|
|
|
// "(xxx)" (Actual value of trackbar, Receive)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_RXVALUE), enabled);
|
|
|
|
// The actual trackbar/slider
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TRANSMIT_SLIDER), enabled);
|
|
|
|
// "Low (xxx)" (Transmit)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TRANSMIT_LOW), enabled);
|
|
|
|
// "High (xxx)" (Transmit)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TRANSMIT_HIGH), enabled);
|
|
|
|
// "Transmit Buffer" (Transmit)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TRANSMIT_TEXT), enabled);
|
|
|
|
// "(xxx)" (Actual value of trackbar, Trasmist)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_TXVALUE), enabled);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: HandleTrackbarChange
|
|
|
|
Whenever the user changes the trackbar thumb position, update the control
|
|
to its right which displays its actual numeric value
|
|
|
|
Arguments:
|
|
|
|
hDlg - Handle to the parent dialog
|
|
hTrackbar - Handle to the trackbar whose thumb has changed
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void HandleTrackbarChange(IN HWND hDlg,
|
|
IN HWND hTrackbar
|
|
)
|
|
{
|
|
DWORD ctrlID;
|
|
TCHAR szCurrentValue[10];
|
|
ULONG position;
|
|
|
|
position = Trackbar_GetPos(hTrackbar);
|
|
|
|
if (GetDlgCtrlID(hTrackbar) == IDC_RECEIVE_SLIDER) {
|
|
//
|
|
// Rx we need to translate the tick position from index to value
|
|
//
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), RxValues[position-1]);
|
|
ctrlID = IDC_RXVALUE;
|
|
}
|
|
else {
|
|
//
|
|
// Tx is just a straight translation between value and index
|
|
//
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), position);
|
|
ctrlID = IDC_TXVALUE;
|
|
}
|
|
SetDlgItemText(hDlg, ctrlID, szCurrentValue);
|
|
}
|
|
|
|
DWORD
|
|
RxValueToTrackbarPosition(IN OUT PDWORD RxValue
|
|
)
|
|
{
|
|
switch (*RxValue) {
|
|
case 1: return 1;
|
|
case 4: return 2;
|
|
case 8: return 3;
|
|
case 14: return 4;
|
|
}
|
|
|
|
//
|
|
// busted value
|
|
//
|
|
*RxValue = 14;
|
|
return 4;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: SetTxTrackbarTicks
|
|
|
|
Creates a tick at 1/4, half, and 3/4 across the span of the trackbar
|
|
|
|
Arguments:
|
|
|
|
hTrackbar - handle to the trackbar that will receive the ticks
|
|
minVal, maxVal - Range on the trackbar
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void
|
|
SetTxTrackbarTics(
|
|
IN HWND TrackbarHwnd
|
|
)
|
|
{
|
|
Trackbar_SetTic(TrackbarHwnd, 6);
|
|
Trackbar_SetTic(TrackbarHwnd, 11);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: SetLabelText
|
|
|
|
Sets the label's to the string identified by resID concated with the passed
|
|
in value and closing paren.
|
|
|
|
The final string is [resID string][value])
|
|
|
|
Arguments:
|
|
|
|
hLabel - handle to the control whose text is going to change
|
|
resID - resource ID for the beginning of the string that will become the
|
|
label's text
|
|
value - number to be concated into the string
|
|
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void
|
|
SetLabelText(
|
|
IN HWND LabelHwnd,
|
|
IN DWORD ResId,
|
|
IN ULONG Value
|
|
)
|
|
{
|
|
TCHAR szTemp[258], txt[258];
|
|
|
|
if (LoadString(g_hInst, ResId, szTemp, CharSizeOf(szTemp))) {
|
|
lstrcpy(txt, szTemp);
|
|
wsprintf(szTemp, _T("%d)"), Value);
|
|
lstrcat(txt, szTemp);
|
|
}
|
|
else {
|
|
lstrcpy(txt, _T("Low"));
|
|
}
|
|
SetWindowText(LabelHwnd, txt);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: InitializeControls
|
|
|
|
Initializes all of the controls that represent Fifo
|
|
|
|
Arguments:
|
|
|
|
ParentHwnd - handle to the dialog
|
|
AdvancedData - Contains all of the initial values
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void InitializeControls(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
TCHAR szCurrentValue[40];
|
|
HWND hwnd;
|
|
int i, periodIdx;
|
|
|
|
//
|
|
// Set up the Fifo buffers checkbox
|
|
//
|
|
if (!AdvancedData->UseFifoBuffersControl) {
|
|
//
|
|
// Something went wrong with the Fifo buffers control. Disable
|
|
// the checkbox
|
|
//
|
|
CheckDlgButton(ParentHwnd, IDC_FIFO, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), FALSE);
|
|
EnableFifoControls(ParentHwnd, FALSE);
|
|
}
|
|
else {
|
|
EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), TRUE);
|
|
|
|
if (!AdvancedData->UseFifoBuffers) {
|
|
EnableFifoControls(ParentHwnd, FALSE);
|
|
CheckDlgButton(ParentHwnd, IDC_FIFO, BST_UNCHECKED);
|
|
}
|
|
else {
|
|
EnableFifoControls(ParentHwnd, TRUE);
|
|
CheckDlgButton(ParentHwnd, IDC_FIFO, BST_CHECKED);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set up the sliders
|
|
//
|
|
if (!AdvancedData->UseRxFIFOControl ||
|
|
!AdvancedData->UseTxFIFOControl) {
|
|
//
|
|
// Something went wrong with the sliders.
|
|
// Disable them
|
|
//
|
|
CheckDlgButton(ParentHwnd, IDC_FIFO, BST_UNCHECKED);
|
|
EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), FALSE);
|
|
EnableFifoControls(ParentHwnd, FALSE);
|
|
}
|
|
else {
|
|
IAccPropServices * pAccPropServices = NULL;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Set up Rx Slider
|
|
//
|
|
hwnd = GetDlgItem(ParentHwnd, IDC_RECEIVE_SLIDER);
|
|
|
|
Trackbar_SetRange(hwnd, TRUE, RX_MIN, 4);
|
|
Trackbar_SetPos(hwnd,
|
|
TRUE,
|
|
RxValueToTrackbarPosition(&AdvancedData->RxFIFO));
|
|
|
|
SetLabelText(GetDlgItem(ParentHwnd, IDC_RECEIVE_LOW),
|
|
IDS_LOW,
|
|
RX_MIN);
|
|
SetLabelText(GetDlgItem(ParentHwnd, IDC_RECEIVE_HIGH),
|
|
IDS_HIGH,
|
|
AdvancedData->FifoRxMax);
|
|
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), AdvancedData->RxFIFO);
|
|
SetDlgItemText(ParentHwnd, IDC_RXVALUE, szCurrentValue);
|
|
|
|
//
|
|
// Create the mapping for this slider for accessibility
|
|
//
|
|
hr = CoCreateInstance(&CLSID_AccPropServices,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_IAccPropServices,
|
|
(PVOID *) &pAccPropServices);
|
|
|
|
if (SUCCEEDED(hr) && pAccPropServices != NULL) {
|
|
IAccPropServices_SetHwndPropStr(pAccPropServices,
|
|
hwnd,
|
|
OBJID_CLIENT,
|
|
CHILDID_SELF,
|
|
PROPID_ACC_VALUEMAP,
|
|
RxValuesStringMap);
|
|
|
|
IAccPropServices_Release(pAccPropServices);
|
|
}
|
|
|
|
//
|
|
// Set up the Tx slider
|
|
//
|
|
hwnd = GetDlgItem(ParentHwnd, IDC_TRANSMIT_SLIDER);
|
|
Trackbar_SetRange(hwnd, TRUE, TX_MIN, AdvancedData->FifoTxMax);
|
|
Trackbar_SetPos(hwnd, TRUE, AdvancedData->TxFIFO);
|
|
|
|
SetTxTrackbarTics(hwnd);
|
|
|
|
SetLabelText(GetDlgItem(ParentHwnd, IDC_TRANSMIT_LOW),
|
|
IDS_LOW,
|
|
TX_MIN);
|
|
SetLabelText(GetDlgItem(ParentHwnd, IDC_TRANSMIT_HIGH),
|
|
IDS_HIGH,
|
|
AdvancedData->FifoTxMax);
|
|
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), AdvancedData->TxFIFO);
|
|
SetDlgItemText(ParentHwnd, IDC_TXVALUE, szCurrentValue);
|
|
|
|
//
|
|
// Create the mapping for this slider for accessibility
|
|
//
|
|
hr = CoCreateInstance(&CLSID_AccPropServices,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
&IID_IAccPropServices,
|
|
(PVOID *) &pAccPropServices);
|
|
|
|
if (SUCCEEDED(hr) && pAccPropServices != NULL) {
|
|
IAccPropServices_SetHwndPropStr(pAccPropServices,
|
|
hwnd,
|
|
OBJID_CLIENT,
|
|
CHILDID_SELF,
|
|
PROPID_ACC_VALUEMAP,
|
|
TxValuesStringMap);
|
|
|
|
IAccPropServices_Release(pAccPropServices);
|
|
}
|
|
}
|
|
|
|
FillPortNameCb(ParentHwnd, AdvancedData);
|
|
|
|
if (!AdvancedData->HidePolling) {
|
|
|
|
//
|
|
// Add the descriptions for each polling period and select the current
|
|
// setting
|
|
//
|
|
hwnd = GetDlgItem(ParentHwnd, IDC_POLL_PERIOD);
|
|
periodIdx = NUM_POLLING_PERIODS;
|
|
for (i = 0; i < NUM_POLLING_PERIODS; i++) {
|
|
ComboBox_AddString(hwnd, PeriodDescription[i]);
|
|
if (PollingPeriods[i] == AdvancedData->PollingPeriod) {
|
|
periodIdx = i;
|
|
}
|
|
}
|
|
|
|
if (periodIdx == NUM_POLLING_PERIODS) {
|
|
wsprintf(szCurrentValue,
|
|
PeriodDescription[NUM_POLLING_PERIODS],
|
|
AdvancedData->PollingPeriod / SECONDS_CONVERSION_FACTOR);
|
|
ComboBox_AddString(hwnd, szCurrentValue);
|
|
}
|
|
|
|
ComboBox_SetCurSel(hwnd, periodIdx);
|
|
}
|
|
else {
|
|
ShowWindow(GetDlgItem(ParentHwnd, IDC_POLL_PERIOD), SW_HIDE);
|
|
ShowWindow(GetDlgItem(ParentHwnd, IDC_POLL_DESC), SW_HIDE);
|
|
}
|
|
} /* InitializeControls */
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: RestoreAdvancedDefaultState
|
|
|
|
Restores all values and UI to their default state, specifically:
|
|
o All Fifo related child controls are enabled
|
|
o The Rx trackbar is set to its max value
|
|
o The Tx trackbar is set to its max value
|
|
o The number of the comport is reset to its original value
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
void RestoreAdvancedDefaultState(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
USHORT ushIndex;
|
|
TCHAR szCurrentValue[10];
|
|
int i;
|
|
|
|
//
|
|
// Set up the Fifo buffers checkbox
|
|
//
|
|
EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), TRUE);
|
|
|
|
EnableFifoControls(ParentHwnd, TRUE);
|
|
CheckDlgButton(ParentHwnd, IDC_FIFO, BST_CHECKED);
|
|
|
|
//
|
|
// Set up the sliders and the static control that show their numberic value
|
|
//
|
|
Trackbar_SetPos(GetDlgItem(ParentHwnd, IDC_RECEIVE_SLIDER),
|
|
TRUE,
|
|
RxValueToTrackbarPosition(&AdvancedData->FifoRxMax));
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), AdvancedData->FifoRxMax);
|
|
SetDlgItemText(ParentHwnd, IDC_RXVALUE, szCurrentValue);
|
|
|
|
Trackbar_SetPos(GetDlgItem(ParentHwnd, IDC_TRANSMIT_SLIDER), TRUE, AdvancedData->FifoTxMax);
|
|
wsprintf(szCurrentValue, TEXT("(%d)"), AdvancedData->FifoTxMax);
|
|
SetDlgItemText(ParentHwnd, IDC_TXVALUE, szCurrentValue);
|
|
|
|
//
|
|
// Set the COM name to whatever it is currently set to in the registry
|
|
//
|
|
ushIndex =
|
|
(USHORT) ComboBox_FindString(GetDlgItem(ParentHwnd, PP_PORT_NUMBER),
|
|
-1,
|
|
AdvancedData->szComName);
|
|
|
|
ushIndex = (ushIndex == CB_ERR) ? 0 : ushIndex;
|
|
|
|
ComboBox_SetCurSel(GetDlgItem(ParentHwnd, PP_PORT_NUMBER), ushIndex);
|
|
ComboBox_SetCurSel(GetDlgItem(ParentHwnd, IDC_POLL_PERIOD), POLL_PERIOD_DEFAULT_IDX);
|
|
} /* RestoreAdvancedDefaultStates */
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description: FillPortNameCb
|
|
|
|
fill in the Port Name combo box selection with a list
|
|
of possible un-used portnames
|
|
|
|
Arguments:
|
|
|
|
poppOurPropParams: where to save the data to
|
|
hDlg: address of the window
|
|
|
|
Return Value:
|
|
|
|
ULONG: returns error messages
|
|
|
|
--*/
|
|
ULONG
|
|
FillPortNameCb(
|
|
HWND ParentHwnd,
|
|
PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
BYTE portUsage[MAX_COM_PORT/8];
|
|
DWORD tmp, portsReported;
|
|
int i, j, nEntries;
|
|
int nCurPortNum;
|
|
TCHAR szCom[40];
|
|
TCHAR szInUse[40];
|
|
char mask, *current;
|
|
HWND portHwnd;
|
|
|
|
portHwnd = GetDlgItem(ParentHwnd, PP_PORT_NUMBER);
|
|
|
|
//
|
|
// Check if our ComName is blank. If it is, disable the com port selector
|
|
//
|
|
if (_tcscmp(AdvancedData->szComName, TEXT("")) == 0) {
|
|
EnableWindow(portHwnd, FALSE);
|
|
EnableWindow(GetDlgItem(ParentHwnd, IDC_COMNUMTEXT), FALSE);
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// assumes szComPort filled in...
|
|
//
|
|
nCurPortNum = myatoi(&AdvancedData->szComName[3]);
|
|
|
|
if (!LoadString(g_hInst, IDS_IN_USE, szInUse, CharSizeOf(szInUse))) {
|
|
wcscpy(szInUse, _T(" (in use)"));
|
|
}
|
|
|
|
//
|
|
// first tally up which ports NOT to offer in list box
|
|
//
|
|
ZeroMemory(portUsage, MAX_COM_PORT/8);
|
|
|
|
if (AdvancedData->hComDB != HCOMDB_INVALID_HANDLE_VALUE) {
|
|
ComDBGetCurrentPortUsage(AdvancedData->hComDB,
|
|
portUsage,
|
|
MAX_COM_PORT / 8,
|
|
CDB_REPORT_BITS,
|
|
&portsReported);
|
|
}
|
|
|
|
//
|
|
// tag the current port as not in use so it shows up in the CB
|
|
//
|
|
current = portUsage + (nCurPortNum-1) / 8;
|
|
if ((i = nCurPortNum % 8))
|
|
*current &= ~(1 << (i-1));
|
|
else
|
|
*current &= ~(0x80);
|
|
|
|
current = portUsage;
|
|
mask = 0x1;
|
|
for(nEntries = j = 0, i = MIN_COM-1; i < MAX_COM_PORT; i++) {
|
|
|
|
wsprintf(szCom, TEXT("COM%d"), i+1);
|
|
if (*current & mask) {
|
|
wcscat(szCom, szInUse);
|
|
}
|
|
|
|
if (mask == (char) 0x80) {
|
|
mask = 0x01;
|
|
current++;
|
|
}
|
|
else {
|
|
mask <<= 1;
|
|
}
|
|
|
|
ComboBox_AddString(portHwnd, szCom);
|
|
}
|
|
|
|
ComboBox_SetCurSel(portHwnd, nCurPortNum-1);
|
|
return 0;
|
|
} /* FillPortNamesCb */
|
|
|
|
/*++
|
|
|
|
Routine Description: FillAdvancedDlg
|
|
|
|
fill in the advanced dialog window
|
|
|
|
Arguments:
|
|
|
|
poppOurPropParams: the data to fill in
|
|
ParentHwnd: address of the window
|
|
|
|
Return Value:
|
|
|
|
ULONG: returns error messages
|
|
|
|
--*/
|
|
ULONG
|
|
FillAdvancedDlg(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
PSP_DEVINFO_DATA DeviceInfoData = AdvancedData->DeviceInfoData;
|
|
HKEY hDeviceKey;
|
|
DWORD dwSize, dwData, dwFifo, dwError = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Open the device key for the source device instance
|
|
//
|
|
hDeviceKey = AdvancedData->hDeviceKey;
|
|
|
|
//
|
|
// Get COM Name
|
|
//
|
|
dwSize = sizeof(AdvancedData->szComName);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szPortName,
|
|
NULL,
|
|
NULL,
|
|
(PBYTE)AdvancedData->szComName,
|
|
&dwSize);
|
|
|
|
if (dwError != ERROR_SUCCESS) {
|
|
wsprintf(AdvancedData->szComName, TEXT("COMX"));
|
|
}
|
|
|
|
//
|
|
// Get ForceFifoEnable information
|
|
//
|
|
AdvancedData->UseFifoBuffersControl = TRUE;
|
|
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szFIFO,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->UseFifoBuffersControl = TRUE;
|
|
if (dwFifo == 0) {
|
|
AdvancedData->UseFifoBuffers = FALSE;
|
|
}
|
|
else {
|
|
AdvancedData->UseFifoBuffers = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
dwData = 1;
|
|
dwSize = sizeof(dwSize);
|
|
dwError = RegSetValueEx(hDeviceKey,
|
|
m_szFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
AdvancedData->UseFifoBuffers = TRUE;
|
|
}
|
|
else {
|
|
AdvancedData->UseFifoBuffers = FALSE;
|
|
AdvancedData->UseFifoBuffersControl = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get FifoRxMax information
|
|
//
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szFifoRxMax,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwFifo);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->FifoRxMax = dwFifo;
|
|
if (AdvancedData->FifoRxMax > RX_MAX) {
|
|
AdvancedData->FifoRxMax = RX_MAX;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
AdvancedData->FifoRxMax = RX_MAX;
|
|
}
|
|
|
|
//
|
|
// Get RxFIFO information
|
|
//
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szFifoTxMax,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->FifoTxMax = dwFifo;
|
|
if (AdvancedData->FifoTxMax > TX_MAX) {
|
|
AdvancedData->FifoTxMax = TX_MAX;
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
AdvancedData->FifoTxMax = TX_MAX;
|
|
}
|
|
|
|
//
|
|
// Get RxFIFO information
|
|
//
|
|
AdvancedData->UseRxFIFOControl = TRUE;
|
|
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szRxFIFO,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->RxFIFO = dwFifo;
|
|
if (AdvancedData->RxFIFO > RX_MAX) {
|
|
goto SetRxFIFO;
|
|
}
|
|
}
|
|
else {
|
|
SetRxFIFO:
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
dwData = AdvancedData->FifoRxMax;
|
|
dwSize = sizeof(dwData);
|
|
dwError = RegSetValueEx(hDeviceKey,
|
|
m_szRxFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
AdvancedData->RxFIFO = AdvancedData->FifoRxMax;
|
|
}
|
|
else {
|
|
AdvancedData->RxFIFO = 0;
|
|
AdvancedData->UseRxFIFOControl = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get TxFIFO information
|
|
//
|
|
AdvancedData->UseTxFIFOControl = TRUE;
|
|
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szTxFIFO,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->TxFIFO = dwFifo;
|
|
if (AdvancedData->TxFIFO > TX_MAX) {
|
|
goto SetTxFIFO;
|
|
}
|
|
}
|
|
else {
|
|
SetTxFIFO:
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
dwData = AdvancedData->FifoTxMax;
|
|
dwSize = sizeof(dwData);
|
|
dwError = RegSetValueEx(hDeviceKey,
|
|
m_szTxFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)(&dwData),
|
|
dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
AdvancedData->TxFIFO = AdvancedData->FifoTxMax;
|
|
}
|
|
else {
|
|
AdvancedData->TxFIFO = 0;
|
|
AdvancedData->UseTxFIFOControl = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get Polling Period information
|
|
//
|
|
AdvancedData->PollingPeriod = PollingPeriods[POLL_PERIOD_DEFAULT_IDX];
|
|
|
|
dwSize = sizeof(dwFifo);
|
|
dwError = RegQueryValueEx(hDeviceKey,
|
|
m_szPollingPeriod,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)(&dwFifo),
|
|
&dwSize);
|
|
|
|
if (dwError == ERROR_SUCCESS) {
|
|
//
|
|
// Save this initial value
|
|
//
|
|
AdvancedData->PollingPeriod = dwFifo;
|
|
}
|
|
else {
|
|
//
|
|
// value does not exist. Create our own
|
|
//
|
|
dwData = AdvancedData->PollingPeriod;
|
|
dwSize = sizeof(dwData);
|
|
dwError = RegSetValueEx(hDeviceKey,
|
|
m_szPollingPeriod,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)(&dwData),
|
|
dwSize);
|
|
}
|
|
|
|
RegCloseKey(hDeviceKey);
|
|
|
|
if (ERROR_SUCCESS != dwError) {
|
|
return dwError;
|
|
}
|
|
else {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
} /* FillAdvancedDlg*/
|
|
|
|
void
|
|
ChangeParentTitle(
|
|
IN HWND Hwnd,
|
|
IN LPCTSTR OldComName,
|
|
IN LPCTSTR NewComName
|
|
)
|
|
{
|
|
INT textLength, offset, newNameLen, oldNameLen;
|
|
PTCHAR oldTitle = NULL, newTitle = NULL;
|
|
PTCHAR oldLocation;
|
|
|
|
textLength = GetWindowTextLength(Hwnd);
|
|
if (textLength == 0) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Account for null char and unicode
|
|
//
|
|
textLength++;
|
|
oldTitle = (PTCHAR) LocalAlloc(LPTR, textLength * sizeof(TCHAR));
|
|
if (!oldTitle) {
|
|
return;
|
|
}
|
|
|
|
if (!GetWindowText(Hwnd, oldTitle, textLength)) {
|
|
goto exit;
|
|
}
|
|
|
|
oldLocation = wcsstr(oldTitle, OldComName);
|
|
if (!oldLocation) {
|
|
goto exit;
|
|
}
|
|
|
|
newNameLen = lstrlen(NewComName);
|
|
oldNameLen = lstrlen(OldComName);
|
|
offset = newNameLen - oldNameLen;
|
|
if (offset > 0) {
|
|
textLength += offset;
|
|
}
|
|
newTitle = (PTCHAR) LocalAlloc(LPTR, textLength * sizeof(TCHAR));
|
|
if (!newTitle) {
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Find the OldComName in the title and do the following
|
|
// 1) up to that location in the string
|
|
// 2) copy the new name
|
|
// 3) copy the remainder of the string after OldComName
|
|
//
|
|
offset = (INT)(oldLocation - oldTitle);
|
|
CopyMemory(newTitle, oldTitle, offset * sizeof(TCHAR)); // 1
|
|
CopyMemory(newTitle + offset, NewComName, newNameLen * sizeof(TCHAR)); // 2
|
|
lstrcpy(newTitle + offset + newNameLen, oldLocation + oldNameLen); // 3
|
|
|
|
SetWindowText(Hwnd, newTitle);
|
|
|
|
exit:
|
|
if (oldTitle) {
|
|
LocalFree(oldTitle);
|
|
}
|
|
if (newTitle) {
|
|
LocalFree(newTitle);
|
|
}
|
|
}
|
|
|
|
void
|
|
MigratePortSettings(
|
|
LPCTSTR OldComName,
|
|
LPCTSTR NewComName
|
|
)
|
|
{
|
|
TCHAR settings[BUFFER_SIZE];
|
|
TCHAR szNew[20], szOld[20];
|
|
|
|
lstrcpy(szOld, OldComName);
|
|
wcscat(szOld, m_szColon);
|
|
|
|
lstrcpy(szNew, NewComName);
|
|
wcscat(szNew, m_szColon);
|
|
|
|
settings[0] = TEXT('\0');
|
|
GetProfileString(m_szPorts,
|
|
szOld,
|
|
TEXT(""),
|
|
settings,
|
|
sizeof(settings) / sizeof(TCHAR) );
|
|
|
|
//
|
|
// Insert the new key based on the old one
|
|
//
|
|
if (settings[0] == TEXT('\0')) {
|
|
WriteProfileString(m_szPorts, szNew, m_szDefParams);
|
|
}
|
|
else {
|
|
WriteProfileString(m_szPorts, szNew, settings);
|
|
}
|
|
|
|
//
|
|
// Notify everybody of the changes and blow away the old key
|
|
//
|
|
SendWinIniChange((LPTSTR)m_szPorts);
|
|
WriteProfileString(m_szPorts, szOld, NULL);
|
|
}
|
|
|
|
void
|
|
EnactComNameChanges(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData,
|
|
IN HKEY hDeviceKey,
|
|
IN UINT NewComNum)
|
|
{
|
|
DWORD dwNewComNameLen;
|
|
TCHAR buffer[BUFFER_SIZE];
|
|
TCHAR szFriendlyNameFormat[LINE_LEN];
|
|
TCHAR szDeviceDesc[LINE_LEN];
|
|
PTCHAR szNewComName;
|
|
UINT i;
|
|
UINT curComNum;
|
|
BOOLEAN updateMapping = TRUE;
|
|
|
|
SP_DEVINSTALL_PARAMS spDevInstall;
|
|
|
|
curComNum = myatoi(AdvancedData->szComName + wcslen(m_szCOM));
|
|
|
|
if (AdvancedData->hComDB != HCOMDB_INVALID_HANDLE_VALUE) {
|
|
BYTE portUsage[MAX_COM_PORT/8];
|
|
DWORD portsReported;
|
|
char mask;
|
|
|
|
//
|
|
// Check to see if the desired new COM number has been claimed in the
|
|
// com name database. If so, ask the user if they are *really* sure
|
|
//
|
|
ComDBGetCurrentPortUsage(AdvancedData->hComDB,
|
|
portUsage,
|
|
MAX_COM_PORT / 8,
|
|
CDB_REPORT_BITS,
|
|
&portsReported);
|
|
|
|
if ((i = NewComNum % 8))
|
|
mask = 1 << (i-1);
|
|
else
|
|
mask = (char) 0x80;
|
|
if ((portUsage[(NewComNum-1)/8] & mask) &&
|
|
MyMessageBox(ParentHwnd, IDS_PORT_IN_USE, IDS_NAME_PROPERTIES,
|
|
MB_YESNO | MB_ICONINFORMATION) == IDNO) {
|
|
//
|
|
// Port has been previously claimed and user doesn't want to override
|
|
//
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!QueryDosDevice(AdvancedData->szComName, buffer, BUFFER_SIZE-1)) {
|
|
//
|
|
// The old com name does not exist in the mapping. Basically, the symbolic
|
|
// link from COMX => \Device\SerialY has been broken. Just change the
|
|
// value in the registry and the friendly name for the device; don't
|
|
// change the dos symbolic name b/c one does not exist
|
|
//
|
|
updateMapping = FALSE;
|
|
}
|
|
else {
|
|
TCHAR szComFileName[20]; // more than enough for "\\.\COMXxxx"
|
|
HANDLE hCom;
|
|
|
|
lstrcpy(szComFileName, L"\\\\.\\");
|
|
lstrcat(szComFileName, AdvancedData->szComName);
|
|
|
|
//
|
|
// Make sure that the port has not been opened by another application
|
|
//
|
|
hCom = CreateFile(szComFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
//
|
|
// If the file handle is invalid, then the com port is open, warn the user
|
|
//
|
|
if (hCom == INVALID_HANDLE_VALUE &&
|
|
MyMessageBox(ParentHwnd, IDS_PORT_OPEN, IDS_NAME_PROPERTIES,
|
|
MB_YESNO | MB_ICONERROR) == IDNO) {
|
|
return;
|
|
}
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(hCom);
|
|
}
|
|
}
|
|
|
|
szNewComName = AdvancedData->szNewComName;
|
|
wsprintf(szNewComName, _T("COM%d"), NewComNum);
|
|
dwNewComNameLen = ByteCountOf(wcslen(szNewComName) + 1);
|
|
|
|
//
|
|
// Change the name in the symbolic namespace.
|
|
// First try to get what device the old com name mapped to
|
|
// (ie something like \Device\Serial0). Then remove the mapping. If
|
|
// the user isn't an admin, then this will fail and the dialog will popup.
|
|
// Finally, map the new name to the old device retrieved from the
|
|
// QueryDosDevice
|
|
//
|
|
if (updateMapping) {
|
|
BOOL removed;
|
|
HKEY hSerialMap;
|
|
|
|
if (!QueryDosDevice(AdvancedData->szComName, buffer, BUFFER_SIZE-1)) {
|
|
//
|
|
// This shouldn't happen because the previous QueryDosDevice call
|
|
// succeeded
|
|
//
|
|
MyMessageBox(ParentHwnd, IDS_PORT_RENAME_ERROR, IDS_NAME_PROPERTIES,
|
|
MB_ICONERROR);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If this fails, then the following define will just replace the current
|
|
// mapping.
|
|
//
|
|
removed = DefineDosDevice(DDD_REMOVE_DEFINITION, AdvancedData->szComName, NULL);
|
|
|
|
if (!DefineDosDevice(DDD_RAW_TARGET_PATH, szNewComName, buffer)) {
|
|
//
|
|
// error, first fix up the remove definition and restore the old
|
|
// mapping
|
|
//
|
|
if (removed) {
|
|
DefineDosDevice(DDD_RAW_TARGET_PATH, AdvancedData->szComName, buffer);
|
|
}
|
|
|
|
MyMessageBox(ParentHwnd, IDS_PORT_RENAME_ERROR, IDS_NAME_PROPERTIES,
|
|
MB_ICONERROR);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Set the \\HARDWARE\DEVICEMAP\SERIALCOMM field
|
|
//
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
m_szRegSerialMap,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hSerialMap) == ERROR_SUCCESS) {
|
|
|
|
TCHAR szSerial[BUFFER_SIZE];
|
|
DWORD dwSerialSize, dwEnum, dwType, dwComSize;
|
|
TCHAR szCom[BUFFER_SIZE];
|
|
|
|
i = 0;
|
|
do {
|
|
dwSerialSize = CharSizeOf(szSerial);
|
|
dwComSize = sizeof(szCom);
|
|
dwEnum = RegEnumValue(hSerialMap,
|
|
i++,
|
|
szSerial,
|
|
&dwSerialSize,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szCom,
|
|
&dwComSize);
|
|
|
|
if (dwEnum == ERROR_SUCCESS) {
|
|
if(dwType != REG_SZ)
|
|
continue;
|
|
|
|
if (wcscmp(szCom, AdvancedData->szComName) == 0) {
|
|
RegSetValueEx(hSerialMap,
|
|
szSerial,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) szNewComName,
|
|
dwNewComNameLen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
} while (dwEnum == ERROR_SUCCESS);
|
|
}
|
|
|
|
RegCloseKey(hSerialMap);
|
|
}
|
|
|
|
//
|
|
// Update the com db
|
|
//
|
|
if (AdvancedData->hComDB != HCOMDB_INVALID_HANDLE_VALUE) {
|
|
ComDBReleasePort(AdvancedData->hComDB, (DWORD) curComNum);
|
|
|
|
ComDBClaimPort(AdvancedData->hComDB, (DWORD) NewComNum, TRUE, NULL);
|
|
}
|
|
|
|
//
|
|
// Set the friendly name in the form of DeviceDesc (COM#)
|
|
//
|
|
if (LoadString(g_hInst,
|
|
IDS_FRIENDLY_FORMAT,
|
|
szFriendlyNameFormat,
|
|
CharSizeOf(szFriendlyNameFormat)) &&
|
|
SetupDiGetDeviceRegistryProperty(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
SPDRP_DEVICEDESC,
|
|
NULL,
|
|
(PBYTE) szDeviceDesc,
|
|
sizeof(szDeviceDesc),
|
|
NULL)) {
|
|
wsprintf(buffer, szFriendlyNameFormat, szDeviceDesc, szNewComName);
|
|
}
|
|
else {
|
|
//
|
|
// Use the COM port name straight out
|
|
//
|
|
lstrcpy(buffer, szNewComName);
|
|
}
|
|
|
|
SetupDiSetDeviceRegistryProperty(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
SPDRP_FRIENDLYNAME,
|
|
(PBYTE) buffer,
|
|
ByteCountOf(wcslen(buffer)+1));
|
|
|
|
//
|
|
// Set the parent dialog's title to reflect the change in the com port's name
|
|
//
|
|
ChangeParentTitle(GetParent(ParentHwnd), AdvancedData->szComName, szNewComName);
|
|
MigratePortSettings(AdvancedData->szComName, szNewComName);
|
|
|
|
//
|
|
// Update the PortName value in the devnode
|
|
//
|
|
RegSetValueEx(hDeviceKey,
|
|
m_szPortName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)szNewComName,
|
|
dwNewComNameLen);
|
|
|
|
//
|
|
// Now broadcast this change to the device manager
|
|
//
|
|
ZeroMemory(&spDevInstall, sizeof(SP_DEVINSTALL_PARAMS));
|
|
spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
|
|
if (SetupDiGetDeviceInstallParams(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
&spDevInstall)) {
|
|
spDevInstall.Flags |= DI_PROPERTIES_CHANGE;
|
|
SetupDiSetDeviceInstallParams(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
&spDevInstall);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description: SaveAdvancedSettings
|
|
|
|
saves the advanced box settings back to the registry, if any were
|
|
changed
|
|
|
|
Arguments:
|
|
|
|
AdvancedData: holds the current settings and the location of of
|
|
the device in the registry
|
|
ParentHwnd: address of the window
|
|
|
|
Return Value:
|
|
|
|
ULONG: returns error messages
|
|
|
|
--*/
|
|
ULONG
|
|
SaveAdvancedSettings(
|
|
IN HWND ParentHwnd,
|
|
IN PADVANCED_DATA AdvancedData
|
|
)
|
|
{
|
|
HKEY hDeviceKey;
|
|
DWORD dwSize, dwData;
|
|
|
|
UINT i = CB_ERR, curComNum, newComNum = CB_ERR;
|
|
UINT uiDlgButtonChecked;
|
|
DWORD dwRxPosition, dwTxPosition, dwPollingPeriod;
|
|
|
|
SP_DEVINSTALL_PARAMS spDevInstall;
|
|
|
|
//
|
|
// Grab all of the new settings
|
|
//
|
|
|
|
uiDlgButtonChecked = IsDlgButtonChecked(ParentHwnd, IDC_FIFO);
|
|
|
|
dwTxPosition = Trackbar_GetPos(GetDlgItem(ParentHwnd, IDC_TRANSMIT_SLIDER));
|
|
dwRxPosition = Trackbar_GetPos(GetDlgItem(ParentHwnd, IDC_RECEIVE_SLIDER));
|
|
|
|
//
|
|
// Index is actually into the array of values
|
|
//
|
|
dwRxPosition = RxValues[dwRxPosition-1];
|
|
|
|
curComNum = myatoi(AdvancedData->szComName + wcslen(m_szCOM));
|
|
newComNum = ComboBox_GetCurSel(GetDlgItem(ParentHwnd, PP_PORT_NUMBER));
|
|
|
|
if (newComNum == CB_ERR) {
|
|
newComNum = curComNum;
|
|
}
|
|
else {
|
|
newComNum++;
|
|
}
|
|
|
|
i = ComboBox_GetCurSel(GetDlgItem(ParentHwnd, IDC_POLL_PERIOD));
|
|
|
|
if (i == CB_ERR || i >= NUM_POLLING_PERIODS) {
|
|
dwPollingPeriod = AdvancedData->PollingPeriod;
|
|
}
|
|
else {
|
|
dwPollingPeriod = PollingPeriods[i];
|
|
}
|
|
|
|
//
|
|
// See if they changed anything
|
|
//
|
|
if (((AdvancedData->UseFifoBuffers && uiDlgButtonChecked == BST_CHECKED) ||
|
|
(!AdvancedData->UseFifoBuffers && uiDlgButtonChecked == BST_UNCHECKED)) &&
|
|
AdvancedData->RxFIFO == dwRxPosition &&
|
|
AdvancedData->TxFIFO == dwTxPosition &&
|
|
AdvancedData->PollingPeriod == dwPollingPeriod &&
|
|
newComNum == curComNum) {
|
|
//
|
|
// They didn't change anything. Just exit.
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Open the device key for the source device instance
|
|
//
|
|
hDeviceKey = SetupDiOpenDevRegKey(AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData,
|
|
DICS_FLAG_GLOBAL,
|
|
0,
|
|
DIREG_DEV,
|
|
KEY_ALL_ACCESS);
|
|
|
|
if (INVALID_HANDLE_VALUE == hDeviceKey) {
|
|
//
|
|
// Not much we can do without a valid key, exit gracefully
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Check to see if the user changed the COM port name
|
|
//
|
|
if (newComNum != curComNum) {
|
|
EnactComNameChanges(ParentHwnd,
|
|
AdvancedData,
|
|
hDeviceKey,
|
|
newComNum);
|
|
}
|
|
|
|
|
|
if ((AdvancedData->UseFifoBuffers && uiDlgButtonChecked == BST_UNCHECKED) ||
|
|
(!AdvancedData->UseFifoBuffers && uiDlgButtonChecked == BST_CHECKED)) {
|
|
//
|
|
// They changed the Use Fifo checkbox.
|
|
//
|
|
dwData = (uiDlgButtonChecked == BST_CHECKED) ? 1 : 0;
|
|
dwSize = sizeof(dwData);
|
|
RegSetValueEx(hDeviceKey,
|
|
m_szFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
}
|
|
|
|
if (AdvancedData->RxFIFO != dwRxPosition) {
|
|
//
|
|
// They changed the RxFIFO setting
|
|
//
|
|
dwData = dwRxPosition;
|
|
dwSize = sizeof(dwData);
|
|
RegSetValueEx(hDeviceKey,
|
|
m_szRxFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
}
|
|
|
|
if (AdvancedData->TxFIFO != dwTxPosition) {
|
|
//
|
|
// They changed the TxFIFO setting
|
|
//
|
|
dwData = dwTxPosition;
|
|
dwSize = sizeof(dwData);
|
|
RegSetValueEx(hDeviceKey,
|
|
m_szTxFIFO,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
}
|
|
|
|
if (AdvancedData->PollingPeriod != dwPollingPeriod) {
|
|
//
|
|
// They changed the polling period
|
|
//
|
|
dwData = dwPollingPeriod;
|
|
dwSize = sizeof(dwData);
|
|
RegSetValueEx(hDeviceKey,
|
|
m_szPollingPeriod,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE *)(&dwData),
|
|
dwSize);
|
|
|
|
//
|
|
// Don't really care if this fails, nothing else we can do
|
|
//
|
|
CM_Reenumerate_DevNode(AdvancedData->DeviceInfoData->DevInst,
|
|
CM_REENUMERATE_NORMAL);
|
|
}
|
|
|
|
RegCloseKey(hDeviceKey);
|
|
|
|
SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
|
|
AdvancedData->DeviceInfoSet,
|
|
AdvancedData->DeviceInfoData);
|
|
|
|
return ERROR_SUCCESS;
|
|
} /* SaveAdvancedSettings*/
|
|
|
|
|