windows-nt/Source/XPSP1/NT/net/config/shell/netsetup/wizard.cpp
2020-09-26 16:20:57 +08:00

1613 lines
43 KiB
C++

#include "pch.h"
#pragma hdrstop
#include "nceh.h"
#include "wizard.h"
#include "ncnetcfg.h"
#include "lancmn.h"
#include "cfg.h"
#include "wgenericpage.h"
//
// Function: CWizProvider::CWizProvider
//
// Purpose: ctor for the CWizProvider class
//
// Parameters: pPL - Info corresponding to a Connection UI Object
//
// Returns: nothing
//
CWizProvider::CWizProvider(ProviderList *pPL, BOOL fDeferLoad)
{
TraceFileFunc(ttidGuiModeSetup);
memcpy(&m_guidUiObject, pPL->pguidProvider, sizeof(GUID));
m_ulMaxPageCount = 0xFFFFFFFF;
m_ulPageCnt = 0;
m_ulPageBufferLen = 0;
m_rghPages = NULL;
m_pWizardUi = NULL;
m_fDeletePages = TRUE;
m_nBtnIdc = pPL->nBtnIdc;
m_fDeferLoad = fDeferLoad;
}
//
// Function: CWizProvider::~CWizProvider
//
// Purpose: dtor for the CWizProvider class
//
// Parameters: none
//
// Returns: nothing
//
CWizProvider::~CWizProvider()
{
TraceFileFunc(ttidGuiModeSetup);
if (m_fDeletePages)
{
DeleteHPages();
}
MemFree(m_rghPages);
ReleaseObj(m_pWizardUi);
}
//
// Function: CWizProvider::HrCreate
//
// Purpose: Two phase constructor for the CWizProvider class
//
// Parameters: pPL [IN] - Provider info from which to query the
// INetConnectionWizardUi interface.
// pProvider [OUT] - If this function succeeds this pointer
// will contain the constructed and
// initialized CWizProvider instance.
// fDeferLoad [IN] - Request the provider defer actual load
//
// Returns: HRESULT, S_OK on success
//
NOTHROW
HRESULT CWizProvider::HrCreate(ProviderList *pPL,
CWizProvider ** ppProvider,
BOOL fDeferLoad)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
CWizProvider *pprov = NULL;
Assert((NULL != pPL) && (NULL != ppProvider));
// Initialize output parameters
*ppProvider = NULL;
// Create the CWizProvider instance
pprov = new CWizProvider(pPL, fDeferLoad);
if ((NULL != pprov) && (FALSE == fDeferLoad))
{
Assert(pPL->pguidProvider);
hr = CoCreateInstance(
reinterpret_cast<REFCLSID>(*pPL->pguidProvider),
NULL,
CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
IID_INetConnectionWizardUi,
(LPVOID*)&pprov->m_pWizardUi);
TraceHr(ttidError, FAL, hr, FALSE, "CoCreateInstance");
if (FAILED(hr))
{
delete pprov;
pprov = NULL;
}
}
// Save the new instance
*ppProvider = pprov;
TraceHr(ttidWizard, FAL, hr, (REGDB_E_CLASSNOTREG == hr), "CWizProvider::HrCreate");
return hr;
}
//
// Function: CWizProvider::HrCompleteDeferredLoad
//
// Purpose: Complete the steps necessary to load what was a defer load object
//
// Parameters: none
//
// Returns: HRESULT, S_OK on success
//
HRESULT CWizProvider::HrCompleteDeferredLoad()
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
if (m_fDeferLoad)
{
m_fDeferLoad = FALSE;
// Attempt to create the UI Object
//
hr = CoCreateInstance(
reinterpret_cast<REFCLSID>(m_guidUiObject),
NULL,
CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
IID_INetConnectionWizardUi,
(LPVOID*)&m_pWizardUi);
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizProvider::HrCompleteDeferredLoad");
return hr;
}
//
// Function: CWizProvider::UlGetMaxPageCount
//
// Purpose: Queries from the provider the maximum number of pages
// that it will return. Subsequent calls to this routine
// return the cached count without requerying the provider.
//
// Parameters: pContext [IN] - Context information, supplied either by
// Setup or by the wizard itself (when not
// launched from Setup).
//
// Returns: ULONG, Maximum number of pages provider will return.
//
NOTHROW
ULONG
CWizProvider::UlGetMaxPageCount(INetConnectionWizardUiContext *pContext)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
if (NULL == m_pWizardUi)
{
m_ulMaxPageCount = 0;
}
else if (0xFFFFFFFF == m_ulMaxPageCount)
{
// Query the provider only once
m_ulMaxPageCount = 0L;
COM_PROTECT_TRY
{
Assert(NULL != m_pWizardUi);
Assert(NULL != pContext);
DWORD dwCount = 0L;
hr = m_pWizardUi->QueryMaxPageCount(pContext, &dwCount);
if (S_OK == hr)
{
m_ulMaxPageCount = dwCount;
}
}
COM_PROTECT_CATCH
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizProvider::GetMaxPageCount");
return m_ulMaxPageCount;
}
//
// Function: CWizProvider::DeleteHPages
//
// Purpose: Call DestroyPropertySheetPage for each cached page
//
// Parameters: none
//
// Returns: nothing
//
VOID CWizProvider::DeleteHPages()
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx=0; ulIdx < ULPageCount(); ulIdx++)
{
DestroyPropertySheetPage(m_rghPages[ulIdx]);
}
m_ulPageCnt=0;
}
//
// Function: CWizProvider::HrAddPages
//
// Purpose: Calls the AddPages method of a provider's
// INetConnectionWizardUi interface to allow for the
// supply of Wizard Pages
//
// Parameters: pContext [IN] - Context information, supplied either by
// Setup or by the wizard itself (when not
// launched from Setup).
//
// Returns: HRESULT, S_OK on success
//
NOTHROW
HRESULT
CWizProvider::HrAddPages(INetConnectionWizardUiContext *pContext)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
if (m_pWizardUi)
{
COM_PROTECT_TRY
{
// Ensure input params are valid
Assert(NULL != m_pWizardUi);
Assert(NULL != pContext);
hr = m_pWizardUi->AddPages(pContext, CWizProvider::FAddPropSheet,
reinterpret_cast<LPARAM>(this));
}
COM_PROTECT_CATCH
}
else
{
hr = E_NOINTERFACE;
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizProvider::HrAddPages");
return hr;
}
//
// Function: CWizProvider::FAddPropSheet
//
// Purpose: Callback function for the AddPages API used to accept
// wizard pages handed back from a provider.
//
// Parameters: hPage [IN] - The page to add
// lParam [IN] - 'this' casted to an LPARAM
//
// Returns: BOOL, TRUE if the page was successfully added.
//
BOOL
CWizProvider::FAddPropSheet(HPROPSHEETPAGE hPage, LPARAM lParam)
{
TraceFileFunc(ttidGuiModeSetup);
CWizProvider * pProvider;
// Validate the input parameters
if ((0L == lParam) || (NULL == hPage))
{
Assert(lParam);
Assert(hPage);
TraceHr(ttidWizard, FAL, E_INVALIDARG, FALSE, "CWizProvider::FAddPropSheet");
return FALSE;
}
pProvider = reinterpret_cast<CWizProvider*>(lParam);
// Grow the buffer if necessary
if (pProvider->m_ulPageCnt == pProvider->m_ulPageBufferLen)
{
HPROPSHEETPAGE* rghPages = reinterpret_cast<HPROPSHEETPAGE*>(
MemAlloc(sizeof(HPROPSHEETPAGE) * (pProvider->m_ulPageBufferLen + 10)));
if (NULL == rghPages)
{
TraceHr(ttidWizard, FAL, E_OUTOFMEMORY, FALSE, "CWizProvider::FAddPropSheet");
return FALSE;
}
// Copy the existing pages to the new buffer
if (NULL != pProvider->m_rghPages)
{
memcpy(rghPages, pProvider->m_rghPages,
sizeof(HPROPSHEETPAGE) * pProvider->m_ulPageBufferLen);
MemFree(pProvider->m_rghPages);
}
pProvider->m_rghPages = rghPages;
pProvider->m_ulPageBufferLen += 10;
}
// Retain the new page
pProvider->m_rghPages[pProvider->m_ulPageCnt++] = hPage;
return TRUE;
}
//
// Function: CWizProvider::HrGetLanInterface
//
// Purpose: Get the special LAN interface
//
// Parameters: ppIntr [OUT] - The special LAN specific interface
//
// Returns: HRESULT, S_OK on success
//
HRESULT CWizProvider::HrGetLanInterface(INetLanConnectionWizardUi ** ppIntr)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr;
Assert(NULL != ppIntr);
Assert(NULL != m_pWizardUi);
*ppIntr = NULL;
hr = m_pWizardUi->QueryInterface(IID_INetLanConnectionWizardUi,
(LPVOID *)ppIntr);
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizProvider::HrGetLanInterface");
return hr;
}
//
// Function: CWizProvider::HrSpecifyAdapterGuid
//
// Purpose: To notify the provider of the adapter guid to process
//
// Parameters: pguid [IN] - The adapter guid to process
//
// Returns: HRESULT, S_OK on success
//
HRESULT CWizProvider::HrSpecifyAdapterGuid(GUID *pguid)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr;
INetLanConnectionWizardUi *pIntr = NULL;
hr = HrGetLanInterface(&pIntr);
if (SUCCEEDED(hr))
{
hr = pIntr->SetDeviceComponent(pguid);
ReleaseObj(pIntr);
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizProvider::HrSpecifyAdapterGuid");
return hr;
}
CAdapterList::CAdapterList()
{
m_prgAdapters = NULL; // Adapter array
m_clAdapters = 0; // Count of adapters in the array
m_lBufSize = 0; // Total available slots in the array
m_lIdx = -1; // Current adapter index
// Range is -1 to m_clAdapters
m_fAdaptersInstalled = FALSE; // No adapters on the machine
}
AdapterEntry * CAdapterList::PAE_Current()
{
TraceFileFunc(ttidGuiModeSetup);
if ((m_lIdx > -1) && (m_lIdx < m_clAdapters))
{
Assert(NULL != m_prgAdapters);
return &m_prgAdapters[m_lIdx];
}
else
{
return NULL;
}
}
AdapterEntry * CAdapterList::PAE_Next()
{
// Find the next, not hidden adapter
//
// Hidden adapters are those which were processed by a previous
// run of setup
//
// Increment the index even if the count is zero
// m_lIdx == -1 means before the first adapter
// m_lIdx == m_clAdapters means after the last adapter
while (m_lIdx < m_clAdapters)
{
m_lIdx++;
if ((m_lIdx < m_clAdapters) && (!m_prgAdapters[m_lIdx].fHide))
break;
}
Assert(m_lIdx >= -1);
return PAE_Current();
}
AdapterEntry * CAdapterList::PAE_Prev()
{
// Find the previous, not hidden adapter
//
// Hidden adapters are those which were processed by a previous
// run of setup
//
// Decrement the index even if the count is zero
// m_lIdx == -1 means before the first adapter
// m_lIdx == m_clAdapters means after the last adapter
while (-1 < m_lIdx)
{
m_lIdx--;
if ((-1 < m_lIdx) && (!m_prgAdapters[m_lIdx].fHide))
break;
}
Assert(m_lIdx < m_clAdapters);
return PAE_Current();
}
GUID * CAdapterList::NextAdapter()
{
AdapterEntry * pae = PAE_Next();
if (NULL != pae)
return &(pae->guidAdapter);
else
return NULL;
}
GUID * CAdapterList::PrevAdapter()
{
AdapterEntry * pae = PAE_Prev();
if (NULL != pae)
return &(pae->guidAdapter);
else
return NULL;
}
GUID * CAdapterList::CurrentAdapter()
{
AdapterEntry * pae = PAE_Current();
if (NULL != pae)
return &(pae->guidAdapter);
else
return NULL;
}
VOID CAdapterList::EmptyList()
{
if (NULL != m_prgAdapters)
{
MemFree(m_prgAdapters);
m_prgAdapters = NULL;
m_clAdapters = 0; // Count of adapters in the array
m_lBufSize = 0; // Total available slots in the array
m_lIdx = -1;
}
}
VOID CAdapterList::HideAllAdapters()
{
for (LONG lIdx=0; lIdx < m_clAdapters; lIdx++)
m_prgAdapters[lIdx].fHide = TRUE;
}
VOID CAdapterList::UnhideNewAdapters()
{
for (LONG lIdx=0; lIdx < m_clAdapters; lIdx++)
if (m_prgAdapters[lIdx].fNew)
{
m_prgAdapters[lIdx].fHide = FALSE;
}
}
HRESULT CAdapterList::HrAppendEntries(AdapterEntry * pae, ULONG cae)
{
if (0 == cae)
{
return S_OK;
}
if (m_clAdapters + (LONG)cae > m_lBufSize)
{
// Grow the buffer
AdapterEntry * prg = reinterpret_cast<AdapterEntry *>(
MemAlloc(sizeof(AdapterEntry) * (m_lBufSize + cae + 10)));
if (NULL == prg)
{
TraceHr(ttidWizard, FAL, E_OUTOFMEMORY, FALSE, "CAdapterList::HrAppendEntries");
return E_OUTOFMEMORY;
}
// Copy the existing pages to the new buffer
if (NULL != m_prgAdapters)
{
memcpy(prg, m_prgAdapters, sizeof(AdapterEntry) * m_lBufSize);
MemFree(m_prgAdapters);
}
m_prgAdapters = prg;
m_lBufSize += (cae + 10);
}
memcpy(&m_prgAdapters[m_clAdapters], pae, cae * sizeof(AdapterEntry));
m_clAdapters += cae;
return S_OK;
}
//
// Function: CAdapterList::HrQueryLanAdapters
//
// Purpose: Query the available LAN adapters.
//
// Parameters: pnc [IN] - An INetCfg interface
// pAL [IN,OUT] - Receives the list of LAN adapters
//
// Returns: HRESULT, S_OK on success
//
HRESULT CAdapterList::HrQueryLanAdapters(INetCfg * pnc, CAdapterList * pAL)
{
HRESULT hr = S_OK;
CAdapterList ALphys;
CAdapterList ALvirt;
TraceTag(ttidWizard, "CAdapterList::HrQueryLanAdapters - Querying available adapters");
// Enumerate the available adapters
Assert(NULL != pnc);
CIterNetCfgComponent nccIter(pnc, &GUID_DEVCLASS_NET);
INetCfgComponent* pncc;
while (SUCCEEDED(hr) && (S_OK == (hr = nccIter.HrNext(&pncc))))
{
hr = HrIsLanCapableAdapter(pncc);
if (S_OK == hr)
{
DWORD dw;
AdapterEntry ae;
ae.fHide = FALSE;
// Get the adapter instance guid
hr = pncc->GetInstanceGuid(&ae.guidAdapter);
if (FAILED(hr))
goto NextAdapter;
// Is it in used in a connection?
hr = HrIsConnection(pncc);
if (FAILED(hr))
goto NextAdapter;
ae.fProcessed = (S_OK == hr);
ae.fNew = !ae.fProcessed; // It's new if it has not been processed
// Check device, if not present skip it
//
hr = pncc->GetDeviceStatus(&dw);
if (FAILED(hr) || (CM_PROB_DEVICE_NOT_THERE == dw))
{
goto NextAdapter;
}
// Is this a virtual adapter?
hr = pncc->GetCharacteristics(&dw);
if (FAILED(hr))
goto NextAdapter;
ae.fVirtual = ((dw & NCF_VIRTUAL) ? TRUE : FALSE);
// Add the entry to the appropriate list
if (ae.fVirtual)
{
hr = ALvirt.HrAppendEntries(&ae, 1);
}
else
{
hr = ALphys.HrAppendEntries(&ae, 1);
}
if (FAILED(hr))
goto NextAdapter;
// Note the fact that LAN capable adapters exist.
// Because in setup we will show the join page.
pAL->m_fAdaptersInstalled = TRUE;
}
NextAdapter:
ReleaseObj(pncc);
hr = S_OK;
}
if (SUCCEEDED(hr))
{
// Merge the physical and virtual lists into the pAL input variable
pAL->EmptyList();
hr = pAL->HrAppendEntries(ALphys.m_prgAdapters, ALphys.m_clAdapters);
if (SUCCEEDED(hr))
{
hr = pAL->HrAppendEntries(ALvirt.m_prgAdapters, ALvirt.m_clAdapters);
}
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CAdapterList::HrQueryUnboundAdapters");
return hr;
}
HRESULT CAdapterList::HrCreateTypicalConnections(CWizard * pWizard)
{
HRESULT hr = S_OK;
// If there are no adapters in the queue or we have no LAN provider...
if (0 == pWizard->UlProviderCount())
{
return S_OK;
}
// Set the current provider
pWizard->SetCurrentProvider(0);
CWizProvider * pWizProvider = pWizard->GetCurrentProvider();
Assert(NULL != pWizProvider);
TraceTag(ttidWizard, "CAdapterList::HrCreateTypicalConnections - Creating any new LAN connections.");
// For each adapter in the list create a connection
for (LONG lIdx=0; lIdx<m_clAdapters; lIdx++)
{
AdapterEntry * pae = &m_prgAdapters[lIdx];
if (!pae->fProcessed)
{
#if DBG
WCHAR szGuid[c_cchGuidWithTerm];
szGuid[0] = 0;
StringFromGUID2(pae->guidAdapter, szGuid, c_cchGuidWithTerm);
TraceTag(ttidWizard, " Guid: %S",szGuid);
#endif
pae->fProcessed = TRUE;
// Push the adapter guid onto the provider
hr = pWizProvider->HrSpecifyAdapterGuid(&(pae->guidAdapter));
if (SUCCEEDED(hr))
{
tstring str;
INetConnection * pConn = NULL;
GenerateUniqueConnectionName(pae->guidAdapter, &str, pWizProvider);
TraceTag(ttidWizard, " Name: %S", str.c_str());
hr = (pWizProvider->PWizardUi())->GetNewConnection(&pConn);
ReleaseObj(pConn);
}
// If we failed to create a connection we need to mark it as hidden
// so it will be skipped in the future. Eat the error or otherwise
// setup will just stop.
//
if (FAILED(hr))
{
TraceHr(ttidWizard, FAL, hr, FALSE, "CAdapterList::HrCreateTypicalConnections - failed creating the connection");
pae->fHide = TRUE;
hr = S_OK;
}
}
}
// Ask the LAN provider to release any cached pointers.
//
(VOID)pWizProvider->HrSpecifyAdapterGuid(NULL);
TraceHr(ttidWizard, FAL, hr, FALSE, "CAdapterList::HrCreateTypicalConnections");
return hr;
}
HRESULT CAdapterList::HrQueryUnboundAdapters(CWizard * pWizard)
{
HRESULT hr = S_OK;
LONG lIdx;
Assert(NULL != pWizard->PNetCfg());
// Handle the first time the adapters are queried
if (0 == m_clAdapters)
{
hr = HrQueryLanAdapters(pWizard->PNetCfg(), this);
if (SUCCEEDED(hr))
{
// Mark all already bound adapters as hidden so they
// won't be displayed in the UI
for (lIdx=0; lIdx<m_clAdapters; lIdx++)
{
m_prgAdapters[lIdx].fHide = m_prgAdapters[lIdx].fProcessed;
}
// Create connections for all unbound adapters
hr = HrCreateTypicalConnections(pWizard);
}
}
else
{
CAdapterList AL;
// Query the current adapters
hr = HrQueryLanAdapters(pWizard->PNetCfg(), &AL);
if (FAILED(hr))
goto Error;
// Eliminate adapters in the original set which are not
// present in new list
for (lIdx=0; lIdx<m_clAdapters; lIdx++)
{
BOOL fFound = FALSE;
LONG lIdxTemp;
for (lIdxTemp=0; lIdxTemp<AL.m_clAdapters; lIdxTemp++)
{
if (m_prgAdapters[lIdx].guidAdapter ==
AL.m_prgAdapters[lIdxTemp].guidAdapter)
{
fFound = TRUE;
break;
}
}
if (fFound)
{
// Compress the located adapter from the new set
if (lIdxTemp + 1 < AL.m_clAdapters)
{
memcpy(&AL.m_prgAdapters[lIdxTemp],
&AL.m_prgAdapters[lIdxTemp+1],
sizeof(AdapterEntry) *
(AL.m_clAdapters - (lIdxTemp + 1)));
}
AL.m_clAdapters--;
}
else
{
// The source adapter is no longer in the set
if (lIdx < m_lIdx)
m_lIdx--;
}
}
Assert(m_lIdx <= m_clAdapters);
if (m_lIdx == m_clAdapters)
m_lIdx = m_clAdapters-1;
// Create connections for the new adapters
hr = AL.HrCreateTypicalConnections(pWizard);
if (FAILED(hr))
goto Error;
// Append new adapters to the original list
hr = HrAppendEntries(AL.m_prgAdapters, AL.m_clAdapters);
}
Error:
TraceHr(ttidWizard, FAL, hr, FALSE, "CAdapterList::HrQueryUnboundAdapters");
return hr;
}
//
// Function: CWizard::CWizard
//
// Purpose: ctor for the CWizard class
//
// Parameters: fLanPages [IN] - Processing LAN pages
// pdata [IN] - Wizard context info
// fDeferred [IN] - Defered loading of providers
//
// Returns: nothing
//
CWizard::CWizard(BOOL fLanPages, PINTERNAL_SETUP_DATA pData, BOOL fDeferred)
{
TraceFileFunc(ttidGuiModeSetup);
m_fLanPages = fLanPages;
m_fExitNoReturn = FALSE;
m_fCoUninit = FALSE;
m_fDeferredProviderLoad = fDeferred;
m_fProviderChanged = FALSE;
m_dwFirstPage = 0;
m_pConn = NULL;
m_pNetCfg = NULL;
m_pUiContext = NULL;
Assert(NULL != pData);
m_pSetupData = pData;
m_dwOperationFlags = pData->OperationFlags;
m_UMMode = UM_DEFAULTHIDE;
m_ulCurProvider = 0;
m_ulPageDataCnt = 0;
ZeroMemory(m_rgPageData, sizeof(m_rgPageData));
m_ulWizProviderCnt = 0;
m_ulPageDataMRU = 0;
ZeroMemory(m_rgpWizProviders, sizeof(m_rgpWizProviders));
}
//
// Function: CWizard::~CWizard
//
// Purpose: dtor for the CWizProvider class
//
// Parameters: none
//
// Returns: nothing
//
// Note: Remove CWizard member re-init from dtor. Present only
// to ensure complete appropriate release of all members
CWizard::~CWizard()
{
TraceFileFunc(ttidGuiModeSetup);
ULONG ulIdx;
// Call the cleanup callback for all registered wizard internal pages
for (ulIdx = 0; ulIdx < m_ulPageDataCnt; ulIdx++)
{
if (m_rgPageData[ulIdx].pfn)
{
m_rgPageData[ulIdx].pfn(this, m_rgPageData[ulIdx].lParam);
}
}
m_ulPageDataCnt = 0L;
// Note: Do not release m_pSetupData, it's only a reference
m_pSetupData = NULL;
// Release any providers that had been retained
for (ulIdx = 0; ulIdx < m_ulWizProviderCnt; ulIdx++)
{
Assert(0 != m_rgpWizProviders[ulIdx]);
delete m_rgpWizProviders[ulIdx];
m_rgpWizProviders[ulIdx] = NULL;
}
m_ulWizProviderCnt = 0L;
m_ulCurProvider = 0;
ReleaseObj(m_pUiContext);
m_pUiContext = NULL;
ReleaseObj(m_pConn);
m_pConn = NULL;
if (m_pNetCfg)
{
(VOID)HrUninitializeAndReleaseINetCfg(FCoUninit(), m_pNetCfg, TRUE);
}
m_pNetCfg = NULL;
}
//
// Function: CWizard::HrCreate
//
// Purpose: Two phase constructor for the CWizard class
//
// Parameters: ppWizard [OUT] - If this function succeeds this pointer
// will contain the constructed and
// fLanPages [IN] - Processing LAN pages
// initialized CWizard instance.
// pdata [IN] - Wizard Context info
// fDeferred [IN] - Providers are defer loaded
//
// Returns: HRESULT, S_OK on success
//
NOTHROW
HRESULT CWizard::HrCreate(CWizard ** ppWizard,
BOOL fLanPages,
PINTERNAL_SETUP_DATA pData,
BOOL fDeferred)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
CWizardUiContext * pContext = NULL;
CWizard * pWiz = NULL;
Assert(NULL != ppWizard);
// Initialize output parameters
*ppWizard = NULL;
// Create the CWizard instance
pWiz = new CWizard(fLanPages, pData, fDeferred);
pContext = new CWizardUiContext(pData);
if ((NULL != pWiz) && (NULL != pContext))
{
// Save the new instance
pWiz->m_pUiContext = pContext;
*ppWizard = pWiz;
}
else
{
hr = E_OUTOFMEMORY;
}
TraceHr(ttidWizard, FAL, hr, FALSE, "CWizard::HrCreate");
return hr;
}
//
// Function: CWizard::HrAddProvider
//
// Purpose: To add a connection provider to list of currently loaded
// connection providers
//
// Parameters: pPL [IN] - GUID of conection provider which implements the
// INetConnectionWizardUi interface.
//
// Returns: HRESULT, S_OK on success
//
NOTHROW
HRESULT CWizard::HrAddProvider(ProviderList *pPL)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = E_OUTOFMEMORY;
CWizProvider * pProvider = NULL;
Assert(NULL != pPL);
Assert(m_eMaxProviders > m_ulWizProviderCnt);
// Restrict the total number of providers managed
if (m_eMaxProviders > m_ulWizProviderCnt)
{
// Instantiate a provider
hr = CWizProvider::HrCreate(pPL, &pProvider,
FDeferredProviderLoad());
if (SUCCEEDED(hr))
{
m_rgpWizProviders[m_ulWizProviderCnt++] = pProvider;
}
}
TraceHr(ttidWizard, FAL, hr, (REGDB_E_CLASSNOTREG == hr), "CWizard::HrAddProvider");
return hr;
}
//
// Function: CWizard::LoadWizProviders
//
// Purpose: Load the requested wizard providers
//
// Parameters: ulCntProviders [IN] - Count of guids in rgpguidProviders
// rgProviders [IN] - Guids of the providers to load
//
// Returns: none
//
VOID CWizard::LoadWizProviders( ULONG ulCntProviders,
ProviderList * rgProviders)
{
if (0 == m_ulWizProviderCnt)
{
TraceTag(ttidWizard, "Loading requested providers");
// Load the connections providers used during Setup
for (UINT nIdx=0; nIdx < ulCntProviders; nIdx++)
{
HRESULT hr = HrAddProvider(&rgProviders[nIdx]);
TraceHr(ttidWizard, FAL, hr, FALSE,
"FSetupRequestWizardPages - Failed to load provider #%d",nIdx);
}
}
}
//
// Function: CWizard::HrCreateWizProviderPages
//
// Purpose: Load the requested wizard provider's pages, if requested.
// Otherwise return the expected page count.
//
// Parameters: 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 CWizard::HrCreateWizProviderPages(BOOL fCountOnly, UINT *pcPages)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
ULONG ulCnt = 0;
ULONG ulIdx;
Assert(NULL != m_pSetupData);
Assert(NULL != m_pUiContext);
// If provider loading was deferred, load them now
//
if (FDeferredProviderLoad())
{
// Count the maximum number of pages
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
HRESULT hrTmp = m_rgpWizProviders[ulIdx]->HrCompleteDeferredLoad();
}
// Deferred Load is no longer true. Reset the state
//
DeferredLoadComplete();
}
if (fCountOnly)
{
// Count the maximum number of pages
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
Assert(m_rgpWizProviders[ulIdx]);
if (m_rgpWizProviders[ulIdx]->UlGetMaxPageCount(m_pUiContext))
{
ulCnt += m_rgpWizProviders[ulIdx]->UlGetMaxPageCount(m_pUiContext);
ulCnt += 1; // For the guard page
}
}
}
else
{
TraceTag(ttidWizard, "Loading each providers pages");
bCallRasDlgEntry = TRUE;
// Load the pages
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
Assert(m_rgpWizProviders[ulIdx]);
Assert(0xFFFFFFFF != m_rgpWizProviders[ulIdx]->UlGetMaxPageCount(m_pUiContext));
if (0 != m_rgpWizProviders[ulIdx]->UlGetMaxPageCount(m_pUiContext))
{
HRESULT hrTmp = m_rgpWizProviders[ulIdx]->HrAddPages(m_pUiContext);
TraceHr(ttidWizard, FAL, hrTmp, S_FALSE == hrTmp,
"CWizard::HrCreateWizProviderPages - %d", ulIdx);
// We only care about out of memory errors when adding pages.
// Providers which fail to add pages are removed from the
// provider list m_rgpWizProviders.
//
if (E_OUTOFMEMORY == hrTmp)
{
hr = hrTmp;
goto Error;
}
}
}
// Cull the providers which loaded no pages
ULONG ulNewCnt = 0;
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
if (0 != m_rgpWizProviders[ulIdx]->ULPageCount())
{
m_rgpWizProviders[ulNewCnt++] = m_rgpWizProviders[ulIdx];
}
else
{
delete m_rgpWizProviders[ulIdx];
}
}
m_ulWizProviderCnt = ulNewCnt;
// Now count how many provider pages were actually loaded, and create
// their associated guard pages
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
if (m_rgpWizProviders[ulIdx]->ULPageCount())
{
// Create the guard page for this provider
// Note that the guard page's id is (CWizProvider *)
hr = HrCreateGuardPage(this, m_rgpWizProviders[ulIdx]);
if (SUCCEEDED(hr))
{
// Includes the guard page
ulCnt += (m_rgpWizProviders[ulIdx]->ULPageCount() + 1);
}
else
{
m_rgpWizProviders[ulIdx]->DeleteHPages();
TraceHr(ttidWizard, FAL, hr, FALSE,"CWizard::HrCreateWizProviderPages - Guard Page Create Failed");
hr = S_OK;
}
}
}
}
(*pcPages) += ulCnt;
Error:
TraceHr(ttidWizard, FAL, hr, S_FALSE == hr,"CWizard::HrCreateWizProviderPages");
return hr;
}
//
// Function: CWizard:AppendProviderPages
//
// Purpose: Append wizard provider pages and their associated guard pages
// to the HPROPSHEETPAGE array
//
// Parameters: pahpsp [IN,OUT] - Ptr to the HPROPSHEETPAGE array which will
// receive the provider pages.
// pcPages [IN] - Ptr to indicate the number of pages added to
// the pahpsp array
// Returns: nothing
//
VOID CWizard::AppendProviderPages(HPROPSHEETPAGE *pahpsp, UINT *pcPages)
{
TraceFileFunc(ttidGuiModeSetup);
ULONG ulIdx;
// Now count how many provider pages were actually loaded, and create
// their associated guard pages
for (ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
ULONG ulPageCnt = m_rgpWizProviders[ulIdx]->ULPageCount();
if (ulPageCnt)
{
m_rgpWizProviders[ulIdx]->XFerDeleteResponsibilities();
// Copy the providers pages
memcpy(&pahpsp[*pcPages], m_rgpWizProviders[ulIdx]->PHPropPages(),
sizeof(HPROPSHEETPAGE) * ulPageCnt);
(*pcPages) += ulPageCnt;
// Append the guard page
AppendGuardPage(this, m_rgpWizProviders[ulIdx], pahpsp, pcPages);
}
}
}
//
// Function: CWizard:LoadAndInsertDeferredProviderPages
//
// Purpose: Insert wizard provider pages and their associated guard pages
// directly into the wizard
//
// Parameters: hwndPropSheet [IN] - Handle to the property sheet
// iddAfterPage [IN] - Page to insert after.
//
// Returns: nothing
//
VOID CWizard::LoadAndInsertDeferredProviderPages(HWND hwndPropSheet, UINT iddAfterPage)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr;
UINT cPages = 0;
// Create the pages
//
hr = HrCreateWizProviderPages(FALSE, &cPages);
if (SUCCEEDED(hr))
{
HPROPSHEETPAGE hPage = GetPageHandle(iddAfterPage);
Assert(hPage);
for (ULONG ulIdx=0; ulIdx<m_ulWizProviderCnt; ulIdx++)
{
ULONG ulPageCnt = m_rgpWizProviders[ulIdx]->ULPageCount();
Assert(0xFFFFFFFF != ulPageCnt);
if (ulPageCnt)
{
BOOL fRet;
HPROPSHEETPAGE hpsp = NULL;
m_rgpWizProviders[ulIdx]->XFerDeleteResponsibilities();
// Get the guard page and insert
//
cPages = 0;
AppendGuardPage(this, m_rgpWizProviders[ulIdx], &hpsp, &cPages);
fRet = PropSheet_InsertPage(hwndPropSheet, hPage, hpsp);
Assert(fRet);
// Copy the providers pages.
do
{
hpsp = (m_rgpWizProviders[ulIdx]->PHPropPages())[ulPageCnt - 1];
fRet = PropSheet_InsertPage(hwndPropSheet, hPage, hpsp);
Assert(fRet);
}
while (--ulPageCnt>0);
}
}
}
TraceHr(ttidWizard, FAL, hr, FALSE,"CWizard::LoadAndInsertDeferredProviderPages");
}
//
// Function: CWizard::RegisterPage
//
// Purpose: Allow a wizard internal page to register a callback function
// and a page specific LPARAM along with the HPROPSHEETPAGE.
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
// hpsp [IN] - Handle to the property page being registered
// pfnCleanup [IN] - Callback function to call before CWizard
// is destroyed.
// lParam [IN] - Page specific parameter.
//
// Returns: nothing
//
VOID CWizard::RegisterPage(LPARAM ulId, HPROPSHEETPAGE hpsp,
PFNPAGECLEANPROC pfnCleanup, LPARAM lParam)
{
TraceFileFunc(ttidGuiModeSetup);
#if DBG
Assert(m_eMaxInternalPages + m_eMaxProviders> m_ulPageDataCnt);
for (UINT nIdx=0;nIdx<m_ulPageDataCnt; nIdx++)
{
Assert(ulId != m_rgPageData[nIdx].ulId);
}
#endif
m_rgPageData[m_ulPageDataCnt].ulId = ulId;
m_rgPageData[m_ulPageDataCnt].hPage = hpsp;
m_rgPageData[m_ulPageDataCnt].lParam = lParam;
m_rgPageData[m_ulPageDataCnt].PageDirection = NWPD_FORWARD;
m_rgPageData[m_ulPageDataCnt].pfn = pfnCleanup;
m_ulPageDataCnt++;
}
//
// Function: CWizard::GetPageData
//
// Purpose: Retrieve data cached by a page via the RegisterPage
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
//
// Returns: LPARAM, the data associated with the registered page
//
LPARAM CWizard::GetPageData(LPARAM ulId)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(m_ulPageDataMRU < m_ulPageDataCnt);
if (ulId == m_rgPageData[m_ulPageDataMRU].ulId)
{
return (m_rgPageData[m_ulPageDataMRU].lParam);
}
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_ulPageDataMRU = ulIdx;
return (m_rgPageData[ulIdx].lParam);
}
}
Assert(0); // PageData not found
return 0L;
}
//
// Function: CWizard::SetPageData
//
// Purpose: Set data value for a page registered via the RegisterPage
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
// lParam [IN] - Data to cache with registered page
//
// Returns: nothing
//
VOID CWizard::SetPageData(LPARAM ulId, LPARAM lParam)
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_rgPageData[ulIdx].lParam = lParam;
return;
}
}
Assert(0); // Page not found
}
//
// Function: CWizard::GetPageIndexFromIID
//
// Purpose: Set the page index
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
//
// Returns: nothing
//
UINT CWizard::GetPageIndexFromIID(LPARAM ulId)
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
return ulIdx;
}
}
AssertSz(0, "GetPageIndexFromIID: Invalid page of the NCW requested"); // Page not found
return 0;
}
// Function: CWizard::GetPageIndexFromHPage
//
// Purpose: Set the page index
//
// Parameters: hPage [IN] - A PROPSHEETPAGE
//
// Returns: nothing
//
UINT CWizard::GetPageIndexFromHPage(HPROPSHEETPAGE hPage)
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx = 0; ulIdx < m_ulPageDataCnt; ulIdx++)
{
if (hPage == m_rgPageData[ulIdx].hPage)
{
return ulIdx;
}
}
AssertSz(0, "GetPageIndexFromHPage: Invalid page of the NCW requested"); // Page not found
return 0;
}
//
// Function: CWizard::GetPageOrigin
//
// Purpose: Retrieve data cached by a page via the RegisterPage
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
//
// Returns: LPARAM, the data associated with the registered page
//
LPARAM CWizard::GetPageOrigin(LPARAM ulId, UINT *pOriginIDC)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(m_ulPageDataMRU < m_ulPageDataCnt);
if (ulId == m_rgPageData[m_ulPageDataMRU].ulId)
{
if (pOriginIDC)
{
*pOriginIDC = m_rgPageData[m_ulPageDataMRU].PageOriginIDC;
}
return (m_rgPageData[m_ulPageDataMRU].PageOrigin);
}
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_ulPageDataMRU = ulIdx;
if (pOriginIDC)
{
*pOriginIDC = m_rgPageData[ulIdx].PageOriginIDC;
}
return (m_rgPageData[ulIdx].PageOrigin);
}
}
Assert(0); // PageData not found
return 0L;
}
//
// Function: CWizard::SetPageOrigin
//
// Purpose: Set data value for a page registered via the RegisterPage
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
// uiOrigin[IN] - Origin of page
//
// Returns: nothing
//
VOID CWizard::SetPageOrigin(LPARAM ulId, UINT uiOrigin, UINT uiOriginIDC)
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_rgPageData[ulIdx].PageOrigin = uiOrigin;
m_rgPageData[ulIdx].PageOriginIDC = uiOriginIDC;
return;
}
}
Assert(0); // Page not found
}
//
// Function: CWizard::GetPageHandle
//
// Purpose: Retrieve PropSheet Page handle cached by a page via the
// RegisterPage
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
//
// Returns: HPROPSHEETPAGE, the propsheet handle associated with the
// registered page
//
HPROPSHEETPAGE CWizard::GetPageHandle(LPARAM ulId)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(m_ulPageDataMRU < m_ulPageDataCnt);
if (ulId == m_rgPageData[m_ulPageDataMRU].ulId)
{
return (m_rgPageData[m_ulPageDataMRU].hPage);
}
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_ulPageDataMRU = ulIdx;
return (m_rgPageData[ulIdx].hPage);
}
}
Assert(0); // Page Handle not found
return NULL;
}
//
// Function: CWizard::GetPageDirection
//
// Purpose: Retrieve page direction associated with a page
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
//
// Returns: PAGEDIRECTION, the direction of travel associated with the
// specified page. Note that the meaning of the direction is
// up to the page. The wizard code initializes all the page
// directions to NWPD_FORWARD before executing a providers pages.
//
PAGEDIRECTION CWizard::GetPageDirection(LPARAM ulId)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(m_ulPageDataMRU < m_ulPageDataCnt);
if (ulId == m_rgPageData[m_ulPageDataMRU].ulId)
{
return (m_rgPageData[m_ulPageDataMRU].PageDirection);
}
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_ulPageDataMRU = ulIdx;
return (m_rgPageData[ulIdx].PageDirection);
}
}
Assert(0); // PageData not found
return NWPD_FORWARD;
}
//
// Function: CWizard::SetPageDirection
//
// Purpose: Retrieve page direction associated with a page
//
// Parameters: ulId [IN] - A page specific value, must be unique amoung
// all registering pages
// PageDirection [IN] - the new page direction setting
//
// Returns: nothing
//
VOID CWizard::SetPageDirection(LPARAM ulId, PAGEDIRECTION PageDirection)
{
TraceFileFunc(ttidGuiModeSetup);
for (ULONG ulIdx=0; ulIdx<m_ulPageDataCnt; ulIdx++)
{
if (ulId == m_rgPageData[ulIdx].ulId)
{
m_rgPageData[ulIdx].PageDirection = PageDirection;
return;
}
}
Assert(0); // PageData not found
}
//
// Function: CWizardUiContext::AddRef
//
// Purpose: Increment the reference count on this object
//
// Parameters: none
//
// Returns: ULONG
//
STDMETHODIMP_(ULONG) CWizardUiContext::AddRef()
{
return ++m_cRef;
}
//
// Function: CWizardUiContext::Release
//
// Purpose: Decrement the reference count on this object
//
// Parameters: none
//
// Returns: ULONG
//
STDMETHODIMP_(ULONG) CWizardUiContext::Release()
{
ULONG cRef = --m_cRef;
if (cRef == 0)
{
delete this;
}
return cRef;
}
//
// Function: CWizardUiContext::QueryInterface
//
// Purpose: Allows for the querying of alternate interfaces
//
// Parameters: riid [IN] - Interface to retrieve
// ppvObj [OUT] - Retrieved interface if function succeeds
//
// Returns: HRESULT, S_OK on success E_NOINTERFACE on failure
//
STDMETHODIMP CWizardUiContext::QueryInterface(REFIID riid, LPVOID FAR *ppvObj)
{
HRESULT hr = S_OK;
*ppvObj = NULL;
if ((riid == IID_IUnknown) || (riid == IID_INetConnectionWizardUiContext))
{
*ppvObj = (LPVOID)this;
AddRef();
}
else
{
hr = E_NOINTERFACE;
}
return hr;
}
STDMETHODIMP CWizardUiContext::GetINetCfg(INetCfg ** ppINetCfg)
{
HRESULT hr = E_FAIL;
if (NULL == ppINetCfg)
{
hr = E_INVALIDARG;
}
else if (NULL != m_pINetCfg)
{
*ppINetCfg = m_pINetCfg;
AddRefObj(*ppINetCfg);
hr = S_OK;
}
return hr;
}