You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4704 lines
148 KiB
4704 lines
148 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|