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

817 lines
24 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: A F I L E X P . C P P
//
// Contents: Functions exported from netsetup for answerfile related work.
//
// Author: kumarp 25-November-97
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "afileint.h"
#include "afilexp.h"
#include "compid.h"
#include "kkenet.h"
#include "kkutils.h"
#include "ncerror.h"
#include "ncnetcfg.h"
#include "ncsetup.h"
#include "nsbase.h"
#include "oemupgrd.h"
#include "resource.h"
#include "upgrade.h"
#include <wdmguid.h>
#include "nslog.h"
//+---------------------------------------------------------------------------
// Global variables
//
CNetInstallInfo* g_pnii;
CNetInstallInfo* g_pniiTemp;
DWORD g_dwOperationFlags = 0;
//+---------------------------------------------------------------------------
//
// Function: HrDoUnattend
//
// Purpose: call member function of CNetInstallInfo to perform
// answerfile based install/upgrade work
//
// Arguments:
// hwndParent [in] handle of parent window
// punk [in] pointer to an interface
// idPage [in] id indicating which section to run
// ppdm [out] pointer to page display mode
// pfAllowChanges [out] pointer to flag controlling read/write behavior
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 26-November-97
//
EXTERN_C
HRESULT
WINAPI
HrDoUnattend (
IN HWND hwndParent,
IN IUnknown* punk,
IN EUnattendWorkType uawType,
OUT EPageDisplayMode* ppdm,
OUT BOOL* pfAllowChanges)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(punk);
Assert(ppdm);
Assert(pfAllowChanges);
Assert(g_pnii);
HRESULT hr = S_OK;
#if DBG
if (FIsDebugFlagSet (dfidBreakOnDoUnattend))
{
AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag "
"\"BreakOnDoUnattend\" has been set. Set your breakpoints now.");
}
#endif //_DEBUG
hr = g_pnii->HrDoUnattended(hwndParent, punk, uawType, ppdm, pfAllowChanges);
TraceHr(ttidError, FAL, hr, FALSE, "HrDoUnattend");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInitForRepair
//
// Purpose: Initialize in repair mode.
//
// Arguments:
//
// Returns: S_OK on success, otherwise an error code
//
// Author: asinha 17-October-2001
//
HRESULT
HrInitForRepair (VOID)
{
TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
g_pnii = NULL;
hr = CNetInstallInfo::HrCreateInstance (
NULL,
&g_pnii);
TraceHr(ttidError, FAL, hr, FALSE,
"HrInitForRepair");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInitForUnattendedNetSetup
//
// Purpose: Initialize net setup for answerfile processing
//
// Arguments:
// pnc [in] pointer to INetCfg object
// pisd [in] pointer to private data supplied by base setup
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 26-November-97
//
HRESULT
HrInitForUnattendedNetSetup (
IN INetCfg* pnc,
IN PINTERNAL_SETUP_DATA pisd)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(pnc);
Assert(pisd);
HRESULT hr = S_OK;
g_dwOperationFlags = pisd->OperationFlags;
if (pisd->OperationFlags & SETUPOPER_BATCH)
{
Assert(pisd->UnattendFile);
AssertSz(!g_pnii, "who initialized g_pnii ??");
hr = HrInitAnswerFileProcessing(pisd->UnattendFile, &g_pnii);
}
TraceHr(ttidError, FAL, hr,
(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
(hr == NETSETUP_E_NO_ANSWERFILE),
"HrInitNetSetup");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrCleanupNetSetup
//
// Purpose: Do cleanup work in NetSetup
//
// Arguments: None
//
// Returns: Nothing
//
// Author: kumarp 26-November-97
//
VOID
HrCleanupNetSetup()
{
TraceFileFunc(ttidGuiModeSetup);
DeleteIfNotNull(g_pnii);
DeleteIfNotNull(g_pniiTemp);
}
//+---------------------------------------------------------------------------
//
// Function: HrGetAnswerFileName
//
// Purpose: Generate full path to the answerfile
//
// Arguments:
// pstrAnswerFileName [out] pointer to name of answerfile
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 26-November-97
//
// Notes: !!!This function has a dependency on the base setup.!!!
// If base setup changes name of the answerfile, this fn
// function will break.
//
HRESULT
HrGetAnswerFileName(
OUT tstring* pstrAnswerFileName)
{
TraceFileFunc(ttidGuiModeSetup);
static const WCHAR c_szAfSubDirAndName[] = L"\\system32\\$winnt$.inf";
HRESULT hr=S_OK;
WCHAR szWinDir[MAX_PATH+1];
DWORD cNumCharsReturned = GetSystemWindowsDirectory(szWinDir, MAX_PATH);
if (cNumCharsReturned)
{
*pstrAnswerFileName = szWinDir;
*pstrAnswerFileName += c_szAfSubDirAndName;
}
else
{
hr = HrFromLastWin32Error();
}
TraceHr(ttidError, FAL, hr, FALSE, "HrGetAnswerFileName");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrInitAnswerFileProcessing
//
// Purpose: Initialize answerfile processing
//
// Arguments:
// szAnswerFileName [in] name of answerfile
// ppnii [out] pointer to pointer to CNetInstallInfo object
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 26-November-97
//
HRESULT
HrInitAnswerFileProcessing (
IN PCWSTR szAnswerFileName,
OUT CNetInstallInfo** ppnii)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(ppnii);
HRESULT hr = S_OK;
tstring strAnswerFileName;
*ppnii = NULL;
if (!szAnswerFileName)
{
hr = HrGetAnswerFileName(&strAnswerFileName);
}
else
{
strAnswerFileName = szAnswerFileName;
}
if (S_OK == hr)
{
hr = CNetInstallInfo::HrCreateInstance (
strAnswerFileName.c_str(),
ppnii);
}
TraceHr(ttidError, FAL, hr,
(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
(hr == NETSETUP_E_NO_ANSWERFILE),
"HrInitAnswerFileProcessing");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrOemUpgrade
//
// Purpose: Process special OEM upgrades by running an inf section
//
// Arguments:
// hkeyDriver [in] the driver key
// pszAnswerFile [in] pointer to answer filename string.
// pszAnswerSection [in] pointer to answer filname sections string
//
// Returns: S_OK on success, otherwise an error code
//
// Date: 30 Mar 1998
//
EXTERN_C
HRESULT
WINAPI
HrOemUpgrade(
IN HKEY hkeyDriver,
IN PCWSTR pszAnswerFile,
IN PCWSTR pszAnswerSection)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(hkeyDriver);
Assert(pszAnswerFile);
Assert(pszAnswerSection);
// Open the answer file.
HINF hinf;
HRESULT hr = HrSetupOpenInfFile(pszAnswerFile, NULL,
INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf);
if (SUCCEEDED(hr))
{
tstring strInfToRun;
tstring strSectionToRun;
tstring strInfToRunType;
// Get the file and section to run for upgrade
hr = HrAfGetInfToRunValue(hinf, pszAnswerFile, pszAnswerSection,
I2R_AfterInstall, &strInfToRun, &strSectionToRun, &strInfToRunType);
if (S_OK == hr)
{
HINF hinfToRun;
// Open the inf file containing the section to run
hr = HrSetupOpenInfFile(strInfToRun.c_str(), NULL,
INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL,
&hinfToRun);
if (SUCCEEDED(hr))
{
TraceTag(ttidNetSetup, "Running section %S in %S",
strSectionToRun.c_str(), strInfToRun.c_str());
// Run the section against the key
hr = HrSetupInstallFromInfSection (NULL,
hinfToRun, strSectionToRun.c_str(), SPINST_REGISTRY,
hkeyDriver, NULL, 0, NULL, NULL, NULL, NULL);
NetSetupLogHrStatusV(hr, SzLoadIds (IDS_STATUS_OF_APPLYING),
pszAnswerSection,
strInfToRunType.c_str(),
strSectionToRun.c_str(),
strInfToRun.c_str());
SetupCloseInfFile(hinfToRun);
}
}
else if (SPAPI_E_LINE_NOT_FOUND == hr)
{
// Nothing to run.
hr = S_FALSE;
}
SetupCloseInfFile(hinf);
}
TraceHr(ttidError, FAL, hr, FALSE, "HrOemUpgrade");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetAnswerFileParametersForComponent
//
// Purpose: Search in answerfile for a component whose InfId matches
// the one specified.
//
// Arguments:
// pszInfId [in] inf id of component
// ppszAnswerFile [out] pointer to answer filename string.
// ppszAnswerSection [out] pointer to answer filename section string
//
// Returns: S_OK on success, otherwise an error code
//
// Author: billbe 12 July 1999
//
// Notes: This fcn is not for adapters. If you need the answerfile
// parameters for an adapter, use
// HrGetAnswerFileParametersForNetCard.
//
HRESULT
HrGetAnswerFileParametersForComponent (
IN PCWSTR pszInfId,
OUT PWSTR* ppszAnswerFile,
OUT PWSTR* ppszAnswerSection)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(pszInfId);
Assert(ppszAnswerFile);
Assert(ppszAnswerSection);
HRESULT hr = S_OK;
TraceTag (ttidNetSetup, "In HrGetAnswerFileParametersForComponent");
*ppszAnswerFile = NULL;
*ppszAnswerSection = NULL;
// If we don't already have a cached pointer...
if (!g_pniiTemp)
{
// Initialize our net install info.
hr = HrInitAnswerFileProcessing(NULL, &g_pniiTemp);
}
if (S_OK == hr)
{
Assert(g_pniiTemp);
if (!g_pniiTemp->AnswerFileInitialized())
{
hr = NETSETUP_E_NO_ANSWERFILE;
TraceTag (ttidNetSetup, "No answerfile");
}
if (S_OK == hr)
{
// Find the component in the list of component's with
// answer file sections.
CNetComponent* pnetcomp;
pnetcomp = g_pniiTemp->FindFromInfID (pszInfId);
if (!pnetcomp)
{
// The component doesn't have a section. Return
// no answer file.
hr = NETSETUP_E_NO_ANSWERFILE;
TraceTag (ttidNetSetup, "Component not found");
}
else
{
if (NCT_Adapter == pnetcomp->Type())
{
// We don't support getting answerfile parameters
// for adapters. HrGetAnswerFileParametersForNetCard
// is the fcn for adapters.
hr = NETSETUP_E_NO_ANSWERFILE;
}
else
{
// Allocate and save the answerfile name and the
// component's section.
hr = HrCoTaskMemAllocAndDupSz (g_pniiTemp->AnswerFileName(),
ppszAnswerFile);
if (S_OK == hr)
{
hr = HrCoTaskMemAllocAndDupSz (
pnetcomp->ParamsSections().c_str(),
ppszAnswerSection);
}
}
}
}
}
else
{
TraceTag (ttidNetSetup, "Answerfile could not be initialized");
}
TraceHr (ttidError, FAL, hr,
(NETSETUP_E_NO_ANSWERFILE == hr) ||
(HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) == hr),
"HrGetAnswerFileParametersForComponent");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetAnswerFileParametersForNetCard
//
// Purpose: Search in answerfile for a net card whose InfID matches
// at least one in the supplied multi-sz list.
//
// Arguments:
// mszInfIDs [in] list of InfIDs
// pszDeviceName [in] exported device name of the card to search
// pguidNetCardInstance [in] pointer to instance guid of the card
// pszAnswerFile [out] pointer to answer filename string.
// pszAnswerSection [out] pointer to answer filname sections string
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 26-November-97
//
// Notes: If more than one such card is found in the answerfile, then
// resolve between the cards by finding out the net-card-address
// of the pszServiceInstance and matching it against that
// stored in the answerfile.
//
EXTERN_C
HRESULT
WINAPI
HrGetAnswerFileParametersForNetCard(
IN HDEVINFO hdi,
IN PSP_DEVINFO_DATA pdeid,
IN PCWSTR pszDeviceName,
IN const GUID* pguidNetCardInstance,
OUT PWSTR* ppszwAnswerFile,
OUT PWSTR* ppszwAnswerSections)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(IsValidHandle(hdi));
Assert(pdeid);
Assert(pguidNetCardInstance);
Assert(ppszwAnswerFile);
Assert(ppszwAnswerSections);
HRESULT hr=E_FAIL;
CNetAdapter* pna=NULL;
WORD wNumAdapters=0;
QWORD qwNetCardAddr=0;
*ppszwAnswerFile = NULL;
*ppszwAnswerSections = NULL;
if (!g_pniiTemp)
{
hr = HrInitAnswerFileProcessing(NULL, &g_pniiTemp);
#if DBG
if (S_OK == hr)
{
Assert(g_pniiTemp);
}
#endif
if (FAILED(hr) || !g_pniiTemp->AnswerFileInitialized())
{
TraceHr (ttidNetSetup, FAL, hr, (hr == NETSETUP_E_NO_ANSWERFILE) ||
hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"HrGetAnswerFileParametersForNetCard");
return hr;
}
}
// the defs of HIDWORD and LODWORD are wrong in byteorder.hxx
# define LODWORD(a) (DWORD)( (a) & ( (DWORD)~0 ))
# define HIDWORD(a) (DWORD)( (a) >> (sizeof(DWORD)*8) )
hr = HrGetNetCardAddr(pszDeviceName, &qwNetCardAddr);
if ((S_OK == hr) && qwNetCardAddr)
{
// there is a bug in wvsprintfA (used in trace.cpp) which does not
// handle %I64x therefore we need to show the QWORD addr as follows
//
TraceTag(ttidNetSetup, "net card address of %S is 0x%x%x",
pszDeviceName, HIDWORD(qwNetCardAddr),
LODWORD(qwNetCardAddr));
hr = g_pniiTemp->FindAdapter(qwNetCardAddr, &pna);
if (NETSETUP_E_NO_EXACT_MATCH == hr)
{
TraceTag(ttidError, "there is no card with this netcard address in the answer-file");
}
}
else
{
TraceTag(ttidError, "error getting netcard address of %S",
pszDeviceName);
// if we either (a) failed to get the NetCard address, or
// (b) if the netcard address was 0 (ISDN adapters), we try other means
//
hr = NETSETUP_E_AMBIGUOUS_MATCH;
}
if (NETSETUP_E_AMBIGUOUS_MATCH == hr)
{
// could not match netcard using the mac addr. If this device is
// PCI, try to match using location info.
//
TraceTag (ttidNetSetup, "Did not find a match for netcard address. "
"But there was at least one section that did not specify an "
"address.\nChecking bus type of installed adapter.");
GUID BusTypeGuid;
hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid,
SPDRP_BUSTYPEGUID, NULL, (BYTE*)&BusTypeGuid,
sizeof (BusTypeGuid), NULL);
if (S_OK == hr)
{
if (GUID_BUS_TYPE_PCI == BusTypeGuid)
{
TraceTag (ttidNetSetup, "Installed adapter is PCI. "
"Retrieving its location info.");
DWORD BusNumber;
hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid,
SPDRP_BUSNUMBER, NULL, (BYTE*)&BusNumber,
sizeof (BusNumber), NULL);
if (S_OK == hr)
{
DWORD Address;
hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid,
SPDRP_ADDRESS, NULL, (BYTE*)&Address,
sizeof (Address), NULL);
if (S_OK == hr)
{
TraceTag (ttidNetSetup, "Installed device location: "
"Bus: %X, Device %x, Function %x\n Will try to "
"use location info to find a match with the "
"remaining ambiguous sections.", BusNumber,
HIWORD(Address), LOWORD(Address));
hr = g_pniiTemp->FindAdapter (BusNumber,
Address, &pna);
#ifdef ENABLETRACE
if (NETSETUP_E_NO_EXACT_MATCH == hr)
{
TraceTag (ttidNetSetup, "No match was found "
"using PCI location info.");
}
else if (NETSETUP_E_AMBIGUOUS_MATCH == hr)
{
TraceTag (ttidNetSetup, "Location info did not "
"match but some sections did not specify "
"location info.");
}
#endif // ENABLETRACE
}
}
}
else
{
hr = NETSETUP_E_AMBIGUOUS_MATCH;
}
}
if (FAILED(hr) && (NETSETUP_E_AMBIGUOUS_MATCH != hr) &&
(NETSETUP_E_NO_EXACT_MATCH != hr))
{
TraceHr(ttidNetSetup, FAL, hr, FALSE, "Trying to retrieve/use "
"PCI location info.");
hr = NETSETUP_E_AMBIGUOUS_MATCH;
}
if (NETSETUP_E_AMBIGUOUS_MATCH == hr)
{
// could not match netcard using the mac addr. try to match
// using the PnP ID
TraceTag (ttidNetSetup, "Will try to use pnp id to find a match "
"with the remaining ambiguous sections.");
PWSTR mszInfIds;
hr = HrGetCompatibleIds (hdi, pdeid, &mszInfIds);
if (S_OK == hr)
{
#ifdef ENABLETRACE
TStringList slInfIds;
tstring strInfIds;
MultiSzToColString(mszInfIds, &slInfIds);
ConvertStringListToCommaList(slInfIds, strInfIds);
TraceTag(ttidNetSetup, "(InfIDs (%d): %S\tDeviceName: %S)",
slInfIds.size(), strInfIds.c_str(), pszDeviceName);
#endif
// find out how many adapters have this InfID
wNumAdapters = g_pniiTemp->AdaptersPage()->GetNumCompatibleAdapters(mszInfIds);
TraceTag(ttidNetSetup, "%d adapters of type '%S' found in the answer-file",
wNumAdapters, mszInfIds);
if (wNumAdapters == 1)
{
// a definite match found
pna = (CNetAdapter*) g_pniiTemp->AdaptersPage()->FindCompatibleAdapter(mszInfIds);
Assert(pna);
// Since matching by inf id can cause one section to be
// matched to multiple adapters, we pass on sections that
// have already been give to an adapter.
//
GUID guid = GUID_NULL;
pna->GetInstanceGuid(&guid);
if (GUID_NULL == guid)
{
// The section is still available.
hr = S_OK;
}
else
{
// This section was given to another adapter.
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
}
else
{
// either there are no adapters of this type in the answerfile
// or there are multiple adapters of the same type.
// we couldn't match the card using the mac addr earlier.
// must return error
//
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
MemFree (mszInfIds);
}
}
}
if (S_OK == hr)
{
Assert(pna);
pna->SetInstanceGuid(pguidNetCardInstance);
hr = HrCoTaskMemAllocAndDupSz(g_pniiTemp->AnswerFileName(),
(PWSTR*) ppszwAnswerFile);
if (S_OK == hr)
{
hr = HrCoTaskMemAllocAndDupSz(pna->ParamsSections().c_str(),
(PWSTR*) ppszwAnswerSections);
}
}
if (S_OK != hr && (NETSETUP_E_NO_ANSWERFILE != hr))
{
// add log so that we know why adapter specific params
// are lost after upgrade
//
if (g_dwOperationFlags & SETUPOPER_NTUPGRADE)
{ // bug 124805 - We only want to see this during upgradres
WCHAR szGuid[c_cchGuidWithTerm];
StringFromGUID2(*pguidNetCardInstance, szGuid, c_cchGuidWithTerm);
NetSetupLogStatusV(LogSevWarning,
SzLoadIds (IDS_ANSWERFILE_SECTION_NOT_FOUND),
szGuid);
}
}
if ((NETSETUP_E_AMBIGUOUS_MATCH == hr) ||
(NETSETUP_E_NO_EXACT_MATCH == hr))
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
TraceHr(ttidError, FAL, hr,
(hr == NETSETUP_E_NO_ANSWERFILE) ||
(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)),
"HrGetAnswerFileParametersForNetCard");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrGetInstanceGuidOfPreNT5NetCardInstance
//
// Purpose: Finds the instance guid of a component specified in the answerfile
// or an already installed component
//
// Arguments:
// szPreNT5NetCardInstance [in] pre-NT5 net card instance name e.g. "ieepro2"
// pguid [out] instance guid of the same card
//
// Returns: S_OK if found, S_FALSE if not, or an error code.
//
// Author: kumarp 12-AUG-97
//
// Notes:
//
EXTERN_C
HRESULT
WINAPI
HrGetInstanceGuidOfPreNT5NetCardInstance (
IN PCWSTR szPreNT5NetCardInstance,
OUT LPGUID pguid)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(szPreNT5NetCardInstance);
Assert(pguid);
HRESULT hr = E_FAIL;
if (IsBadStringPtr(szPreNT5NetCardInstance, 64) ||
IsBadWritePtr(pguid, sizeof(GUID)))
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
}
else if (g_pnii)
{
hr = g_pnii->HrGetInstanceGuidOfPreNT5NetCardInstance (
szPreNT5NetCardInstance, pguid);
}
TraceHr(ttidError, FAL, hr, FALSE,
"HrGetInstanceGuidOfPreNT5NetCardInstance");
return hr;
}
HRESULT
HrResolveAnswerFileAdapters (
IN INetCfg* pnc)
{
TraceFileFunc(ttidGuiModeSetup);
Assert(g_pnii);
HRESULT hr = S_OK;
if (g_pnii)
{
hr = g_pnii->AdaptersPage()->HrResolveNetAdapters(pnc);
}
TraceHr(ttidError, FAL, hr, FALSE, "HrResolveAnswerFileAdapters");
return hr;
}