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.

4701 lines
143 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. devres.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. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Private Prototypes
  16. //
  17. //
  18. // Global Data
  19. //
  20. static INTERFACE_TYPE ResourcePickerReadOnlyInterfaces[] = {
  21. //
  22. // List of interface-types that we don't want user to edit properties of
  23. //
  24. PCIBus,
  25. //
  26. // End of list
  27. //
  28. InterfaceTypeUndefined
  29. };
  30. static const BOOL ResTypeEditable[ResType_MAX+1] = {
  31. //
  32. // lists resource types that are shown and are editable
  33. FALSE, // ResType_None
  34. TRUE, // ResType_Mem
  35. TRUE, // ResType_IO
  36. TRUE, // ResType_DMA
  37. TRUE, // ResType_IRQ
  38. FALSE, // ResType_DoNotUse
  39. FALSE // ResType_BusNumber
  40. };
  41. #if (ResType_MAX+1) != 7
  42. #error Fix SetupAPI devres.c, ResType_MAX has changed
  43. #endif
  44. //
  45. // HELP ID's
  46. //
  47. static const DWORD DevResHelpIDs[]=
  48. {
  49. IDC_DEVRES_ICON, IDH_NOHELP, // "Low (%d)" (Static)
  50. IDC_DEVRES_DEVDESC, IDH_NOHELP,
  51. IDC_DEVRES_SETTINGSTATE, IDH_DEVMGR_RESOURCES_SETTINGS,
  52. IDC_DEVRES_SETTINGSLIST, IDH_DEVMGR_RESOURCES_SETTINGS,
  53. IDC_DEVRES_LCTEXT, IDH_DEVMGR_RESOURCES_BASEDON,
  54. IDC_DEVRES_LOGCONFIGLIST, IDH_DEVMGR_RESOURCES_BASEDON,
  55. IDC_DEVRES_CHANGE, IDH_DEVMGR_RESOURCES_CHANGE,
  56. IDC_DEVRES_USESYSSETTINGS, IDH_DEVMGR_RESOURCES_AUTO,
  57. IDC_DEVRES_CONFLICTDEVTEXT, IDH_DEVMGR_RESOURCES_CONFLICTS,
  58. IDC_DEVRES_CONFLICTINFOLIST, IDH_DEVMGR_RESOURCES_CONFLICTS,
  59. IDC_DEVRES_MFPARENT, IDH_DEVMGR_RESOURCES_PARENT,
  60. IDC_DEVRES_MFPARENT_DESC, IDH_DEVMGR_RESOURCES_PARENT,
  61. IDC_DEVRES_MAKEFORCED, IDH_DEVMGR_RESOURCES_SETMANUALLY,
  62. 0, 0
  63. };
  64. //
  65. // HACKHACK (jamiehun)
  66. // after we've changed UI from a MakeForced, we post this message to get back control of keyboard
  67. //
  68. #define WM_USER_FOCUS (WM_USER+101)
  69. //
  70. // API to obtain a resource-picker page
  71. //
  72. HPROPSHEETPAGE
  73. GetResourceSelectionPage(
  74. IN HDEVINFO DeviceInfoSet,
  75. IN PSP_DEVINFO_DATA DeviceInfoData
  76. )
  77. {
  78. LPDMPROP_DATA pdmData;
  79. PROPSHEETPAGE PropPage;
  80. //
  81. // private data
  82. // anything we "do" here must be "undone" in pResourcePickerPropPageCallback
  83. //
  84. pdmData = (LPDMPROP_DATA)MyMalloc(sizeof(DMPROP_DATA));
  85. if (pdmData == NULL) {
  86. return NULL;
  87. }
  88. ZeroMemory(pdmData,sizeof(DMPROP_DATA));
  89. pdmData->hDevInfo = DeviceInfoSet;
  90. pdmData->lpdi = DeviceInfoData;
  91. //
  92. // validate expectations
  93. //
  94. MYASSERT(pdmData->hDevInfo != NULL);
  95. MYASSERT(pdmData->lpdi != NULL);
  96. MYASSERT(pdmData->lpdi->DevInst != 0);
  97. ZeroMemory(&PropPage,sizeof(PropPage));
  98. //
  99. // create the Resources Property Page
  100. //
  101. PropPage.dwSize = sizeof(PROPSHEETPAGE);
  102. PropPage.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
  103. PropPage.hInstance = MyDllModuleHandle;
  104. PropPage.pszTemplate = MAKEINTRESOURCE(IDD_DEF_DEVRESOURCE_PROP);
  105. PropPage.pszIcon = NULL;
  106. PropPage.pszTitle = NULL;
  107. PropPage.pfnDlgProc = pResourcePickerDlgProc;
  108. PropPage.lParam = (LPARAM)pdmData;
  109. PropPage.pfnCallback = pResourcePickerPropPageCallback;
  110. #ifdef _UNICODE
  111. PropPage.dwFlags |= PSP_USEFUSIONCONTEXT;
  112. PropPage.hActCtx = NULL;
  113. #endif
  114. return CreatePropertySheetPage(&PropPage);
  115. } // GetResourceSelectionPage
  116. //
  117. // CreatePropertySheetPage - callback function
  118. //
  119. UINT CALLBACK pResourcePickerPropPageCallback(
  120. HWND hwnd,
  121. UINT uMsg,
  122. LPPROPSHEETPAGE ppsp
  123. )
  124. /*++
  125. Routine Description:
  126. Callback to handle cleanup of the property sheet
  127. Arguments:
  128. Standard PropSheetPageProc arguments.
  129. Return Value:
  130. Standard PropSheetPageProc return.
  131. --*/
  132. {
  133. switch (uMsg) {
  134. //case PSPCB_ADDREF:
  135. // break;
  136. case PSPCB_CREATE:
  137. break;
  138. case PSPCB_RELEASE:
  139. //
  140. // release the memory we've previously allocated, outside of the actual dialog
  141. //
  142. if (ppsp->lParam != 0) {
  143. LPDMPROP_DATA pdmData = (LPDMPROP_DATA)(ppsp->lParam);
  144. MyFree(pdmData);
  145. }
  146. break;
  147. }
  148. return TRUE;
  149. }
  150. //
  151. // Main dialog proceedure
  152. //
  153. INT_PTR
  154. CALLBACK
  155. pResourcePickerDlgProc(
  156. HWND hDlg,
  157. UINT message,
  158. WPARAM wParam,
  159. LPARAM lParam
  160. )
  161. /*++
  162. Routine Description:
  163. This routine provides the dialog box procedure for the main resource
  164. picker property page. MEMPHIS COMPATIBLE.
  165. Arguments:
  166. Standard dialog box procedure arguments.
  167. Return Value:
  168. Standard dialog box procedure return.
  169. --*/
  170. {
  171. LPDMPROP_DATA lpdmpd = NULL;
  172. if (message == WM_INITDIALOG) {
  173. lpdmpd = (LPDMPROP_DATA)((LPPROPSHEETPAGE)lParam)->lParam;
  174. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)lpdmpd);
  175. } else {
  176. lpdmpd = (LPDMPROP_DATA)GetWindowLongPtr(hDlg, DWLP_USER);
  177. }
  178. switch (message) {
  179. //
  180. // initialize
  181. //
  182. case WM_INITDIALOG: {
  183. HICON hIcon = NULL;
  184. int iIcon = 0, iIndex = 0;
  185. ULONG ulSize;
  186. PDEVICE_INFO_SET pDeviceInfoSet;
  187. HMACHINE hMachine;
  188. lpdmpd->himlResourceImages = NULL;
  189. lpdmpd->CurrentLC = 0;
  190. lpdmpd->CurrentLCType = 0;
  191. lpdmpd->MatchingLC = 0;
  192. lpdmpd->MatchingLCType = 0;
  193. lpdmpd->SelectedLC = 0;
  194. lpdmpd->SelectedLCType = 0;
  195. lpdmpd->hDlg = hDlg;
  196. lpdmpd->dwFlags = 0;
  197. hMachine = pGetMachine(lpdmpd);
  198. lpdmpd->dwFlags |= DMPROP_FLAG_CHANGESSAVED; // Nothing to save yet
  199. //
  200. // NOTE: On Windows95, since lc info is in memory, they first
  201. // call CM_Setup_DevNode with CM_SETUP_WRITE_LOG_CONFS flag so
  202. // that in-memory lc data is flushed to the registry at this
  203. // point.
  204. //
  205. //
  206. // Init the Resource's image list.
  207. //
  208. lpdmpd->himlResourceImages = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
  209. GetSystemMetrics(SM_CYSMICON),
  210. ILC_MASK, // | ILC_SHARED,
  211. 1,
  212. 1);
  213. //
  214. // add icons to image list
  215. //
  216. for (iIcon = IDI_RESOURCEFIRST;iIcon < IDI_RESOURCELAST;++iIcon) {
  217. //
  218. // resource icon
  219. //
  220. hIcon = LoadIcon(MyDllModuleHandle, MAKEINTRESOURCE(iIcon));
  221. iIndex = ImageList_AddIcon(lpdmpd->himlResourceImages, hIcon);
  222. }
  223. for (iIcon = IDI_RESOURCEOVERLAYFIRST;iIcon <= IDI_RESOURCEOVERLAYLAST;++iIcon) {
  224. //
  225. // overlay icon
  226. //
  227. hIcon = LoadIcon(MyDllModuleHandle, MAKEINTRESOURCE(iIcon));
  228. iIndex = ImageList_AddIcon(lpdmpd->himlResourceImages, hIcon);
  229. //
  230. // Tag this icon as an overlay icon (the first index is an
  231. // index into the image list (specifies the icon), the
  232. // second index is just an index to assign to each mask
  233. // (starting with 1).
  234. //
  235. ImageList_SetOverlayImage(lpdmpd->himlResourceImages,
  236. iIndex,
  237. iIcon-IDI_RESOURCEOVERLAYFIRST+1);
  238. }
  239. if(pInitDevResourceDlg(lpdmpd)) {
  240. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED; // need to save (prob because there was no config)
  241. }
  242. if (!(lpdmpd->dwFlags & DMPROP_FLAG_NO_RESOURCES)) {
  243. pShowConflicts(lpdmpd);
  244. }
  245. if (GuiSetupInProgress) {
  246. //
  247. // occasionally legacy devices cause resource-picker popup during setup
  248. // we do this here instead of create prop sheet, since I don't trust
  249. // people to cleanup on fail. At least here is less risky
  250. // clean this up in WM_DESTROY
  251. //
  252. lpdmpd->hDialogEvent = CreateEvent(NULL,TRUE,FALSE,SETUP_HAS_OPEN_DIALOG_EVENT);
  253. if (lpdmpd->hDialogEvent) {
  254. SetEvent(lpdmpd->hDialogEvent);
  255. }
  256. } else {
  257. lpdmpd->hDialogEvent = NULL;
  258. }
  259. break;
  260. }
  261. //
  262. // cleanup
  263. //
  264. case WM_DESTROY: {
  265. HICON hIcon;
  266. LOG_CONF LogConf;
  267. LONG nItems, n;
  268. HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  269. int Count, i;
  270. //
  271. // Clean up the ICON resource usage
  272. //
  273. if ((hIcon = (HICON)LOWORD(SendDlgItemMessage(hDlg,
  274. IDC_DEVRES_ICON, STM_GETICON, 0, 0L)))) {
  275. DestroyIcon(hIcon);
  276. }
  277. //
  278. // free the LC handles that were saved in the combobox data
  279. //
  280. nItems = (LONG)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
  281. CB_GETCOUNT, 0, 0L);
  282. for (n = 0; n < nItems ; n++) {
  283. LogConf = (LOG_CONF)SendDlgItemMessage(hDlg,
  284. IDC_DEVRES_LOGCONFIGLIST,
  285. CB_GETITEMDATA, n, 0L);
  286. CM_Free_Log_Conf_Handle(LogConf);
  287. }
  288. if (lpdmpd->CurrentLC != 0) {
  289. CM_Free_Log_Conf_Handle(lpdmpd->CurrentLC);
  290. }
  291. ListView_DeleteAllItems(hList); // this will destroy all data
  292. if (lpdmpd->himlResourceImages) {
  293. ImageList_Destroy(lpdmpd->himlResourceImages);
  294. }
  295. if (lpdmpd->hDialogEvent) {
  296. //
  297. // we were holding up setup, now let setup proceed
  298. //
  299. ResetEvent(lpdmpd->hDialogEvent);
  300. CloseHandle(lpdmpd->hDialogEvent);
  301. lpdmpd->hDialogEvent = NULL;
  302. }
  303. // MyFree(lpdmpd); - do this in pResourcePickerPropPageCallback instead
  304. break;
  305. }
  306. case WM_COMMAND:
  307. //
  308. // old-style controls
  309. //
  310. switch(LOWORD(wParam)) {
  311. case IDC_DEVRES_USESYSSETTINGS: {
  312. //
  313. // consider resource settings to have changed
  314. //
  315. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
  316. PropSheet_Changed(GetParent(hDlg), hDlg);
  317. if (IsDlgButtonChecked(hDlg, (int)wParam)) {
  318. //
  319. // Revert back to allocated display, if any
  320. //
  321. lpdmpd->dwFlags |= DMPROP_FLAG_USESYSSETTINGS;
  322. pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
  323. } else {
  324. //
  325. // Allow editing
  326. //
  327. lpdmpd->dwFlags &= ~DMPROP_FLAG_USESYSSETTINGS;
  328. }
  329. pShowUpdateEdit(lpdmpd); // update controls
  330. break;
  331. }
  332. case IDC_DEVRES_LOGCONFIGLIST: {
  333. //
  334. // drop-down list action
  335. //
  336. switch (HIWORD(wParam)) {
  337. case CBN_SELENDOK: {
  338. ULONG ulIndex = 0;
  339. int iItem;
  340. LOG_CONF SelLC;
  341. HWND hwndLC = GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST);
  342. //
  343. // If there is not a Log Config selected, then bail
  344. //
  345. iItem = (int)SendMessage(hwndLC, CB_GETCURSEL, 0, 0);
  346. if(iItem != CB_ERR) {
  347. SelLC = (LOG_CONF)SendMessage(hwndLC,CB_GETITEMDATA, (WPARAM)iItem,(LPARAM)0);
  348. } else {
  349. SelLC = (LOG_CONF)0;
  350. }
  351. if(SelLC != lpdmpd->SelectedLC) {
  352. pSelectLogConf(lpdmpd,SelLC,lpdmpd->ConfigListLCType,FALSE);
  353. }
  354. //
  355. // I prob don't need this here, but I'm playing safe!
  356. //
  357. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
  358. break;
  359. }
  360. }
  361. break;
  362. }
  363. case IDC_DEVRES_CHANGE: {
  364. //
  365. // change selected setting
  366. //
  367. pChangeCurrentResSetting(lpdmpd);
  368. break;
  369. }
  370. case IDC_DEVRES_MAKEFORCED: {
  371. //
  372. // possibly allow editing (after we've shown message)
  373. // when we get here, always show a configuration
  374. //
  375. if(lpdmpd->dwFlags & DMPROP_FLAG_FORCEDONLY) {
  376. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED; // need to save
  377. }
  378. pShowViewAllEdit(lpdmpd);
  379. //
  380. // select in the first available config to edit
  381. //
  382. pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
  383. //
  384. // ensure we have reasonable focus for accessability
  385. //
  386. PostMessage(hDlg,WM_USER_FOCUS,IDC_DEVRES_SETTINGSLIST,0);
  387. break;
  388. }
  389. default:
  390. break;
  391. }
  392. break;
  393. case WM_USER_FOCUS:
  394. //
  395. // change focus to DlgItem wParam
  396. //
  397. SetFocus(GetDlgItem(hDlg,(int)wParam));
  398. return TRUE;
  399. case WM_NOTIFY: {
  400. //
  401. // new controls & property codes
  402. //
  403. NMHDR * pHdr = (NMHDR*)lParam;
  404. switch (pHdr->code) {
  405. case PSN_SETACTIVE: {
  406. HICON hIcon = NULL, hOldIcon = NULL;
  407. TCHAR szString[MAX_PATH];
  408. ULONG ulSize = 0;
  409. HMACHINE hMachine;
  410. hMachine = pGetMachine(lpdmpd);
  411. //
  412. // Set the ICON and device description
  413. //
  414. if (SetupDiLoadClassIcon(&lpdmpd->lpdi->ClassGuid, &hIcon, NULL)) {
  415. if ((hOldIcon = (HICON)LOWORD(SendDlgItemMessage(hDlg, IDC_DEVRES_ICON,
  416. STM_SETICON,
  417. (WPARAM)hIcon, 0L)))) {
  418. DestroyIcon(hOldIcon);
  419. }
  420. }
  421. //
  422. // First try to get the device's friendly name, then fall back to its description,
  423. // and finally, use the "Unknown Device" description.
  424. //
  425. ulSize = MAX_PATH * sizeof(TCHAR);
  426. if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  427. CM_DRP_FRIENDLYNAME,
  428. NULL, (LPBYTE)szString,
  429. &ulSize, 0,hMachine) != CR_SUCCESS) {
  430. ulSize = MAX_PATH * sizeof(TCHAR);
  431. if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  432. CM_DRP_DEVICEDESC,
  433. NULL, (LPBYTE)szString,
  434. &ulSize, 0,hMachine) != CR_SUCCESS) {
  435. LoadString(MyDllModuleHandle, IDS_DEVNAME_UNK, szString, MAX_PATH);
  436. }
  437. }
  438. SetDlgItemText(hDlg, IDC_DEVRES_DEVDESC, szString);
  439. break;
  440. }
  441. case PSN_APPLY: {
  442. BOOL bRet = FALSE;
  443. //
  444. // If there were Changes and they haven't been saved,
  445. // then save them.
  446. // consider some special cases as "haven't been saved"
  447. //
  448. if((lpdmpd->CurrentLC == 0) && (lpdmpd->dwFlags&DMPROP_FLAG_FIXEDCONFIG)) {
  449. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
  450. }
  451. switch(pOkToSave(lpdmpd)) {
  452. case IDNO:
  453. //
  454. // proceed without saving
  455. //
  456. bRet = TRUE;
  457. break;
  458. case IDCANCEL:
  459. //
  460. // don't proceed
  461. //
  462. bRet = FALSE;
  463. break;
  464. case IDYES:
  465. //
  466. // proceed and save
  467. //
  468. bRet = pSaveDevResSettings(lpdmpd);
  469. #if 0
  470. if (bRet) {
  471. if ((lpdmpd->lpdi)->Flags & DI_NEEDREBOOT) {
  472. PropSheet_RebootSystem(GetParent(hDlg));
  473. } else if ((lpdmpd->lpdi)->Flags & DI_NEEDRESTART) {
  474. PropSheet_RestartWindows(GetParent(hDlg));
  475. }
  476. #endif
  477. if (bRet) {
  478. //
  479. // This page doesn't support roll-back, if we saved
  480. // something then we're committed, disable the cancel
  481. // botton.
  482. //
  483. PropSheet_CancelToClose(GetParent(hDlg));
  484. }
  485. break;
  486. default:
  487. MYASSERT(FALSE /* pOkToSave returned invalid value */);
  488. bRet = FALSE;
  489. break;
  490. }
  491. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, bRet ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE);
  492. return TRUE;
  493. }
  494. case LVN_DELETEALLITEMS:
  495. if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
  496. return FALSE; // we want LVN_DELETEITEM messages
  497. }
  498. break;
  499. case LVN_DELETEITEM: {
  500. LPNMLISTVIEW pListView = (LPNMLISTVIEW)pHdr;
  501. if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
  502. PITEMDATA pItemData = (PITEMDATA)(LPVOID)(pListView->lParam);
  503. //
  504. // when an item is deleted, destroy associated data
  505. //
  506. if (pItemData->MatchingResDes) {
  507. CM_Free_Res_Des_Handle(pItemData->MatchingResDes);
  508. }
  509. MyFree(pItemData);
  510. }
  511. break;
  512. }
  513. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
  514. break;
  515. case LVN_ITEMCHANGED:
  516. //
  517. // If the item change is comming from the resource
  518. // list, and there is a logconfig to be edited:
  519. //
  520. if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
  521. //
  522. // see if we should enable resource change
  523. //
  524. pCheckEnableResourceChange(lpdmpd);
  525. }
  526. break;
  527. case NM_DBLCLK:
  528. //
  529. // If the double click is from the SETTINGS list
  530. // AND the DEVRES_CHANGE button is enabled, then
  531. // allow the change.
  532. //
  533. if (pHdr->idFrom == IDC_DEVRES_SETTINGSLIST) {
  534. //
  535. // this routine should check that we can change settings
  536. //
  537. pChangeCurrentResSetting(lpdmpd);
  538. }
  539. break;
  540. }
  541. break;
  542. }
  543. case WM_SYSCOLORCHANGE: {
  544. HWND hChildWnd = GetWindow(hDlg, GW_CHILD);
  545. while (hChildWnd != NULL) {
  546. SendMessage(hChildWnd, WM_SYSCOLORCHANGE, wParam, lParam);
  547. hChildWnd = GetWindow(hChildWnd, GW_HWNDNEXT);
  548. }
  549. break;
  550. }
  551. case WM_HELP: // F1
  552. WinHelp(((LPHELPINFO)lParam)->hItemHandle, DEVRES_HELP, HELP_WM_HELP, (ULONG_PTR)DevResHelpIDs);
  553. break;
  554. case WM_CONTEXTMENU: // right mouse click
  555. WinHelp((HWND)wParam, DEVRES_HELP, HELP_CONTEXTMENU, (ULONG_PTR)DevResHelpIDs);
  556. break;
  557. }
  558. return FALSE;
  559. }
  560. //
  561. // Helper functions
  562. //
  563. HMACHINE
  564. pGetMachine(
  565. LPDMPROP_DATA lpdmpd
  566. )
  567. /*++
  568. Routine Description:
  569. Retrieve Machine Handle
  570. Arguments:
  571. lpdmpd - Property Data
  572. Return Value:
  573. handle
  574. --*/
  575. {
  576. HMACHINE hMachine;
  577. PDEVICE_INFO_SET pDeviceInfoSet;
  578. if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
  579. return NULL;
  580. }
  581. hMachine = pDeviceInfoSet->hMachine;
  582. UnlockDeviceInfoSet(pDeviceInfoSet);
  583. return hMachine;
  584. }
  585. BOOL
  586. pInitDevResourceDlg(
  587. LPDMPROP_DATA lpdmpd
  588. )
  589. /*++
  590. Routine Description:
  591. This routine intializes the main resource picker property page.
  592. MEMPHIS COMPATIBLE.
  593. Arguments:
  594. Return Value:
  595. TRUE if "not saved"
  596. --*/
  597. {
  598. HWND hDlg = lpdmpd->hDlg;
  599. CONFIGRET Status = CR_SUCCESS;
  600. BOOL bHasCurrent = FALSE;
  601. BOOL bShowCurrent = FALSE;
  602. BOOL bHasForced = FALSE;
  603. BOOL bNoForcedConfig = FALSE;
  604. BOOL bNeedsForcedConfig = FALSE;
  605. BOOL bHasConfigList = FALSE;
  606. LV_COLUMN LvCol;
  607. HWND hWndList = NULL;
  608. TCHAR szString[MAX_PATH], szTemp[MAX_PATH], szConfigType[MAX_PATH],
  609. szConfig[MAX_PATH];
  610. ULONG ulIndex = 0, ulSize = 0, DevStatus = 0, DevProblem = 0;
  611. DWORD BusType = (DWORD)(-1);
  612. LOG_CONF LogConf;
  613. DWORD dwPriority = 0;
  614. WORD wItem;
  615. ULONG ConfigFlags;
  616. HMACHINE hMachine = NULL;
  617. PDEVICE_INFO_SET pDeviceInfoSet;
  618. int iIndex;
  619. BOOL bHasPrivs = FALSE;
  620. //
  621. // Set initial control states
  622. //
  623. pHideAllControls(lpdmpd);
  624. //
  625. // determine priv token
  626. // security checks are visual only
  627. // real security checks are done in umpnpmgr
  628. //
  629. bHasPrivs = pSetupDoesUserHavePrivilege(SE_LOAD_DRIVER_NAME);
  630. hMachine = pGetMachine(lpdmpd);
  631. //
  632. // retrieves current configuration, if any
  633. //
  634. bHasCurrent = pGetCurrentConfig(lpdmpd);
  635. //
  636. // We sometimes get called to show this page even if the device
  637. // doesn't consume any resources. Check for that case and if so, just
  638. // display an informational message and disable everything else.
  639. //
  640. if (!pDevRequiresResources(lpdmpd->lpdi->DevInst,hMachine)) {
  641. //
  642. // This device has no resources
  643. //
  644. pShowViewNoResources(lpdmpd);
  645. lpdmpd->dwFlags |= DMPROP_FLAG_NO_RESOURCES;
  646. goto Final;
  647. }
  648. //
  649. // Initialize the ListView control
  650. //
  651. hWndList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  652. LvCol.mask = LVCF_TEXT;
  653. if (LoadString(MyDllModuleHandle, IDS_RESOURCETYPE, szString, MAX_PATH)) {
  654. LvCol.pszText = (LPTSTR)szString;
  655. ListView_InsertColumn(hWndList, 0, (LV_COLUMN FAR *)&LvCol);
  656. }
  657. if (LoadString(MyDllModuleHandle, IDS_RESOURCESETTING, szString, MAX_PATH)) {
  658. LvCol.pszText = (LPTSTR)szString;
  659. ListView_InsertColumn(hWndList, 1, (LV_COLUMN FAR *)&LvCol);
  660. }
  661. ListView_SetImageList(hWndList,lpdmpd->himlResourceImages, LVSIL_SMALL);
  662. //
  663. // Get DevStatus & DevProblem here, we may use this info further down
  664. //
  665. if (CM_Get_DevNode_Status_Ex(&DevStatus, &DevProblem, lpdmpd->lpdi->DevInst,
  666. 0,hMachine) != CR_SUCCESS) {
  667. //
  668. // we should never get here, show this as a problem
  669. //
  670. lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
  671. } else if (DevStatus & DN_HAS_PROBLEM) {
  672. //
  673. // cache problem flag away
  674. //
  675. lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
  676. } else if (DevStatus & DN_PRIVATE_PROBLEM) {
  677. //
  678. // driver indicates problem
  679. // for now, do same as above
  680. //
  681. lpdmpd->dwFlags |= DMPROP_FLAG_HASPROBLEM;
  682. }
  683. if (bIsMultiFunctionChild(lpdmpd->lpdi,hMachine)) {
  684. //
  685. // If this is a MultiFunction Child, disable all change controls, put up
  686. // special text, and show the alloc config
  687. //
  688. pShowViewMFReadOnly(lpdmpd,FALSE);
  689. goto Final;
  690. }
  691. //
  692. // begin with read-only view, assuming settings are system
  693. //
  694. lpdmpd->dwFlags |= DMPROP_FLAG_USESYSSETTINGS;
  695. if (CM_Get_First_Log_Conf_Ex(NULL,
  696. lpdmpd->lpdi->DevInst,
  697. FORCED_LOG_CONF,
  698. hMachine) == CR_SUCCESS) {
  699. //
  700. // the user currently has a forced config
  701. //
  702. lpdmpd->dwFlags &= ~DMPROP_FLAG_USESYSSETTINGS;
  703. bHasForced = TRUE;
  704. }
  705. bShowCurrent = pShowViewReadOnly(lpdmpd,bHasPrivs);
  706. if (!bHasPrivs || hMachine) {
  707. //
  708. // if we don't have enough priv's
  709. // or we're displaying resources of a remote machine
  710. // bottle out here
  711. // we'll either be displaying current resources
  712. // or displaying a problem
  713. //
  714. goto Final;
  715. }
  716. if(!bHasForced) {
  717. //
  718. // Check bus we're using
  719. // to see if it's one of the read-only displays
  720. //
  721. ulSize = sizeof(BusType);
  722. if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  723. CM_DRP_LEGACYBUSTYPE,
  724. NULL, (LPBYTE)&BusType,
  725. &ulSize, 0,hMachine) != CR_SUCCESS) {
  726. BusType = (DWORD)InterfaceTypeUndefined;
  727. }
  728. if (BusType != (DWORD)InterfaceTypeUndefined) {
  729. int InterfaceItem;
  730. for(InterfaceItem = 0; ResourcePickerReadOnlyInterfaces[InterfaceItem] != InterfaceTypeUndefined; InterfaceItem++) {
  731. if (BusType == (DWORD)ResourcePickerReadOnlyInterfaces[InterfaceItem]) {
  732. //
  733. // Bus is one that we do not allow forced configs
  734. // we can skip all the funky code below
  735. //
  736. // this is a good thing for 64-bit PCI
  737. //
  738. goto Final;
  739. }
  740. }
  741. }
  742. }
  743. //
  744. // Retrieve alternate configurations for this device
  745. //
  746. if (bHasCurrent) {
  747. //
  748. // Current config (if any) is indicated with zero handle
  749. //
  750. LoadString(MyDllModuleHandle, IDS_CURRENTCONFIG, szString, MAX_PATH);
  751. iIndex = (int)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
  752. CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPSTR)szString);
  753. SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETITEMDATA,(WPARAM)iIndex, (LPARAM)0);
  754. SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETCURSEL,(WPARAM)0, (LPARAM)0);
  755. }
  756. //
  757. // now fill in alternate configurations
  758. // override preferred over basic (in that order)
  759. // don't use Filtered, filtered might remove configs that require reboot
  760. // but they are fine to have here
  761. //
  762. if(CM_Get_First_Log_Conf_Ex(&LogConf,lpdmpd->lpdi->DevInst,OVERRIDE_LOG_CONF,hMachine) == CR_SUCCESS) {
  763. lpdmpd->ConfigListLCType = OVERRIDE_LOG_CONF;
  764. LoadString(MyDllModuleHandle, IDS_OVERRIDECONFIG, szConfigType, MAX_PATH);
  765. bHasConfigList = TRUE;
  766. } else if(CM_Get_First_Log_Conf_Ex(&LogConf,lpdmpd->lpdi->DevInst,BASIC_LOG_CONF,hMachine) == CR_SUCCESS) {
  767. lpdmpd->ConfigListLCType = BASIC_LOG_CONF;
  768. LoadString(MyDllModuleHandle, IDS_BASICCONFIG, szConfigType, MAX_PATH);
  769. bHasConfigList = TRUE;
  770. } else {
  771. //
  772. // If there are no alternate configs, we cannot allow a forced config
  773. //
  774. bNoForcedConfig = TRUE; // cannot force
  775. bHasConfigList = FALSE;
  776. lpdmpd->ConfigListLCType = BASIC_LOG_CONF;
  777. lpdmpd->dwFlags |= DMPROP_FLAG_SINGLE_CONFIG;
  778. }
  779. if(bHasConfigList) {
  780. ulIndex = 0;
  781. if (!pConfigHasNoAlternates(lpdmpd,LogConf)) {
  782. //
  783. // first configuration has more than one alternative
  784. //
  785. lpdmpd->dwFlags &= ~DMPROP_FLAG_SINGLE_CONFIG;
  786. } else {
  787. //
  788. // begin with the assumption there is a single fixed 'basic' config
  789. // we will generally be proved wrong
  790. //
  791. lpdmpd->dwFlags |= DMPROP_FLAG_SINGLE_CONFIG;
  792. }
  793. while (Status == CR_SUCCESS) {
  794. //
  795. // Add this config to the Combobox
  796. //
  797. wsprintf(szTemp, TEXT("%s %04u"), szConfigType, ulIndex);
  798. wItem = (WORD)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
  799. CB_ADDSTRING, 0,
  800. (LPARAM)(LPSTR)szTemp);
  801. //
  802. // Save the log config handle as the item data in the combobox
  803. //
  804. SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST, CB_SETITEMDATA,
  805. wItem, (LPARAM)LogConf);
  806. //
  807. // Get the next config
  808. //
  809. Status = CM_Get_Next_Log_Conf_Ex(&LogConf, LogConf, 0,hMachine);
  810. ulIndex++;
  811. }
  812. if (ulIndex > 1) {
  813. //
  814. // there is more than one config
  815. //
  816. lpdmpd->dwFlags &= ~DMPROP_FLAG_SINGLE_CONFIG;
  817. }
  818. if (lpdmpd->dwFlags & DMPROP_FLAG_SINGLE_CONFIG) {
  819. bNoForcedConfig = TRUE;
  820. }
  821. if (bHasCurrent) {
  822. //
  823. // try to find a matching LC now, and if we could find one,
  824. // re-load current display (this applies editable ranges to the resources)
  825. //
  826. if(pFindMatchingAllocConfig(lpdmpd)) {
  827. pLoadCurrentConfig(lpdmpd,TRUE);
  828. }
  829. }
  830. } else {
  831. }
  832. //
  833. // Get ConfigFlags here, we may use this info further down
  834. //
  835. ulSize = sizeof(ConfigFlags);
  836. if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  837. CM_DRP_CONFIGFLAGS,
  838. NULL, (LPBYTE)&ConfigFlags,
  839. &ulSize, 0,hMachine) != CR_SUCCESS) {
  840. ConfigFlags = 0;
  841. }
  842. if (ConfigFlags & CONFIGFLAG_NEEDS_FORCED_CONFIG) {
  843. //
  844. // registry says that we need a forced config
  845. // registry can only say this to us once
  846. //
  847. bNeedsForcedConfig = TRUE;
  848. ConfigFlags &= ~CONFIGFLAG_NEEDS_FORCED_CONFIG;
  849. CM_Set_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  850. CM_DRP_CONFIGFLAGS,
  851. (LPBYTE)&ConfigFlags,
  852. sizeof(ConfigFlags),
  853. 0,
  854. hMachine);
  855. }
  856. //
  857. // determine if it can be software-config'd or not
  858. // we need to do this prior to any initial display
  859. //
  860. dwPriority = pGetMinLCPriority(lpdmpd->lpdi->DevInst, lpdmpd->ConfigListLCType,hMachine);
  861. if (dwPriority < LCPRI_HARDRECONFIG) {
  862. //
  863. // doesn't need to be manually configured
  864. //
  865. lpdmpd->dwFlags &= ~DMPROP_FLAG_FORCEDONLY;
  866. } else {
  867. //
  868. // this cannot be software config'd
  869. // FORCEDONLY & bNoForcedConfig is a quandry, shouldn't happen
  870. //
  871. lpdmpd->dwFlags |= DMPROP_FLAG_FORCEDONLY;
  872. if(!bHasConfigList) {
  873. MYASSERT(bHasConfigList);
  874. } else {
  875. MYASSERT(!bNoForcedConfig);
  876. bNoForcedConfig = FALSE;
  877. }
  878. }
  879. //
  880. // Try to determine initial display
  881. //
  882. // we've already covered pShowViewNoResources (no actual or potential configs)
  883. // and pShowViewMFReadOnly (it's a multi-function device)
  884. //
  885. // we're currently showing as pShowViewReadOnly
  886. //
  887. // some cases....
  888. // (1) show forced config, don't allow auto-config (config flags say requires forced)
  889. // (2) show forced config, allow auto-config
  890. // (3) don't show any config, but maybe show a forced-config button
  891. // (4) auto-config, don't allow forced config
  892. // (5) show auto-config, allow forced-config
  893. //
  894. if (bNeedsForcedConfig) {
  895. if (!bHasConfigList) {
  896. MYASSERT(bHasConfigList);
  897. bNeedsForcedConfig = FALSE;
  898. } else {
  899. MYASSERT(!bNoForcedConfig);
  900. bNoForcedConfig = FALSE;
  901. if (bHasForced) {
  902. //
  903. // already got one, but we'll go through the motions
  904. // we'll show what we have, allow user to change it
  905. // but we wont needlessly save it
  906. //
  907. bNeedsForcedConfig = FALSE;
  908. }
  909. //
  910. // caller said that device must have forced config, so go immediately there
  911. // = case (1) unless we've otherwise said we cannot have a forced config
  912. //
  913. lpdmpd->dwFlags |= DMPROP_FLAG_FORCEDONLY;
  914. pSelectLogConf(lpdmpd,(LOG_CONF)0,ALLOC_LOG_CONF,TRUE);
  915. pShowViewAllEdit(lpdmpd);
  916. goto Final;
  917. }
  918. }
  919. if ((!bShowCurrent) || (lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
  920. //
  921. // determine between pShowViewNoAlloc and pShowViewNeedForced
  922. //
  923. if (bNoForcedConfig) {
  924. //
  925. // there is a problem - device doesn't currently have a current configuration
  926. // but we don't have the option of letting them set forced config
  927. // so this ends up display only (tough-luck scenario)
  928. // if there are current resources, show them
  929. //
  930. pShowViewReadOnly(lpdmpd,FALSE);
  931. } else {
  932. //
  933. // we show the problem and we give the user
  934. // an option to force config
  935. //
  936. pShowViewNeedForced(lpdmpd);
  937. }
  938. goto Final;
  939. }
  940. if (!bHasConfigList) {
  941. //
  942. // If we have a current config, but no basic configs, we just display what we have
  943. // and don't give option to edit
  944. //
  945. pShowViewReadOnly(lpdmpd,FALSE);
  946. goto Final;
  947. }
  948. if ((lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) && bNoForcedConfig) {
  949. //
  950. // we can't force a bNoForcedConfig item - display only
  951. //
  952. pShowViewReadOnly(lpdmpd,FALSE);
  953. goto Final;
  954. }
  955. //
  956. // we already have and will be displaying a current config
  957. //
  958. pShowViewAllEdit(lpdmpd);
  959. bNeedsForcedConfig = (BOOL)!bHasCurrent; // rarely, if ever, will this return TRUE
  960. Final:
  961. return bNeedsForcedConfig;
  962. } // InitDevResourceDlg
  963. PITEMDATA
  964. pGetResourceToChange(
  965. IN LPDMPROP_DATA lpdmpd,
  966. OUT int *pCur
  967. )
  968. /*++
  969. Routine Description:
  970. Gets resource to change
  971. NULL if we cannot change resource
  972. Arguments:
  973. lpdmpd = dialog data
  974. pCur = (out) index
  975. Return Value:
  976. PITEMDATA saved for selected resource
  977. --*/
  978. {
  979. HWND hList = GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_SETTINGSLIST);
  980. PITEMDATA pItemData = NULL;
  981. int iCur;
  982. //
  983. // first check the obvious
  984. //
  985. if (lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES) {
  986. //
  987. // no editing allowed
  988. //
  989. return NULL;
  990. }
  991. if (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) {
  992. //
  993. // showing system settings
  994. //
  995. return NULL;
  996. }
  997. //
  998. // Check if there is a selected item.
  999. // If yes, then activate the change button
  1000. // if the LC allows editing.
  1001. //
  1002. iCur = (int)ListView_GetNextItem(hList,-1, LVNI_SELECTED);
  1003. if (iCur == LB_ERR) {
  1004. //
  1005. // no selection
  1006. //
  1007. return NULL;
  1008. }
  1009. pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
  1010. if (pItemData == NULL) {
  1011. //
  1012. // shouldn't happen
  1013. //
  1014. MYASSERT(pItemData);
  1015. return NULL;
  1016. }
  1017. if (pItemData->bFixed) {
  1018. //
  1019. // this is an un-editable setting
  1020. //
  1021. return NULL;
  1022. }
  1023. if (pItemData->MatchingResDes == (RES_DES)0) {
  1024. //
  1025. // should be caught by bFixed
  1026. //
  1027. MYASSERT(pItemData->MatchingResDes != (RES_DES)0);
  1028. return NULL;
  1029. }
  1030. //
  1031. // we're happy
  1032. //
  1033. if (pCur) {
  1034. *pCur = iCur;
  1035. }
  1036. return pItemData;
  1037. }
  1038. VOID
  1039. pCheckEnableResourceChange(
  1040. LPDMPROP_DATA lpdmpd
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. enables/disable change button
  1045. Arguments:
  1046. Return Value:
  1047. none
  1048. --*/
  1049. {
  1050. #if 0 // this seems to confuse people
  1051. EnableWindow(GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_CHANGE),
  1052. pGetResourceToChange(lpdmpd,NULL)!=NULL);
  1053. #endif // 0
  1054. //
  1055. // show this button enabled if we are in EDIT mode
  1056. //
  1057. EnableWindow(GetDlgItem(lpdmpd->hDlg, IDC_DEVRES_CHANGE),
  1058. (lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES)==0 &&
  1059. (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)==0);
  1060. }
  1061. BOOL
  1062. pDevHasConfig(
  1063. DEVINST DevInst,
  1064. ULONG ulConfigType,
  1065. HMACHINE hMachine
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This routine determines whether a log config of the specified type
  1070. exists for this device instance.
  1071. MEMPHIS COMPATIBLE.
  1072. Arguments:
  1073. DevInst Device instance to query log configs for.
  1074. ulConfigType Specifies the type of log conf to check for the presense of.
  1075. Return Value:
  1076. TRUE if the device has a config of that type and FALSE if it does not.
  1077. --*/
  1078. {
  1079. BOOL bRet = (CM_Get_First_Log_Conf_Ex(NULL, DevInst, ulConfigType,hMachine) == CR_SUCCESS);
  1080. return bRet;
  1081. } // DevHasConfig
  1082. DWORD
  1083. pGetMinLCPriority(
  1084. IN DEVINST DevInst,
  1085. IN ULONG ulConfigType,
  1086. IN HMACHINE hMachine
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. This routine returns the minimum priority value of all log confs of the
  1091. specified type for this device. MEMPHIS COMPATIBLE.
  1092. Arguments:
  1093. DevInst Device instance to query log configs for.
  1094. ulConfigType Specifies the type of log conf.
  1095. Return Value:
  1096. Returns the minimum priority value found or LCPRI_LASTSOFTCONFIG if no priorities
  1097. are found.
  1098. --*/
  1099. {
  1100. CONFIGRET Status = CR_SUCCESS;
  1101. ULONG priority, minPriority = MAX_LCPRI;
  1102. LOG_CONF LogConf, tempLC;
  1103. BOOL FoundOneLogConfWithPriority = FALSE;
  1104. //
  1105. // Walk through each log conf of this type for this device and
  1106. // save the smallest value.
  1107. //
  1108. Status = CM_Get_First_Log_Conf_Ex(&LogConf, DevInst, ulConfigType,hMachine);
  1109. while (Status == CR_SUCCESS) {
  1110. if (CM_Get_Log_Conf_Priority_Ex(LogConf, &priority, 0,hMachine) == CR_SUCCESS) {
  1111. FoundOneLogConfWithPriority = TRUE;
  1112. minPriority = min(minPriority, priority);
  1113. }
  1114. tempLC = LogConf;
  1115. Status = CM_Get_Next_Log_Conf_Ex(&LogConf, LogConf, 0,hMachine);
  1116. CM_Free_Log_Conf_Handle(tempLC);
  1117. }
  1118. if(FoundOneLogConfWithPriority) {
  1119. return minPriority;
  1120. } else {
  1121. //
  1122. // None of the LogConfigs had an associated priority. This is common on
  1123. // NT, because the bus drivers don't specify ConfigMgr-style priorities
  1124. // when responding to IRQ_MN_QUERY_RESOURCE_REQUIREMENTS. Since these
  1125. // cases are all PnP bus drivers, however, it is most correct to specify
  1126. // these LogConfigs as soft-settable.
  1127. //
  1128. return LCPRI_LASTSOFTCONFIG;
  1129. }
  1130. } // GetMinLCPriority
  1131. BOOL
  1132. pDevRequiresResources(
  1133. DEVINST DevInst,
  1134. HMACHINE hMachine
  1135. )
  1136. {
  1137. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, BASIC_LOG_CONF,hMachine) == CR_SUCCESS) {
  1138. return TRUE;
  1139. }
  1140. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, FILTERED_LOG_CONF,hMachine) == CR_SUCCESS) {
  1141. return TRUE;
  1142. }
  1143. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, OVERRIDE_LOG_CONF,hMachine) == CR_SUCCESS) {
  1144. return TRUE;
  1145. }
  1146. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
  1147. return TRUE;
  1148. }
  1149. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, BOOT_LOG_CONF,hMachine) == CR_SUCCESS) {
  1150. return TRUE;
  1151. }
  1152. if (CM_Get_First_Log_Conf_Ex(NULL, DevInst, ALLOC_LOG_CONF,hMachine) == CR_SUCCESS) {
  1153. return TRUE;
  1154. }
  1155. return FALSE;
  1156. } // DevRequiresResources
  1157. BOOL
  1158. pGetCurrentConfig(
  1159. IN OUT LPDMPROP_DATA lpdmpd
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. This routine determines the current known configuration
  1164. current configs are either forced, alloc or boot configs.
  1165. Arguments:
  1166. lpdmpd Property data.
  1167. Return Value:
  1168. TRUE if we set the current config
  1169. --*/
  1170. {
  1171. PDEVICE_INFO_SET pDeviceInfoSet;
  1172. HMACHINE hMachine;
  1173. ULONG Status;
  1174. ULONG Problem;
  1175. MYASSERT(lpdmpd!=NULL);
  1176. MYASSERT(lpdmpd->lpdi!=NULL);
  1177. MYASSERT(lpdmpd->CurrentLC==0);
  1178. MYASSERT(lpdmpd->lpdi->DevInst!=0);
  1179. if (lpdmpd==NULL ||
  1180. lpdmpd->lpdi==NULL ||
  1181. lpdmpd->lpdi->DevInst==0) {
  1182. return FALSE;
  1183. }
  1184. lpdmpd->dwFlags &= ~DMPROP_FLAG_DISPLAY_MASK;
  1185. if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
  1186. return FALSE;
  1187. }
  1188. hMachine = pDeviceInfoSet->hMachine;
  1189. UnlockDeviceInfoSet (pDeviceInfoSet);
  1190. if (CM_Get_DevNode_Status_Ex(&Status, &Problem, lpdmpd->lpdi->DevInst,
  1191. 0,hMachine) != CR_SUCCESS) {
  1192. Problem = 0;
  1193. Status = 0;
  1194. } else if((Status & DN_HAS_PROBLEM)==0) {
  1195. //
  1196. // If this device is running, does this devinst have a ALLOC log config?
  1197. //
  1198. if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
  1199. lpdmpd->lpdi->DevInst,
  1200. ALLOC_LOG_CONF,
  1201. hMachine) == CR_SUCCESS) {
  1202. lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_ALLOC;
  1203. lpdmpd->CurrentLCType = ALLOC_LOG_CONF;
  1204. return TRUE;
  1205. }
  1206. }
  1207. //
  1208. // If no config so far, does it have a FORCED log config?
  1209. //
  1210. if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
  1211. lpdmpd->lpdi->DevInst,
  1212. FORCED_LOG_CONF,
  1213. hMachine) == CR_SUCCESS) {
  1214. lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_FORCED;
  1215. lpdmpd->CurrentLCType = FORCED_LOG_CONF;
  1216. return TRUE;
  1217. }
  1218. //
  1219. // if there's a hardware-disabled problem, boot-config isn't valid
  1220. //
  1221. if(((Status & DN_HAS_PROBLEM)==0) || (Problem != CM_PROB_HARDWARE_DISABLED)) {
  1222. //
  1223. // Does it have a BOOT log config?
  1224. //
  1225. if (CM_Get_First_Log_Conf_Ex(&lpdmpd->CurrentLC,
  1226. lpdmpd->lpdi->DevInst,
  1227. BOOT_LOG_CONF,
  1228. hMachine) == CR_SUCCESS) {
  1229. lpdmpd->dwFlags |= DMPROP_FLAG_DISPLAY_BOOT;
  1230. lpdmpd->CurrentLCType = BOOT_LOG_CONF;
  1231. return TRUE;
  1232. }
  1233. }
  1234. return FALSE;
  1235. }
  1236. void
  1237. pGetHdrValues(
  1238. IN LPBYTE pData,
  1239. IN RESOURCEID ResType,
  1240. OUT PULONG64 pulValue,
  1241. OUT PULONG64 pulLen,
  1242. OUT PULONG64 pulEnd,
  1243. OUT PULONG pulFlags
  1244. )
  1245. {
  1246. switch (ResType) {
  1247. case ResType_Mem: {
  1248. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
  1249. *pulValue = pMemData->MEM_Header.MD_Alloc_Base;
  1250. *pulLen = (pMemData->MEM_Header.MD_Alloc_End -
  1251. pMemData->MEM_Header.MD_Alloc_Base + 1);
  1252. *pulEnd = pMemData->MEM_Header.MD_Alloc_End;
  1253. *pulFlags = pMemData->MEM_Header.MD_Flags;
  1254. break;
  1255. }
  1256. case ResType_IO: {
  1257. PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
  1258. *pulValue = pIoData->IO_Header.IOD_Alloc_Base;
  1259. *pulLen = (pIoData->IO_Header.IOD_Alloc_End -
  1260. pIoData->IO_Header.IOD_Alloc_Base + 1);
  1261. *pulEnd = pIoData->IO_Header.IOD_Alloc_End;
  1262. *pulFlags = pIoData->IO_Header.IOD_DesFlags;
  1263. break;
  1264. }
  1265. case ResType_DMA: {
  1266. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
  1267. *pulValue = pDmaData->DMA_Header.DD_Alloc_Chan;
  1268. *pulLen = 1;
  1269. *pulEnd = *pulValue;
  1270. *pulFlags = pDmaData->DMA_Header.DD_Flags;
  1271. break;
  1272. }
  1273. case ResType_IRQ: {
  1274. DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
  1275. *pulValue = pIrqData->IRQ_Header.IRQD_Alloc_Num;
  1276. *pulLen = 1;
  1277. *pulEnd = *pulValue;
  1278. *pulFlags = pIrqData->IRQ_Header.IRQD_Flags;
  1279. break;
  1280. }
  1281. }
  1282. if(*pulEnd < *pulValue) {
  1283. //
  1284. // filter out bad/zero-length range
  1285. //
  1286. *pulLen = 0;
  1287. }
  1288. return;
  1289. } // GetHdrValues
  1290. void
  1291. pGetRangeValues(
  1292. IN LPBYTE pData,
  1293. IN RESOURCEID ResType,
  1294. IN ULONG ulIndex,
  1295. OUT PULONG64 pulValue, OPTIONAL
  1296. OUT PULONG64 pulLen, OPTIONAL
  1297. OUT PULONG64 pulEnd, OPTIONAL
  1298. OUT PULONG64 pulAlign, OPTIONAL
  1299. OUT PULONG pulFlags OPTIONAL
  1300. )
  1301. {
  1302. //
  1303. // keep local copies
  1304. // we transfer to parameters at end
  1305. //
  1306. ULONG64 ulValue;
  1307. ULONG64 ulLen;
  1308. ULONG64 ulEnd;
  1309. ULONG64 ulAlign;
  1310. ULONG ulFlags;
  1311. switch (ResType) {
  1312. case ResType_Mem: {
  1313. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
  1314. ulValue = pMemData->MEM_Data[ulIndex].MR_Min;
  1315. ulLen = pMemData->MEM_Data[ulIndex].MR_nBytes;
  1316. ulEnd = pMemData->MEM_Data[ulIndex].MR_Max;
  1317. ulFlags = pMemData->MEM_Data[ulIndex].MR_Flags;
  1318. ulAlign = pMemData->MEM_Data[ulIndex].MR_Align;
  1319. break;
  1320. }
  1321. case ResType_IO: {
  1322. PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
  1323. ulValue = pIoData->IO_Data[ulIndex].IOR_Min;
  1324. ulLen = pIoData->IO_Data[ulIndex].IOR_nPorts;
  1325. ulEnd = pIoData->IO_Data[ulIndex].IOR_Max;
  1326. ulFlags = pIoData->IO_Data[ulIndex].IOR_RangeFlags;
  1327. ulAlign = pIoData->IO_Data[ulIndex].IOR_Align;
  1328. break;
  1329. }
  1330. case ResType_DMA: {
  1331. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
  1332. ulValue = pDmaData->DMA_Data[ulIndex].DR_Min;
  1333. ulLen = 1;
  1334. ulEnd = ulValue;
  1335. ulFlags = pDmaData->DMA_Data[ulIndex].DR_Flags;
  1336. ulAlign = 1;
  1337. break;
  1338. }
  1339. case ResType_IRQ: {
  1340. DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
  1341. ulValue = pIrqData->IRQ_Data[ulIndex].IRQR_Min;
  1342. ulLen = 1;
  1343. ulEnd = ulValue;
  1344. ulFlags = pIrqData->IRQ_Data[ulIndex].IRQR_Flags;
  1345. ulAlign = 1;
  1346. break;
  1347. }
  1348. }
  1349. if(ulEnd < ulValue) {
  1350. //
  1351. // filter out bad/zero-length range
  1352. //
  1353. ulLen = 0;
  1354. }
  1355. pAlignValues(&ulValue, ulValue, ulLen, ulEnd, ulAlign,1);
  1356. //
  1357. // copy return parameters
  1358. //
  1359. if (pulValue) {
  1360. *pulValue = ulValue;
  1361. }
  1362. if (pulLen) {
  1363. *pulLen = ulLen;
  1364. }
  1365. if (pulEnd) {
  1366. *pulEnd = ulEnd;
  1367. }
  1368. if (pulAlign) {
  1369. *pulAlign = ulAlign;
  1370. }
  1371. if (pulFlags) {
  1372. *pulFlags = ulFlags;
  1373. }
  1374. return;
  1375. }
  1376. BOOL
  1377. pAlignValues(
  1378. IN OUT PULONG64 pulValue,
  1379. IN ULONG64 ulStart,
  1380. IN ULONG64 ulLen,
  1381. IN ULONG64 ulEnd,
  1382. IN ULONG64 ulAlignment,
  1383. IN int Increment
  1384. )
  1385. {
  1386. ULONG64 NtAlign = ~ulAlignment + 1; // convert from mask to modulus
  1387. ULONG64 Value;
  1388. ULONG64 Upp;
  1389. ULONG64 Remainder;
  1390. Value = *pulValue;
  1391. if (NtAlign == 0) {
  1392. return FALSE; // bogus alignment value
  1393. }
  1394. if (NtAlign != 1 && Increment != 0) {
  1395. //
  1396. // see if we are aligned
  1397. //
  1398. Remainder = Value % NtAlign;
  1399. if (Remainder != 0) {
  1400. //
  1401. // need to re-align
  1402. //
  1403. if (Increment>0) {
  1404. //
  1405. // Return the first valid aligned value greater than this value
  1406. //
  1407. Value += NtAlign - Remainder;
  1408. if (Value <= *pulValue) {
  1409. //
  1410. // overflow detected
  1411. //
  1412. return FALSE;
  1413. }
  1414. } else {
  1415. //
  1416. // Return the first valid aligned value less than this value
  1417. //
  1418. Value -= Remainder;
  1419. //
  1420. // we never overflow going down, since zero is a common denominator
  1421. // of alignment
  1422. //
  1423. }
  1424. }
  1425. }
  1426. //
  1427. // now check boundaries
  1428. //
  1429. if (Value < ulStart) {
  1430. return FALSE;
  1431. }
  1432. Upp = Value+ulLen-1;
  1433. if (Upp < Value) {
  1434. //
  1435. // catch overflow error
  1436. //
  1437. return FALSE;
  1438. }
  1439. if (Upp > ulEnd) {
  1440. return FALSE;
  1441. }
  1442. //
  1443. // set newly aligned value
  1444. //
  1445. *pulValue = Value;
  1446. return TRUE;
  1447. }
  1448. void
  1449. pFormatResString(
  1450. LPDMPROP_DATA lpdmpd,
  1451. LPTSTR lpszString,
  1452. ULONG64 ulVal,
  1453. ULONG64 ulLen,
  1454. RESOURCEID ResType
  1455. )
  1456. {
  1457. if (ulLen == 0) {
  1458. wsprintf(lpszString, szNoValue);
  1459. } else if ((ResType == ResType_DMA) || (ResType == ResType_IRQ)) {
  1460. wsprintf(lpszString, szOneDecNoConflict, (UINT)ulVal);
  1461. } else if (ResType == ResType_IO) {
  1462. wsprintf(lpszString, szTwoWordHexNoConflict, (ULONG)ulVal,
  1463. (ULONG)(ulVal + ulLen - 1));
  1464. } else if (lpdmpd && (lpdmpd->dwFlags & DMPROP_FLAG_64BIT_RANGE)) {
  1465. wsprintf(lpszString, szTwo64bitHexNoConflict, (ULONG64)ulVal,
  1466. (ULONG64)(ulVal + ulLen - 1));
  1467. } else {
  1468. wsprintf(lpszString, szTwoDWordHexNoConflict, (ULONG)ulVal,
  1469. (ULONG)(ulVal + ulLen - 1));
  1470. }
  1471. }
  1472. BOOL
  1473. pUnFormatResString(
  1474. LPTSTR lpszString,
  1475. PULONG64 pulVal,
  1476. PULONG64 pulEnd,
  1477. RESOURCEID ridResType
  1478. )
  1479. {
  1480. BOOL bRet = FALSE;
  1481. LPTSTR lpszTemp = NULL;
  1482. LPTSTR lpszTemp2 = NULL;
  1483. LPTSTR lpszCopy;
  1484. // ISSUE-2000/02/03 Fix pUnFormatResString bugs
  1485. //
  1486. // - extend this to handling DWORDLONG values
  1487. // - use correct Prev/Next functions for parsing string
  1488. //
  1489. //
  1490. // Allocate space for, and make a copy of the input string
  1491. //
  1492. lpszCopy = MyMalloc((lstrlen(lpszString)+1) * sizeof(TCHAR));
  1493. if (lpszCopy == NULL) {
  1494. return FALSE;
  1495. }
  1496. lstrcpy(lpszCopy, lpszString);
  1497. //
  1498. // Locate the dash if there is one, and convert the white space prev to
  1499. // the dash to a NULL. (ie 0200 - 0400 while be 0200)
  1500. //
  1501. lpszTemp = lpszCopy;
  1502. while ((*lpszTemp != '-') && (*lpszTemp != '\0')) {
  1503. lpszTemp++; // AnsiNext?
  1504. }
  1505. if (*lpszTemp != '\0') {
  1506. lpszTemp2 = lpszTemp-1;
  1507. ++lpszTemp;
  1508. }
  1509. //
  1510. // Search back to set the NULL for the Value
  1511. //
  1512. if (lpszTemp2 != NULL) {
  1513. while ((*lpszTemp2 == ' ') || (*lpszTemp2 == '\t'))
  1514. lpszTemp2--; // AnsiPrev?
  1515. *(lpszTemp2+1)= '\0';
  1516. }
  1517. //
  1518. // Convert the first entry
  1519. //
  1520. if (pConvertEditText(lpszCopy, pulVal, ridResType)) {
  1521. //
  1522. // If there is a second entry, convert it, otherwise assume a length
  1523. // of one.
  1524. //
  1525. if (*lpszTemp != '\0') {
  1526. if (pConvertEditText(lpszTemp, pulEnd,ridResType)) {
  1527. bRet = TRUE;
  1528. }
  1529. } else {
  1530. *pulEnd = *pulVal;
  1531. bRet = TRUE;
  1532. }
  1533. }
  1534. MyFree(lpszCopy);
  1535. return bRet;
  1536. }
  1537. BOOL
  1538. pConvertEditText(
  1539. LPTSTR lpszConvert,
  1540. PULONG64 pulVal,
  1541. RESOURCEID ridResType
  1542. )
  1543. {
  1544. LPTSTR lpConvert;
  1545. if ((ridResType == ResType_Mem) || (ridResType == ResType_IO)) {
  1546. *pulVal = _tcstoul(lpszConvert, &lpConvert, (WORD)16);
  1547. } else {
  1548. *pulVal = _tcstoul(lpszConvert, &lpConvert, (WORD)10);
  1549. }
  1550. if (lpConvert == lpszConvert+lstrlen(lpszConvert)) {
  1551. return TRUE;
  1552. } else {
  1553. return FALSE;
  1554. }
  1555. } // ConvertEditText
  1556. void
  1557. pWarnResSettingNotEditable(
  1558. HWND hDlg,
  1559. WORD idWarning
  1560. )
  1561. {
  1562. TCHAR szTitle[MAX_PATH];
  1563. TCHAR szMessage[MAX_PATH * 2];
  1564. //
  1565. // Give some warning Messages. If there is no logconfig,
  1566. // then we cannot edit any settings, if there is, then
  1567. // just the setting they are choosing is not editable.
  1568. //
  1569. LoadString(MyDllModuleHandle, IDS_DEVRES_NOMODIFYTITLE, szTitle, MAX_PATH);
  1570. LoadString(MyDllModuleHandle, idWarning, szMessage, MAX_PATH * 2);
  1571. MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONEXCLAMATION);
  1572. } // WarnResSettingsNotEditable
  1573. int
  1574. pWarnNoSave(
  1575. HWND hDlg,
  1576. WORD idWarning
  1577. )
  1578. /*++
  1579. Routine Description:
  1580. Warn that the settings will not be saved
  1581. Arguments:
  1582. Return Value:
  1583. IDCANCEL = don't proceed
  1584. IDOK/IDYES/IDNO = proceed without saving
  1585. --*/
  1586. {
  1587. TCHAR szTitle[MAX_PATH];
  1588. TCHAR szMessage[MAX_PATH * 2];
  1589. int res;
  1590. //
  1591. // Give a warning message of why we can't save settings
  1592. //
  1593. LoadString(MyDllModuleHandle, IDS_MAKE_FORCED_TITLE, szTitle, MAX_PATH);
  1594. LoadString(MyDllModuleHandle, idWarning, szMessage, MAX_PATH * 2);
  1595. //res = MessageBox(hDlg, szMessage, szTitle, MB_OKCANCEL | MB_TASKMODAL | MB_ICONEXCLAMATION);
  1596. //return res;
  1597. res = MessageBox(hDlg, szMessage, szTitle, MB_OK | MB_TASKMODAL | MB_ICONEXCLAMATION);
  1598. return IDCANCEL;
  1599. }
  1600. LPVOID
  1601. pGetListViewItemData(
  1602. HWND hList,
  1603. int iItem,
  1604. int iSubItem
  1605. )
  1606. {
  1607. LV_ITEM lviItem;
  1608. lviItem.mask = LVIF_PARAM;
  1609. lviItem.iItem = iItem;
  1610. lviItem.iSubItem = iSubItem;
  1611. if (ListView_GetItem(hList, &lviItem)) {
  1612. return (LPVOID)lviItem.lParam;
  1613. } else {
  1614. return NULL;
  1615. }
  1616. } // GetListViewItemData
  1617. BOOL
  1618. pSaveDevResSettings(
  1619. LPDMPROP_DATA lpdmpd
  1620. )
  1621. /*++
  1622. Routine Description:
  1623. This routine saves the resources based on the users selections.
  1624. MEMPHIS COMPATIBLE.
  1625. Arguments:
  1626. lpdmpd Property data.
  1627. Return Value:
  1628. Returns TRUE if the function succeeded and FALSE if it failed.
  1629. --*/
  1630. {
  1631. HWND hDlg = lpdmpd->hDlg;
  1632. HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  1633. CONFIGRET Status = CR_SUCCESS;
  1634. LOG_CONF ForcedLogConf;
  1635. RES_DES ResDes, ResDesTemp, ResDes1;
  1636. RESOURCEID ResType;
  1637. ULONG ulSize = 0, ulCount = 0, i = 0, iCur = 0;
  1638. LPBYTE pData = NULL;
  1639. PITEMDATA pItemData = NULL;
  1640. BOOL bRet = TRUE;
  1641. SP_PROPCHANGE_PARAMS PropChangeParams;
  1642. HMACHINE hMachine = pGetMachine(lpdmpd);
  1643. if ((lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)!=0) {
  1644. //-------------------------------------------------------------------
  1645. // If the user checked the "Use Automatic Settings" checkbox, then
  1646. // delete any Boot/Forced configs, otherwise write the current settings
  1647. // as a forced config.
  1648. //-------------------------------------------------------------------
  1649. if (CM_Get_First_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst,
  1650. FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
  1651. CM_Free_Log_Conf_Ex(ForcedLogConf, 0,hMachine);
  1652. CM_Free_Log_Conf_Handle(ForcedLogConf);
  1653. }
  1654. // Let the helper modules (class installer/co-installers) get in on the act...
  1655. //
  1656. PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  1657. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  1658. PropChangeParams.StateChange = DICS_PROPCHANGE;
  1659. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  1660. // no need to set PropChangeParams.HwProfile, since this is a global property change.
  1661. DoInstallActionWithParams(DIF_PROPERTYCHANGE,
  1662. lpdmpd->hDevInfo,
  1663. lpdmpd->lpdi,
  1664. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  1665. sizeof(PropChangeParams),
  1666. INSTALLACTION_CALL_CI
  1667. );
  1668. } else {
  1669. //-------------------------------------------------------------------
  1670. // The Use Automatic Settings is not selected.
  1671. //-------------------------------------------------------------------
  1672. bRet = pSaveCustomResSettings(lpdmpd,hMachine);
  1673. }
  1674. return bRet;
  1675. }
  1676. BOOL
  1677. pSaveCustomResSettings(
  1678. LPDMPROP_DATA lpdmpd,
  1679. IN HMACHINE hMachine
  1680. )
  1681. /*++
  1682. Routine Description:
  1683. This routine saves custom (user edited) resources. MEMPHIS COMPATIBLE but
  1684. extracted from Memphis version of SaveDevResSetting().
  1685. Arguments:
  1686. lpdmpd Property data.
  1687. Return Value:
  1688. Returns TRUE if the function succeeded and FALSE if it failed.
  1689. --*/
  1690. {
  1691. HWND hDlg = lpdmpd->hDlg;
  1692. TCHAR szWarn[MAX_MSG_LEN];
  1693. TCHAR szTitle[MAX_MSG_LEN];
  1694. TCHAR szTemp[MAX_MSG_LEN];
  1695. DWORD dwPriority, dwLCPri;
  1696. LOG_CONF ForcedLogConf;
  1697. RES_DES ResDes;
  1698. HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  1699. PITEMDATA pItemData = NULL;
  1700. LONG iCur;
  1701. BOOL bRet = FALSE;
  1702. SP_PROPCHANGE_PARAMS PropChangeParams;
  1703. DWORD HardReconfigFlag;
  1704. SP_DEVINSTALL_PARAMS DevInstallParams;
  1705. PRESDES_ENTRY pResList = NULL, pResDesEntry = NULL, pTemp = NULL;
  1706. PITEMDATA_LISTNODE ItemDataList = NULL, ItemDataListEntry, ItemDataListEnd = NULL;
  1707. PGENERIC_RESOURCE pGenRes;
  1708. ULONG i, ulFlags;
  1709. ULONG64 ulValue, ulLen, ulEnd;
  1710. LOG_CONF LogConf;
  1711. ULONG ulSize;
  1712. ULONG ulConfigFlags;
  1713. HCURSOR hOldCursor;
  1714. BOOL UsingMatch = FALSE;
  1715. LogConf = lpdmpd->SelectedLC;
  1716. if (LogConf == 0) {
  1717. LogConf = lpdmpd->MatchingLC;
  1718. UsingMatch = TRUE;
  1719. }
  1720. if (LogConf == 0) {
  1721. LogConf = lpdmpd->CurrentLC;
  1722. UsingMatch = FALSE;
  1723. }
  1724. if (LogConf == 0) {
  1725. //MYASSERT(FALSE);
  1726. return FALSE;
  1727. }
  1728. //
  1729. // form the "warning - do you want to continue" message
  1730. //
  1731. if(!LoadString(MyDllModuleHandle, IDS_MAKE_FORCED_TITLE, szTitle, MAX_MSG_LEN)) {
  1732. szTitle[0]=TEXT('\0');
  1733. }
  1734. if(!LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN1, szWarn, MAX_MSG_LEN)) {
  1735. szWarn[0]=TEXT('\0');
  1736. }
  1737. if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN2, szTemp, MAX_MSG_LEN)) {
  1738. lstrcat(szWarn, szTemp);
  1739. }
  1740. if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN3, szTemp, MAX_MSG_LEN)) {
  1741. lstrcat(szWarn, szTemp);
  1742. }
  1743. if(LoadString(MyDllModuleHandle, IDS_FORCEDCONFIG_WARN4, szTemp, MAX_MSG_LEN)) {
  1744. lstrcat(szWarn, szTemp);
  1745. }
  1746. //
  1747. // If the LCPRI is soft configurable, and the user chooses YES to the
  1748. // warning, then save the new config. If the LCPRI is not soft
  1749. // configurable, just save with no warning
  1750. //
  1751. dwLCPri = pGetMinLCPriority(lpdmpd->lpdi->DevInst, lpdmpd->ConfigListLCType,hMachine);
  1752. if (((dwLCPri >= LCPRI_DESIRED) && (dwLCPri <= LCPRI_LASTSOFTCONFIG)) &&
  1753. (MessageBox(hDlg, szWarn, szTitle, MB_YESNO|MB_ICONEXCLAMATION) == IDNO)) {
  1754. //
  1755. // user doesn't want to change anything
  1756. //
  1757. bRet = FALSE;
  1758. } else {
  1759. //
  1760. // We're still using the selected basic LC, but use the range index
  1761. // embedded in the listview control
  1762. // ISSUE-2000/02/03-JamieHun Selected Basic LC, check if user overrode
  1763. // Need to check the value to see if a user overrode it (is this possible?)
  1764. //
  1765. bRet = TRUE;
  1766. if (CM_Get_First_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst,
  1767. FORCED_LOG_CONF,hMachine) == CR_SUCCESS) {
  1768. CM_Free_Log_Conf_Ex(ForcedLogConf, 0,hMachine);
  1769. CM_Free_Log_Conf_Handle(ForcedLogConf);
  1770. }
  1771. //
  1772. // Save the current choices as the forced config
  1773. //
  1774. CM_Add_Empty_Log_Conf_Ex(&ForcedLogConf, lpdmpd->lpdi->DevInst, LCPRI_FORCECONFIG,
  1775. FORCED_LOG_CONF | PRIORITY_EQUAL_FIRST,hMachine);
  1776. pGetResDesDataList(LogConf, &pResList, FALSE,hMachine);
  1777. pResDesEntry = pResList;
  1778. if (UsingMatch && (lpdmpd->dwFlags & DMPROP_FLAG_MATCH_OUT_OF_ORDER)) {
  1779. //
  1780. // The resource descriptors are out-of-order. Maintain the original ordering.
  1781. //
  1782. // First, build up a linked list of the data in the listview resource items.
  1783. //
  1784. iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
  1785. while (iCur != -1) {
  1786. pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
  1787. if (pItemData) {
  1788. //
  1789. // Allocate an item data list node for this data.
  1790. //
  1791. ItemDataListEntry = MyMalloc(sizeof(ITEMDATA_LISTNODE));
  1792. if (!ItemDataListEntry) {
  1793. bRet = FALSE;
  1794. goto clean0;
  1795. }
  1796. ItemDataListEntry->ItemData = pItemData;
  1797. ItemDataListEntry->Next = NULL;
  1798. //
  1799. // Append this new item to the end of our list.
  1800. //
  1801. if (ItemDataListEnd) {
  1802. ItemDataListEnd->Next = ItemDataListEntry;
  1803. } else {
  1804. ItemDataList = ItemDataListEntry;
  1805. }
  1806. ItemDataListEnd = ItemDataListEntry;
  1807. }
  1808. iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
  1809. }
  1810. //
  1811. // Now loop through each resdes entry, writing each one out. For each one, check
  1812. // to see if it has a corresponding entry in our listview item data list.
  1813. //
  1814. while (pResDesEntry) {
  1815. pGenRes = (PGENERIC_RESOURCE)pResDesEntry->ResDesData;
  1816. for(ItemDataListEntry = ItemDataList, ItemDataListEnd = NULL;
  1817. ItemDataListEntry;
  1818. ItemDataListEnd = ItemDataListEntry, ItemDataListEntry = ItemDataListEntry->Next)
  1819. {
  1820. if(pResDesEntry->ResDesType == ItemDataListEntry->ItemData->ResType) {
  1821. for (i = 0; i < pGenRes->GENERIC_Header.GENERIC_Count; i++) {
  1822. pGetRangeValues(pResDesEntry->ResDesData, pResDesEntry->ResDesType, i,
  1823. &ulValue, &ulLen, &ulEnd, NULL, &ulFlags);
  1824. if ((ItemDataListEntry->ItemData->ulLen == ulLen) &&
  1825. (ItemDataListEntry->ItemData->ulValue >= ulValue) &&
  1826. (ItemDataListEntry->ItemData->ulEnd <= ulEnd)) {
  1827. //
  1828. // We found the matching resource descriptor. Write this out.
  1829. //
  1830. pWriteValuesToForced(ForcedLogConf,
  1831. ItemDataListEntry->ItemData->ResType,
  1832. ItemDataListEntry->ItemData->RangeCount,
  1833. ItemDataListEntry->ItemData->MatchingResDes,
  1834. ItemDataListEntry->ItemData->ulValue,
  1835. ItemDataListEntry->ItemData->ulLen,
  1836. ItemDataListEntry->ItemData->ulEnd,
  1837. hMachine );
  1838. //
  1839. // Remove this item from our list.
  1840. //
  1841. if (ItemDataListEnd) {
  1842. ItemDataListEnd->Next = ItemDataListEntry->Next;
  1843. } else {
  1844. ItemDataList = ItemDataListEntry->Next;
  1845. }
  1846. MyFree(ItemDataListEntry);
  1847. break;
  1848. }
  1849. }
  1850. if(i < pGenRes->GENERIC_Header.GENERIC_Count) {
  1851. //
  1852. // Then we broke out of the loop early, which means we found a match
  1853. // already.
  1854. //
  1855. break;
  1856. }
  1857. }
  1858. }
  1859. //
  1860. // If we didn't find a match, then go ahead and write out the non-arbitrated
  1861. // resdes.
  1862. //
  1863. if (!ItemDataListEntry) {
  1864. pWriteResDesRangeToForced(ForcedLogConf,
  1865. pResDesEntry->ResDesType,
  1866. 0,
  1867. 0,
  1868. pResDesEntry->ResDesData,
  1869. hMachine);
  1870. }
  1871. pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
  1872. }
  1873. } else {
  1874. iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
  1875. while (iCur != -1) {
  1876. pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
  1877. if (pItemData) {
  1878. // retrieve values
  1879. while (pResDesEntry &&
  1880. (pItemData->ResType != pResDesEntry->ResDesType)) {
  1881. //
  1882. // write out any preceding non arbitrated resources
  1883. //
  1884. pWriteResDesRangeToForced(ForcedLogConf,
  1885. pResDesEntry->ResDesType,
  1886. 0,
  1887. 0,
  1888. pResDesEntry->ResDesData,
  1889. hMachine);
  1890. pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
  1891. }
  1892. if (pGetMatchingResDes(pItemData->ulValue,
  1893. pItemData->ulLen,
  1894. pItemData->ulEnd,
  1895. pItemData->ResType,
  1896. LogConf,
  1897. &ResDes,
  1898. hMachine)) {
  1899. //
  1900. // Write the first range as the chosen forced resource
  1901. //
  1902. pWriteValuesToForced(ForcedLogConf, pItemData->ResType,
  1903. pItemData->RangeCount, ResDes,
  1904. pItemData->ulValue,
  1905. pItemData->ulLen,
  1906. pItemData->ulEnd,
  1907. hMachine);
  1908. }
  1909. }
  1910. if (pResDesEntry) {
  1911. pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
  1912. } else {
  1913. MYASSERT(pResDesEntry);
  1914. }
  1915. iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
  1916. }
  1917. while (pResDesEntry) {
  1918. //
  1919. // write out any subsequent non arbitrated resources
  1920. //
  1921. pWriteResDesRangeToForced(ForcedLogConf,
  1922. pResDesEntry->ResDesType,
  1923. 0,
  1924. 0,
  1925. pResDesEntry->ResDesData,
  1926. hMachine);
  1927. pResDesEntry = (PRESDES_ENTRY)pResDesEntry->Next;
  1928. }
  1929. }
  1930. CM_Free_Log_Conf_Handle(ForcedLogConf);
  1931. //
  1932. // consider clearing problem flags
  1933. //
  1934. ulSize = sizeof(ulConfigFlags);
  1935. if (CM_Get_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  1936. CM_DRP_CONFIGFLAGS,
  1937. NULL, (LPBYTE)&ulConfigFlags,
  1938. &ulSize, 0,hMachine) == CR_SUCCESS) {
  1939. if ((ulConfigFlags & CONFIGFLAG_PARTIAL_LOG_CONF) != 0) {
  1940. //
  1941. // have flag(s) to change
  1942. // CONFIGFLAG_PARTIAL_LOG_CONF should be cleared - we should have written a complete config now
  1943. //
  1944. ulConfigFlags &= ~ (CONFIGFLAG_PARTIAL_LOG_CONF);
  1945. CM_Set_DevInst_Registry_Property_Ex(lpdmpd->lpdi->DevInst,
  1946. CM_DRP_CONFIGFLAGS,
  1947. (LPBYTE)&ulConfigFlags,
  1948. sizeof(ulConfigFlags),
  1949. 0,
  1950. hMachine);
  1951. }
  1952. }
  1953. //
  1954. // Give the class installer/co-installers a crack at the propchange process.
  1955. //
  1956. PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  1957. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  1958. PropChangeParams.StateChange = DICS_PROPCHANGE;
  1959. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  1960. // no need to set PropChangeParams.HwProfile, since this is a global property change.
  1961. DoInstallActionWithParams(DIF_PROPERTYCHANGE,
  1962. lpdmpd->hDevInfo,
  1963. lpdmpd->lpdi,
  1964. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  1965. sizeof(PropChangeParams),
  1966. INSTALLACTION_CALL_CI | INSTALLACTION_NO_DEFAULT
  1967. );
  1968. //
  1969. // Check the Priority of this LC. If it is greater
  1970. // than LCPRI_LASTSOFTCONFIG, then we need to reboot
  1971. // otherwise try the dynamic changestate route.
  1972. //
  1973. if (CM_Get_Log_Conf_Priority_Ex(LogConf, &dwPriority, 0,hMachine) != CR_SUCCESS) {
  1974. dwPriority = LCPRI_LASTSOFTCONFIG;
  1975. }
  1976. if (dwPriority <= LCPRI_LASTSOFTCONFIG) {
  1977. //
  1978. // Do the default action for SoftConfigable devices, which
  1979. // will attempt to restart the device with the new config
  1980. // This could take a while so use an hourglass
  1981. //
  1982. hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1983. DoInstallActionWithParams(DIF_PROPERTYCHANGE,
  1984. lpdmpd->hDevInfo,
  1985. lpdmpd->lpdi,
  1986. (PSP_CLASSINSTALL_HEADER)&PropChangeParams,
  1987. sizeof(PropChangeParams),
  1988. 0 // don't call class-installer, just do default action
  1989. );
  1990. SetCursor(hOldCursor);
  1991. HardReconfigFlag = 0;
  1992. } else if((dwPriority > LCPRI_LASTSOFTCONFIG) && (dwPriority <= LCPRI_RESTART)) {
  1993. HardReconfigFlag = DI_NEEDRESTART;
  1994. } else {
  1995. HardReconfigFlag = DI_NEEDREBOOT;
  1996. }
  1997. lpdmpd->dwFlags |= DMPROP_FLAG_CHANGESSAVED;
  1998. //
  1999. // Properties have changed, so set flags to indicate if restart/reboot is required,
  2000. // and to tell DevMgr to re-init the UI.
  2001. //
  2002. DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  2003. if(SetupDiGetDeviceInstallParams(lpdmpd->hDevInfo,
  2004. lpdmpd->lpdi,
  2005. &DevInstallParams)) {
  2006. DevInstallParams.Flags |= (HardReconfigFlag | DI_PROPERTIES_CHANGE);
  2007. SetupDiSetDeviceInstallParams(lpdmpd->hDevInfo,
  2008. lpdmpd->lpdi,
  2009. &DevInstallParams
  2010. );
  2011. }
  2012. //
  2013. // If we need to reboot, then set a problem on the device that indicates this (in case
  2014. // the user doesn't listen to us, we want to flag this devnode so that the user will see
  2015. // that this devnode needs a reboot if they go into DevMgr, etc.)
  2016. //
  2017. if(HardReconfigFlag) {
  2018. PDEVICE_INFO_SET pDeviceInfoSet;
  2019. PDEVINFO_ELEM DevInfoElem;
  2020. if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
  2021. //
  2022. // We'd better be able to access this device information set!
  2023. // In case we couldn't don't bother trying to set the needs-reboot problem,
  2024. // because the whole mess is invalid!
  2025. //
  2026. MYASSERT(pDeviceInfoSet);
  2027. } else {
  2028. try {
  2029. DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet, lpdmpd->lpdi, NULL);
  2030. //
  2031. // We'd better be able to find this element!
  2032. //
  2033. MYASSERT(DevInfoElem);
  2034. //
  2035. // In case we can't find it, don't try to set any problem on the devnode.
  2036. //
  2037. if(DevInfoElem) {
  2038. SetDevnodeNeedsRebootProblem(DevInfoElem,
  2039. pDeviceInfoSet,
  2040. MSG_LOG_REBOOT_DEVRES
  2041. );
  2042. }
  2043. } finally {
  2044. UnlockDeviceInfoSet(pDeviceInfoSet);
  2045. }
  2046. }
  2047. }
  2048. }
  2049. clean0:
  2050. while (ItemDataList) {
  2051. ItemDataListEntry = ItemDataList->Next;
  2052. MyFree(ItemDataList);
  2053. ItemDataList = ItemDataListEntry;
  2054. }
  2055. pDeleteResDesDataList(pResList);
  2056. return bRet;
  2057. } // SaveCustomResSettings
  2058. BOOL
  2059. pWriteResDesRangeToForced(
  2060. IN LOG_CONF ForcedLogConf,
  2061. IN RESOURCEID ResType,
  2062. IN ULONG RangeIndex,
  2063. IN RES_DES RD, OPTIONAL
  2064. IN LPBYTE ResDesData, OPTIONAL
  2065. IN HMACHINE hMachine OPTIONAL
  2066. )
  2067. {
  2068. RES_DES ResDes;
  2069. ULONG ulSize;
  2070. LPBYTE pData = NULL;
  2071. BOOL Success = FALSE;
  2072. if ((RD == 0) && (ResDesData == NULL)) {
  2073. return FALSE; // pass in data or handle!
  2074. }
  2075. if (!ResDesData) {
  2076. if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, RD, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2077. return FALSE;
  2078. }
  2079. pData = MyMalloc(ulSize);
  2080. if (pData == NULL) {
  2081. return FALSE;
  2082. }
  2083. if (CM_Get_Res_Des_Data_Ex(RD, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2084. MyFree(pData);
  2085. return FALSE;
  2086. }
  2087. } else {
  2088. pData = ResDesData;
  2089. }
  2090. //
  2091. // convert the first range data into hdr data
  2092. //
  2093. switch (ResType) {
  2094. case ResType_Mem: {
  2095. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
  2096. PMEM_RESOURCE pForced = (PMEM_RESOURCE)MyMalloc(sizeof(MEM_RESOURCE));
  2097. if (!pForced) {
  2098. break;
  2099. }
  2100. pForced->MEM_Header.MD_Count = 0;
  2101. pForced->MEM_Header.MD_Type = MType_Range;
  2102. pForced->MEM_Header.MD_Alloc_Base = pMemData->MEM_Data[RangeIndex].MR_Min;
  2103. pForced->MEM_Header.MD_Alloc_End = pMemData->MEM_Data[RangeIndex].MR_Min +
  2104. pMemData->MEM_Data[RangeIndex].MR_nBytes - 1;
  2105. pForced->MEM_Header.MD_Flags = pMemData->MEM_Data[RangeIndex].MR_Flags;
  2106. pForced->MEM_Header.MD_Reserved = 0;
  2107. Success = CM_Add_Res_Des_Ex(NULL,
  2108. ForcedLogConf,
  2109. ResType_Mem,
  2110. pForced,
  2111. sizeof(MEM_RESOURCE),
  2112. DEVRES_WIDTH_FLAGS,
  2113. hMachine) == CR_SUCCESS;
  2114. MyFree(pForced);
  2115. break;
  2116. }
  2117. case ResType_IO: {
  2118. PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
  2119. PIO_RESOURCE pForced = (PIO_RESOURCE)MyMalloc(sizeof(IO_RESOURCE));
  2120. if (!pForced) {
  2121. break;
  2122. }
  2123. pForced->IO_Header.IOD_Count = 0;
  2124. pForced->IO_Header.IOD_Type = IOType_Range;
  2125. pForced->IO_Header.IOD_Alloc_Base = pIoData->IO_Data[RangeIndex].IOR_Min;
  2126. pForced->IO_Header.IOD_Alloc_End = pIoData->IO_Data[RangeIndex].IOR_Min +
  2127. pIoData->IO_Data[RangeIndex].IOR_nPorts - 1;
  2128. pForced->IO_Header.IOD_DesFlags = pIoData->IO_Data[RangeIndex].IOR_RangeFlags;
  2129. Success = CM_Add_Res_Des_Ex(NULL,
  2130. ForcedLogConf,
  2131. ResType_IO,
  2132. pForced,
  2133. sizeof(IO_RESOURCE),
  2134. DEVRES_WIDTH_FLAGS,
  2135. hMachine) == CR_SUCCESS;
  2136. MyFree(pForced);
  2137. break;
  2138. }
  2139. case ResType_DMA: {
  2140. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
  2141. PDMA_RESOURCE pForced = (PDMA_RESOURCE)MyMalloc(sizeof(DMA_RESOURCE));
  2142. if (!pForced) {
  2143. break;
  2144. }
  2145. pForced->DMA_Header.DD_Count = 0;
  2146. pForced->DMA_Header.DD_Type = DType_Range;
  2147. pForced->DMA_Header.DD_Flags = pDmaData->DMA_Data[RangeIndex].DR_Flags;
  2148. pForced->DMA_Header.DD_Alloc_Chan = pDmaData->DMA_Data[RangeIndex].DR_Min;
  2149. Success = CM_Add_Res_Des_Ex(NULL,
  2150. ForcedLogConf,
  2151. ResType_DMA,
  2152. pForced,
  2153. sizeof(DMA_RESOURCE),
  2154. DEVRES_WIDTH_FLAGS,
  2155. hMachine) == CR_SUCCESS;
  2156. MyFree(pForced);
  2157. break;
  2158. }
  2159. case ResType_IRQ: {
  2160. DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
  2161. DEVRES_PIRQ_RESOURCE pForced = (DEVRES_PIRQ_RESOURCE)MyMalloc(sizeof(DEVRES_IRQ_RESOURCE));
  2162. if (!pForced) {
  2163. break;
  2164. }
  2165. pForced->IRQ_Header.IRQD_Count = 0;
  2166. pForced->IRQ_Header.IRQD_Type = IRQType_Range;
  2167. pForced->IRQ_Header.IRQD_Flags = pIrqData->IRQ_Data[RangeIndex].IRQR_Flags;
  2168. pForced->IRQ_Header.IRQD_Alloc_Num = pIrqData->IRQ_Data[RangeIndex].IRQR_Min;
  2169. pForced->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1);
  2170. Success = CM_Add_Res_Des_Ex(NULL,
  2171. ForcedLogConf,
  2172. ResType_IRQ,
  2173. pForced,
  2174. sizeof(DEVRES_IRQ_RESOURCE),
  2175. DEVRES_WIDTH_FLAGS,
  2176. hMachine) == CR_SUCCESS;
  2177. MyFree(pForced);
  2178. break;
  2179. }
  2180. case ResType_BusNumber: {
  2181. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)pData;
  2182. PBUSNUMBER_RESOURCE pForced = (PBUSNUMBER_RESOURCE)MyMalloc(sizeof(BUSNUMBER_RESOURCE));
  2183. if (!pForced) {
  2184. break;
  2185. }
  2186. pForced->BusNumber_Header.BUSD_Count = 0;
  2187. pForced->BusNumber_Header.BUSD_Type = BusNumberType_Range;
  2188. pForced->BusNumber_Header.BUSD_Flags = pBusData->BusNumber_Data[RangeIndex].BUSR_Flags;
  2189. pForced->BusNumber_Header.BUSD_Alloc_Base = pBusData->BusNumber_Data[RangeIndex].BUSR_Min;
  2190. pForced->BusNumber_Header.BUSD_Alloc_End = pBusData->BusNumber_Data[RangeIndex].BUSR_Min +
  2191. pBusData->BusNumber_Data[RangeIndex].BUSR_nBusNumbers;
  2192. Success = CM_Add_Res_Des_Ex(NULL,
  2193. ForcedLogConf,
  2194. ResType_BusNumber,
  2195. pForced,
  2196. sizeof(BUSNUMBER_RESOURCE),
  2197. DEVRES_WIDTH_FLAGS,
  2198. hMachine) == CR_SUCCESS;
  2199. MyFree(pForced);
  2200. break;
  2201. }
  2202. case ResType_DevicePrivate: {
  2203. PDEVPRIVATE_RESOURCE pPrvData = (PDEVPRIVATE_RESOURCE)pData;
  2204. PDEVPRIVATE_RESOURCE pForced = (PDEVPRIVATE_RESOURCE)MyMalloc(sizeof(DEVPRIVATE_RESOURCE));
  2205. if (!pForced) {
  2206. break;
  2207. }
  2208. pForced->PRV_Header.PD_Count = 0;
  2209. pForced->PRV_Header.PD_Type = PType_Range;
  2210. pForced->PRV_Header.PD_Data1 = pPrvData->PRV_Data[RangeIndex].PR_Data1;
  2211. pForced->PRV_Header.PD_Data2 = pPrvData->PRV_Data[RangeIndex].PR_Data2;
  2212. pForced->PRV_Header.PD_Data3 = pPrvData->PRV_Data[RangeIndex].PR_Data3;
  2213. pForced->PRV_Header.PD_Flags = 0;
  2214. Success = CM_Add_Res_Des_Ex(NULL,
  2215. ForcedLogConf,
  2216. ResType_DevicePrivate,
  2217. pForced,
  2218. sizeof(DEVPRIVATE_RESOURCE),
  2219. DEVRES_WIDTH_FLAGS,
  2220. hMachine) == CR_SUCCESS;
  2221. MyFree(pForced);
  2222. break;
  2223. }
  2224. case ResType_PcCardConfig: {
  2225. Success = CM_Add_Res_Des_Ex(NULL,
  2226. ForcedLogConf,
  2227. ResType_PcCardConfig,
  2228. pData,
  2229. sizeof(PCCARD_RESOURCE),
  2230. DEVRES_WIDTH_FLAGS,
  2231. hMachine);
  2232. break;
  2233. }
  2234. }
  2235. if (pData != ResDesData) {
  2236. MyFree(pData);
  2237. }
  2238. return Success;
  2239. } // WriteResDesRangeToForced
  2240. BOOL
  2241. pWriteValuesToForced(
  2242. IN LOG_CONF ForcedLogConf,
  2243. IN RESOURCEID ResType,
  2244. IN ULONG RangeIndex,
  2245. IN RES_DES RD,
  2246. IN ULONG64 ulValue,
  2247. IN ULONG64 ulLen,
  2248. IN ULONG64 ulEnd,
  2249. IN HMACHINE hMachine
  2250. )
  2251. {
  2252. RES_DES ResDes;
  2253. ULONG ulSize;
  2254. LPBYTE pData = NULL;
  2255. BOOL Success = FALSE;
  2256. if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, RD, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2257. return FALSE;
  2258. }
  2259. pData = MyMalloc(ulSize);
  2260. if (pData == NULL) {
  2261. return FALSE;
  2262. }
  2263. if (CM_Get_Res_Des_Data_Ex(RD, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2264. MyFree(pData);
  2265. return FALSE;
  2266. }
  2267. //
  2268. // convert the first range data into hdr data
  2269. //
  2270. switch (ResType) {
  2271. case ResType_Mem: {
  2272. PMEM_RESOURCE pMemData = (PMEM_RESOURCE)pData;
  2273. PMEM_RESOURCE pForced = (PMEM_RESOURCE)MyMalloc(sizeof(MEM_RESOURCE));
  2274. if (!pForced) {
  2275. break;
  2276. }
  2277. pForced->MEM_Header.MD_Count = 0;
  2278. pForced->MEM_Header.MD_Type = MType_Range;
  2279. pForced->MEM_Header.MD_Alloc_Base = ulValue;
  2280. pForced->MEM_Header.MD_Alloc_End = ulEnd;
  2281. pForced->MEM_Header.MD_Flags = pMemData->MEM_Data[RangeIndex].MR_Flags;
  2282. pForced->MEM_Header.MD_Reserved = 0;
  2283. Success = CM_Add_Res_Des_Ex(NULL,
  2284. ForcedLogConf,
  2285. ResType_Mem,
  2286. pForced,
  2287. sizeof(MEM_RESOURCE),
  2288. DEVRES_WIDTH_FLAGS,
  2289. hMachine) == CR_SUCCESS;
  2290. MyFree(pForced);
  2291. break;
  2292. }
  2293. case ResType_IO: {
  2294. PIO_RESOURCE pIoData = (PIO_RESOURCE)pData;
  2295. PIO_RESOURCE pForced = (PIO_RESOURCE)MyMalloc(sizeof(IO_RESOURCE));
  2296. if (!pForced) {
  2297. break;
  2298. }
  2299. pForced->IO_Header.IOD_Count = 0;
  2300. pForced->IO_Header.IOD_Type = IOType_Range;
  2301. pForced->IO_Header.IOD_Alloc_Base = ulValue;
  2302. pForced->IO_Header.IOD_Alloc_End = ulEnd;
  2303. pForced->IO_Header.IOD_DesFlags = pIoData->IO_Data[RangeIndex].IOR_RangeFlags;
  2304. Success = CM_Add_Res_Des_Ex(NULL,
  2305. ForcedLogConf,
  2306. ResType_IO,
  2307. pForced,
  2308. sizeof(IO_RESOURCE),
  2309. DEVRES_WIDTH_FLAGS,
  2310. hMachine) == CR_SUCCESS;
  2311. MyFree(pForced);
  2312. break;
  2313. }
  2314. case ResType_DMA: {
  2315. PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)pData;
  2316. PDMA_RESOURCE pForced = (PDMA_RESOURCE)MyMalloc(sizeof(DMA_RESOURCE));
  2317. if (!pForced) {
  2318. break;
  2319. }
  2320. pForced->DMA_Header.DD_Count = 0;
  2321. pForced->DMA_Header.DD_Type = DType_Range;
  2322. pForced->DMA_Header.DD_Flags = pDmaData->DMA_Data[RangeIndex].DR_Flags;
  2323. pForced->DMA_Header.DD_Alloc_Chan = (ULONG)ulValue;
  2324. Success = CM_Add_Res_Des_Ex(NULL,
  2325. ForcedLogConf,
  2326. ResType_DMA,
  2327. pForced,
  2328. sizeof(DMA_RESOURCE),
  2329. DEVRES_WIDTH_FLAGS,
  2330. hMachine) == CR_SUCCESS;
  2331. MyFree(pForced);
  2332. break;
  2333. }
  2334. case ResType_IRQ: {
  2335. DEVRES_PIRQ_RESOURCE pIrqData = (DEVRES_PIRQ_RESOURCE)pData;
  2336. DEVRES_PIRQ_RESOURCE pForced = (DEVRES_PIRQ_RESOURCE)MyMalloc(sizeof(DEVRES_IRQ_RESOURCE));
  2337. if (!pForced) {
  2338. break;
  2339. }
  2340. pForced->IRQ_Header.IRQD_Count = 0;
  2341. pForced->IRQ_Header.IRQD_Type = IRQType_Range;
  2342. pForced->IRQ_Header.IRQD_Flags = pIrqData->IRQ_Data[RangeIndex].IRQR_Flags;
  2343. pForced->IRQ_Header.IRQD_Alloc_Num = (ULONG)ulValue;
  2344. pForced->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1);
  2345. Success = CM_Add_Res_Des_Ex(NULL,
  2346. ForcedLogConf,
  2347. ResType_IRQ,
  2348. pForced,
  2349. sizeof(DEVRES_IRQ_RESOURCE),
  2350. DEVRES_WIDTH_FLAGS,
  2351. hMachine) == CR_SUCCESS;
  2352. MyFree(pForced);
  2353. break;
  2354. }
  2355. case ResType_BusNumber: {
  2356. PBUSNUMBER_RESOURCE pBusData = (PBUSNUMBER_RESOURCE)pData;
  2357. PBUSNUMBER_RESOURCE pForced = (PBUSNUMBER_RESOURCE)MyMalloc(sizeof(BUSNUMBER_RESOURCE));
  2358. if (!pForced) {
  2359. break;
  2360. }
  2361. pForced->BusNumber_Header.BUSD_Count = 0;
  2362. pForced->BusNumber_Header.BUSD_Type = BusNumberType_Range;
  2363. pForced->BusNumber_Header.BUSD_Flags = pBusData->BusNumber_Data[RangeIndex].BUSR_Flags;
  2364. pForced->BusNumber_Header.BUSD_Alloc_Base = (ULONG)ulValue;
  2365. pForced->BusNumber_Header.BUSD_Alloc_End = (ULONG)ulEnd;
  2366. Success = CM_Add_Res_Des_Ex(NULL,
  2367. ForcedLogConf,
  2368. ResType_BusNumber,
  2369. pForced,
  2370. sizeof(BUSNUMBER_RESOURCE),
  2371. DEVRES_WIDTH_FLAGS,
  2372. hMachine) == CR_SUCCESS;
  2373. MyFree(pForced);
  2374. break;
  2375. }
  2376. case ResType_DevicePrivate: {
  2377. break;
  2378. }
  2379. case ResType_PcCardConfig: {
  2380. break;
  2381. }
  2382. }
  2383. if (pData) {
  2384. MyFree(pData);
  2385. }
  2386. return Success;
  2387. } // WriteValuesToForced
  2388. BOOL
  2389. MakeResourceData(
  2390. OUT LPBYTE *ppResourceData,
  2391. OUT PULONG pulSize,
  2392. IN RESOURCEID ResType,
  2393. IN ULONG64 ulValue,
  2394. IN ULONG64 ulLen,
  2395. IN ULONG ulFlags
  2396. )
  2397. {
  2398. BOOL bStatus = TRUE;
  2399. try {
  2400. switch (ResType) {
  2401. case ResType_Mem: {
  2402. PMEM_RESOURCE p;
  2403. *pulSize = sizeof(MEM_RESOURCE);
  2404. if (ppResourceData) {
  2405. *ppResourceData = MyMalloc(*pulSize);
  2406. p = (PMEM_RESOURCE)(*ppResourceData);
  2407. if (!p) {
  2408. bStatus = FALSE;
  2409. break;
  2410. }
  2411. p->MEM_Header.MD_Count = 0;
  2412. p->MEM_Header.MD_Type = MType_Range;
  2413. p->MEM_Header.MD_Alloc_Base = ulValue;
  2414. p->MEM_Header.MD_Alloc_End = ulValue + ulLen - 1;
  2415. p->MEM_Header.MD_Flags = ulFlags;
  2416. p->MEM_Header.MD_Reserved = 0;
  2417. }
  2418. break;
  2419. }
  2420. case ResType_IO: {
  2421. PIO_RESOURCE p;
  2422. *pulSize = sizeof(IO_RESOURCE);
  2423. if (ppResourceData) {
  2424. *ppResourceData = MyMalloc(*pulSize);
  2425. p = (PIO_RESOURCE)(*ppResourceData);
  2426. if (!p) {
  2427. bStatus = FALSE;
  2428. break;
  2429. }
  2430. p->IO_Header.IOD_Count = 0;
  2431. p->IO_Header.IOD_Type = IOType_Range;
  2432. p->IO_Header.IOD_Alloc_Base = ulValue;
  2433. p->IO_Header.IOD_Alloc_End = ulValue + ulLen - 1;
  2434. p->IO_Header.IOD_DesFlags = ulFlags;
  2435. }
  2436. break;
  2437. }
  2438. case ResType_DMA: {
  2439. PDMA_RESOURCE p;
  2440. *pulSize = sizeof(DMA_RESOURCE);
  2441. if (ppResourceData) {
  2442. *ppResourceData = MyMalloc(*pulSize);
  2443. p = (PDMA_RESOURCE)(*ppResourceData);
  2444. if (!p) {
  2445. bStatus = FALSE;
  2446. break;
  2447. }
  2448. p->DMA_Header.DD_Count = 0;
  2449. p->DMA_Header.DD_Type = DType_Range;
  2450. p->DMA_Header.DD_Flags = ulFlags;
  2451. p->DMA_Header.DD_Alloc_Chan = (ULONG)ulValue;
  2452. }
  2453. break;
  2454. }
  2455. case ResType_IRQ: {
  2456. DEVRES_PIRQ_RESOURCE p;
  2457. *pulSize = sizeof(DEVRES_IRQ_RESOURCE);
  2458. if (ppResourceData) {
  2459. *ppResourceData = MyMalloc(*pulSize);
  2460. p = (DEVRES_PIRQ_RESOURCE)(*ppResourceData);
  2461. if (!p) {
  2462. bStatus = FALSE;
  2463. break;
  2464. }
  2465. p->IRQ_Header.IRQD_Count = 0;
  2466. p->IRQ_Header.IRQD_Type = IRQType_Range;
  2467. p->IRQ_Header.IRQD_Flags = ulFlags;
  2468. p->IRQ_Header.IRQD_Alloc_Num = (ULONG)ulValue;
  2469. p->IRQ_Header.IRQD_Affinity = (DEVRES_AFFINITY)(-1); // for any processor
  2470. }
  2471. break;
  2472. }
  2473. default:
  2474. //
  2475. // ResTypeEditable or ResType_MAX may be wrong if this ASSERT's
  2476. //
  2477. MYASSERT(FALSE);
  2478. bStatus = FALSE;
  2479. }
  2480. } except(EXCEPTION_EXECUTE_HANDLER) {
  2481. bStatus = FALSE;
  2482. }
  2483. return bStatus;
  2484. } // MakeResourceData
  2485. BOOL
  2486. pShowWindow(
  2487. IN HWND hWnd,
  2488. IN int nShow
  2489. )
  2490. /*++
  2491. Routine Description:
  2492. A variation of ShowWindow that enables/disables window
  2493. Arguments:
  2494. (See ShowWindow)
  2495. hWnd - handle of window to show
  2496. nShow - typically SW_HIDE or SW_SHOW
  2497. Return Value:
  2498. success status of ShowWindow
  2499. --*/
  2500. {
  2501. EnableWindow(hWnd,nShow!=SW_HIDE);
  2502. return ShowWindow(hWnd,nShow);
  2503. }
  2504. BOOL
  2505. pEnableWindow(
  2506. IN HWND hWnd,
  2507. IN BOOL Enable
  2508. )
  2509. /*++
  2510. Routine Description:
  2511. A variation of EnableWindow that only enables a window if it is visible
  2512. Arguments:
  2513. (See EnableWindow)
  2514. hWnd - handle of window to enable/disable
  2515. Enable - TRUE enables window (if window visible) FALSE disables window
  2516. Return Value:
  2517. success status of EnableWindow
  2518. --*/
  2519. {
  2520. //
  2521. // I had to use GetWindowLong, as IsWindowVisible also checks parent flag
  2522. // and parent is hidden until dialog is initialized
  2523. //
  2524. if((GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE) == FALSE) {
  2525. Enable = FALSE;
  2526. }
  2527. return EnableWindow(hWnd,Enable);
  2528. }
  2529. BOOL
  2530. pGetResDesDataList(
  2531. IN LOG_CONF LogConf,
  2532. IN OUT PRESDES_ENTRY *pResList,
  2533. IN BOOL bArbitratedOnly,
  2534. IN HMACHINE hMachine
  2535. )
  2536. /*++
  2537. Routine Description:
  2538. Creates a list of resource descriptors for further processing
  2539. Arguments:
  2540. LogConf - log config of interest
  2541. pResList - list out
  2542. bArbitratedOnly - filter out non-arbitrated resources
  2543. hMachine - machine that LogConf is on
  2544. Return Value:
  2545. None.
  2546. --*/
  2547. {
  2548. BOOL bStatus = TRUE;
  2549. CONFIGRET Status = CR_SUCCESS;
  2550. PRESDES_ENTRY pHead = NULL, pEntry = NULL, pPrevious = NULL, pTemp = NULL;
  2551. RES_DES ResDes;
  2552. RESOURCEID ResType;
  2553. ULONG ulSize;
  2554. LPBYTE pData = NULL;
  2555. //
  2556. // Retrieve each res des in this log conf
  2557. //
  2558. Status = CM_Get_Next_Res_Des_Ex(&ResDes, LogConf, ResType_All, &ResType, 0,hMachine);
  2559. while (Status == CR_SUCCESS) {
  2560. if (bArbitratedOnly && (ResType <= ResType_None || ResType > ResType_MAX)) {
  2561. goto NextResDes;
  2562. }
  2563. if (bArbitratedOnly && ResTypeEditable[ResType] == FALSE) {
  2564. goto NextResDes;
  2565. }
  2566. if (CM_Get_Res_Des_Data_Size_Ex(&ulSize, ResDes, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2567. CM_Free_Res_Des_Handle(ResDes);
  2568. bStatus = FALSE;
  2569. goto Clean0;
  2570. }
  2571. if (ulSize>0) {
  2572. pData = MyMalloc(ulSize);
  2573. if (pData == NULL) {
  2574. CM_Free_Res_Des_Handle(ResDes);
  2575. bStatus = FALSE;
  2576. goto Clean0;
  2577. }
  2578. if (CM_Get_Res_Des_Data_Ex(ResDes, pData, ulSize, DEVRES_WIDTH_FLAGS,hMachine) != CR_SUCCESS) {
  2579. CM_Free_Res_Des_Handle(ResDes);
  2580. MyFree(pData);
  2581. bStatus = FALSE;
  2582. goto Clean0;
  2583. }
  2584. } else {
  2585. pData = NULL;
  2586. }
  2587. //
  2588. // Allocate a node for this res des and attach it to the list
  2589. //
  2590. pEntry = MyMalloc(sizeof(RESDES_ENTRY));
  2591. if (pEntry == NULL) {
  2592. CM_Free_Res_Des_Handle(ResDes);
  2593. MyFree(pData);
  2594. bStatus = FALSE;
  2595. goto Clean0;
  2596. }
  2597. pEntry->ResDesData = pData;
  2598. pEntry->ResDesType = ResType;
  2599. pEntry->ResDesDataSize = ulSize;
  2600. pEntry->ResDesHandle = ResDes;
  2601. pEntry->Next = NULL;
  2602. pEntry->CrossLink = NULL;
  2603. if (!pHead) {
  2604. pHead = pEntry; // first entry
  2605. }
  2606. if (pPrevious) {
  2607. pPrevious->Next = pEntry; // attach to previous entry
  2608. }
  2609. pPrevious = pEntry;
  2610. //
  2611. // Get next res des in LogConf
  2612. //
  2613. NextResDes:
  2614. Status = CM_Get_Next_Res_Des_Ex(&ResDes, ResDes, ResType_All, &ResType, 0,hMachine);
  2615. }
  2616. bStatus = TRUE;
  2617. Clean0:
  2618. if (!bStatus) {
  2619. pDeleteResDesDataList(pHead);
  2620. } else {
  2621. *pResList = pHead;
  2622. }
  2623. return bStatus;
  2624. } // GetResDesDataList
  2625. VOID
  2626. pDeleteResDesDataList(
  2627. IN PRESDES_ENTRY pResList
  2628. )
  2629. /*++
  2630. Routine Description:
  2631. Deletes memory used by RESDES list
  2632. Arguments:
  2633. pResList - list returned by GetResDesDataList
  2634. Return Value:
  2635. None.
  2636. --*/
  2637. {
  2638. PRESDES_ENTRY pTemp;
  2639. while (pResList) {
  2640. pTemp = pResList;
  2641. pResList = (PRESDES_ENTRY)pResList->Next;
  2642. if (pTemp->ResDesData) {
  2643. MyFree(pTemp->ResDesData);
  2644. }
  2645. if (pTemp->ResDesHandle) {
  2646. CM_Free_Res_Des_Handle(pTemp->ResDesHandle);
  2647. }
  2648. MyFree(pTemp);
  2649. }
  2650. }
  2651. VOID
  2652. pHideAllControls(
  2653. IN LPDMPROP_DATA lpdmpd
  2654. )
  2655. /*++
  2656. Routine Description:
  2657. Hide (and disable) all controls - start off with a clean slate
  2658. Only Icon & device description will be visible
  2659. Arguments:
  2660. hDlg = dialog handle of controls
  2661. lpdmpd = property data
  2662. Return Value:
  2663. none
  2664. --*/
  2665. {
  2666. HWND hDlg = lpdmpd->hDlg;
  2667. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_HIDE);
  2668. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
  2669. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_HIDE);
  2670. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_HIDE);
  2671. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
  2672. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
  2673. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
  2674. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
  2675. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
  2676. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
  2677. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT), SW_HIDE);
  2678. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT_DESC), SW_HIDE);
  2679. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_HIDE);
  2680. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_HIDE);
  2681. lpdmpd->dwFlags |= DMPROP_FLAG_VIEWONLYRES;
  2682. }
  2683. VOID
  2684. pShowViewNoResources(
  2685. IN LPDMPROP_DATA lpdmpd
  2686. )
  2687. /*++
  2688. Routine Description:
  2689. Show page indicating this device has no resources
  2690. Arguments:
  2691. hDlg = dialog handle of controls
  2692. lpdmpd = property data
  2693. Return Value:
  2694. none
  2695. --*/
  2696. {
  2697. HWND hDlg = lpdmpd->hDlg;
  2698. TCHAR szString[MAX_PATH];
  2699. pHideAllControls(lpdmpd); // all hidden and disabled
  2700. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_SHOW); // show and enable text
  2701. LoadString(MyDllModuleHandle, IDS_DEVRES_NO_RESOURCES, szString, MAX_PATH);
  2702. SetDlgItemText(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT, szString);
  2703. }
  2704. BOOL
  2705. pShowViewMFReadOnly(
  2706. IN LPDMPROP_DATA lpdmpd,
  2707. IN BOOL HideIfProb
  2708. )
  2709. /*++
  2710. Routine Description:
  2711. Show page apropriate for multifunction card that cannot be edited
  2712. Resource settings are visible
  2713. Arguments:
  2714. hDlg = dialog handle of controls
  2715. lpdmpd = property data
  2716. Return Value:
  2717. none
  2718. --*/
  2719. {
  2720. TCHAR szString[MAX_PATH];
  2721. DEVNODE dnParent;
  2722. ULONG ulSize;
  2723. HWND hDlg = lpdmpd->hDlg;
  2724. HMACHINE hMachine = pGetMachine(lpdmpd);
  2725. pHideAllControls(lpdmpd); // all hidden and disabled
  2726. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW); // show config information
  2727. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW); // show
  2728. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
  2729. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
  2730. //
  2731. // indicate we cannot change as it's multi-function
  2732. //
  2733. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW);
  2734. if (LoadString(MyDllModuleHandle, IDS_DEVRES_NO_CHANGE_MF, szString, MAX_PATH)) {
  2735. SetDlgItemText(hDlg, IDC_DEVRES_NO_CHANGE_TEXT, szString);
  2736. }
  2737. //
  2738. // for parent description
  2739. //
  2740. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT), SW_SHOW);
  2741. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MFPARENT_DESC), SW_SHOW);
  2742. //
  2743. // Get the Parent's Description.
  2744. //
  2745. LoadString(MyDllModuleHandle, IDS_DEVNAME_UNK, szString, MAX_PATH);
  2746. if (lpdmpd->lpdi->DevInst) {
  2747. if (CM_Get_Parent_Ex(&dnParent, lpdmpd->lpdi->DevInst, 0,hMachine)
  2748. == CR_SUCCESS) {
  2749. //
  2750. // First, try to retrieve friendly name, then fall back to device description.
  2751. //
  2752. ulSize = MAX_PATH * sizeof(TCHAR);
  2753. if(CM_Get_DevNode_Registry_Property_Ex(dnParent, CM_DRP_FRIENDLYNAME,
  2754. NULL, szString, &ulSize, 0,hMachine) != CR_SUCCESS) {
  2755. ulSize = MAX_PATH * sizeof(TCHAR);
  2756. CM_Get_DevNode_Registry_Property_Ex(dnParent, CM_DRP_DEVICEDESC,
  2757. NULL, szString, &ulSize, 0,hMachine);
  2758. }
  2759. }
  2760. }
  2761. SetDlgItemText(hDlg, IDC_DEVRES_MFPARENT_DESC, szString);
  2762. //
  2763. // load and display current config (if any)
  2764. // return FALSE if no current config
  2765. //
  2766. return pLoadCurrentConfig(lpdmpd,HideIfProb);
  2767. }
  2768. BOOL
  2769. pShowViewReadOnly(
  2770. IN LPDMPROP_DATA lpdmpd,
  2771. IN BOOL HideIfProb
  2772. )
  2773. /*++
  2774. Routine Description:
  2775. Show page of resources, don't allow editing, don't show editing controls
  2776. Arguments:
  2777. hDlg = dialog handle of controls
  2778. lpdmpd = property data
  2779. Return Value:
  2780. none
  2781. --*/
  2782. {
  2783. HWND hDlg = lpdmpd->hDlg;
  2784. pHideAllControls(lpdmpd); // all hidden and disabled
  2785. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW); // show
  2786. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), FALSE);
  2787. ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW); // shown disabled
  2788. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), FALSE);
  2789. ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_SHOW); // shown disabled
  2790. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), FALSE);
  2791. ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_SHOW); // shown disabled
  2792. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
  2793. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
  2794. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
  2795. //
  2796. // will indicate if we're showing system settings or forced settings
  2797. //
  2798. CheckDlgButton(hDlg, IDC_DEVRES_USESYSSETTINGS, (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS ) ? TRUE : FALSE);
  2799. //
  2800. // load and display current config (if any)
  2801. // return FALSE if no current config
  2802. //
  2803. return pLoadCurrentConfig(lpdmpd,HideIfProb);
  2804. }
  2805. VOID
  2806. pShowViewNoAlloc(
  2807. IN LPDMPROP_DATA lpdmpd
  2808. )
  2809. /*++
  2810. Routine Description:
  2811. Modify the middle part of the control to indicate there is a problem (and there isn't much we can do about it)
  2812. Arguments:
  2813. hDlg = dialog handle of controls
  2814. lpdmpd = property data
  2815. Return Value:
  2816. none
  2817. --*/
  2818. {
  2819. HWND hDlg = lpdmpd->hDlg;
  2820. //
  2821. // hide all middle controls
  2822. //
  2823. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
  2824. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
  2825. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
  2826. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
  2827. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
  2828. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
  2829. lpdmpd->dwFlags |= DMPROP_FLAG_VIEWONLYRES;
  2830. //pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW); // this may say why
  2831. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
  2832. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_HIDE); // no alloc, so hide this header & textbox
  2833. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_HIDE);
  2834. }
  2835. VOID
  2836. pShowViewNeedForced(
  2837. IN LPDMPROP_DATA lpdmpd
  2838. )
  2839. /*++
  2840. Routine Description:
  2841. Modify the middle part of the control to indicate a forced config is required
  2842. Arguments:
  2843. hDlg = dialog handle of controls
  2844. lpdmpd = property data
  2845. Return Value:
  2846. none
  2847. --*/
  2848. {
  2849. HWND hDlg = lpdmpd->hDlg;
  2850. pShowViewNoAlloc(lpdmpd);
  2851. //
  2852. // show what we need for make forced config
  2853. //
  2854. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT), SW_SHOW); // this may say why
  2855. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_SHOW);
  2856. }
  2857. VOID
  2858. pShowViewAllEdit(
  2859. IN LPDMPROP_DATA lpdmpd
  2860. )
  2861. /*++
  2862. Routine Description:
  2863. Allow editing
  2864. Arguments:
  2865. lpdmpd = property data
  2866. Return Value:
  2867. none
  2868. --*/
  2869. {
  2870. HWND hDlg = lpdmpd->hDlg;
  2871. //
  2872. // show middle controls for editing
  2873. //
  2874. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_SHOW);
  2875. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_SHOW);
  2876. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_CHANGE_TEXT ), SW_HIDE);
  2877. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_SHOW);
  2878. ShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_SHOW); // shown, but disabled
  2879. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), FALSE);
  2880. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_MAKEFORCED), SW_HIDE);
  2881. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTDEVTEXT), SW_SHOW); // show conflict information space
  2882. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CONFLICTINFOLIST), SW_SHOW);
  2883. pShowUpdateEdit(lpdmpd);
  2884. }
  2885. VOID
  2886. pShowUpdateEdit(
  2887. IN LPDMPROP_DATA lpdmpd
  2888. )
  2889. /*++
  2890. Routine Description:
  2891. Allow editing
  2892. Arguments:
  2893. lpdmpd = property data
  2894. Return Value:
  2895. none
  2896. --*/
  2897. {
  2898. HWND hDlg = lpdmpd->hDlg;
  2899. //
  2900. // modify editing status - we can edit
  2901. //
  2902. lpdmpd->dwFlags &= ~DMPROP_FLAG_VIEWONLYRES;
  2903. if(lpdmpd->dwFlags & DMPROP_FLAG_FORCEDONLY) {
  2904. //
  2905. // in this case, we will never be able to use system settings
  2906. //
  2907. lpdmpd->dwFlags &= ~ DMPROP_FLAG_USESYSSETTINGS;
  2908. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), FALSE);
  2909. }
  2910. //
  2911. // indicate if it's system settings or not
  2912. //
  2913. CheckDlgButton(hDlg, IDC_DEVRES_USESYSSETTINGS,
  2914. (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?TRUE:FALSE);
  2915. //
  2916. // we can change logconfiglist if it's not system settings
  2917. //
  2918. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?FALSE:TRUE);
  2919. EnableWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)?FALSE:TRUE);
  2920. //
  2921. // change "Change Settings" button
  2922. //
  2923. pCheckEnableResourceChange(lpdmpd);
  2924. }
  2925. BOOL
  2926. pLoadCurrentConfig(
  2927. IN LPDMPROP_DATA lpdmpd,
  2928. BOOL HideIfProb
  2929. )
  2930. /*++
  2931. Routine Description:
  2932. Modify the top part, to show current configuration, if any
  2933. Arguments:
  2934. hDlg = dialog handle of controls
  2935. lpdmpd = property data
  2936. Return Value:
  2937. TRUE if we're showing current config
  2938. --*/
  2939. {
  2940. TCHAR szMessage[MAX_PATH];
  2941. ULONG Problem;
  2942. ULONG Status;
  2943. HWND hDlg = lpdmpd->hDlg;
  2944. HMACHINE hMachine = pGetMachine(lpdmpd);
  2945. BOOL DoLoadConfig = FALSE;
  2946. lpdmpd->SelectedLC = 0;
  2947. lpdmpd->SelectedLCType = lpdmpd->CurrentLCType;
  2948. if (lpdmpd->CurrentLC != 0) {
  2949. DoLoadConfig = TRUE;
  2950. }
  2951. if(HideIfProb && (lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
  2952. //
  2953. // if there's a problem and HideIfProb is TRUE, don't bother showing current config
  2954. //
  2955. DoLoadConfig = FALSE;
  2956. }
  2957. if (DoLoadConfig) {
  2958. //
  2959. // load in current configuration
  2960. //
  2961. pLoadConfig(lpdmpd,lpdmpd->CurrentLC,lpdmpd->CurrentLCType);
  2962. return TRUE;
  2963. }
  2964. //
  2965. // case where there is no suitable configuration
  2966. //
  2967. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
  2968. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_HIDE);
  2969. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LCTEXT), SW_HIDE);
  2970. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_LOGCONFIGLIST), SW_HIDE);
  2971. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_USESYSSETTINGS), SW_HIDE);
  2972. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_CHANGE), SW_HIDE);
  2973. pShowViewNoAlloc(lpdmpd);
  2974. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_SHOW);
  2975. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_SHOW);
  2976. //
  2977. // explain why there is a problem
  2978. // goes into NOALLOCTEXT
  2979. //
  2980. LoadString(MyDllModuleHandle, IDS_DEVRES_NOALLOC_PROBLEM, szMessage, MAX_PATH);
  2981. //
  2982. // consider being more descriptive
  2983. //
  2984. if ((lpdmpd->lpdi->DevInst==0)
  2985. || (CM_Get_DevNode_Status_Ex(&Status, &Problem, lpdmpd->lpdi->DevInst,
  2986. 0,hMachine) != CR_SUCCESS)) {
  2987. Status = 0;
  2988. Problem = 0;
  2989. }
  2990. if ((Status & DN_HAS_PROBLEM)!=0) {
  2991. switch (Problem) {
  2992. case CM_PROB_DISABLED:
  2993. case CM_PROB_HARDWARE_DISABLED:
  2994. LoadString(MyDllModuleHandle, IDS_DEVRES_NOALLOC_DISABLED, szMessage, MAX_PATH);
  2995. break;
  2996. case CM_PROB_NORMAL_CONFLICT:
  2997. LoadString(MyDllModuleHandle, IDS_DEVRES_NORMAL_CONFLICT, szMessage, MAX_PATH);
  2998. break;
  2999. default:
  3000. break;
  3001. }
  3002. }
  3003. SetDlgItemText(hDlg, IDC_DEVRES_NOALLOCTEXT, szMessage);
  3004. return FALSE; // display in NoAlloc state
  3005. }
  3006. BOOL
  3007. pConfigHasNoAlternates(
  3008. LPDMPROP_DATA lpdmpd,
  3009. LOG_CONF testLC
  3010. )
  3011. /*++
  3012. Routine Description:
  3013. A Basic config could be restrictive "these are the set of resources to use"
  3014. This determines if the basic config passed is such a config
  3015. Arguments:
  3016. testLC = basic config to test
  3017. Return Value:
  3018. TRUE if it's a singular config
  3019. --*/
  3020. {
  3021. HMACHINE hMachine = NULL;
  3022. PRESDES_ENTRY pConfigValues = NULL;
  3023. PRESDES_ENTRY pValue = NULL;
  3024. BOOL bSuccess = TRUE;
  3025. ULONG64 ulValue = 0, ulLen = 0, ulEnd = 0;
  3026. ULONG ulFlags = 0;
  3027. PGENERIC_RESOURCE pGenRes = NULL;
  3028. hMachine = pGetMachine(lpdmpd);
  3029. pGetResDesDataList(testLC, &pConfigValues, TRUE, hMachine); // arbitratable resources
  3030. for(pValue = pConfigValues;pValue;pValue = pValue->Next) {
  3031. //
  3032. // is this a singular value?
  3033. //
  3034. pGenRes = (PGENERIC_RESOURCE)(pValue->ResDesData);
  3035. if(pGenRes->GENERIC_Header.GENERIC_Count != 1) {
  3036. //
  3037. // more than one entry - not singular
  3038. //
  3039. bSuccess = FALSE;
  3040. break;
  3041. }
  3042. pGetRangeValues(pValue->ResDesData, pValue->ResDesType, 0, &ulValue, &ulLen, &ulEnd, NULL, &ulFlags);
  3043. if (ulValue+(ulLen-1) != ulEnd) {
  3044. //
  3045. // not singular
  3046. //
  3047. bSuccess = FALSE;
  3048. break;
  3049. }
  3050. }
  3051. pDeleteResDesDataList(pConfigValues);
  3052. return bSuccess;
  3053. }
  3054. BOOL
  3055. pLoadConfig(
  3056. LPDMPROP_DATA lpdmpd,
  3057. LOG_CONF forceLC,
  3058. ULONG forceLCType
  3059. )
  3060. /*++
  3061. Routine Description:
  3062. Display a configuration
  3063. Arguments:
  3064. hDlg = dialog handle of controls
  3065. lpdmpd = property data
  3066. forceLC = LogConf to display
  3067. forceLCType = type for LogConf
  3068. Return Value:
  3069. TRUE if config loaded
  3070. --*/
  3071. {
  3072. HWND hDlg = lpdmpd->hDlg;
  3073. CONFIGRET Status = CR_SUCCESS;
  3074. HWND hWndList;
  3075. LV_ITEM lviItem;
  3076. TCHAR szTemp[MAX_PATH];
  3077. int iNewItem = 0;
  3078. ULONG ulSize,ulFlags;
  3079. ULONG64 ulValue, ulLen, ulEnd, ulAlign;
  3080. ULONG64 ulMaxMem = 0;
  3081. ULONG ulRange;
  3082. LPBYTE pData = NULL;
  3083. RES_DES ResDes;
  3084. RESOURCEID ResType;
  3085. PITEMDATA pItemData = NULL;
  3086. HMACHINE hMachine = NULL;
  3087. PDEVICE_INFO_SET pDeviceInfoSet;
  3088. BOOL RetCode = FALSE;
  3089. PRESDES_ENTRY pKnownValues = NULL;
  3090. PRESDES_ENTRY pShowValues = NULL;
  3091. PRESDES_ENTRY pShowEntry = NULL;
  3092. BOOL bFixedConfig = FALSE;
  3093. BOOL bNoMatch;
  3094. BOOL bFixed;
  3095. ULONG MatchLevel = NO_LC_MATCH;
  3096. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSTATE), SW_SHOW);
  3097. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NO_RESOURCES_TEXT), SW_HIDE);
  3098. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST), SW_SHOW);
  3099. pShowWindow(GetDlgItem(hDlg, IDC_DEVRES_NOALLOCTEXT), SW_HIDE);
  3100. hWndList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  3101. SendMessage(hWndList, WM_SETREDRAW, (WPARAM)FALSE, 0);
  3102. ListView_DeleteAllItems(hWndList);
  3103. lpdmpd->dwFlags |= DMPROP_FLAG_FIXEDCONFIG; // until we determine there is at least one setting we can edit
  3104. if (forceLC == 0) {
  3105. forceLC = lpdmpd->CurrentLC;
  3106. forceLCType = lpdmpd->CurrentLCType;
  3107. }
  3108. if (forceLC == 0) {
  3109. MYASSERT(FALSE);
  3110. goto Final;
  3111. }
  3112. hMachine = pGetMachine(lpdmpd);
  3113. //
  3114. // setup values that will remain the same each time I add an item
  3115. //
  3116. lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  3117. lviItem.pszText = szTemp; // reuse the szTemp buffer
  3118. lviItem.iSubItem = 0;
  3119. lviItem.iImage = IDI_RESOURCE - IDI_RESOURCEFIRST;
  3120. pGetResDesDataList(forceLC, &pShowValues, TRUE, hMachine); // editable resources
  3121. if (forceLCType == BOOT_LOG_CONF || forceLCType == FORCED_LOG_CONF || forceLCType == ALLOC_LOG_CONF) {
  3122. bFixedConfig = TRUE;
  3123. if (forceLC == lpdmpd->CurrentLC && lpdmpd->MatchingLC != 0) {
  3124. //
  3125. // we're displaying CurrentLC, use flags & resdes's from matching LC where possible
  3126. //
  3127. if (pGetResDesDataList(lpdmpd->MatchingLC, &pKnownValues, TRUE, hMachine)) {
  3128. //
  3129. // match-up currentLC with some matching LC, so we can use flags/ranges from matching LC
  3130. //
  3131. MatchLevel = pMergeResDesDataLists(pShowValues,pKnownValues,NULL);
  3132. }
  3133. }
  3134. } else if (lpdmpd->CurrentLC != 0) {
  3135. //
  3136. // the config we're displaying may allow ranges of values
  3137. // we're going to try and match up what we are displaying to current config
  3138. //
  3139. if (pGetResDesDataList(lpdmpd->CurrentLC, &pKnownValues, TRUE, hMachine)) {
  3140. //
  3141. // try and use current values where possible
  3142. //
  3143. MatchLevel = pMergeResDesDataLists(pKnownValues,pShowValues,NULL);
  3144. }
  3145. }
  3146. pShowEntry = pShowValues;
  3147. while (pShowEntry) {
  3148. bNoMatch = FALSE;
  3149. bFixed = FALSE;
  3150. ResDes = (RES_DES)0;
  3151. ResType = pShowEntry->ResDesType;
  3152. ulRange = 0;
  3153. if (bFixedConfig) {
  3154. //
  3155. // we've got a current config
  3156. //
  3157. pGetHdrValues(pShowEntry->ResDesData, pShowEntry->ResDesType, &ulValue, &ulLen, &ulEnd, &ulFlags);
  3158. if((ResType ==ResType_Mem) && (ulEnd > ulMaxMem)) {
  3159. //
  3160. // base our memory display on the fixed-config only
  3161. //
  3162. ulMaxMem = ulEnd;
  3163. }
  3164. if (pShowEntry->CrossLink) {
  3165. //
  3166. // use range's res-des
  3167. //
  3168. ResDes = pShowEntry->CrossLink->ResDesHandle;
  3169. pShowEntry->CrossLink->ResDesHandle = (RES_DES)0;
  3170. //
  3171. // allow adjustment based on nearest basic config
  3172. //
  3173. pGetMatchingRange(ulValue,ulLen,pShowEntry->CrossLink->ResDesData, pShowEntry->CrossLink->ResDesType,&ulRange,&bFixed,NULL);
  3174. } else {
  3175. //
  3176. // no range res-des
  3177. //
  3178. ResDes = (RES_DES)0;
  3179. //
  3180. // indicate that this is a non-adjustable value
  3181. //
  3182. bFixed = TRUE;
  3183. }
  3184. } else {
  3185. //
  3186. // we've got resource-ranges
  3187. //
  3188. if (pShowEntry->CrossLink) {
  3189. //
  3190. // take current settings from what we merged in
  3191. //
  3192. pGetHdrValues(pShowEntry->CrossLink->ResDesData, pShowEntry->CrossLink->ResDesType, &ulValue, &ulLen, &ulEnd, &ulFlags);
  3193. } else {
  3194. //
  3195. // just take first range
  3196. //
  3197. pGetRangeValues(pShowEntry->ResDesData, pShowEntry->ResDesType, 0, &ulValue, &ulLen, &ulEnd, &ulAlign, &ulFlags);
  3198. }
  3199. //
  3200. // range check if this is a memory resource - find highest memory value
  3201. //
  3202. if(ResType ==ResType_Mem) {
  3203. ULONG64 HighVal;
  3204. ULONG64 HighLen;
  3205. if(LocateClosestValue(pShowEntry->ResDesData, pShowEntry->ResDesType,(ULONG64)(-1),ulLen, 0 ,&HighVal,&HighLen,NULL)) {
  3206. HighVal += HighLen-1;
  3207. if(HighVal > ulMaxMem) {
  3208. ulMaxMem = ulEnd;
  3209. }
  3210. }
  3211. }
  3212. pGetMatchingRange(ulValue,ulLen,pShowEntry->ResDesData, pShowEntry->ResDesType,&ulRange,&bFixed,&ulFlags);
  3213. //
  3214. // use res-des from range
  3215. //
  3216. ResDes = pShowEntry->ResDesHandle;
  3217. pShowEntry->ResDesHandle = (RES_DES)0;
  3218. if (pShowEntry->CrossLink == NULL && bFixed == FALSE) {
  3219. //
  3220. // unknown value
  3221. //
  3222. bNoMatch = TRUE;
  3223. }
  3224. }
  3225. if (ulLen>0) {
  3226. //
  3227. // Write first column text field (uses szTemp, lParam is res type)
  3228. //
  3229. LoadString(MyDllModuleHandle, IDS_RESOURCE_BASE + ResType, szTemp, MAX_PATH);
  3230. ulRange = 0;
  3231. pItemData = (PITEMDATA)MyMalloc(sizeof(ITEMDATA));
  3232. if (pItemData != NULL) {
  3233. pItemData->ResType = ResType;
  3234. pItemData->MatchingResDes = ResDes;
  3235. pItemData->RangeCount = ulRange;
  3236. pItemData->ulValue = ulValue; // selected value
  3237. pItemData->ulLen = ulLen;
  3238. pItemData->ulEnd = ulValue + ulLen - 1;
  3239. pItemData->ulFlags = ulFlags;
  3240. pItemData->bValid = !bNoMatch; // if no chosen value
  3241. pItemData->bFixed = bFixed;
  3242. }
  3243. if (bFixed == FALSE) {
  3244. //
  3245. // we have at least one editable value
  3246. //
  3247. lpdmpd->dwFlags &= ~DMPROP_FLAG_FIXEDCONFIG;
  3248. }
  3249. lviItem.iItem = iNewItem;
  3250. lviItem.lParam = (LPARAM)pItemData;
  3251. ListView_InsertItem(hWndList, &lviItem);
  3252. //
  3253. // Write second column text field (uses szTemp, lParam is res handle)
  3254. //
  3255. if (bNoMatch) {
  3256. pFormatResString(lpdmpd,szTemp, 0, 0, ResType);
  3257. } else {
  3258. pFormatResString(lpdmpd,szTemp, ulValue, ulLen, ResType);
  3259. }
  3260. ListView_SetItemText(hWndList, iNewItem, 1, szTemp);
  3261. ++iNewItem;
  3262. }
  3263. pShowEntry = pShowEntry->Next;
  3264. }
  3265. if(ulMaxMem > 0xFFFFFFFF) {
  3266. //
  3267. // an excuse to require 64-bit address range
  3268. //
  3269. lpdmpd->dwFlags |= DMPROP_FLAG_64BIT_RANGE;
  3270. }
  3271. SendMessage(hWndList, WM_SETREDRAW, (WPARAM)TRUE, 0);
  3272. RetCode = TRUE;
  3273. Final:
  3274. pDeleteResDesDataList(pKnownValues);
  3275. pDeleteResDesDataList(pShowValues);
  3276. //
  3277. // initialize listview headings here
  3278. //
  3279. ListView_SetColumnWidth(hWndList, 0, LVSCW_AUTOSIZE_USEHEADER);
  3280. ListView_SetColumnWidth(hWndList, 1, LVSCW_AUTOSIZE_USEHEADER);
  3281. //
  3282. // change "Change Settings" button
  3283. //
  3284. pCheckEnableResourceChange(lpdmpd);
  3285. return RetCode;
  3286. }
  3287. BOOL
  3288. bIsMultiFunctionChild(
  3289. PSP_DEVINFO_DATA lpdi,
  3290. HMACHINE hMachine
  3291. )
  3292. /*++
  3293. Routine Description:
  3294. Returns flag indicating if this is a child of a
  3295. multifunction device
  3296. Arguments:
  3297. Return Value:
  3298. TRUE if MF child
  3299. --*/
  3300. {
  3301. ULONG Status;
  3302. ULONG ProblemNumber;
  3303. if (lpdi->DevInst) {
  3304. if (CM_Get_DevNode_Status_Ex(&Status, &ProblemNumber,
  3305. lpdi->DevInst, 0,hMachine) == CR_SUCCESS) {
  3306. //
  3307. // If the passed in dev is not an MF child, then it is the top
  3308. // level MF_Parent
  3309. //
  3310. if (Status & DN_MF_CHILD) {
  3311. return TRUE;
  3312. } else {
  3313. return FALSE;
  3314. }
  3315. }
  3316. }
  3317. return FALSE;
  3318. }
  3319. VOID
  3320. pSelectLogConf(
  3321. LPDMPROP_DATA lpdmpd,
  3322. LOG_CONF forceLC,
  3323. ULONG forceLCType,
  3324. BOOL Always
  3325. )
  3326. /*++
  3327. Routine Description:
  3328. Selects a LogConf, showing the config in the LC control
  3329. Arguments:
  3330. Return Value:
  3331. TRUE if MF child
  3332. --*/
  3333. {
  3334. HWND hDlg = lpdmpd->hDlg;
  3335. int count;
  3336. int i;
  3337. LOG_CONF LogConf;
  3338. if (Always == FALSE && forceLC == lpdmpd->SelectedLC) {
  3339. //
  3340. // selection remains the same
  3341. //
  3342. return;
  3343. }
  3344. count = (int)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
  3345. if (count == 0) {
  3346. MYASSERT(FALSE/*shouldn't get here*/);
  3347. pLoadCurrentConfig(lpdmpd,FALSE);
  3348. return;
  3349. }
  3350. if (forceLC == 0 && lpdmpd->CurrentLC == 0) {
  3351. //
  3352. // no currentLC, so select first default
  3353. //
  3354. forceLC = (LOG_CONF)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
  3355. CB_GETITEMDATA, (WPARAM)0, (LPARAM)0);
  3356. if (forceLC == (LOG_CONF)0) {
  3357. MYASSERT(FALSE/*shouldn't get here*/);
  3358. pLoadCurrentConfig(lpdmpd,FALSE);
  3359. return;
  3360. }
  3361. forceLCType = lpdmpd->ConfigListLCType;
  3362. }
  3363. for (i=0;i<count;i++) {
  3364. LogConf = (LOG_CONF)SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,
  3365. CB_GETITEMDATA, (WPARAM)i, (LPARAM)0);
  3366. if (LogConf == forceLC) {
  3367. //
  3368. // set these first so we don't recurse around
  3369. //
  3370. lpdmpd->SelectedLC = forceLC;
  3371. lpdmpd->SelectedLCType = forceLCType;
  3372. //
  3373. // change dialog to reflect new selection
  3374. //
  3375. SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_SETCURSEL, (WPARAM)i, (LPARAM)0);
  3376. pLoadConfig(lpdmpd,forceLC,forceLCType);
  3377. pShowConflicts(lpdmpd);
  3378. return;
  3379. }
  3380. }
  3381. SendDlgItemMessage(hDlg, IDC_DEVRES_LOGCONFIGLIST,CB_SETCURSEL, (WPARAM)(-1), (LPARAM)0);
  3382. pLoadConfig(lpdmpd,forceLC,forceLCType);
  3383. pShowConflicts(lpdmpd);
  3384. }
  3385. VOID
  3386. pChangeCurrentResSetting(
  3387. IN LPDMPROP_DATA lpdmpd
  3388. )
  3389. /*++
  3390. Routine Description:
  3391. Brings up edit dialog to change currently selected resource
  3392. Arguments:
  3393. Return Value:
  3394. none
  3395. --*/
  3396. {
  3397. HWND hDlg = lpdmpd->hDlg;
  3398. RESOURCEEDITINFO rei;
  3399. HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  3400. int iCur;
  3401. PITEMDATA pItemData = NULL;
  3402. LV_ITEM lviItem;
  3403. GENERIC_RESOURCE GenResInfo;
  3404. PDEVICE_INFO_SET pDeviceInfoSet;
  3405. BOOL changed = FALSE;
  3406. TCHAR szTemp[MAX_PATH];
  3407. pItemData = pGetResourceToChange(lpdmpd,&iCur);
  3408. if (pItemData == NULL) {
  3409. //
  3410. // we cannot edit this resource for some reason, give the user a hint
  3411. // and maybe I'll get less ear-ache "I cannot change the settings"
  3412. //
  3413. if ((lpdmpd->dwFlags & DMPROP_FLAG_VIEWONLYRES)!=0 ||
  3414. (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS)!=0) {
  3415. //
  3416. // editing not allowed - prob double-clicked on settings
  3417. //
  3418. return;
  3419. }
  3420. if (lpdmpd->dwFlags & DMPROP_FLAG_FIXEDCONFIG) {
  3421. pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYALL);
  3422. } else {
  3423. //
  3424. // see if user needs to select a resource
  3425. //
  3426. iCur = (int)ListView_GetNextItem(hList,-1, LVNI_SELECTED);
  3427. if (iCur == LB_ERR) {
  3428. //
  3429. // no selection
  3430. //
  3431. pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYSELECT);
  3432. } else {
  3433. //
  3434. // resource is just not editable
  3435. //
  3436. pWarnResSettingNotEditable(hDlg, IDS_DEVRES_NOMODIFYSINGLE);
  3437. }
  3438. }
  3439. goto clean0;
  3440. }
  3441. ZeroMemory(&rei,sizeof(rei));
  3442. rei.hMachine = pGetMachine(lpdmpd);
  3443. rei.KnownLC = lpdmpd->CurrentLC;
  3444. rei.MatchingBasicLC = lpdmpd->MatchingLC;
  3445. rei.SelectedBasicLC = lpdmpd->SelectedLC;
  3446. rei.lpdi = lpdmpd->lpdi;
  3447. rei.dwPropFlags = lpdmpd->dwFlags;
  3448. rei.bShareable = FALSE;
  3449. rei.ridResType = pItemData->ResType;
  3450. rei.ResDes = pItemData->MatchingResDes;
  3451. rei.ulCurrentVal = pItemData->ulValue;
  3452. rei.ulCurrentLen = pItemData->ulLen;
  3453. rei.ulCurrentEnd = pItemData->ulEnd;
  3454. rei.ulCurrentFlags = pItemData->ulFlags;
  3455. rei.ulRangeCount = pItemData->RangeCount;
  3456. rei.pData = NULL;
  3457. if (DialogBoxParam(MyDllModuleHandle,
  3458. MAKEINTRESOURCE(IDD_EDIT_RESOURCE),
  3459. hDlg,
  3460. EditResourceDlgProc,
  3461. (LPARAM)(PRESOURCEEDITINFO)&rei) != IDOK) {
  3462. goto clean0;
  3463. }
  3464. //
  3465. // Update The Current Resource settings to Future
  3466. // Settings, and update the Conflict list.
  3467. //
  3468. pItemData->ulValue = rei.ulCurrentVal;
  3469. pItemData->ulLen = rei.ulCurrentLen;
  3470. pItemData->ulEnd = rei.ulCurrentEnd;
  3471. pItemData->ulFlags = rei.ulCurrentFlags;
  3472. pItemData->RangeCount = rei.ulRangeCount;
  3473. pItemData->bValid = TRUE; // indicate that user has explicitly changed this value
  3474. pFormatResString(lpdmpd,szTemp,
  3475. rei.ulCurrentVal,
  3476. rei.ulCurrentLen,
  3477. rei.ridResType);
  3478. ListView_SetItemText(hList, iCur, 1, szTemp);
  3479. pShowConflicts(lpdmpd);
  3480. //
  3481. // clear the flag for saving changes
  3482. //
  3483. lpdmpd->dwFlags &= ~DMPROP_FLAG_CHANGESSAVED;
  3484. PropSheet_Changed(GetParent(hDlg), hDlg);
  3485. clean0:
  3486. ;
  3487. }
  3488. VOID
  3489. pShowConflicts(
  3490. IN LPDMPROP_DATA lpdmpd
  3491. )
  3492. /*++
  3493. Routine Description:
  3494. Selects a LogConf, showing the config in the LC control
  3495. Arguments:
  3496. Return Value:
  3497. TRUE if MF child
  3498. --*/
  3499. {
  3500. HWND hDlg = lpdmpd->hDlg;
  3501. CONFIGRET Status = CR_SUCCESS;
  3502. LPVOID vaArray[4];
  3503. TCHAR szTemp[MAX_PATH+4], szBuffer[MAX_PATH+16], szSetting[MAX_PATH];
  3504. TCHAR szFormat[MAX_PATH], szItemFormat[MAX_PATH];
  3505. TCHAR szUnavailable[MAX_PATH];
  3506. LPTSTR pszConflictList = NULL, pszConflictList2 = NULL;
  3507. ULONG ulSize = 0, ulLength, ulBufferLen, ulNewLength;
  3508. ULONG ulStartOffset = 0;
  3509. int Count = 0, i = 0;
  3510. PITEMDATA pItemData = NULL;
  3511. LPBYTE pResourceData = NULL;
  3512. HWND hwndResList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  3513. HMACHINE hMachine;
  3514. ULONG ConflictCount = 0;
  3515. ULONG ConflictIndex = 0;
  3516. CONFLICT_LIST ConflictList = 0;
  3517. PDEVICE_INFO_SET pDeviceInfoSet;
  3518. CONFLICT_DETAILS ConflictDetails;
  3519. BOOL ReservedResource = FALSE;
  3520. BOOL AnyReportedResources = FALSE;
  3521. BOOL AnyBadResources = FALSE;
  3522. PCONFLICT_EXCEPTIONS pConflictExceptions = NULL;
  3523. //
  3524. // number of resources listed
  3525. //
  3526. Count = ListView_GetItemCount(hwndResList);
  3527. if (Count <= 0) {
  3528. goto Clean0;
  3529. }
  3530. //
  3531. // initial buffer that holds the strings
  3532. // with all the conflict info in them
  3533. //
  3534. ulBufferLen = 2048;
  3535. ulLength = 0;
  3536. pszConflictList = MyMalloc(ulBufferLen * sizeof(TCHAR));
  3537. if (pszConflictList == NULL) {
  3538. goto Clean0;
  3539. }
  3540. pszConflictList[0] = 0;
  3541. //
  3542. // obtain machine
  3543. //
  3544. if(!(pDeviceInfoSet = AccessDeviceInfoSet(lpdmpd->hDevInfo))) {
  3545. goto Clean0;
  3546. }
  3547. hMachine = pDeviceInfoSet->hMachine;
  3548. UnlockDeviceInfoSet (pDeviceInfoSet);
  3549. //
  3550. // do these once - these format strings use %1!s! type formats (FormatMessage)
  3551. //
  3552. LoadString(MyDllModuleHandle, IDS_CONFLICT_FMT, szFormat, MAX_PATH);
  3553. LoadString(MyDllModuleHandle, IDS_CONFLICT_UNAVAILABLE, szUnavailable, MAX_PATH);
  3554. //
  3555. // for every listed resource
  3556. //
  3557. for (i = 0; i < Count; i++) {
  3558. ConflictList = 0;
  3559. ConflictCount = 0;
  3560. //
  3561. // get the resource we're about to test
  3562. //
  3563. pItemData = (PITEMDATA)pGetListViewItemData(hwndResList, i, 0);
  3564. if (pItemData == NULL || pItemData->bValid == FALSE) {
  3565. //
  3566. // for whatever reason, we don't want to show conflict information on this resource
  3567. //
  3568. ListView_SetItemState(hwndResList, i,
  3569. INDEXTOOVERLAYMASK(0),
  3570. LVIS_OVERLAYMASK);
  3571. goto NextResource;
  3572. }
  3573. //
  3574. // this is set to indicate conflict not reported, but is reserved
  3575. //
  3576. ReservedResource = FALSE;
  3577. //
  3578. // need resource-data for determining conflict
  3579. //
  3580. if (MakeResourceData(&pResourceData, &ulSize,
  3581. pItemData->ResType,
  3582. pItemData->ulValue,
  3583. pItemData->ulLen,
  3584. pItemData->ulFlags)) {
  3585. Status = CM_Query_Resource_Conflict_List(&ConflictList,
  3586. lpdmpd->lpdi->DevInst,
  3587. pItemData->ResType,
  3588. pResourceData,
  3589. ulSize,
  3590. DEVRES_WIDTH_FLAGS,
  3591. hMachine);
  3592. if (Status != CR_SUCCESS) {
  3593. //
  3594. // on the unlikely event of an error, remember an error occurred
  3595. //
  3596. ConflictList = 0;
  3597. ConflictCount = 0;
  3598. AnyBadResources = TRUE;
  3599. } else {
  3600. //
  3601. // find out how many things conflicted
  3602. //
  3603. Status = CM_Get_Resource_Conflict_Count(ConflictList,&ConflictCount);
  3604. if (Status != CR_SUCCESS) {
  3605. MYASSERT(Status == CR_SUCCESS);
  3606. ConflictCount = 0;
  3607. AnyBadResources = TRUE;
  3608. }
  3609. }
  3610. if(ConflictCount && (lpdmpd->dwFlags & DMPROP_FLAG_SINGLE_CONFIG) && !(lpdmpd->dwFlags & DMPROP_FLAG_HASPROBLEM)) {
  3611. //
  3612. // NTRAID#166214-2000/08/19-JamieHun Conflict Supression Hack
  3613. //
  3614. // rules are
  3615. // (1) device doesn't have a problem
  3616. // (2) device can only have one configuration (ie, there's no basic config, or the basic config is singular)
  3617. // (3) it has a ResourcePickerExceptions string, and that string indicates that the exception is allowed for the specific conflict
  3618. if(pConflictExceptions==NULL) {
  3619. pConflictExceptions = pLoadConflictExceptions(lpdmpd);
  3620. }
  3621. if (pConflictExceptions) {
  3622. BOOL muted = TRUE;
  3623. //
  3624. // count from 0 (first conflict) through to ConflictCount (excl)
  3625. //
  3626. for(ConflictIndex = 0; ConflictIndex < ConflictCount; ConflictIndex ++) {
  3627. //
  3628. // obtain details for this conflict
  3629. //
  3630. ZeroMemory(&ConflictDetails,sizeof(ConflictDetails));
  3631. ConflictDetails.CD_ulSize = sizeof(ConflictDetails);
  3632. ConflictDetails.CD_ulMask = CM_CDMASK_DEVINST | CM_CDMASK_DESCRIPTION | CM_CDMASK_FLAGS;
  3633. Status = CM_Get_Resource_Conflict_Details(ConflictList,ConflictIndex,&ConflictDetails);
  3634. if (Status == CR_SUCCESS) {
  3635. if (!pIsConflictException(lpdmpd,pConflictExceptions,ConflictDetails.CD_dnDevInst,ConflictDetails.CD_szDescription,pItemData->ResType,pItemData->ulValue,pItemData->ulLen)) {
  3636. muted = FALSE;
  3637. break;
  3638. }
  3639. }
  3640. }
  3641. if(muted) {
  3642. ConflictCount = 0;
  3643. }
  3644. }
  3645. }
  3646. if (ConflictCount || ReservedResource) {
  3647. ulStartOffset = ulLength; // record start in case we decide to backtrack
  3648. AnyReportedResources = TRUE; // say we reported at least one problem
  3649. TreatAsReserved:
  3650. ulLength = ulStartOffset;
  3651. pszConflictList[ulLength] = 0;
  3652. //
  3653. // we're going to mark the resource as a problem
  3654. //
  3655. ListView_GetItemText(hwndResList, i, 1, szSetting, MAX_PATH);
  3656. switch (pItemData->ResType) {
  3657. case ResType_Mem:
  3658. LoadString(MyDllModuleHandle, IDS_MEMORY_FULL, szBuffer, MAX_PATH);
  3659. break;
  3660. case ResType_IO:
  3661. LoadString(MyDllModuleHandle, IDS_IO_FULL, szBuffer, MAX_PATH);
  3662. break;
  3663. case ResType_DMA:
  3664. LoadString(MyDllModuleHandle, IDS_DMA_FULL, szBuffer, MAX_PATH);
  3665. break;
  3666. case ResType_IRQ:
  3667. LoadString(MyDllModuleHandle, IDS_IRQ_FULL, szBuffer, MAX_PATH);
  3668. break;
  3669. default:
  3670. MYASSERT(FALSE);
  3671. }
  3672. if ( ReservedResource == FALSE) {
  3673. //
  3674. // count from 0 (header) 1 (first conflict) through to ConflictCount
  3675. //
  3676. for(ConflictIndex = 0; ConflictIndex <= ConflictCount; ConflictIndex ++) {
  3677. if (ConflictIndex == 0) {
  3678. //
  3679. // first pass through, do header message
  3680. //
  3681. vaArray[0] = szBuffer;
  3682. vaArray[1] = szSetting;
  3683. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY ,
  3684. szFormat,
  3685. 0,0,
  3686. szTemp,MAX_PATH,
  3687. (va_list*)vaArray); // FORMAT_MESSAGE_ARGUMENT_ARRAY
  3688. } else {
  3689. //
  3690. // obtain details for this conflict
  3691. //
  3692. ZeroMemory(&ConflictDetails,sizeof(ConflictDetails));
  3693. ConflictDetails.CD_ulSize = sizeof(ConflictDetails);
  3694. ConflictDetails.CD_ulMask = CM_CDMASK_DEVINST | CM_CDMASK_DESCRIPTION | CM_CDMASK_FLAGS;
  3695. Status = CM_Get_Resource_Conflict_Details(ConflictList,ConflictIndex-1,&ConflictDetails);
  3696. if (Status == CR_SUCCESS) {
  3697. if ((ConflictDetails.CD_ulFlags & CM_CDFLAGS_RESERVED) != 0) {
  3698. //
  3699. // treat as reserved - backtrack
  3700. //
  3701. ReservedResource = TRUE;
  3702. goto TreatAsReserved;
  3703. } else {
  3704. if (ConflictDetails.CD_szDescription[0] == 0) {
  3705. //
  3706. // treat as reserved - backtrack
  3707. //
  3708. ReservedResource = TRUE;
  3709. goto TreatAsReserved;
  3710. }
  3711. wsprintf(szBuffer,TEXT(" %s\r\n"),ConflictDetails.CD_szDescription);
  3712. }
  3713. } else {
  3714. //
  3715. // treat as reserved
  3716. //
  3717. ReservedResource = TRUE;
  3718. goto TreatAsReserved;
  3719. }
  3720. lstrcpyn(szTemp,szBuffer,MAX_PATH);
  3721. }
  3722. ulNewLength = ulLength + lstrlen(szTemp); // excluding terminating NUL
  3723. if ((ulNewLength+1) < ulBufferLen) {
  3724. //
  3725. // need to allocate more space - we'll double it and add some more every time
  3726. //
  3727. pszConflictList2 = MyRealloc(pszConflictList,(ulBufferLen+ulNewLength+1) * sizeof(TCHAR));
  3728. if (pszConflictList2 != NULL) {
  3729. //
  3730. // succeeded in resizing buffer
  3731. //
  3732. pszConflictList = pszConflictList2;
  3733. ulBufferLen = ulBufferLen+ulNewLength+1;
  3734. }
  3735. }
  3736. if ((ulNewLength+1) < ulBufferLen) {
  3737. lstrcpy(pszConflictList + ulLength , szTemp);
  3738. ulLength = ulNewLength;
  3739. }
  3740. }
  3741. } else {
  3742. //
  3743. // there is some other problem with resource
  3744. //
  3745. vaArray[0] = szBuffer;
  3746. vaArray[1] = szSetting;
  3747. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY ,
  3748. szUnavailable,
  3749. 0,0,
  3750. szTemp,MAX_PATH,
  3751. (va_list*)vaArray); // FORMAT_MESSAGE_ARGUMENT_ARRAY
  3752. ulNewLength = ulLength + lstrlen(szTemp); // excluding terminating NUL
  3753. if ((ulNewLength+1) < ulBufferLen) {
  3754. //
  3755. // need to allocate more space - we'll double it and add some more every time
  3756. //
  3757. pszConflictList2 = MyRealloc(pszConflictList,(ulBufferLen+ulNewLength+1) * sizeof(TCHAR));
  3758. if (pszConflictList2 != NULL) {
  3759. //
  3760. // succeeded in resizing buffer
  3761. //
  3762. pszConflictList = pszConflictList2;
  3763. ulBufferLen = ulBufferLen+ulNewLength+1;
  3764. }
  3765. }
  3766. if ((ulNewLength+1) < ulBufferLen) {
  3767. lstrcpy(pszConflictList + ulLength , szTemp);
  3768. ulLength = ulNewLength;
  3769. }
  3770. }
  3771. //
  3772. // Set the Conflict Overlay for this resource.
  3773. //
  3774. ListView_SetItemState(hwndResList, i,
  3775. INDEXTOOVERLAYMASK(IDI_CONFLICT - IDI_RESOURCEOVERLAYFIRST + 1),
  3776. LVIS_OVERLAYMASK);
  3777. } else {
  3778. //
  3779. // resource is (aparently) working fine
  3780. //
  3781. ListView_SetItemState(hwndResList, i,
  3782. INDEXTOOVERLAYMASK(0),
  3783. LVIS_OVERLAYMASK);
  3784. }
  3785. if (ConflictList) {
  3786. CM_Free_Resource_Conflict_Handle(ConflictList);
  3787. }
  3788. if (pResourceData != NULL) {
  3789. MyFree(pResourceData);
  3790. }
  3791. } else {
  3792. //
  3793. // couldn't make the resource descriptor
  3794. AnyBadResources = TRUE;
  3795. }
  3796. NextResource:
  3797. ;
  3798. }
  3799. Clean0:
  3800. ;
  3801. //
  3802. // If there were any conflicts, put the list in the multiline edit box.
  3803. //
  3804. if (AnyReportedResources) {
  3805. SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, pszConflictList);
  3806. } else if (AnyBadResources) {
  3807. //
  3808. // this would most likely occur on
  3809. // (1) running this on 95/98 (shouldn't happen)
  3810. // (2) using new setupapi on old cfgmgr32
  3811. //
  3812. LoadString(MyDllModuleHandle, IDS_CONFLICT_GENERALERROR, szBuffer, MAX_PATH);
  3813. SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, szBuffer);
  3814. } else {
  3815. LoadString(MyDllModuleHandle, IDS_DEVRES_NOCONFLICTDEVS, szBuffer, MAX_PATH);
  3816. SetDlgItemText(hDlg, IDC_DEVRES_CONFLICTINFOLIST, szBuffer);
  3817. }
  3818. if(pszConflictList != NULL) {
  3819. MyFree(pszConflictList);
  3820. }
  3821. if (pConflictExceptions != NULL) {
  3822. pFreeConflictExceptions(pConflictExceptions);
  3823. }
  3824. return;
  3825. }
  3826. int
  3827. pOkToSave(
  3828. IN LPDMPROP_DATA lpdmpd
  3829. )
  3830. /*++
  3831. Routine Description:
  3832. Check to see if there's something the user hasn't done
  3833. Arguments:
  3834. Return Value:
  3835. IDYES = save settings
  3836. IDNO = don't save settings
  3837. IDCANCEL = don't exit
  3838. --*/
  3839. {
  3840. HWND hDlg = lpdmpd->hDlg;
  3841. HWND hList = GetDlgItem(hDlg, IDC_DEVRES_SETTINGSLIST);
  3842. int iCur;
  3843. int nRes;
  3844. PITEMDATA pItemData;
  3845. if (lpdmpd->dwFlags & DMPROP_FLAG_NO_RESOURCES) {
  3846. //
  3847. // no changes - because there are no resources
  3848. //
  3849. return IDNO;
  3850. }
  3851. if (lpdmpd->dwFlags & DMPROP_FLAG_CHANGESSAVED) {
  3852. //
  3853. // no changes
  3854. //
  3855. return IDNO;
  3856. }
  3857. if (lpdmpd->dwFlags & DMPROP_FLAG_USESYSSETTINGS) {
  3858. //
  3859. // always ok to "use sys settings"
  3860. //
  3861. return IDYES;
  3862. }
  3863. //
  3864. // user is forcing a config - let's see if all settings are valid
  3865. //
  3866. //
  3867. // The resource descriptors are out-of-order. Maintain the original ordering.
  3868. //
  3869. // First, build up a linked list of the data in the listview resource items.
  3870. //
  3871. iCur = (int)ListView_GetNextItem(hList, -1, LVNI_ALL);
  3872. while (iCur >= 0) {
  3873. pItemData = (PITEMDATA)pGetListViewItemData(hList, iCur, 0);
  3874. if (pItemData) {
  3875. if (pItemData->bValid == FALSE) {
  3876. //
  3877. // we've got an invalid entry - can't save
  3878. //
  3879. nRes = pWarnNoSave(hDlg,IDS_FORCEDCONFIG_PARTIAL);
  3880. if (nRes != IDOK) {
  3881. return IDCANCEL;
  3882. }
  3883. return IDNO;
  3884. }
  3885. }
  3886. iCur = (int)ListView_GetNextItem(hList, iCur, LVNI_ALL);
  3887. }
  3888. //
  3889. // everything checks out
  3890. //
  3891. return IDYES;
  3892. }