//+--------------------------------------------------------------------------- // // 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; }