Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1176 lines
34 KiB

/** FILE: pp_lpt.c ********** Module Header *******************************
*
* Control panel applet for configuring LPT ports. This file contains
* the dialog and utility functions for managing the UI for setting LPT
* port parameters
*
@@BEGIN_DDKSPLIT
* History:
* jsenior - 7/10/98 - created
@@END_DDKSPLIT
*
* Copyright (C) 1990-1995 Microsoft Corporation
*
*************************************************************************/
//==========================================================================
// Include files
//==========================================================================
#include "ports.h"
#include "pp_lpt.h"
#include <windowsx.h>
TCHAR m_szFilterResourceMethod[] = TEXT("FilterResourceMethod");
TCHAR m_szParEnableLegacyZip[] = TEXT("ParEnableLegacyZip");
TCHAR m_szParEnableLegacyZipRegPath[] = TEXT("SYSTEM\\CurrentControlSet\\Services\\Parport\\Parameters");
const DWORD LptHelpIDs[]=
{
IDC_STATIC, IDH_NOHELP, //Filter resource method text - help not needed
IDC_FILTERMETHOD_TRYNOT, idh_devmgr_portset_trynot, //first radio button
IDC_FILTERMETHOD_NEVER, idh_devmgr_portset_never, //second radio button
IDC_FILTERMETHOD_ACCEPTANY, idh_devmgr_portset_acceptany, //third radio button
IDC_LPTNUMTEXT, idh_devmgr_portset_portnum, //Port number text
PP_LPT_PORT_NUMBER, idh_devmgr_portset_LPTchoice, //the list box for port number
IDC_LPT_ENABLE_LEGACY, idh_devmgr_enable_legacy, //Enable legacy detection checkbox
0, 0
};
#define NUM_FILTER_RESOURCE_METHODS 3
DWORD FilterResourceMethods[NUM_FILTER_RESOURCE_METHODS] = {
0, // Try not to use an interrupt
1, // Never use an interrupt
2 // Accept any interrupt given to the port
};
// C Runtime
// @@BEGIN_DDKSPLIT
//
// Prototype for IsUserAdmin (in pp.c)
//
BOOL
IsUserAdmin(VOID);
// @@END_DDKSPLIT
void
InformDriverOfChanges(BOOL NeedReboot,
IN PLPT_PROP_PARAMS LptPropParams);
void
LptPortOnHelp(HWND ParentHwnd,
LPHELPINFO HelpInfo);
BOOL
LptPortOnContextMenu(HWND HwndControl,
WORD Xpos,
WORD Ypos);
BOOL
LptPortOnInitDialog(
HWND ParentHwnd,
HWND FocusHwnd,
LPARAM Lparam);
ULONG
LptFillPortSettings(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropPageData);
ULONG
LptFillPortNameCb(
HWND ParentHwnd,
PLPT_PROP_PARAMS LptPropPageData);
void LptInitializeControls(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropPageData);
ULONG
LptSetFilterResourceMethod(
HWND ParentHwnd,
PLPT_PROP_PARAMS LptPropPageData);
ULONG
LptSavePortSettings(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropParams);
BOOL
LptPortOnNotify(
HWND ParentHwnd,
LPNMHDR NmHdr);
void
LptPortOnCommand(
HWND ParentHwnd,
int ControlId,
HWND ControlHwnd,
UINT NotifyCode);
UINT
LptEnactPortNameChanges(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropParams,
IN HKEY hDeviceKey,
IN UINT NewLptNum);
void
LptEnumerateUsedPorts(
IN HWND ParentHwnd,
IN PBYTE Buffer,
IN DWORD BufferSize);
void
LptInitPropParams(IN OUT PLPT_PROP_PARAMS Params,
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData);
HPROPSHEETPAGE
LptInitSettingsPage(PROPSHEETPAGE * psp,
OUT PLPT_PROP_PARAMS Params);
INT_PTR
APIENTRY
LptPortSettingsDlgProc(IN HWND hDlg,
IN UINT uMessage,
IN WPARAM wParam,
IN LPARAM lParam);
UINT
CALLBACK
LptPortSettingsDlgCallback(HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp);
/*++
Routine Description: ParallelPortPropPageProvider
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
ParallelPortPropPageProvider(LPVOID Info,
LPFNADDPROPSHEETPAGE AddFunc,
LPARAM Lparam)
{
PSP_PROPSHEETPAGE_REQUEST pprPropPageRequest;
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpsp;
PLPT_PROP_PARAMS params = NULL;
pprPropPageRequest = (PSP_PROPSHEETPAGE_REQUEST) Info;
// @@BEGIN_DDKSPLIT
//
// Only administrators are allowed to see this page
//
if (!IsUserAdmin()) {
return FALSE;
}
// @@END_DDKSPLIT
//
// Allocate and zero out memory for the struct that will contain
// page specific data
//
params = (PLPT_PROP_PARAMS) LocalAlloc(LPTR, sizeof(LPT_PROP_PARAMS));
if (!params) {
ErrMemDlg(GetFocus());
return FALSE;
}
if (pprPropPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) {
LptInitPropParams(params,
pprPropPageRequest->DeviceInfoSet,
pprPropPageRequest->DeviceInfoData);
hpsp = LptInitSettingsPage(&psp, params);
if (!hpsp) {
return FALSE;
}
if (!(*AddFunc)(hpsp, Lparam)) {
DestroyPropertySheetPage(hpsp);
return FALSE;
}
}
return TRUE;
} // ParallelPortPropPageProvider
/*++
Routine Description: LptPortSettingsDlgProc
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
LptPortSettingsDlgProc(IN HWND hDlg,
IN UINT uMessage,
IN WPARAM wParam,
IN LPARAM lParam)
{
switch(uMessage) {
case WM_COMMAND:
LptPortOnCommand(hDlg, (int) LOWORD(wParam), (HWND)lParam, (UINT)HIWORD(wParam));
break;
case WM_CONTEXTMENU:
return LptPortOnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
case WM_HELP:
LptPortOnHelp(hDlg, (LPHELPINFO) lParam);
break;
case WM_INITDIALOG:
return LptPortOnInitDialog(hDlg, (HWND)wParam, lParam);
case WM_NOTIFY:
return LptPortOnNotify(hDlg, (NMHDR *)lParam);
}
return FALSE;
} // PortSettingsDialogProc
void
LptInitPropParams(IN OUT PLPT_PROP_PARAMS Params,
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
BOOL bResult;
DWORD requiredSize = 0;
SP_DEVINFO_LIST_DETAIL_DATA detailData;
ZeroMemory(Params, sizeof(LPT_PROP_PARAMS));
Params->DeviceInfoSet = DeviceInfoSet;
Params->DeviceInfoData = DeviceInfoData;
Params->ChangesEnabled = TRUE;
//
// Get the device ID first: if the device path is larger then
// MAX_PATH, we will try again with a bigger buffer
//
bResult = SetupDiGetDeviceInstanceId(DeviceInfoSet,
DeviceInfoData,
NULL,
MAX_PATH,
&requiredSize);
//
// 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) {
Params->ChangesEnabled = FALSE;
}
} // LptInitPropParams
HPROPSHEETPAGE LptInitSettingsPage(PROPSHEETPAGE * psp,
OUT PLPT_PROP_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_LPT_PORTSETTINGS);
//
// following points to the dlg window proc
//
psp->pfnDlgProc = LptPortSettingsDlgProc;
psp->lParam = (LPARAM) Params;
//
// following points to some control callback of the dlg window proc
//
psp->pfnCallback = LptPortSettingsDlgCallback;
//
// allocate our "Ports Setting" sheet
//
return CreatePropertySheetPage(psp);
}
UINT
CALLBACK
LptPortSettingsDlgCallback(HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
PLPT_PROP_PARAMS params;
switch (uMsg) {
case PSPCB_CREATE:
return TRUE; // return TRUE to continue with creation of page
case PSPCB_RELEASE:
params = (PLPT_PROP_PARAMS) ppsp->lParam;
LocalFree(params);
return 0; // return value ignored
default:
break;
}
return TRUE;
}
BOOL
LptPortOnInitDialog(
HWND ParentHwnd,
HWND FocusHwnd,
LPARAM Lparam
)
{
PLPT_PROP_PARAMS lptPropParams;
lptPropParams = (PLPT_PROP_PARAMS) ((LPPROPSHEETPAGE)Lparam)->lParam;
//
// Save value away
SetWindowLongPtr(ParentHwnd, DWLP_USER, (ULONG_PTR) lptPropParams);
//
// Initialize the dialog box parameters
//
LptFillPortSettings(ParentHwnd, lptPropParams);
//
// Set up the dialog box with these initialized parameters
//
LptInitializeControls(ParentHwnd, lptPropParams);
return TRUE;
}
/*++
Routine Description: LptFillPortSettings
Gets the settings out of the registry ready for initializing the dialog box
with.
Arguments:
LptPropPageData: the data to fill in
ParentHwnd: address of the window
Return Value:
ULONG: returns error messages
--*/
ULONG
LptFillPortSettings(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropPageData
)
{
HKEY hKey;
DWORD dwPortNameSize, dwError;
TCHAR szCharBuffer[81];
DWORD dwSize, dwData, dwMethod;
//
// Open the device key for the source device instance, and retrieve its
// "PortName" value.
//
hKey = SetupDiOpenDevRegKey(LptPropPageData->DeviceInfoSet,
LptPropPageData->DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_ALL_ACCESS);
if (INVALID_HANDLE_VALUE == hKey) {
return GetLastError();
}
dwPortNameSize = sizeof(LptPropPageData->szLptName);
dwError = RegQueryValueEx(hKey,
m_szPortName, // "PortName"
NULL,
NULL,
(PBYTE)LptPropPageData->szLptName,
&dwPortNameSize);
if(ERROR_SUCCESS != dwError) {
RegCloseKey(hKey);
return dwError;
}
//
// create "lpt#:"
//
lstrcpy(szCharBuffer, LptPropPageData->szLptName);
lstrcat(szCharBuffer, m_szColon);
dwSize = sizeof(LptPropPageData->FilterResourceMethod);
dwError = RegQueryValueEx(hKey,
m_szFilterResourceMethod,
NULL,
NULL,
(LPBYTE)(&LptPropPageData->FilterResourceMethod),
&dwSize);
if (dwError != ERROR_SUCCESS) {
//
// value does not exist. Create our own:
// Get Filter Resource Method information
//
LptPropPageData->FilterResourceMethod =
FilterResourceMethods[RESOURCE_METHOD_DEFAULT_IDX];
dwError = RegSetValueEx(hKey,
m_szFilterResourceMethod,
0,
REG_DWORD,
(LPBYTE)(&LptPropPageData->FilterResourceMethod),
sizeof(LptPropPageData->FilterResourceMethod));
}
RegCloseKey(hKey);
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
m_szParEnableLegacyZipRegPath,
0,
KEY_ALL_ACCESS,
&hKey);
if (dwError != ERROR_SUCCESS) {
//
// Don't have access maybe?
//
LptPropPageData->ParEnableLegacyZip = ENABLELEGACYZIPDEFAULT;
return dwError;
}
dwSize = sizeof(LptPropPageData->ParEnableLegacyZip);
dwError = RegQueryValueEx(hKey,
TEXT("ParEnableLegacyZip"),
NULL,
NULL,
(LPBYTE)(&LptPropPageData->ParEnableLegacyZip),
&dwSize);
if (dwError != ERROR_SUCCESS) {
//
// value does not exist. Create our own
//
LptPropPageData->ParEnableLegacyZip = ENABLELEGACYZIPDEFAULT;
dwError = RegSetValueEx(hKey,
m_szParEnableLegacyZip,
0,
REG_DWORD,
(LPBYTE)(&LptPropPageData->ParEnableLegacyZip),
sizeof(LptPropPageData->ParEnableLegacyZip));
}
RegCloseKey(hKey);
return dwError;
} // LptFillPortSettings
/*++
Routine Description: LptInitializeControls
Initializes all of the controls that represent Fifo
Arguments:
ParentHwnd - handle to the dialog
LptPropPageData - Contains all of the initial values
Return Value:
None
--*/
void LptInitializeControls(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropPageData
)
{
TCHAR szCurrentValue[40];
HWND hwnd;
int i, periodIdx;
LptFillPortNameCb(ParentHwnd, LptPropPageData);
LptSetFilterResourceMethod(ParentHwnd, LptPropPageData);
//
// Set the state of the Enable Legacy Detection checkbox
//
if (LptPropPageData->ParEnableLegacyZip) {
CheckDlgButton(ParentHwnd,
IDC_LPT_ENABLE_LEGACY,
BST_CHECKED);
} else {
CheckDlgButton(ParentHwnd,
IDC_LPT_ENABLE_LEGACY,
BST_UNCHECKED);
}
if (!LptPropPageData->ChangesEnabled) {
// EnableWindow(GetDlgItem(ParentHwnd, IDC_FIFO), FALSE);
}
} // LptInitializeControls
/*++
Routine Description: LptSetFilterResourceMethod
Checks the appropriate resource method to use
Arguments:
LptPropPageData: where to get the data from
ParentHwnd: address of the window
Return Value:
ULONG: returns error messages
--*/
ULONG
LptSetFilterResourceMethod(
HWND ParentHwnd,
PLPT_PROP_PARAMS LptPropPageData
)
{
switch (LptPropPageData->FilterResourceMethod) {
case FILTERMETHOD_TRYNOT:
CheckRadioButton( ParentHwnd, // handle to dialog box
IDC_FILTERMETHOD_TRYNOT, // first button in group
IDC_FILTERMETHOD_ACCEPTANY, // last button in group
IDC_FILTERMETHOD_TRYNOT // selected
);
break;
case FILTERMETHOD_ACCEPTANY:
CheckRadioButton( ParentHwnd, // handle to dialog box
IDC_FILTERMETHOD_TRYNOT, // first button in group
IDC_FILTERMETHOD_ACCEPTANY, // last button in group
IDC_FILTERMETHOD_ACCEPTANY // selected
);
break;
case FILTERMETHOD_NEVER:
CheckRadioButton( ParentHwnd, // handle to dialog box
IDC_FILTERMETHOD_TRYNOT, // first button in group
IDC_FILTERMETHOD_ACCEPTANY, // last button in group
IDC_FILTERMETHOD_NEVER // selected
);
break;
default:
CheckRadioButton( ParentHwnd, // handle to dialog box
IDC_FILTERMETHOD_TRYNOT, // first button in group
IDC_FILTERMETHOD_ACCEPTANY, // last button in group
IDC_FILTERMETHOD_NEVER // selected
);
break;
}
return 0;
}
/*++
Routine Description: LptFillPortNameCb
fill in the Port Name combo box selection with a list
of possible un-used portnames
Arguments:
LptPropPageData: where to get the data from
hDlg: address of the window
Return Value:
ULONG: returns error messages
--*/
ULONG
LptFillPortNameCb(
HWND ParentHwnd,
PLPT_PROP_PARAMS LptPropPageData
)
{
BYTE portUsage[MAX_LPT_PORT];
DWORD tmp, portsReported;
int i, nEntries;
int nCurPortNum;
TCHAR szLpt[40];
TCHAR szInUse[40];
HWND portHwnd;
portHwnd = GetDlgItem(ParentHwnd, PP_LPT_PORT_NUMBER);
//
// Check if our LptName is blank. If it is, disable the lpt port selector
//
if (_tcscmp(LptPropPageData->szLptName, TEXT("")) == 0) {
EnableWindow(portHwnd, FALSE);
EnableWindow(GetDlgItem(ParentHwnd, IDC_LPTNUMTEXT), FALSE);
return 0;
}
//
// assumes szLptPort filled in...
//
nCurPortNum = myatoi(&LptPropPageData->szLptName[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_LPT_PORT);
// Find out which ports not to offer
LptEnumerateUsedPorts(ParentHwnd,
portUsage,
MAX_LPT_PORT);
for(i = MIN_LPT-1; i < MAX_LPT_PORT; i++) {
wsprintf(szLpt, TEXT("LPT%d"), i+1);
if (portUsage[i] &&
_tcscmp(szLpt, LptPropPageData->szLptName)) {
wcscat(szLpt, szInUse);
}
ComboBox_AddString(portHwnd, szLpt);
}
ComboBox_SetCurSel(portHwnd, nCurPortNum-1);
return 0;
} // FillPortNamesCb
void
LptPortOnCommand(
HWND ParentHwnd,
int ControlId,
HWND ControlHwnd,
UINT NotifyCode
)
{
PLPT_PROP_PARAMS params =
(PLPT_PROP_PARAMS) GetWindowLongPtr(ParentHwnd, DWLP_USER);
if (NotifyCode == CBN_SELCHANGE) {
PropSheet_Changed(GetParent(ParentHwnd), ParentHwnd);
}
else {
switch (ControlId) {
//
// Because this is a prop sheet, we should never get this.
// All notifications for ctrols outside of the sheet come through
// WM_NOTIFY
//
case IDOK:
case IDCANCEL:
EndDialog(ParentHwnd, 0);
return;
}
}
} // LptPortOnCommand
BOOL
LptPortOnNotify(
HWND ParentHwnd,
LPNMHDR NmHdr
)
{
PLPT_PROP_PARAMS params =
(PLPT_PROP_PARAMS) GetWindowLongPtr(ParentHwnd, DWLP_USER);
switch (NmHdr->code) {
//
// Sent when the user clicks on Apply OR OK !!
//
case PSN_APPLY:
//
// Write out the lpt port options to the registry
//
LptSavePortSettings(ParentHwnd, params);
SetWindowLongPtr(ParentHwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;
default:
return FALSE;
}
} // LptPortOnNotify
/*++
Routine Description: LptSavePortSettings
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
LptSavePortSettings(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropParams
)
{
HKEY hKey;
DWORD dwSize, dwData;
UINT i = CB_ERR, curLptNum, newLptNum = CB_ERR;
UINT uiTryNotChecked, uiNeverChecked, uiAcceptAnyChecked;
DWORD curFilterResourceMethod;
DWORD newFilterResourceMethod = 0;
DWORD curParEnableLegacyZip, newParEnableLegacyZip;
ULONG error = ERROR_SUCCESS;
SP_DEVINSTALL_PARAMS spDevInstall;
//
// Grab all of the new settings
//
// Filter resource method
curFilterResourceMethod = newFilterResourceMethod = LptPropParams->FilterResourceMethod;
if (BST_CHECKED ==
IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_TRYNOT))
newFilterResourceMethod = 0;
else if (BST_CHECKED ==
IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_NEVER))
newFilterResourceMethod = 1;
else if (BST_CHECKED ==
IsDlgButtonChecked(ParentHwnd, IDC_FILTERMETHOD_ACCEPTANY))
newFilterResourceMethod = 2;
// LPT port number
curLptNum = myatoi(LptPropParams->szLptName + wcslen(m_szLPT));
newLptNum = ComboBox_GetCurSel(GetDlgItem(ParentHwnd, PP_LPT_PORT_NUMBER));
if (newLptNum == CB_ERR) {
newLptNum = curLptNum;
} else {
newLptNum++;
}
// Legacy device detection
curParEnableLegacyZip = LptPropParams->ParEnableLegacyZip;
if (BST_CHECKED == IsDlgButtonChecked(ParentHwnd, IDC_LPT_ENABLE_LEGACY)) {
newParEnableLegacyZip = 0x1;
} else {
newParEnableLegacyZip = 0x0;
}
//
// See if they changed anything
//
if ((curLptNum == newLptNum) &&
(curFilterResourceMethod == newFilterResourceMethod) &&
(curParEnableLegacyZip == newParEnableLegacyZip)) {
//
// They didn't change anything. Just exit.
//
return ERROR_SUCCESS;
}
//
// Open the device key for the source device instance
//
hKey = SetupDiOpenDevRegKey(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_ALL_ACCESS);
if (INVALID_HANDLE_VALUE == hKey) {
//
// Not much we can do, just exit gracefully
//
return ERROR_SUCCESS;
}
// Check the LPT port name for changes
if (newLptNum != curLptNum) {
LptEnactPortNameChanges(ParentHwnd,
LptPropParams,
hKey,
newLptNum);
}
// Check the Filter resource method for changes
if (curFilterResourceMethod != newFilterResourceMethod) {
//
// They changed the Filter Resource Method
//
dwData = newFilterResourceMethod;
dwSize = sizeof(dwData);
RegSetValueEx(hKey,
m_szFilterResourceMethod,
0,
REG_DWORD,
(CONST BYTE *)(&dwData),
dwSize);
}
RegCloseKey(hKey);
if (curParEnableLegacyZip != newParEnableLegacyZip) {
//
// Open the services path and set the new value for Legacy Parallel device
// detection.
//
DWORD disposition = 0;
error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
m_szParEnableLegacyZipRegPath,
0,
(TCHAR *) NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
(LPSECURITY_ATTRIBUTES) NULL,
&hKey,
&disposition);
if (error == ERROR_SUCCESS) {
error = RegSetValueEx(hKey,
m_szParEnableLegacyZip,
0,
REG_DWORD,
(LPBYTE)(&newParEnableLegacyZip),
sizeof(newParEnableLegacyZip));
RegCloseKey(hKey);
if (error != ERROR_SUCCESS) {
goto ParEnableLegacyZipSetParamFailed;
}
if (newParEnableLegacyZip == 0) {
//
// We want a reboot when disabling this thing, because the parallel
// enumerator won't get rid of legacy devices.
//
InformDriverOfChanges(TRUE, LptPropParams);
} else {
InformDriverOfChanges(FALSE, LptPropParams);
}
} else {
ParEnableLegacyZipSetParamFailed:
MyMessageBox(ParentHwnd,
IDS_LPT_LEGACY_FAILED,
IDS_LPT_PROPERTIES,
MB_OK);
//
// Don't want to overload the user by telling them they have to
// reboot. Since we were unable to set things correctly, just
// rebuild the stack.
//
InformDriverOfChanges(FALSE, LptPropParams);
}
} else {
InformDriverOfChanges(FALSE, LptPropParams);
}
return error;
} // LptSaveAdvancedSettings
UINT
LptEnactPortNameChanges(
IN HWND ParentHwnd,
IN PLPT_PROP_PARAMS LptPropParams,
IN HKEY hDeviceKey,
IN UINT NewLptNum)
{
HANDLE hLpt;
DWORD dwError, dwNewLptNameLen;
UINT curLptNum;
BYTE portUsage[MAX_LPT_PORT];
TCHAR charBuffer[LINE_LEN],
friendlyNameFormat[LINE_LEN],
deviceDesc[LINE_LEN],
buffer[BUFFER_SIZE],
szNewLptName[20];
//
// Check if we're trying to rename the port to the same name.
//
wsprintf(szNewLptName,_T("\\DosDevices\\LPT%d"),NewLptNum);
if (wcscmp(szNewLptName, LptPropParams->szLptName) == 0) {
return ERROR_SUCCESS;
}
//
// Check if a valid port number has been passed in
//
if (MAX_LPT_PORT < NewLptNum) {
//
// Get out of here - exceeding array bounds
// This should never happen in the property page since it is a hardcoded
// selection box. The user can't simply type a number.
//
MyMessageBox(ParentHwnd, IDS_LPT_NUM_ERROR, IDS_LPT_PROPERTIES,
MB_OK | MB_ICONINFORMATION);
return ERROR_SUCCESS;
}
//
// Get an array of used ports
//
LptEnumerateUsedPorts(ParentHwnd,
portUsage,
MAX_LPT_PORT);
if (portUsage[NewLptNum-1]) {
//
// Port name is taken by another port. Check if user wants system to
// get into inconsistent state.
//
if (IDNO == MyMessageBox(ParentHwnd, IDS_LPT_PORT_INUSE,
IDS_LPT_PROPERTIES, MB_YESNO |
MB_ICONINFORMATION)) {
return ERROR_SUCCESS;
}
}
curLptNum = myatoi(LptPropParams->szLptName + wcslen(m_szLPT));
//
// Make sure that the port has not been opened by another application
//
wsprintf(buffer, L"\\\\.\\%ws", LptPropParams->szLptName);
hLpt = CreateFile(buffer, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
//
// If the file handle is invalid, then the Lpt port is open, warn the user
//
if (hLpt == INVALID_HANDLE_VALUE &&
MyMessageBox(ParentHwnd, IDS_PORT_OPEN, IDS_LPT_PROPERTIES,
MB_YESNO | MB_ICONINFORMATION) == IDNO) {
return GetLastError();
}
CloseHandle(hLpt);
wsprintf(szNewLptName, _T("LPT%d"), NewLptNum);
//
// Open the device key for the source device instance, and write its
// new "PortName" value.
//
hDeviceKey = SetupDiOpenDevRegKey(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_ALL_ACCESS);
if (INVALID_HANDLE_VALUE == hDeviceKey) {
return GetLastError();
}
dwNewLptNameLen = ByteCountOf(wcslen(szNewLptName) + 1);
dwError = RegSetValueEx(hDeviceKey,
m_szPortName,
0,
REG_SZ,
(PBYTE) szNewLptName,
dwNewLptNameLen);
if (ERROR_SUCCESS == dwError) {
wcscpy(LptPropParams->szLptName, szNewLptName);
} else {
return dwError;
}
// Now generate a string, to be used for the device's friendly name, that
// incorporates both the INF-specified device description, and the port
// name. For example,
//
// ECP Printer Port (LPT1)
//
if (LoadString(g_hInst,
IDS_FRIENDLY_FORMAT,
friendlyNameFormat,
CharSizeOf(friendlyNameFormat)) &&
SetupDiGetDeviceRegistryProperty(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)deviceDesc,
sizeof(deviceDesc),
NULL)) {
wsprintf(charBuffer, friendlyNameFormat, deviceDesc, szNewLptName);
}
else {
//
// Simply use LPT port name.
//
lstrcpy(charBuffer, szNewLptName);
}
SetupDiSetDeviceRegistryProperty(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
SPDRP_FRIENDLYNAME,
(PBYTE)charBuffer,
ByteCountOf(lstrlen(charBuffer) + 1)
);
return ERROR_SUCCESS;
} // LptEnactPortNameChanges
void
InformDriverOfChanges(BOOL NeedReboot,
IN PLPT_PROP_PARAMS LptPropParams)
{
SP_DEVINSTALL_PARAMS spDevInstall;
//
// Now broadcast this change to the device manager
//
ZeroMemory(&spDevInstall, sizeof(SP_DEVINSTALL_PARAMS));
spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (SetupDiGetDeviceInstallParams(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
&spDevInstall)) {
if (NeedReboot) {
spDevInstall.Flags |= DI_PROPERTIES_CHANGE | DI_NEEDREBOOT;
} else {
spDevInstall.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;
}
SetupDiSetDeviceInstallParams(LptPropParams->DeviceInfoSet,
LptPropParams->DeviceInfoData,
&spDevInstall);
}
}
//
// Takes a Buffer of bytes and marks out which port names are taken
//
void
LptEnumerateUsedPorts(
IN HWND ParentHwnd,
IN PBYTE Buffer,
IN DWORD BufferSize)
{
HKEY hParallelMap;
TCHAR szParallel[BUFFER_SIZE];
DWORD dwParallelSize, dwLptSize, dwEnum, dwType, dwResult, dwPortNum;
TCHAR szLpt[BUFFER_SIZE];
PTCHAR szParPortNum;
ZeroMemory(Buffer, BufferSize);
//
//
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
m_szRegParallelMap,
0,
KEY_ALL_ACCESS,
&hParallelMap) == ERROR_SUCCESS) {
dwEnum = 0;
do {
dwParallelSize = CharSizeOf(szParallel);
dwLptSize = sizeof(szLpt);
dwResult = RegEnumValue(hParallelMap,
dwEnum++,
szParallel,
&dwParallelSize,
NULL,
&dwType,
(LPBYTE)szLpt,
&dwLptSize);
if (dwResult != ERROR_SUCCESS ||
dwType != REG_SZ) {
continue;
}
szParPortNum = _tcsspnp(szLpt,_T("\\DosDevices\\LPT"));
if (szParPortNum) {
//
// Find out if this is an actual port and not simply a
// device attached to the port
//
if (_tcscspn(szParPortNum,_T(".")) ==
_tcslen(szParPortNum)) {
dwPortNum = myatoi(szParPortNum);
if (dwPortNum-1 < BufferSize) {
Buffer[dwPortNum-1] = TRUE;
}
}
}
} while (dwResult == ERROR_SUCCESS);
RegCloseKey(hParallelMap);
}
} // LptEnumerateUsedPorts
BOOL
LptPortOnContextMenu(HWND HwndControl,
WORD Xpos,
WORD Ypos)
{
WinHelp(HwndControl,
_T("devmgr.hlp"),
HELP_CONTEXTMENU,
(ULONG_PTR) LptHelpIDs);
return FALSE;
}
void
LptPortOnHelp(HWND ParentHwnd,
LPHELPINFO HelpInfo)
{
if (HelpInfo->iContextType == HELPINFO_WINDOW) {
WinHelp((HWND) HelpInfo->hItemHandle,
_T("devmgr.hlp"),
HELP_WM_HELP,
(ULONG_PTR) LptHelpIDs);
}
}