windows-nt/Source/XPSP1/NT/base/ntsetup/syssetup/i386/pcihal.c

791 lines
22 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
pcihal.c
Abstract:
Routines for the Pci Hal property page.
Author:
Santosh Jodh 10-July-1998
--*/
#include "setupp.h"
#pragma hdrstop
#include <windowsx.h>
#define MSG_SIZE 2048
#define Allocate(n) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n)
#define Release(p) HeapFree(GetProcessHeap(), 0, (LPVOID)p)
typedef struct _PciHalPropData PCIHALPROPDATA, *PPCIHALPROPDATA;
struct _PciHalPropData {
HKEY LocalMachine;
BOOLEAN CloseKey;
DWORD Options;
HDEVINFO DeviceInfoSet;
PSP_DEVINFO_DATA DeviceInfoData;
};
const DWORD gPciPropHelpIds[] =
{
IDC_PCIHAL_ICON, (DWORD)-1, // Icon
IDC_PCIHAL_DEVDESC, (DWORD)-1, // Name of PC
IDC_PCIHAL_ENABLE, IDH_IRQ_ENABLE, // Enable IRQ Routing
IDC_PCIHAL_MSSPEC, IDH_IRQ_MSSPEC, // Use $PIR table
IDC_PCIHAL_REALMODE, IDH_IRQ_REALMODE, // Use table from Real-mode BIOS call
IDC_PCIHAL_SETDEFAULTS, IDH_IRQ_SETDEFAULTS, // Set defaults for options
IDC_PCIHAL_RESULTS, IDH_IRQ_RESULTS, // Status information
0,0
};
//
// Table used to translate status codes into string ids.
//
UINT gStatus[PIR_STATUS_MAX + 1] = { IDS_PCIHAL_ERROR,
IDS_PCIHAL_ENABLED,
IDS_PCIHAL_DISABLED,
IDS_PCIHAL_NOSTATUS
};
UINT gTableStatus[PIR_STATUS_TABLE_MAX] = { IDS_PCIHAL_TABLE_REGISTRY,
IDS_PCIHAL_TABLE_MSSPEC,
IDS_PCIHAL_TABLE_REALMODE,
IDS_PCIHAL_TABLE_NONE,
IDS_PCIHAL_TABLE_ERROR,
IDS_PCIHAL_TABLE_BAD,
IDS_PCIHAL_TABLE_SUCCESS
};
UINT gMiniportStatus[PIR_STATUS_MINIPORT_MAX] = { IDS_PCIHAL_MINIPORT_NORMAL,
IDS_PCIHAL_MINIPORT_COMPATIBLE,
IDS_PCIHAL_MINIPORT_OVERRIDE,
IDS_PCIHAL_MINIPORT_NONE,
IDS_PCIHAL_MINIPORT_ERROR,
IDS_PCIHAL_MINIPORT_NOKEY,
IDS_PCIHAL_MINIPORT_SUCCESS,
IDS_PCIHAL_MINIPORT_INVALID
};
PCIHALPROPDATA gPciHalPropData = {0};
VOID
PciHalSetControls (
IN HWND Dialog,
IN DWORD Options,
IN DWORD Attributes
)
/*++
Routine Description:
This routine sets the controls on the Irq Routing page to the
specified options.
Input Parameters:
Dialog - Window handle for the property sheet page.
Options - Pci Irq Routing options to be displayed.
Return Value:
None.
--*/
{
BOOL enabled = FALSE;
//
// Enable the buttons depending on the options.
//
if (Options & PIR_OPTION_ENABLED)
{
enabled = TRUE;
CheckDlgButton(Dialog, IDC_PCIHAL_ENABLE, 1);
}
CheckDlgButton(Dialog, IDC_PCIHAL_MSSPEC, Options & PIR_OPTION_MSSPEC);
CheckDlgButton(Dialog, IDC_PCIHAL_REALMODE, Options & PIR_OPTION_REALMODE);
//
// Gray the windows not meaningful.
//
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_ENABLE), !(Attributes & PIR_OPTION_ENABLED));
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_SETDEFAULTS), !(Attributes & PIR_OPTION_ENABLED));
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_MSSPEC), enabled && !(Attributes & PIR_OPTION_MSSPEC));
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_REALMODE), enabled && !(Attributes & PIR_OPTION_REALMODE));
}
LPTSTR
PciHalGetDescription (
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData
)
/*++
Routine Description:
This routine allocates memory and returns the device description
for the specified device.
Input Parameters:
DeviceInfoSet - For the device.
DeviceInfoData - For the device.
Return Value:
Pointer to the description iff successful. Else NULL.
--*/
{
LPTSTR desc;
DWORD size;
desc = NULL;
//
// Get the size of the description for this device.
//
size = 0;
SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
NULL,
0,
&size);
if (size != 0)
{
//
// Account for the terminating NULL character.
//
size++;
//
// Allocate memory for the device description.
//
desc = Allocate(size * sizeof(TCHAR));
if (desc != NULL)
{
//
// Get the device description.
//
if (SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
SPDRP_DEVICEDESC,
NULL,
(PBYTE)desc,
size * sizeof(TCHAR),
&size) == FALSE)
{
Release(desc);
desc = NULL;
}
}
}
return desc;
}
LPTSTR
PciHalGetStatus (
IN DWORD Status,
IN DWORD TableStatus,
IN DWORD MiniportStatus
)
/*++
Routine Description:
This routine converts the different status codes into
a status string and returns the pointer to the string.
The caller should free the memory when done using this
string.
Input Parameters:
Status - Pci Irq Routing status.
TableStatus - Pci Irq Routing Table status. Lower WORD
indicates the source of the table. The upper WORD indicates
the table processing status.
MiniportStatus - Pci Irq Routing Miniport status. Lower
WORD indicates the source of the miniport. The upper WORD
indicates the miniport processing status.
Return Value:
Pointer to the status string iff successful. Else NULL.
--*/
{
LPTSTR status;
TCHAR temp[128];
status = Allocate(MSG_SIZE * sizeof(TCHAR));
if (status)
{
//
// Get the status about Pci Irq Routing.
//
LoadString(MyModuleHandle, gStatus[Status], status, MSG_SIZE);
//
// Get the status about the source of Pci Irq Routing Table.
//
if ((TableStatus & 0xFFFF) < PIR_STATUS_TABLE_MAX)
{
lstrcat(status, L"\r\n\r\n");
LoadString(MyModuleHandle, gTableStatus[TableStatus & 0xFFFF], temp, sizeof(temp)/sizeof(temp[0]));
lstrcat(status, temp);
}
//
// Get the status about the Pci Irq Routing table.
//
TableStatus >>= 16;
if (TableStatus < PIR_STATUS_TABLE_MAX)
{
lstrcat(status, L"\r\n\r\n");
LoadString(MyModuleHandle, gTableStatus[TableStatus], temp, sizeof(temp) / sizeof(TCHAR));
lstrcat(status, temp);
}
//
// Get the status about the source of the miniport.
//
if ((MiniportStatus & 0xFFFF) < PIR_STATUS_MINIPORT_MAX)
{
lstrcat(status, L"\r\n\r\n");
LoadString(MyModuleHandle, gMiniportStatus[MiniportStatus & 0xFFFF], temp, sizeof(temp) / sizeof(TCHAR));
lstrcat(status, temp);
}
//
// Get the status about the miniport status.
//
MiniportStatus >>= 16;
if (MiniportStatus < PIR_STATUS_MINIPORT_MAX)
{
lstrcat(status, L"\r\n\r\n");
LoadString(MyModuleHandle, gMiniportStatus[MiniportStatus], temp, sizeof(temp) / sizeof(TCHAR));
lstrcat(status, temp);
}
}
return status;
}
BOOL
PciHalOnInitDialog (
IN HWND Dialog,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
This routine initializes the property sheet page on creation.
Input Paramters:
Dialog - Window handle for the property sheet page.
wParam - wParam of the WM_INITDIALOG message.
lParam - Pointer to the property sheet page.
Return Value:
TRUE.
--*/
{
PPCIHALPROPDATA pciHalPropData;
HKEY hKey;
DWORD size;
DWORD status;
DWORD tableStatus;
DWORD miniportStatus;
DWORD attributes;
HICON hIconOld;
HICON hIconNew;
INT iconIndex;
LPTSTR desc;
SP_DEVINFO_LIST_DETAIL_DATA details;
pciHalPropData = (PPCIHALPROPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
//
// Read the Pci Irq Routing options and status from the registry.
//
pciHalPropData->Options = 0;
status = PIR_STATUS_MAX;
tableStatus = PIR_STATUS_TABLE_MAX | (PIR_STATUS_TABLE_MAX << 16);
miniportStatus = PIR_STATUS_MINIPORT_MAX | (PIR_STATUS_MINIPORT_MAX << 16);
details.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
attributes = PIR_OPTION_ENABLED | PIR_OPTION_MSSPEC | PIR_OPTION_REALMODE;
if (SetupDiGetDeviceInfoListDetail(pciHalPropData->DeviceInfoSet, &details)) {
if (RegConnectRegistry((details.RemoteMachineName[0] == TEXT('\0'))? NULL : details.RemoteMachineName, HKEY_LOCAL_MACHINE, &pciHalPropData->LocalMachine) == ERROR_SUCCESS) {
pciHalPropData->CloseKey = TRUE;
if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_PCIIR, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
size = sizeof(pciHalPropData->Options);
RegQueryValueEx(hKey, REGSTR_VAL_OPTIONS, NULL, NULL, (LPBYTE)&pciHalPropData->Options, &size);
size = sizeof(status);
RegQueryValueEx(hKey, REGSTR_VAL_STAT, NULL, NULL, (LPBYTE)&status, &size);
size = sizeof(tableStatus);
RegQueryValueEx(hKey, REGSTR_VAL_TABLE_STAT, NULL, NULL, (LPBYTE)&tableStatus, &size);
size = sizeof(miniportStatus);
RegQueryValueEx(hKey, REGSTR_VAL_MINIPORT_STAT, NULL, NULL, (LPBYTE)&miniportStatus, &size);
RegCloseKey(hKey);
}
//
// Gray out the controls if the user does not have READ+WRITE access to the REGSTR_PATH_PCIIR.
//
if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_PCIIR, 0, KEY_READ | KEY_WRITE, &hKey) == ERROR_SUCCESS) {
RegCloseKey(hKey);
attributes = 0;
if (RegOpenKeyEx(pciHalPropData->LocalMachine, REGSTR_PATH_BIOSINFO L"\\PciIrqRouting", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
size = sizeof(attributes);
RegQueryValueEx(hKey, L"Attributes", NULL, NULL, (LPBYTE)&attributes, &size);
RegCloseKey(hKey);
}
}
}
}
//
// Set the class icon.
//
if (SetupDiLoadClassIcon( &pciHalPropData->DeviceInfoData->ClassGuid,
&hIconNew,
&iconIndex) == TRUE)
{
hIconOld = (HICON)SendDlgItemMessage( Dialog,
IDC_PCIHAL_ICON,
STM_SETICON,
(WPARAM)hIconNew,
0);
if (hIconOld)
{
DestroyIcon(hIconOld);
}
}
//
// Set the device description.
//
desc = PciHalGetDescription(pciHalPropData->DeviceInfoSet, pciHalPropData->DeviceInfoData);
if (desc)
{
SetDlgItemText(Dialog, IDC_PCIHAL_DEVDESC, desc);
Release(desc);
}
//
// Set the initial state of the controls.
//
PciHalSetControls(Dialog, pciHalPropData->Options, attributes);
//
// Display status.
//
desc = PciHalGetStatus(status, tableStatus, miniportStatus);
if (desc)
{
SetDlgItemText(Dialog, IDC_PCIHAL_RESULTS, desc);
Release(desc);
}
//
// Let the system set the focus.
//
return TRUE;
}
BOOL
PciHalOnCommand (
IN HWND Dialog,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
This routine handles the message when the user modifies something
on the property sheet page.
Input Parameters:
Dialog - Window handle for the property sheet page.
wParam - wParam of the WM_COMMAND message.
lParam - lParam of the WM_COMMAND message.
Return Value:
TRUE if this function handles the message. Else FALSE.
--*/
{
BOOL status;
BOOL enabled;
status = FALSE;
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_PCIHAL_SETDEFAULTS:
//
// Set the controls to the default value.
//
status = TRUE;
PciHalSetControls(Dialog, PIR_OPTION_DEFAULT, 0);
break;
case IDC_PCIHAL_ENABLE:
//
// Gray out the sub-options if Irq Routing is being disabled.
//
status = TRUE;
enabled = IsDlgButtonChecked(Dialog, IDC_PCIHAL_ENABLE);
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_MSSPEC), enabled);
EnableWindow(GetDlgItem(Dialog, IDC_PCIHAL_REALMODE), enabled);
break;
default:
break;
}
return status;
}
BOOL
PciHalOnNotify(
IN HWND Dialog,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
This routine handles the WM_NOTIFY message for the Pci Irq Routing
property sheet page.
Input Parameters:
Dialog - Window handle for the property sheet page.
wParam - wParam of the WM_NOTIFY message.
lParam - lParam of the WM_NOTIFY message.
Return Value:
TRUE if this function handles the message. Else FALSE.
--*/
{
BOOL status = FALSE;
HKEY hKey;
DWORD options;
switch (((LPNMHDR)lParam)->code)
{
case PSN_RESET:
//
// User hit cancel.
//
status = TRUE;
if (RegOpenKey(gPciHalPropData.LocalMachine, REGSTR_PATH_PCIIR, &hKey) == ERROR_SUCCESS)
{
RegSetValueEx( hKey,
REGSTR_VAL_OPTIONS,
0,
REG_DWORD,
(CONST BYTE *)&gPciHalPropData.Options,
sizeof(gPciHalPropData.Options));
RegCloseKey(hKey);
}
break;
case PSN_APPLY:
//
// User hit Apply or Ok.
//
status = TRUE;
//
// Read the different control status and write it to the registry.
//
options = gPciHalPropData.Options;
if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_ENABLE) == BST_CHECKED)
{
options |= PIR_OPTION_ENABLED;
}
else
{
options &= ~PIR_OPTION_ENABLED;
}
if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_MSSPEC))
{
options |= PIR_OPTION_MSSPEC;
}
else
{
options &= ~PIR_OPTION_MSSPEC;
}
if (IsDlgButtonChecked(Dialog, IDC_PCIHAL_REALMODE))
{
options |= PIR_OPTION_REALMODE;
}
else
{
options &= ~PIR_OPTION_REALMODE;
}
if (RegOpenKey(gPciHalPropData.LocalMachine, REGSTR_PATH_PCIIR, &hKey) == ERROR_SUCCESS)
{
RegSetValueEx( hKey,
REGSTR_VAL_OPTIONS,
0,
REG_DWORD,
(CONST BYTE *)&options,
sizeof(options));
RegCloseKey(hKey);
}
//
// Reboot if any of the options changed.
//
if (options != gPciHalPropData.Options)
{
SP_DEVINSTALL_PARAMS deviceInstallParams;
memset(&deviceInstallParams, 0, sizeof(deviceInstallParams));
deviceInstallParams.cbSize = sizeof(deviceInstallParams);
if (SetupDiGetDeviceInstallParams( gPciHalPropData.DeviceInfoSet,
gPciHalPropData.DeviceInfoData,
&deviceInstallParams))
{
deviceInstallParams.Flags |= DI_NEEDREBOOT;
SetupDiSetDeviceInstallParams( gPciHalPropData.DeviceInfoSet,
gPciHalPropData.DeviceInfoData,
&deviceInstallParams);
}
}
break;
default:
break;
}
return status;
}
BOOL
PciHalDialogProc(
IN HWND Dialog,
IN UINT Message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
This is the DlgProc for the Pci Irq Routing property sheet page.
Input Parameters:
Standard DlgProc parameters.
Return Value:
TRUE if it handles the message. Else FALSE.
--*/
{
BOOL status = FALSE;
PCWSTR szHelpFile = L"devmgr.hlp";
switch (Message)
{
case WM_INITDIALOG:
status = PciHalOnInitDialog(Dialog, wParam, lParam);
break;
case WM_COMMAND:
status = PciHalOnCommand(Dialog, wParam, lParam);
break;
case WM_NOTIFY:
status = PciHalOnNotify(Dialog, wParam, lParam);
break;
case WM_HELP:
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, szHelpFile, HELP_WM_HELP, (ULONG_PTR)gPciPropHelpIds);
status = TRUE;
break;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, szHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)gPciPropHelpIds);
status = TRUE;
break;
case WM_DESTROY:
if (gPciHalPropData.CloseKey) {
RegCloseKey(gPciHalPropData.LocalMachine);
gPciHalPropData.CloseKey = FALSE;
}
default:
break;
}
return status;
}
DWORD
PciHalCoInstaller(
IN DI_FUNCTION InstallFunction,
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
IN OUT PCOINSTALLER_CONTEXT_DATA Context
)
{
BOOL status;
HPROPSHEETPAGE pageHandle;
PROPSHEETPAGE page;
SP_DEVINFO_LIST_DETAIL_DATA details;
SP_ADDPROPERTYPAGE_DATA addPropertyPageData;
switch (InstallFunction) {
case DIF_ADDPROPERTYPAGE_ADVANCED:
case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
details.cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA);
if (SetupDiGetDeviceInfoListDetail(DeviceInfoSet, &details)) {
if (RegConnectRegistry((details.RemoteMachineName[0] == TEXT('\0'))? NULL : details.RemoteMachineName, HKEY_LOCAL_MACHINE, &gPciHalPropData.LocalMachine) == ERROR_SUCCESS) {
RegCloseKey(gPciHalPropData.LocalMachine);
status = TRUE;
break;
}
}
default:
status = FALSE;
break;
}
if (status) {
ZeroMemory(&addPropertyPageData, sizeof(SP_ADDPROPERTYPAGE_DATA));
addPropertyPageData.ClassInstallHeader.cbSize =
sizeof(SP_CLASSINSTALL_HEADER);
if (SetupDiGetClassInstallParams(DeviceInfoSet, DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&addPropertyPageData,
sizeof(SP_ADDPROPERTYPAGE_DATA), NULL )) {
if (addPropertyPageData.NumDynamicPages < MAX_INSTALLWIZARD_DYNAPAGES) {
//
// Initialize our globals here.
//
gPciHalPropData.DeviceInfoSet = DeviceInfoSet;
gPciHalPropData.DeviceInfoData = DeviceInfoData;
//
// Initialize our property page here.
//
memset(&page, 0, sizeof(PROPSHEETPAGE));
page.dwSize = sizeof(PROPSHEETPAGE);
page.hInstance = MyModuleHandle;
page.pszTemplate = MAKEINTRESOURCE(IDD_PCIHAL_PROPPAGE);
page.pfnDlgProc = PciHalDialogProc;
page.lParam = (LPARAM)&gPciHalPropData;
pageHandle = CreatePropertySheetPage(&page);
if (pageHandle != NULL)
{
addPropertyPageData.DynamicPages[addPropertyPageData.NumDynamicPages++] = pageHandle;
SetupDiSetClassInstallParams(DeviceInfoSet, DeviceInfoData,
(PSP_CLASSINSTALL_HEADER)&addPropertyPageData,
sizeof(SP_ADDPROPERTYPAGE_DATA));
return NO_ERROR;
}
}
}
}
return NO_ERROR;
}