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

939 lines
26 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992-2001.
//
// File: A D A P T E R . C P P
//
// Contents: Physical adapter class definition.
//
// Notes:
//
// Author: Alok Sinha
//
//----------------------------------------------------------------------------
#include "adapter.h"
#include "common.h"
#ifdef CUSTOM_EVENTS
#include "public.h"
#endif
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::CMuxPhysicalAdapter
//
// Purpose: Constructor for class CMuxPhysicalAdapter
//
// Arguments: None
//
// Returns:
//
// Notes:
//
CMuxPhysicalAdapter::CMuxPhysicalAdapter (INetCfg *pnc,
GUID *pguidAdapter)
{
TraceMsg( L"-->CMuxPhysicalAdapter::CMuxPhysicalAdapter(Constructor).\n" );
m_pnc = pnc;
m_pnc->AddRef();
CopyMemory( &m_guidAdapter,
pguidAdapter,
sizeof(GUID) );
TraceMsg( L"<--CMuxPhysicalAdapter::CMuxPhysicalAdapter(Constructor).\n" );
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::~CMuxPhysicalAdapter
//
// Purpose: Destructor for class CMuxPhysicalAdapter
//
// Arguments: None
//
// Returns:
//
// Notes:
//
CMuxPhysicalAdapter::~CMuxPhysicalAdapter (VOID)
{
CMuxVirtualMiniport *pMiniport;
DWORD dwMiniportCount;
DWORD i;
TraceMsg( L"-->CMuxPhysicalAdapter::~CMuxPhysicalAdapter(Destructor).\n" );
//
// Delete all the instances representing the virtual miniports.
// We are only deleting the class instances, not uninstalling the
// the virtual miniports.
//
dwMiniportCount = m_MiniportList.ListCount();
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportList.Remove( &pMiniport );
delete pMiniport;
}
dwMiniportCount = m_MiniportsToAdd.ListCount();
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToAdd.Remove( &pMiniport );
delete pMiniport;
}
dwMiniportCount = m_MiniportsToRemove.ListCount();
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToRemove.Remove( &pMiniport );
delete pMiniport;
}
ReleaseObj( m_pnc );
TraceMsg( L"<--CMuxPhysicalAdapter::~CMuxPhysicalAdapter(Destructor).\n" );
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::LoadConfiguration
//
// Purpose: Read the registry to get the device IDs of the
// virtual miniports installed on the adapter and
// crate an instance to represent each virtual miniport.
//
// Arguments: None
//
// Returns: S_OK on success, otherwise an error code.
//
// Notes:
//
HRESULT CMuxPhysicalAdapter::LoadConfiguration (VOID)
{
HKEY hkeyAdapterGuid;
WCHAR szAdapterGuidKey[MAX_PATH+1];
WCHAR szAdapterGuid[MAX_PATH+1];
LPWSTR lpMiniportList;
LPWSTR lpMiniport;
LPWSTR lpMiniportGuid;
DWORD dwDisp;
CMuxVirtualMiniport *pMiniport;
GUID guidMiniport;
DWORD dwBytes;
LONG lResult;
TraceMsg( L"-->CMuxPhysicalAdapter::LoadConfiguration.\n" );
//
// Build the registry key using the adapter guid under which
// device IDs of the virtual miniports are stored.
//
StringFromGUID2( m_guidAdapter,
szAdapterGuid,
MAX_PATH+1 );
swprintf( szAdapterGuidKey,
L"%s\\%s",
c_szAdapterList,
szAdapterGuid );
lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
szAdapterGuidKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyAdapterGuid,
&dwDisp);
if ( lResult == ERROR_SUCCESS ) {
//
// If dwDisp indicates that a new key is created then, we know there
// is no virtual miniport currently listed underneath and we simply
// return.
//
if ( dwDisp != REG_CREATED_NEW_KEY ) {
dwBytes = 0;
lResult = RegQueryValueExW(
hkeyAdapterGuid,
c_szUpperBindings,
NULL,
NULL,
NULL,
&dwBytes );
lpMiniportList = (LPWSTR)calloc( dwBytes, 1 );
if ( lpMiniportList ) {
lResult = RegQueryValueExW(
hkeyAdapterGuid,
c_szUpperBindings,
NULL,
NULL,
(LPBYTE)lpMiniportList,
&dwBytes );
if ( lResult == ERROR_SUCCESS ) {
lpMiniport = lpMiniportList;
#ifndef PASSTHRU_NOTIFY
//
// In case of mux, c_szUpperBindings is a multi_sz string.
//
while ( wcslen(lpMiniport) ) {
lpMiniportGuid = RemoveDevicePrefix( lpMiniport );
TraceMsg( L" Loading configuration for miniport %s...\n",
lpMiniportGuid );
if ( lpMiniportGuid ) {
CLSIDFromString( lpMiniportGuid,
&guidMiniport );
//
// Create an instance representing the virtual miniport.
//
pMiniport = new CMuxVirtualMiniport( m_pnc,
&guidMiniport,
&m_guidAdapter );
if ( pMiniport ) {
//
// Load any miniport specific configuration.
//
pMiniport->LoadConfiguration();
//
// Save the miniport instance in a list.
//
m_MiniportList.Insert( pMiniport,
guidMiniport );
}
free( lpMiniportGuid );
}
//
// Get next miniport guid.
//
lpMiniport += wcslen(lpMiniport) + 1;
}
#else
//
// In case of the passthru driver, c_szUpperBindings is
// a reg_sz string.
//
lpMiniportGuid = RemoveDevicePrefix( lpMiniport );
TraceMsg( L" Loading configuration for miniport %s...\n",
lpMiniportGuid );
if ( lpMiniportGuid ) {
CLSIDFromString( lpMiniportGuid,
&guidMiniport );
//
// Create an instance representing the virtual miniport.
//
pMiniport = new CMuxVirtualMiniport( m_pnc,
&guidMiniport,
&m_guidAdapter );
if ( pMiniport ) {
//
// Load any miniport specific configuration.
//
pMiniport->LoadConfiguration();
//
// Save the miniport instance in a list.
//
m_MiniportList.Insert( pMiniport,
guidMiniport );
}
free( lpMiniportGuid );
}
#endif
}
else {
TraceMsg( L" Failed to read the registry value: %s.\n",
c_szUpperBindings );
}
free( lpMiniportList );
}
else {
lResult = ERROR_NOT_ENOUGH_MEMORY;
}
}
RegCloseKey( hkeyAdapterGuid );
}
else {
TraceMsg( L" Failed to open the registry key: %s.\n",
szAdapterGuidKey );
}
TraceMsg( L"<--CMuxPhysicalAdapter::LoadConfiguration(HRESULT = %x).\n",
HRESULT_FROM_WIN32(lResult) );
return HRESULT_FROM_WIN32(lResult);
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::GetAdapterGUID
//
// Purpose: Returns the adapter GUID.
//
// Arguments:
// OUT pguidAdapter: GUID of the adapter returned.
//
// Returns: None.
//
// Notes:
//
VOID CMuxPhysicalAdapter::GetAdapterGUID (GUID *pguidAdapter)
{
TraceMsg( L"-->CMuxPhysicalAdapter::GetAdapterGUID.\n" );
CopyMemory( pguidAdapter,
&m_guidAdapter,
sizeof(GUID) );
TraceMsg( L"<--CMuxPhysicalAdapter::GetAdapterGUID.\n" );
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::AddMiniport
//
// Purpose: Puts the miniport instance into the list of newly added miniports.
//
// Arguments:
// IN pMiniport: A newly create miniport instance.
//
// Returns: S_OK on success, otherwize and error code.
//
// Notes:
//
HRESULT CMuxPhysicalAdapter::AddMiniport (CMuxVirtualMiniport *pMiniport)
{
GUID guidMiniport;
HRESULT hr;
TraceMsg( L"-->CMuxPhysicalAdapter::AddMiniport.\n" );
pMiniport->GetMiniportGUID( &guidMiniport );
hr = m_MiniportsToAdd.Insert( pMiniport,
guidMiniport );
TraceMsg( L"<--CMuxPhysicalAdapter::AddMiniport(HRESULT = %x).\n",
hr );
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::RemoveMiniport
//
// Purpose: Remove a specified miniport instance from the list and
// uninstalls the corresponding virtual miniport.
//
// Arguments:
// IN pguidMiniportToRemove: GUID of the miniport to be removed
// and uninstalled. If it is NULL then,
// the first miniport instance is removed.
//
// Returns: S_OK on success, otherwize and error code.
//
// Notes:
//
HRESULT CMuxPhysicalAdapter::RemoveMiniport (GUID *pguidMiniportToRemove)
{
CMuxVirtualMiniport *pMiniport;
GUID guidMiniport;
HRESULT hr;
TraceMsg( L"-->CMuxPhysicalAdapter::RemoveMiniport.\n" );
//
// If miniport GUID specified then, delete that one.
//
if ( pguidMiniportToRemove ) {
hr = m_MiniportList.RemoveByKey( *pguidMiniportToRemove,
&pMiniport );
}
else {
//
// No GUID specified, so we just delete the first one.
//
hr = m_MiniportList.Remove( &pMiniport );
}
if ( hr == S_OK ) {
pMiniport->GetMiniportGUID( &guidMiniport );
m_MiniportsToRemove.Insert( pMiniport,
guidMiniport );
pMiniport->DeInstall();
}
TraceMsg( L"<--CMuxPhysicalAdapter::RemoveMiniport(HRESULT = %x).\n",
hr );
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::Remove
//
// Purpose: Uninstall all the instances of virtual miniports.
//
// Arguments: None
//
// Returns: S_OK.
//
// Notes:
//
HRESULT CMuxPhysicalAdapter::Remove (VOID)
{
CMuxVirtualMiniport *pMiniport;
GUID guidMiniport;
DWORD dwMiniportCount;
DWORD i;
TraceMsg( L"-->CMuxPhysicalAdapter::Remove.\n" );
dwMiniportCount = m_MiniportList.ListCount();
TraceMsg ( L" Removing %d miniports.\n",
dwMiniportCount );
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportList.Remove( &pMiniport );
pMiniport->GetMiniportGUID( &guidMiniport );
m_MiniportsToRemove.Insert( pMiniport,
guidMiniport );
pMiniport->DeInstall();
}
TraceMsg( L"<--CMuxPhysicalAdapter::Remove(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::ApplyRegistryChanges
//
// Purpose: Update the registry depending on the actions performed.
//
// Arguments:
// IN eApplyAction: Action that was last performed.
//
//
// Returns: S_OK.
//
// Notes:
// More than one action could have been performed by the user
// but this function is called only once at the end. So, the argument
// only denotes the very last action performed. For example, if the
// user deletes one miniport and adds two miniports then, the argument
// will denote an add action.
//
HRESULT CMuxPhysicalAdapter::ApplyRegistryChanges (ConfigAction eApplyAction)
{
HKEY hkeyAdapterList;
HKEY hkeyAdapterGuid;
WCHAR szAdapterGuid[MAX_PATH+1];
CMuxVirtualMiniport *pMiniport = NULL;
DWORD dwMiniportCount;
DWORD dwDisp;
DWORD i;
LONG lResult;
HRESULT hr;
TraceMsg( L"-->CMuxPhysicalAdapter::ApplyRegistryChanges.\n" );
//
// Open/create and then close the registry key to ensure that it does exist.
//
StringFromGUID2( m_guidAdapter,
szAdapterGuid,
MAX_PATH+1 );
lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
c_szAdapterList,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyAdapterList,
&dwDisp);
if ( lResult == ERROR_SUCCESS ) {
lResult = RegCreateKeyExW( hkeyAdapterList,
szAdapterGuid,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyAdapterGuid,
&dwDisp);
if ( lResult == ERROR_SUCCESS ) {
RegCloseKey( hkeyAdapterGuid );
}
else {
TraceMsg( L" Failed to create/open the registry key: %s\\%s.\n",
c_szAdapterList, szAdapterGuid );
}
RegCloseKey( hkeyAdapterList );
}
else {
TraceMsg( L" Failed to open the registry key: %s.\n",
c_szAdapterList );
}
//
// Update the registry in case there were new miniports installed.
//
hr = HRESULT_FROM_WIN32( lResult );
dwMiniportCount = m_MiniportsToAdd.ListCount();
TraceMsg( L" Applying registry changes when %d miniports added.\n",
dwMiniportCount );
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToAdd.Find( i,
&pMiniport );
//
// Do virtual miniport specific registry changes.
//
// We need to tell the miniport instance explicitly what the action
// is.
//
hr = pMiniport->ApplyRegistryChanges( eActAdd );
if ( hr != S_OK ) {
TraceMsg( L" Failed to apply registry changes to miniport(%d).\n",
i );
}
}
//
// Update the registry in case one or more miniports were uninstalled.
//
dwMiniportCount = m_MiniportsToRemove.ListCount();
TraceMsg( L" Applying registry changes when %d miniports removed.\n",
dwMiniportCount );
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToRemove.Find( i,
&pMiniport );
//
// Do virtual miniport specific registry changes.
//
// We need to tell the miniport instance explicitly what the action
// is.
//
hr = pMiniport->ApplyRegistryChanges( eActRemove );
if ( hr != S_OK ) {
TraceMsg( L" Failed to apply registry changes to miniport(%d).\n",
i );
}
}
//
// If the adapter is being removed or the protocol is being uninstalled,
// delete the adatper registry key.
//
if ( eApplyAction == eActRemove ) {
//
// Delete the adapter key.
//
lResult = RegCreateKeyExW( HKEY_LOCAL_MACHINE,
c_szAdapterList,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hkeyAdapterList,
&dwDisp);
if ( lResult == ERROR_SUCCESS ) {
TraceMsg( L" Deleting the registry key: %s.\n", szAdapterGuid );
RegDeleteKeyW( hkeyAdapterList,
szAdapterGuid );
}
}
TraceMsg( L"<--CMuxPhysicalAdapter::ApplyRegistryChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::ApplyPnpChanges
//
// Purpose: Apply the PnP changes depending on the actions performed.
//
// Arguments:
// IN pfCallback : SendPnpConfig Callback interface.
// IN eApplyAction: Action that was last performed.
//
//
// Returns: S_OK.
//
// Notes:
// More than one action could have been performed by the user
// but this function is called only once at the end. So, the argument
// only denotes the very last action performed. For example, if the
// user deletes one miniport and adds two miniports then, the argument
// will denote an add action.
//
HRESULT CMuxPhysicalAdapter::ApplyPnpChanges(
INetCfgPnpReconfigCallback *pfCallback,
ConfigAction eApplyAction)
{
CMuxVirtualMiniport *pMiniport;
GUID guidMiniport;
WCHAR szMiniportGuid[MAX_PATH+1];
LPWSTR lpDevice;
DWORD dwMiniportCount;
DWORD i;
DWORD dwBytes;
INetCfgComponent *pncc;
HRESULT hr;
#ifdef CUSTOM_EVENTS
LPWSTR lpszBindName;
PNOTIFY_CUSTOM_EVENT lppnpEvent;
#endif
TraceMsg( L"-->CMuxPhysicalAdapter::ApplyPnpChanges.\n" );
#ifdef CUSTOM_EVENTS
//
// Find the instance of the adapter to get its bindname.
//
hr = HrFindInstance( m_pnc,
m_guidAdapter,
&pncc );
if ( hr == S_OK ) {
hr = pncc->GetBindName( &lpszBindName );
if ( hr != S_OK ) {
TraceMsg( L" GetBindName failed.(HRESULT = %x). PnP changes will not "
L"be applied and the driver will not be notified.\n",
hr );
}
ReleaseObj( pncc );
}
else {
TraceMsg( L" PnP changes will not "
L"be applied and the driver will not be notified.\n",
hr );
}
#endif
dwMiniportCount = m_MiniportsToAdd.ListCount();
TraceMsg( L" Applying PnP changes to %d new miniports.\n",
dwMiniportCount );
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToAdd.Remove( &pMiniport );
pMiniport->GetMiniportGUID( &guidMiniport );
m_MiniportList.Insert( pMiniport,
guidMiniport );
//
// Do miniport specific Pnp Changes when they are added.
//
hr = pMiniport->ApplyPnpChanges( pfCallback,
eActAdd );
#ifdef CUSTOM_EVENTS
//
// Notify the driver that one or more virtual miniports have been added.
//
StringFromGUID2( guidMiniport,
szMiniportGuid,
MAX_PATH+1 );
lpDevice = AddDevicePrefix( szMiniportGuid );
if ( lpDevice ) {
dwBytes = sizeof(NOTIFY_CUSTOM_EVENT) +
((wcslen(lpDevice) + 1) * sizeof(WCHAR));
lppnpEvent = (PNOTIFY_CUSTOM_EVENT)malloc( dwBytes );
if ( lppnpEvent ) {
lppnpEvent->uSignature = NOTIFY_SIGNATURE;
lppnpEvent->uEvent = MUX_CUSTOM_EVENT;
wcscpy( lppnpEvent->szMiniport,
lpDevice );
hr = pfCallback->SendPnpReconfig( NCRL_NDIS,
c_szMuxService,
lpszBindName,
(PVOID)lppnpEvent,
dwBytes );
TraceMsg( L" INetCfgPnpReconfigCallback->SendPnpReconfig returned "
L"%#x.\n",
hr );
if ( hr != S_OK ) {
TraceMsg( L" Failed to apply Pnp changes, miniport(%d).\n",
i );
}
free( lppnpEvent );
}
free( lpDevice );
}
#endif
}
dwMiniportCount = m_MiniportsToRemove.ListCount();
TraceMsg( L" Applying PnP changes to %d removed miniports.\n",
dwMiniportCount );
for (i=0; i < dwMiniportCount; ++i) {
m_MiniportsToRemove.Remove( &pMiniport );
pMiniport->GetMiniportGUID( &guidMiniport );
//
// Do miniport specific Pnp Changes when they are uninstalled.
//
hr = pMiniport->ApplyPnpChanges( pfCallback,
eActRemove );
delete pMiniport;
#ifdef CUSTOM_EVENTS
//
// Notify the driver that one or more virtual miniports have been
// uninstalled.
//
// We can't notify the driver in case the adapter or the protocol is
// being uninstalled because the binding handle doesn't exist.
//
if ( eApplyAction != eActRemove ) {
StringFromGUID2( guidMiniport,
szMiniportGuid,
MAX_PATH+1 );
lpDevice = AddDevicePrefix( szMiniportGuid );
if ( lpDevice ) {
dwBytes = sizeof(NOTIFY_CUSTOM_EVENT) +
((wcslen(lpDevice) + 1) * sizeof(WCHAR));
lppnpEvent = (PNOTIFY_CUSTOM_EVENT)malloc( dwBytes );
if ( lppnpEvent ) {
lppnpEvent->uSignature = NOTIFY_SIGNATURE;
lppnpEvent->uEvent = MUX_CUSTOM_EVENT;
wcscpy( lppnpEvent->szMiniport,
lpDevice );
hr = pfCallback->SendPnpReconfig( NCRL_NDIS,
c_szMuxService,
lpszBindName,
(PVOID)lppnpEvent,
dwBytes );
TraceMsg( L" INetCfgPnpReconfigCallback->SendPnpReconfig returned "
L"%#x.\n",
hr );
if ( hr != S_OK ) {
TraceMsg( L" Failed to apply Pnp changes, miniport(%d).\n",
i );
}
free( lppnpEvent );
}
free( lpDevice );
}
}
#endif
}
#ifdef CUSTOM_EVENTS
CoTaskMemFree( lpszBindName );
#endif
TraceMsg( L"<--CMuxPhysicalAdapter::ApplyPnpChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::CancelChanges
//
// Purpose: Cancel any changes made.
//
// Arguments: None
//
//
// Returns: S_OK.
//
// Notes:
//
HRESULT CMuxPhysicalAdapter::CancelChanges (VOID)
{
TraceMsg( L"-->CMuxPhysicalAdapter::CancelChanges.\n" );
TraceMsg( L"<--CMuxPhysicalAdapter::CancelChanges(HRESULT = %x).\n",
S_OK );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CMuxPhysicalAdapter::AllMiniportsRemoved
//
// Purpose: Find out if there is no miniport installed on the adapter.
//
// Arguments: None
//
//
// Returns: TRUE if all the miniports associated with this adapter have been
// uninstalled and there is none pending to be added, otherwise FALSE.
//
// Notes:
//
BOOL CMuxPhysicalAdapter::AllMiniportsRemoved (VOID)
{
return (m_MiniportList.ListCount() + m_MiniportsToAdd.ListCount()) == 0;
}