Windows-Server-2003/base/pnp/setupapi/devres.c

4705 lines
143 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995-2000 Microsoft Corporation
Module Name:
devres.c
Abstract:
Routines for displaying resource dialogs.
Author:
Paula Tomlinson (paulat) 7-Feb-1996
Revision History:
Jamie Hunter (jamiehun) 19-Mar-1998
--*/
#include "precomp.h"
#pragma hdrstop
//
// Private Prototypes
//
//
// Global Data
//
static INTERFACE_TYPE ResourcePickerReadOnlyInterfaces[] = {
//
// List of interface-types that we don't want user to edit properties of
//
PCIBus,
//
// End of list
//
InterfaceTypeUndefined
};
static const BOOL ResTypeEditable[ResType_MAX+1] = {
//
// lists resource types that are shown and are editable
FALSE, // ResType_None
TRUE, // ResType_Mem
TRUE, // ResType_IO
TRUE, // ResType_DMA
TRUE, // ResType_IRQ
FALSE, // ResType_DoNotUse
FALSE // ResType_BusNumber
};
#if (ResType_MAX+1) != 7
#error Fix SetupAPI devres.c, ResType_MAX has changed
#endif
//
// HELP ID's
//
static const DWORD DevResHelpIDs[]=
{
IDC_DEVRES_ICON, IDH_NOHELP, // "Low (%d)" (Static)
IDC_DEVRES_DEVDESC, IDH_NOHELP,
IDC_DEVRES_SETTINGSTATE, IDH_DEVMGR_RESOURCES_SETTINGS,
IDC_DEVRES_SETTINGSLIST, IDH_DEVMGR_RESOURCES_SETTINGS,
IDC_DEVRES_LCTEXT, IDH_DEVMGR_RESOURCES_BASEDON,
IDC_DEVRES_LOGCONFIGLIST, IDH_DEVMGR_RESOURCES_BASEDON,
IDC_DEVRES_CHANGE, IDH_DEVMGR_RESOURCES_CHANGE,
IDC_DEVRES_USESYSSETTINGS, IDH_DEVMGR_RESOURCES_AUTO,
IDC_DEVRES_CONFLICTDEVTEXT, IDH_DEVMGR_RESOURCES_CONFLICTS,
IDC_DEVRES_CONFLICTINFOLIST, IDH_DEVMGR_RESOURCES_CONFLICTS,
IDC_DEVRES_MFPARENT, IDH_DEVMGR_RESOURCES_PARENT,
IDC_DEVRES_MFPARENT_DESC, IDH_DEVMGR_RESOURCES_PARENT,
IDC_DEVRES_MAKEFORCED, IDH_DEVMGR_RESOURCES_SETMANUALLY,
0, 0
};
//
// HACKHACK (jamiehun)
// after we've changed UI from a MakeForced, we post this message to get back control of keyboard
//
#define WM_USER_FOCUS (WM_USER+101)
//
// API to obtain a resource-picker page
//
HPROPSHEETPAGE
GetResourceSelectionPage(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData
)
{
LPDMPROP_DATA pdmData;
PROPSHEETPAGE PropPage;
//
// private data
// anything we "do" here must be "undone" in pResourcePickerPropPageCallback
//
pdmData = (LPDMPROP_DATA)MyMalloc(sizeof(DMPROP_DATA));
if (pdmData == NULL) {
return NULL;
}
ZeroMemory(pdmData,sizeof(DMPROP_DATA));
pdmData->hDevInfo = DeviceInfoSet;
pdmData->lpdi = DeviceInfoData;
//
// validate expectations
//
MYASSERT(pdmData->hDevInfo != NULL);
MYASSERT(pdmData->lpdi != NULL);
MYASSERT(pdmData->lpdi->DevInst != 0);
ZeroMemory(&PropPage,sizeof(PropPage));
//
// create the Resources Property Page
//
PropPage.dwSize = sizeof(PROPSHEETPAGE);
PropPage.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
PropPage.hInstance = MyDllModuleHandle;
PropPage.pszTemplate = MAKEINTRESOURCE(IDD_DEF_DEVRESOURCE_PROP);
PropPage.pszIcon = NULL;
PropPage.pszTitle = NULL;
PropPage.pfnDlgProc = pResourcePickerDlgProc;
PropPage.lParam = (LPARAM)pdmData;
PropPage.pfnCallback = pResourcePickerPropPageCallback;
#ifdef _UNICODE
PropPage.dwFlags |= PSP_USEFUSIONCONTEXT;
PropPage.hActCtx = NULL;
#endif
return CreatePropertySheetPage(&PropPage);
} // GetResourceSelectionPage
//
// CreatePropertySheetPage - callback function
//
UINT CALLBACK pResourcePickerPropPageCallback(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp
)
/*++
Routine Description:
Callback to handle cleanup of the property sheet
Arguments:
Standard PropSheetPageProc arguments.
Return Value:
Standard PropSheetPageProc return.
--*/
{
switch (uMsg) {
//case PSPCB_ADDREF:
// break;
case PSPCB_CREATE:
break;
case PSPCB_RELEASE:
//
// release the memory we've previously allocated, outside of the actual dialog
//
if (ppsp->lParam != 0) {
LPDMPROP_DATA pdmData = (LPDMPROP_DATA)(ppsp->lParam);
MyFree(pdmData);
}
break;
}
return TRUE;
}
//
// Main dialog proceedure
//
INT_PTR
CALLBACK
pResourcePickerDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
This routine provides the dialog box procedure for the main resource
picker property page. MEMPHIS COMPATIBLE.
Arguments:
Standard dialog box procedure arguments.
Return Value:
Standard dialog box procedure return.
--*/
{
LPDMPROP_DATA lpdmpd = NULL;
if (message == WM_INITDIALOG) {
lpdmpd = (LPDMPROP_DATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)lpdmpd);
} else {
lpdmpd = (LPDMPROP_DATA)GetWindowLongPtr(hDlg, DWLP_USER);
}
switch (message) {
//
// initialize
//
case WM_INITDIALOG: {
HICON hIcon = NULL;
int iIcon = 0, iIndex = 0;
ULONG ulSize;
PDEVICE_INFO_SET pDeviceInfoSet;
HMACHINE hMachine;
lpdmpd->himlResourceImages = NULL;
lpdmpd->CurrentLC = 0;
lpdmpd->CurrentLCType = 0;
lpdmpd->MatchingLC = 0;
lpdmpd->MatchingLCType = 0;
lpdmpd->SelectedLC = 0;
lpdmpd->SelectedLCType = 0;
lpdmpd->hDlg = hDlg;
lpdmpd->dwFlags = 0;
hMachine = pGetMachine(lpdmpd);
lpdmpd->dwFlags |= DMPROP_FLAG_CHANGESSAVED; // Nothing to save yet
//
// NOTE: On Windows95, since lc info is in memory, they first
// call CM_Setup_DevNode with CM_SETUP_WRITE_LOG_CONFS flag so
// that in-memory lc data is flushed to the registry at this
// point.
//
//
// Init the Resource's image list.
//
lpdmpd->himlResourceImages = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
ILC_MASK, // | ILC_SHARED,
1,
1);
//
// add icons to image list
//
for (iIcon = IDI_RESOURCEFIRST;iIcon < IDI_RESOURCELAST;++iIcon) {
//
// resource icon
//
hIcon = LoadIcon(MyDllModuleHandle, MAKEINTRESOURCE(iIcon));
iIndex = ImageList_AddIcon(lpdmpd->himlResourceImages, hIcon);
}
for (iIcon = IDI_RESOURCEOVERLAYFIRST;iIcon <= IDI_RESOURCEOVERLAYLAST;++iIcon) {
//
// overlay icon
//
hIcon = LoadIcon(MyDllModuleHandle, MAKEINTRESOURCE(iIcon));
iIndex = ImageList_AddIcon(lpdmpd->himlResourceImages, hIcon);
//
// Tag this icon as an overlay icon (the first index is an
// index into the image list (specifies the icon), the
// second index is just an index to assign to each mask
// (starting with 1).
//
ImageList_SetOverlayImage(lpdmpd->himlResourceImages,
iIndex,
iIcon-IDI_RESOURCEOVERLAYFIRST+1);
}
if(pInitDevResourceDlg(lpdmpd)) {
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED; // need to save (prob because there was no config)
}
if (!(lpdmpd->dwFlags & DMPROP_FLAG_NO_RESOURCES)) {
pShowConflicts(lpdmpd);
}
if (GuiSetupInProgress) {
//
// occasionally legacy devices cause resource-picker popup during setup
// we do this here instead of create prop sheet, since I don't trust
// people to cleanup on fail. At least here is less risky
// clean this up in WM_DESTROY
//
lpdmpd->hDialogEvent = CreateEvent(NULL,TRUE,FALSE,SETUP_HAS_OPEN_DIALOG_EVENT);
if (lpdmpd->hDialogEvent) {
SetEvent(lpdmpd->hDialogEvent);
}
} else {
lpdmpd->hDialogEvent = NULL;
}
break;
}
//
// cleanup
//
case WM_DESTROY: {
HICON hIcon;
LOG_CONF LogConf;
LONG nItems, n;
HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
int Count, i;
//
// Clean up the ICON resource usage
//
if ((hIcon = (HICON)LOWORD(SendDlgItemMessage(hDlg,
IDC_DEVRES_ICON, STM_GETICON, 0, 0L)))) {
DestroyIcon(hIcon);
}
//
// free the LC handles that were saved in the combobox data
//
nItems = (LONG)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
CB_GETCOUNT, 0, 0L);
for (n = 0; n < nItems ; n++) {
LogConf = (LOG_CONF)SendDlgItemMessage(hDlg,
IDC_DEVRES_LOGCONFIGLIST,
CB_GETITEMDATA, n, 0L);
CM_Free_Log_Conf_Handle(LogConf);
}
if (lpdmpd->CurrentLC != 0) {
CM_Free_Log_Conf_Handle(lpdmpd->CurrentLC);
}
ListView_DeleteAllItems(hList); // this will destroy all data
if (lpdmpd->himlResourceImages) {
ImageList_Destroy(lpdmpd->himlResourceImages);
}
if (lpdmpd->hDialogEvent) {
//
// we were holding up setup, now let setup proceed
//
ResetEvent(lpdmpd->hDialogEvent);
CloseHandle(lpdmpd->hDialogEvent);
lpdmpd->hDialogEvent = NULL;
}
// MyFree(lpdmpd); - do this in pResourcePickerPropPageCallback instead
break;
}
case WM_COMMAND:
//
// old-style controls
//
switch(LOWORD(wParam)) {
case IDC_DEVRES_USESYSSETTINGS: {
//
// consider resource settings to have changed
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
PropSheet_Changed(GetParent(hDlg), hDlg);
if (IsDlgButtonChecked(hDlg, (int)wParam)) {
//
// Revert back to allocated display, if any
//
lpdmpd->dwFlags |= DMPROP_FLAG_USESYSSETTINGS;
pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
} else {
//
// Allow editing
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_USESYSSETTINGS;
}
pShowUpdateEdit(lpdmpd); // update controls
break;
}
case IDC_DEVRES_LOGCONFIGLIST: {
//
// drop-down list action
//
switch (HIWORD(wParam)) {
case CBN_SELENDOK: {
ULONG ulIndex = 0;
int iItem;
LOG_CONF SelLC;
HWND hwndLC = GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST);
//
// If there is not a Log Config selected, then bail
//
iItem = (int)SendMessage(hwndLC, CB_GETCURSEL, 0, 0);
if(iItem != CB_ERR) {
SelLC = (LOG_CONF)SendMessage(hwndLC,CB_GETITEMDATA, (WPARAM)iItem,(LPARAM)0);
} else {
SelLC = (LOG_CONF)0;
}
if(SelLC != lpdmpd->SelectedLC) {
pSelectLogConf(lpdmpd,SelLC,lpdmpd->ConfigListLCType,FALSE);
}
//
// I prob don't need this here, but I'm playing safe!
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
break;
}
}
break;
}
case IDC_DEVRES_CHANGE: {
//
// change selected setting
//
pChangeCurrentResSetting(lpdmpd);
break;
}
case IDC_DEVRES_MAKEFORCED: {
//
// possibly allow editing (after we've shown message)
// when we get here, always show a configuration
//
if(lpdmpd->dwFlags & DMPROP_FLAG_FORCEDONLY) {
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED; // need to save
}
pShowViewAllEdit(lpdmpd);
//
// select in the first available config to edit
//
pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
//
// ensure we have reasonable focus for accessability
//
PostMessage(hDlg,WM_USER_FOCUS,IDC_DEVRES_SETTINGSLIST,0);
break;
}
default:
break;
}
break;
case WM_USER_FOCUS:
//
// change focus to DlgItem wParam
//
SetFocus(GetDlgItem(hDlg,(int)wParam));
return TRUE;
case WM_NOTIFY: {
//
// new controls & property codes
//
NMHDR * pHdr = (NMHDR*)lParam;
switch (pHdr->code) {
case PSN_SETACTIVE: {
HICON hIcon = NULL, hOldIcon = NULL;
TCHAR szString[MAX_PATH];
ULONG ulSize = 0;
HMACHINE hMachine;
hMachine = pGetMachine(lpdmpd);
//
// Set the ICON and device description
//
if (SetupDiLoadClassIcon(&lpdmpd->lpdi->ClassGuid, &hIcon, NULL)) {
if ((hOldIcon = (HICON)LOWORD(SendDlgItemMessage(hDlg, IDC_DEVRES_ICON,
STM_SETICON,
(WPARAM)hIcon, 0L)))) {
DestroyIcon(hOldIcon);
}
}
//
// First try to get the device's friendly name, then fall back to its description,
// and finally, use the "Unknown Device" description.
//
ulSize = MAX_PATH * sizeof(TCHAR);
if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_FRIENDLYNAME,
NULL, (LPBYTE)szString,
&ulSize, 0,hMachine) != CR_SUCCESS) {
ulSize = MAX_PATH * sizeof(TCHAR);
if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_DEVICEDESC,
NULL, (LPBYTE)szString,
&ulSize, 0,hMachine) != CR_SUCCESS) {
LoadString(MyDllModuleHandle, IDS_DEVNAME_UNK, szString, MAX_PATH);
}
}
SetDlgItemText(hDlg, IDC_DEVRES_DEVDESC, szString);
break;
}
case PSN_APPLY: {
BOOL bRet = FALSE;
//
// If there were Changes and they haven't been saved,
// then save them.
// consider some special cases as "haven't been saved"
//
if((lpdmpd->CurrentLC == 0) && (lpdmpd->dwFlags&DMPROP_FLAG_FIXEDCONFIG)) {
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
}
switch(pOkToSave(lpdmpd)) {
case IDNO:
//
// proceed without saving
//
bRet = TRUE;
break;
case IDCANCEL:
//
// don't proceed
//
bRet = FALSE;
break;
case IDYES:
//
// proceed and save
//
bRet = pSaveDevResSettings(lpdmpd);
#if 0
if (bRet) {
if ((lpdmpd->lpdi)->Flags & DI_NEEDREBOOT) {
PropSheet_RebootSystem(GetParent(hDlg));
} else if ((lpdmpd->lpdi)->Flags & DI_NEEDRESTART) {
PropSheet_RestartWindows(GetParent(hDlg));
}
#endif
if (bRet) {
//
// This page doesn't support roll-back, if we saved
// something then we're committed, disable the cancel
// botton.
//
PropSheet_CancelToClose(GetParent(hDlg));
}
break;
default:
MYASSERT(FALSE /* pOkToSave returned invalid value */);
bRet = FALSE;
break;
}
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, bRet ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE);
return TRUE;
}
case LVN_DELETEALLITEMS:
if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
return FALSE; // we want LVN_DELETEITEM messages
}
break;
case LVN_DELETEITEM: {
LPNMLISTVIEW pListView = (LPNMLISTVIEW)pHdr;
if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
PITEMDATA pItemData = (PITEMDATA)(LPVOID)(pListView->lParam);
//
// when an item is deleted, destroy associated data
//
if (pItemData->MatchingResDes) {
CM_Free_Res_Des_Handle(pItemData->MatchingResDes);
}
MyFree(pItemData);
}
break;
}
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
break;
case LVN_ITEMCHANGED:
//
// If the item change is comming from the resource
// list, and there is a logconfig to be edited:
//
if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
//
// see if we should enable resource change
//
pCheckEnableResourceChange(lpdmpd);
}
break;
case NM_DBLCLK:
//
// If the double click is from the SETTINGS list
// AND the DEVRES_CHANGE button is enabled, then
// allow the change.
//
if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
//
// this routine should check that we can change settings
//
pChangeCurrentResSetting(lpdmpd);
}
break;
}
break;
}
case WM_SYSCOLORCHANGE: {
HWND hChildWnd = GetWindow(hDlg, GW_CHILD);
while (hChildWnd != NULL) {
SendMessage(hChildWnd, WM_SYSCOLORCHANGE, wParam, lParam);
hChildWnd = GetWindow(hChildWnd, GW_HWNDNEXT);
}
break;
}
case WM_HELP: // F1
WinHelp(((LPHELPINFO)lParam)->hItemHandle, DEVRES_HELP, HELP_WM_HELP, (ULONG_PTR)DevResHelpIDs);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND)wParam, DEVRES_HELP, HELP_CONTEXTMENU, (ULONG_PTR)DevResHelpIDs);
break;
}
return FALSE;
}
//
// Helper functions
//
HMACHINE
pGetMachine(
LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Retrieve Machine Handle
Arguments:
lpdmpd - Property Data
Return Value:
handle
--*/
{
HMACHINE hMachine;
PDEVICE_INFO_SET pDeviceInfoSet;
if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
return NULL;
}
hMachine = pDeviceInfoSet->hMachine;
UnlockDeviceInfoSet(pDeviceInfoSet);
return hMachine;
}
BOOL
pInitDevResourceDlg(
LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
This routine intializes the main resource picker property page.
MEMPHIS COMPATIBLE.
Arguments:
Return Value:
TRUE if "not saved"
--*/
{
HWND hDlg = lpdmpd->hDlg;
CONFIGRET Status = CR_SUCCESS;
BOOL bHasCurrent = FALSE;
BOOL bShowCurrent = FALSE;
BOOL bHasForced = FALSE;
BOOL bNoForcedConfig = FALSE;
BOOL bNeedsForcedConfig = FALSE;
BOOL bHasConfigList = FALSE;
LV_COLUMN LvCol;
HWND hWndList = NULL;
TCHAR szString[MAX_PATH], szTemp[MAX_PATH], szConfigType[MAX_PATH],
szConfig[MAX_PATH];
ULONG ulIndex = 0, ulSize = 0, DevStatus = 0, DevProblem = 0;
DWORD BusType = (DWORD)(-1);
LOG_CONF LogConf;
DWORD dwPriority = 0;
WORD wItem;
ULONG ConfigFlags;
HMACHINE hMachine = NULL;
PDEVICE_INFO_SET pDeviceInfoSet;
int iIndex;
BOOL bHasPrivs = FALSE;
//
// Set initial control states
//
pHideAllControls(lpdmpd);
//
// determine priv token
// security checks are visual only
// real security checks are done in umpnpmgr
//
bHasPrivs = pSetupDoesUserHavePrivilege(SE_LOAD_DRIVER_NAME);
hMachine = pGetMachine(lpdmpd);
//
// retrieves current configuration, if any
//
bHasCurrent = pGetCurrentConfig(lpdmpd);
//
// We sometimes get called to show this page even if the device
// doesn't consume any resources. Check for that case and if so, just
// display an informational message and disable everything else.
//
if (!pDevRequiresResources(lpdmpd->lpdi->DevInst,hMachine)) {
//
// This device has no resources
//
pShowViewNoResources(lpdmpd);
lpdmpd->dwFlags |= DMPROP_FLAG_NO_RESOURCES;
goto Final;
}
//
// Initialize the ListView control
//
hWndList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
LvCol.mask = LVCF_TEXT;
if (LoadString(MyDllModuleHandle, IDS_RESOURCETYPE, szString, MAX_PATH)) {
LvCol.pszText = (LPTSTR)szString;
ListView_InsertColumn(hWndList, 0, (LV_COLUMN FAR *)&LvCol);
}
if (LoadString(MyDllModuleHandle, IDS_RESOURCESETTING, szString, MAX_PATH)) {
LvCol.pszText = (LPTSTR)szString;
ListView_InsertColumn(hWndList, 1, (LV_COLUMN FAR *)&LvCol);
}
ListView_SetImageList(hWndList,lpdmpd->himlResourceImages, LVSIL_SMALL);
//
// Get DevStatus & DevProblem here, we may use this info further down
//
if (CM_Get_DevNode_Status_Ex(&DevStatus, &DevProblem, lpdmpd->lpdi->DevInst,
0,hMachine) != CR_SUCCESS) {
//
// we should never get here, show this as a problem
//
lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
} else if (DevStatus & DN_HAS_PROBLEM) {
//
// cache problem flag away
//
lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
} else if (DevStatus & DN_PRIVATE_PROBLEM) {
//
// driver indicates problem
// for now, do same as above
//
lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
}
if (bIsMultiFunctionChild(lpdmpd->lpdi,hMachine)) {
//
// If this is a MultiFunction Child, disable all change controls, put up
// special text, and show the alloc config
//
pShowViewMFReadOnly(lpdmpd,FALSE);
goto Final;
}
//
// begin with read-only view, assuming settings are system
//
lpdmpd->dwFlags |= DMPROP_FLAG_USESYSSETTINGS;
if (CM_Get_First_Log_Conf_Ex(NULL,
lpdmpd->lpdi->DevInst,
FORCED_LOG_CONF,
hMachine) == CR_SUCCESS) {
//
// the user currently has a forced config
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_USESYSSETTINGS;
bHasForced = TRUE;
}
bShowCurrent = pShowViewReadOnly(lpdmpd,bHasPrivs);
if (!bHasPrivs || hMachine) {
//
// if we don't have enough priv's
// or we're displaying resources of a remote machine
// bottle out here
// we'll either be displaying current resources
// or displaying a problem
//
goto Final;
}
if(!bHasForced) {
//
// Check bus we're using
// to see if it's one of the read-only displays
//
ulSize = sizeof(BusType);
if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_LEGACYBUSTYPE,
NULL, (LPBYTE)&BusType,
&ulSize, 0,hMachine) != CR_SUCCESS) {
BusType = (DWORD)InterfaceTypeUndefined;
}
if (BusType != (DWORD)InterfaceTypeUndefined) {
int InterfaceItem;
for(InterfaceItem = 0; ResourcePickerReadOnlyInterfaces[InterfaceItem] != InterfaceTypeUndefined; InterfaceItem++) {
if (BusType == (DWORD)ResourcePickerReadOnlyInterfaces[InterfaceItem]) {
//
// Bus is one that we do not allow forced configs
// we can skip all the funky code below
//
// this is a good thing for 64-bit PCI
//
goto Final;
}
}
}
}
//
// Retrieve alternate configurations for this device
//
if (bHasCurrent) {
//
// Current config (if any) is indicated with zero handle
//
LoadString(MyDllModuleHandle, IDS_CURRENTCONFIG, szString, MAX_PATH);
iIndex = (int)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPSTR)szString);
SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETITEMDATA,(WPARAM)iIndex, (LPARAM)0);
SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETCURSEL,(WPARAM)0, (LPARAM)0);
}
//
// now fill in alternate configurations
// override preferred over basic (in that order)
// don't use Filtered, filtered might remove configs that require reboot
// but they are fine to have here
//
if(CM_Get_First_Log_Conf_Ex(&LogConf,lpdmpd->lpdi->DevInst,OVERRIDE_LOG_CONF,hMachine) == CR_SUCCESS) {
lpdmpd->ConfigListLCType = OVERRIDE_LOG_CONF;
LoadString(MyDllModuleHandle, IDS_OVERRIDECONFIG, szConfigType, MAX_PATH);
bHasConfigList = TRUE;
} else if(CM_Get_First_Log_Conf_Ex(&LogConf,lpdmpd->lpdi->DevInst,BASIC_LOG_CONF,hMachine) == CR_SUCCESS) {
lpdmpd->ConfigListLCType = BASIC_LOG_CONF;
LoadString(MyDllModuleHandle, IDS_BASICCONFIG, szConfigType, MAX_PATH);
bHasConfigList = TRUE;
} else {
//
// If there are no alternate configs, we cannot allow a forced config
//
bNoForcedConfig = TRUE; // cannot force
bHasConfigList = FALSE;
lpdmpd->ConfigListLCType = BASIC_LOG_CONF;
lpdmpd->dwFlags |= DMPROP_FLAG_SINGLE_CONFIG;
}
if(bHasConfigList) {
ulIndex = 0;
if (!pConfigHasNoAlternates(lpdmpd,LogConf)) {
//
// first configuration has more than one alternative
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_SINGLE_CONFIG;
} else {
//
// begin with the assumption there is a single fixed 'basic' config
// we will generally be proved wrong
//
lpdmpd->dwFlags |= DMPROP_FLAG_SINGLE_CONFIG;
}
while (Status == CR_SUCCESS) {
//
// Add this config to the Combobox
//
wsprintf(szTemp, TEXT("%s %04u"), szConfigType, ulIndex);
wItem = (WORD)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
CB_ADDSTRING, 0,
(LPARAM)(LPSTR)szTemp);
//
// Save the log config handle as the item data in the combobox
//
SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETITEMDATA,
wItem, (LPARAM)LogConf);
//
// Get the next config
//
Status = CM_Get_Next_Log_Conf_Ex(&LogConf, LogConf, 0,hMachine);
ulIndex++;
}
if (ulIndex > 1) {
//
// there is more than one config
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_SINGLE_CONFIG;
}
if (lpdmpd->dwFlags & DMPROP_FLAG_SINGLE_CONFIG) {
bNoForcedConfig = TRUE;
}
if (bHasCurrent) {
//
// try to find a matching LC now, and if we could find one,
// re-load current display (this applies editable ranges to the resources)
//
if(pFindMatchingAllocConfig(lpdmpd)) {
pLoadCurrentConfig(lpdmpd,TRUE);
}
}
} else {
}
//
// Get ConfigFlags here, we may use this info further down
//
ulSize = sizeof(ConfigFlags);
if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_CONFIGFLAGS,
NULL, (LPBYTE)&ConfigFlags,
&ulSize, 0,hMachine) != CR_SUCCESS) {
ConfigFlags = 0;
}
if (ConfigFlags & CONFIGFLAG_NEEDS_FORCED_CONFIG) {
//
// registry says that we need a forced config
// registry can only say this to us once
//
bNeedsForcedConfig = TRUE;
ConfigFlags &= ~CONFIGFLAG_NEEDS_FORCED_CONFIG;
CM_Set_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_CONFIGFLAGS,
(LPBYTE)&ConfigFlags,
sizeof(ConfigFlags),
0,
hMachine);
}
//
// determine if it can be software-config'd or not
// we need to do this prior to any initial display
//
dwPriority = pGetMinLCPriority(lpdmpd->lpdi->DevInst, lpdmpd->ConfigListLCType,hMachine);
if (dwPriority < LCPRI_HARDRECONFIG) {
//
// doesn't need to be manually configured
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_FORCEDONLY;
} else {
//
// this cannot be software config'd
// FORCEDONLY & bNoForcedConfig is a quandry, shouldn't happen
//
lpdmpd->dwFlags |= DMPROP_FLAG_FORCEDONLY;
if(!bHasConfigList) {
MYASSERT(bHasConfigList);
} else {
MYASSERT(!bNoForcedConfig);
bNoForcedConfig = FALSE;
}
}
//
// Try to determine initial display
//
// we've already covered pShowViewNoResources (no actual or potential configs)
// and pShowViewMFReadOnly (it's a multi-function device)
//
// we're currently showing as pShowViewReadOnly
//
// some cases....
// (1) show forced config, don't allow auto-config (config flags say requires forced)
// (2) show forced config, allow auto-config
// (3) don't show any config, but maybe show a forced-config button
// (4) auto-config, don't allow forced config
// (5) show auto-config, allow forced-config
//
if (bNeedsForcedConfig) {
if (!bHasConfigList) {
MYASSERT(bHasConfigList);
bNeedsForcedConfig = FALSE;
} else {
MYASSERT(!bNoForcedConfig);
bNoForcedConfig = FALSE;
if (bHasForced) {
//
// already got one, but we'll go through the motions
// we'll show what we have, allow user to change it
// but we wont needlessly save it
//
bNeedsForcedConfig = FALSE;
}
//
// caller said that device must have forced config, so go immediately there
// = case (1) unless we've otherwise said we cannot have a forced config
//
lpdmpd->dwFlags |= DMPROP_FLAG_FORCEDONLY;
pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
pShowViewAllEdit(lpdmpd);
goto Final;
}
}
if ((!bShowCurrent) || (lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
//
// determine between pShowViewNoAlloc and pShowViewNeedForced
//
if (bNoForcedConfig) {
//
// there is a problem - device doesn't currently have a current configuration
// but we don't have the option of letting them set forced config
// so this ends up display only (tough-luck scenario)
// if there are current resources, show them
//
pShowViewReadOnly(lpdmpd,FALSE);
} else {
//
// we show the problem and we give the user
// an option to force config
//
pShowViewNeedForced(lpdmpd);
}
goto Final;
}
if (!bHasConfigList) {
//
// If we have a current config, but no basic configs, we just display what we have
// and don't give option to edit
//
pShowViewReadOnly(lpdmpd,FALSE);
goto Final;
}
if ((lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) && bNoForcedConfig) {
//
// we can't force a bNoForcedConfig item - display only
//
pShowViewReadOnly(lpdmpd,FALSE);
goto Final;
}
//
// we already have and will be displaying a current config
//
pShowViewAllEdit(lpdmpd);
bNeedsForcedConfig = (BOOL)!bHasCurrent; // rarely, if ever, will this return TRUE
Final:
return bNeedsForcedConfig;
} // InitDevResourceDlg
PITEMDATA
pGetResourceToChange(
IN LPDMPROP_DATA lpdmpd,
OUT int *pCur
)
/*++
Routine Description:
Gets resource to change
NULL if we cannot change resource
Arguments:
lpdmpd = dialog data
pCur = (out) index
Return Value:
PITEMDATA saved for selected resource
--*/
{
HWND hList = GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_SETTINGSLIST);
PITEMDATA pItemData = NULL;
int iCur;
//
// first check the obvious
//
if (lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES) {
//
// no editing allowed
//
return NULL;
}
if (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) {
//
// showing system settings
//
return NULL;
}
//
// Check if there is a selected item.
// If yes, then activate the change button
// if the LC allows editing.
//
iCur = (int)ListView_GetNextItem(hList,-1, LVNI_SELECTED);
if (iCur == LB_ERR) {
//
// no selection
//
return NULL;
}
pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
if (pItemData == NULL) {
//
// shouldn't happen
//
MYASSERT(pItemData);
return NULL;
}
if (pItemData->bFixed) {
//
// this is an un-editable setting
//
return NULL;
}
if (pItemData->MatchingResDes == (RES_DES)0) {
//
// should be caught by bFixed
//
MYASSERT(pItemData->MatchingResDes != (RES_DES)0);
return NULL;
}
//
// we're happy
//
if (pCur) {
*pCur = iCur;
}
return pItemData;
}
VOID
pCheckEnableResourceChange(
LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
enables/disable change button
Arguments:
Return Value:
none
--*/
{
#if 0 // this seems to confuse people
EnableWindow(GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_CHANGE),
pGetResourceToChange(lpdmpd,NULL)!=NULL);
#endif // 0
//
// show this button enabled if we are in EDIT mode
//
EnableWindow(GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_CHANGE),
(lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES)==0 &&
(lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)==0);
}
BOOL
pDevHasConfig(
DEVINST DevInst,
ULONG ulConfigType,
HMACHINE hMachine
)
/*++
Routine Description:
This routine determines whether a log config of the specified type
exists for this device instance.
MEMPHIS COMPATIBLE.
Arguments:
DevInst Device instance to query log configs for.
ulConfigType Specifies the type of log conf to check for the presense of.
Return Value:
TRUE if the device has a config of that type and FALSE if it does not.
--*/
{
BOOL bRet = (CM_Get_First_Log_Conf_Ex(NULL, DevInst, ulConfigType,hMachine) == CR_SUCCESS);
return bRet;
} // DevHasConfig
DWORD
pGetMinLCPriority(
IN DEVINST DevInst,
IN ULONG ulConfigType,
IN HMACHINE hMachine
)
/*++
Routine Description:
This routine returns the minimum priority value of all log confs of the
specified type for this device. MEMPHIS COMPATIBLE.
Arguments:
DevInst Device instance to query log configs for.
ulConfigType Specifies the type of log conf.
Return Value:
Returns the minimum priority value found or LCPRI_LASTSOFTCONFIG if no priorities
are found.
--*/
{
CONFIGRET Status = CR_SUCCESS;
ULONG priority, minPriority = MAX_LCPRI;
LOG_CONF LogConf, tempLC;
BOOL FoundOneLogConfWithPriority = FALSE;
//
// Walk through each log conf of this type for this device and
// save the smallest value.
//
Status = CM_Get_First_Log_Conf_Ex(&LogConf, DevInst, ulConfigType,hMachine);
while (Status == CR_SUCCESS) {
if (CM_Get_Log_Conf_Priority_Ex(LogConf, &priority, 0,hMachine) == CR_SUCCESS) {
FoundOneLogConfWithPriority = TRUE;
minPriority = min(minPriority, priority);
}
tempLC = LogConf;
Status = CM_Get_Next_Log_Conf_Ex(&LogConf, LogConf, 0,hMachine);
CM_Free_Log_Conf_Handle(tempLC);
}
if(FoundOneLogConfWithPriority) {
return minPriority;
} else {
//
// None of the LogConfigs had an associated priority. This is common on
// NT, because the bus drivers don't specify ConfigMgr-style priorities
// when responding to IRQ_MN_QUERY_RESOURCE_REQUIREMENTS. Since these
// cases are all PnP bus drivers, however, it is most correct to specify
// these LogConfigs as soft-settable.
//
return LCPRI_LASTSOFTCONFIG;
}
} // GetMinLCPriority
BOOL
pDevRequiresResources(
DEVINST DevInst,
HMACHINE hMachine
)
{
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, BASIC_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, FILTERED_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, OVERRIDE_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, BOOT_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, ALLOC_LOG_CONF,hMachine) == CR_SUCCESS) {
return TRUE;
}
return FALSE;
} // DevRequiresResources
BOOL
pGetCurrentConfig(
IN OUT LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
This routine determines the current known configuration
current configs are either forced, alloc or boot configs.
Arguments:
lpdmpd Property data.
Return Value:
TRUE if we set the current config
--*/
{
PDEVICE_INFO_SET pDeviceInfoSet;
HMACHINE hMachine;
ULONG Status;
ULONG Problem;
MYASSERT(lpdmpd!=NULL);
MYASSERT(lpdmpd->lpdi!=NULL);
MYASSERT(lpdmpd->CurrentLC==0);
MYASSERT(lpdmpd->lpdi->DevInst!=0);
if (lpdmpd==NULL ||
lpdmpd->lpdi==NULL ||
lpdmpd->lpdi->DevInst==0) {
return FALSE;
}
lpdmpd->dwFlags &= ~DMPROP_FLAG_DISPLAY_MASK;
if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
return FALSE;
}
hMachine = pDeviceInfoSet->hMachine;
UnlockDeviceInfoSet (pDeviceInfoSet);
if (CM_Get_DevNode_Status_Ex(&Status, &Problem, lpdmpd->lpdi->DevInst,
0,hMachine) != CR_SUCCESS) {
Problem = 0;
Status = 0;
} else if((Status & DN_HAS_PROBLEM)==0) {
//
// If this device is running, does this devinst have a ALLOC log config?
//
if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
lpdmpd->lpdi->DevInst,
ALLOC_LOG_CONF,
hMachine) == CR_SUCCESS) {
lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_ALLOC;
lpdmpd->CurrentLCType = ALLOC_LOG_CONF;
return TRUE;
}
}
//
// If no config so far, does it have a FORCED log config?
//
if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
lpdmpd->lpdi->DevInst,
FORCED_LOG_CONF,
hMachine) == CR_SUCCESS) {
lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_FORCED;
lpdmpd->CurrentLCType = FORCED_LOG_CONF;
return TRUE;
}
//
// if there's a hardware-disabled problem, boot-config isn't valid
//
if(((Status & DN_HAS_PROBLEM)==0) || (Problem != CM_PROB_HARDWARE_DISABLED)) {
//
// Does it have a BOOT log config?
//
if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
lpdmpd->lpdi->DevInst,
BOOT_LOG_CONF,
hMachine) == CR_SUCCESS) {
lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_BOOT;
lpdmpd->CurrentLCType = BOOT_LOG_CONF;
return TRUE;
}
}
return FALSE;
}
void
pGetHdrValues(
IN LPBYTE pData,
IN RESOURCEID ResType,
OUT PULONG64 pulValue,
OUT PULONG64 pulLen,
OUT PULONG64 pulEnd,
OUT PULONG pulFlags
)
{
switch (ResType) {
case ResType_Mem: {
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
*pulValue = pMemData->MEM_Header.MD_Alloc_Base;
*pulLen = (pMemData->MEM_Header.MD_Alloc_End -
pMemData->MEM_Header.MD_Alloc_Base + 1);
*pulEnd = pMemData->MEM_Header.MD_Alloc_End;
*pulFlags = pMemData->MEM_Header.MD_Flags;
break;
}
case ResType_IO: {
PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
*pulValue = pIoData->IO_Header.IOD_Alloc_Base;
*pulLen = (pIoData->IO_Header.IOD_Alloc_End -
pIoData->IO_Header.IOD_Alloc_Base + 1);
*pulEnd = pIoData->IO_Header.IOD_Alloc_End;
*pulFlags = pIoData->IO_Header.IOD_DesFlags;
break;
}
case ResType_DMA: {
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
*pulValue = pDmaData->DMA_Header.DD_Alloc_Chan;
*pulLen = 1;
*pulEnd = *pulValue;
*pulFlags = pDmaData->DMA_Header.DD_Flags;
break;
}
case ResType_IRQ: {
DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
*pulValue = pIrqData->IRQ_Header.IRQD_Alloc_Num;
*pulLen = 1;
*pulEnd = *pulValue;
*pulFlags = pIrqData->IRQ_Header.IRQD_Flags;
break;
}
}
if(*pulEnd < *pulValue) {
//
// filter out bad/zero-length range
//
*pulLen = 0;
}
return;
} // GetHdrValues
void
pGetRangeValues(
IN LPBYTE pData,
IN RESOURCEID ResType,
IN ULONG ulIndex,
OUT PULONG64 pulValue, OPTIONAL
OUT PULONG64 pulLen, OPTIONAL
OUT PULONG64 pulEnd, OPTIONAL
OUT PULONG64 pulAlign, OPTIONAL
OUT PULONG pulFlags OPTIONAL
)
{
//
// keep local copies
// we transfer to parameters at end
//
ULONG64 ulValue;
ULONG64 ulLen;
ULONG64 ulEnd;
ULONG64 ulAlign;
ULONG ulFlags;
switch (ResType) {
case ResType_Mem: {
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
ulValue = pMemData->MEM_Data[ulIndex].MR_Min;
ulLen = pMemData->MEM_Data[ulIndex].MR_nBytes;
ulEnd = pMemData->MEM_Data[ulIndex].MR_Max;
ulFlags = pMemData->MEM_Data[ulIndex].MR_Flags;
ulAlign = pMemData->MEM_Data[ulIndex].MR_Align;
break;
}
case ResType_IO: {
PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
ulValue = pIoData->IO_Data[ulIndex].IOR_Min;
ulLen = pIoData->IO_Data[ulIndex].IOR_nPorts;
ulEnd = pIoData->IO_Data[ulIndex].IOR_Max;
ulFlags = pIoData->IO_Data[ulIndex].IOR_RangeFlags;
ulAlign = pIoData->IO_Data[ulIndex].IOR_Align;
break;
}
case ResType_DMA: {
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
ulValue = pDmaData->DMA_Data[ulIndex].DR_Min;
ulLen = 1;
ulEnd = ulValue;
ulFlags = pDmaData->DMA_Data[ulIndex].DR_Flags;
ulAlign = 1;
break;
}
case ResType_IRQ: {
DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
ulValue = pIrqData->IRQ_Data[ulIndex].IRQR_Min;
ulLen = 1;
ulEnd = ulValue;
ulFlags = pIrqData->IRQ_Data[ulIndex].IRQR_Flags;
ulAlign = 1;
break;
}
}
if(ulEnd < ulValue) {
//
// filter out bad/zero-length range
//
ulLen = 0;
}
pAlignValues(&ulValue, ulValue, ulLen, ulEnd, ulAlign,1);
//
// copy return parameters
//
if (pulValue) {
*pulValue = ulValue;
}
if (pulLen) {
*pulLen = ulLen;
}
if (pulEnd) {
*pulEnd = ulEnd;
}
if (pulAlign) {
*pulAlign = ulAlign;
}
if (pulFlags) {
*pulFlags = ulFlags;
}
return;
}
BOOL
pAlignValues(
IN OUT PULONG64 pulValue,
IN ULONG64 ulStart,
IN ULONG64 ulLen,
IN ULONG64 ulEnd,
IN ULONG64 ulAlignment,
IN int Increment
)
{
ULONG64 NtAlign = ~ulAlignment + 1; // convert from mask to modulus
ULONG64 Value;
ULONG64 Upp;
ULONG64 Remainder;
Value = *pulValue;
if (NtAlign == 0) {
return FALSE; // bogus alignment value
}
if (NtAlign != 1 && Increment != 0) {
//
// see if we are aligned
//
Remainder = Value % NtAlign;
if (Remainder != 0) {
//
// need to re-align
//
if (Increment>0) {
//
// Return the first valid aligned value greater than this value
//
Value += NtAlign - Remainder;
if (Value <= *pulValue) {
//
// overflow detected
//
return FALSE;
}
} else {
//
// Return the first valid aligned value less than this value
//
Value -= Remainder;
//
// we never overflow going down, since zero is a common denominator
// of alignment
//
}
}
}
//
// now check boundaries
//
if (Value < ulStart) {
return FALSE;
}
Upp = Value+ulLen-1;
if (Upp < Value) {
//
// catch overflow error
//
return FALSE;
}
if (Upp > ulEnd) {
return FALSE;
}
//
// set newly aligned value
//
*pulValue = Value;
return TRUE;
}
void
pFormatResString(
LPDMPROP_DATA lpdmpd,
LPTSTR lpszString,
ULONG64 ulVal,
ULONG64 ulLen,
RESOURCEID ResType
)
{
if (ulLen == 0) {
wsprintf(lpszString, szNoValue);
} else if ((ResType == ResType_DMA) || (ResType == ResType_IRQ)) {
wsprintf(lpszString, szOneDecNoConflict, (UINT)ulVal);
} else if (ResType == ResType_IO) {
wsprintf(lpszString, szTwoWordHexNoConflict, (ULONG)ulVal,
(ULONG)(ulVal + ulLen - 1));
} else if ((ulVal+(ulLen-1)) >= 0x100000000) {
//
// NTRAID # 712013 - this needs to be improved
//
wsprintf(lpszString, szTwo64bitHexNoConflict, (ULONG64)ulVal,
(ULONG64)(ulVal + ulLen - 1));
} else {
wsprintf(lpszString, szTwoDWordHexNoConflict, (ULONG)ulVal,
(ULONG)(ulVal + ulLen - 1));
}
}
BOOL
pUnFormatResString(
LPTSTR lpszString,
PULONG64 pulVal,
PULONG64 pulEnd,
RESOURCEID ridResType
)
{
BOOL bRet = FALSE;
LPTSTR lpszTemp = NULL;
LPTSTR lpszTemp2 = NULL;
LPTSTR lpszCopy;
// ISSUE-2000/02/03 Fix pUnFormatResString bugs
//
// - extend this to handling DWORDLONG values
// - use correct Prev/Next functions for parsing string
//
//
// Allocate space for, and make a copy of the input string
//
lpszCopy = MyMalloc((lstrlen(lpszString)+1) * sizeof(TCHAR));
if (lpszCopy == NULL) {
return FALSE;
}
lstrcpy(lpszCopy, lpszString);
//
// Locate the dash if there is one, and convert the white space prev to
// the dash to a NULL. (ie 0200 - 0400 while be 0200)
//
lpszTemp = lpszCopy;
while ((*lpszTemp != '-') && (*lpszTemp != '\0')) {
lpszTemp++; // AnsiNext?
}
if (*lpszTemp != '\0') {
lpszTemp2 = lpszTemp-1;
++lpszTemp;
}
//
// Search back to set the NULL for the Value
//
if (lpszTemp2 != NULL) {
while ((*lpszTemp2 == ' ') || (*lpszTemp2 == '\t'))
lpszTemp2--; // AnsiPrev?
*(lpszTemp2+1)= '\0';
}
//
// Convert the first entry
//
if (pConvertEditText(lpszCopy, pulVal, ridResType)) {
//
// If there is a second entry, convert it, otherwise assume a length
// of one.
//
if (*lpszTemp != '\0') {
if (pConvertEditText(lpszTemp, pulEnd,ridResType)) {
bRet = TRUE;
}
} else {
*pulEnd = *pulVal;
bRet = TRUE;
}
}
MyFree(lpszCopy);
return bRet;
}
BOOL
pConvertEditText(
LPTSTR lpszConvert,
PULONG64 pulVal,
RESOURCEID ridResType
)
{
LPTSTR lpConvert;
if ((ridResType == ResType_Mem) || (ridResType == ResType_IO)) {
*pulVal = _tcstoul(lpszConvert, &lpConvert, (WORD)16);
} else {
*pulVal = _tcstoul(lpszConvert, &lpConvert, (WORD)10);
}
if (lpConvert == lpszConvert+lstrlen(lpszConvert)) {
return TRUE;
} else {
return FALSE;
}
} // ConvertEditText
void
pWarnResSettingNotEditable(
HWND hDlg,
WORD idWarning
)
{
TCHAR szTitle[MAX_PATH];
TCHAR szMessage[MAX_PATH * 2];
//
// Give some warning Messages. If there is no logconfig,
// then we cannot edit any settings, if there is, then
// just the setting they are choosing is not editable.
//
LoadString(MyDllModuleHandle, IDS_DEVRES_NOMODIFYTITLE, szTitle, MAX_PATH);
LoadString(MyDllModuleHandle, idWarning, szMessage, MAX_PATH * 2);
MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONEXCLAMATION);
} // WarnResSettingsNotEditable
int
pWarnNoSave(
HWND hDlg,
WORD idWarning
)
/*++
Routine Description:
Warn that the settings will not be saved
Arguments:
Return Value:
IDCANCEL = don't proceed
IDOK/IDYES/IDNO = proceed without saving
--*/
{
TCHAR szTitle[MAX_PATH];
TCHAR szMessage[MAX_PATH * 2];
int res;
//
// Give a warning message of why we can't save settings
//
LoadString(MyDllModuleHandle, IDS_MAKE_FORCED_TITLE, szTitle, MAX_PATH);
LoadString(MyDllModuleHandle, idWarning, szMessage, MAX_PATH * 2);
//res = MessageBox(hDlg, szMessage, szTitle, MB_OKCANCEL | MB_TASKMODAL | MB_ICONEXCLAMATION);
//return res;
res = MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONEXCLAMATION);
return IDCANCEL;
}
LPVOID
pGetListViewItemData(
HWND hList,
int iItem,
int iSubItem
)
{
LV_ITEM lviItem;
lviItem.mask = LVIF_PARAM;
lviItem.iItem = iItem;
lviItem.iSubItem = iSubItem;
if (ListView_GetItem(hList, &lviItem)) {
return (LPVOID)lviItem.lParam;
} else {
return NULL;
}
} // GetListViewItemData
BOOL
pSaveDevResSettings(
LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
This routine saves the resources based on the users selections.
MEMPHIS COMPATIBLE.
Arguments:
lpdmpd Property data.
Return Value:
Returns TRUE if the function succeeded and FALSE if it failed.
--*/
{
HWND hDlg = lpdmpd->hDlg;
HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
CONFIGRET Status = CR_SUCCESS;
LOG_CONF ForcedLogConf;
RES_DES ResDes, ResDesTemp, ResDes1;
RESOURCEID ResType;
ULONG ulSize = 0, ulCount = 0, i = 0, iCur = 0;
LPBYTE pData = NULL;
PITEMDATA pItemData = NULL;
BOOL bRet = TRUE;
SP_PROPCHANGE_PARAMS PropChangeParams;
HMACHINE hMachine = pGetMachine(lpdmpd);
if ((lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)!=0) {
//-------------------------------------------------------------------
// If the user checked the "Use Automatic Settings" checkbox, then
// delete any Boot/Forced configs, otherwise write the current settings
// as a forced config.
//-------------------------------------------------------------------
if (CM_Get_First_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst,
FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
CM_Free_Log_Conf_Ex(ForcedLogConf, 0,hMachine);
CM_Free_Log_Conf_Handle(ForcedLogConf);
}
// Let the helper modules (class installer/co-installers) get in on the act...
//
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.StateChange = DICS_PROPCHANGE;
PropChangeParams.Scope = DICS_FLAG_GLOBAL;
// no need to set PropChangeParams.HwProfile, since this is a global property change.
DoInstallActionWithParams(DIF_PROPERTYCHANGE,
lpdmpd->hDevInfo,
lpdmpd->lpdi,
(PSP_CLASSINSTALL_HEADER)&PropChangeParams,
sizeof(PropChangeParams),
INSTALLACTION_CALL_CI
);
} else {
//-------------------------------------------------------------------
// The Use Automatic Settings is not selected.
//-------------------------------------------------------------------
bRet = pSaveCustomResSettings(lpdmpd,hMachine);
}
return bRet;
}
BOOL
pSaveCustomResSettings(
LPDMPROP_DATA lpdmpd,
IN HMACHINE hMachine
)
/*++
Routine Description:
This routine saves custom (user edited) resources. MEMPHIS COMPATIBLE but
extracted from Memphis version of SaveDevResSetting().
Arguments:
lpdmpd Property data.
Return Value:
Returns TRUE if the function succeeded and FALSE if it failed.
--*/
{
HWND hDlg = lpdmpd->hDlg;
TCHAR szWarn[MAX_MSG_LEN];
TCHAR szTitle[MAX_MSG_LEN];
TCHAR szTemp[MAX_MSG_LEN];
DWORD dwPriority, dwLCPri;
LOG_CONF ForcedLogConf;
RES_DES ResDes;
HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
PITEMDATA pItemData = NULL;
LONG iCur;
BOOL bRet = FALSE;
SP_PROPCHANGE_PARAMS PropChangeParams;
DWORD HardReconfigFlag;
SP_DEVINSTALL_PARAMS DevInstallParams;
PRESDES_ENTRY pResList = NULL, pResDesEntry = NULL, pTemp = NULL;
PITEMDATA_LISTNODE ItemDataList = NULL, ItemDataListEntry, ItemDataListEnd = NULL;
PGENERIC_RESOURCE pGenRes;
ULONG i, ulFlags;
ULONG64 ulValue, ulLen, ulEnd;
LOG_CONF LogConf;
ULONG ulSize;
ULONG ulConfigFlags;
HCURSOR hOldCursor;
BOOL UsingMatch = FALSE;
LogConf = lpdmpd->SelectedLC;
if (LogConf == 0) {
LogConf = lpdmpd->MatchingLC;
UsingMatch = TRUE;
}
if (LogConf == 0) {
LogConf = lpdmpd->CurrentLC;
UsingMatch = FALSE;
}
if (LogConf == 0) {
//MYASSERT(FALSE);
return FALSE;
}
//
// form the "warning - do you want to continue" message
//
if(!LoadString(MyDllModuleHandle, IDS_MAKE_FORCED_TITLE, szTitle, MAX_MSG_LEN)) {
szTitle[0]=TEXT('\0');
}
if(!LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN1, szWarn, MAX_MSG_LEN)) {
szWarn[0]=TEXT('\0');
}
if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN2, szTemp, MAX_MSG_LEN)) {
lstrcat(szWarn, szTemp);
}
if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN3, szTemp, MAX_MSG_LEN)) {
lstrcat(szWarn, szTemp);
}
if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN4, szTemp, MAX_MSG_LEN)) {
lstrcat(szWarn, szTemp);
}
//
// If the LCPRI is soft configurable, and the user chooses YES to the
// warning, then save the new config. If the LCPRI is not soft
// configurable, just save with no warning
//
dwLCPri = pGetMinLCPriority(lpdmpd->lpdi->DevInst, lpdmpd->ConfigListLCType,hMachine);
if (((dwLCPri >= LCPRI_DESIRED) && (dwLCPri <= LCPRI_LASTSOFTCONFIG)) &&
(MessageBox(hDlg, szWarn, szTitle, MB_YESNO|MB_ICONEXCLAMATION) == IDNO)) {
//
// user doesn't want to change anything
//
bRet = FALSE;
} else {
//
// We're still using the selected basic LC, but use the range index
// embedded in the listview control
// ISSUE-2000/02/03-JamieHun Selected Basic LC, check if user overrode
// Need to check the value to see if a user overrode it (is this possible?)
//
bRet = TRUE;
if (CM_Get_First_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst,
FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
CM_Free_Log_Conf_Ex(ForcedLogConf, 0,hMachine);
CM_Free_Log_Conf_Handle(ForcedLogConf);
}
//
// Save the current choices as the forced config
//
CM_Add_Empty_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst, LCPRI_FORCECONFIG,
FORCED_LOG_CONF | PRIORITY_EQUAL_FIRST,hMachine);
pGetResDesDataList(LogConf, &pResList, FALSE,hMachine);
pResDesEntry = pResList;
if (UsingMatch && (lpdmpd->dwFlags & DMPROP_FLAG_MATCH_OUT_OF_ORDER)) {
//
// The resource descriptors are out-of-order. Maintain the original ordering.
//
// First, build up a linked list of the data in the listview resource items.
//
iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
while (iCur != -1) {
pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
if (pItemData) {
//
// Allocate an item data list node for this data.
//
ItemDataListEntry = MyMalloc(sizeof(ITEMDATA_LISTNODE));
if (!ItemDataListEntry) {
bRet = FALSE;
goto clean0;
}
ItemDataListEntry->ItemData = pItemData;
ItemDataListEntry->Next = NULL;
//
// Append this new item to the end of our list.
//
if (ItemDataListEnd) {
ItemDataListEnd->Next = ItemDataListEntry;
} else {
ItemDataList = ItemDataListEntry;
}
ItemDataListEnd = ItemDataListEntry;
}
iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
}
//
// Now loop through each resdes entry, writing each one out. For each one, check
// to see if it has a corresponding entry in our listview item data list.
//
while (pResDesEntry) {
pGenRes = (PGENERIC_RESOURCE)pResDesEntry->ResDesData;
for(ItemDataListEntry = ItemDataList, ItemDataListEnd = NULL;
ItemDataListEntry;
ItemDataListEnd = ItemDataListEntry, ItemDataListEntry = ItemDataListEntry->Next)
{
if(pResDesEntry->ResDesType == ItemDataListEntry->ItemData->ResType) {
for (i = 0; i < pGenRes->GENERIC_Header.GENERIC_Count; i++) {
pGetRangeValues(pResDesEntry->ResDesData, pResDesEntry->ResDesType, i,
&ulValue, &ulLen, &ulEnd, NULL, &ulFlags);
if ((ItemDataListEntry->ItemData->ulLen == ulLen) &&
(ItemDataListEntry->ItemData->ulValue >= ulValue) &&
(ItemDataListEntry->ItemData->ulEnd <= ulEnd)) {
//
// We found the matching resource descriptor. Write this out.
//
pWriteValuesToForced(ForcedLogConf,
ItemDataListEntry->ItemData->ResType,
ItemDataListEntry->ItemData->RangeCount,
ItemDataListEntry->ItemData->MatchingResDes,
ItemDataListEntry->ItemData->ulValue,
ItemDataListEntry->ItemData->ulLen,
ItemDataListEntry->ItemData->ulEnd,
hMachine );
//
// Remove this item from our list.
//
if (ItemDataListEnd) {
ItemDataListEnd->Next = ItemDataListEntry->Next;
} else {
ItemDataList = ItemDataListEntry->Next;
}
MyFree(ItemDataListEntry);
break;
}
}
if(i < pGenRes->GENERIC_Header.GENERIC_Count) {
//
// Then we broke out of the loop early, which means we found a match
// already.
//
break;
}
}
}
//
// If we didn't find a match, then go ahead and write out the non-arbitrated
// resdes.
//
if (!ItemDataListEntry) {
pWriteResDesRangeToForced(ForcedLogConf,
pResDesEntry->ResDesType,
0,
0,
pResDesEntry->ResDesData,
hMachine);
}
pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
}
} else {
iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
while (iCur != -1) {
pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
if (pItemData) {
// retrieve values
while (pResDesEntry &&
(pItemData->ResType != pResDesEntry->ResDesType)) {
//
// write out any preceding non arbitrated resources
//
pWriteResDesRangeToForced(ForcedLogConf,
pResDesEntry->ResDesType,
0,
0,
pResDesEntry->ResDesData,
hMachine);
pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
}
if (pGetMatchingResDes(pItemData->ulValue,
pItemData->ulLen,
pItemData->ulEnd,
pItemData->ResType,
LogConf,
&ResDes,
hMachine)) {
//
// Write the first range as the chosen forced resource
//
pWriteValuesToForced(ForcedLogConf, pItemData->ResType,
pItemData->RangeCount, ResDes,
pItemData->ulValue,
pItemData->ulLen,
pItemData->ulEnd,
hMachine);
}
}
if (pResDesEntry) {
pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
} else {
MYASSERT(pResDesEntry);
}
iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
}
while (pResDesEntry) {
//
// write out any subsequent non arbitrated resources
//
pWriteResDesRangeToForced(ForcedLogConf,
pResDesEntry->ResDesType,
0,
0,
pResDesEntry->ResDesData,
hMachine);
pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
}
}
CM_Free_Log_Conf_Handle(ForcedLogConf);
//
// consider clearing problem flags
//
ulSize = sizeof(ulConfigFlags);
if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_CONFIGFLAGS,
NULL, (LPBYTE)&ulConfigFlags,
&ulSize, 0,hMachine) == CR_SUCCESS) {
if ((ulConfigFlags & CONFIGFLAG_PARTIAL_LOG_CONF) != 0) {
//
// have flag(s) to change
// CONFIGFLAG_PARTIAL_LOG_CONF should be cleared - we should have written a complete config now
//
ulConfigFlags &= ~ (CONFIGFLAG_PARTIAL_LOG_CONF);
CM_Set_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
CM_DRP_CONFIGFLAGS,
(LPBYTE)&ulConfigFlags,
sizeof(ulConfigFlags),
0,
hMachine);
}
}
//
// Give the class installer/co-installers a crack at the propchange process.
//
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.StateChange = DICS_PROPCHANGE;
PropChangeParams.Scope = DICS_FLAG_GLOBAL;
// no need to set PropChangeParams.HwProfile, since this is a global property change.
DoInstallActionWithParams(DIF_PROPERTYCHANGE,
lpdmpd->hDevInfo,
lpdmpd->lpdi,
(PSP_CLASSINSTALL_HEADER)&PropChangeParams,
sizeof(PropChangeParams),
INSTALLACTION_CALL_CI | INSTALLACTION_NO_DEFAULT
);
//
// Check the Priority of this LC. If it is greater
// than LCPRI_LASTSOFTCONFIG, then we need to reboot
// otherwise try the dynamic changestate route.
//
if (CM_Get_Log_Conf_Priority_Ex(LogConf, &dwPriority, 0,hMachine) != CR_SUCCESS) {
dwPriority = LCPRI_LASTSOFTCONFIG;
}
if (dwPriority <= LCPRI_LASTSOFTCONFIG) {
//
// Do the default action for SoftConfigable devices, which
// will attempt to restart the device with the new config
// This could take a while so use an hourglass
//
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
DoInstallActionWithParams(DIF_PROPERTYCHANGE,
lpdmpd->hDevInfo,
lpdmpd->lpdi,
(PSP_CLASSINSTALL_HEADER)&PropChangeParams,
sizeof(PropChangeParams),
0 // don't call class-installer, just do default action
);
SetCursor(hOldCursor);
HardReconfigFlag = 0;
} else if((dwPriority > LCPRI_LASTSOFTCONFIG) && (dwPriority <= LCPRI_RESTART)) {
HardReconfigFlag = DI_NEEDRESTART;
} else {
HardReconfigFlag = DI_NEEDREBOOT;
}
lpdmpd->dwFlags |= DMPROP_FLAG_CHANGESSAVED;
//
// Properties have changed, so set flags to indicate if restart/reboot is required,
// and to tell DevMgr to re-init the UI.
//
DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if(SetupDiGetDeviceInstallParams(lpdmpd->hDevInfo,
lpdmpd->lpdi,
&DevInstallParams)) {
DevInstallParams.Flags |= (HardReconfigFlag | DI_PROPERTIES_CHANGE);
SetupDiSetDeviceInstallParams(lpdmpd->hDevInfo,
lpdmpd->lpdi,
&DevInstallParams
);
}
//
// If we need to reboot, then set a problem on the device that indicates this (in case
// the user doesn't listen to us, we want to flag this devnode so that the user will see
// that this devnode needs a reboot if they go into DevMgr, etc.)
//
if(HardReconfigFlag) {
PDEVICE_INFO_SET pDeviceInfoSet;
PDEVINFO_ELEM DevInfoElem;
if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
//
// We'd better be able to access this device information set!
// In case we couldn't don't bother trying to set the needs-reboot problem,
// because the whole mess is invalid!
//
MYASSERT(pDeviceInfoSet);
} else {
try {
DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet, lpdmpd->lpdi, NULL);
//
// We'd better be able to find this element!
//
MYASSERT(DevInfoElem);
//
// In case we can't find it, don't try to set any problem on the devnode.
//
if(DevInfoElem) {
SetDevnodeNeedsRebootProblem(DevInfoElem,
pDeviceInfoSet,
MSG_LOG_REBOOT_DEVRES
);
}
} finally {
UnlockDeviceInfoSet(pDeviceInfoSet);
}
}
}
}
clean0:
while (ItemDataList) {
ItemDataListEntry = ItemDataList->Next;
MyFree(ItemDataList);
ItemDataList = ItemDataListEntry;
}
pDeleteResDesDataList(pResList);
return bRet;
} // SaveCustomResSettings
BOOL
pWriteResDesRangeToForced(
IN LOG_CONF ForcedLogConf,
IN RESOURCEID ResType,
IN ULONG RangeIndex,
IN RES_DES RD, OPTIONAL
IN LPBYTE ResDesData, OPTIONAL
IN HMACHINE hMachine OPTIONAL
)
{
RES_DES ResDes;
ULONG ulSize;
LPBYTE pData = NULL;
BOOL Success = FALSE;
if ((RD == 0) && (ResDesData == NULL)) {
return FALSE; // pass in data or handle!
}
if (!ResDesData) {
if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, RD, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
return FALSE;
}
pData = MyMalloc(ulSize);
if (pData == NULL) {
return FALSE;
}
if (CM_Get_Res_Des_Data_Ex(RD, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
MyFree(pData);
return FALSE;
}
} else {
pData = ResDesData;
}
//
// convert the first range data into hdr data
//
switch (ResType) {
case ResType_Mem: {
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
PMEM_RESOURCE pForced = (PMEM_RESOURCE)MyMalloc(sizeof(MEM_RESOURCE));
if (!pForced) {
break;
}
pForced->MEM_Header.MD_Count = 0;
pForced->MEM_Header.MD_Type = MType_Range;
pForced->MEM_Header.MD_Alloc_Base = pMemData->MEM_Data[RangeIndex].MR_Min;
pForced->MEM_Header.MD_Alloc_End = pMemData->MEM_Data[RangeIndex].MR_Min +
pMemData->MEM_Data[RangeIndex].MR_nBytes - 1;
pForced->MEM_Header.MD_Flags = pMemData->MEM_Data[RangeIndex].MR_Flags;
pForced->MEM_Header.MD_Reserved = 0;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_Mem,
pForced,
sizeof(MEM_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_IO: {
PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
PIO_RESOURCE pForced = (PIO_RESOURCE)MyMalloc(sizeof(IO_RESOURCE));
if (!pForced) {
break;
}
pForced->IO_Header.IOD_Count = 0;
pForced->IO_Header.IOD_Type = IOType_Range;
pForced->IO_Header.IOD_Alloc_Base = pIoData->IO_Data[RangeIndex].IOR_Min;
pForced->IO_Header.IOD_Alloc_End = pIoData->IO_Data[RangeIndex].IOR_Min +
pIoData->IO_Data[RangeIndex].IOR_nPorts - 1;
pForced->IO_Header.IOD_DesFlags = pIoData->IO_Data[RangeIndex].IOR_RangeFlags;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_IO,
pForced,
sizeof(IO_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_DMA: {
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
PDMA_RESOURCE pForced = (PDMA_RESOURCE)MyMalloc(sizeof(DMA_RESOURCE));
if (!pForced) {
break;
}
pForced->DMA_Header.DD_Count = 0;
pForced->DMA_Header.DD_Type = DType_Range;
pForced->DMA_Header.DD_Flags = pDmaData->DMA_Data[RangeIndex].DR_Flags;
pForced->DMA_Header.DD_Alloc_Chan = pDmaData->DMA_Data[RangeIndex].DR_Min;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_DMA,
pForced,
sizeof(DMA_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_IRQ: {
DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
DEVRES_PIRQ_RESOURCE pForced = (DEVRES_PIRQ_RESOURCE)MyMalloc(sizeof(DEVRES_IRQ_RESOURCE));
if (!pForced) {
break;
}
pForced->IRQ_Header.IRQD_Count = 0;
pForced->IRQ_Header.IRQD_Type = IRQType_Range;
pForced->IRQ_Header.IRQD_Flags = pIrqData->IRQ_Data[RangeIndex].IRQR_Flags;
pForced->IRQ_Header.IRQD_Alloc_Num = pIrqData->IRQ_Data[RangeIndex].IRQR_Min;
pForced->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1);
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_IRQ,
pForced,
sizeof(DEVRES_IRQ_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_BusNumber: {
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)pData;
PBUSNUMBER_RESOURCE pForced = (PBUSNUMBER_RESOURCE)MyMalloc(sizeof(BUSNUMBER_RESOURCE));
if (!pForced) {
break;
}
pForced->BusNumber_Header.BUSD_Count = 0;
pForced->BusNumber_Header.BUSD_Type = BusNumberType_Range;
pForced->BusNumber_Header.BUSD_Flags = pBusData->BusNumber_Data[RangeIndex].BUSR_Flags;
pForced->BusNumber_Header.BUSD_Alloc_Base = pBusData->BusNumber_Data[RangeIndex].BUSR_Min;
pForced->BusNumber_Header.BUSD_Alloc_End = pBusData->BusNumber_Data[RangeIndex].BUSR_Min +
pBusData->BusNumber_Data[RangeIndex].BUSR_nBusNumbers;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_BusNumber,
pForced,
sizeof(BUSNUMBER_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_DevicePrivate: {
PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)pData;
PDEVPRIVATE_RESOURCE pForced = (PDEVPRIVATE_RESOURCE)MyMalloc(sizeof(DEVPRIVATE_RESOURCE));
if (!pForced) {
break;
}
pForced->PRV_Header.PD_Count = 0;
pForced->PRV_Header.PD_Type = PType_Range;
pForced->PRV_Header.PD_Data1 = pPrvData->PRV_Data[RangeIndex].PR_Data1;
pForced->PRV_Header.PD_Data2 = pPrvData->PRV_Data[RangeIndex].PR_Data2;
pForced->PRV_Header.PD_Data3 = pPrvData->PRV_Data[RangeIndex].PR_Data3;
pForced->PRV_Header.PD_Flags = 0;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_DevicePrivate,
pForced,
sizeof(DEVPRIVATE_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_PcCardConfig: {
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_PcCardConfig,
pData,
sizeof(PCCARD_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine);
break;
}
}
if (pData != ResDesData) {
MyFree(pData);
}
return Success;
} // WriteResDesRangeToForced
BOOL
pWriteValuesToForced(
IN LOG_CONF ForcedLogConf,
IN RESOURCEID ResType,
IN ULONG RangeIndex,
IN RES_DES RD,
IN ULONG64 ulValue,
IN ULONG64 ulLen,
IN ULONG64 ulEnd,
IN HMACHINE hMachine
)
{
RES_DES ResDes;
ULONG ulSize;
LPBYTE pData = NULL;
BOOL Success = FALSE;
if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, RD, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
return FALSE;
}
pData = MyMalloc(ulSize);
if (pData == NULL) {
return FALSE;
}
if (CM_Get_Res_Des_Data_Ex(RD, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
MyFree(pData);
return FALSE;
}
//
// convert the first range data into hdr data
//
switch (ResType) {
case ResType_Mem: {
PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
PMEM_RESOURCE pForced = (PMEM_RESOURCE)MyMalloc(sizeof(MEM_RESOURCE));
if (!pForced) {
break;
}
pForced->MEM_Header.MD_Count = 0;
pForced->MEM_Header.MD_Type = MType_Range;
pForced->MEM_Header.MD_Alloc_Base = ulValue;
pForced->MEM_Header.MD_Alloc_End = ulEnd;
pForced->MEM_Header.MD_Flags = pMemData->MEM_Data[RangeIndex].MR_Flags;
pForced->MEM_Header.MD_Reserved = 0;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_Mem,
pForced,
sizeof(MEM_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_IO: {
PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
PIO_RESOURCE pForced = (PIO_RESOURCE)MyMalloc(sizeof(IO_RESOURCE));
if (!pForced) {
break;
}
pForced->IO_Header.IOD_Count = 0;
pForced->IO_Header.IOD_Type = IOType_Range;
pForced->IO_Header.IOD_Alloc_Base = ulValue;
pForced->IO_Header.IOD_Alloc_End = ulEnd;
pForced->IO_Header.IOD_DesFlags = pIoData->IO_Data[RangeIndex].IOR_RangeFlags;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_IO,
pForced,
sizeof(IO_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_DMA: {
PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
PDMA_RESOURCE pForced = (PDMA_RESOURCE)MyMalloc(sizeof(DMA_RESOURCE));
if (!pForced) {
break;
}
pForced->DMA_Header.DD_Count = 0;
pForced->DMA_Header.DD_Type = DType_Range;
pForced->DMA_Header.DD_Flags = pDmaData->DMA_Data[RangeIndex].DR_Flags;
pForced->DMA_Header.DD_Alloc_Chan = (ULONG)ulValue;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_DMA,
pForced,
sizeof(DMA_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_IRQ: {
DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
DEVRES_PIRQ_RESOURCE pForced = (DEVRES_PIRQ_RESOURCE)MyMalloc(sizeof(DEVRES_IRQ_RESOURCE));
if (!pForced) {
break;
}
pForced->IRQ_Header.IRQD_Count = 0;
pForced->IRQ_Header.IRQD_Type = IRQType_Range;
pForced->IRQ_Header.IRQD_Flags = pIrqData->IRQ_Data[RangeIndex].IRQR_Flags;
pForced->IRQ_Header.IRQD_Alloc_Num = (ULONG)ulValue;
pForced->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1);
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_IRQ,
pForced,
sizeof(DEVRES_IRQ_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_BusNumber: {
PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)pData;
PBUSNUMBER_RESOURCE pForced = (PBUSNUMBER_RESOURCE)MyMalloc(sizeof(BUSNUMBER_RESOURCE));
if (!pForced) {
break;
}
pForced->BusNumber_Header.BUSD_Count = 0;
pForced->BusNumber_Header.BUSD_Type = BusNumberType_Range;
pForced->BusNumber_Header.BUSD_Flags = pBusData->BusNumber_Data[RangeIndex].BUSR_Flags;
pForced->BusNumber_Header.BUSD_Alloc_Base = (ULONG)ulValue;
pForced->BusNumber_Header.BUSD_Alloc_End = (ULONG)ulEnd;
Success = CM_Add_Res_Des_Ex(NULL,
ForcedLogConf,
ResType_BusNumber,
pForced,
sizeof(BUSNUMBER_RESOURCE),
DEVRES_WIDTH_FLAGS,
hMachine) == CR_SUCCESS;
MyFree(pForced);
break;
}
case ResType_DevicePrivate: {
break;
}
case ResType_PcCardConfig: {
break;
}
}
if (pData) {
MyFree(pData);
}
return Success;
} // WriteValuesToForced
BOOL
MakeResourceData(
OUT LPBYTE *ppResourceData,
OUT PULONG pulSize,
IN RESOURCEID ResType,
IN ULONG64 ulValue,
IN ULONG64 ulLen,
IN ULONG ulFlags
)
{
BOOL bStatus = TRUE;
try {
switch (ResType) {
case ResType_Mem: {
PMEM_RESOURCE p;
*pulSize = sizeof(MEM_RESOURCE);
if (ppResourceData) {
*ppResourceData = MyMalloc(*pulSize);
p = (PMEM_RESOURCE)(*ppResourceData);
if (!p) {
bStatus = FALSE;
break;
}
p->MEM_Header.MD_Count = 0;
p->MEM_Header.MD_Type = MType_Range;
p->MEM_Header.MD_Alloc_Base = ulValue;
p->MEM_Header.MD_Alloc_End = ulValue + ulLen - 1;
p->MEM_Header.MD_Flags = ulFlags;
p->MEM_Header.MD_Reserved = 0;
}
break;
}
case ResType_IO: {
PIO_RESOURCE p;
*pulSize = sizeof(IO_RESOURCE);
if (ppResourceData) {
*ppResourceData = MyMalloc(*pulSize);
p = (PIO_RESOURCE)(*ppResourceData);
if (!p) {
bStatus = FALSE;
break;
}
p->IO_Header.IOD_Count = 0;
p->IO_Header.IOD_Type = IOType_Range;
p->IO_Header.IOD_Alloc_Base = ulValue;
p->IO_Header.IOD_Alloc_End = ulValue + ulLen - 1;
p->IO_Header.IOD_DesFlags = ulFlags;
}
break;
}
case ResType_DMA: {
PDMA_RESOURCE p;
*pulSize = sizeof(DMA_RESOURCE);
if (ppResourceData) {
*ppResourceData = MyMalloc(*pulSize);
p = (PDMA_RESOURCE)(*ppResourceData);
if (!p) {
bStatus = FALSE;
break;
}
p->DMA_Header.DD_Count = 0;
p->DMA_Header.DD_Type = DType_Range;
p->DMA_Header.DD_Flags = ulFlags;
p->DMA_Header.DD_Alloc_Chan = (ULONG)ulValue;
}
break;
}
case ResType_IRQ: {
DEVRES_PIRQ_RESOURCE p;
*pulSize = sizeof(DEVRES_IRQ_RESOURCE);
if (ppResourceData) {
*ppResourceData = MyMalloc(*pulSize);
p = (DEVRES_PIRQ_RESOURCE)(*ppResourceData);
if (!p) {
bStatus = FALSE;
break;
}
p->IRQ_Header.IRQD_Count = 0;
p->IRQ_Header.IRQD_Type = IRQType_Range;
p->IRQ_Header.IRQD_Flags = ulFlags;
p->IRQ_Header.IRQD_Alloc_Num = (ULONG)ulValue;
p->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1); // for any processor
}
break;
}
default:
//
// ResTypeEditable or ResType_MAX may be wrong if this ASSERT's
//
MYASSERT(FALSE);
bStatus = FALSE;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
bStatus = FALSE;
}
return bStatus;
} // MakeResourceData
BOOL
pShowWindow(
IN HWND hWnd,
IN int nShow
)
/*++
Routine Description:
A variation of ShowWindow that enables/disables window
Arguments:
(See ShowWindow)
hWnd - handle of window to show
nShow - typically SW_HIDE or SW_SHOW
Return Value:
success status of ShowWindow
--*/
{
EnableWindow(hWnd,nShow!=SW_HIDE);
return ShowWindow(hWnd,nShow);
}
BOOL
pEnableWindow(
IN HWND hWnd,
IN BOOL Enable
)
/*++
Routine Description:
A variation of EnableWindow that only enables a window if it is visible
Arguments:
(See EnableWindow)
hWnd - handle of window to enable/disable
Enable - TRUE enables window (if window visible) FALSE disables window
Return Value:
success status of EnableWindow
--*/
{
//
// I had to use GetWindowLong, as IsWindowVisible also checks parent flag
// and parent is hidden until dialog is initialized
//
if((GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE) == FALSE) {
Enable = FALSE;
}
return EnableWindow(hWnd,Enable);
}
BOOL
pGetResDesDataList(
IN LOG_CONF LogConf,
IN OUT PRESDES_ENTRY *pResList,
IN BOOL bArbitratedOnly,
IN HMACHINE hMachine
)
/*++
Routine Description:
Creates a list of resource descriptors for further processing
Arguments:
LogConf - log config of interest
pResList - list out
bArbitratedOnly - filter out non-arbitrated resources
hMachine - machine that LogConf is on
Return Value:
None.
--*/
{
BOOL bStatus = TRUE;
CONFIGRET Status = CR_SUCCESS;
PRESDES_ENTRY pHead = NULL, pEntry = NULL, pPrevious = NULL, pTemp = NULL;
RES_DES ResDes;
RESOURCEID ResType;
ULONG ulSize;
LPBYTE pData = NULL;
//
// Retrieve each res des in this log conf
//
Status = CM_Get_Next_Res_Des_Ex(&ResDes, LogConf, ResType_All, &ResType, 0,hMachine);
while (Status == CR_SUCCESS) {
if (bArbitratedOnly && (ResType <= ResType_None || ResType > ResType_MAX)) {
goto NextResDes;
}
if (bArbitratedOnly && ResTypeEditable[ResType] == FALSE) {
goto NextResDes;
}
if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, ResDes, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
CM_Free_Res_Des_Handle(ResDes);
bStatus = FALSE;
goto Clean0;
}
if (ulSize>0) {
pData = MyMalloc(ulSize);
if (pData == NULL) {
CM_Free_Res_Des_Handle(ResDes);
bStatus = FALSE;
goto Clean0;
}
if (CM_Get_Res_Des_Data_Ex(ResDes, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
CM_Free_Res_Des_Handle(ResDes);
MyFree(pData);
bStatus = FALSE;
goto Clean0;
}
} else {
pData = NULL;
}
//
// Allocate a node for this res des and attach it to the list
//
pEntry = MyMalloc(sizeof(RESDES_ENTRY));
if (pEntry == NULL) {
CM_Free_Res_Des_Handle(ResDes);
MyFree(pData);
bStatus = FALSE;
goto Clean0;
}
pEntry->ResDesData = pData;
pEntry->ResDesType = ResType;
pEntry->ResDesDataSize = ulSize;
pEntry->ResDesHandle = ResDes;
pEntry->Next = NULL;
pEntry->CrossLink = NULL;
if (!pHead) {
pHead = pEntry; // first entry
}
if (pPrevious) {
pPrevious->Next = pEntry; // attach to previous entry
}
pPrevious = pEntry;
//
// Get next res des in LogConf
//
NextResDes:
Status = CM_Get_Next_Res_Des_Ex(&ResDes, ResDes, ResType_All, &ResType, 0,hMachine);
}
bStatus = TRUE;
Clean0:
if (!bStatus) {
pDeleteResDesDataList(pHead);
} else {
*pResList = pHead;
}
return bStatus;
} // GetResDesDataList
VOID
pDeleteResDesDataList(
IN PRESDES_ENTRY pResList
)
/*++
Routine Description:
Deletes memory used by RESDES list
Arguments:
pResList - list returned by GetResDesDataList
Return Value:
None.
--*/
{
PRESDES_ENTRY pTemp;
while (pResList) {
pTemp = pResList;
pResList = (PRESDES_ENTRY)pResList->Next;
if (pTemp->ResDesData) {
MyFree(pTemp->ResDesData);
}
if (pTemp->ResDesHandle) {
CM_Free_Res_Des_Handle(pTemp->ResDesHandle);
}
MyFree(pTemp);
}
}
VOID
pHideAllControls(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Hide (and disable) all controls - start off with a clean slate
Only Icon & device description will be visible
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT_DESC), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_HIDE);
lpdmpd->dwFlags |= DMPROP_FLAG_VIEWONLYRES;
}
VOID
pShowViewNoResources(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Show page indicating this device has no resources
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
TCHAR szString[MAX_PATH];
pHideAllControls(lpdmpd); // all hidden and disabled
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_SHOW); // show and enable text
LoadString(MyDllModuleHandle, IDS_DEVRES_NO_RESOURCES, szString, MAX_PATH);
SetDlgItemText(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT, szString);
}
BOOL
pShowViewMFReadOnly(
IN LPDMPROP_DATA lpdmpd,
IN BOOL HideIfProb
)
/*++
Routine Description:
Show page apropriate for multifunction card that cannot be edited
Resource settings are visible
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
TCHAR szString[MAX_PATH];
DEVNODE dnParent;
ULONG ulSize;
HWND hDlg = lpdmpd->hDlg;
HMACHINE hMachine = pGetMachine(lpdmpd);
pHideAllControls(lpdmpd); // all hidden and disabled
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW); // show config information
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW); // show
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
//
// indicate we cannot change as it's multi-function
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW);
if (LoadString(MyDllModuleHandle, IDS_DEVRES_NO_CHANGE_MF, szString, MAX_PATH)) {
SetDlgItemText(hDlg, IDC_DEVRES_NO_CHANGE_TEXT, szString);
}
//
// for parent description
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT_DESC), SW_SHOW);
//
// Get the Parent's Description.
//
LoadString(MyDllModuleHandle, IDS_DEVNAME_UNK, szString, MAX_PATH);
if (lpdmpd->lpdi->DevInst) {
if (CM_Get_Parent_Ex(&dnParent, lpdmpd->lpdi->DevInst, 0,hMachine)
== CR_SUCCESS) {
//
// First, try to retrieve friendly name, then fall back to device description.
//
ulSize = MAX_PATH * sizeof(TCHAR);
if(CM_Get_DevNode_Registry_Property_Ex(dnParent, CM_DRP_FRIENDLYNAME,
NULL, szString, &ulSize, 0,hMachine) != CR_SUCCESS) {
ulSize = MAX_PATH * sizeof(TCHAR);
CM_Get_DevNode_Registry_Property_Ex(dnParent, CM_DRP_DEVICEDESC,
NULL, szString, &ulSize, 0,hMachine);
}
}
}
SetDlgItemText(hDlg, IDC_DEVRES_MFPARENT_DESC, szString);
//
// load and display current config (if any)
// return FALSE if no current config
//
return pLoadCurrentConfig(lpdmpd,HideIfProb);
}
BOOL
pShowViewReadOnly(
IN LPDMPROP_DATA lpdmpd,
IN BOOL HideIfProb
)
/*++
Routine Description:
Show page of resources, don't allow editing, don't show editing controls
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
pHideAllControls(lpdmpd); // all hidden and disabled
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW); // show
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), FALSE);
ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW); // shown disabled
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), FALSE);
ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_SHOW); // shown disabled
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), FALSE);
ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_SHOW); // shown disabled
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
//
// will indicate if we're showing system settings or forced settings
//
CheckDlgButton(hDlg, IDC_DEVRES_USESYSSETTINGS, (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS ) ? TRUE : FALSE);
//
// load and display current config (if any)
// return FALSE if no current config
//
return pLoadCurrentConfig(lpdmpd,HideIfProb);
}
VOID
pShowViewNoAlloc(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Modify the middle part of the control to indicate there is a problem (and there isn't much we can do about it)
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
//
// hide all middle controls
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
lpdmpd->dwFlags |= DMPROP_FLAG_VIEWONLYRES;
//pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW); // this may say why
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_HIDE); // no alloc, so hide this header & textbox
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_HIDE);
}
VOID
pShowViewNeedForced(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Modify the middle part of the control to indicate a forced config is required
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
pShowViewNoAlloc(lpdmpd);
//
// show what we need for make forced config
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW); // this may say why
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_SHOW);
}
VOID
pShowViewAllEdit(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Allow editing
Arguments:
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
//
// show middle controls for editing
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_SHOW);
ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_SHOW); // shown, but disabled
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
pShowUpdateEdit(lpdmpd);
}
VOID
pShowUpdateEdit(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Allow editing
Arguments:
lpdmpd = property data
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
//
// modify editing status - we can edit
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_VIEWONLYRES;
if(lpdmpd->dwFlags & DMPROP_FLAG_FORCEDONLY) {
//
// in this case, we will never be able to use system settings
//
lpdmpd->dwFlags &= ~ DMPROP_FLAG_USESYSSETTINGS;
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), FALSE);
}
//
// indicate if it's system settings or not
//
CheckDlgButton(hDlg, IDC_DEVRES_USESYSSETTINGS,
(lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?TRUE:FALSE);
//
// we can change logconfiglist if it's not system settings
//
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?FALSE:TRUE);
EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?FALSE:TRUE);
//
// change "Change Settings" button
//
pCheckEnableResourceChange(lpdmpd);
}
BOOL
pLoadCurrentConfig(
IN LPDMPROP_DATA lpdmpd,
BOOL HideIfProb
)
/*++
Routine Description:
Modify the top part, to show current configuration, if any
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
Return Value:
TRUE if we're showing current config
--*/
{
TCHAR szMessage[MAX_PATH];
ULONG Problem;
ULONG Status;
HWND hDlg = lpdmpd->hDlg;
HMACHINE hMachine = pGetMachine(lpdmpd);
BOOL DoLoadConfig = FALSE;
lpdmpd->SelectedLC = 0;
lpdmpd->SelectedLCType = lpdmpd->CurrentLCType;
if (lpdmpd->CurrentLC != 0) {
DoLoadConfig = TRUE;
}
if(HideIfProb && (lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
//
// if there's a problem and HideIfProb is TRUE, don't bother showing current config
//
DoLoadConfig = FALSE;
}
if (DoLoadConfig) {
//
// load in current configuration
//
pLoadConfig(lpdmpd,lpdmpd->CurrentLC,lpdmpd->CurrentLCType);
return TRUE;
}
//
// case where there is no suitable configuration
//
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
pShowViewNoAlloc(lpdmpd);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_SHOW);
//
// explain why there is a problem
// goes into NOALLOCTEXT
//
LoadString(MyDllModuleHandle, IDS_DEVRES_NOALLOC_PROBLEM, szMessage, MAX_PATH);
//
// consider being more descriptive
//
if ((lpdmpd->lpdi->DevInst==0)
|| (CM_Get_DevNode_Status_Ex(&Status, &Problem, lpdmpd->lpdi->DevInst,
0,hMachine) != CR_SUCCESS)) {
Status = 0;
Problem = 0;
}
if ((Status & DN_HAS_PROBLEM)!=0) {
switch (Problem) {
case CM_PROB_DISABLED:
case CM_PROB_HARDWARE_DISABLED:
LoadString(MyDllModuleHandle, IDS_DEVRES_NOALLOC_DISABLED, szMessage, MAX_PATH);
break;
case CM_PROB_NORMAL_CONFLICT:
LoadString(MyDllModuleHandle, IDS_DEVRES_NORMAL_CONFLICT, szMessage, MAX_PATH);
break;
default:
break;
}
}
SetDlgItemText(hDlg, IDC_DEVRES_NOALLOCTEXT, szMessage);
return FALSE; // display in NoAlloc state
}
BOOL
pConfigHasNoAlternates(
LPDMPROP_DATA lpdmpd,
LOG_CONF testLC
)
/*++
Routine Description:
A Basic config could be restrictive "these are the set of resources to use"
This determines if the basic config passed is such a config
Arguments:
testLC = basic config to test
Return Value:
TRUE if it's a singular config
--*/
{
HMACHINE hMachine = NULL;
PRESDES_ENTRY pConfigValues = NULL;
PRESDES_ENTRY pValue = NULL;
BOOL bSuccess = TRUE;
ULONG64 ulValue = 0, ulLen = 0, ulEnd = 0;
ULONG ulFlags = 0;
PGENERIC_RESOURCE pGenRes = NULL;
hMachine = pGetMachine(lpdmpd);
pGetResDesDataList(testLC, &pConfigValues, TRUE, hMachine); // arbitratable resources
for(pValue = pConfigValues;pValue;pValue = pValue->Next) {
//
// is this a singular value?
//
pGenRes = (PGENERIC_RESOURCE)(pValue->ResDesData);
if(pGenRes->GENERIC_Header.GENERIC_Count != 1) {
//
// more than one entry - not singular
//
bSuccess = FALSE;
break;
}
pGetRangeValues(pValue->ResDesData, pValue->ResDesType, 0, &ulValue, &ulLen, &ulEnd, NULL, &ulFlags);
if (ulValue+(ulLen-1) != ulEnd) {
//
// not singular
//
bSuccess = FALSE;
break;
}
}
pDeleteResDesDataList(pConfigValues);
return bSuccess;
}
BOOL
pLoadConfig(
LPDMPROP_DATA lpdmpd,
LOG_CONF forceLC,
ULONG forceLCType
)
/*++
Routine Description:
Display a configuration
Arguments:
hDlg = dialog handle of controls
lpdmpd = property data
forceLC = LogConf to display
forceLCType = type for LogConf
Return Value:
TRUE if config loaded
--*/
{
HWND hDlg = lpdmpd->hDlg;
CONFIGRET Status = CR_SUCCESS;
HWND hWndList;
LV_ITEM lviItem;
TCHAR szTemp[MAX_PATH];
int iNewItem = 0;
ULONG ulSize,ulFlags;
ULONG64 ulValue, ulLen, ulEnd, ulAlign;
ULONG64 ulMaxMem = 0;
ULONG ulRange;
LPBYTE pData = NULL;
RES_DES ResDes;
RESOURCEID ResType;
PITEMDATA pItemData = NULL;
HMACHINE hMachine = NULL;
PDEVICE_INFO_SET pDeviceInfoSet;
BOOL RetCode = FALSE;
PRESDES_ENTRY pKnownValues = NULL;
PRESDES_ENTRY pShowValues = NULL;
PRESDES_ENTRY pShowEntry = NULL;
BOOL bFixedConfig = FALSE;
BOOL bNoMatch;
BOOL bFixed;
ULONG MatchLevel = NO_LC_MATCH;
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_SHOW);
pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_HIDE);
hWndList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
SendMessage(hWndList, WM_SETREDRAW, (WPARAM)FALSE, 0);
ListView_DeleteAllItems(hWndList);
lpdmpd->dwFlags |= DMPROP_FLAG_FIXEDCONFIG; // until we determine there is at least one setting we can edit
if (forceLC == 0) {
forceLC = lpdmpd->CurrentLC;
forceLCType = lpdmpd->CurrentLCType;
}
if (forceLC == 0) {
MYASSERT(FALSE);
goto Final;
}
hMachine = pGetMachine(lpdmpd);
//
// setup values that will remain the same each time I add an item
//
lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lviItem.pszText = szTemp; // reuse the szTemp buffer
lviItem.iSubItem = 0;
lviItem.iImage = IDI_RESOURCE - IDI_RESOURCEFIRST;
pGetResDesDataList(forceLC, &pShowValues, TRUE, hMachine); // editable resources
if (forceLCType == BOOT_LOG_CONF || forceLCType == FORCED_LOG_CONF || forceLCType == ALLOC_LOG_CONF) {
bFixedConfig = TRUE;
if (forceLC == lpdmpd->CurrentLC && lpdmpd->MatchingLC != 0) {
//
// we're displaying CurrentLC, use flags & resdes's from matching LC where possible
//
if (pGetResDesDataList(lpdmpd->MatchingLC, &pKnownValues, TRUE, hMachine)) {
//
// match-up currentLC with some matching LC, so we can use flags/ranges from matching LC
//
MatchLevel = pMergeResDesDataLists(pShowValues,pKnownValues,NULL);
}
}
} else if (lpdmpd->CurrentLC != 0) {
//
// the config we're displaying may allow ranges of values
// we're going to try and match up what we are displaying to current config
//
if (pGetResDesDataList(lpdmpd->CurrentLC, &pKnownValues, TRUE, hMachine)) {
//
// try and use current values where possible
//
MatchLevel = pMergeResDesDataLists(pKnownValues,pShowValues,NULL);
}
}
pShowEntry = pShowValues;
while (pShowEntry) {
bNoMatch = FALSE;
bFixed = FALSE;
ResDes = (RES_DES)0;
ResType = pShowEntry->ResDesType;
ulRange = 0;
if (bFixedConfig) {
//
// we've got a current config
//
pGetHdrValues(pShowEntry->ResDesData, pShowEntry->ResDesType, &ulValue, &ulLen, &ulEnd, &ulFlags);
if((ResType ==ResType_Mem) && (ulEnd > ulMaxMem)) {
//
// base our memory display on the fixed-config only
//
ulMaxMem = ulEnd;
}
if (pShowEntry->CrossLink) {
//
// use range's res-des
//
ResDes = pShowEntry->CrossLink->ResDesHandle;
pShowEntry->CrossLink->ResDesHandle = (RES_DES)0;
//
// allow adjustment based on nearest basic config
//
pGetMatchingRange(ulValue,ulLen,pShowEntry->CrossLink->ResDesData, pShowEntry->CrossLink->ResDesType,&ulRange,&bFixed,NULL);
} else {
//
// no range res-des
//
ResDes = (RES_DES)0;
//
// indicate that this is a non-adjustable value
//
bFixed = TRUE;
}
} else {
//
// we've got resource-ranges
//
if (pShowEntry->CrossLink) {
//
// take current settings from what we merged in
//
pGetHdrValues(pShowEntry->CrossLink->ResDesData, pShowEntry->CrossLink->ResDesType, &ulValue, &ulLen, &ulEnd, &ulFlags);
} else {
//
// just take first range
//
pGetRangeValues(pShowEntry->ResDesData, pShowEntry->ResDesType, 0, &ulValue, &ulLen, &ulEnd, &ulAlign, &ulFlags);
}
//
// range check if this is a memory resource - find highest memory value
//
if(ResType ==ResType_Mem) {
ULONG64 HighVal;
ULONG64 HighLen;
if(LocateClosestValue(pShowEntry->ResDesData, pShowEntry->ResDesType,(ULONG64)(-1),ulLen, 0 ,&HighVal,&HighLen,NULL)) {
HighVal += HighLen-1;
if(HighVal > ulMaxMem) {
ulMaxMem = ulEnd;
}
}
}
pGetMatchingRange(ulValue,ulLen,pShowEntry->ResDesData, pShowEntry->ResDesType,&ulRange,&bFixed,&ulFlags);
//
// use res-des from range
//
ResDes = pShowEntry->ResDesHandle;
pShowEntry->ResDesHandle = (RES_DES)0;
if (pShowEntry->CrossLink == NULL && bFixed == FALSE) {
//
// unknown value
//
bNoMatch = TRUE;
}
}
if (ulLen>0) {
//
// Write first column text field (uses szTemp, lParam is res type)
//
LoadString(MyDllModuleHandle, IDS_RESOURCE_BASE + ResType, szTemp, MAX_PATH);
ulRange = 0;
pItemData = (PITEMDATA)MyMalloc(sizeof(ITEMDATA));
if (pItemData != NULL) {
pItemData->ResType = ResType;
pItemData->MatchingResDes = ResDes;
pItemData->RangeCount = ulRange;
pItemData->ulValue = ulValue; // selected value
pItemData->ulLen = ulLen;
pItemData->ulEnd = ulValue + ulLen - 1;
pItemData->ulFlags = ulFlags;
pItemData->bValid = !bNoMatch; // if no chosen value
pItemData->bFixed = bFixed;
}
if (bFixed == FALSE) {
//
// we have at least one editable value
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_FIXEDCONFIG;
}
lviItem.iItem = iNewItem;
lviItem.lParam = (LPARAM)pItemData;
ListView_InsertItem(hWndList, &lviItem);
//
// Write second column text field (uses szTemp, lParam is res handle)
//
if (bNoMatch) {
pFormatResString(lpdmpd,szTemp, 0, 0, ResType);
} else {
pFormatResString(lpdmpd,szTemp, ulValue, ulLen, ResType);
}
ListView_SetItemText(hWndList, iNewItem, 1, szTemp);
++iNewItem;
}
pShowEntry = pShowEntry->Next;
}
if(ulMaxMem > 0xFFFFFFFF) {
//
// an excuse to require 64-bit address range
//
lpdmpd->dwFlags |= DMPROP_FLAG_64BIT_RANGE;
}
SendMessage(hWndList, WM_SETREDRAW, (WPARAM)TRUE, 0);
RetCode = TRUE;
Final:
pDeleteResDesDataList(pKnownValues);
pDeleteResDesDataList(pShowValues);
//
// initialize listview headings here
//
ListView_SetColumnWidth(hWndList, 0, LVSCW_AUTOSIZE_USEHEADER);
ListView_SetColumnWidth(hWndList, 1, LVSCW_AUTOSIZE_USEHEADER);
//
// change "Change Settings" button
//
pCheckEnableResourceChange(lpdmpd);
return RetCode;
}
BOOL
bIsMultiFunctionChild(
PSP_DEVINFO_DATA lpdi,
HMACHINE hMachine
)
/*++
Routine Description:
Returns flag indicating if this is a child of a
multifunction device
Arguments:
Return Value:
TRUE if MF child
--*/
{
ULONG Status;
ULONG ProblemNumber;
if (lpdi->DevInst) {
if (CM_Get_DevNode_Status_Ex(&Status, &ProblemNumber,
lpdi->DevInst, 0,hMachine) == CR_SUCCESS) {
//
// If the passed in dev is not an MF child, then it is the top
// level MF_Parent
//
if (Status & DN_MF_CHILD) {
return TRUE;
} else {
return FALSE;
}
}
}
return FALSE;
}
VOID
pSelectLogConf(
LPDMPROP_DATA lpdmpd,
LOG_CONF forceLC,
ULONG forceLCType,
BOOL Always
)
/*++
Routine Description:
Selects a LogConf, showing the config in the LC control
Arguments:
Return Value:
TRUE if MF child
--*/
{
HWND hDlg = lpdmpd->hDlg;
int count;
int i;
LOG_CONF LogConf;
if (Always == FALSE && forceLC == lpdmpd->SelectedLC) {
//
// selection remains the same
//
return;
}
count = (int)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
if (count == 0) {
MYASSERT(FALSE/*shouldn't get here*/);
pLoadCurrentConfig(lpdmpd,FALSE);
return;
}
if (forceLC == 0 && lpdmpd->CurrentLC == 0) {
//
// no currentLC, so select first default
//
forceLC = (LOG_CONF)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
CB_GETITEMDATA, (WPARAM)0, (LPARAM)0);
if (forceLC == (LOG_CONF)0) {
MYASSERT(FALSE/*shouldn't get here*/);
pLoadCurrentConfig(lpdmpd,FALSE);
return;
}
forceLCType = lpdmpd->ConfigListLCType;
}
for (i=0;i<count;i++) {
LogConf = (LOG_CONF)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
CB_GETITEMDATA, (WPARAM)i, (LPARAM)0);
if (LogConf == forceLC) {
//
// set these first so we don't recurse around
//
lpdmpd->SelectedLC = forceLC;
lpdmpd->SelectedLCType = forceLCType;
//
// change dialog to reflect new selection
//
SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_SETCURSEL, (WPARAM)i, (LPARAM)0);
pLoadConfig(lpdmpd,forceLC,forceLCType);
pShowConflicts(lpdmpd);
return;
}
}
SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_SETCURSEL, (WPARAM)(-1), (LPARAM)0);
pLoadConfig(lpdmpd,forceLC,forceLCType);
pShowConflicts(lpdmpd);
}
VOID
pChangeCurrentResSetting(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Brings up edit dialog to change currently selected resource
Arguments:
Return Value:
none
--*/
{
HWND hDlg = lpdmpd->hDlg;
RESOURCEEDITINFO rei;
HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
int iCur;
PITEMDATA pItemData = NULL;
LV_ITEM lviItem;
GENERIC_RESOURCE GenResInfo;
PDEVICE_INFO_SET pDeviceInfoSet;
BOOL changed = FALSE;
TCHAR szTemp[MAX_PATH];
pItemData = pGetResourceToChange(lpdmpd,&iCur);
if (pItemData == NULL) {
//
// we cannot edit this resource for some reason, give the user a hint
// and maybe I'll get less ear-ache "I cannot change the settings"
//
if ((lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES)!=0 ||
(lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)!=0) {
//
// editing not allowed - prob double-clicked on settings
//
return;
}
if (lpdmpd->dwFlags & DMPROP_FLAG_FIXEDCONFIG) {
pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYALL);
} else {
//
// see if user needs to select a resource
//
iCur = (int)ListView_GetNextItem(hList,-1, LVNI_SELECTED);
if (iCur == LB_ERR) {
//
// no selection
//
pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYSELECT);
} else {
//
// resource is just not editable
//
pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYSINGLE);
}
}
goto clean0;
}
ZeroMemory(&rei,sizeof(rei));
rei.hMachine = pGetMachine(lpdmpd);
rei.KnownLC = lpdmpd->CurrentLC;
rei.MatchingBasicLC = lpdmpd->MatchingLC;
rei.SelectedBasicLC = lpdmpd->SelectedLC;
rei.lpdi = lpdmpd->lpdi;
rei.dwPropFlags = lpdmpd->dwFlags;
rei.bShareable = FALSE;
rei.ridResType = pItemData->ResType;
rei.ResDes = pItemData->MatchingResDes;
rei.ulCurrentVal = pItemData->ulValue;
rei.ulCurrentLen = pItemData->ulLen;
rei.ulCurrentEnd = pItemData->ulEnd;
rei.ulCurrentFlags = pItemData->ulFlags;
rei.ulRangeCount = pItemData->RangeCount;
rei.pData = NULL;
if (DialogBoxParam(MyDllModuleHandle,
MAKEINTRESOURCE(IDD_EDIT_RESOURCE),
hDlg,
EditResourceDlgProc,
(LPARAM)(PRESOURCEEDITINFO)&rei) != IDOK) {
goto clean0;
}
//
// Update The Current Resource settings to Future
// Settings, and update the Conflict list.
//
pItemData->ulValue = rei.ulCurrentVal;
pItemData->ulLen = rei.ulCurrentLen;
pItemData->ulEnd = rei.ulCurrentEnd;
pItemData->ulFlags = rei.ulCurrentFlags;
pItemData->RangeCount = rei.ulRangeCount;
pItemData->bValid = TRUE; // indicate that user has explicitly changed this value
pFormatResString(lpdmpd,szTemp,
rei.ulCurrentVal,
rei.ulCurrentLen,
rei.ridResType);
ListView_SetItemText(hList, iCur, 1, szTemp);
pShowConflicts(lpdmpd);
//
// clear the flag for saving changes
//
lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
PropSheet_Changed(GetParent(hDlg), hDlg);
clean0:
;
}
VOID
pShowConflicts(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Selects a LogConf, showing the config in the LC control
Arguments:
Return Value:
TRUE if MF child
--*/
{
HWND hDlg = lpdmpd->hDlg;
CONFIGRET Status = CR_SUCCESS;
LPVOID vaArray[4];
TCHAR szTemp[MAX_PATH+4], szBuffer[MAX_PATH+16], szSetting[MAX_PATH];
TCHAR szFormat[MAX_PATH], szItemFormat[MAX_PATH];
TCHAR szUnavailable[MAX_PATH];
LPTSTR pszConflictList = NULL, pszConflictList2 = NULL;
ULONG ulSize = 0, ulLength, ulBufferLen, ulNewLength;
ULONG ulStartOffset = 0;
int Count = 0, i = 0;
PITEMDATA pItemData = NULL;
LPBYTE pResourceData = NULL;
HWND hwndResList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
HMACHINE hMachine;
ULONG ConflictCount = 0;
ULONG ConflictIndex = 0;
CONFLICT_LIST ConflictList = 0;
PDEVICE_INFO_SET pDeviceInfoSet;
CONFLICT_DETAILS ConflictDetails;
BOOL ReservedResource = FALSE;
BOOL AnyReportedResources = FALSE;
BOOL AnyBadResources = FALSE;
PCONFLICT_EXCEPTIONS pConflictExceptions = NULL;
//
// number of resources listed
//
Count = ListView_GetItemCount(hwndResList);
if (Count <= 0) {
goto Clean0;
}
//
// initial buffer that holds the strings
// with all the conflict info in them
//
ulBufferLen = 2048;
ulLength = 0;
pszConflictList = MyMalloc(ulBufferLen * sizeof(TCHAR));
if (pszConflictList == NULL) {
goto Clean0;
}
pszConflictList[0] = 0;
//
// obtain machine
//
if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
goto Clean0;
}
hMachine = pDeviceInfoSet->hMachine;
UnlockDeviceInfoSet (pDeviceInfoSet);
//
// do these once - these format strings use %1!s! type formats (FormatMessage)
//
LoadString(MyDllModuleHandle, IDS_CONFLICT_FMT, szFormat, MAX_PATH);
LoadString(MyDllModuleHandle, IDS_CONFLICT_UNAVAILABLE, szUnavailable, MAX_PATH);
//
// for every listed resource
//
for (i = 0; i < Count; i++) {
ConflictList = 0;
ConflictCount = 0;
//
// get the resource we're about to test
//
pItemData = (PITEMDATA)pGetListViewItemData(hwndResList, i, 0);
if (pItemData == NULL || pItemData->bValid == FALSE) {
//
// for whatever reason, we don't want to show conflict information on this resource
//
ListView_SetItemState(hwndResList, i,
INDEXTOOVERLAYMASK(0),
LVIS_OVERLAYMASK);
goto NextResource;
}
//
// this is set to indicate conflict not reported, but is reserved
//
ReservedResource = FALSE;
//
// need resource-data for determining conflict
//
if (MakeResourceData(&pResourceData, &ulSize,
pItemData->ResType,
pItemData->ulValue,
pItemData->ulLen,
pItemData->ulFlags)) {
Status = CM_Query_Resource_Conflict_List(&ConflictList,
lpdmpd->lpdi->DevInst,
pItemData->ResType,
pResourceData,
ulSize,
DEVRES_WIDTH_FLAGS,
hMachine);
if (Status != CR_SUCCESS) {
//
// on the unlikely event of an error, remember an error occurred
//
ConflictList = 0;
ConflictCount = 0;
AnyBadResources = TRUE;
} else {
//
// find out how many things conflicted
//
Status = CM_Get_Resource_Conflict_Count(ConflictList,&ConflictCount);
if (Status != CR_SUCCESS) {
MYASSERT(Status == CR_SUCCESS);
ConflictCount = 0;
AnyBadResources = TRUE;
}
}
if(ConflictCount && (lpdmpd->dwFlags & DMPROP_FLAG_SINGLE_CONFIG) && !(lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
//
// NTRAID#166214-2000/08/19-JamieHun Conflict Supression Hack
//
// rules are
// (1) device doesn't have a problem
// (2) device can only have one configuration (ie, there's no basic config, or the basic config is singular)
// (3) it has a ResourcePickerExceptions string, and that string indicates that the exception is allowed for the specific conflict
if(pConflictExceptions==NULL) {
pConflictExceptions = pLoadConflictExceptions(lpdmpd);
}
if (pConflictExceptions) {
BOOL muted = TRUE;
//
// count from 0 (first conflict) through to ConflictCount (excl)
//
for(ConflictIndex = 0; ConflictIndex < ConflictCount; ConflictIndex ++) {
//
// obtain details for this conflict
//
ZeroMemory(&ConflictDetails,sizeof(ConflictDetails));
ConflictDetails.CD_ulSize = sizeof(ConflictDetails);
ConflictDetails.CD_ulMask = CM_CDMASK_DEVINST | CM_CDMASK_DESCRIPTION | CM_CDMASK_FLAGS;
Status = CM_Get_Resource_Conflict_Details(ConflictList,ConflictIndex,&ConflictDetails);
if (Status == CR_SUCCESS) {
if (!pIsConflictException(lpdmpd,pConflictExceptions,ConflictDetails.CD_dnDevInst,ConflictDetails.CD_szDescription,pItemData->ResType,pItemData->ulValue,pItemData->ulLen)) {
muted = FALSE;
break;
}
}
}
if(muted) {
ConflictCount = 0;
}
}
}
if (ConflictCount || ReservedResource) {
ulStartOffset = ulLength; // record start in case we decide to backtrack
AnyReportedResources = TRUE; // say we reported at least one problem
TreatAsReserved:
ulLength = ulStartOffset;
pszConflictList[ulLength] = 0;
//
// we're going to mark the resource as a problem
//
ListView_GetItemText(hwndResList, i, 1, szSetting, MAX_PATH);
switch (pItemData->ResType) {
case ResType_Mem:
LoadString(MyDllModuleHandle, IDS_MEMORY_FULL, szBuffer, MAX_PATH);
break;
case ResType_IO:
LoadString(MyDllModuleHandle, IDS_IO_FULL, szBuffer, MAX_PATH);
break;
case ResType_DMA:
LoadString(MyDllModuleHandle, IDS_DMA_FULL, szBuffer, MAX_PATH);
break;
case ResType_IRQ:
LoadString(MyDllModuleHandle, IDS_IRQ_FULL, szBuffer, MAX_PATH);
break;
default:
MYASSERT(FALSE);
}
if ( ReservedResource == FALSE) {
//
// count from 0 (header) 1 (first conflict) through to ConflictCount
//
for(ConflictIndex = 0; ConflictIndex <= ConflictCount; ConflictIndex ++) {
if (ConflictIndex == 0) {
//
// first pass through, do header message
//
vaArray[0] = szBuffer;
vaArray[1] = szSetting;
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY ,
szFormat,
0,0,
szTemp,MAX_PATH,
(va_list*)vaArray); // FORMAT_MESSAGE_ARGUMENT_ARRAY
} else {
//
// obtain details for this conflict
//
ZeroMemory(&ConflictDetails,sizeof(ConflictDetails));
ConflictDetails.CD_ulSize = sizeof(ConflictDetails);
ConflictDetails.CD_ulMask = CM_CDMASK_DEVINST | CM_CDMASK_DESCRIPTION | CM_CDMASK_FLAGS;
Status = CM_Get_Resource_Conflict_Details(ConflictList,ConflictIndex-1,&ConflictDetails);
if (Status == CR_SUCCESS) {
if ((ConflictDetails.CD_ulFlags & CM_CDFLAGS_RESERVED) != 0) {
//
// treat as reserved - backtrack
//
ReservedResource = TRUE;
goto TreatAsReserved;
} else {
if (ConflictDetails.CD_szDescription[0] == 0) {
//
// treat as reserved - backtrack
//
ReservedResource = TRUE;
goto TreatAsReserved;
}
wsprintf(szBuffer,TEXT(" %s\r\n"),ConflictDetails.CD_szDescription);
}
} else {
//
// treat as reserved
//
ReservedResource = TRUE;
goto TreatAsReserved;
}
lstrcpyn(szTemp,szBuffer,MAX_PATH);
}
ulNewLength = ulLength + lstrlen(szTemp); // excluding terminating NUL
if ((ulNewLength+1) < ulBufferLen) {
//
// need to allocate more space - we'll double it and add some more every time
//
pszConflictList2 = MyRealloc(pszConflictList,(ulBufferLen+ulNewLength+1) * sizeof(TCHAR));
if (pszConflictList2 != NULL) {
//
// succeeded in resizing buffer
//
pszConflictList = pszConflictList2;
ulBufferLen = ulBufferLen+ulNewLength+1;
}
}
if ((ulNewLength+1) < ulBufferLen) {
lstrcpy(pszConflictList + ulLength , szTemp);
ulLength = ulNewLength;
}
}
} else {
//
// there is some other problem with resource
//
vaArray[0] = szBuffer;
vaArray[1] = szSetting;
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY ,
szUnavailable,
0,0,
szTemp,MAX_PATH,
(va_list*)vaArray); // FORMAT_MESSAGE_ARGUMENT_ARRAY
ulNewLength = ulLength + lstrlen(szTemp); // excluding terminating NUL
if ((ulNewLength+1) < ulBufferLen) {
//
// need to allocate more space - we'll double it and add some more every time
//
pszConflictList2 = MyRealloc(pszConflictList,(ulBufferLen+ulNewLength+1) * sizeof(TCHAR));
if (pszConflictList2 != NULL) {
//
// succeeded in resizing buffer
//
pszConflictList = pszConflictList2;
ulBufferLen = ulBufferLen+ulNewLength+1;
}
}
if ((ulNewLength+1) < ulBufferLen) {
lstrcpy(pszConflictList + ulLength , szTemp);
ulLength = ulNewLength;
}
}
//
// Set the Conflict Overlay for this resource.
//
ListView_SetItemState(hwndResList, i,
INDEXTOOVERLAYMASK(IDI_CONFLICT - IDI_RESOURCEOVERLAYFIRST + 1),
LVIS_OVERLAYMASK);
} else {
//
// resource is (aparently) working fine
//
ListView_SetItemState(hwndResList, i,
INDEXTOOVERLAYMASK(0),
LVIS_OVERLAYMASK);
}
if (ConflictList) {
CM_Free_Resource_Conflict_Handle(ConflictList);
}
if (pResourceData != NULL) {
MyFree(pResourceData);
}
} else {
//
// couldn't make the resource descriptor
AnyBadResources = TRUE;
}
NextResource:
;
}
Clean0:
;
//
// If there were any conflicts, put the list in the multiline edit box.
//
if (AnyReportedResources) {
SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, pszConflictList);
} else if (AnyBadResources) {
//
// this would most likely occur on
// (1) running this on 95/98 (shouldn't happen)
// (2) using new setupapi on old cfgmgr32
//
LoadString(MyDllModuleHandle, IDS_CONFLICT_GENERALERROR, szBuffer, MAX_PATH);
SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, szBuffer);
} else {
LoadString(MyDllModuleHandle, IDS_DEVRES_NOCONFLICTDEVS, szBuffer, MAX_PATH);
SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, szBuffer);
}
if(pszConflictList != NULL) {
MyFree(pszConflictList);
}
if (pConflictExceptions != NULL) {
pFreeConflictExceptions(pConflictExceptions);
}
return;
}
int
pOkToSave(
IN LPDMPROP_DATA lpdmpd
)
/*++
Routine Description:
Check to see if there's something the user hasn't done
Arguments:
Return Value:
IDYES = save settings
IDNO = don't save settings
IDCANCEL = don't exit
--*/
{
HWND hDlg = lpdmpd->hDlg;
HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
int iCur;
int nRes;
PITEMDATA pItemData;
if (lpdmpd->dwFlags & DMPROP_FLAG_NO_RESOURCES) {
//
// no changes - because there are no resources
//
return IDNO;
}
if (lpdmpd->dwFlags & DMPROP_FLAG_CHANGESSAVED) {
//
// no changes
//
return IDNO;
}
if (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) {
//
// always ok to "use sys settings"
//
return IDYES;
}
//
// user is forcing a config - let's see if all settings are valid
//
//
// The resource descriptors are out-of-order. Maintain the original ordering.
//
// First, build up a linked list of the data in the listview resource items.
//
iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
while (iCur >= 0) {
pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
if (pItemData) {
if (pItemData->bValid == FALSE) {
//
// we've got an invalid entry - can't save
//
nRes = pWarnNoSave(hDlg,IDS_FORCEDCONFIG_PARTIAL);
if (nRes != IDOK) {
return IDCANCEL;
}
return IDNO;
}
}
iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
}
//
// everything checks out
//
return IDYES;
}