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.
437 lines
17 KiB
437 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
net.c
|
|
|
|
Abstract:
|
|
|
|
Process NetCards section of WINBOM.INI
|
|
|
|
Author:
|
|
|
|
Donald McNamara (donaldm) 5/11/2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "factoryp.h"
|
|
|
|
// UpdateDriverForPlugAndPlayDevices constants
|
|
#include <newdev.h>
|
|
|
|
// NetBT registry refresh IOCTL
|
|
#include <nbtioctl.h>
|
|
|
|
// for run-time loading of newdev.dll
|
|
typedef BOOL (WINAPI *ExternalUpdateDriverForPlugAndPlayDevicesW)
|
|
(
|
|
HWND hwndParent,
|
|
LPCWSTR HardwareId,
|
|
LPCWSTR FullInfPath,
|
|
DWORD InstallFlags,
|
|
PBOOL bRebootRequired OPTIONAL
|
|
);
|
|
|
|
extern CONFIGRET CMP_WaitServicesAvailable(IN HMACHINE hMachine);
|
|
|
|
//
|
|
// function prototypes
|
|
//
|
|
BOOL
|
|
SetupRegistryForRemoteBoot(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
InstallNetworkCard(
|
|
LPTSTR lpszWinBOMPath,
|
|
BOOL bForceIDScan
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function installs all network card found in the system.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if there are no fatal errors.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HINSTANCE hInstNewDev;
|
|
ExternalUpdateDriverForPlugAndPlayDevicesW pUpdateDriverForPlugAndPlayDevicesW = NULL;
|
|
|
|
// We need the "UpdateDriverForPlugAndPlayDevices" function from newdev.dll.
|
|
//
|
|
if ( NULL == (hInstNewDev = LoadLibrary(L"newdev.dll")) )
|
|
{
|
|
FacLogFileStr(3 | LOG_ERR, L"Failed to load newdev.dll. Error = %d", GetLastError());
|
|
return bRet;
|
|
}
|
|
pUpdateDriverForPlugAndPlayDevicesW =
|
|
(ExternalUpdateDriverForPlugAndPlayDevicesW) GetProcAddress(hInstNewDev, "UpdateDriverForPlugAndPlayDevicesW");
|
|
if ( NULL == pUpdateDriverForPlugAndPlayDevicesW )
|
|
{
|
|
FacLogFileStr(3 | LOG_ERR, L"Failed to get UpdateDriverForPlugAndPlayDevicesW. Error = %d", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
BOOL bRebootFlag = FALSE;
|
|
|
|
// Need to ensure that pnp services are available.
|
|
//
|
|
CMP_WaitServicesAvailable(NULL);
|
|
|
|
//
|
|
// If remote boot then do the necessary registry processing
|
|
// so that upper level protocol drivers can bind & work
|
|
// correctly with already created device objects
|
|
//
|
|
if ( !IsRemoteBoot() ||
|
|
SetupRegistryForRemoteBoot() )
|
|
{
|
|
if ( !bForceIDScan )
|
|
{
|
|
LPTSTR lpszHardwareId;
|
|
|
|
// Now check to see if there are any PNP ids in the [NetCards] section of the winbom.
|
|
//
|
|
LPTSTR lpszNetCards = IniGetString(lpszWinBOMPath, WBOM_NETCARD_SECTION, NULL, NULLSTR);
|
|
|
|
// Check to make sure that we have a valid string
|
|
//
|
|
if ( lpszNetCards )
|
|
{
|
|
for ( lpszHardwareId = lpszNetCards; *lpszHardwareId; lpszHardwareId += (lstrlen(lpszHardwareId) + 1) )
|
|
{
|
|
// Get the INF name
|
|
//
|
|
LPTSTR lpszInfFileName = IniGetExpand(lpszWinBOMPath, WBOM_NETCARD_SECTION, lpszHardwareId, NULLSTR);
|
|
|
|
// At this point lpHardwareId is the PNP id for a network card that we want to install and
|
|
// lpszInfFileName is the name of the Inf to use to install this card.
|
|
//
|
|
if ( lpszInfFileName && *lpszInfFileName && *lpszHardwareId )
|
|
{
|
|
if ( pUpdateDriverForPlugAndPlayDevicesW(NULL,
|
|
lpszHardwareId,
|
|
lpszInfFileName,
|
|
INSTALLFLAG_READONLY,
|
|
&bRebootFlag) )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
FacLogFileStr(3 | LOG_ERR, L"Failed to install network driver listed in the NetCards section. Hardware ID: %s, InfName: %s, Error = %d.", lpszHardwareId, lpszInfFileName, GetLastError());
|
|
|
|
//
|
|
// Not setting bRet to FALSE here since it is FALSE by default, and
|
|
// if we succesfully install at least one network card we want to return TRUE.
|
|
//
|
|
}
|
|
}
|
|
FREE(lpszInfFileName);
|
|
}
|
|
}
|
|
FREE(lpszNetCards);
|
|
}
|
|
else // if ( bForceIDScan )
|
|
{
|
|
HDEVINFO DeviceInfoSet = NULL;
|
|
|
|
// Get the list of all present devices.
|
|
//
|
|
DeviceInfoSet = SetupDiGetClassDevs(NULL,
|
|
NULL,
|
|
NULL,
|
|
DIGCF_ALLCLASSES);
|
|
|
|
if ( INVALID_HANDLE_VALUE == DeviceInfoSet )
|
|
{
|
|
FacLogFileStr(3 | LOG_ERR, L"Failed SetupDiGetClassDevsEx(). Error = %d", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
DWORD dwDevice;
|
|
SP_DEVINFO_DATA DeviceInfoData;
|
|
|
|
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
|
|
|
|
// Loop through all the devices.
|
|
//
|
|
for ( dwDevice = 0; SetupDiEnumDeviceInfo(DeviceInfoSet, dwDevice, &DeviceInfoData); dwDevice++ )
|
|
{
|
|
SP_DEVINSTALL_PARAMS DeviceInstallParams = {0};
|
|
SP_DRVINFO_DATA DriverInfoData = {0};
|
|
ULONG ulStatus = 0,
|
|
ulProblemNumber = 0;
|
|
|
|
DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
|
|
DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
|
|
|
|
// If we can get the dev node status and the devnode does have a problem, then
|
|
// build a list of possible drivers for this device and select the best one.
|
|
// Otherwise just skip this this device.
|
|
//
|
|
if ( ( CR_SUCCESS == CM_Get_DevNode_Status(&ulStatus, &ulProblemNumber, DeviceInfoData.DevInst, 0) ) &&
|
|
( ( IsRemoteBoot() &&
|
|
IsEqualGUID(&DeviceInfoData.ClassGuid, (LPGUID)&GUID_DEVCLASS_NET) ) ||
|
|
( ulStatus & (DN_HAS_PROBLEM | DN_PRIVATE_PROBLEM) ) ) &&
|
|
SetupDiBuildDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER) )
|
|
{
|
|
if ( ( SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV, DeviceInfoSet, &DeviceInfoData) ) &&
|
|
( SetupDiGetSelectedDriver(DeviceInfoSet, &DeviceInfoData, &DriverInfoData) ) )
|
|
{
|
|
//
|
|
// DriverInfoData contains details about the best driver, we can now see if this is a NET driver
|
|
// as at this point the class will have been modified to NET if best driver is a NET driver.
|
|
// Compare DeviceInfoData.ClassGuid against NET class GUID. If no match, skip.
|
|
// Otherwise get DRVINFO_DETAIL_DATA into a resizable buffer to get HardwareID.
|
|
// Use The HardwareID and InfFileName entries in DRVINFO_DETAIL_DATA
|
|
// to pass into UpdateDriverForPlugAndPlayDevices.
|
|
// DO NOT pass FORCE flag into UpdateDriverForPlugAndPlayDevices.
|
|
//
|
|
if ( IsEqualGUID(&DeviceInfoData.ClassGuid, (LPGUID)&GUID_DEVCLASS_NET) )
|
|
{
|
|
DWORD cbBytesNeeded = 0;
|
|
PSP_DRVINFO_DETAIL_DATA pDriverInfoDetailData = NULL;
|
|
|
|
if ( ( ( SetupDiGetDriverInfoDetail(DeviceInfoSet,
|
|
&DeviceInfoData,
|
|
&DriverInfoData,
|
|
NULL,
|
|
0,
|
|
&cbBytesNeeded) ) ||
|
|
( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) ) &&
|
|
|
|
( cbBytesNeeded ) &&
|
|
|
|
( pDriverInfoDetailData = MALLOC( cbBytesNeeded) ) &&
|
|
|
|
( 0 != (pDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA)) ) &&
|
|
|
|
( SetupDiGetDriverInfoDetail(DeviceInfoSet,
|
|
&DeviceInfoData,
|
|
&DriverInfoData,
|
|
pDriverInfoDetailData,
|
|
cbBytesNeeded,
|
|
NULL) ) )
|
|
{
|
|
if ( pUpdateDriverForPlugAndPlayDevicesW(NULL,
|
|
pDriverInfoDetailData->HardwareID,
|
|
pDriverInfoDetailData->InfFileName,
|
|
INSTALLFLAG_READONLY,
|
|
&bRebootFlag) )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
FacLogFileStr(3 | LOG_ERR, L"Failed to install network driver. Error = %d", GetLastError());
|
|
|
|
//
|
|
// Not setting bRet to FALSE here since it is FALSE by default, and
|
|
// if we succesfully install at least one network card we want to return TRUE.
|
|
//
|
|
}
|
|
}
|
|
// Free this if allocated. Macro checks for NULL.
|
|
//
|
|
FREE ( pDriverInfoDetailData );
|
|
}
|
|
}
|
|
SetupDiDestroyDriverInfoList(DeviceInfoSet, &DeviceInfoData, SPDIT_COMPATDRIVER);
|
|
}
|
|
}
|
|
// Make sure we clean up the list.
|
|
//
|
|
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FreeLibrary(hInstNewDev);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL SetupNetwork(LPSTATEDATA lpStateData)
|
|
{
|
|
LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath;
|
|
BOOL bRet = TRUE;
|
|
TCHAR szScratch[MAX_PATH] = NULLSTR;
|
|
|
|
if ( GetPrivateProfileString(WBOM_FACTORY_SECTION, WBOM_FACTORY_FORCEIDSCAN, NULLSTR, szScratch, AS(szScratch), lpszWinBOMPath) )
|
|
{
|
|
if ( LSTRCMPI(szScratch, _T("NO")) == 0 )
|
|
FacLogFile(1, IDS_LOG_NONET);
|
|
else
|
|
{
|
|
// Attempt to install the Net card using the [NetCards] section of the WINBOM
|
|
//
|
|
if ( !InstallNetworkCard(lpszWinBOMPath, FALSE) )
|
|
{
|
|
FacLogFile(1, IDS_LOG_FORCEDNETSCAN);
|
|
|
|
// Attempt a forced scan of all network capable devices
|
|
//
|
|
if ( !InstallNetworkCard(lpszWinBOMPath, TRUE) )
|
|
{
|
|
FacLogFile(0 | LOG_ERR, IDS_ERR_FAILEDNETDRIVER);
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//
|
|
// constant strings for remote boot
|
|
//
|
|
#define NETCFG_INSTANCEID_VALUE_NAME TEXT("NetCfgInstanceId")
|
|
#define NETBOOTCARD_ROOT_DEVICE_GUID TEXT("{54C7D140-09EF-11D1-B25A-F5FE627ED95E}")
|
|
#define NETBT_TCPIP_DEVICE_PATH TEXT("\\Device\\NetBt_Tcpip_") NETBOOTCARD_ROOT_DEVICE_GUID
|
|
#define NET_CLASS_DEVICE_INSTANCE_PATH TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\0000")
|
|
|
|
NTSTATUS
|
|
ForceNetbtRegistryRead(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine description:
|
|
|
|
Issue IOCTL to NETBT to re-read its registry setting.
|
|
|
|
Arguements :
|
|
|
|
|
|
Return Value :
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
UNICODE_STRING nameString;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
HANDLE hNetbtDevice = NULL;
|
|
|
|
//
|
|
// Step I:
|
|
//
|
|
// Open NETBT driver
|
|
//
|
|
RtlInitUnicodeString( &nameString,
|
|
NETBT_TCPIP_DEVICE_PATH );
|
|
|
|
InitializeObjectAttributes( &objectAttributes,
|
|
&nameString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
|
|
status = NtCreateFile( &hNetbtDevice,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&objectAttributes,
|
|
&ioStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
0,
|
|
NULL,
|
|
0 );
|
|
|
|
if ( NT_SUCCESS(status) )
|
|
{
|
|
//
|
|
// Issue IOCTL to purge the cache...
|
|
//
|
|
status = NtDeviceIoControlFile( hNetbtDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
IOCTL_NETBT_REREAD_REGISTRY,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0 );
|
|
//
|
|
// Close NETBT driver
|
|
//
|
|
NtClose( hNetbtDevice );
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
BOOL
|
|
SetupRegistryForRemoteBoot(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Munges the registry and sets up the required entries for
|
|
upper layer protocol drivers to see that a valid NIC is
|
|
installed.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return value:
|
|
|
|
TRUE if successful, otherwise FALSE.
|
|
|
|
--*/
|
|
{
|
|
BOOL Result = FALSE;
|
|
HKEY InstanceKey;
|
|
|
|
// Open the remote boot network card instance
|
|
//
|
|
if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
NET_CLASS_DEVICE_INSTANCE_PATH,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&InstanceKey) )
|
|
{
|
|
// Set the hard-coded instance id
|
|
//
|
|
if ( ERROR_SUCCESS == RegSetValueEx( InstanceKey,
|
|
NETCFG_INSTANCEID_VALUE_NAME,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)NETBOOTCARD_ROOT_DEVICE_GUID,
|
|
(lstrlen(NETBOOTCARD_ROOT_DEVICE_GUID) + 1) * sizeof(TCHAR)) )
|
|
{
|
|
// Set the return value to TRUE...
|
|
//
|
|
Result = TRUE;
|
|
}
|
|
|
|
// Close the key...
|
|
//
|
|
RegCloseKey( InstanceKey );
|
|
}
|
|
|
|
return Result;
|
|
}
|