windows-nt/Source/XPSP1/NT/net/config/netcfg/engine/adapter.cpp
2020-09-26 16:20:57 +08:00

401 lines
12 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1999.
//
// File: A D A P T E R. C P P
//
// Contents: Class installer functions for eumerated devices.
//
// Notes:
//
// Author: billbe 11 Nov 1996
//
//---------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "adapter.h"
#include "benchmrk.h"
#include "classinst.h"
#include "ncreg.h"
#include "ncsvc.h"
#include "netcomm.h"
VOID
CiSetFriendlyNameIfNeeded(IN const COMPONENT_INSTALL_INFO &cii);
//+--------------------------------------------------------------------------
//
// Function: HrCiGetBusInfoFromInf
//
// Purpose: Finds an adapter's bus information as listed in its inf
// file.
//
// Arguments:
// hinfFile [in] A handle to the component's inf file
// szSectionName [in] The inf section to search in
// peBusType [out] The bus type of the adapter
// pulAdapterId [out] The AdapterId of the adapter (Eisa and Mca)
// pulAdapterMask [out] The AdapterMask of the adapter (Eisa)
//
// Returns: HRESULT. S_OK if successful, error code otherwise
//
// Author: billbe 14 Jun 1997
//
// Notes:
//
HRESULT
HrCiGetBusInfoFromInf (HINF hinfFile, COMPONENT_INSTALL_INFO* pcii)
{
HRESULT hr = S_OK;
if (InterfaceTypeUndefined == pcii->BusType)
{
// Find the inf line that contains BusType and retrieve it
DWORD dwBusType;
hr = HrSetupGetFirstDword(hinfFile, pcii->pszSectionName,
L"BusType", &dwBusType);
if (S_OK == hr)
{
pcii->BusType = EInterfaceTypeFromDword(dwBusType);
}
else
{
TraceTag (ttidError, "Inf missing BusType field.");
}
}
TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetBusInfoFromInf");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiInstallEnumeratedComponent
//
// Purpose: This function completes the install of an enumerated
// device.
//
// Arguments:
// hinf [in] SetupApi handle to an inf file
// hkeyInstance [in] The registry instance key of the adapter
// during inf processing.
// pcai [in] A structure containing the component information
// See compinst.h for definition
// hwndParent [in] The handle to the parent, for displaying UI
// hdi [in] See Device Installer Api for more info
// pdeid [in] See Device Installer Api for more info
//
// Returns: HRESULT. S_OK if successful and no restart required,
// NETCFG_S_REBOOT if a reboot is required,
// or error code otherwise
//
// Author: billbe 28 Apr 1997
//
// Notes:
//
HRESULT
HrCiInstallEnumeratedComponent (
IN HINF hinf,
IN HKEY hkeyInstance,
IN const COMPONENT_INSTALL_INFO& cii)
{
Assert (IsValidHandle (hinf));
Assert (hkeyInstance);
Assert (IsValidHandle (cii.hdi));
Assert (cii.pdeid);
HRESULT hr;
// Because adapters can share descriptions, we may need to append
// instance info so the user and other apps can differentiate.
//
// If the following fcn fails, we can still go on and
// install the adapter.
CiSetFriendlyNameIfNeeded (cii);
// Is this a PCI multiport adapter where each port has the same
// PnP Id? This is indicated by the inf value Port1DeviceNumber or
// Port1FunctionNumber in the main section.
//
if (PCIBus == cii.BusType)
{
INFCONTEXT ctx;
DWORD dwPortNumber;
BOOL fUseDeviceNumber;
DWORD dwFirstPort;
hr = HrSetupGetFirstDword (hinf, cii.pszSectionName,
L"Port1DeviceNumber", &dwFirstPort);
if (S_OK == hr)
{
// The port number is based on the device number.
fUseDeviceNumber = TRUE;
}
else
{
hr = HrSetupGetFirstDword (hinf, cii.pszSectionName,
L"Port1FunctionNumber", &dwFirstPort);
if (S_OK == hr)
{
// The port number is based on the function number.
fUseDeviceNumber = FALSE;
}
}
if (S_OK == hr)
{
// We have a mapping so now we need to get the address of the
// device (device and function number).
//
DWORD dwAddress;
hr = HrSetupDiGetDeviceRegistryProperty(cii.hdi, cii.pdeid,
SPDRP_ADDRESS, NULL, (BYTE*)&dwAddress, sizeof(dwAddress),
NULL);
if (S_OK == hr)
{
// Use our mapping to get the correct port number.
//
DWORD dwPortLocation;
dwPortLocation = fUseDeviceNumber ?
HIWORD(dwAddress) : LOWORD(dwAddress);
// Make sure the port location (either device or
// function number) is greater than or equal to the first
// port number, otherwise we will get a bogus port number.
//
if (dwPortLocation >= dwFirstPort)
{
dwPortNumber = dwPortLocation - dwFirstPort + 1;
// Now store the port number in the device key for internal
// consumption.
HKEY hkeyDev;
hr = HrSetupDiCreateDevRegKey (cii.hdi, cii.pdeid,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL, &hkeyDev);
if (S_OK == hr)
{
(VOID) HrRegSetDword (hkeyDev, L"Port", dwPortNumber);
RegCloseKey (hkeyDev);
}
// Store the port in the driver key for public
// consumption.
//
(VOID) HrRegSetDword (hkeyInstance, L"Port",
dwPortNumber);
}
}
}
else
{
// No mapping available, so we won't display port number.
hr = S_OK;
}
}
// Update any advanced parameters that do not have a current value
// with a default.
UpdateAdvancedParametersIfNeeded (cii.hdi, cii.pdeid);
// On fresh installs, INetCfg will be starting this adapter,
// so we have to make sure we don't.
//
if (!cii.fPreviouslyInstalled)
{
(VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG,
SDDFT_FLAGS, SDFBO_OR);
}
// Now finish the install of the adapter.
//
TraceTag(ttidClassInst, "Calling SetupDiInstallDevice");
#ifdef ENABLETRACE
CBenchmark bmrk;
bmrk.Start("SetupDiInstallDevice");
#endif //ENABLETRACE
hr = HrSetupDiInstallDevice (cii.hdi, cii.pdeid);
#ifdef ENABLETRACE
bmrk.Stop();
TraceTag(ttidBenchmark, "%s : %s seconds",
bmrk.SznDescription(), bmrk.SznBenchmarkSeconds (2));
#endif //ENABLETRACE
if (!cii.fPreviouslyInstalled)
{
(VOID) HrSetupDiSetDeipFlags (cii.hdi, cii.pdeid, DI_DONOTCALLCONFIGMG,
SDDFT_FLAGS, SDFBO_XOR);
}
TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr,
"HrCiInstallEnumeratedComponent");
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: HrCiRegOpenKeyFromEnumDevs
//
// Purpose: Enumerates through each device in an HDEVINFO and returns an
// hkey to its driver key.
//
// Arguments:
// hdi [in] See Device Installer Api
// dwIndex [inout] The index of the device to retrieve
// samDesired [in] The access level of the hkey
// phkey [out] The device's driver key
//
// Returns: HRESULT. S_OK if successful, an error code otherwise
//
// Author: billbe 13 Jun 1997
//
// Notes:
//
HRESULT
HrCiRegOpenKeyFromEnumDevs(HDEVINFO hdi, DWORD* pIndex, REGSAM samDesired,
HKEY* phkey)
{
Assert(IsValidHandle(hdi));
Assert (phkey);
// Initialize output parameter.
*phkey = NULL;
SP_DEVINFO_DATA deid;
HRESULT hr;
// enumerate through the devices
while ((S_OK == (hr = HrSetupDiEnumDeviceInfo(hdi, *pIndex, &deid))))
{
// open the adapter's instance key
HRESULT hrT;
hrT = HrSetupDiOpenDevRegKey(hdi, &deid, DICS_FLAG_GLOBAL,
0, DIREG_DRV, samDesired, phkey);
if (S_OK == hrT)
{
break;
}
else
{
// If the key does not exists this is a phantom device,
// (or if this device is hosed, we want to ignore it too)
// move on to the next one and delete this one from
// our list
(*pIndex)++;
(VOID)SetupDiDeleteDeviceInfo(hdi, &deid);
}
}
TraceHr (ttidError, FAL, hr,
HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr,
"HrCiRegOpenKeyFromEnumDevs");
return hr;
}
///////////////Legacy NT4 app support///////////////////////////////////
VOID
AddOrRemoveLegacyNt4AdapterKey (
IN HDEVINFO hdi,
IN PSP_DEVINFO_DATA pdeid,
IN const GUID* pInstanceGuid,
IN PCWSTR pszDescription,
IN LEGACY_NT4_KEY_OP Op)
{
Assert (IsValidHandle (hdi));
Assert (pdeid);
Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pInstanceGuid));
Assert (FImplies ((LEGACY_NT4_KEY_ADD == Op), pszDescription));
extern const WCHAR c_szRegKeyNt4Adapters[];
const WCHAR c_szRegValDescription[] = L"Description";
const WCHAR c_szRegValServiceName[] = L"ServiceName";
PWSTR pszDriver;
HRESULT hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc (
hdi, pdeid, SPDRP_DRIVER, NULL, (BYTE**)&pszDriver);
if (S_OK == hr)
{
PWSTR pszNumber = wcsrchr (pszDriver, L'\\');
if (pszNumber && *(++pszNumber))
{
PWSTR pszStopString;
ULONG Instance = 0;
HKEY hkeyAdapters;
Instance = wcstoul (pszNumber, &pszStopString, c_nBase10);
// The NT4 key was one based so increment the instance number.
Instance++;
DWORD Disp;
hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE, c_szRegKeyNt4Adapters,
0, KEY_WRITE, NULL, &hkeyAdapters, &Disp);
if (S_OK == hr)
{
WCHAR szInstanceNumber [12];
_snwprintf (szInstanceNumber, celems(szInstanceNumber) - 1,
L"%d", Instance);
HKEY hkeyInstance;
if (LEGACY_NT4_KEY_ADD == Op)
{
hr = HrRegCreateKeyEx (hkeyAdapters, szInstanceNumber, 0,
KEY_WRITE, NULL, &hkeyInstance, NULL);
if (S_OK == hr)
{
WCHAR szGuid[c_cchGuidWithTerm];
StringFromGUID2 (*pInstanceGuid, szGuid,
c_cchGuidWithTerm);
hr = HrRegSetValueEx (hkeyInstance,
c_szRegValServiceName, REG_SZ,
(const BYTE*)szGuid, sizeof (szGuid));
TraceHr (ttidError, FAL, hr, FALSE,
"AddAdapterToNt4Key: Setting Service Name "
"in legacy registry");
hr = HrRegSetValueEx (hkeyInstance,
c_szRegValDescription, REG_SZ,
(const BYTE*)pszDescription,
CbOfSzAndTerm (pszDescription));
TraceHr (ttidError, FAL, hr, FALSE,
"AddAdapterToNt4Key: Setting Description in "
"legacy registry");
RegCloseKey (hkeyInstance);
}
}
else
{
hr = HrRegDeleteKey (hkeyAdapters, szInstanceNumber);
}
RegCloseKey (hkeyAdapters);
}
}
delete [] pszDriver;
}
}