Leaked source code of windows server 2003
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.

1064 lines
32 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include "connutil.h"
  4. #include "resource.h"
  5. #include "ncreg.h"
  6. #include "nsres.h"
  7. #include "wizard.h"
  8. #include "ncsetup.h"
  9. #include "..\lanui\util.h"
  10. #include "ncmisc.h"
  11. // Note: This module needs to touch pWizard as little as possible because it
  12. // it is deleted before this page is entered.
  13. //
  14. inline BOOL FNetDevPagesAdded(DWORD dw)
  15. {
  16. return ((dw & 0x10000000) != 0);
  17. }
  18. inline DWORD DwNetDevMarkPagesAdded(DWORD dw)
  19. {
  20. return (dw | 0x10000000);
  21. }
  22. inline BOOL FNetDevChecked(DWORD dw)
  23. {
  24. return ((dw & 0x01000000) != 0);
  25. }
  26. inline DWORD NetDevToggleChecked(DWORD dw)
  27. {
  28. if (dw & 0x01000000)
  29. return (dw & ~0x01000000);
  30. else
  31. return (dw | 0x01000000);
  32. }
  33. typedef struct
  34. {
  35. SP_CLASSIMAGELIST_DATA cild;
  36. HIMAGELIST hImageStateIcons;
  37. HDEVINFO hdi;
  38. HPROPSHEETPAGE hpsp; // The wnetdev HPROPSHEETPAGE
  39. PINTERNAL_SETUP_DATA pSetupData;
  40. } NetDevInfo;
  41. typedef struct
  42. {
  43. DWORD dwFlags;
  44. DWORD cPages;
  45. HPROPSHEETPAGE * phpsp;
  46. SP_DEVINFO_DATA deid;
  47. } NetDevItemInfo;
  48. // CHECKED_BY_DEFAULT controls whether the items needing configuration are
  49. // checked by default or not.
  50. //
  51. #define CHECKED_BY_DEFAULT 1
  52. // TRUE if all the devices are selected for configuration.
  53. //
  54. static BOOL bAllSelected=FALSE;
  55. // DevInst of the device whose property page will be displayed after
  56. // the first page on which device selection is shown.
  57. //
  58. static DWORD dwFirstDevInst=0;
  59. HRESULT HrGetDevicesThatHaveWizardPagesToAdd(HDEVINFO* phdi);
  60. HRESULT HrFillNetDevList(HWND hwndLV, NetDevInfo * pNdi);
  61. // The property page of every isdn device queries if all the
  62. // devices have been selected or not. We return TRUE only if
  63. // all the devices have been selected and the query is from
  64. // the device whose property page is displayed first. This
  65. // is done to prevent the user from coming back to the device
  66. // selection page since there is nothing to do once all the
  67. // devices have been selected.
  68. //
  69. VOID SetSelectedAll (HWND hwndDlg, DWORD dwDevInst)
  70. {
  71. if (dwDevInst == dwFirstDevInst)
  72. {
  73. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)bAllSelected );
  74. }
  75. else
  76. {
  77. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE );
  78. }
  79. return;
  80. }
  81. HRESULT HrNetDevInitListView(HWND hwndLV, NetDevInfo * pNdi)
  82. {
  83. TraceFileFunc(ttidGuiModeSetup);
  84. DWORD dwStyle;
  85. RECT rc;
  86. LV_COLUMN lvc = {0};
  87. SP_CLASSIMAGELIST_DATA * pcild;
  88. Assert(hwndLV);
  89. Assert(NULL != pNdi);
  90. // Set the shared image lists bit so the caller can destroy the class
  91. // image lists itself
  92. //
  93. dwStyle = GetWindowLong(hwndLV, GWL_STYLE);
  94. SetWindowLong(hwndLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
  95. // Create small image lists
  96. //
  97. HRESULT hr = HrSetupDiGetClassImageList(&pNdi->cild);
  98. if (SUCCEEDED(hr))
  99. {
  100. AssertSz(pNdi->cild.ImageList, "No class image list data!");
  101. ListView_SetImageList(hwndLV, pNdi->cild.ImageList, LVSIL_SMALL);
  102. }
  103. else
  104. {
  105. TraceError("HrSetupDiGetClassImageList returns failure", hr);
  106. hr = S_OK;
  107. }
  108. // Create state image lists
  109. pNdi->hImageStateIcons = ImageList_LoadBitmapAndMirror(
  110. _Module.GetResourceInstance(),
  111. MAKEINTRESOURCE(IDB_CHECKSTATE),
  112. 16,
  113. 0,
  114. PALETTEINDEX(6));
  115. ListView_SetImageList(hwndLV, pNdi->hImageStateIcons, LVSIL_STATE);
  116. GetClientRect(hwndLV, &rc);
  117. lvc.mask = LVCF_FMT | LVCF_WIDTH;
  118. lvc.fmt = LVCFMT_LEFT;
  119. lvc.cx = rc.right;
  120. // $REVIEW(tongl 12\22\97): Fix for bug#127472
  121. // lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  122. ListView_InsertColumn(hwndLV, 0, &lvc);
  123. if (SUCCEEDED(hr))
  124. {
  125. // Selete the first item
  126. ListView_SetItemState(hwndLV, 0, LVIS_SELECTED, LVIS_SELECTED);
  127. }
  128. TraceError("HrNetDevInitListView", hr);
  129. return hr;
  130. }
  131. BOOL OnNetDevInitDialog(HWND hwndDlg, LPARAM lParam)
  132. {
  133. TraceFileFunc(ttidGuiModeSetup);
  134. NetDevInfo * pNdi;
  135. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam;
  136. Assert(psp->lParam);
  137. pNdi = reinterpret_cast<NetDevInfo *>(psp->lParam);
  138. ::SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pNdi);
  139. if (NULL != pNdi)
  140. {
  141. HWND hwndLV = GetDlgItem(hwndDlg, LVC_NETDEVLIST);
  142. Assert(hwndLV);
  143. if (SUCCEEDED(HrNetDevInitListView(hwndLV, pNdi)))
  144. {
  145. // Populate the list
  146. //
  147. if (NULL != pNdi->hdi)
  148. {
  149. (VOID)HrFillNetDevList(hwndLV, pNdi);
  150. }
  151. }
  152. }
  153. return FALSE; // We didn't change the default item of focus
  154. }
  155. VOID OnNetDevDestroy(HWND hwndDlg)
  156. {
  157. TraceFileFunc(ttidGuiModeSetup);
  158. NetDevInfo *pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
  159. if (NULL != pNdi)
  160. {
  161. if (pNdi->cild.ImageList)
  162. {
  163. // Destroy the class image list data
  164. (void) HrSetupDiDestroyClassImageList(&pNdi->cild);
  165. }
  166. if (pNdi->hImageStateIcons)
  167. {
  168. ImageList_Destroy(pNdi->hImageStateIcons);
  169. }
  170. // The cleanup any pages we loaded for the providers
  171. // but did not add to setup wizard will be done by processing the
  172. // LVN_DELETEITEM message
  173. //
  174. }
  175. ::SetWindowLongPtr(hwndDlg, DWLP_USER, 0);
  176. if (NULL != pNdi)
  177. {
  178. MemFree(pNdi);
  179. }
  180. }
  181. //
  182. // Function: OnNetDevPageNext
  183. //
  184. // Purpose: Handle the PSN_WIZNEXT notification
  185. //
  186. // Parameters: hwndDlg - Handle to NetDev dialog
  187. //
  188. // Returns: BOOL, TRUE if we processed the message
  189. //
  190. BOOL OnNetDevPageNext(HWND hwndDlg)
  191. {
  192. TraceFileFunc(ttidGuiModeSetup);
  193. BOOL fRet = FALSE; // Accept the default behaviour
  194. HWND hwndLV = GetDlgItem(hwndDlg, LVC_NETDEVLIST);
  195. int nCount = ListView_GetItemCount(hwndLV);
  196. int nCountSelected = 0;
  197. NetDevInfo *pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
  198. if ((0 < nCount) && (NULL != pNdi) && (NULL != pNdi->hpsp))
  199. {
  200. fRet = TRUE;
  201. // Loop through the items in the listview if any are checked
  202. // But have not yet been marked as having their pages added,
  203. // add the pages and mark the item.
  204. //
  205. for (int nIdx=0; nIdx<nCount; nIdx++)
  206. {
  207. LV_ITEM lvi = {0};
  208. lvi.mask = LVIF_PARAM;
  209. lvi.iItem = nIdx;
  210. if (TRUE == ListView_GetItem(hwndLV, &lvi))
  211. {
  212. NetDevItemInfo * pndii = (NetDevItemInfo*)lvi.lParam;
  213. // Add the pages to the wizard if checked in the UI
  214. // but not already added.
  215. //
  216. if (pndii && FNetDevChecked(pndii->dwFlags))
  217. {
  218. // Keep track of how many device have been selected.
  219. //
  220. nCountSelected++;
  221. if (!FNetDevPagesAdded(pndii->dwFlags))
  222. {
  223. //
  224. // Since property pages are added when the device is
  225. // selected, any device could end up being the first to
  226. // show the property page as the devices could be
  227. // selected in a random order. So, we always save the
  228. // device instance in case this is the last device
  229. // selected.
  230. dwFirstDevInst = pndii->deid.DevInst;
  231. // Mark the pages as added
  232. //
  233. pndii->dwFlags = DwNetDevMarkPagesAdded(pndii->dwFlags);
  234. for (DWORD nIdx = pndii->cPages; nIdx > 0; nIdx--)
  235. {
  236. PropSheet_InsertPage(GetParent(hwndDlg),
  237. (WPARAM)pNdi->hpsp,
  238. (LPARAM)pndii->phpsp[nIdx - 1]);
  239. }
  240. // After loading the pages mark the option, uncheckable
  241. // (Note: with testing we might be able to support removal)
  242. //
  243. lvi.state = INDEXTOSTATEIMAGEMASK(SELS_INTERMEDIATE);
  244. lvi.mask = LVIF_STATE;
  245. lvi.stateMask = LVIS_STATEIMAGEMASK;
  246. BOOL ret = ListView_SetItem(hwndLV, &lvi);
  247. // Clear the reinstall flag on the device needing configuration
  248. //
  249. SetupDiSetConfigFlags(pNdi->hdi, &(pndii->deid),
  250. CONFIGFLAG_REINSTALL, SDFBO_XOR);
  251. }
  252. }
  253. }
  254. }
  255. bAllSelected = nCountSelected == nCount;
  256. }
  257. return fRet;
  258. }
  259. //
  260. // Function: OnNetDevPageActivate
  261. //
  262. // Purpose: Handle the PSN_SETACTIVE notification
  263. //
  264. // Parameters: hwndDlg - Handle to NetDev dialog
  265. //
  266. // Returns: BOOL, TRUE
  267. //
  268. BOOL OnNetDevPageActivate(HWND hwndDlg)
  269. {
  270. TraceFileFunc(ttidGuiModeSetup);
  271. TraceTag(ttidWizard, "Entering NetDev page...");
  272. NetDevInfo *pNdi;
  273. if (0 == ListView_GetItemCount(GetDlgItem(hwndDlg, LVC_NETDEVLIST)))
  274. {
  275. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  276. TraceTag(ttidWizard, "NetDev page refuses activation, no items to display.");
  277. }
  278. else
  279. {
  280. pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
  281. Assert(pNdi);
  282. if ( pNdi )
  283. {
  284. Assert(pNdi->pSetupData);
  285. if ( pNdi->pSetupData )
  286. {
  287. pNdi->pSetupData->ShowHideWizardPage(TRUE);
  288. }
  289. }
  290. }
  291. // disable the back button (#342922)
  292. ::SendMessage(GetParent(hwndDlg), PSM_SETWIZBUTTONS, 0, (LPARAM)(PSWIZB_NEXT));
  293. return TRUE;
  294. }
  295. //
  296. // Function: OnListViewDeleteItem
  297. //
  298. // Purpose: Handle the LVN_DELETEITEM notification
  299. //
  300. // Parameters: hwndList - Handle to listview control
  301. // pnmh - Ptr to the NMHDR for this notification
  302. //
  303. // Returns: none
  304. //
  305. VOID OnListViewDeleteItem(HWND hwndList, LPNMHDR pnmh)
  306. {
  307. NetDevItemInfo * pndii = NULL;
  308. NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pnmh);
  309. LV_ITEM lvi = {0};
  310. lvi.mask = LVIF_PARAM;
  311. lvi.iItem = pnmlv->iItem;
  312. if (TRUE == ListView_GetItem(hwndList, &lvi))
  313. {
  314. NetDevItemInfo * pndii = (NetDevItemInfo*)lvi.lParam;
  315. // Delete pages held, but that were not added to the wizard
  316. //
  317. if (pndii && !FNetDevPagesAdded(pndii->dwFlags))
  318. {
  319. for (DWORD nIdx = 0; nIdx < pndii->cPages; nIdx++)
  320. {
  321. DestroyPropertySheetPage(pndii->phpsp[nIdx]);
  322. }
  323. delete pndii;
  324. }
  325. }
  326. }
  327. //
  328. // Function: OnListViewDeleteItem
  329. //
  330. // Purpose: Handle the NM_CLICK notification for the listview control
  331. //
  332. // Parameters: hwndList - Handle to listview control
  333. // pnmh - Ptr to the NMHDR for this notification
  334. //
  335. // Returns: none
  336. //
  337. VOID OnListViewClick(HWND hwndList, LPNMHDR pnmh)
  338. {
  339. INT iItem;
  340. DWORD dwpts;
  341. RECT rc;
  342. LV_HITTESTINFO lvhti;
  343. // we have the location
  344. dwpts = GetMessagePos();
  345. // translate it relative to the listview
  346. GetWindowRect(hwndList, &rc);
  347. lvhti.pt.x = LOWORD(dwpts) - rc.left;
  348. lvhti.pt.y = HIWORD(dwpts) - rc.top;
  349. // get currently selected item
  350. iItem = ListView_HitTest(hwndList, &lvhti);
  351. // if no selection, or click not on state return false
  352. if (-1 != iItem)
  353. {
  354. // set the current selection
  355. //
  356. ListView_SetItemState(hwndList, iItem, LVIS_SELECTED, LVIS_SELECTED);
  357. if (LVHT_ONITEMSTATEICON != (LVHT_ONITEMSTATEICON & lvhti.flags))
  358. {
  359. iItem = -1;
  360. }
  361. if (-1 != iItem)
  362. {
  363. LV_ITEM lvItem;
  364. // Get the item
  365. //
  366. lvItem.iItem = iItem;
  367. lvItem.mask = LVIF_PARAM;
  368. lvItem.iSubItem = 0;
  369. if (ListView_GetItem(hwndList, &lvItem))
  370. {
  371. Assert(lvItem.lParam);
  372. NetDevItemInfo *pndii = (NetDevItemInfo*)lvItem.lParam;
  373. // Toggle the state (only if we haven't already added pages)
  374. //
  375. if (pndii && !FNetDevPagesAdded(pndii->dwFlags))
  376. {
  377. pndii->dwFlags = NetDevToggleChecked(pndii->dwFlags);
  378. if (FNetDevChecked(pndii->dwFlags))
  379. lvItem.state = INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
  380. else
  381. lvItem.state = INDEXTOSTATEIMAGEMASK(SELS_UNCHECKED);
  382. lvItem.mask = LVIF_STATE;
  383. lvItem.stateMask = LVIS_STATEIMAGEMASK;
  384. BOOL ret = ListView_SetItem(hwndList, &lvItem);
  385. }
  386. }
  387. }
  388. }
  389. }
  390. //
  391. // Function: dlgprocNetDev
  392. //
  393. // Purpose: Dialog Procedure for the NetDev wizard page
  394. //
  395. // Parameters: standard dlgproc parameters
  396. //
  397. // Returns: INT_PTR
  398. //
  399. INT_PTR CALLBACK dlgprocNetDev( HWND hwndDlg, UINT uMsg,
  400. WPARAM wParam, LPARAM lParam )
  401. {
  402. TraceFileFunc(ttidGuiModeSetup);
  403. BOOL frt = FALSE;
  404. switch (uMsg)
  405. {
  406. case WM_INITDIALOG:
  407. OnNetDevInitDialog(hwndDlg, lParam);
  408. break;
  409. case WM_DESTROY:
  410. OnNetDevDestroy(hwndDlg);
  411. break;
  412. case WM_NOTIFY:
  413. {
  414. LPNMHDR pnmh = (LPNMHDR)lParam;
  415. if (LVC_NETDEVLIST == (int)pnmh->idFrom)
  416. {
  417. Assert(GetDlgItem(hwndDlg, LVC_NETDEVLIST) == pnmh->hwndFrom);
  418. if (NM_CLICK == pnmh->code)
  419. {
  420. OnListViewClick(pnmh->hwndFrom, pnmh);
  421. }
  422. else if (LVN_DELETEITEM == pnmh->code)
  423. {
  424. OnListViewDeleteItem(pnmh->hwndFrom, pnmh);
  425. }
  426. }
  427. else
  428. {
  429. // Must be a property sheet notification
  430. //
  431. switch (pnmh->code)
  432. {
  433. // propsheet notification
  434. case PSN_HELP:
  435. break;
  436. case PSN_SETACTIVE:
  437. frt = OnNetDevPageActivate(hwndDlg);
  438. break;
  439. case PSN_APPLY:
  440. break;
  441. case PSN_KILLACTIVE:
  442. break;
  443. case PSN_RESET:
  444. break;
  445. case PSN_WIZBACK:
  446. break;
  447. case PSN_WIZFINISH:
  448. break;
  449. case PSN_WIZNEXT:
  450. frt = OnNetDevPageNext(hwndDlg);
  451. break;
  452. default:
  453. break;
  454. }
  455. }
  456. }
  457. break;
  458. case WM_SELECTED_ALL:
  459. SetSelectedAll (hwndDlg, (DWORD)lParam);
  460. frt = TRUE;
  461. default:
  462. break;
  463. }
  464. return( frt );
  465. }
  466. //
  467. // Function: NetDevPageCleanup
  468. //
  469. // Purpose: As a callback function to allow any page allocated memory
  470. // to be cleaned up, after the page will no longer be accessed.
  471. //
  472. // Parameters: pWizard [IN] - The wizard against which the page called
  473. // register page
  474. // lParam [IN] - The lParam supplied in the RegisterPage call
  475. //
  476. // Returns: nothing
  477. //
  478. VOID NetDevPageCleanup(CWizard *pWizard, LPARAM lParam)
  479. {
  480. TraceFileFunc(ttidGuiModeSetup);
  481. // Nothing to do. The pNdi is destroyed by the WM_DESTROY message
  482. // processed above.
  483. }
  484. //
  485. // Function: CreateNetDevPage
  486. //
  487. // Purpose: To determine if the NetDev page needs to be shown, and to
  488. // to create the page if requested.
  489. //
  490. // Parameters: pWizard [IN] - Ptr to a Wizard instance
  491. // pData [IN] - Context data to describe the world in
  492. // which the Wizard will be run
  493. // fCountOnly [IN] - If True, only the maximum number of
  494. // pages this routine will create need
  495. // be determined.
  496. // pnPages [IN] - Increment by the number of pages
  497. // to create/created
  498. //
  499. // Returns: HRESULT, S_OK on success
  500. //
  501. HRESULT HrCreateNetDevPage(CWizard *pWizard, PINTERNAL_SETUP_DATA pData,
  502. BOOL fCountOnly, UINT *pnPages)
  503. {
  504. TraceFileFunc(ttidGuiModeSetup);
  505. HRESULT hr = S_OK;
  506. if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
  507. {
  508. (*pnPages)++;
  509. // If not only counting, create and register the page
  510. if (!fCountOnly)
  511. {
  512. HPROPSHEETPAGE hpsp;
  513. PROPSHEETPAGE psp;
  514. NetDevInfo * pNdi;
  515. hr = E_OUTOFMEMORY;
  516. TraceTag(ttidWizard, "Creating NetDev Page");
  517. pNdi = reinterpret_cast<NetDevInfo *>(MemAlloc(sizeof(NetDevInfo)));
  518. if (NULL != pNdi)
  519. {
  520. ZeroMemory(pNdi, sizeof(NetDevInfo));
  521. psp.dwSize = sizeof( PROPSHEETPAGE );
  522. psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  523. psp.pszHeaderTitle = SzLoadIds(IDS_T_NetDev);
  524. psp.pszHeaderSubTitle = SzLoadIds(IDS_ST_NetDev);
  525. psp.pszTemplate = MAKEINTRESOURCE(IDD_NetDevSelect);
  526. psp.hInstance = _Module.GetResourceInstance();
  527. psp.hIcon = NULL;
  528. psp.pfnDlgProc = dlgprocNetDev;
  529. psp.lParam = reinterpret_cast<LPARAM>(pNdi);
  530. hpsp = CreatePropertySheetPage(&psp);
  531. if (hpsp)
  532. {
  533. pNdi->pSetupData = pData;
  534. pNdi->hpsp = hpsp;
  535. pWizard->RegisterPage(IDD_NetDevSelect, hpsp,
  536. NetDevPageCleanup, (LPARAM)pNdi);
  537. hr = S_OK;
  538. }
  539. else
  540. {
  541. MemFree(pNdi);
  542. }
  543. }
  544. }
  545. }
  546. TraceHr(ttidWizard, FAL, hr, FALSE, "HrCreateNetDevPage");
  547. return hr;
  548. }
  549. //
  550. // Function: AppendNetDevPage
  551. //
  552. // Purpose: Add the NetDev page, if it was created, to the set of pages
  553. // that will be displayed.
  554. //
  555. // Parameters: pWizard [IN] - Ptr to Wizard Instance
  556. // pahpsp [IN,OUT] - Array of pages to add our page to
  557. // pcPages [IN,OUT] - Count of pages in pahpsp
  558. //
  559. // Returns: Nothing
  560. //
  561. VOID AppendNetDevPage(CWizard *pWizard, HPROPSHEETPAGE* pahpsp, UINT *pcPages)
  562. {
  563. TraceFileFunc(ttidGuiModeSetup);
  564. if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
  565. {
  566. HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_NetDevSelect);
  567. Assert(hPage);
  568. pahpsp[*pcPages] = hPage;
  569. (*pcPages)++;
  570. }
  571. }
  572. //
  573. // Function: NetDevRetrieveInfo
  574. //
  575. // Purpose: To retrieve any network device info
  576. //
  577. // Parameters: pWizard [in] - Contains NetDevInfo blob to populate
  578. //
  579. // Returns: Nothing
  580. //
  581. VOID NetDevRetrieveInfo(CWizard * pWizard)
  582. {
  583. TraceFileFunc(ttidGuiModeSetup);
  584. Assert(pWizard);
  585. if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
  586. {
  587. // The pNdi pointer below was cached in two locations.
  588. // 1) In the HPROPSHEETPAGE lParam for access by the page
  589. // 2) In the wizard so we can make this NetDevRetrieveInfo call.
  590. // This second item was optional and could have been done in the
  591. // InitDialog above instead.
  592. NetDevInfo * pNdi = reinterpret_cast<NetDevInfo *>
  593. (pWizard->GetPageData(IDD_NetDevSelect));
  594. TraceTag(ttidWizard, "NetDev retrieving info...");
  595. if (NULL == pNdi)
  596. return;
  597. // Query all pages that might be added
  598. //
  599. (VOID)HrGetDevicesThatHaveWizardPagesToAdd(&pNdi->hdi);
  600. }
  601. }
  602. //
  603. // Function: HrSendFinishInstallWizardFunction
  604. //
  605. // Purpose: Sends a DIF_NEWDEVICEWIZARD_FINISHINSTALL fcn to the class
  606. // installer (and co-installers). The installers respond
  607. // if there are wizard pages to add
  608. //
  609. // Parameters: hdi [in] - See Device Installer Api for description
  610. // of the structure.
  611. // pdeid [in] - See Device Installer Api
  612. // pndwd [out] - See Device Installer Api
  613. //
  614. //
  615. // Returns: HRESULT. S_OK if successful, or a win32 converted error
  616. //
  617. HRESULT
  618. HrSendFinishInstallWizardFunction(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid,
  619. PSP_NEWDEVICEWIZARD_DATA pndwd)
  620. {
  621. TraceFileFunc(ttidGuiModeSetup);
  622. Assert(IsValidHandle(hdi));
  623. Assert(pdeid);
  624. Assert(pndwd);
  625. ZeroMemory(pndwd, sizeof(*pndwd));
  626. // Set up the structure to retrieve wizard pages
  627. //
  628. pndwd->ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  629. pndwd->ClassInstallHeader.InstallFunction =
  630. DIF_NEWDEVICEWIZARD_FINISHINSTALL;
  631. // Set up our wizard structure in the device structure
  632. HRESULT hr = HrSetupDiSetClassInstallParams(hdi, pdeid,
  633. reinterpret_cast<PSP_CLASSINSTALL_HEADER>(pndwd),
  634. sizeof(*pndwd));
  635. if (SUCCEEDED(hr))
  636. {
  637. // Call the class installers (and co-installers)
  638. hr = HrSetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL,
  639. hdi, pdeid);
  640. if (SUCCEEDED(hr) || SPAPI_E_DI_DO_DEFAULT == hr)
  641. {
  642. // Get the wizard data
  643. hr = HrSetupDiGetFixedSizeClassInstallParams(hdi, pdeid,
  644. reinterpret_cast<PSP_CLASSINSTALL_HEADER>(pndwd),
  645. sizeof(*pndwd));
  646. }
  647. }
  648. TraceError("HrSendFinishInstallWizardFunction", hr);
  649. return hr;
  650. }
  651. //
  652. // Function: HrGetDeviceWizardPages
  653. //
  654. // Purpose: To retrieve wizard pages for a device
  655. //
  656. // Parameters: hdi [in] - See Device Installer Api for description
  657. // of the structure.
  658. // pdeid [in] - See Device Installer Api
  659. // pphpsp [out] - An array of wizard pages for the device
  660. // pcPages [out] - The number of pages in pphpsp
  661. //
  662. //
  663. // Returns: HRESULT. S_OK if successful, or a win32 converted error
  664. //
  665. HRESULT
  666. HrGetDeviceWizardPages(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid,
  667. HPROPSHEETPAGE** pphpsp, DWORD* pcPages)
  668. {
  669. TraceFileFunc(ttidGuiModeSetup);
  670. Assert(IsValidHandle(hdi));
  671. Assert(pdeid);
  672. Assert(pphpsp);
  673. Assert(pcPages);
  674. HRESULT hr;
  675. SP_NEWDEVICEWIZARD_DATA ndwd;
  676. if (( NULL == pphpsp ) || ( NULL == pcPages ) )
  677. {
  678. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  679. }
  680. else
  681. {
  682. *pphpsp = NULL;
  683. *pcPages = 0;
  684. // Get the wizard data
  685. hr = HrSetupDiGetFixedSizeClassInstallParams(hdi, pdeid,
  686. reinterpret_cast<PSP_CLASSINSTALL_HEADER>(&ndwd),
  687. sizeof(ndwd));
  688. // If successful and the correct header is present...
  689. if (SUCCEEDED(hr) && ndwd.NumDynamicPages &&
  690. (DIF_NEWDEVICEWIZARD_FINISHINSTALL == ndwd.ClassInstallHeader.InstallFunction))
  691. {
  692. // Copy the handles to the out parameter
  693. //
  694. *pphpsp = new HPROPSHEETPAGE[ndwd.NumDynamicPages];
  695. if(pphpsp && *pphpsp)
  696. {
  697. CopyMemory(*pphpsp, ndwd.DynamicPages,
  698. sizeof(HPROPSHEETPAGE) * ndwd.NumDynamicPages);
  699. *pcPages = ndwd.NumDynamicPages;
  700. hr = S_OK;
  701. }
  702. else
  703. {
  704. hr = E_OUTOFMEMORY;
  705. }
  706. }
  707. }
  708. TraceError("HrGetDeviceWizardPages", hr);
  709. return hr;
  710. }
  711. //
  712. // Function: HrFillNetDevList
  713. //
  714. // Purpose: To populate the listview with text and data of the ISDN
  715. // cards which need configuration
  716. //
  717. // Parameters: hwndLV - Handle to the the listview control
  718. // pNdi - Net Device Info
  719. //
  720. // Returns: HRESULT. S_OK if successful, or a win32 converted error
  721. //
  722. HRESULT HrFillNetDevList(HWND hwndLV, NetDevInfo * pNdi)
  723. {
  724. TraceFileFunc(ttidGuiModeSetup);
  725. SP_DEVINFO_DATA deid;
  726. DWORD dwIndex = 0;
  727. HRESULT hr = S_OK;
  728. Assert(hwndLV);
  729. Assert(pNdi);
  730. Assert(pNdi->hdi);
  731. while (SUCCEEDED(hr = HrSetupDiEnumDeviceInfo(pNdi->hdi, dwIndex, &deid)))
  732. {
  733. HPROPSHEETPAGE * phpsp = NULL;
  734. DWORD cPages = 0;
  735. hr = HrGetDeviceWizardPages(pNdi->hdi, &deid, &phpsp, &cPages);
  736. if (SUCCEEDED(hr) && (cPages > 0))
  737. {
  738. NetDevItemInfo * pndii = new NetDevItemInfo;
  739. if (NULL != pndii)
  740. {
  741. ZeroMemory(pndii, sizeof(NetDevItemInfo));
  742. pndii->phpsp = phpsp;
  743. pndii->cPages = cPages;
  744. pndii->deid = deid;
  745. #if CHECKED_BY_DEFAULT
  746. pndii->dwFlags = NetDevToggleChecked(pndii->dwFlags);
  747. #else
  748. pndii->dwFlags = 0;
  749. #endif
  750. PWSTR szName = NULL;
  751. hr = HrSetupDiGetDeviceName(pNdi->hdi, &deid, &szName);
  752. if (SUCCEEDED(hr))
  753. {
  754. int nIdx;
  755. LV_ITEM lvi;
  756. int nCount = ListView_GetItemCount(hwndLV);
  757. Assert(NULL != szName);
  758. Assert(lstrlen(szName));
  759. // Add the item info to the list view
  760. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
  761. lvi.iItem = nCount;
  762. lvi.iSubItem = 0;
  763. #if CHECKED_BY_DEFAULT
  764. lvi.state = INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
  765. #else
  766. lvi.state = INDEXTOSTATEIMAGEMASK(SELS_UNCHECKED);
  767. #endif
  768. lvi.stateMask = LVIS_STATEIMAGEMASK;
  769. lvi.pszText = szName;
  770. lvi.cchTextMax = lstrlen(lvi.pszText);
  771. if ( HrSetupDiGetClassImageIndex(&pNdi->cild, &GUID_DEVCLASS_NET, &lvi.iImage) != S_OK )
  772. {
  773. // In case of failure, hard-code the value of the image index of
  774. // Net class image.
  775. lvi.iImage = 18;
  776. }
  777. lvi.lParam = (LPARAM)pndii;
  778. if (-1 == ListView_InsertItem(hwndLV, &lvi))
  779. {
  780. TraceError("HrFillNetDevList - ListView_InsertItem", E_OUTOFMEMORY);
  781. }
  782. delete [](BYTE *)szName;
  783. }
  784. }
  785. }
  786. dwIndex++;
  787. }
  788. // Convert running out of items to S_OK
  789. //
  790. if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
  791. {
  792. hr = S_OK;
  793. }
  794. TraceError("HrFillNetDevList", hr);
  795. return hr;
  796. }
  797. //
  798. // Function: HrGetDevicesThatHaveWizardPagesToAdd
  799. //
  800. // Purpose: To retrieve a list of devices that have wizard pages to add
  801. // to the networking wizard
  802. //
  803. // Parameters: phdi [out] - See Device Install Api for description of the
  804. // structure. This will hold a list of device.
  805. //
  806. // Returns: HRESULT
  807. //
  808. HRESULT
  809. HrGetDevicesThatHaveWizardPagesToAdd(HDEVINFO* phdi)
  810. {
  811. TraceFileFunc(ttidGuiModeSetup);
  812. Assert(phdi);
  813. // initialize out param
  814. *phdi = NULL;
  815. // Create a device info list to hold the list of devices
  816. HRESULT hr = HrSetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL,
  817. DIGCF_PRESENT, phdi);
  818. if (SUCCEEDED(hr))
  819. {
  820. SP_DEVINFO_DATA deid;
  821. DWORD dwIndex = 0;
  822. SP_NEWDEVICEWIZARD_DATA ndwd = {0};
  823. DWORD dwConfigFlags = 0;
  824. BOOL fDeleteDeviceInfo;
  825. // Enumerate each device in phdi and check if it was a failed install
  826. // Gui-mode setup marks any device with wizard pages as needing
  827. // reinstall
  828. //
  829. while (SUCCEEDED(hr = HrSetupDiEnumDeviceInfo(*phdi, dwIndex, &deid)))
  830. {
  831. fDeleteDeviceInfo = FALSE;
  832. // Get the current config flags for the device
  833. // We don't need the return value because we will be checking
  834. // if pdwConfigFlags is non-null
  835. (void) HrSetupDiGetDeviceRegistryProperty(*phdi, &deid,
  836. SPDRP_CONFIGFLAGS, NULL,
  837. (BYTE*)(&dwConfigFlags), sizeof(dwConfigFlags), NULL);
  838. // Are there any config flags and if so, is the reinstall bit
  839. // present?
  840. if (dwConfigFlags & CONFIGFLAG_REINSTALL)
  841. {
  842. // Note that we leak this (pdeid) and we don't care because it's
  843. // only twelve bytes per adapter and only during setup. Note also
  844. // that the reason we allocate as opposed to use the stack is so that
  845. // the data passed lives at least as long as the wizard pages themselves.
  846. //
  847. PSP_DEVINFO_DATA pdeid = new SP_DEVINFO_DATA;
  848. if(pdeid)
  849. {
  850. CopyMemory(pdeid, &deid, sizeof(SP_DEVINFO_DATA));
  851. // Get any wizard pages
  852. //
  853. hr = HrSendFinishInstallWizardFunction(*phdi, pdeid, &ndwd);
  854. if (FAILED(hr) || !ndwd.NumDynamicPages)
  855. {
  856. // no pages so we will delete this device info from
  857. // our list
  858. fDeleteDeviceInfo = TRUE;
  859. // Clean up because we didn't keep this.
  860. //
  861. delete pdeid;
  862. }
  863. }
  864. // clear the config flags for the next pass
  865. dwConfigFlags = 0;
  866. }
  867. else
  868. {
  869. // no config flags so there weren't any pages. We will
  870. // delete this device info from our list
  871. fDeleteDeviceInfo = TRUE;
  872. }
  873. if (fDeleteDeviceInfo)
  874. {
  875. // There were no pages added so remove the device
  876. // from our list
  877. (void) SetupDiDeleteDeviceInfo(*phdi, &deid);
  878. }
  879. else
  880. {
  881. dwIndex++;
  882. }
  883. }
  884. // Failures during this portion should be ignored since we may have
  885. // successfully added devices to phdi
  886. if (FAILED(hr))
  887. {
  888. hr = S_OK;
  889. }
  890. }
  891. TraceError("HrGetDevicesThatHaveWizardPagesToAdd", hr);
  892. return hr;
  893. }