Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1146 lines
34 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. devres1.c
  5. Abstract:
  6. Routines for displaying resource dialogs.
  7. Author:
  8. Paula Tomlinson (paulat) 7-Feb-1996
  9. Revision History:
  10. Jamie Hunter (jamiehun) 19-Mar-1998
  11. Removed EditResource Dialog Proceedures into this file
  12. Resource picking functionality improved
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define Nearness(x,y) (((x)>(y))?(x)-(y):(y)-(x))
  17. static UDACCEL udAccel[] = {{0,1},{1,16},{2,256},{3,4096},{4,16000}};
  18. static const DWORD EditResHelpIDs[]=
  19. {
  20. IDC_EDITRES_INSTRUCTIONS, IDH_NOHELP,
  21. IDC_EDITRES_MFCHILDREN, IDH_NOHELP,
  22. IDC_EDITRES_VALUE_LABEL, IDH_DEVMGR_RESOURCES_EDIT_VALUE,
  23. IDC_EDITRES_VALUE, IDH_DEVMGR_RESOURCES_EDIT_VALUE,
  24. IDC_EDITRES_CONFLICTINFO, IDH_DEVMGR_RESOURCES_EDIT_INFO,
  25. IDC_EDITRES_CONFLICTTEXT, IDH_DEVMGR_RESOURCES_EDIT_INFO,
  26. IDC_EDITRES_CONFLICTLIST, IDH_DEVMGR_RESOURCES_EDIT_INFO,
  27. 0, 0
  28. };
  29. void
  30. InitEditResDlg(
  31. HWND hDlg,
  32. PRESOURCEEDITINFO lprei,
  33. ULONG64 ulVal,
  34. ULONG64 ulLen
  35. );
  36. void
  37. ClearEditResConflictList(
  38. HWND hDlg,
  39. DWORD dwFlags
  40. );
  41. void
  42. UpdateEditResConflictList(
  43. HWND hDlg,
  44. PRESOURCEEDITINFO lprei,
  45. ULONG64 ulVal,
  46. ULONG64 ulLen,
  47. ULONG ulFlags
  48. );
  49. void
  50. GetOtherValues(
  51. IN LPBYTE pData,
  52. IN RESOURCEID ResType,
  53. IN LONG Increment,
  54. OUT PULONG64 pulValue,
  55. OUT PULONG64 pulLen,
  56. OUT PULONG64 pulEnd
  57. );
  58. void
  59. UpdateEditResConflictList(
  60. HWND hDlg,
  61. PRESOURCEEDITINFO lprei,
  62. ULONG64 ulVal,
  63. ULONG64 ulLen,
  64. ULONG ulFlags
  65. );
  66. BOOL
  67. bValidateResourceVal(
  68. HWND hDlg,
  69. PULONG64 pulVal,
  70. PULONG64 pulLen,
  71. PULONG64 pulEnd,
  72. PULONG pulIndex,
  73. PRESOURCEEDITINFO lprei
  74. );
  75. BOOL
  76. bConflictWarn(
  77. HWND hDlg,
  78. ULONG64 ulVal,
  79. ULONG64 ulLen,
  80. ULONG64 ulEnd,
  81. PRESOURCEEDITINFO lprei
  82. );
  83. void
  84. ClearEditResConflictList(
  85. HWND hDlg,
  86. DWORD dwFlags
  87. );
  88. void
  89. UpdateMFChildList(
  90. HWND hDlg,
  91. PRESOURCEEDITINFO lprei
  92. );
  93. //---------------------------------------------------------------------------
  94. // Edit Resource Dialog Box
  95. //---------------------------------------------------------------------------
  96. INT_PTR
  97. WINAPI
  98. EditResourceDlgProc(
  99. HWND hDlg,
  100. UINT wMsg,
  101. WPARAM wParam,
  102. LPARAM lParam
  103. )
  104. {
  105. TCHAR szBuffer[MAX_PATH];
  106. //
  107. // ISSUE-2000/02/03-JamieHun Remove statics from EditResourceDlgProc
  108. //
  109. static ULONG64 ulEditedValue, ulEditedLen, ulEditedEnd;
  110. switch (wMsg) {
  111. case WM_INITDIALOG: {
  112. PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)lParam;
  113. ULONG ulSize = 0;
  114. SetWindowLongPtr(hDlg, DWLP_USER, lParam); // save for later msgs
  115. lprei->dwFlags &= ~REI_FLAGS_CONFLICT; // no conflict yet
  116. lprei->dwFlags |= REI_FLAG_NONUSEREDIT; // no manual edits yet
  117. ulEditedValue = lprei->ulCurrentVal;
  118. ulEditedLen = lprei->ulCurrentLen;
  119. ulEditedEnd = lprei->ulCurrentEnd;
  120. InitEditResDlg(hDlg, lprei, ulEditedValue, ulEditedLen);
  121. SetFocus(GetDlgItem(hDlg, IDC_EDITRES_VALUE));
  122. break; // return default (FALSE) to indicate we've set focus
  123. }
  124. case WM_NOTIFY: {
  125. PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  126. LPNM_UPDOWN lpnm = (LPNM_UPDOWN)lParam;
  127. switch (lpnm->hdr.code) {
  128. case UDN_DELTAPOS:
  129. if (lpnm->hdr.idFrom == IDC_EDITRES_SPIN) {
  130. if (lpnm->iDelta > 0) {
  131. GetOtherValues(lprei->pData, lprei->ridResType, +1,
  132. &ulEditedValue,
  133. &ulEditedLen,
  134. &ulEditedEnd);
  135. } else {
  136. GetOtherValues(lprei->pData, lprei->ridResType, -1,
  137. &ulEditedValue,
  138. &ulEditedLen,
  139. &ulEditedEnd);
  140. }
  141. pFormatResString(NULL,szBuffer, ulEditedValue, ulEditedLen,
  142. lprei->ridResType);
  143. lprei->dwFlags |= REI_FLAG_NONUSEREDIT;
  144. SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
  145. UpdateEditResConflictList(hDlg, lprei,
  146. ulEditedValue,
  147. ulEditedLen,
  148. lprei->ulCurrentFlags);
  149. }
  150. break;
  151. }
  152. break;
  153. }
  154. case WM_COMMAND: {
  155. switch(LOWORD(wParam)) {
  156. case IDOK: {
  157. PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO) GetWindowLongPtr(hDlg, DWLP_USER);
  158. ULONG ulIndex;
  159. //
  160. // Validate the values (could have been manually edited)
  161. //
  162. if (bValidateResourceVal(hDlg, &ulEditedValue, &ulEditedLen,
  163. &ulEditedEnd, &ulIndex, lprei)) {
  164. //
  165. // Warn if there is a conflict. If use accepts conflict
  166. // end the dialog, otherwise update the
  167. // edit control since it may have been changed by the
  168. // Validate call.
  169. //
  170. //No HMACHINE
  171. if(bConflictWarn(hDlg, ulEditedValue, ulEditedLen,
  172. ulEditedEnd, lprei)) {
  173. lprei->ulCurrentVal = ulEditedValue;
  174. lprei->ulCurrentLen = ulEditedLen;
  175. lprei->ulCurrentEnd = ulEditedEnd;
  176. lprei->ulRangeCount = ulIndex;
  177. EndDialog(hDlg, IDOK);
  178. if (lprei->pData) {
  179. MyFree(lprei->pData);
  180. }
  181. } else {
  182. //
  183. // Format and display the data
  184. //
  185. pFormatResString(NULL,szBuffer, ulEditedValue, ulEditedLen, lprei->ridResType);
  186. SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
  187. //
  188. // Update the Conflict List.
  189. //
  190. UpdateEditResConflictList(hDlg, lprei, ulEditedValue, ulEditedLen, lprei->ulCurrentFlags);
  191. }
  192. }
  193. return TRUE;
  194. }
  195. case IDCANCEL: {
  196. PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  197. if (lprei->pData) {
  198. MyFree(lprei->pData);
  199. }
  200. EndDialog(hDlg, FALSE);
  201. return TRUE;
  202. }
  203. case IDC_EDITRES_VALUE: {
  204. switch (HIWORD(wParam)) {
  205. case EN_CHANGE: {
  206. PRESOURCEEDITINFO lprei = (PRESOURCEEDITINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  207. // If Non user edit, then clear the flag, else
  208. // clear the conflict list, since we are unsure
  209. // of what the user has entered at this time
  210. if (lprei->dwFlags & REI_FLAG_NONUSEREDIT) {
  211. lprei->dwFlags &= ~REI_FLAG_NONUSEREDIT;
  212. } else {
  213. ClearEditResConflictList(hDlg, CEF_UNKNOWN);
  214. }
  215. break;
  216. }
  217. // If the edit control looses focus, then we should
  218. // validte the contents
  219. case EN_KILLFOCUS: {
  220. }
  221. break;
  222. }
  223. break;
  224. }
  225. }
  226. break;
  227. }
  228. case WM_HELP: // F1
  229. WinHelp(((LPHELPINFO)lParam)->hItemHandle, DEVRES_HELP, HELP_WM_HELP, (ULONG_PTR)EditResHelpIDs);
  230. break;
  231. case WM_CONTEXTMENU: // right mouse click
  232. WinHelp((HWND)wParam, DEVRES_HELP, HELP_CONTEXTMENU, (ULONG_PTR)EditResHelpIDs);
  233. break;
  234. }
  235. return FALSE;
  236. } // EditResourceDlgProc
  237. void
  238. InitEditResDlg(
  239. HWND hDlg,
  240. PRESOURCEEDITINFO lprei,
  241. ULONG64 ulVal,
  242. ULONG64 ulLen
  243. )
  244. {
  245. TCHAR szBuffer[MAX_PATH], szInstr[MAX_PATH], szTemp[MAX_PATH],
  246. szResType[MAX_PATH], szResTypeLC[MAX_PATH];
  247. ULONG ulSize = 0;
  248. //
  249. // Set the initial Value
  250. //
  251. pFormatResString(NULL,szBuffer, ulVal, ulLen, lprei->ridResType);
  252. SetDlgItemText(hDlg, IDC_EDITRES_VALUE, szBuffer);
  253. //
  254. // Setup the Spinner
  255. //
  256. SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETRANGE, 0, MAKELONG(MAX_SPINRANGE, 0));
  257. SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETPOS, 0, MAKELONG(0,0));
  258. SendDlgItemMessage(hDlg, IDC_EDITRES_SPIN, UDM_SETACCEL, 5, (LPARAM)(LPUDACCEL)udAccel);
  259. //
  260. // Limit the Edit Text.
  261. //
  262. switch (lprei->ridResType) {
  263. case ResType_Mem:
  264. LoadString(MyDllModuleHandle, IDS_MEMORY_FULL, szResType, MAX_PATH);
  265. LoadString(MyDllModuleHandle, IDS_MEMORY_FULL_LC, szResTypeLC, MAX_PATH);
  266. LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR1, szInstr, MAX_PATH);
  267. LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR2, szTemp, MAX_PATH);
  268. lstrcat(szInstr, szTemp);
  269. //
  270. // Limit the Input field to Start Val (8) + End Val(8) + seperator (4)
  271. //
  272. SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 20, 0l);
  273. break;
  274. case ResType_IO:
  275. LoadString(MyDllModuleHandle, IDS_IO_FULL, szResType, MAX_PATH);
  276. LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR1, szInstr, MAX_PATH);
  277. LoadString(MyDllModuleHandle, IDS_EDITRES_RANGEINSTR2, szTemp, MAX_PATH);
  278. LoadString(MyDllModuleHandle, IDS_IO_FULL_LC, szResTypeLC, MAX_PATH);
  279. lstrcat(szInstr, szTemp);
  280. //
  281. // Limit the Input field to Start Val (4) + End Val(4) + seperator (4)
  282. //
  283. SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 12, 0l);
  284. break;
  285. case ResType_DMA:
  286. LoadString(MyDllModuleHandle, IDS_DMA_FULL, szResType, MAX_PATH);
  287. LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR1, szInstr, MAX_PATH);
  288. LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR2, szTemp, MAX_PATH);
  289. LoadString(MyDllModuleHandle, IDS_DMA_FULL_LC, szResTypeLC, MAX_PATH);
  290. lstrcat(szInstr, szTemp);
  291. //
  292. // Limit the Input field to Val (2)
  293. //
  294. SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 2, 0l);
  295. break;
  296. case ResType_IRQ:
  297. LoadString(MyDllModuleHandle, IDS_IRQ_FULL, szResType, MAX_PATH);
  298. LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR1, szInstr, MAX_PATH);
  299. LoadString(MyDllModuleHandle, IDS_EDITRES_SINGLEINSTR2, szTemp, MAX_PATH);
  300. LoadString(MyDllModuleHandle, IDS_IRQ_FULL_LC, szResTypeLC, MAX_PATH);
  301. lstrcat(szInstr, szTemp);
  302. //
  303. // Limit the Input field to Val (2)
  304. //
  305. SendDlgItemMessage(hDlg, IDC_EDITRES_VALUE, EM_LIMITTEXT, 2, 0l);
  306. break;
  307. }
  308. //
  309. // Set the Instruction Text
  310. //
  311. wsprintf(szBuffer, szInstr, szResTypeLC);
  312. SetDlgItemText(hDlg, IDC_EDITRES_INSTRUCTIONS, szBuffer);
  313. //
  314. // Set the Dialog Title
  315. //
  316. LoadString(MyDllModuleHandle, IDS_EDITRES_TITLE, szTemp, MAX_PATH);
  317. wsprintf(szBuffer, szTemp, szResType);
  318. SetWindowText(hDlg, szBuffer);
  319. //
  320. // If this is a MF parent device, then show which children own this resource.
  321. //
  322. UpdateMFChildList(hDlg, lprei);
  323. //
  324. // Read the res des data and store a ptr to it so we
  325. // don't have to refetch it multiple times.
  326. //
  327. lprei->pData = NULL;
  328. if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, lprei->ResDes, CM_RESDES_WIDTH_64,lprei->hMachine) == CR_SUCCESS) {
  329. lprei->pData = MyMalloc(ulSize);
  330. if (lprei->pData != NULL) {
  331. CM_Get_Res_Des_Data_Ex(lprei->ResDes, lprei->pData, ulSize, CM_RESDES_WIDTH_64,lprei->hMachine);
  332. }
  333. }
  334. //
  335. // Update the Conflict List.
  336. //
  337. UpdateEditResConflictList(hDlg, lprei, ulVal, ulLen, lprei->ulCurrentFlags);
  338. } // InitEditResDlg
  339. BOOL
  340. LocateClosestValue(
  341. IN LPBYTE pData,
  342. IN RESOURCEID ResType,
  343. IN ULONG64 TestValue,
  344. IN ULONG64 TestLen,
  345. IN INT Mode,
  346. OUT PULONG64 OutValue, OPTIONAL
  347. OUT PULONG64 OutLen, OPTIONAL
  348. OUT PULONG OutIndex OPTIONAL
  349. )
  350. /*++
  351. Routine Description:
  352. This routine finds the nearest valid address/range
  353. to that the user specified
  354. if Mode == 0, the nearest value is used
  355. if Mode > 0, the nearest higher value is used
  356. if Mode < 0, the nearest lower value is used
  357. Arguments:
  358. pData - information about the resources being selected
  359. ResType - type of resource being selected
  360. CurrentValue - value entered by user
  361. CurrentLen - length based on range entered by user
  362. Mode - search mode, -1 = previous, 1 = next, 0 = nearest
  363. OutValue - nearest valid value
  364. OutLen - length associated with nearest valid value
  365. Return Value:
  366. If exact match found, return TRUE
  367. otherwise FALSE
  368. --*/
  369. {
  370. PGENERIC_RESOURCE pGenRes = (PGENERIC_RESOURCE)pData;
  371. ULONG64 Start, Len, End, Align;
  372. ULONG Flags;
  373. ULONG64 BestVal;
  374. ULONG64 BestValL;
  375. ULONG64 BestValU;
  376. ULONG64 FoundVal = 0;
  377. ULONG64 FoundLen = 0;
  378. ULONG FoundIndex = 0;
  379. ULONG Index;
  380. BOOL FindNearest = TRUE; // indicates we should find nearest
  381. //
  382. // precedence (1) Value&Len match exactly
  383. // precedence (2) closest valid value
  384. //
  385. //
  386. // cover a catch-all case - start of the very first resource range
  387. //
  388. pGetRangeValues(pData, ResType, 0, &Start, &Len, &End, &Align, &Flags);
  389. //
  390. // we have at least 1 found value
  391. //
  392. FoundVal = Start;
  393. FoundLen = Len;
  394. //
  395. // Find a nearby valid range to the one supplied
  396. //
  397. //
  398. // check each range at a time
  399. // sometimes ranges may not be given in ascending order
  400. // eg, first range is a preferred, second range is alternative
  401. //
  402. for (Index = 0; Index < pGenRes->GENERIC_Header.GENERIC_Count; Index++) {
  403. //
  404. // get limits for this range
  405. //
  406. pGetRangeValues(pData, ResType, Index, &Start, &Len, &End, &Align, &Flags);
  407. //
  408. // first, try to find a value that is GOOD, that is <= TestValue
  409. //
  410. BestValL = TestValue;
  411. if (pAlignValues(&BestValL, Start, Len, End, Align, -1) == FALSE) {
  412. //
  413. // if it failed, use the lowest value in this range (ie Start)
  414. //
  415. BestValL = Start;
  416. }
  417. //
  418. // find an upper value that is aligned
  419. //
  420. if (BestValL == TestValue) {
  421. //
  422. // if match was exact, skip test
  423. //
  424. BestValU = TestValue;
  425. } else {
  426. //
  427. // search for upper limit
  428. //
  429. BestValU = TestValue;
  430. if (pAlignValues(&BestValU, Start, Len, End, Align, 1) == FALSE) {
  431. //
  432. // couldn't use it - find highest valid value
  433. //
  434. BestValU = End-Len+1;
  435. if (pAlignValues(&BestValU, Start, Len, End, Align, -1) == FALSE) {
  436. //
  437. // still no go
  438. //
  439. BestValU = BestValL;
  440. }
  441. }
  442. }
  443. //
  444. // now we have found our boundaries
  445. // may need to modify, depending on preferences
  446. //
  447. if (Mode<0) {
  448. //
  449. // if range is < TestVal, use highest, else lowest
  450. //
  451. if (BestValU <= TestValue) {
  452. BestVal = BestValU;
  453. } else {
  454. BestVal = BestValL;
  455. }
  456. } else if (Mode>0) {
  457. //
  458. // if range is > TestVal, use lowest, else highest
  459. //
  460. if (BestValL >= TestValue) {
  461. BestVal = BestValL;
  462. } else {
  463. BestVal = BestValU;
  464. }
  465. } else {
  466. //
  467. // use closest of the two values
  468. //
  469. if (Nearness(BestValL,TestValue)<= Nearness(BestValU,TestValue)) {
  470. BestVal = BestValL;
  471. } else {
  472. BestVal = BestValU;
  473. }
  474. }
  475. //
  476. // we know that BestVal is valid within the range
  477. // and is the choice for this range
  478. //
  479. //
  480. // handle the match cases
  481. //
  482. if (TestValue == BestVal && TestLen == Len) {
  483. //
  484. // exact match
  485. //
  486. if (OutValue != NULL) {
  487. *OutValue = BestVal;
  488. }
  489. if (OutLen != NULL) {
  490. *OutLen = Len;
  491. }
  492. if (OutIndex != NULL) {
  493. *OutIndex = Index;
  494. }
  495. return TRUE;
  496. }
  497. if (FindNearest && Mode != 0) {
  498. //
  499. // we are currently in "FindNearest" mode which means
  500. // we haven't found one in the direction we wanted
  501. //
  502. if (Mode < 0 && BestVal <= TestValue) {
  503. //
  504. // not looking for nearness now we've found one lower
  505. //
  506. FoundVal = BestVal;
  507. FoundLen = Len;
  508. FoundIndex = Index;
  509. FindNearest = FALSE;
  510. } else if (Mode > 0 && BestVal >= TestValue) {
  511. //
  512. // not looking for nearness now we've found one higher
  513. //
  514. FoundVal = BestVal;
  515. FoundLen = Len;
  516. FoundIndex = Index;
  517. FindNearest = FALSE;
  518. }
  519. } else if (FindNearest ||
  520. (Mode < 0 && BestVal <= TestValue) ||
  521. (Mode > 0 && BestVal >= TestValue)) {
  522. if (Nearness(BestVal,TestValue) < Nearness(FoundVal,TestValue)) {
  523. //
  524. // this address is nearer
  525. //
  526. FoundVal = BestVal;
  527. FoundLen = Len;
  528. FoundIndex = Index;
  529. } else if (Nearness(BestVal,TestValue) == Nearness(FoundVal,TestValue)) {
  530. //
  531. // this address guess is as near as nearest guess, pick the better length
  532. //
  533. // I can't see any place that this should happen
  534. // but theoretically it could happen
  535. // so this is a safety net more than anything else
  536. //
  537. if (Nearness(Len,TestLen) < Nearness(FoundLen,TestLen)) {
  538. //
  539. // this length is nearer
  540. //
  541. FoundVal = BestVal;
  542. FoundLen = Len;
  543. FoundIndex = Index;
  544. } else if (Nearness(Len,TestLen) == Nearness(FoundLen,TestLen)) {
  545. //
  546. // pick the bigger (safer)
  547. //
  548. if (Len > FoundLen) {
  549. //
  550. // this length is bigger
  551. //
  552. FoundVal = BestVal;
  553. FoundLen = Len;
  554. FoundIndex = Index;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. //
  561. // if we get here, we didn't find an exact match
  562. //
  563. // Use our best guess
  564. if (OutValue != NULL) {
  565. *OutValue = FoundVal;
  566. }
  567. if (OutLen != NULL) {
  568. *OutLen = FoundLen;
  569. }
  570. if (OutIndex != NULL) {
  571. *OutIndex = FoundIndex;
  572. }
  573. return FALSE;
  574. }
  575. void
  576. GetOtherValues(
  577. IN LPBYTE pData,
  578. IN RESOURCEID ResType,
  579. IN LONG Increment,
  580. IN OUT PULONG64 pulValue,
  581. IN OUT PULONG64 pulLen,
  582. IN OUT PULONG64 pulEnd
  583. )
  584. /*++
  585. Routine Description:
  586. Finds the next valid value, wrapping around to beginning/end value when end of range
  587. Arguments:
  588. pData - resource data
  589. ResType - resource type
  590. Increment - 1 or -1
  591. pulValue - pointer to old/new start that is changed
  592. pulLen - pointer to old/new length
  593. pulEnd - pointer to old/new end
  594. Return Value:
  595. none
  596. --*/
  597. {
  598. ULONG64 TestValue = *pulValue;
  599. ULONG64 TestLen = *pulLen;
  600. ULONG64 RetValue = 0;
  601. ULONG64 RetLen = 0;
  602. MYASSERT((Increment == 1) || (Increment == -1));
  603. if (Increment == 1) {
  604. TestValue++;
  605. LocateClosestValue(pData,ResType,TestValue,TestLen, 1 ,&RetValue,&RetLen,NULL);
  606. if (RetValue < TestValue) {
  607. //
  608. // wrap around, find lowest possible valid address
  609. //
  610. LocateClosestValue(pData,ResType,0,TestLen, 0 ,&RetValue,&RetLen,NULL);
  611. }
  612. } else {
  613. TestValue--;
  614. LocateClosestValue(pData,ResType,TestValue,TestLen, -1 ,&RetValue,&RetLen,NULL);
  615. if (RetValue > TestValue) {
  616. //
  617. // wrap around, find highest possible valid address
  618. //
  619. LocateClosestValue(pData,ResType,(ULONG64)(-1),TestLen, 0 ,&RetValue,&RetLen,NULL);
  620. }
  621. }
  622. *pulValue = RetValue;
  623. *pulLen = RetLen;
  624. *pulEnd = RetValue + RetLen - 1;
  625. return;
  626. } // GetOtherValues
  627. void
  628. UpdateEditResConflictList(
  629. HWND hDlg,
  630. PRESOURCEEDITINFO lprei,
  631. ULONG64 ulVal,
  632. ULONG64 ulLen,
  633. ULONG ulFlags
  634. )
  635. /*++
  636. Routine Description:
  637. Updates all the conflict information for the selected resource
  638. Should give more details than UpdateDevResConflictList
  639. Arguments:
  640. hDlg - handle of this dialog to display into
  641. lprei - resource edit info
  642. ulVal - value to try
  643. ulLen - length to test
  644. ulFlags - flags part of resdes
  645. Return Value:
  646. none
  647. --*/
  648. {
  649. CONFIGRET Status = CR_SUCCESS;
  650. HWND hwndConflictList = GetDlgItem(hDlg, IDC_EDITRES_CONFLICTLIST);
  651. ULONG ConflictCount = 0;
  652. ULONG ConflictIndex = 0;
  653. ULONG ulSize = 0;
  654. LPBYTE pResourceData = NULL;
  655. CONFLICT_LIST ConflictList = 0;
  656. PDEVICE_INFO_SET pDeviceInfoSet;
  657. CONFLICT_DETAILS ConflictDetails;
  658. TCHAR szBuffer[MAX_PATH];
  659. TCHAR szItemFormat[MAX_PATH];
  660. BOOL ReservedResource = FALSE;
  661. BOOL BadResource = FALSE;
  662. //
  663. // need resource-data for determining conflict
  664. //
  665. if (MakeResourceData(&pResourceData, &ulSize,
  666. lprei->ridResType,
  667. ulVal,
  668. ulLen,
  669. ulFlags)) {
  670. Status = CM_Query_Resource_Conflict_List(&ConflictList,
  671. lprei->lpdi->DevInst,
  672. lprei->ridResType,
  673. pResourceData,
  674. ulSize,
  675. DEVRES_WIDTH_FLAGS,
  676. lprei->hMachine);
  677. if (Status != CR_SUCCESS) {
  678. //
  679. // error occurred
  680. //
  681. ConflictList = 0;
  682. ConflictCount = 0;
  683. BadResource = TRUE;
  684. } else {
  685. //
  686. // find out how many things conflicted
  687. //
  688. Status = CM_Get_Resource_Conflict_Count(ConflictList,&ConflictCount);
  689. if (Status != CR_SUCCESS) {
  690. //
  691. // error shouldn't occur
  692. //
  693. MYASSERT(Status == CR_SUCCESS);
  694. ConflictCount = 0;
  695. BadResource = TRUE;
  696. }
  697. }
  698. } else {
  699. MYASSERT(FALSE);
  700. //
  701. // should not fail
  702. //
  703. ConflictList = 0;
  704. ConflictCount = 0;
  705. BadResource = TRUE;
  706. }
  707. if (BadResource) {
  708. //
  709. // The resource conflict information is indeterminate
  710. //
  711. SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
  712. lprei->dwFlags &= ~REI_FLAGS_CONFLICT;
  713. LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICT, szBuffer, MAX_PATH);
  714. SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
  715. LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICTINGDEVS, szBuffer, MAX_PATH);
  716. SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
  717. } else if (ConflictCount || ReservedResource) {
  718. TreatAsReserved:
  719. SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
  720. lprei->dwFlags |= REI_FLAGS_CONFLICT;
  721. if(ReservedResource == FALSE) {
  722. //
  723. // The resource conflicts with another unknown device.
  724. //
  725. LoadString(MyDllModuleHandle, IDS_EDITRES_DEVCONFLICT, szBuffer, MAX_PATH);
  726. SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
  727. for(ConflictIndex = 0; ConflictIndex < ConflictCount ; ConflictIndex++) {
  728. //
  729. // obtain details for this conflict
  730. //
  731. ZeroMemory(&ConflictDetails,sizeof(ConflictDetails));
  732. ConflictDetails.CD_ulSize = sizeof(ConflictDetails);
  733. ConflictDetails.CD_ulMask = CM_CDMASK_DEVINST | CM_CDMASK_DESCRIPTION | CM_CDMASK_FLAGS;
  734. Status = CM_Get_Resource_Conflict_Details(ConflictList,ConflictIndex,&ConflictDetails);
  735. if (Status == CR_SUCCESS) {
  736. if ((ConflictDetails.CD_ulFlags & CM_CDFLAGS_RESERVED) != 0) {
  737. //
  738. // treat as reserved - backtrack
  739. //
  740. ReservedResource = TRUE;
  741. goto TreatAsReserved;
  742. }
  743. //
  744. // convert CD_dnDevInst to string information
  745. //
  746. lstrcpy(szBuffer,ConflictDetails.CD_szDescription);
  747. if (szBuffer[0] == 0) {
  748. ReservedResource = TRUE;
  749. goto TreatAsReserved;
  750. }
  751. } else {
  752. MYASSERT(Status == CR_SUCCESS);
  753. ReservedResource = TRUE;
  754. goto TreatAsReserved;
  755. }
  756. SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
  757. }
  758. } else {
  759. LoadString(MyDllModuleHandle, IDS_EDITRES_RESERVED, szBuffer, MAX_PATH);
  760. SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
  761. LoadString(MyDllModuleHandle, IDS_EDITRES_RESERVEDRANGE, szBuffer, MAX_PATH);
  762. SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
  763. }
  764. } else {
  765. //
  766. // The resource does not conflict with any other devices.
  767. //
  768. SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
  769. lprei->dwFlags &= ~REI_FLAGS_CONFLICT;
  770. LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICT, szBuffer, MAX_PATH);
  771. SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
  772. LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICTINGDEVS, szBuffer, MAX_PATH);
  773. SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
  774. }
  775. if (ConflictList) {
  776. CM_Free_Resource_Conflict_Handle(ConflictList);
  777. }
  778. if (pResourceData != NULL) {
  779. MyFree(pResourceData);
  780. }
  781. return;
  782. }
  783. BOOL
  784. bValidateResourceVal(
  785. HWND hDlg,
  786. PULONG64 pulVal,
  787. PULONG64 pulLen,
  788. PULONG64 pulEnd,
  789. PULONG pulIndex,
  790. PRESOURCEEDITINFO lprei
  791. )
  792. {
  793. TCHAR szSetting[MAX_VAL_LEN], szNewSetting[MAX_VAL_LEN];
  794. TCHAR szMessage[MAX_MSG_LEN], szTemp[MAX_MSG_LEN], szTemp1[MAX_MSG_LEN];
  795. TCHAR szTitle[MAX_PATH];
  796. ULONG64 ulVal, ulEnd, ulLen;
  797. ULONG64 ulValidVal, ulValidLen;
  798. ULONG ulIndex;
  799. BOOL bRet;
  800. BOOL exact = TRUE;
  801. GetDlgItemText(hDlg, IDC_EDITRES_VALUE, szSetting, MAX_VAL_LEN);
  802. if (pUnFormatResString(szSetting, &ulVal, &ulEnd, lprei->ridResType)) {
  803. ulLen = ulEnd - ulVal + 1;
  804. //
  805. // Validate the Current Settings
  806. //
  807. // If an exact match doesn't exist
  808. // use a close match
  809. // close is based on start address
  810. //
  811. if (LocateClosestValue(lprei->pData, lprei->ridResType,
  812. ulVal, ulLen,0,
  813. &ulValidVal, &ulValidLen,&ulIndex) == FALSE) {
  814. //
  815. // An alternate setting was found
  816. // we think this might be what the user wanted
  817. //
  818. LoadString(MyDllModuleHandle, IDS_EDITRES_ENTRYERROR, szTitle, MAX_PATH);
  819. LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR1, szTemp, MAX_MSG_LEN);
  820. LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR2, szTemp1, MAX_MSG_LEN);
  821. lstrcat(szTemp, szTemp1);
  822. LoadString(MyDllModuleHandle, IDS_EDITRES_VALIDATEERROR3, szTemp1, MAX_MSG_LEN);
  823. lstrcat(szTemp, szTemp1);
  824. pFormatResString(NULL, szSetting, ulVal, ulLen, lprei->ridResType);
  825. pFormatResString(NULL,szNewSetting, ulValidVal, ulValidLen, lprei->ridResType);
  826. wsprintf(szMessage, szTemp, szSetting, szNewSetting);
  827. if (MessageBox(hDlg, szMessage, szTitle,
  828. MB_YESNO | MB_TASKMODAL | MB_ICONEXCLAMATION) == IDYES) {
  829. //
  830. // Update the Edited values.
  831. //
  832. *pulVal = ulValidVal;
  833. *pulLen = ulValidLen;
  834. *pulEnd = ulValidVal + ulValidLen - 1;
  835. *pulIndex = ulIndex;
  836. bRet = TRUE;
  837. } else {
  838. bRet = FALSE;
  839. }
  840. } else {
  841. //
  842. // The specified values are valid
  843. //
  844. *pulVal = ulVal;
  845. *pulLen = ulLen;
  846. *pulEnd = ulEnd;
  847. *pulIndex = ulIndex;
  848. bRet = TRUE;
  849. }
  850. } else {
  851. switch (lprei->ridResType) {
  852. case ResType_Mem:
  853. LoadString(MyDllModuleHandle, IDS_ERROR_BADMEMTEXT, szMessage, MAX_MSG_LEN);
  854. break;
  855. case ResType_IO:
  856. LoadString(MyDllModuleHandle, IDS_ERROR_BADIOTEXT, szMessage, MAX_MSG_LEN);
  857. break;
  858. case ResType_DMA:
  859. LoadString(MyDllModuleHandle, IDS_ERROR_BADDMATEXT, szMessage, MAX_MSG_LEN);
  860. break;
  861. case ResType_IRQ:
  862. LoadString(MyDllModuleHandle, IDS_ERROR_BADIRQTEXT, szMessage, MAX_MSG_LEN);
  863. break;
  864. }
  865. LoadString(MyDllModuleHandle, IDS_EDITRES_ENTRYERROR, szTitle, MAX_PATH);
  866. MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONASTERISK);
  867. bRet = FALSE;
  868. }
  869. return bRet;
  870. } // bValidateResoureceVal
  871. BOOL
  872. bConflictWarn(
  873. HWND hDlg,
  874. ULONG64 ulVal,
  875. ULONG64 ulLen,
  876. ULONG64 ulEnd,
  877. PRESOURCEEDITINFO lprei
  878. )
  879. {
  880. BOOL bRet = TRUE;
  881. TCHAR szMessage[MAX_MSG_LEN], szTitle[MAX_PATH];
  882. if (!(lprei->dwFlags & REI_FLAG_NONUSEREDIT)) {
  883. //
  884. // user edits have been made so the conflict flag may not be
  885. // up-to-date, check conflicts now.
  886. //
  887. UpdateEditResConflictList(hDlg, lprei, ulVal, ulLen, lprei->ulCurrentFlags);
  888. }
  889. if (lprei->dwFlags & REI_FLAGS_CONFLICT) {
  890. LoadString(MyDllModuleHandle, IDS_EDITRES_CONFLICTWARNMSG, szMessage, MAX_MSG_LEN);
  891. LoadString(MyDllModuleHandle, IDS_EDITRES_CONFLICTWARNTITLE, szTitle, MAX_PATH);
  892. if (MessageBox(hDlg, szMessage, szTitle,
  893. MB_YESNO | MB_DEFBUTTON2| MB_TASKMODAL | MB_ICONEXCLAMATION) == IDNO) {
  894. bRet = FALSE;
  895. } else {
  896. bRet = TRUE; // User approved conflict
  897. }
  898. }
  899. return bRet;
  900. } // bConflictWarn
  901. void
  902. ClearEditResConflictList(
  903. HWND hDlg,
  904. DWORD dwFlags
  905. )
  906. {
  907. HWND hwndConflictList = GetDlgItem(hDlg, IDC_EDITRES_CONFLICTLIST);
  908. TCHAR szBuffer[MAX_PATH];
  909. //
  910. // Clear the Conflict list to start.
  911. //
  912. SendMessage(hwndConflictList, LB_RESETCONTENT, 0, 0L);
  913. //
  914. // Load and set the info text string
  915. //
  916. if (dwFlags & CEF_UNKNOWN) {
  917. LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICT, szBuffer, MAX_PATH);
  918. } else {
  919. LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICT, szBuffer, MAX_PATH);
  920. }
  921. SetDlgItemText(hDlg, IDC_EDITRES_CONFLICTTEXT, szBuffer);
  922. //
  923. // Load and set the List string
  924. //
  925. if (dwFlags & CEF_UNKNOWN) {
  926. LoadString(MyDllModuleHandle, IDS_EDITRES_UNKNOWNCONFLICTINGDEVS, szBuffer, MAX_PATH);
  927. } else {
  928. LoadString(MyDllModuleHandle, IDS_EDITRES_NOCONFLICTINGDEVS, szBuffer, MAX_PATH);
  929. }
  930. SendMessage(hwndConflictList, LB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuffer);
  931. } // ClearEditResConflictList
  932. void
  933. UpdateMFChildList(
  934. HWND hDlg,
  935. PRESOURCEEDITINFO lprei
  936. )
  937. {
  938. UNREFERENCED_PARAMETER(hDlg);
  939. UNREFERENCED_PARAMETER(lprei);
  940. //
  941. // See if this is a MF parent device. Check for a Child0000 subkey
  942. //
  943. // NOT IMPLEMENTED, SEE WINDOWS 95 SOURCES.
  944. //
  945. } // UpdateMFChildList