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
1064 lines
32 KiB
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "connutil.h"
|
|
#include "resource.h"
|
|
#include "ncreg.h"
|
|
#include "nsres.h"
|
|
#include "wizard.h"
|
|
#include "ncsetup.h"
|
|
#include "..\lanui\util.h"
|
|
#include "ncmisc.h"
|
|
|
|
// Note: This module needs to touch pWizard as little as possible because it
|
|
// it is deleted before this page is entered.
|
|
//
|
|
|
|
|
|
inline BOOL FNetDevPagesAdded(DWORD dw)
|
|
{
|
|
return ((dw & 0x10000000) != 0);
|
|
}
|
|
|
|
inline DWORD DwNetDevMarkPagesAdded(DWORD dw)
|
|
{
|
|
return (dw | 0x10000000);
|
|
}
|
|
|
|
inline BOOL FNetDevChecked(DWORD dw)
|
|
{
|
|
return ((dw & 0x01000000) != 0);
|
|
}
|
|
|
|
inline DWORD NetDevToggleChecked(DWORD dw)
|
|
{
|
|
if (dw & 0x01000000)
|
|
return (dw & ~0x01000000);
|
|
else
|
|
return (dw | 0x01000000);
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
SP_CLASSIMAGELIST_DATA cild;
|
|
HIMAGELIST hImageStateIcons;
|
|
HDEVINFO hdi;
|
|
HPROPSHEETPAGE hpsp; // The wnetdev HPROPSHEETPAGE
|
|
PINTERNAL_SETUP_DATA pSetupData;
|
|
} NetDevInfo;
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwFlags;
|
|
DWORD cPages;
|
|
HPROPSHEETPAGE * phpsp;
|
|
SP_DEVINFO_DATA deid;
|
|
} NetDevItemInfo;
|
|
|
|
// CHECKED_BY_DEFAULT controls whether the items needing configuration are
|
|
// checked by default or not.
|
|
//
|
|
#define CHECKED_BY_DEFAULT 1
|
|
|
|
// TRUE if all the devices are selected for configuration.
|
|
//
|
|
static BOOL bAllSelected=FALSE;
|
|
|
|
// DevInst of the device whose property page will be displayed after
|
|
// the first page on which device selection is shown.
|
|
//
|
|
static DWORD dwFirstDevInst=0;
|
|
|
|
HRESULT HrGetDevicesThatHaveWizardPagesToAdd(HDEVINFO* phdi);
|
|
HRESULT HrFillNetDevList(HWND hwndLV, NetDevInfo * pNdi);
|
|
|
|
|
|
// The property page of every isdn device queries if all the
|
|
// devices have been selected or not. We return TRUE only if
|
|
// all the devices have been selected and the query is from
|
|
// the device whose property page is displayed first. This
|
|
// is done to prevent the user from coming back to the device
|
|
// selection page since there is nothing to do once all the
|
|
// devices have been selected.
|
|
//
|
|
|
|
VOID SetSelectedAll (HWND hwndDlg, DWORD dwDevInst)
|
|
{
|
|
|
|
if (dwDevInst == dwFirstDevInst)
|
|
{
|
|
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)bAllSelected );
|
|
}
|
|
else
|
|
{
|
|
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)FALSE );
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
HRESULT HrNetDevInitListView(HWND hwndLV, NetDevInfo * pNdi)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
DWORD dwStyle;
|
|
RECT rc;
|
|
LV_COLUMN lvc = {0};
|
|
SP_CLASSIMAGELIST_DATA * pcild;
|
|
|
|
Assert(hwndLV);
|
|
Assert(NULL != pNdi);
|
|
|
|
// Set the shared image lists bit so the caller can destroy the class
|
|
// image lists itself
|
|
//
|
|
dwStyle = GetWindowLong(hwndLV, GWL_STYLE);
|
|
SetWindowLong(hwndLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
|
|
|
|
// Create small image lists
|
|
//
|
|
HRESULT hr = HrSetupDiGetClassImageList(&pNdi->cild);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AssertSz(pNdi->cild.ImageList, "No class image list data!");
|
|
ListView_SetImageList(hwndLV, pNdi->cild.ImageList, LVSIL_SMALL);
|
|
}
|
|
else
|
|
{
|
|
TraceError("HrSetupDiGetClassImageList returns failure", hr);
|
|
hr = S_OK;
|
|
}
|
|
|
|
// Create state image lists
|
|
pNdi->hImageStateIcons = ImageList_LoadBitmapAndMirror(
|
|
_Module.GetResourceInstance(),
|
|
MAKEINTRESOURCE(IDB_CHECKSTATE),
|
|
16,
|
|
0,
|
|
PALETTEINDEX(6));
|
|
ListView_SetImageList(hwndLV, pNdi->hImageStateIcons, LVSIL_STATE);
|
|
|
|
GetClientRect(hwndLV, &rc);
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = rc.right;
|
|
// $REVIEW(tongl 12\22\97): Fix for bug#127472
|
|
// lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
|
|
|
|
ListView_InsertColumn(hwndLV, 0, &lvc);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Selete the first item
|
|
ListView_SetItemState(hwndLV, 0, LVIS_SELECTED, LVIS_SELECTED);
|
|
}
|
|
|
|
TraceError("HrNetDevInitListView", hr);
|
|
return hr;
|
|
}
|
|
|
|
BOOL OnNetDevInitDialog(HWND hwndDlg, LPARAM lParam)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
NetDevInfo * pNdi;
|
|
PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam;
|
|
Assert(psp->lParam);
|
|
pNdi = reinterpret_cast<NetDevInfo *>(psp->lParam);
|
|
::SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pNdi);
|
|
|
|
if (NULL != pNdi)
|
|
{
|
|
HWND hwndLV = GetDlgItem(hwndDlg, LVC_NETDEVLIST);
|
|
Assert(hwndLV);
|
|
|
|
if (SUCCEEDED(HrNetDevInitListView(hwndLV, pNdi)))
|
|
{
|
|
// Populate the list
|
|
//
|
|
if (NULL != pNdi->hdi)
|
|
{
|
|
(VOID)HrFillNetDevList(hwndLV, pNdi);
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE; // We didn't change the default item of focus
|
|
}
|
|
|
|
VOID OnNetDevDestroy(HWND hwndDlg)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
NetDevInfo *pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
|
|
if (NULL != pNdi)
|
|
{
|
|
if (pNdi->cild.ImageList)
|
|
{
|
|
// Destroy the class image list data
|
|
(void) HrSetupDiDestroyClassImageList(&pNdi->cild);
|
|
}
|
|
|
|
if (pNdi->hImageStateIcons)
|
|
{
|
|
ImageList_Destroy(pNdi->hImageStateIcons);
|
|
}
|
|
|
|
// The cleanup any pages we loaded for the providers
|
|
// but did not add to setup wizard will be done by processing the
|
|
// LVN_DELETEITEM message
|
|
//
|
|
}
|
|
|
|
::SetWindowLongPtr(hwndDlg, DWLP_USER, 0);
|
|
if (NULL != pNdi)
|
|
{
|
|
MemFree(pNdi);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: OnNetDevPageNext
|
|
//
|
|
// Purpose: Handle the PSN_WIZNEXT notification
|
|
//
|
|
// Parameters: hwndDlg - Handle to NetDev dialog
|
|
//
|
|
// Returns: BOOL, TRUE if we processed the message
|
|
//
|
|
BOOL OnNetDevPageNext(HWND hwndDlg)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
BOOL fRet = FALSE; // Accept the default behaviour
|
|
HWND hwndLV = GetDlgItem(hwndDlg, LVC_NETDEVLIST);
|
|
int nCount = ListView_GetItemCount(hwndLV);
|
|
int nCountSelected = 0;
|
|
NetDevInfo *pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
|
|
|
|
if ((0 < nCount) && (NULL != pNdi) && (NULL != pNdi->hpsp))
|
|
{
|
|
fRet = TRUE;
|
|
|
|
// Loop through the items in the listview if any are checked
|
|
// But have not yet been marked as having their pages added,
|
|
// add the pages and mark the item.
|
|
//
|
|
|
|
for (int nIdx=0; nIdx<nCount; nIdx++)
|
|
{
|
|
LV_ITEM lvi = {0};
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nIdx;
|
|
|
|
if (TRUE == ListView_GetItem(hwndLV, &lvi))
|
|
{
|
|
NetDevItemInfo * pndii = (NetDevItemInfo*)lvi.lParam;
|
|
|
|
// Add the pages to the wizard if checked in the UI
|
|
// but not already added.
|
|
//
|
|
|
|
if (pndii && FNetDevChecked(pndii->dwFlags))
|
|
{
|
|
|
|
// Keep track of how many device have been selected.
|
|
//
|
|
nCountSelected++;
|
|
|
|
if (!FNetDevPagesAdded(pndii->dwFlags))
|
|
{
|
|
//
|
|
// Since property pages are added when the device is
|
|
// selected, any device could end up being the first to
|
|
// show the property page as the devices could be
|
|
// selected in a random order. So, we always save the
|
|
// device instance in case this is the last device
|
|
// selected.
|
|
|
|
dwFirstDevInst = pndii->deid.DevInst;
|
|
|
|
// Mark the pages as added
|
|
//
|
|
pndii->dwFlags = DwNetDevMarkPagesAdded(pndii->dwFlags);
|
|
|
|
for (DWORD nIdx = pndii->cPages; nIdx > 0; nIdx--)
|
|
{
|
|
PropSheet_InsertPage(GetParent(hwndDlg),
|
|
(WPARAM)pNdi->hpsp,
|
|
(LPARAM)pndii->phpsp[nIdx - 1]);
|
|
}
|
|
|
|
// After loading the pages mark the option, uncheckable
|
|
// (Note: with testing we might be able to support removal)
|
|
//
|
|
lvi.state = INDEXTOSTATEIMAGEMASK(SELS_INTERMEDIATE);
|
|
lvi.mask = LVIF_STATE;
|
|
lvi.stateMask = LVIS_STATEIMAGEMASK;
|
|
BOOL ret = ListView_SetItem(hwndLV, &lvi);
|
|
|
|
// Clear the reinstall flag on the device needing configuration
|
|
//
|
|
SetupDiSetConfigFlags(pNdi->hdi, &(pndii->deid),
|
|
CONFIGFLAG_REINSTALL, SDFBO_XOR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bAllSelected = nCountSelected == nCount;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//
|
|
// Function: OnNetDevPageActivate
|
|
//
|
|
// Purpose: Handle the PSN_SETACTIVE notification
|
|
//
|
|
// Parameters: hwndDlg - Handle to NetDev dialog
|
|
//
|
|
// Returns: BOOL, TRUE
|
|
//
|
|
BOOL OnNetDevPageActivate(HWND hwndDlg)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
TraceTag(ttidWizard, "Entering NetDev page...");
|
|
|
|
NetDevInfo *pNdi;
|
|
|
|
if (0 == ListView_GetItemCount(GetDlgItem(hwndDlg, LVC_NETDEVLIST)))
|
|
{
|
|
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
|
|
TraceTag(ttidWizard, "NetDev page refuses activation, no items to display.");
|
|
}
|
|
else
|
|
{
|
|
pNdi = (NetDevInfo *)::GetWindowLongPtr(hwndDlg, DWLP_USER);
|
|
|
|
Assert(pNdi);
|
|
|
|
if ( pNdi )
|
|
{
|
|
Assert(pNdi->pSetupData);
|
|
|
|
if ( pNdi->pSetupData )
|
|
{
|
|
pNdi->pSetupData->ShowHideWizardPage(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
// disable the back button (#342922)
|
|
::SendMessage(GetParent(hwndDlg), PSM_SETWIZBUTTONS, 0, (LPARAM)(PSWIZB_NEXT));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Function: OnListViewDeleteItem
|
|
//
|
|
// Purpose: Handle the LVN_DELETEITEM notification
|
|
//
|
|
// Parameters: hwndList - Handle to listview control
|
|
// pnmh - Ptr to the NMHDR for this notification
|
|
//
|
|
// Returns: none
|
|
//
|
|
VOID OnListViewDeleteItem(HWND hwndList, LPNMHDR pnmh)
|
|
{
|
|
NetDevItemInfo * pndii = NULL;
|
|
NM_LISTVIEW * pnmlv = reinterpret_cast<NM_LISTVIEW *>(pnmh);
|
|
LV_ITEM lvi = {0};
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = pnmlv->iItem;
|
|
|
|
if (TRUE == ListView_GetItem(hwndList, &lvi))
|
|
{
|
|
NetDevItemInfo * pndii = (NetDevItemInfo*)lvi.lParam;
|
|
|
|
// Delete pages held, but that were not added to the wizard
|
|
//
|
|
if (pndii && !FNetDevPagesAdded(pndii->dwFlags))
|
|
{
|
|
for (DWORD nIdx = 0; nIdx < pndii->cPages; nIdx++)
|
|
{
|
|
DestroyPropertySheetPage(pndii->phpsp[nIdx]);
|
|
}
|
|
|
|
delete pndii;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: OnListViewDeleteItem
|
|
//
|
|
// Purpose: Handle the NM_CLICK notification for the listview control
|
|
//
|
|
// Parameters: hwndList - Handle to listview control
|
|
// pnmh - Ptr to the NMHDR for this notification
|
|
//
|
|
// Returns: none
|
|
//
|
|
VOID OnListViewClick(HWND hwndList, LPNMHDR pnmh)
|
|
{
|
|
INT iItem;
|
|
DWORD dwpts;
|
|
RECT rc;
|
|
LV_HITTESTINFO lvhti;
|
|
|
|
// we have the location
|
|
dwpts = GetMessagePos();
|
|
|
|
// translate it relative to the listview
|
|
GetWindowRect(hwndList, &rc);
|
|
|
|
lvhti.pt.x = LOWORD(dwpts) - rc.left;
|
|
lvhti.pt.y = HIWORD(dwpts) - rc.top;
|
|
|
|
// get currently selected item
|
|
iItem = ListView_HitTest(hwndList, &lvhti);
|
|
|
|
// if no selection, or click not on state return false
|
|
if (-1 != iItem)
|
|
{
|
|
// set the current selection
|
|
//
|
|
ListView_SetItemState(hwndList, iItem, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
if (LVHT_ONITEMSTATEICON != (LVHT_ONITEMSTATEICON & lvhti.flags))
|
|
{
|
|
iItem = -1;
|
|
}
|
|
|
|
if (-1 != iItem)
|
|
{
|
|
LV_ITEM lvItem;
|
|
|
|
// Get the item
|
|
//
|
|
lvItem.iItem = iItem;
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iSubItem = 0;
|
|
|
|
if (ListView_GetItem(hwndList, &lvItem))
|
|
{
|
|
Assert(lvItem.lParam);
|
|
NetDevItemInfo *pndii = (NetDevItemInfo*)lvItem.lParam;
|
|
|
|
// Toggle the state (only if we haven't already added pages)
|
|
//
|
|
if (pndii && !FNetDevPagesAdded(pndii->dwFlags))
|
|
{
|
|
pndii->dwFlags = NetDevToggleChecked(pndii->dwFlags);
|
|
if (FNetDevChecked(pndii->dwFlags))
|
|
lvItem.state = INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
|
|
else
|
|
lvItem.state = INDEXTOSTATEIMAGEMASK(SELS_UNCHECKED);
|
|
|
|
lvItem.mask = LVIF_STATE;
|
|
lvItem.stateMask = LVIS_STATEIMAGEMASK;
|
|
BOOL ret = ListView_SetItem(hwndList, &lvItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: dlgprocNetDev
|
|
//
|
|
// Purpose: Dialog Procedure for the NetDev wizard page
|
|
//
|
|
// Parameters: standard dlgproc parameters
|
|
//
|
|
// Returns: INT_PTR
|
|
//
|
|
INT_PTR CALLBACK dlgprocNetDev( HWND hwndDlg, UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam )
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
BOOL frt = FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
OnNetDevInitDialog(hwndDlg, lParam);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
OnNetDevDestroy(hwndDlg);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|
|
|
if (LVC_NETDEVLIST == (int)pnmh->idFrom)
|
|
{
|
|
Assert(GetDlgItem(hwndDlg, LVC_NETDEVLIST) == pnmh->hwndFrom);
|
|
if (NM_CLICK == pnmh->code)
|
|
{
|
|
OnListViewClick(pnmh->hwndFrom, pnmh);
|
|
}
|
|
else if (LVN_DELETEITEM == pnmh->code)
|
|
{
|
|
OnListViewDeleteItem(pnmh->hwndFrom, pnmh);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Must be a property sheet notification
|
|
//
|
|
switch (pnmh->code)
|
|
{
|
|
// propsheet notification
|
|
case PSN_HELP:
|
|
break;
|
|
|
|
case PSN_SETACTIVE:
|
|
frt = OnNetDevPageActivate(hwndDlg);
|
|
break;
|
|
|
|
case PSN_APPLY:
|
|
break;
|
|
|
|
case PSN_KILLACTIVE:
|
|
break;
|
|
|
|
case PSN_RESET:
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
break;
|
|
|
|
case PSN_WIZFINISH:
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
frt = OnNetDevPageNext(hwndDlg);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SELECTED_ALL:
|
|
|
|
SetSelectedAll (hwndDlg, (DWORD)lParam);
|
|
frt = TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return( frt );
|
|
}
|
|
|
|
|
|
//
|
|
// Function: NetDevPageCleanup
|
|
//
|
|
// Purpose: As a callback function to allow any page allocated memory
|
|
// to be cleaned up, after the page will no longer be accessed.
|
|
//
|
|
// Parameters: pWizard [IN] - The wizard against which the page called
|
|
// register page
|
|
// lParam [IN] - The lParam supplied in the RegisterPage call
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
VOID NetDevPageCleanup(CWizard *pWizard, LPARAM lParam)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
// Nothing to do. The pNdi is destroyed by the WM_DESTROY message
|
|
// processed above.
|
|
}
|
|
|
|
//
|
|
// Function: CreateNetDevPage
|
|
//
|
|
// Purpose: To determine if the NetDev page needs to be shown, and to
|
|
// to create the page if requested.
|
|
//
|
|
// Parameters: pWizard [IN] - Ptr to a Wizard instance
|
|
// pData [IN] - Context data to describe the world in
|
|
// which the Wizard will be run
|
|
// fCountOnly [IN] - If True, only the maximum number of
|
|
// pages this routine will create need
|
|
// be determined.
|
|
// pnPages [IN] - Increment by the number of pages
|
|
// to create/created
|
|
//
|
|
// Returns: HRESULT, S_OK on success
|
|
//
|
|
HRESULT HrCreateNetDevPage(CWizard *pWizard, PINTERNAL_SETUP_DATA pData,
|
|
BOOL fCountOnly, UINT *pnPages)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
|
|
{
|
|
(*pnPages)++;
|
|
|
|
// If not only counting, create and register the page
|
|
if (!fCountOnly)
|
|
{
|
|
HPROPSHEETPAGE hpsp;
|
|
PROPSHEETPAGE psp;
|
|
NetDevInfo * pNdi;
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
TraceTag(ttidWizard, "Creating NetDev Page");
|
|
|
|
pNdi = reinterpret_cast<NetDevInfo *>(MemAlloc(sizeof(NetDevInfo)));
|
|
if (NULL != pNdi)
|
|
{
|
|
ZeroMemory(pNdi, sizeof(NetDevInfo));
|
|
|
|
psp.dwSize = sizeof( PROPSHEETPAGE );
|
|
psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
|
|
psp.pszHeaderTitle = SzLoadIds(IDS_T_NetDev);
|
|
psp.pszHeaderSubTitle = SzLoadIds(IDS_ST_NetDev);
|
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_NetDevSelect);
|
|
psp.hInstance = _Module.GetResourceInstance();
|
|
psp.hIcon = NULL;
|
|
psp.pfnDlgProc = dlgprocNetDev;
|
|
psp.lParam = reinterpret_cast<LPARAM>(pNdi);
|
|
|
|
hpsp = CreatePropertySheetPage(&psp);
|
|
if (hpsp)
|
|
{
|
|
pNdi->pSetupData = pData;
|
|
pNdi->hpsp = hpsp;
|
|
pWizard->RegisterPage(IDD_NetDevSelect, hpsp,
|
|
NetDevPageCleanup, (LPARAM)pNdi);
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
MemFree(pNdi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidWizard, FAL, hr, FALSE, "HrCreateNetDevPage");
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Function: AppendNetDevPage
|
|
//
|
|
// Purpose: Add the NetDev page, if it was created, to the set of pages
|
|
// that will be displayed.
|
|
//
|
|
// Parameters: pWizard [IN] - Ptr to Wizard Instance
|
|
// pahpsp [IN,OUT] - Array of pages to add our page to
|
|
// pcPages [IN,OUT] - Count of pages in pahpsp
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
VOID AppendNetDevPage(CWizard *pWizard, HPROPSHEETPAGE* pahpsp, UINT *pcPages)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
|
|
{
|
|
HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_NetDevSelect);
|
|
Assert(hPage);
|
|
pahpsp[*pcPages] = hPage;
|
|
(*pcPages)++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: NetDevRetrieveInfo
|
|
//
|
|
// Purpose: To retrieve any network device info
|
|
//
|
|
// Parameters: pWizard [in] - Contains NetDevInfo blob to populate
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
VOID NetDevRetrieveInfo(CWizard * pWizard)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
Assert(pWizard);
|
|
|
|
if (!IsPostInstall(pWizard) && !IsUnattended(pWizard) && !IsUpgrade(pWizard))
|
|
{
|
|
// The pNdi pointer below was cached in two locations.
|
|
// 1) In the HPROPSHEETPAGE lParam for access by the page
|
|
// 2) In the wizard so we can make this NetDevRetrieveInfo call.
|
|
// This second item was optional and could have been done in the
|
|
// InitDialog above instead.
|
|
NetDevInfo * pNdi = reinterpret_cast<NetDevInfo *>
|
|
(pWizard->GetPageData(IDD_NetDevSelect));
|
|
|
|
TraceTag(ttidWizard, "NetDev retrieving info...");
|
|
|
|
if (NULL == pNdi)
|
|
return;
|
|
|
|
// Query all pages that might be added
|
|
//
|
|
(VOID)HrGetDevicesThatHaveWizardPagesToAdd(&pNdi->hdi);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Function: HrSendFinishInstallWizardFunction
|
|
//
|
|
// Purpose: Sends a DIF_NEWDEVICEWIZARD_FINISHINSTALL fcn to the class
|
|
// installer (and co-installers). The installers respond
|
|
// if there are wizard pages to add
|
|
//
|
|
// Parameters: hdi [in] - See Device Installer Api for description
|
|
// of the structure.
|
|
// pdeid [in] - See Device Installer Api
|
|
// pndwd [out] - See Device Installer Api
|
|
//
|
|
//
|
|
// Returns: HRESULT. S_OK if successful, or a win32 converted error
|
|
//
|
|
HRESULT
|
|
HrSendFinishInstallWizardFunction(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid,
|
|
PSP_NEWDEVICEWIZARD_DATA pndwd)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
Assert(IsValidHandle(hdi));
|
|
Assert(pdeid);
|
|
Assert(pndwd);
|
|
|
|
ZeroMemory(pndwd, sizeof(*pndwd));
|
|
|
|
// Set up the structure to retrieve wizard pages
|
|
//
|
|
pndwd->ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
|
pndwd->ClassInstallHeader.InstallFunction =
|
|
DIF_NEWDEVICEWIZARD_FINISHINSTALL;
|
|
|
|
|
|
// Set up our wizard structure in the device structure
|
|
HRESULT hr = HrSetupDiSetClassInstallParams(hdi, pdeid,
|
|
reinterpret_cast<PSP_CLASSINSTALL_HEADER>(pndwd),
|
|
sizeof(*pndwd));
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call the class installers (and co-installers)
|
|
hr = HrSetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL,
|
|
hdi, pdeid);
|
|
|
|
if (SUCCEEDED(hr) || SPAPI_E_DI_DO_DEFAULT == hr)
|
|
{
|
|
// Get the wizard data
|
|
hr = HrSetupDiGetFixedSizeClassInstallParams(hdi, pdeid,
|
|
reinterpret_cast<PSP_CLASSINSTALL_HEADER>(pndwd),
|
|
sizeof(*pndwd));
|
|
}
|
|
}
|
|
|
|
TraceError("HrSendFinishInstallWizardFunction", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Function: HrGetDeviceWizardPages
|
|
//
|
|
// Purpose: To retrieve wizard pages for a device
|
|
//
|
|
// Parameters: hdi [in] - See Device Installer Api for description
|
|
// of the structure.
|
|
// pdeid [in] - See Device Installer Api
|
|
// pphpsp [out] - An array of wizard pages for the device
|
|
// pcPages [out] - The number of pages in pphpsp
|
|
//
|
|
//
|
|
// Returns: HRESULT. S_OK if successful, or a win32 converted error
|
|
//
|
|
HRESULT
|
|
HrGetDeviceWizardPages(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid,
|
|
HPROPSHEETPAGE** pphpsp, DWORD* pcPages)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
Assert(IsValidHandle(hdi));
|
|
Assert(pdeid);
|
|
Assert(pphpsp);
|
|
Assert(pcPages);
|
|
|
|
HRESULT hr;
|
|
SP_NEWDEVICEWIZARD_DATA ndwd;
|
|
|
|
if (( NULL == pphpsp ) || ( NULL == pcPages ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
|
|
}
|
|
else
|
|
{
|
|
*pphpsp = NULL;
|
|
*pcPages = 0;
|
|
|
|
// Get the wizard data
|
|
hr = HrSetupDiGetFixedSizeClassInstallParams(hdi, pdeid,
|
|
reinterpret_cast<PSP_CLASSINSTALL_HEADER>(&ndwd),
|
|
sizeof(ndwd));
|
|
|
|
// If successful and the correct header is present...
|
|
if (SUCCEEDED(hr) && ndwd.NumDynamicPages &&
|
|
(DIF_NEWDEVICEWIZARD_FINISHINSTALL == ndwd.ClassInstallHeader.InstallFunction))
|
|
{
|
|
// Copy the handles to the out parameter
|
|
//
|
|
*pphpsp = new HPROPSHEETPAGE[ndwd.NumDynamicPages];
|
|
if(pphpsp && *pphpsp)
|
|
{
|
|
CopyMemory(*pphpsp, ndwd.DynamicPages,
|
|
sizeof(HPROPSHEETPAGE) * ndwd.NumDynamicPages);
|
|
*pcPages = ndwd.NumDynamicPages;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceError("HrGetDeviceWizardPages", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Function: HrFillNetDevList
|
|
//
|
|
// Purpose: To populate the listview with text and data of the ISDN
|
|
// cards which need configuration
|
|
//
|
|
// Parameters: hwndLV - Handle to the the listview control
|
|
// pNdi - Net Device Info
|
|
//
|
|
// Returns: HRESULT. S_OK if successful, or a win32 converted error
|
|
//
|
|
HRESULT HrFillNetDevList(HWND hwndLV, NetDevInfo * pNdi)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
SP_DEVINFO_DATA deid;
|
|
DWORD dwIndex = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
Assert(hwndLV);
|
|
Assert(pNdi);
|
|
Assert(pNdi->hdi);
|
|
while (SUCCEEDED(hr = HrSetupDiEnumDeviceInfo(pNdi->hdi, dwIndex, &deid)))
|
|
{
|
|
HPROPSHEETPAGE * phpsp = NULL;
|
|
DWORD cPages = 0;
|
|
|
|
hr = HrGetDeviceWizardPages(pNdi->hdi, &deid, &phpsp, &cPages);
|
|
if (SUCCEEDED(hr) && (cPages > 0))
|
|
{
|
|
NetDevItemInfo * pndii = new NetDevItemInfo;
|
|
if (NULL != pndii)
|
|
{
|
|
ZeroMemory(pndii, sizeof(NetDevItemInfo));
|
|
pndii->phpsp = phpsp;
|
|
pndii->cPages = cPages;
|
|
pndii->deid = deid;
|
|
|
|
#if CHECKED_BY_DEFAULT
|
|
pndii->dwFlags = NetDevToggleChecked(pndii->dwFlags);
|
|
#else
|
|
pndii->dwFlags = 0;
|
|
#endif
|
|
|
|
PWSTR szName = NULL;
|
|
hr = HrSetupDiGetDeviceName(pNdi->hdi, &deid, &szName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
int nIdx;
|
|
LV_ITEM lvi;
|
|
int nCount = ListView_GetItemCount(hwndLV);
|
|
|
|
Assert(NULL != szName);
|
|
Assert(lstrlen(szName));
|
|
|
|
// Add the item info to the list view
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
|
|
lvi.iItem = nCount;
|
|
lvi.iSubItem = 0;
|
|
#if CHECKED_BY_DEFAULT
|
|
lvi.state = INDEXTOSTATEIMAGEMASK(SELS_CHECKED);
|
|
#else
|
|
lvi.state = INDEXTOSTATEIMAGEMASK(SELS_UNCHECKED);
|
|
#endif
|
|
lvi.stateMask = LVIS_STATEIMAGEMASK;
|
|
lvi.pszText = szName;
|
|
lvi.cchTextMax = lstrlen(lvi.pszText);
|
|
|
|
if ( HrSetupDiGetClassImageIndex(&pNdi->cild, &GUID_DEVCLASS_NET, &lvi.iImage) != S_OK )
|
|
{
|
|
// In case of failure, hard-code the value of the image index of
|
|
// Net class image.
|
|
|
|
lvi.iImage = 18;
|
|
}
|
|
|
|
lvi.lParam = (LPARAM)pndii;
|
|
|
|
if (-1 == ListView_InsertItem(hwndLV, &lvi))
|
|
{
|
|
TraceError("HrFillNetDevList - ListView_InsertItem", E_OUTOFMEMORY);
|
|
}
|
|
|
|
delete [](BYTE *)szName;
|
|
}
|
|
}
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
// Convert running out of items to S_OK
|
|
//
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("HrFillNetDevList", hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Function: HrGetDevicesThatHaveWizardPagesToAdd
|
|
//
|
|
// Purpose: To retrieve a list of devices that have wizard pages to add
|
|
// to the networking wizard
|
|
//
|
|
// Parameters: phdi [out] - See Device Install Api for description of the
|
|
// structure. This will hold a list of device.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
HRESULT
|
|
HrGetDevicesThatHaveWizardPagesToAdd(HDEVINFO* phdi)
|
|
{
|
|
TraceFileFunc(ttidGuiModeSetup);
|
|
|
|
Assert(phdi);
|
|
|
|
// initialize out param
|
|
*phdi = NULL;
|
|
|
|
// Create a device info list to hold the list of devices
|
|
HRESULT hr = HrSetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL,
|
|
DIGCF_PRESENT, phdi);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SP_DEVINFO_DATA deid;
|
|
DWORD dwIndex = 0;
|
|
SP_NEWDEVICEWIZARD_DATA ndwd = {0};
|
|
DWORD dwConfigFlags = 0;
|
|
BOOL fDeleteDeviceInfo;
|
|
|
|
// Enumerate each device in phdi and check if it was a failed install
|
|
// Gui-mode setup marks any device with wizard pages as needing
|
|
// reinstall
|
|
//
|
|
while (SUCCEEDED(hr = HrSetupDiEnumDeviceInfo(*phdi, dwIndex, &deid)))
|
|
{
|
|
fDeleteDeviceInfo = FALSE;
|
|
// Get the current config flags for the device
|
|
// We don't need the return value because we will be checking
|
|
// if pdwConfigFlags is non-null
|
|
(void) HrSetupDiGetDeviceRegistryProperty(*phdi, &deid,
|
|
SPDRP_CONFIGFLAGS, NULL,
|
|
(BYTE*)(&dwConfigFlags), sizeof(dwConfigFlags), NULL);
|
|
|
|
|
|
// Are there any config flags and if so, is the reinstall bit
|
|
// present?
|
|
if (dwConfigFlags & CONFIGFLAG_REINSTALL)
|
|
{
|
|
// Note that we leak this (pdeid) and we don't care because it's
|
|
// only twelve bytes per adapter and only during setup. Note also
|
|
// that the reason we allocate as opposed to use the stack is so that
|
|
// the data passed lives at least as long as the wizard pages themselves.
|
|
//
|
|
PSP_DEVINFO_DATA pdeid = new SP_DEVINFO_DATA;
|
|
|
|
if(pdeid)
|
|
{
|
|
CopyMemory(pdeid, &deid, sizeof(SP_DEVINFO_DATA));
|
|
|
|
// Get any wizard pages
|
|
//
|
|
hr = HrSendFinishInstallWizardFunction(*phdi, pdeid, &ndwd);
|
|
|
|
if (FAILED(hr) || !ndwd.NumDynamicPages)
|
|
{
|
|
// no pages so we will delete this device info from
|
|
// our list
|
|
fDeleteDeviceInfo = TRUE;
|
|
|
|
// Clean up because we didn't keep this.
|
|
//
|
|
delete pdeid;
|
|
}
|
|
}
|
|
|
|
// clear the config flags for the next pass
|
|
dwConfigFlags = 0;
|
|
}
|
|
else
|
|
{
|
|
// no config flags so there weren't any pages. We will
|
|
// delete this device info from our list
|
|
fDeleteDeviceInfo = TRUE;
|
|
}
|
|
|
|
if (fDeleteDeviceInfo)
|
|
{
|
|
// There were no pages added so remove the device
|
|
// from our list
|
|
(void) SetupDiDeleteDeviceInfo(*phdi, &deid);
|
|
}
|
|
else
|
|
{
|
|
dwIndex++;
|
|
}
|
|
}
|
|
|
|
// Failures during this portion should be ignored since we may have
|
|
// successfully added devices to phdi
|
|
if (FAILED(hr))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
TraceError("HrGetDevicesThatHaveWizardPagesToAdd", hr);
|
|
return hr;
|
|
}
|
|
|
|
|