1147 lines
34 KiB
C
1147 lines
34 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
devres1.c
|
||
|
||
Abstract:
|
||
|
||
Routines for displaying resource dialogs.
|
||
|
||
Author:
|
||
|
||
Paula Tomlinson (paulat) 7-Feb-1996
|
||
|
||
Revision History:
|
||
|
||
Jamie Hunter (jamiehun) 19-Mar-1998
|
||
Removed EditResource Dialog Proceedures into this file
|
||
Resource picking functionality improved
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#define Nearness(x,y) (((x)>(y))?(x)-(y):(y)-(x))
|
||
|
||
static UDACCEL udAccel[] = {{0,1},{1,16},{2,256},{3,4096},{4,16000}};
|
||
|
||
static const DWORD EditResHelpIDs[]=
|
||
{
|
||
IDC_EDITRES_INSTRUCTIONS, IDH_NOHELP,
|
||
IDC_EDITRES_MFCHILDREN, IDH_NOHELP,
|
||
IDC_EDITRES_VALUE_LABEL, IDH_DEVMGR_RESOURCES_EDIT_VALUE,
|
||
IDC_EDITRES_VALUE, IDH_DEVMGR_RESOURCES_EDIT_VALUE,
|
||
IDC_EDITRES_CONFLICTINFO, IDH_DEVMGR_RESOURCES_EDIT_INFO,
|
||
IDC_EDITRES_CONFLICTTEXT, IDH_DEVMGR_RESOURCES_EDIT_INFO,
|
||
IDC_EDITRES_CONFLICTLIST, IDH_DEVMGR_RESOURCES_EDIT_INFO,
|
||
0, 0
|
||
};
|
||
|
||
|
||
void
|
||
InitEditResDlg(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen
|
||
);
|
||
|
||
void
|
||
ClearEditResConflictList(
|
||
HWND hDlg,
|
||
DWORD dwFlags
|
||
);
|
||
|
||
void
|
||
UpdateEditResConflictList(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen,
|
||
ULONG ulFlags
|
||
);
|
||
|
||
void
|
||
GetOtherValues(
|
||
IN LPBYTE pData,
|
||
IN RESOURCEID ResType,
|
||
IN LONG Increment,
|
||
OUT PULONG64 pulValue,
|
||
OUT PULONG64 pulLen,
|
||
OUT PULONG64 pulEnd
|
||
);
|
||
|
||
void
|
||
UpdateEditResConflictList(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen,
|
||
ULONG ulFlags
|
||
);
|
||
|
||
BOOL
|
||
bValidateResourceVal(
|
||
HWND hDlg,
|
||
PULONG64 pulVal,
|
||
PULONG64 pulLen,
|
||
PULONG64 pulEnd,
|
||
PULONG pulIndex,
|
||
PRESOURCEEDITINFO lprei
|
||
);
|
||
|
||
BOOL
|
||
bConflictWarn(
|
||
HWND hDlg,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen,
|
||
ULONG64 ulEnd,
|
||
PRESOURCEEDITINFO lprei
|
||
);
|
||
|
||
void
|
||
ClearEditResConflictList(
|
||
HWND hDlg,
|
||
DWORD dwFlags
|
||
);
|
||
|
||
void
|
||
UpdateMFChildList(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei
|
||
);
|
||
|
||
//---------------------------------------------------------------------------
|
||
// Edit Resource Dialog Box
|
||
//---------------------------------------------------------------------------
|
||
|
||
|
||
|
||
INT_PTR
|
||
WINAPI
|
||
EditResourceDlgProc(
|
||
HWND hDlg,
|
||
UINT wMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
{
|
||
TCHAR szBuffer[MAX_PATH];
|
||
//
|
||
// ISSUE-2000/02/03-JamieHun Remove statics from EditResourceDlgProc
|
||
//
|
||
static ULONG64 ulEditedValue, ulEditedLen, ulEditedEnd;
|
||
|
||
|
||
switch (wMsg) {
|
||
|
||
case WM_INITDIALOG: {
|
||
|
||
PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)lParam;
|
||
ULONG ulSize = 0;
|
||
|
||
SetWindowLongPtr(hDlg, DWLP_USER, lParam); // save for later msgs
|
||
|
||
lprei->dwFlags &= ~REI_FLAGS_CONFLICT; // no conflict yet
|
||
lprei->dwFlags |= REI_FLAG_NONUSEREDIT; // no manual edits yet
|
||
|
||
ulEditedValue = lprei->ulCurrentVal;
|
||
ulEditedLen = lprei->ulCurrentLen;
|
||
ulEditedEnd = lprei->ulCurrentEnd;
|
||
|
||
InitEditResDlg(hDlg, lprei, ulEditedValue, ulEditedLen);
|
||
|
||
SetFocus(GetDlgItem(hDlg, IDC_EDITRES_VALUE));
|
||
break; // return default (FALSE) to indicate we've set focus
|
||
}
|
||
|
||
case WM_NOTIFY: {
|
||
|
||
PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
|
||
LPNM_UPDOWN lpnm = (LPNM_UPDOWN)lParam;
|
||
|
||
switch (lpnm->hdr.code) {
|
||
|
||
case UDN_DELTAPOS:
|
||
if (lpnm->hdr.idFrom == IDC_EDITRES_SPIN) {
|
||
|
||
if (lpnm->iDelta > 0) {
|
||
GetOtherValues(lprei->pData, lprei->ridResType, +1,
|
||
&ulEditedValue,
|
||
&ulEditedLen,
|
||
&ulEditedEnd);
|
||
} else {
|
||
GetOtherValues(lprei->pData, lprei->ridResType, -1,
|
||
&ulEditedValue,
|
||
&ulEditedLen,
|
||
&ulEditedEnd);
|
||
}
|
||
|
||
pFormatResString(NULL,szBuffer, ulEditedValue, ulEditedLen,
|
||
lprei->ridResType);
|
||
|
||
lprei->dwFlags |= REI_FLAG_NONUSEREDIT;
|
||
SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
|
||
UpdateEditResConflictList(hDlg, lprei,
|
||
ulEditedValue,
|
||
ulEditedLen,
|
||
lprei->ulCurrentFlags);
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
case WM_COMMAND: {
|
||
|
||
switch(LOWORD(wParam)) {
|
||
|
||
case IDOK: {
|
||
|
||
PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO) GetWindowLongPtr(hDlg, DWLP_USER);
|
||
ULONG ulIndex;
|
||
|
||
//
|
||
// Validate the values (could have been manually edited)
|
||
//
|
||
if (bValidateResourceVal(hDlg, &ulEditedValue, &ulEditedLen,
|
||
&ulEditedEnd, &ulIndex, lprei)) {
|
||
//
|
||
// Warn if there is a conflict. If use accepts conflict
|
||
// end the dialog, otherwise update the
|
||
// edit control since it may have been changed by the
|
||
// Validate call.
|
||
//
|
||
//No HMACHINE
|
||
if(bConflictWarn(hDlg, ulEditedValue, ulEditedLen,
|
||
ulEditedEnd, lprei)) {
|
||
|
||
lprei->ulCurrentVal = ulEditedValue;
|
||
lprei->ulCurrentLen = ulEditedLen;
|
||
lprei->ulCurrentEnd = ulEditedEnd;
|
||
lprei->ulRangeCount = ulIndex;
|
||
EndDialog(hDlg, IDOK);
|
||
|
||
if (lprei->pData) {
|
||
MyFree(lprei->pData);
|
||
}
|
||
|
||
} else {
|
||
//
|
||
// Format and display the data
|
||
//
|
||
pFormatResString(NULL,szBuffer, ulEditedValue, ulEditedLen, lprei->ridResType);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
|
||
//
|
||
// Update the Conflict List.
|
||
//
|
||
UpdateEditResConflictList(hDlg, lprei, ulEditedValue, ulEditedLen, lprei->ulCurrentFlags);
|
||
}
|
||
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
case IDCANCEL: {
|
||
|
||
PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
|
||
|
||
if (lprei->pData) {
|
||
MyFree(lprei->pData);
|
||
}
|
||
|
||
EndDialog(hDlg, FALSE);
|
||
return TRUE;
|
||
}
|
||
|
||
case IDC_EDITRES_VALUE: {
|
||
switch (HIWORD(wParam)) {
|
||
case EN_CHANGE: {
|
||
|
||
PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
|
||
|
||
// If Non user edit, then clear the flag, else
|
||
// clear the conflict list, since we are unsure
|
||
// of what the user has entered at this time
|
||
|
||
if (lprei->dwFlags & REI_FLAG_NONUSEREDIT) {
|
||
lprei->dwFlags &= ~REI_FLAG_NONUSEREDIT;
|
||
} else {
|
||
ClearEditResConflictList(hDlg, CEF_UNKNOWN);
|
||
}
|
||
break;
|
||
}
|
||
|
||
// If the edit control looses focus, then we should
|
||
// validte the contents
|
||
case EN_KILLFOCUS: {
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case WM_HELP: // F1
|
||
WinHelp(((LPHELPINFO)lParam)->hItemHandle, DEVRES_HELP, HELP_WM_HELP, (ULONG_PTR)EditResHelpIDs);
|
||
break;
|
||
|
||
case WM_CONTEXTMENU: // right mouse click
|
||
WinHelp((HWND)wParam, DEVRES_HELP, HELP_CONTEXTMENU, (ULONG_PTR)EditResHelpIDs);
|
||
break;
|
||
}
|
||
return FALSE;
|
||
|
||
} // EditResourceDlgProc
|
||
|
||
|
||
|
||
|
||
void
|
||
InitEditResDlg(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen
|
||
)
|
||
{
|
||
TCHAR szBuffer[MAX_PATH], szInstr[MAX_PATH], szTemp[MAX_PATH],
|
||
szResType[MAX_PATH], szResTypeLC[MAX_PATH];
|
||
ULONG ulSize = 0;
|
||
|
||
|
||
//
|
||
// Set the initial Value
|
||
//
|
||
pFormatResString(NULL,szBuffer, ulVal, ulLen, lprei->ridResType);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
|
||
|
||
//
|
||
// Setup the Spinner
|
||
//
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETRANGE, 0, MAKELONG(MAX_SPINRANGE, 0));
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETPOS, 0, MAKELONG(0,0));
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETACCEL, 5, (LPARAM)(LPUDACCEL)udAccel);
|
||
|
||
//
|
||
// Limit the Edit Text.
|
||
//
|
||
switch (lprei->ridResType) {
|
||
|
||
case ResType_Mem:
|
||
LoadString(MyDllModuleHandle, IDS_MEMORY_FULL, szResType, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_MEMORY_FULL_LC, szResTypeLC, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR1, szInstr, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR2, szTemp, MAX_PATH);
|
||
lstrcat(szInstr, szTemp);
|
||
|
||
//
|
||
// Limit the Input field to Start Val (8) + End Val(8) + seperator (4)
|
||
//
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 20, 0l);
|
||
break;
|
||
|
||
case ResType_IO:
|
||
LoadString(MyDllModuleHandle, IDS_IO_FULL, szResType, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR1, szInstr, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR2, szTemp, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_IO_FULL_LC, szResTypeLC, MAX_PATH);
|
||
lstrcat(szInstr, szTemp);
|
||
|
||
//
|
||
// Limit the Input field to Start Val (4) + End Val(4) + seperator (4)
|
||
//
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 12, 0l);
|
||
break;
|
||
|
||
case ResType_DMA:
|
||
LoadString(MyDllModuleHandle, IDS_DMA_FULL, szResType, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR1, szInstr, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR2, szTemp, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_DMA_FULL_LC, szResTypeLC, MAX_PATH);
|
||
lstrcat(szInstr, szTemp);
|
||
|
||
//
|
||
// Limit the Input field to Val (2)
|
||
//
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 2, 0l);
|
||
break;
|
||
|
||
case ResType_IRQ:
|
||
LoadString(MyDllModuleHandle, IDS_IRQ_FULL, szResType, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR1, szInstr, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR2, szTemp, MAX_PATH);
|
||
LoadString(MyDllModuleHandle, IDS_IRQ_FULL_LC, szResTypeLC, MAX_PATH);
|
||
lstrcat(szInstr, szTemp);
|
||
|
||
//
|
||
// Limit the Input field to Val (2)
|
||
//
|
||
SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 2, 0l);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Set the Instruction Text
|
||
//
|
||
wsprintf(szBuffer, szInstr, szResTypeLC);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_INSTRUCTIONS, szBuffer);
|
||
|
||
//
|
||
// Set the Dialog Title
|
||
//
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_TITLE, szTemp, MAX_PATH);
|
||
wsprintf(szBuffer, szTemp, szResType);
|
||
SetWindowText(hDlg, szBuffer);
|
||
|
||
//
|
||
// If this is a MF parent device, then show which children own this resource.
|
||
//
|
||
UpdateMFChildList(hDlg, lprei);
|
||
|
||
//
|
||
// Read the res des data and store a ptr to it so we
|
||
// don't have to refetch it multiple times.
|
||
//
|
||
lprei->pData = NULL;
|
||
if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, lprei->ResDes, CM_RESDES_WIDTH_64,lprei->hMachine) == CR_SUCCESS) {
|
||
lprei->pData = MyMalloc(ulSize);
|
||
if (lprei->pData != NULL) {
|
||
CM_Get_Res_Des_Data_Ex(lprei->ResDes, lprei->pData, ulSize, CM_RESDES_WIDTH_64,lprei->hMachine);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Update the Conflict List.
|
||
//
|
||
UpdateEditResConflictList(hDlg, lprei, ulVal, ulLen, lprei->ulCurrentFlags);
|
||
|
||
|
||
} // InitEditResDlg
|
||
|
||
|
||
|
||
BOOL
|
||
LocateClosestValue(
|
||
IN LPBYTE pData,
|
||
IN RESOURCEID ResType,
|
||
IN ULONG64 TestValue,
|
||
IN ULONG64 TestLen,
|
||
IN INT Mode,
|
||
OUT PULONG64 OutValue, OPTIONAL
|
||
OUT PULONG64 OutLen, OPTIONAL
|
||
OUT PULONG OutIndex OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine finds the nearest valid address/range
|
||
to that the user specified
|
||
if Mode == 0, the nearest value is used
|
||
if Mode > 0, the nearest higher value is used
|
||
if Mode < 0, the nearest lower value is used
|
||
|
||
Arguments:
|
||
|
||
pData - information about the resources being selected
|
||
ResType - type of resource being selected
|
||
CurrentValue - value entered by user
|
||
CurrentLen - length based on range entered by user
|
||
Mode - search mode, -1 = previous, 1 = next, 0 = nearest
|
||
OutValue - nearest valid value
|
||
OutLen - length associated with nearest valid value
|
||
|
||
Return Value:
|
||
|
||
If exact match found, return TRUE
|
||
otherwise FALSE
|
||
|
||
--*/
|
||
{
|
||
PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)pData;
|
||
ULONG64 Start, Len, End, Align;
|
||
ULONG Flags;
|
||
ULONG64 BestVal;
|
||
ULONG64 BestValL;
|
||
ULONG64 BestValU;
|
||
ULONG64 FoundVal = 0;
|
||
ULONG64 FoundLen = 0;
|
||
ULONG FoundIndex = 0;
|
||
ULONG Index;
|
||
BOOL FindNearest = TRUE; // indicates we should find nearest
|
||
|
||
//
|
||
// precedence (1) Value&Len match exactly
|
||
// precedence (2) closest valid value
|
||
//
|
||
|
||
//
|
||
// cover a catch-all case - start of the very first resource range
|
||
//
|
||
pGetRangeValues(pData, ResType, 0, &Start, &Len, &End, &Align, &Flags);
|
||
//
|
||
// we have at least 1 found value
|
||
//
|
||
FoundVal = Start;
|
||
FoundLen = Len;
|
||
|
||
//
|
||
// Find a nearby valid range to the one supplied
|
||
//
|
||
|
||
//
|
||
// check each range at a time
|
||
// sometimes ranges may not be given in ascending order
|
||
// eg, first range is a preferred, second range is alternative
|
||
//
|
||
for (Index = 0; Index < pGenRes->GENERIC_Header.GENERIC_Count; Index++) {
|
||
|
||
//
|
||
// get limits for this range
|
||
//
|
||
pGetRangeValues(pData, ResType, Index, &Start, &Len, &End, &Align, &Flags);
|
||
|
||
//
|
||
// first, try to find a value that is GOOD, that is <= TestValue
|
||
//
|
||
|
||
BestValL = TestValue;
|
||
if (pAlignValues(&BestValL, Start, Len, End, Align, -1) == FALSE) {
|
||
//
|
||
// if it failed, use the lowest value in this range (ie Start)
|
||
//
|
||
BestValL = Start;
|
||
}
|
||
|
||
//
|
||
// find an upper value that is aligned
|
||
//
|
||
if (BestValL == TestValue) {
|
||
//
|
||
// if match was exact, skip test
|
||
//
|
||
BestValU = TestValue;
|
||
} else {
|
||
//
|
||
// search for upper limit
|
||
//
|
||
BestValU = TestValue;
|
||
if (pAlignValues(&BestValU, Start, Len, End, Align, 1) == FALSE) {
|
||
//
|
||
// couldn't use it - find highest valid value
|
||
//
|
||
BestValU = End-Len+1;
|
||
if (pAlignValues(&BestValU, Start, Len, End, Align, -1) == FALSE) {
|
||
//
|
||
// still no go
|
||
//
|
||
BestValU = BestValL;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// now we have found our boundaries
|
||
// may need to modify, depending on preferences
|
||
//
|
||
|
||
if (Mode<0) {
|
||
//
|
||
// if range is < TestVal, use highest, else lowest
|
||
//
|
||
if (BestValU <= TestValue) {
|
||
BestVal = BestValU;
|
||
} else {
|
||
BestVal = BestValL;
|
||
}
|
||
} else if (Mode>0) {
|
||
//
|
||
// if range is > TestVal, use lowest, else highest
|
||
//
|
||
if (BestValL >= TestValue) {
|
||
BestVal = BestValL;
|
||
} else {
|
||
BestVal = BestValU;
|
||
}
|
||
} else {
|
||
//
|
||
// use closest of the two values
|
||
//
|
||
if (Nearness(BestValL,TestValue)<= Nearness(BestValU,TestValue)) {
|
||
BestVal = BestValL;
|
||
} else {
|
||
BestVal = BestValU;
|
||
}
|
||
}
|
||
|
||
//
|
||
// we know that BestVal is valid within the range
|
||
// and is the choice for this range
|
||
//
|
||
|
||
//
|
||
// handle the match cases
|
||
//
|
||
if (TestValue == BestVal && TestLen == Len) {
|
||
//
|
||
// exact match
|
||
//
|
||
|
||
if (OutValue != NULL) {
|
||
*OutValue = BestVal;
|
||
}
|
||
if (OutLen != NULL) {
|
||
*OutLen = Len;
|
||
}
|
||
if (OutIndex != NULL) {
|
||
*OutIndex = Index;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
if (FindNearest && Mode != 0) {
|
||
//
|
||
// we are currently in "FindNearest" mode which means
|
||
// we haven't found one in the direction we wanted
|
||
//
|
||
if (Mode < 0 && BestVal <= TestValue) {
|
||
//
|
||
// not looking for nearness now we've found one lower
|
||
//
|
||
FoundVal = BestVal;
|
||
FoundLen = Len;
|
||
FoundIndex = Index;
|
||
FindNearest = FALSE;
|
||
} else if (Mode > 0 && BestVal >= TestValue) {
|
||
//
|
||
// not looking for nearness now we've found one higher
|
||
//
|
||
FoundVal = BestVal;
|
||
FoundLen = Len;
|
||
FoundIndex = Index;
|
||
FindNearest = FALSE;
|
||
}
|
||
|
||
} else if (FindNearest ||
|
||
(Mode < 0 && BestVal <= TestValue) ||
|
||
(Mode > 0 && BestVal >= TestValue)) {
|
||
if (Nearness(BestVal,TestValue) < Nearness(FoundVal,TestValue)) {
|
||
//
|
||
// this address is nearer
|
||
//
|
||
FoundVal = BestVal;
|
||
FoundLen = Len;
|
||
FoundIndex = Index;
|
||
} else if (Nearness(BestVal,TestValue) == Nearness(FoundVal,TestValue)) {
|
||
//
|
||
// this address guess is as near as nearest guess, pick the better length
|
||
//
|
||
// I can't see any place that this should happen
|
||
// but theoretically it could happen
|
||
// so this is a safety net more than anything else
|
||
//
|
||
if (Nearness(Len,TestLen) < Nearness(FoundLen,TestLen)) {
|
||
//
|
||
// this length is nearer
|
||
//
|
||
FoundVal = BestVal;
|
||
FoundLen = Len;
|
||
FoundIndex = Index;
|
||
} else if (Nearness(Len,TestLen) == Nearness(FoundLen,TestLen)) {
|
||
//
|
||
// pick the bigger (safer)
|
||
//
|
||
if (Len > FoundLen) {
|
||
//
|
||
// this length is bigger
|
||
//
|
||
FoundVal = BestVal;
|
||
FoundLen = Len;
|
||
FoundIndex = Index;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// if we get here, we didn't find an exact match
|
||
//
|
||
|
||
// Use our best guess
|
||
if (OutValue != NULL) {
|
||
*OutValue = FoundVal;
|
||
}
|
||
if (OutLen != NULL) {
|
||
*OutLen = FoundLen;
|
||
}
|
||
if (OutIndex != NULL) {
|
||
*OutIndex = FoundIndex;
|
||
}
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
|
||
void
|
||
GetOtherValues(
|
||
IN LPBYTE pData,
|
||
IN RESOURCEID ResType,
|
||
IN LONG Increment,
|
||
IN OUT PULONG64 pulValue,
|
||
IN OUT PULONG64 pulLen,
|
||
IN OUT PULONG64 pulEnd
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the next valid value, wrapping around to beginning/end value when end of range
|
||
|
||
Arguments:
|
||
|
||
pData - resource data
|
||
ResType - resource type
|
||
Increment - 1 or -1
|
||
pulValue - pointer to old/new start that is changed
|
||
pulLen - pointer to old/new length
|
||
pulEnd - pointer to old/new end
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
{
|
||
|
||
ULONG64 TestValue = *pulValue;
|
||
ULONG64 TestLen = *pulLen;
|
||
ULONG64 RetValue = 0;
|
||
ULONG64 RetLen = 0;
|
||
|
||
MYASSERT((Increment == 1) || (Increment == -1));
|
||
|
||
if (Increment == 1) {
|
||
TestValue++;
|
||
LocateClosestValue(pData,ResType,TestValue,TestLen, 1 ,&RetValue,&RetLen,NULL);
|
||
if (RetValue < TestValue) {
|
||
//
|
||
// wrap around, find lowest possible valid address
|
||
//
|
||
LocateClosestValue(pData,ResType,0,TestLen, 0 ,&RetValue,&RetLen,NULL);
|
||
}
|
||
} else {
|
||
TestValue--;
|
||
LocateClosestValue(pData,ResType,TestValue,TestLen, -1 ,&RetValue,&RetLen,NULL);
|
||
if (RetValue > TestValue) {
|
||
//
|
||
// wrap around, find highest possible valid address
|
||
//
|
||
LocateClosestValue(pData,ResType,(ULONG64)(-1),TestLen, 0 ,&RetValue,&RetLen,NULL);
|
||
}
|
||
}
|
||
|
||
*pulValue = RetValue;
|
||
*pulLen = RetLen;
|
||
*pulEnd = RetValue + RetLen - 1;
|
||
|
||
return;
|
||
|
||
} // GetOtherValues
|
||
|
||
|
||
void
|
||
UpdateEditResConflictList(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen,
|
||
ULONG ulFlags
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates all the conflict information for the selected resource
|
||
Should give more details than UpdateDevResConflictList
|
||
|
||
Arguments:
|
||
|
||
hDlg - handle of this dialog to display into
|
||
lprei - resource edit info
|
||
ulVal - value to try
|
||
ulLen - length to test
|
||
ulFlags - flags part of resdes
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
{
|
||
CONFIGRET Status = CR_SUCCESS;
|
||
HWND hwndConflictList = GetDlgItem(hDlg, IDC_EDITRES_CONFLICTLIST);
|
||
ULONG ConflictCount = 0;
|
||
ULONG ConflictIndex = 0;
|
||
ULONG ulSize = 0;
|
||
LPBYTE pResourceData = NULL;
|
||
CONFLICT_LIST ConflictList = 0;
|
||
PDEVICE_INFO_SET pDeviceInfoSet;
|
||
CONFLICT_DETAILS ConflictDetails;
|
||
TCHAR szBuffer[MAX_PATH];
|
||
TCHAR szItemFormat[MAX_PATH];
|
||
BOOL ReservedResource = FALSE;
|
||
BOOL BadResource = FALSE;
|
||
|
||
//
|
||
// need resource-data for determining conflict
|
||
//
|
||
if (MakeResourceData(&pResourceData, &ulSize,
|
||
lprei->ridResType,
|
||
ulVal,
|
||
ulLen,
|
||
ulFlags)) {
|
||
|
||
Status = CM_Query_Resource_Conflict_List(&ConflictList,
|
||
lprei->lpdi->DevInst,
|
||
lprei->ridResType,
|
||
pResourceData,
|
||
ulSize,
|
||
DEVRES_WIDTH_FLAGS,
|
||
lprei->hMachine);
|
||
|
||
if (Status != CR_SUCCESS) {
|
||
//
|
||
// error occurred
|
||
//
|
||
ConflictList = 0;
|
||
ConflictCount = 0;
|
||
BadResource = TRUE;
|
||
} else {
|
||
//
|
||
// find out how many things conflicted
|
||
//
|
||
Status = CM_Get_Resource_Conflict_Count(ConflictList,&ConflictCount);
|
||
if (Status != CR_SUCCESS) {
|
||
//
|
||
// error shouldn't occur
|
||
//
|
||
MYASSERT(Status == CR_SUCCESS);
|
||
ConflictCount = 0;
|
||
BadResource = TRUE;
|
||
}
|
||
}
|
||
} else {
|
||
MYASSERT(FALSE);
|
||
//
|
||
// should not fail
|
||
//
|
||
ConflictList = 0;
|
||
ConflictCount = 0;
|
||
BadResource = TRUE;
|
||
}
|
||
if (BadResource) {
|
||
//
|
||
// The resource conflict information is indeterminate
|
||
//
|
||
SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
|
||
lprei->dwFlags &= ~REI_FLAGS_CONFLICT;
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICT, szBuffer, MAX_PATH);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICTINGDEVS, szBuffer, MAX_PATH);
|
||
SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
|
||
|
||
} else if (ConflictCount || ReservedResource) {
|
||
|
||
TreatAsReserved:
|
||
|
||
SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
|
||
lprei->dwFlags |= REI_FLAGS_CONFLICT;
|
||
|
||
if(ReservedResource == FALSE) {
|
||
//
|
||
// The resource conflicts with another unknown device.
|
||
//
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_DEVCONFLICT, szBuffer, MAX_PATH);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
|
||
|
||
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 ((ConflictDetails.CD_ulFlags & CM_CDFLAGS_RESERVED) != 0) {
|
||
//
|
||
// treat as reserved - backtrack
|
||
//
|
||
ReservedResource = TRUE;
|
||
goto TreatAsReserved;
|
||
}
|
||
//
|
||
// convert CD_dnDevInst to string information
|
||
//
|
||
lstrcpy(szBuffer,ConflictDetails.CD_szDescription);
|
||
if (szBuffer[0] == 0) {
|
||
ReservedResource = TRUE;
|
||
goto TreatAsReserved;
|
||
}
|
||
|
||
} else {
|
||
MYASSERT(Status == CR_SUCCESS);
|
||
ReservedResource = TRUE;
|
||
goto TreatAsReserved;
|
||
}
|
||
|
||
SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
|
||
}
|
||
} else {
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RESERVED, szBuffer, MAX_PATH);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_RESERVEDRANGE, szBuffer, MAX_PATH);
|
||
SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
|
||
}
|
||
|
||
} else {
|
||
//
|
||
// The resource does not conflict with any other devices.
|
||
//
|
||
SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
|
||
lprei->dwFlags &= ~REI_FLAGS_CONFLICT;
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICT, szBuffer, MAX_PATH);
|
||
SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICTINGDEVS, szBuffer, MAX_PATH);
|
||
SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
|
||
}
|
||
|
||
if (ConflictList) {
|
||
CM_Free_Resource_Conflict_Handle(ConflictList);
|
||
}
|
||
|
||
if (pResourceData != NULL) {
|
||
MyFree(pResourceData);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
BOOL
|
||
bValidateResourceVal(
|
||
HWND hDlg,
|
||
PULONG64 pulVal,
|
||
PULONG64 pulLen,
|
||
PULONG64 pulEnd,
|
||
PULONG pulIndex,
|
||
PRESOURCEEDITINFO lprei
|
||
)
|
||
{
|
||
TCHAR szSetting[MAX_VAL_LEN], szNewSetting[MAX_VAL_LEN];
|
||
TCHAR szMessage[MAX_MSG_LEN], szTemp[MAX_MSG_LEN], szTemp1[MAX_MSG_LEN];
|
||
TCHAR szTitle[MAX_PATH];
|
||
ULONG64 ulVal, ulEnd, ulLen;
|
||
ULONG64 ulValidVal, ulValidLen;
|
||
ULONG ulIndex;
|
||
BOOL bRet;
|
||
BOOL exact = TRUE;
|
||
|
||
|
||
GetDlgItemText(hDlg, IDC_EDITRES_VALUE, szSetting, MAX_VAL_LEN);
|
||
|
||
if (pUnFormatResString(szSetting, &ulVal, &ulEnd, lprei->ridResType)) {
|
||
|
||
ulLen = ulEnd - ulVal + 1;
|
||
|
||
//
|
||
// Validate the Current Settings
|
||
//
|
||
// If an exact match doesn't exist
|
||
// use a close match
|
||
// close is based on start address
|
||
//
|
||
|
||
if (LocateClosestValue(lprei->pData, lprei->ridResType,
|
||
ulVal, ulLen,0,
|
||
&ulValidVal, &ulValidLen,&ulIndex) == FALSE) {
|
||
//
|
||
// An alternate setting was found
|
||
// we think this might be what the user wanted
|
||
//
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_ENTRYERROR, szTitle, MAX_PATH);
|
||
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR1, szTemp, MAX_MSG_LEN);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR2, szTemp1, MAX_MSG_LEN);
|
||
lstrcat(szTemp, szTemp1);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR3, szTemp1, MAX_MSG_LEN);
|
||
lstrcat(szTemp, szTemp1);
|
||
|
||
pFormatResString(NULL, szSetting, ulVal, ulLen, lprei->ridResType);
|
||
pFormatResString(NULL,szNewSetting, ulValidVal, ulValidLen, lprei->ridResType);
|
||
|
||
wsprintf(szMessage, szTemp, szSetting, szNewSetting);
|
||
|
||
if (MessageBox(hDlg, szMessage, szTitle,
|
||
MB_YESNO | MB_TASKMODAL | MB_ICONEXCLAMATION) == IDYES) {
|
||
//
|
||
// Update the Edited values.
|
||
//
|
||
*pulVal = ulValidVal;
|
||
*pulLen = ulValidLen;
|
||
*pulEnd = ulValidVal + ulValidLen - 1;
|
||
*pulIndex = ulIndex;
|
||
bRet = TRUE;
|
||
} else {
|
||
bRet = FALSE;
|
||
}
|
||
|
||
} else {
|
||
//
|
||
// The specified values are valid
|
||
//
|
||
*pulVal = ulVal;
|
||
*pulLen = ulLen;
|
||
*pulEnd = ulEnd;
|
||
*pulIndex = ulIndex;
|
||
bRet = TRUE;
|
||
}
|
||
|
||
} else {
|
||
|
||
switch (lprei->ridResType) {
|
||
case ResType_Mem:
|
||
LoadString(MyDllModuleHandle, IDS_ERROR_BADMEMTEXT, szMessage, MAX_MSG_LEN);
|
||
break;
|
||
case ResType_IO:
|
||
LoadString(MyDllModuleHandle, IDS_ERROR_BADIOTEXT, szMessage, MAX_MSG_LEN);
|
||
break;
|
||
case ResType_DMA:
|
||
LoadString(MyDllModuleHandle, IDS_ERROR_BADDMATEXT, szMessage, MAX_MSG_LEN);
|
||
break;
|
||
case ResType_IRQ:
|
||
LoadString(MyDllModuleHandle, IDS_ERROR_BADIRQTEXT, szMessage, MAX_MSG_LEN);
|
||
break;
|
||
}
|
||
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_ENTRYERROR, szTitle, MAX_PATH);
|
||
MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONASTERISK);
|
||
bRet = FALSE;
|
||
}
|
||
|
||
return bRet;
|
||
|
||
} // bValidateResoureceVal
|
||
|
||
|
||
|
||
BOOL
|
||
bConflictWarn(
|
||
HWND hDlg,
|
||
ULONG64 ulVal,
|
||
ULONG64 ulLen,
|
||
ULONG64 ulEnd,
|
||
PRESOURCEEDITINFO lprei
|
||
)
|
||
{
|
||
BOOL bRet = TRUE;
|
||
TCHAR szMessage[MAX_MSG_LEN], szTitle[MAX_PATH];
|
||
|
||
|
||
if (!(lprei->dwFlags & REI_FLAG_NONUSEREDIT)) {
|
||
//
|
||
// user edits have been made so the conflict flag may not be
|
||
// up-to-date, check conflicts now.
|
||
//
|
||
UpdateEditResConflictList(hDlg, lprei, ulVal, ulLen, lprei->ulCurrentFlags);
|
||
}
|
||
|
||
if (lprei->dwFlags & REI_FLAGS_CONFLICT) {
|
||
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_CONFLICTWARNMSG, szMessage, MAX_MSG_LEN);
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_CONFLICTWARNTITLE, szTitle, MAX_PATH);
|
||
|
||
if (MessageBox(hDlg, szMessage, szTitle,
|
||
MB_YESNO | MB_DEFBUTTON2| MB_TASKMODAL | MB_ICONEXCLAMATION) == IDNO) {
|
||
bRet = FALSE;
|
||
} else {
|
||
bRet = TRUE; // User approved conflict
|
||
}
|
||
}
|
||
|
||
return bRet;
|
||
|
||
} // bConflictWarn
|
||
|
||
|
||
|
||
void
|
||
ClearEditResConflictList(
|
||
HWND hDlg,
|
||
DWORD dwFlags
|
||
)
|
||
{
|
||
HWND hwndConflictList = GetDlgItem(hDlg, IDC_EDITRES_CONFLICTLIST);
|
||
TCHAR szBuffer[MAX_PATH];
|
||
|
||
//
|
||
// Clear the Conflict list to start.
|
||
//
|
||
SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
|
||
|
||
//
|
||
// Load and set the info text string
|
||
//
|
||
if (dwFlags & CEF_UNKNOWN) {
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICT, szBuffer, MAX_PATH);
|
||
} else {
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICT, szBuffer, MAX_PATH);
|
||
}
|
||
SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
|
||
|
||
//
|
||
// Load and set the List string
|
||
//
|
||
if (dwFlags & CEF_UNKNOWN) {
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICTINGDEVS, szBuffer, MAX_PATH);
|
||
} else {
|
||
LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICTINGDEVS, szBuffer, MAX_PATH);
|
||
}
|
||
SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
|
||
|
||
} // ClearEditResConflictList
|
||
|
||
|
||
|
||
|
||
|
||
void
|
||
UpdateMFChildList(
|
||
HWND hDlg,
|
||
PRESOURCEEDITINFO lprei
|
||
)
|
||
{
|
||
UNREFERENCED_PARAMETER(hDlg);
|
||
UNREFERENCED_PARAMETER(lprei);
|
||
|
||
//
|
||
// See if this is a MF parent device. Check for a Child0000 subkey
|
||
//
|
||
// NOT IMPLEMENTED, SEE WINDOWS 95 SOURCES.
|
||
//
|
||
|
||
} // UpdateMFChildList
|
||
|
||
|