1259 lines
29 KiB
C
1259 lines
29 KiB
C
|
/*----------------------------------------------------------------------
|
||
|
file: pp.c - property page
|
||
|
|
||
|
@@BEGIN_DDKSPLIT
|
||
|
|
||
|
ToDo_NT50
|
||
|
{
|
||
|
* Bug?: DIF_MOVEDEVICE in class installer opens reg key as READ access
|
||
|
to perform a write.(ports.c)
|
||
|
}
|
||
|
|
||
|
* History:
|
||
|
7-29-97 - Add this module for NT5.0, kpb
|
||
|
|
||
|
@@END_DDKSPLIT
|
||
|
----------------------------------------------------------------------*/
|
||
|
#include "ports.h"
|
||
|
#include "pp.h"
|
||
|
|
||
|
// @@BEGIN_DDKSPLIT
|
||
|
BOOL
|
||
|
IsUserAdmin(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns TRUE if the caller's process is a
|
||
|
member of the Administrators local group.
|
||
|
|
||
|
Caller is NOT expected to be impersonating anyone and IS
|
||
|
expected to be able to open their own process and process
|
||
|
token.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE - Caller has Administrators local group.
|
||
|
|
||
|
FALSE - Caller does not have Administrators local group.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
HANDLE Token;
|
||
|
DWORD BytesRequired;
|
||
|
PTOKEN_GROUPS Groups;
|
||
|
BOOL b;
|
||
|
DWORD i;
|
||
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
|
PSID AdministratorsGroup;
|
||
|
|
||
|
//
|
||
|
// Open the process token.
|
||
|
//
|
||
|
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&Token)) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
b = FALSE;
|
||
|
Groups = NULL;
|
||
|
|
||
|
//
|
||
|
// Get group information.
|
||
|
//
|
||
|
if(!GetTokenInformation(Token,TokenGroups,NULL,0,&BytesRequired)
|
||
|
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||
|
&& (Groups = (PTOKEN_GROUPS)LocalAlloc(LMEM_FIXED,BytesRequired))
|
||
|
&& GetTokenInformation(Token,TokenGroups,Groups,BytesRequired,&BytesRequired)) {
|
||
|
|
||
|
b = AllocateAndInitializeSid(
|
||
|
&NtAuthority,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0, 0, 0, 0, 0, 0,
|
||
|
&AdministratorsGroup
|
||
|
);
|
||
|
|
||
|
if(b) {
|
||
|
|
||
|
//
|
||
|
// See if the user has the administrator group.
|
||
|
//
|
||
|
b = FALSE;
|
||
|
for(i=0; i<Groups->GroupCount; i++) {
|
||
|
if(EqualSid(Groups->Groups[i].Sid,AdministratorsGroup)) {
|
||
|
b = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FreeSid(AdministratorsGroup);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Clean up and return.
|
||
|
//
|
||
|
|
||
|
if(Groups) {
|
||
|
LocalFree(Groups);
|
||
|
}
|
||
|
|
||
|
CloseHandle(Token);
|
||
|
|
||
|
return(b);
|
||
|
}
|
||
|
// @@END_DDKSPLIT
|
||
|
|
||
|
TCHAR m_szDevMgrHelp[] = _T("devmgr.hlp");
|
||
|
|
||
|
const DWORD HelpIDs[]=
|
||
|
{
|
||
|
IDC_STATIC, IDH_NOHELP,
|
||
|
IDC_ADVANCED, IDH_DEVMGR_PORTSET_ADVANCED, // "&Advanced" (Button)
|
||
|
PP_PORT_BAUDRATE, IDH_DEVMGR_PORTSET_BPS, // "" (ComboBox)
|
||
|
PP_PORT_DATABITS, IDH_DEVMGR_PORTSET_DATABITS, // "" (ComboBox)
|
||
|
PP_PORT_PARITY, IDH_DEVMGR_PORTSET_PARITY, // "" (ComboBox)
|
||
|
PP_PORT_STOPBITS, IDH_DEVMGR_PORTSET_STOPBITS, // "" (ComboBox)
|
||
|
PP_PORT_FLOWCTL, IDH_DEVMGR_PORTSET_FLOW, // "" (ComboBox)
|
||
|
IDC_RESTORE_PORT, IDH_DEVMGR_PORTSET_DEFAULTS, // "&Restore Defaults" (Button)
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
void InitPortParams(
|
||
|
IN OUT PPORT_PARAMS Params,
|
||
|
IN HDEVINFO DeviceInfoSet,
|
||
|
IN PSP_DEVINFO_DATA DeviceInfoData
|
||
|
)
|
||
|
{
|
||
|
BOOL showAdvanced = TRUE;
|
||
|
SP_DEVINFO_LIST_DETAIL_DATA detailData;
|
||
|
|
||
|
ZeroMemory(Params, sizeof(PORT_PARAMS));
|
||
|
|
||
|
Params->DeviceInfoSet = DeviceInfoSet;
|
||
|
Params->DeviceInfoData = DeviceInfoData;
|
||
|
Params->ChangesEnabled = TRUE;
|
||
|
|
||
|
//
|
||
|
// Now we know how big our structure is, so we can allocate memory
|
||
|
//
|
||
|
Params->pAdvancedData =
|
||
|
(PADVANCED_DATA) LocalAlloc(LPTR, sizeof(ADVANCED_DATA));
|
||
|
|
||
|
if (Params->pAdvancedData == NULL) {
|
||
|
//
|
||
|
// Not enough memory
|
||
|
//
|
||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
showAdvanced = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Params->pAdvancedData->HidePolling = FALSE;
|
||
|
}
|
||
|
//
|
||
|
// See if we are being invoked locally or over the network. If over the net,
|
||
|
// then disable all possible changes.
|
||
|
//
|
||
|
detailData.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
|
||
|
if (SetupDiGetDeviceInfoListDetail(DeviceInfoSet, &detailData) &&
|
||
|
detailData.RemoteMachineHandle != NULL) {
|
||
|
showAdvanced = FALSE;
|
||
|
Params->ChangesEnabled = FALSE;
|
||
|
}
|
||
|
|
||
|
// @@BEGIN_DDKSPLIT
|
||
|
//
|
||
|
// The user can still change the buadrate etc b/c it is written to some
|
||
|
// magic place in the registry, not into the devnode
|
||
|
//
|
||
|
if (!IsUserAdmin()) {
|
||
|
showAdvanced = FALSE;
|
||
|
}
|
||
|
// @@END_DDKSPLIT
|
||
|
|
||
|
if (Params->pAdvancedData)
|
||
|
{
|
||
|
Params->pAdvancedData->DeviceInfoSet = DeviceInfoSet;
|
||
|
Params->pAdvancedData->DeviceInfoData = DeviceInfoData;
|
||
|
}
|
||
|
|
||
|
Params->ShowAdvanced = showAdvanced;
|
||
|
}
|
||
|
|
||
|
HPROPSHEETPAGE InitSettingsPage(PROPSHEETPAGE * psp,
|
||
|
OUT PPORT_PARAMS Params)
|
||
|
{
|
||
|
//
|
||
|
// Add the Port Settings property page
|
||
|
//
|
||
|
psp->dwSize = sizeof(PROPSHEETPAGE);
|
||
|
psp->dwFlags = PSP_USECALLBACK; // | PSP_HASHELP;
|
||
|
psp->hInstance = g_hInst;
|
||
|
psp->pszTemplate = MAKEINTRESOURCE(DLG_PP_PORTSETTINGS);
|
||
|
|
||
|
//
|
||
|
// following points to the dlg window proc
|
||
|
//
|
||
|
psp->pfnDlgProc = PortSettingsDlgProc;
|
||
|
psp->lParam = (LPARAM) Params;
|
||
|
|
||
|
//
|
||
|
// following points to some control callback of the dlg window proc
|
||
|
//
|
||
|
psp->pfnCallback = PortSettingsDlgCallback;
|
||
|
|
||
|
//
|
||
|
// allocate our "Ports Setting" sheet
|
||
|
//
|
||
|
return CreatePropertySheetPage(psp);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: SerialPortPropPageProvider
|
||
|
|
||
|
Entry-point for adding additional device manager property
|
||
|
sheet pages. Registry specifies this routine under
|
||
|
Control\Class\PortNode::EnumPropPage32="msports.dll,thisproc"
|
||
|
entry. This entry-point gets called only when the Device
|
||
|
Manager asks for additional property pages.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Info - points to PROPSHEETPAGE_REQUEST, see setupapi.h
|
||
|
AddFunc - function ptr to call to add sheet.
|
||
|
Lparam - add sheet functions private data handle.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOL: FALSE if pages could not be added, TRUE on success
|
||
|
|
||
|
--*/
|
||
|
BOOL APIENTRY SerialPortPropPageProvider(LPVOID Info,
|
||
|
LPFNADDPROPSHEETPAGE AddFunc,
|
||
|
LPARAM Lparam
|
||
|
)
|
||
|
{
|
||
|
PSP_PROPSHEETPAGE_REQUEST pprPropPageRequest;
|
||
|
PROPSHEETPAGE psp;
|
||
|
HPROPSHEETPAGE hpsp;
|
||
|
PPORT_PARAMS params = NULL;
|
||
|
|
||
|
pprPropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) Info;
|
||
|
|
||
|
if (PortTypeSerial !=
|
||
|
GetPortType(pprPropPageRequest->DeviceInfoSet,
|
||
|
pprPropPageRequest->DeviceInfoData,
|
||
|
FALSE)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate and zero out memory for the struct that will contain
|
||
|
// page specific data
|
||
|
//
|
||
|
params = (PPORT_PARAMS) LocalAlloc(LPTR, sizeof(PORT_PARAMS));
|
||
|
|
||
|
if (!params) {
|
||
|
ErrMemDlg(GetFocus());
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (pprPropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) {
|
||
|
InitPortParams(params,
|
||
|
pprPropPageRequest->DeviceInfoSet,
|
||
|
pprPropPageRequest->DeviceInfoData);
|
||
|
|
||
|
hpsp = InitSettingsPage(&psp, params);
|
||
|
|
||
|
if (!hpsp) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!(*AddFunc)(hpsp, Lparam)) {
|
||
|
DestroyPropertySheetPage(hpsp);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
} /* SerialPortPropPageProvider */
|
||
|
|
||
|
|
||
|
UINT CALLBACK
|
||
|
PortSettingsDlgCallback(HWND hwnd,
|
||
|
UINT uMsg,
|
||
|
LPPROPSHEETPAGE ppsp)
|
||
|
{
|
||
|
PPORT_PARAMS params;
|
||
|
|
||
|
switch (uMsg) {
|
||
|
case PSPCB_CREATE:
|
||
|
return TRUE; // return TRUE to continue with creation of page
|
||
|
|
||
|
case PSPCB_RELEASE:
|
||
|
params = (PPORT_PARAMS) ppsp->lParam;
|
||
|
if (params->pAdvancedData) {
|
||
|
LocalFree(params->pAdvancedData);
|
||
|
}
|
||
|
LocalFree(params);
|
||
|
|
||
|
return 0; // return value ignored
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Port_OnCommand(
|
||
|
HWND DialogHwnd,
|
||
|
int ControlId,
|
||
|
HWND ControlHwnd,
|
||
|
UINT NotifyCode
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
Port_OnContextMenu(
|
||
|
HWND HwndControl,
|
||
|
WORD Xpos,
|
||
|
WORD Ypos
|
||
|
);
|
||
|
|
||
|
void
|
||
|
Port_OnHelp(
|
||
|
HWND DialogHwnd,
|
||
|
LPHELPINFO HelpInfo
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
Port_OnInitDialog(
|
||
|
HWND DialogHwnd,
|
||
|
HWND FocusHwnd,
|
||
|
LPARAM Lparam
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
Port_OnNotify(
|
||
|
HWND DialogHwnd,
|
||
|
LPNMHDR NmHdr
|
||
|
);
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: PortSettingsDlgProc
|
||
|
|
||
|
The windows control function for the Port Settings properties window
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg, uMessage, wParam, lParam: standard windows DlgProc parameters
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOL: FALSE if function fails, TRUE if function passes
|
||
|
|
||
|
--*/
|
||
|
INT_PTR APIENTRY
|
||
|
PortSettingsDlgProc(IN HWND hDlg,
|
||
|
IN UINT uMessage,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam)
|
||
|
{
|
||
|
switch(uMessage) {
|
||
|
case WM_COMMAND:
|
||
|
Port_OnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
return Port_OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
|
||
|
|
||
|
case WM_HELP:
|
||
|
Port_OnHelp(hDlg, (LPHELPINFO) lParam);
|
||
|
break;
|
||
|
|
||
|
case WM_INITDIALOG:
|
||
|
return Port_OnInitDialog(hDlg, (HWND)wParam, lParam);
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
return Port_OnNotify(hDlg, (NMHDR *)lParam);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
} /* PortSettingsDialogProc */
|
||
|
|
||
|
void
|
||
|
Port_OnAdvancedClicked(
|
||
|
HWND DialogHwnd,
|
||
|
PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Initialize the new COM name with the current COM name
|
||
|
//
|
||
|
lstrcpy(Params->pAdvancedData->szNewComName,
|
||
|
Params->PortSettings.szComName);
|
||
|
|
||
|
if (DisplayAdvancedDialog(DialogHwnd, Params->pAdvancedData)) {
|
||
|
//
|
||
|
// Only update if there is a change
|
||
|
//
|
||
|
if (_tcscmp(Params->pAdvancedData->szNewComName,
|
||
|
Params->PortSettings.szComName) != 0) {
|
||
|
lstrcpy(Params->PortSettings.szComName,
|
||
|
Params->pAdvancedData->szNewComName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Port_OnRestorePortClicked(
|
||
|
HWND DialogHwnd,
|
||
|
PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
RestorePortSettings(DialogHwnd, Params);
|
||
|
PropSheet_Changed(GetParent(DialogHwnd), DialogHwnd);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Port_OnCommand(
|
||
|
HWND DialogHwnd,
|
||
|
int ControlId,
|
||
|
HWND ControlHwnd,
|
||
|
UINT NotifyCode
|
||
|
)
|
||
|
{
|
||
|
PPORT_PARAMS params = (PPORT_PARAMS)GetWindowLongPtr(DialogHwnd, DWLP_USER);
|
||
|
|
||
|
if (NotifyCode == CBN_SELCHANGE) {
|
||
|
PropSheet_Changed(GetParent(DialogHwnd), DialogHwnd);
|
||
|
}
|
||
|
else {
|
||
|
switch (ControlId) {
|
||
|
case IDC_ADVANCED:
|
||
|
Port_OnAdvancedClicked(DialogHwnd, params);
|
||
|
break;
|
||
|
|
||
|
case IDC_RESTORE_PORT:
|
||
|
Port_OnRestorePortClicked(DialogHwnd, params);
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// Because this is a prop sheet, we should never get this.
|
||
|
// All notifications for ctrols outside of the sheet come through
|
||
|
// WM_NOTIFY
|
||
|
//
|
||
|
case IDCANCEL:
|
||
|
EndDialog(DialogHwnd, 0);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
Port_OnContextMenu(
|
||
|
HWND HwndControl,
|
||
|
WORD Xpos,
|
||
|
WORD Ypos
|
||
|
)
|
||
|
{
|
||
|
WinHelp(HwndControl,
|
||
|
m_szDevMgrHelp,
|
||
|
HELP_CONTEXTMENU,
|
||
|
(ULONG_PTR) HelpIDs);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Port_OnHelp(
|
||
|
HWND DialogHwnd,
|
||
|
LPHELPINFO HelpInfo
|
||
|
)
|
||
|
{
|
||
|
if (HelpInfo->iContextType == HELPINFO_WINDOW) {
|
||
|
WinHelp((HWND) HelpInfo->hItemHandle,
|
||
|
m_szDevMgrHelp,
|
||
|
HELP_WM_HELP,
|
||
|
(ULONG_PTR) HelpIDs);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
Port_OnInitDialog(
|
||
|
HWND DialogHwnd,
|
||
|
HWND FocusHwnd,
|
||
|
LPARAM Lparam
|
||
|
)
|
||
|
{
|
||
|
PPORT_PARAMS params;
|
||
|
|
||
|
//
|
||
|
// on WM_INITDIALOG call, lParam points to the property
|
||
|
// sheet page.
|
||
|
//
|
||
|
// The lParam field in the property sheet page struct is set by the
|
||
|
// caller. When I created the property sheet, I passed in a pointer
|
||
|
// to a struct containing information about the device. Save this in
|
||
|
// the user window long so I can access it on later messages.
|
||
|
//
|
||
|
params = (PPORT_PARAMS) ((LPPROPSHEETPAGE)Lparam)->lParam;
|
||
|
SetWindowLongPtr(DialogHwnd, DWLP_USER, (ULONG_PTR) params);
|
||
|
|
||
|
//
|
||
|
// Set up the combo boxes with choices
|
||
|
//
|
||
|
FillCommDlg(DialogHwnd);
|
||
|
|
||
|
//
|
||
|
// Read current settings
|
||
|
//
|
||
|
FillPortSettingsDlg(DialogHwnd, params);
|
||
|
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, IDC_ADVANCED),
|
||
|
params->ShowAdvanced);
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, IDC_RESTORE_PORT),
|
||
|
params->ChangesEnabled);
|
||
|
|
||
|
return TRUE; // No need for us to set the focus.
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
Port_OnNotify(
|
||
|
HWND DialogHwnd,
|
||
|
LPNMHDR NmHdr
|
||
|
)
|
||
|
{
|
||
|
PPORT_PARAMS params = (PPORT_PARAMS)GetWindowLongPtr(DialogHwnd, DWLP_USER);
|
||
|
|
||
|
switch (NmHdr->code) {
|
||
|
//
|
||
|
// Sent when the user clicks on Apply OR OK !!
|
||
|
//
|
||
|
case PSN_APPLY:
|
||
|
//
|
||
|
// Write out the com port options to the registry
|
||
|
//
|
||
|
SavePortSettingsDlg(DialogHwnd, params);
|
||
|
SetWindowLongPtr(DialogHwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
|
||
|
return TRUE;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
SetCBFromRes(
|
||
|
HWND HwndCB,
|
||
|
DWORD ResId,
|
||
|
DWORD Default,
|
||
|
BOOL CheckDecimal)
|
||
|
{
|
||
|
TCHAR szTemp[258], szDecSep[2], cSep;
|
||
|
LPTSTR pThis, pThat, pDecSep;
|
||
|
int iRV;
|
||
|
|
||
|
if (CheckDecimal) {
|
||
|
iRV = GetLocaleInfo(GetUserDefaultLCID(), LOCALE_SDECIMAL,szDecSep,2);
|
||
|
|
||
|
if (iRV == 0) {
|
||
|
//
|
||
|
// following code can take only one char for decimal separator,
|
||
|
// better leave the point as separator
|
||
|
//
|
||
|
CheckDecimal = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!LoadString(g_hInst, ResId, szTemp, CharSizeOf(szTemp)))
|
||
|
return;
|
||
|
|
||
|
for (pThis = szTemp, cSep = *pThis++; pThis; pThis = pThat) {
|
||
|
if (pThat = _tcschr( pThis, cSep))
|
||
|
*pThat++ = TEXT('\0');
|
||
|
|
||
|
if(CheckDecimal) {
|
||
|
//
|
||
|
// Assume dec separator in resource is '.', comment was put to this
|
||
|
// effect
|
||
|
//
|
||
|
pDecSep = _tcschr(pThis,TEXT('.'));
|
||
|
if (pDecSep) {
|
||
|
//
|
||
|
// assume decimal sep width == 1
|
||
|
//
|
||
|
*pDecSep = *szDecSep;
|
||
|
}
|
||
|
}
|
||
|
SendMessage(HwndCB, CB_ADDSTRING, 0, (LPARAM) pThis);
|
||
|
}
|
||
|
|
||
|
SendMessage(HwndCB, CB_SETCURSEL, Default, 0L);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: FillCommDlg
|
||
|
|
||
|
Fill in baud rate, parity, etc in port dialog box
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg: the window address
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOL: FALSE if function fails, TRUE if function passes
|
||
|
|
||
|
--*/
|
||
|
BOOL
|
||
|
FillCommDlg(
|
||
|
HWND DialogHwnd
|
||
|
)
|
||
|
{
|
||
|
SHORT shIndex;
|
||
|
TCHAR szTemp[81];
|
||
|
|
||
|
//
|
||
|
// just list all of the baud rates
|
||
|
//
|
||
|
for(shIndex = 0; m_nBaudRates[shIndex]; shIndex++) {
|
||
|
MyItoa(m_nBaudRates[shIndex], szTemp, 10);
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_ADDSTRING,
|
||
|
0,
|
||
|
(LPARAM)szTemp);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set 9600 as default baud selection
|
||
|
//
|
||
|
shIndex = (USHORT) SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_FINDSTRING,
|
||
|
(WPARAM)-1,
|
||
|
(LPARAM)m_sz9600);
|
||
|
|
||
|
shIndex = (shIndex == CB_ERR) ? 0 : shIndex;
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_SETCURSEL,
|
||
|
shIndex,
|
||
|
0L);
|
||
|
|
||
|
for(shIndex = 0; m_nDataBits[shIndex]; shIndex++) {
|
||
|
MyItoa(m_nDataBits[shIndex], szTemp, 10);
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_DATABITS,
|
||
|
CB_ADDSTRING,
|
||
|
0,
|
||
|
(LPARAM)szTemp);
|
||
|
}
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_DATABITS,
|
||
|
CB_SETCURSEL,
|
||
|
DEF_WORD,
|
||
|
0L);
|
||
|
|
||
|
SetCBFromRes(GetDlgItem(DialogHwnd, PP_PORT_PARITY),
|
||
|
IDS_PARITY,
|
||
|
DEF_PARITY,
|
||
|
FALSE);
|
||
|
|
||
|
SetCBFromRes(GetDlgItem(DialogHwnd, PP_PORT_STOPBITS),
|
||
|
IDS_BITS,
|
||
|
DEF_STOP,
|
||
|
TRUE);
|
||
|
|
||
|
SetCBFromRes(GetDlgItem(DialogHwnd, PP_PORT_FLOWCTL),
|
||
|
IDS_FLOWCONTROL,
|
||
|
DEF_SHAKE,
|
||
|
FALSE);
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} /* FillCommDlg */
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: FillPortSettingsDlg
|
||
|
|
||
|
fill in the port settings dlg sheet
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
params: the data to fill in
|
||
|
hDlg: address of the window
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ULONG: returns error messages
|
||
|
|
||
|
--*/
|
||
|
ULONG
|
||
|
FillPortSettingsDlg(
|
||
|
IN HWND DialogHwnd,
|
||
|
IN PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
HKEY hDeviceKey;
|
||
|
DWORD dwPortNameSize, dwError;
|
||
|
TCHAR szCharBuffer[81];
|
||
|
|
||
|
//
|
||
|
// Open the device key for the source device instance, and retrieve its
|
||
|
// "PortName" value.
|
||
|
//
|
||
|
hDeviceKey = SetupDiOpenDevRegKey(Params->DeviceInfoSet,
|
||
|
Params->DeviceInfoData,
|
||
|
DICS_FLAG_GLOBAL,
|
||
|
0,
|
||
|
DIREG_DEV,
|
||
|
KEY_READ);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hDeviceKey) {
|
||
|
goto RetGetLastError;
|
||
|
}
|
||
|
|
||
|
dwPortNameSize = sizeof(Params->PortSettings.szComName);
|
||
|
dwError = RegQueryValueEx(hDeviceKey,
|
||
|
m_szPortName, // "PortName"
|
||
|
NULL,
|
||
|
NULL,
|
||
|
(PBYTE)Params->PortSettings.szComName,
|
||
|
&dwPortNameSize);
|
||
|
|
||
|
RegCloseKey(hDeviceKey);
|
||
|
|
||
|
if(ERROR_SUCCESS != dwError) {
|
||
|
goto RetERROR;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// create "com#:"
|
||
|
//
|
||
|
lstrcpy(szCharBuffer, Params->PortSettings.szComName);
|
||
|
lstrcat(szCharBuffer, m_szColon);
|
||
|
|
||
|
//
|
||
|
// get values from system, fills in baudrate, parity, etc.
|
||
|
//
|
||
|
GetPortSettings(DialogHwnd, szCharBuffer, Params);
|
||
|
|
||
|
if (!Params->ChangesEnabled) {
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, PP_PORT_BAUDRATE), FALSE);
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, PP_PORT_PARITY), FALSE);
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, PP_PORT_DATABITS), FALSE);
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, PP_PORT_STOPBITS), FALSE);
|
||
|
EnableWindow(GetDlgItem(DialogHwnd, PP_PORT_FLOWCTL), FALSE);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
RetERROR:
|
||
|
return dwError;
|
||
|
|
||
|
RetGetLastError:
|
||
|
return GetLastError();
|
||
|
} /* FillPortSettingsDlg */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: GetPortSettings
|
||
|
|
||
|
Read in port settings from the system
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DialogHwnd: address of the window
|
||
|
ComName: the port we're dealing with
|
||
|
Params: where to put the information we're getting
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ULONG: returns error messages
|
||
|
|
||
|
--*/
|
||
|
void
|
||
|
GetPortSettings(
|
||
|
IN HWND DialogHwnd,
|
||
|
IN PTCHAR ComName,
|
||
|
IN PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
TCHAR szParms[81];
|
||
|
PTCHAR szCur, szNext;
|
||
|
int nIndex;
|
||
|
int nBaud;
|
||
|
|
||
|
//
|
||
|
// read settings in from system
|
||
|
//
|
||
|
GetProfileString(m_szPorts,
|
||
|
ComName,
|
||
|
g_szNull,
|
||
|
szParms,
|
||
|
81);
|
||
|
|
||
|
StripBlanks(szParms);
|
||
|
if (lstrlen(szParms) == 0) {
|
||
|
lstrcpy(szParms, m_szDefParams);
|
||
|
WriteProfileString(m_szPorts, ComName, szParms);
|
||
|
}
|
||
|
|
||
|
szCur = szParms;
|
||
|
|
||
|
//
|
||
|
// baud rate
|
||
|
//
|
||
|
szNext = strscan(szCur, m_szComma);
|
||
|
if (*szNext) {
|
||
|
//
|
||
|
// If we found a comma, terminate
|
||
|
//
|
||
|
*szNext++ = 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// current Baud Rate selection
|
||
|
//
|
||
|
if (*szCur) {
|
||
|
Params->PortSettings.BaudRate = myatoi(szCur);
|
||
|
}
|
||
|
else {
|
||
|
//
|
||
|
// must not have been written, use default
|
||
|
//
|
||
|
Params->PortSettings.BaudRate = m_nBaudRates[DEF_BAUD];
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set the current value in the dialog sheet
|
||
|
//
|
||
|
nIndex = (int)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_FINDSTRING,
|
||
|
(WPARAM)-1,
|
||
|
(LPARAM)szCur);
|
||
|
|
||
|
nIndex = (nIndex == CB_ERR) ? 0 : nIndex;
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
|
||
|
szCur = szNext;
|
||
|
|
||
|
//
|
||
|
// parity
|
||
|
//
|
||
|
szNext = strscan(szCur, m_szComma);
|
||
|
|
||
|
if (*szNext) {
|
||
|
*szNext++ = 0;
|
||
|
}
|
||
|
StripBlanks(szCur);
|
||
|
|
||
|
switch(*szCur) {
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
Params->PortSettings.Parity = nIndex;
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_PARITY,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
szCur = szNext;
|
||
|
|
||
|
//
|
||
|
// word length: 4 - 8
|
||
|
//
|
||
|
szNext = strscan(szCur, m_szComma);
|
||
|
|
||
|
if (*szNext) {
|
||
|
*szNext++ = 0;
|
||
|
}
|
||
|
|
||
|
StripBlanks(szCur);
|
||
|
nIndex = *szCur - TEXT('4');
|
||
|
|
||
|
if (nIndex < 0 || nIndex > 4) {
|
||
|
nIndex = DEF_WORD;
|
||
|
}
|
||
|
|
||
|
Params->PortSettings.DataBits = nIndex;
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_DATABITS,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
|
||
|
szCur = szNext;
|
||
|
|
||
|
//
|
||
|
// stop bits
|
||
|
//
|
||
|
szNext = strscan(szCur, m_szComma);
|
||
|
|
||
|
if (*szNext) {
|
||
|
*szNext++ = 0;
|
||
|
}
|
||
|
|
||
|
StripBlanks(szCur);
|
||
|
|
||
|
if (!lstrcmp(szCur, TEXT("1"))) {
|
||
|
nIndex = STOP_1;
|
||
|
}
|
||
|
else if(!lstrcmp(szCur, TEXT("1.5"))) {
|
||
|
nIndex = STOP_15;
|
||
|
}
|
||
|
else if(!lstrcmp(szCur, TEXT("2"))) {
|
||
|
nIndex = STOP_2;
|
||
|
}
|
||
|
else {
|
||
|
nIndex = DEF_STOP;
|
||
|
}
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_STOPBITS,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
|
||
|
Params->PortSettings.StopBits = nIndex;
|
||
|
szCur = szNext;
|
||
|
|
||
|
//
|
||
|
// handshaking: Hardware, xon/xoff, or none
|
||
|
//
|
||
|
szNext = strscan(szCur, m_szComma);
|
||
|
|
||
|
if (*szNext) {
|
||
|
*szNext++ = 0;
|
||
|
}
|
||
|
|
||
|
StripBlanks(szCur);
|
||
|
|
||
|
if (*szCur == TEXT('p')) {
|
||
|
nIndex = FLOW_HARD;
|
||
|
}
|
||
|
else if (*szCur == TEXT('x')) {
|
||
|
nIndex = FLOW_XON;
|
||
|
}
|
||
|
else {
|
||
|
nIndex = FLOW_NONE;
|
||
|
}
|
||
|
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_FLOWCTL,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
|
||
|
Params->PortSettings.FlowControl = nIndex;
|
||
|
} /* GetPortSettings */
|
||
|
|
||
|
void
|
||
|
RestorePortSettings(
|
||
|
HWND DialogHwnd,
|
||
|
PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
UINT nIndex;
|
||
|
|
||
|
//
|
||
|
// baud rate
|
||
|
//
|
||
|
nIndex = (UINT)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_FINDSTRING,
|
||
|
(WPARAM)-1,
|
||
|
(LPARAM)TEXT("9600"));
|
||
|
|
||
|
nIndex = (nIndex == CB_ERR) ? 0 : nIndex;
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
CB_SETCURSEL,
|
||
|
nIndex,
|
||
|
0L);
|
||
|
|
||
|
//
|
||
|
// parity
|
||
|
//
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_PARITY,
|
||
|
CB_SETCURSEL,
|
||
|
PAR_NONE,
|
||
|
0L);
|
||
|
|
||
|
//
|
||
|
// word length: 4 - 8
|
||
|
//
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_DATABITS,
|
||
|
CB_SETCURSEL,
|
||
|
4, // the 4th index is 8, what we want
|
||
|
0L);
|
||
|
|
||
|
//
|
||
|
// stop bits
|
||
|
//
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_STOPBITS,
|
||
|
CB_SETCURSEL,
|
||
|
STOP_1,
|
||
|
0L);
|
||
|
|
||
|
//
|
||
|
// handshaking: Hardware, xon/xoff, or none
|
||
|
//
|
||
|
SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_FLOWCTL,
|
||
|
CB_SETCURSEL,
|
||
|
FLOW_NONE,
|
||
|
0L);
|
||
|
|
||
|
// nIndex = FLOW_HARD;
|
||
|
// nIndex = FLOW_XON;
|
||
|
// nIndex = FLOW_NONE;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: SavePortSettingsDlg
|
||
|
|
||
|
save changes in the Ports Settings dlg sheet
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Params: where to save the data to
|
||
|
ParentHwnd: address of the window
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ULONG: returns error messages
|
||
|
|
||
|
--*/
|
||
|
ULONG
|
||
|
SavePortSettingsDlg(
|
||
|
IN HWND DialogHwnd,
|
||
|
IN PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
TCHAR szCharBuffer[81];
|
||
|
DWORD dwPortnum, dwOldPortnum;
|
||
|
DWORD dwPortNameSize, dwError;
|
||
|
TCHAR szNewComName[21];
|
||
|
TCHAR szSerialKey[41];
|
||
|
TCHAR szTitle[81];
|
||
|
TCHAR szTitleFormat[81];
|
||
|
HKEY hDeviceKey, hKey;
|
||
|
|
||
|
//
|
||
|
// create "com#:"
|
||
|
//
|
||
|
// lstrcpy(szCharBuffer, Params->pAdvancedData->szNewComName);
|
||
|
lstrcpy(szCharBuffer, Params->PortSettings.szComName);
|
||
|
lstrcat(szCharBuffer, m_szColon);
|
||
|
|
||
|
//
|
||
|
// store changes to win.ini; broadcast changes to apps
|
||
|
//
|
||
|
SavePortSettings(DialogHwnd, szCharBuffer, Params);
|
||
|
|
||
|
return 0;
|
||
|
} /* SavePortSettingsDlg */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description: SavePortSettings
|
||
|
|
||
|
Read the dlg screen selections for baudrate, parity, etc.
|
||
|
If changed from what we started with, then save them
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg: address of the window
|
||
|
szComName: which comport we're dealing with
|
||
|
Params: contains, baudrate, parity, etc
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ULONG: returns error messages
|
||
|
|
||
|
--*/
|
||
|
void
|
||
|
SavePortSettings(
|
||
|
IN HWND DialogHwnd,
|
||
|
IN PTCHAR ComName,
|
||
|
IN PPORT_PARAMS Params
|
||
|
)
|
||
|
{
|
||
|
TCHAR szBuild[PATHMAX];
|
||
|
ULONG i;
|
||
|
PP_PORTSETTINGS pppNewPortSettings;
|
||
|
|
||
|
//
|
||
|
// Get the baud rate
|
||
|
//
|
||
|
i = (ULONG)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_BAUDRATE,
|
||
|
WM_GETTEXT,
|
||
|
18,
|
||
|
(LPARAM)szBuild);
|
||
|
if (!i) {
|
||
|
goto Return;
|
||
|
}
|
||
|
|
||
|
pppNewPortSettings.BaudRate = myatoi(szBuild);
|
||
|
|
||
|
//
|
||
|
// Get the parity setting
|
||
|
//
|
||
|
i = (ULONG)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_PARITY,
|
||
|
CB_GETCURSEL,
|
||
|
0,
|
||
|
0L);
|
||
|
|
||
|
if (i == CB_ERR || i == CB_ERRSPACE) {
|
||
|
goto Return;
|
||
|
}
|
||
|
|
||
|
pppNewPortSettings.Parity = i;
|
||
|
lstrcat(szBuild, m_pszParitySuf[i]);
|
||
|
|
||
|
//
|
||
|
// Get the word length
|
||
|
//
|
||
|
i = (ULONG)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_DATABITS,
|
||
|
CB_GETCURSEL,
|
||
|
0,
|
||
|
0L);
|
||
|
|
||
|
if (i == CB_ERR || i == CB_ERRSPACE) {
|
||
|
goto Return;
|
||
|
}
|
||
|
|
||
|
pppNewPortSettings.DataBits = i;
|
||
|
lstrcat(szBuild, m_pszLenSuf[i]);
|
||
|
|
||
|
//
|
||
|
// Get the stop bits
|
||
|
//
|
||
|
i = (ULONG)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_STOPBITS,
|
||
|
CB_GETCURSEL,
|
||
|
0,
|
||
|
0L);
|
||
|
|
||
|
if (i == CB_ERR || i == CB_ERRSPACE) {
|
||
|
goto Return;
|
||
|
}
|
||
|
|
||
|
pppNewPortSettings.StopBits = i;
|
||
|
lstrcat(szBuild, m_pszStopSuf[i]);
|
||
|
|
||
|
//
|
||
|
// Get the flow control
|
||
|
//
|
||
|
i = (ULONG)SendDlgItemMessage(DialogHwnd,
|
||
|
PP_PORT_FLOWCTL,
|
||
|
CB_GETCURSEL,
|
||
|
0,
|
||
|
0L);
|
||
|
|
||
|
if (i == CB_ERR || i == CB_ERRSPACE) {
|
||
|
goto Return;
|
||
|
}
|
||
|
|
||
|
pppNewPortSettings.FlowControl = i;
|
||
|
lstrcat(szBuild, m_pszFlowSuf[i]);
|
||
|
|
||
|
//
|
||
|
// if any of the values changed, then save it off
|
||
|
//
|
||
|
if (Params->PortSettings.BaudRate != pppNewPortSettings.BaudRate ||
|
||
|
Params->PortSettings.Parity != pppNewPortSettings.Parity ||
|
||
|
Params->PortSettings.DataBits != pppNewPortSettings.DataBits ||
|
||
|
Params->PortSettings.StopBits != pppNewPortSettings.StopBits ||
|
||
|
Params->PortSettings.FlowControl != pppNewPortSettings.FlowControl) {
|
||
|
|
||
|
//
|
||
|
// Write settings string to [ports] section in win.ini
|
||
|
// NT translates this if a translate key is set in registry
|
||
|
// and it winds up getting written to
|
||
|
// HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports
|
||
|
//
|
||
|
WriteProfileString(m_szPorts, ComName, szBuild);
|
||
|
|
||
|
//
|
||
|
// Send global notification message to all windows
|
||
|
//
|
||
|
SendWinIniChange((LPTSTR)m_szPorts);
|
||
|
|
||
|
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
|
||
|
Params->DeviceInfoSet,
|
||
|
Params->DeviceInfoData)) {
|
||
|
//
|
||
|
// Possibly do something here
|
||
|
//
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Return:
|
||
|
return;
|
||
|
|
||
|
} /* SavePortSettings */
|