windows-nt/Source/XPSP1/NT/base/pnp/setupapi/devres1.c
2020-09-26 16:20:57 +08:00

1147 lines
34 KiB
C
Raw Blame History

This file contains invisible Unicode characters

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

/*++
Copyright (c) 1995 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