4705 lines
143 KiB
C
4705 lines
143 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|