769 lines
26 KiB
C++
769 lines
26 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 2000.
|
||
|
//
|
||
|
// File: N C S Y S P R P . C P P
|
||
|
//
|
||
|
// Contents: Functions that related to SysPrep.exe requiremnts.
|
||
|
//
|
||
|
// Notes: 1.
|
||
|
// 1.a sysprep calls NetSetupPrepareSysPrep
|
||
|
// 1.b NetSetup saves adapter specific settings into $ncsp$.inf file.
|
||
|
// NetSetup does this by calling INetCfgComponent::SaveAdapterParameters
|
||
|
// implemented by notify object.
|
||
|
//
|
||
|
// 2.
|
||
|
// 2.a Mini-Setup calls NetSetupRequestWizardPages passing the
|
||
|
// "SETUPOPER_MINISETUP" flag right after PnP device installation.
|
||
|
// 2.b NetSetup's InstallUpgradeWorkThrd thread checks the "SETUPOPER_MINISETUP" flag,
|
||
|
// if set, it calls FNetSetupApplySysPrep which reads Answer-File "$ncsp$.inf".
|
||
|
// It then calls notify object's INetCfgComponent::RestoreAdapterParameters
|
||
|
// to restore adapter specific parameter settings from "$ncsp$.inf" Answer-File.
|
||
|
//
|
||
|
// 3. Only ONE network adapter card is supported on this version.
|
||
|
//
|
||
|
// Author: FrankLi 22-April-2000
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
#include "pch.h"
|
||
|
#pragma hdrstop
|
||
|
#include "kkcwinf.h"
|
||
|
#include "ncstring.h"
|
||
|
#include "netcfgp.h"
|
||
|
#include "nsbase.h"
|
||
|
#include "kkutils.h"
|
||
|
#include "ncnetcfg.h"
|
||
|
#include "lancmn.h"
|
||
|
#include "ncreg.h"
|
||
|
#include "ncsysprp.h"
|
||
|
#include "resource.h"
|
||
|
|
||
|
|
||
|
// constants from ncnetcfg\netinfid.cpp
|
||
|
extern WCHAR c_szInfId_MS_TCPIP[] = L"ms_tcpip";
|
||
|
extern WCHAR c_szInfId_MS_MSClient[] = L"ms_msclient";
|
||
|
extern WCHAR c_szInfId_MS_NWClient[] = L"ms_nwclient";
|
||
|
|
||
|
// constants from ncbase\afilestr.cpp
|
||
|
extern WCHAR c_szRegKeyAnswerFileMap[] = L"SYSTEM\\Setup\\AnswerFileMap";
|
||
|
|
||
|
// constants for adapter specific sections
|
||
|
const WCHAR c_szParams_MS_TCPIP_Adapter01[] = L"params.ms_tcpip_Adapter01";
|
||
|
//const WCHAR c_szParams_MS_MSClient_Adapter01[] = L"params.ms_msclient_Adapter01";
|
||
|
//const WCHAR c_szParams_MS_NWClient_Adapter01[] = L"params.ms_nwclient_Adapter01";
|
||
|
|
||
|
// The Answer-File name to save registry settings
|
||
|
static const WCHAR c_szNetConfigSysPrepAnswerFile[] = L"\\$ncsp$.inf";
|
||
|
|
||
|
// struct to map component Id to its corresponding adapter specific parameter
|
||
|
// Answer-File section
|
||
|
struct
|
||
|
{
|
||
|
PCWSTR pwszId;
|
||
|
PCWSTR pwszIdAdapterParamsSection;
|
||
|
} g_IdMap[] = {{c_szInfId_MS_TCPIP, c_szParams_MS_TCPIP_Adapter01},
|
||
|
// no adapter specific parameters for MSClient and NWClient
|
||
|
//{c_szInfId_MS_MSClient, c_szParams_MS_MSClient_Adapter01},
|
||
|
//{c_szInfId_MS_NWClient, c_szParams_MS_NWClient_Adapter01}
|
||
|
};
|
||
|
|
||
|
// forward declaration
|
||
|
HRESULT HrSaveNetworkComponentsForSysPrep(INetCfg* pNetCfg);
|
||
|
HRESULT HrRestoreNetworkComponentsForSysPrep(INetCfg* pNetCfg);
|
||
|
HRESULT HrGetFirstAdapterInstanceGuid(INetCfg * pnc, BOOL fDuringSetup, GUID * pGuidAdapter);
|
||
|
BOOL FSectionHasAtLeastOneKey(IN CWInfFile* pwifAnswerFile, IN PCWSTR pszSection);
|
||
|
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// internal helper APIs used by CNetCfgSysPrep implementation
|
||
|
// to save settings from notify object:
|
||
|
|
||
|
// Purpose: save REG_DWORD to our internal CWinfFile object
|
||
|
inline HRESULT HrSetupSetFirstDword(IN HWIF hwif,
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN DWORD dwValue)
|
||
|
{
|
||
|
Assert (hwif && pwszSection && pwszKey);
|
||
|
CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
|
||
|
PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
|
||
|
if (pwifSection)
|
||
|
{
|
||
|
pwifAnswerFile->GotoEndOfSection(pwifSection);
|
||
|
pwifAnswerFile->AddKey(pwszKey, dwValue);
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// Purpose: save REG_SZ to our internal CWinfFile object
|
||
|
inline HRESULT HrSetupSetFirstString(IN HWIF hwif,
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN PCWSTR pwszValue)
|
||
|
{
|
||
|
Assert (hwif && pwszSection && pwszKey && pwszValue);
|
||
|
CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
|
||
|
|
||
|
PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
|
||
|
if (pwifSection)
|
||
|
{
|
||
|
pwifAnswerFile->GotoEndOfSection(pwifSection);
|
||
|
pwifAnswerFile->AddKey(pwszKey, pwszValue);
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// Purpose: save BOOL data to our internal CWinfFile object
|
||
|
inline HRESULT HrSetupSetFirstStringAsBool(IN HWIF hwif,
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN BOOL fValue)
|
||
|
{
|
||
|
Assert (hwif && pwszSection && pwszKey);
|
||
|
CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
|
||
|
|
||
|
PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
|
||
|
if (pwifSection)
|
||
|
{
|
||
|
pwifAnswerFile->GotoEndOfSection(pwifSection);
|
||
|
pwifAnswerFile->AddBoolKey(pwszKey, fValue);
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// Purpose: save MULTI_SZ to our internal CWinfFile object
|
||
|
HRESULT HrSetupSetFirstMultiSzField(IN HWIF hwif,
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN PCWSTR pmszValue)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
Assert (hwif && pwszSection && pwszKey && pmszValue);
|
||
|
|
||
|
TStringList slValues;
|
||
|
MultiSzToColString(pmszValue, &slValues);
|
||
|
if (slValues.empty())
|
||
|
{
|
||
|
// empty pmszValue
|
||
|
return HrSetupSetFirstString(hwif, pwszSection, pwszKey, pmszValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
|
||
|
PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
|
||
|
if (pwifSection)
|
||
|
{
|
||
|
pwifAnswerFile->GotoEndOfSection(pwifSection);
|
||
|
pwifAnswerFile->AddKey(pwszKey, slValues);
|
||
|
}
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
EraseAndDeleteAll(&slValues);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Implementation of INetCfgSysPrep component
|
||
|
inline HRESULT CNetCfgSysPrep::HrSetupSetFirstDword(
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN DWORD dwValue)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&m_csWrite);
|
||
|
if (m_hwif)
|
||
|
{
|
||
|
hr = ::HrSetupSetFirstDword(
|
||
|
m_hwif,
|
||
|
pwszSection,
|
||
|
pwszKey,
|
||
|
dwValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
LeaveCriticalSection(&m_csWrite);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
inline HRESULT CNetCfgSysPrep::HrSetupSetFirstString(
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN PCWSTR pwszValue)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&m_csWrite);
|
||
|
if (m_hwif)
|
||
|
{
|
||
|
hr = ::HrSetupSetFirstString(
|
||
|
m_hwif,
|
||
|
pwszSection,
|
||
|
pwszKey,
|
||
|
pwszValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
LeaveCriticalSection(&m_csWrite);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
inline HRESULT CNetCfgSysPrep::HrSetupSetFirstStringAsBool(
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN BOOL fValue)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&m_csWrite);
|
||
|
if (m_hwif)
|
||
|
{
|
||
|
hr = ::HrSetupSetFirstStringAsBool(
|
||
|
m_hwif,
|
||
|
pwszSection,
|
||
|
pwszKey,
|
||
|
fValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
LeaveCriticalSection(&m_csWrite);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
inline HRESULT CNetCfgSysPrep::HrSetupSetFirstMultiSzField(
|
||
|
IN PCWSTR pwszSection,
|
||
|
IN PCWSTR pwszKey,
|
||
|
IN PCWSTR pmszValue)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
EnterCriticalSection(&m_csWrite);
|
||
|
if (m_hwif)
|
||
|
{
|
||
|
hr = ::HrSetupSetFirstMultiSzField(
|
||
|
m_hwif,
|
||
|
pwszSection,
|
||
|
pwszKey,
|
||
|
pmszValue);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
LeaveCriticalSection(&m_csWrite);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: FNetSetupPrepareSysPrep
|
||
|
//
|
||
|
// Purpose: wrapper for HrSaveNetworkComponentsForSysPrep
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// Returns: TRUE on success, otherwise, FALSE
|
||
|
//
|
||
|
//
|
||
|
BOOL FNetSetupPrepareSysPrep()
|
||
|
{
|
||
|
INetCfg* pNetCfg = NULL;
|
||
|
BOOL fInitCom = TRUE;
|
||
|
HRESULT hr;
|
||
|
|
||
|
DefineFunctionName("FNetSetupPrepareSysPrep");
|
||
|
TraceFunctionEntry(ttidNetSetup);
|
||
|
|
||
|
hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg,
|
||
|
FALSE, // no write lock
|
||
|
0, // don't wait for it
|
||
|
L"Save Configuration for SysPrep",
|
||
|
NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// Retain our success in initializing COM only if we asked to
|
||
|
// initialize COM in the first place.
|
||
|
if (! fInitCom)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: Failed to init COM", __FUNCNAME__);
|
||
|
return FALSE;
|
||
|
}
|
||
|
// Save network component per adapter registry settings
|
||
|
hr = HrSaveNetworkComponentsForSysPrep(pNetCfg);
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
// delete the HKLM\SYSTEM\Setup\AnswerFileMap registry key if it exits
|
||
|
HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap);
|
||
|
}
|
||
|
|
||
|
HrUninitializeAndReleaseINetCfg (fInitCom, pNetCfg, FALSE);
|
||
|
}
|
||
|
|
||
|
TraceError("FNetSetupPrepareSysPrep", hr);
|
||
|
return (hr == S_OK)? TRUE : FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Function: HrSaveNetworkComponentsForSysPrep
|
||
|
//
|
||
|
// Purpose: Ask notify object to save adapter specific settings
|
||
|
//
|
||
|
// Parameters: pNetCfg [IN] - An INetCfg interface
|
||
|
//
|
||
|
// Returns: HRESULT, S_OK on success
|
||
|
//
|
||
|
//
|
||
|
// Note: only 1 network adapter card is supported. If there are more than 1,
|
||
|
// we'll pick the first working one.
|
||
|
HRESULT HrSaveNetworkComponentsForSysPrep(INetCfg* pNetCfg)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
GUID guidAdapter; // network adapter's Instance GUID
|
||
|
BOOL fApplyWrite = FALSE; // flag to save internal registry settings to Answer-File
|
||
|
BOOL fRet = TRUE;
|
||
|
|
||
|
DefineFunctionName("HrSaveNetworkComponentsForSysPrep");
|
||
|
|
||
|
hr = HrGetFirstAdapterInstanceGuid(pNetCfg, FALSE, &guidAdapter); // FALSE ==> not in setup
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: HrGetFirstAdapterInstanceGuid failed 0x%08x", __FUNCNAME__, hr);
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
CWInfFile* pwifAnswerFile = new CWInfFile();
|
||
|
// initialize answer file class
|
||
|
if ((pwifAnswerFile == NULL) || (pwifAnswerFile->Init() == FALSE))
|
||
|
{
|
||
|
AssertSz(FALSE,"HrSaveNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
|
||
|
if (pwifAnswerFile)
|
||
|
delete pwifAnswerFile;
|
||
|
return(E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
// access INetCfgSysPrep ATL component using C++ instead of CoCreateInstance
|
||
|
CComObject<CNetCfgSysPrep>* pncsp = new CComObject<CNetCfgSysPrep>;
|
||
|
// initialize CNetCfgSysPrep class
|
||
|
if ((pncsp == NULL) || (pncsp->HrInit((HWIF) pwifAnswerFile) != S_OK))
|
||
|
{
|
||
|
AssertSz(FALSE,"HrSaveNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
|
||
|
delete pwifAnswerFile;
|
||
|
if (pncsp)
|
||
|
delete pncsp;
|
||
|
return(E_OUTOFMEMORY);
|
||
|
}
|
||
|
pncsp->AddRef(); // keep a reference to our component
|
||
|
|
||
|
for (UINT nIdx = 0; nIdx < celems(g_IdMap); nIdx++)
|
||
|
{
|
||
|
INetCfgComponent* pINetCfgComponent;
|
||
|
PCWSTR pwszInfId;
|
||
|
PCWSTR pwszAdapterParamsSections;
|
||
|
|
||
|
|
||
|
pwszInfId = g_IdMap[nIdx].pwszId;
|
||
|
pwszAdapterParamsSections = g_IdMap[nIdx].pwszIdAdapterParamsSection;
|
||
|
|
||
|
hr = pNetCfg->FindComponent(pwszInfId, &pINetCfgComponent);
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
Assert (pINetCfgComponent);
|
||
|
// Component has already installed, we'll call notify object's
|
||
|
// INetCfgComponentSysPrep::SaveAdapterParameters
|
||
|
|
||
|
// Need to query for the private component interface which
|
||
|
// gives us access to the notify object.
|
||
|
//
|
||
|
INetCfgComponentPrivate* pComponentPrivate;
|
||
|
hr = pINetCfgComponent->QueryInterface(
|
||
|
IID_INetCfgComponentPrivate,
|
||
|
reinterpret_cast<void**>(&pComponentPrivate));
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
INetCfgComponentSysPrep* pINetCfgComponentSysPrep;
|
||
|
|
||
|
// Query the notify object for its INetCfgComponentSysPrep interface.
|
||
|
// If it doesn't support it, that's okay, we can continue.
|
||
|
//
|
||
|
|
||
|
hr = pComponentPrivate->QueryNotifyObject(
|
||
|
IID_INetCfgComponentSysPrep,
|
||
|
(void**) &pINetCfgComponentSysPrep);
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
// add a section first
|
||
|
pwifAnswerFile->AddSection(pwszAdapterParamsSections);
|
||
|
// trigger Notify object to save registry settings
|
||
|
hr = pINetCfgComponentSysPrep->SaveAdapterParameters(
|
||
|
reinterpret_cast<INetCfgSysPrep*>(pncsp), pwszAdapterParamsSections, &guidAdapter);
|
||
|
if (hr == S_OK)
|
||
|
fApplyWrite = TRUE;
|
||
|
ReleaseObj(pINetCfgComponentSysPrep);
|
||
|
}
|
||
|
else if (hr == E_NOINTERFACE)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: %S component doesn't support IID_INetCfgComponentSysPrep", __FUNCNAME__, pwszInfId);
|
||
|
}
|
||
|
else
|
||
|
fRet = FALSE; // unexpected error
|
||
|
ReleaseObj(pComponentPrivate);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: can't find IID_INetCfgComponentPrivate for component %S", __FUNCNAME__, pwszInfId);
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
|
||
|
ReleaseObj (pINetCfgComponent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// it is okay that this component has not been installed
|
||
|
TraceTag(ttidNetSetup, "%s: Can't find %S component", __FUNCNAME__, pwszInfId);
|
||
|
}
|
||
|
} // end for
|
||
|
|
||
|
|
||
|
pncsp->SetHWif(NULL); // no more writes for those components holding our INetCfgSysPrep interface
|
||
|
ReleaseObj(pncsp); // done with the usage of INetCfgSysPrep component
|
||
|
|
||
|
if (fApplyWrite)
|
||
|
{
|
||
|
WCHAR wszSystemDir[MAX_PATH];
|
||
|
|
||
|
// get the path to $ncsp$.inf (NetConfig SysPrep Answer-File)
|
||
|
if (GetSystemDirectory(wszSystemDir, MAX_PATH) != 0)
|
||
|
{
|
||
|
tstring strAnswerFile;
|
||
|
strAnswerFile = wszSystemDir;
|
||
|
strAnswerFile += c_szNetConfigSysPrepAnswerFile;
|
||
|
// save the parameters filled by notify object to Answer-File
|
||
|
if (! pwifAnswerFile->SaveAsEx(strAnswerFile.c_str()))
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: GetSystemDirectory failed 0x%8x", __FUNCNAME__, GetLastError());
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete pwifAnswerFile;
|
||
|
|
||
|
return fRet? S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: FNetSetupApplySysPrep
|
||
|
//
|
||
|
// Purpose: wrapper for HrRestoreNetworkComponentsForSysPrep
|
||
|
//
|
||
|
// Parameters:
|
||
|
//
|
||
|
// Returns: TRUE on success, otherwise, FALSE
|
||
|
//
|
||
|
// Notes: This causes NetSetup to load the content of
|
||
|
// %systemroot%\system32\$ncsp$.inf into a CWInfFile object.
|
||
|
// Then, NetSetup will instruct notify object to restore their
|
||
|
// per adatper settings from the corresponding sections of the
|
||
|
// $ncsp$.inf file.
|
||
|
|
||
|
BOOL FNetSetupApplySysPrep()
|
||
|
{
|
||
|
INetCfg* pNetCfg = NULL;
|
||
|
BOOL fInitCom = TRUE;
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
DefineFunctionName("FNetSetupApplySysPrep");
|
||
|
TraceFunctionEntry(ttidNetSetup);
|
||
|
|
||
|
hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg,
|
||
|
FALSE, // no write lock
|
||
|
0, // don't wait for it
|
||
|
L"Restore Configuration for SysPrep",
|
||
|
NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
// Retain our success in initializing COM only if we asked to
|
||
|
// initialize COM in the first place.
|
||
|
if (! fInitCom)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: Failed to init COM", __FUNCNAME__);
|
||
|
return FALSE;
|
||
|
}
|
||
|
// Restore network component per adapter registry settings
|
||
|
hr = HrRestoreNetworkComponentsForSysPrep(pNetCfg);
|
||
|
|
||
|
HrUninitializeAndReleaseINetCfg (fInitCom, pNetCfg, FALSE);
|
||
|
}
|
||
|
|
||
|
TraceError("FNetSetupApplySysPrep", hr);
|
||
|
return (hr == S_OK)? TRUE : FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: HrRestoreNetworkComponentsForSysPrep
|
||
|
//
|
||
|
// Purpose: read $ncsp$.inf file. If this file has
|
||
|
// adapter specific sections, trigger the corresponding
|
||
|
// notify object to restore the settings to registry.
|
||
|
//
|
||
|
// Parameters: pNetCfg [IN] - An INetCfg interface
|
||
|
//
|
||
|
// Returns: HRESULT, S_OK on success
|
||
|
//
|
||
|
//
|
||
|
HRESULT HrRestoreNetworkComponentsForSysPrep(INetCfg* pNetCfg)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
GUID guidAdapter; // network adapter's Instance GUID
|
||
|
WCHAR wszSystemDir[MAX_PATH]; // system32 directory
|
||
|
tstring strAnswerFile; // Answer-File which was saved by SysPrep
|
||
|
BOOL fRet = TRUE; // notify object's status in restore settings
|
||
|
|
||
|
DefineFunctionName("HrRestoreNetworkComponentsForSysPrep");
|
||
|
|
||
|
|
||
|
// get the path to $ncsp$.inf (NetConfig SysPrep Answer-File)
|
||
|
if (GetSystemDirectory(wszSystemDir, MAX_PATH) != 0)
|
||
|
{
|
||
|
strAnswerFile = wszSystemDir;
|
||
|
strAnswerFile += c_szNetConfigSysPrepAnswerFile;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: GetSystemDirectory failed 0x%8x", __FUNCNAME__, GetLastError());
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
hr = HrGetFirstAdapterInstanceGuid(pNetCfg, TRUE, &guidAdapter); // TRUE ==> during setup
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: HrGetFirstAdapterInstanceGuid failed 0x%08x", __FUNCNAME__, hr);
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
CWInfFile* pwifAnswerFile = new CWInfFile();
|
||
|
// initialize answer file class
|
||
|
if ((pwifAnswerFile == NULL) || (pwifAnswerFile->Init() == FALSE))
|
||
|
{
|
||
|
AssertSz(FALSE,"HrRestoreNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
|
||
|
if (pwifAnswerFile)
|
||
|
delete pwifAnswerFile;
|
||
|
return(E_OUTOFMEMORY);
|
||
|
}
|
||
|
// read $ncsp$.inf Answer-File into pwifAnswerFile object
|
||
|
if (pwifAnswerFile->Open(strAnswerFile.c_str()) == FALSE)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: pwifAnswerFile->Open failed 0x%08x", __FUNCNAME__);
|
||
|
delete pwifAnswerFile;
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
for (UINT nIdx = 0; nIdx < celems(g_IdMap); nIdx++)
|
||
|
{
|
||
|
INetCfgComponent* pINetCfgComponent;
|
||
|
PCWSTR pwszInfId; // component ID
|
||
|
PCWSTR pwszAdapterParamsSections; // adapter specific parameter section
|
||
|
|
||
|
|
||
|
pwszInfId = g_IdMap[nIdx].pwszId;
|
||
|
pwszAdapterParamsSections = g_IdMap[nIdx].pwszIdAdapterParamsSection;
|
||
|
|
||
|
// trigger Notify object to restore registry settings if
|
||
|
// the section has at least one line of parameter
|
||
|
pwifAnswerFile->FindSection(pwszAdapterParamsSections);
|
||
|
if (FSectionHasAtLeastOneKey(pwifAnswerFile, pwszAdapterParamsSections))
|
||
|
{
|
||
|
hr = pNetCfg->FindComponent(pwszInfId, &pINetCfgComponent);
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
Assert (pINetCfgComponent);
|
||
|
// Component has already installed, just call notify object's
|
||
|
// INetCfgComponentSysPrep::RestoreAdapterParameters
|
||
|
|
||
|
// Need to query for the private component interface which
|
||
|
// gives us access to the notify object.
|
||
|
//
|
||
|
INetCfgComponentPrivate* pComponentPrivate;
|
||
|
hr = pINetCfgComponent->QueryInterface(
|
||
|
IID_INetCfgComponentPrivate,
|
||
|
reinterpret_cast<void**>(&pComponentPrivate));
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
INetCfgComponentSysPrep* pINetCfgComponentSysPrep;
|
||
|
|
||
|
// Query the notify object for its INetCfgComponentSysPrep interface.
|
||
|
// If it doesn't support it, that's okay, we can continue.
|
||
|
//
|
||
|
|
||
|
hr = pComponentPrivate->QueryNotifyObject(
|
||
|
IID_INetCfgComponentSysPrep,
|
||
|
(void**) &pINetCfgComponentSysPrep);
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
hr = pINetCfgComponentSysPrep->RestoreAdapterParameters(
|
||
|
strAnswerFile.c_str(), pwszAdapterParamsSections, &guidAdapter);
|
||
|
if (hr != S_OK)
|
||
|
fRet = FALSE; // notify object can't restore settings
|
||
|
ReleaseObj(pINetCfgComponentSysPrep);
|
||
|
}
|
||
|
else if (hr == E_NOINTERFACE)
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: %S component doesn't support IID_INetCfgComponentSysPrep", __FUNCNAME__, pwszInfId);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
fRet = FALSE; // unexpected error
|
||
|
ReleaseObj(pComponentPrivate);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: can't find IID_INetCfgComponentPrivate for component %S", __FUNCNAME__, pwszInfId);
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
ReleaseObj (pINetCfgComponent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// this component wasn't installed before SysPrep
|
||
|
TraceTag(ttidNetSetup, "%s: Can't find %S component", __FUNCNAME__, pwszInfId);
|
||
|
}
|
||
|
} // end if section has at least one key to restore setting
|
||
|
} // end for
|
||
|
|
||
|
// delete the Answer-File in free build.
|
||
|
#ifndef DBG
|
||
|
DeleteFile(strAnswerFile.c_str());
|
||
|
#endif
|
||
|
delete pwifAnswerFile;
|
||
|
return fRet? S_OK : S_FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: FSectionHasAtLeastOneKey
|
||
|
//
|
||
|
// Purpose: Check if an Answer-File section has at least one key
|
||
|
//
|
||
|
// Parameters: pwifAnswerFile [IN] - pointer to a CWInfFile object
|
||
|
// pszSection [IN] - the section to check
|
||
|
//
|
||
|
// Returns: TRUE if found else FALSE
|
||
|
//
|
||
|
BOOL FSectionHasAtLeastOneKey(IN CWInfFile* pwifAnswerFile, IN PCWSTR pwszSection)
|
||
|
{
|
||
|
Assert(pwifAnswerFile && pwszSection);
|
||
|
PCWInfSection pwifs = pwifAnswerFile->FindSection(pwszSection);
|
||
|
if (pwifs == NULL)
|
||
|
return FALSE;
|
||
|
PCWInfKey pwifk = pwifs->FirstKey();
|
||
|
if (pwifs == NULL)
|
||
|
return FALSE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Function: HrGetFirstAdapterInstanceGuid
|
||
|
//
|
||
|
// Purpose: Get the first installed adapter instance guid
|
||
|
//
|
||
|
// Parameters: pnc [IN] - An INetCfg interface
|
||
|
// fDuringSetup [IN] - TRUE when this is being called during the setup time
|
||
|
// pGuidAdapter [IN,OUT] - Receives an instance GUID of an adapter
|
||
|
//
|
||
|
// Returns: HRESULT, S_OK on success
|
||
|
//
|
||
|
HRESULT HrGetFirstAdapterInstanceGuid(INetCfg * pnc, BOOL fDuringSetup, GUID * pGuidAdapter)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
DefineFunctionName("HrGetFirstAdapterInstanceGuid");
|
||
|
TraceTag(ttidNetSetup, "HrGetFirstAdapterInstanceGuid - Enter Find first available adapter");
|
||
|
|
||
|
// Enumerate the available adapters
|
||
|
Assert(pnc && pGuidAdapter);
|
||
|
CIterNetCfgComponent nccIter(pnc, &GUID_DEVCLASS_NET);
|
||
|
INetCfgComponent* pncc;
|
||
|
while (SUCCEEDED(hr) && (S_OK == (hr = nccIter.HrNext(&pncc))))
|
||
|
{
|
||
|
hr = HrIsLanCapableAdapter(pncc);
|
||
|
TraceError("HrIsLanCapableAdapter", hr);
|
||
|
if (S_OK == hr)
|
||
|
{
|
||
|
DWORD dw;
|
||
|
ULONG ul;
|
||
|
|
||
|
TraceTag(ttidNetSetup, "%s: Found HrIsLanCapableAdapter", __FUNCNAME__);
|
||
|
|
||
|
if (! fDuringSetup)
|
||
|
{
|
||
|
// Is it in used in a connection?
|
||
|
hr = HrIsConnection(pncc);
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
TraceError("HrGetFirstAdapterInstanceGuid: HrIsConnection", hr);
|
||
|
goto NextAdapter;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Is this a virtual adapter?
|
||
|
hr = pncc->GetCharacteristics(&dw);
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
TraceError("GetCharacteristics", hr);
|
||
|
goto NextAdapter;
|
||
|
}
|
||
|
if (! (dw & NCF_PHYSICAL))
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: It is not a PHYSICAL adapter", __FUNCNAME__);
|
||
|
goto NextAdapter;
|
||
|
}
|
||
|
|
||
|
// Check device, if not present skip it
|
||
|
//
|
||
|
hr = pncc->GetDeviceStatus(&ul);
|
||
|
if ((hr != S_OK) || (ul != 0))
|
||
|
{
|
||
|
TraceTag(ttidNetSetup, "%s: device is not active.", __FUNCNAME__);
|
||
|
goto NextAdapter;
|
||
|
}
|
||
|
|
||
|
// Get the adapter instance guid
|
||
|
hr = pncc->GetInstanceGuid(pGuidAdapter);
|
||
|
if (hr != S_OK)
|
||
|
{
|
||
|
TraceError("GetInstanceGuid", hr); //
|
||
|
goto NextAdapter;
|
||
|
}
|
||
|
|
||
|
ReleaseObj(pncc);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
NextAdapter:
|
||
|
ReleaseObj(pncc);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|