windows-nt/Source/XPSP1/NT/shell/osshell/cpls/ports/advandlg.c
2020-09-26 16:20:57 +08:00

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*/