|
|
// ATlkObj.cpp : Implementation of CATlkObj
#include "pch.h"
#pragma hdrstop
#include <atalkwsh.h>
#include "atlkobj.h"
#include "ncatlui.h"
#include "ncmisc.h"
#include "ncreg.h"
#include "ncpnp.h"
#include "ncsvc.h"
#include <netconp.h>
extern const WCHAR c_szAdapterSections[]; //extern const WCHAR c_szAdapters[];
extern const WCHAR c_szBackslash[]; extern const WCHAR c_szDevice[]; extern const WCHAR c_szSpecificTo[]; extern const WCHAR c_szInfId_MS_NdisWanAtalk[]; extern const WCHAR c_szEmpty[];
// Registry Paths
static const WCHAR c_szAtlk[] = L"AppleTalk"; static const WCHAR c_szATLKParameters[] = L"System\\CurrentControlSet\\Services\\AppleTalk\\Parameters"; static const WCHAR c_szATLKAdapters[] = L"System\\CurrentControlSet\\Services\\AppleTalk\\Parameters\\Adapters";
// Values under the Adapter component's "Parameters" key
static const WCHAR c_szMediaType[] = L"MediaType"; //$ REVIEW duplicate string
// Values under AppleTalk\Parameters
static const WCHAR c_szDefaultPort[] = L"DefaultPort"; // REG_SZ
static const WCHAR c_szDesiredZone[] = L"DesiredZone"; // REG_SZ
static const WCHAR c_szEnableRouter[] = L"EnableRouter"; // REG_DWORD
// Values under AppleTalk\Parameters\Adapters\<AdapterId>
static const WCHAR c_szAarpRetries[] = L"AarpRetries"; // REG_DWORD
static const WCHAR c_szDdpCheckSums[] = L"DdpCheckSums"; // REG_DWORD
static const WCHAR c_szDefaultZone[] = L"DefaultZone"; // REG_SZ
static const WCHAR c_szNetworkRangeLowerEnd[] = L"NetworkRangeLowerEnd";// REG_DWORD
static const WCHAR c_szNetworkRangeUpperEnd[] = L"NetworkRangeUpperEnd";// REG_DWORD
static const WCHAR c_szPortName[] = L"PortName"; // REG_SZ
static const WCHAR c_szRouterPramNode[] = L"RouterPramNode"; // REG_DWORD
static const WCHAR c_szSeedingNetwork[] = L"SeedingNetwork"; // REG_DWORD
static const WCHAR c_szUserPramNode1[] = L"UserPramNode1"; // REG_DWORD
static const WCHAR c_szUserPramNode2[] = L"UserPramNode2"; // REG_DWORD
static const WCHAR c_szZoneList[] = L"ZoneList"; // REG_MULTI_SZ
// Useful default constant
const WCHAR c_chAt = L'@'; static const WCHAR c_dwZero = 0L; static const WCHAR c_dwTen = 10L; //static const WCHAR c_szMacPrint[] = L"MacPrint";
// Declare structure for reading/writing AppleTalk\Parameters values
static const REGBATCH regbatchATLKParams[] = { {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szDefaultPort, REG_SZ, offsetof(ATLK_PARAMS,szDefaultPort), (BYTE *)&c_szEmpty}, {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szDesiredZone, REG_SZ, offsetof(ATLK_PARAMS,szDesiredZone), (BYTE *)&c_szEmpty}, {HKEY_LOCAL_MACHINE, c_szATLKParameters, c_szEnableRouter, REG_DWORD, offsetof(ATLK_PARAMS,dwEnableRouter), (BYTE *)&c_szEmpty}};
static const REGBATCH regbatchATLKAdapters[] = { {HKEY_LOCAL_MACHINE, c_szEmpty, c_szAarpRetries, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwAarpRetries), (BYTE *)&c_dwTen}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szDdpCheckSums, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwDdpCheckSums), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szNetworkRangeLowerEnd, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwNetworkRangeLowerEnd), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szNetworkRangeUpperEnd, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwNetworkRangeUpperEnd), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szRouterPramNode, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwRouterPramNode), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szSeedingNetwork, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwSeedingNetwork), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szUserPramNode1, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwUserPramNode1), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szUserPramNode2, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwUserPramNode2), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szMediaType, REG_DWORD, offsetof(ATLK_ADAPTER,m_dwMediaType), (BYTE *)&c_dwZero}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szDefaultZone, REG_SZ, offsetof(ATLK_ADAPTER,m_szDefaultZone), (BYTE *)&c_szEmpty}, {HKEY_LOCAL_MACHINE, c_szEmpty, c_szPortName, REG_SZ, offsetof(ATLK_ADAPTER,m_szPortName), (BYTE *)&c_szEmpty}};
// Local utility functions
HRESULT HrQueryAdapterComponentInfo(INetCfgComponent *pncc, CAdapterInfo * pAI);
HRESULT HrPortNameFromAdapter(INetCfgComponent *pncc, tstring * pstr);
// Prototype from nwlnkcfg\nwlnkutl.h
HRESULT HrAnswerFileAdapterToPNCC(INetCfg *pnc, PCWSTR pszAdapterId, INetCfgComponent** ppncc);
//
// Function: CATlkObj::CATlkObj
//
// Purpose: ctor for the CATlkObj class
//
// Parameters: none
//
// Returns: none
//
CATlkObj::CATlkObj() : m_pNetCfg(NULL), m_pNCC(NULL), m_eInstallAction(eActUnknown), m_pspObj(NULL), m_pATLKEnv(NULL), m_pATLKEnv_PP(NULL), m_pUnkPropContext(NULL), m_nIdxAdapterSelected(CB_ERR), m_fAdapterListChanged(FALSE), m_fPropertyChange(FALSE), m_fFirstTimeInstall(FALSE) { }
//
// Function: CATlkObj::CATlkObj
//
// Purpose: dtor for the CATlkObj class
//
// Parameters: none
//
// Returns: none
//
CATlkObj::~CATlkObj() { // Should always be cleaned up in advance of reach this dtor
Assert(NULL == m_pATLKEnv_PP);
ReleaseObj(m_pUnkPropContext); ReleaseObj(m_pNetCfg); ReleaseObj(m_pNCC); CleanupPropPages(); delete m_pATLKEnv; }
// INetCfgNotify
STDMETHODIMP CATlkObj::Initialize ( INetCfgComponent* pnccItem, INetCfg* pNetCfg, BOOL fInstalling ) { Validate_INetCfgNotify_Initialize(pnccItem, pNetCfg, fInstalling);
ReleaseObj(m_pNCC); m_pNCC = pnccItem; AddRefObj(m_pNCC); ReleaseObj(m_pNetCfg); m_pNetCfg = pNetCfg; AddRefObj(m_pNetCfg); m_fFirstTimeInstall = fInstalling;
// Read the current configuration
HRESULT hr = CATLKEnv::HrCreate(&m_pATLKEnv, this);
TraceError("CATlkObj::Initialize",hr); return hr; }
STDMETHODIMP CATlkObj::ReadAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection ) { Validate_INetCfgNotify_ReadAnswerFile(pszAnswerFile, pszAnswerSection );
HRESULT hr = S_OK;
m_eInstallAction = eActInstall;
// Only process answer file and install sub-components if the answer file
// is present. If the answer file is not present we should already be installed.
if (NULL != pszAnswerFile) { hr = HrProcessAnswerFile(pszAnswerFile, pszAnswerSection); }
TraceError("CATlkObj::ReadAnswerFile",hr); return hr; }
//
// Function: CATlkObj::HrProcessAnswerFile
//
// Purpose: Process the answer file information, merging
// its contents into the internal information
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATlkObj::HrProcessAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection) { TraceFileFunc(ttidDefault);
CSetupInfFile csif; BOOL fValue; HRESULT hr = S_OK; INFCONTEXT infctx; tstring str;
AssertSz(pszAnswerFile, "Answer file string is NULL!"); AssertSz(pszAnswerSection, "Answer file sections string is NULL!");
// Open the answer file.
hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (FAILED(hr)) { goto Error; }
// Read the property containing the list of adapter sections
hr = ::HrSetupFindFirstLine(csif.Hinf(), pszAnswerSection, c_szAdapterSections, &infctx); if (S_OK == hr) { DWORD dwIdx; DWORD dwCnt = SetupGetFieldCount(&infctx);
// For each adapter in the list read the adapter information
for (dwIdx=1; dwIdx <= dwCnt; dwIdx++) { hr = ::HrSetupGetStringField(infctx, dwIdx, &str); if (FAILED(hr)) { TraceError("CATlkObj::HrProcessAnswerFile - Failed to read adapter section name",hr); break; }
hr = HrReadAdapterAnswerFileSection(&csif, str.c_str()); if (FAILED(hr)) { goto Error; } } }
TraceTag(ttidDefault, "***Appletalk processing default port***");
// Read the default port property (REG_SZ)
hr = csif.HrGetString(pszAnswerSection, c_szDefaultPort, &str); if (SUCCEEDED(hr)) { tstring strNew = str;
// If the \device\ prefix is present, strip it off
//
if (0 == _wcsnicmp(str.c_str(), c_szDevice, wcslen(c_szDevice))) { strNew = ((PWSTR)str.c_str()) + wcslen(c_szDevice); TraceTag(ttidDefault, "Removing the device prefix. Device=%S",strNew.c_str()); }
// Convert the Adapter0x to \Device\{bind-name}
INetCfgComponent* pncc = NULL; hr = ::HrAnswerFileAdapterToPNCC(PNetCfg(), strNew.c_str(), &pncc); if (S_OK == hr) { PWSTR pszBindName; hr = pncc->GetBindName(&pszBindName); ReleaseObj(pncc); if (FAILED(hr)) { goto Error; }
str = c_szDevice; str += pszBindName;
CoTaskMemFree(pszBindName);
TraceTag(ttidDefault, "Port located and configured"); m_pATLKEnv->SetDefaultPort(str.c_str()); } }
TraceTag(ttidDefault, "***Appletalk finished processing default port***");
// Read the default zone property (REG_SZ)
hr = csif.HrGetString(pszAnswerSection, c_szDesiredZone, &str); if (SUCCEEDED(hr)) { m_pATLKEnv->SetDesiredZone(str.c_str()); }
// Read the EnableRouter property (DWORD used as a boolean)
hr = csif.HrGetStringAsBool(pszAnswerSection, c_szEnableRouter, &fValue); if (SUCCEEDED(hr)) { m_pATLKEnv->EnableRouting(fValue); }
// Determine the best default port overriding the recorded default only
// if the default port cannot be found
m_pATLKEnv->InitDefaultPort();
hr = S_OK; m_fPropertyChange = TRUE;
Error: TraceError("CATlkObj::HrProcessAnswerFile", hr); return hr; }
//
// Function: CATlkObj::HrReadAdapterAnswerFileSection
//
// Purpose: Read the adapter answer file section and create
// the adapter info section if successful
//
// Parameters:
//
// Returns:
//
HRESULT CATlkObj::HrReadAdapterAnswerFileSection(CSetupInfFile * pcsif, PCWSTR pszSection) { HRESULT hr = S_OK; CAdapterInfo * pAI = NULL; tstring str;
INetCfgComponent* pncc = NULL;
// Read the SpecificTo adapter name
hr = pcsif->HrGetString(pszSection, c_szSpecificTo, &str); if (FAILED(hr)) { goto Error; }
// Search for the specified adapter in the set of existing adapters
hr = ::HrAnswerFileAdapterToPNCC(PNetCfg(), str.c_str(), &pncc); if (FAILED(hr)) { goto Error; }
// if we found the adapter component object (pncc != NULL) process
// the adapter section
if (pncc) { DWORD dwData; DWORD dwDataUpper; INFCONTEXT infctx;
pAI = new CAdapterInfo(); Assert(NULL != pAI);
pAI->SetDirty(TRUE);
// Get the adapter component info (media type, description, ...)
hr = ::HrQueryAdapterComponentInfo(pncc, pAI); if (FAILED(hr)) { goto Error; }
// Read the NetworkRangeUpperEnd
hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeUpperEnd, &dwDataUpper); if (FAILED(hr)) { dwDataUpper = pAI->DwQueryNetRangeUpper(); TraceTag(ttidDefault, "CATlkObj::HrReadAdapterAnswerFileSection - Defaulting property %S",c_szNetworkRangeUpperEnd); }
// Read the NetworkRangeLowerEnd
hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeLowerEnd, &dwData); if (FAILED(hr)) { dwData = pAI->DwQueryNetRangeLower(); TraceTag(ttidDefault, "CATlkObj::HrReadAdapterAnswerFileSection - Defaulting property %S",c_szNetworkRangeLowerEnd); }
pAI->SetAdapterNetRange(dwData, dwDataUpper);
// Read the DefaultZone
hr = pcsif->HrGetString(pszSection, c_szDefaultZone, &str); if (SUCCEEDED(hr)) { pAI->SetDefaultZone(str.c_str()); }
// Read the SeedingNetwork
hr = pcsif->HrGetDword(pszSection, c_szNetworkRangeLowerEnd, &dwData); if (SUCCEEDED(hr)) { pAI->SetSeedingNetwork(!!dwData); }
// Generate the PortName
hr = ::HrPortNameFromAdapter(pncc, &str); if (FAILED(hr)) { goto Error; }
pAI->SetPortName(str.c_str());
// Read the ZoneList
hr = HrSetupFindFirstLine(pcsif->Hinf(), pszSection, c_szZoneList, &infctx); if (S_OK == hr) { DWORD dwIdx; DWORD dwCnt = SetupGetFieldCount(&infctx);
// For each adapter in the list read the adapter information
for (dwIdx=1; dwIdx <= dwCnt; dwIdx++) { hr = ::HrSetupGetStringField(infctx, dwIdx, &str); if (FAILED(hr)) { TraceError("CATlkObj::HrProcessAnswerFile - Failed to read adapter section name",hr); goto Error; }
if (!str.empty()) { pAI->LstpstrZoneList().push_back(new tstring(str)); } } }
pAI->SetDirty(TRUE); m_pATLKEnv->AdapterInfoList().push_back(pAI); MarkAdapterListChanged(); }
// Normalize any errors
hr = S_OK;
Done: ReleaseObj(pncc); return hr;
Error: delete pAI; TraceError("CATlkObj::HrReadAdapterAnswerFileSection",hr); goto Done; }
STDMETHODIMP CATlkObj::Install (DWORD) { CAdapterInfo * pAI; ATLK_ADAPTER_INFO_LIST::iterator iter;
m_eInstallAction = eActInstall;
// Mark all the initially detected adapters as dirty
for (iter = m_pATLKEnv->AdapterInfoList().begin(); iter != m_pATLKEnv->AdapterInfoList().end(); iter++) { pAI = *iter; pAI->SetDirty(TRUE); } return S_OK; }
STDMETHODIMP CATlkObj::Removing () { m_eInstallAction = eActRemove; return S_OK; }
STDMETHODIMP CATlkObj::Validate () { return S_OK; }
STDMETHODIMP CATlkObj::CancelChanges () { return S_OK; }
STDMETHODIMP CATlkObj::ApplyRegistryChanges () { HRESULT hr = S_OK;
// Have any changes been validated?
switch(m_eInstallAction) { case eActInstall: hr = HrCommitInstall(); if (SUCCEEDED(hr)) { m_fFirstTimeInstall = FALSE; hr = HrAtlkReconfig(); } break; case eActRemove: hr = HrCommitRemove(); break; default: // eActUnknown
if (m_fAdapterListChanged || m_fPropertyChange) { // Update the registry if the adapter list changed
Assert(NULL != m_pATLKEnv); hr = m_pATLKEnv->HrUpdateRegistry(); if (SUCCEEDED(hr)) { hr = HrAtlkReconfig(); } } break; }
TraceError("CATlkObj::ApplyRegistryChanges",hr); return hr; }
// INetCfgProperties
STDMETHODIMP CATlkObj::SetContext(IUnknown * pUnk) { ReleaseObj(m_pUnkPropContext); m_pUnkPropContext = pUnk; if (m_pUnkPropContext) { AddRefObj(m_pUnkPropContext); }
return S_OK; }
STDMETHODIMP CATlkObj::MergePropPages ( IN OUT DWORD* pdwDefPages, OUT LPBYTE* pahpspPrivate, OUT UINT* pcPages, IN HWND hwndParent, OUT PCWSTR* pszStartPage) { Validate_INetCfgProperties_MergePropPages ( pdwDefPages, pahpspPrivate, pcPages, hwndParent, pszStartPage);
HRESULT hr = S_OK; HPROPSHEETPAGE *ahpsp = NULL; CAdapterInfo * pAI = NULL;
Assert(pahpspPrivate); Assert(NULL == *pahpspPrivate); // Out param init done via Validate above
*pcPages = 0; Assert(NULL != m_pATLKEnv);
if (NULL != m_pATLKEnv_PP) { TraceError("CATlkObj::MergePropPages - multiple property page instances requested.", hr); return E_UNEXPECTED; }
// AppleTalk requires "complete" installation before property changes are
// allowed. If we've just installed but Apply has not yet been pressed,
// disallow property page display
if (m_fFirstTimeInstall) { NcMsgBox(::GetFocus(), IDS_ATLK_CAPTION, IDS_ATLK_INSTALL_PENDING, MB_OK | MB_ICONEXCLAMATION); return S_FALSE; }
// Start with new property pages each time.
CleanupPropPages();
// Locate the adapter referenced in the connection we stashed away
if (NULL != m_pUnkPropContext) { INetLanConnectionUiInfo * pLanConn = NULL; ATLK_ADAPTER_INFO_LIST::iterator iter;
hr = m_pUnkPropContext->QueryInterface(IID_INetLanConnectionUiInfo, reinterpret_cast<LPVOID *>(&pLanConn)); if (S_OK == hr) { GUID guid; hr = pLanConn->GetDeviceGuid(&guid); ReleaseObj(pLanConn); if (SUCCEEDED(hr)) { // Find the adapter in our adapter list
for (iter = m_pATLKEnv->AdapterInfoList().begin(); iter != m_pATLKEnv->AdapterInfoList().end(); iter++) { CAdapterInfo * pAITmp = *iter;
if (guid == *pAITmp->PInstanceGuid()) { // Copy the adapter data
hr = pAITmp->HrCopy(&pAI); break; } } } }
if (SUCCEEDED(hr)) { // If no adapter in this connection or it's
// disabled/hidden/deleted we show no pages
if ((NULL == pAI) || pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden()) { Assert(0 == *pcPages); hr = S_FALSE; goto cleanup; } } } else { // m_pUnkPropContext should have been set first
hr = E_UNEXPECTED; }
if (FAILED(hr)) { goto Error; }
// Create a copy of the enviroment for property page usage
hr = m_pATLKEnv->HrCopy(&m_pATLKEnv_PP); if (FAILED(hr)) { goto Error; }
Assert(NULL != m_pATLKEnv_PP); Assert(NULL != pAI);
// Query the zonelist every time, only for non-Seeding adapters.
if (!pAI->FSeedingNetwork() || !m_pATLKEnv_PP->FRoutingEnabled()) { (void) m_pATLKEnv->HrGetAppleTalkInfoFromNetwork(pAI); }
// Add the adapter to the property sheet's list
m_pATLKEnv_PP->AdapterInfoList().push_back(pAI);
// Allocate the CPropSheetPage object for the "General" page
m_pspObj = new CATLKGeneralDlg(this, m_pATLKEnv_PP);
// Allocate a buffer large enough to hold the handle to the Appletalk config.
// property page.
ahpsp = (HPROPSHEETPAGE *)CoTaskMemAlloc(sizeof(HPROPSHEETPAGE)); if (!ahpsp) { hr = E_OUTOFMEMORY; goto cleanup; // Alloc failed to no need to free ahpsp
}
// Create the actual PROPSHEETPAGE for each object.
ahpsp[0] = m_pspObj->CreatePage(DLG_ATLK_GENERAL, 0);
// Validate what we've created
if (NULL == ahpsp[0]) { hr = E_OUTOFMEMORY; goto Error; } else { *pahpspPrivate = (LPBYTE)ahpsp; *pcPages = 1; }
cleanup: TraceError("CATlkObj::MergePropPages", hr); return hr;
Error: CoTaskMemFree(ahpsp); delete m_pATLKEnv_PP; m_pATLKEnv_PP = NULL; goto cleanup; }
//
// Function: CATlkObj::CleanupPropPages
//
// Purpose:
//
// Parameters:
//
// Returns: nothing
//
VOID CATlkObj::CleanupPropPages() { delete m_pspObj; m_pspObj = NULL; }
//
// Function: CATlkObj::ValidateProperties
//
// Purpose:
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
STDMETHODIMP CATlkObj::ValidateProperties (HWND) { return S_OK; }
//
// Function: CATlkObj::CancelProperties
//
// Purpose:
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
STDMETHODIMP CATlkObj::CancelProperties () { // Discard any changes made via the property pages
delete m_pATLKEnv_PP; m_pATLKEnv_PP = NULL; return S_OK; }
//
// Function: CATlkObj::ApplyProperties
//
// Purpose:
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
STDMETHODIMP CATlkObj::ApplyProperties () { // Extract the adapter info from the property sheet's
// enviroment block
Assert(!m_pATLKEnv_PP->AdapterInfoList().empty()); CAdapterInfo * pAICurrent = m_pATLKEnv_PP->AdapterInfoList().front(); m_pATLKEnv_PP->AdapterInfoList().pop_front(); Assert(NULL != pAICurrent);
// Remove the current adapter from the original enviroment
CAdapterInfo * pAI; ATLK_ADAPTER_INFO_LIST::iterator iter; for (iter = m_pATLKEnv->AdapterInfoList().begin(); iter != m_pATLKEnv->AdapterInfoList().end(); iter++) { pAI = *iter; if (0 == _wcsicmp(pAI->SzBindName(), pAICurrent->SzBindName())) { m_pATLKEnv->AdapterInfoList().erase(iter, iter); break; } }
// Add pAICurrent to the base enviroment block
m_pATLKEnv->AdapterInfoList().push_back(pAICurrent);
// Update the base enviroment from the property sheet's enviroment
m_pATLKEnv->SetDefaultMediaType(m_pATLKEnv_PP->DwDefaultAdaptersMediaType()); m_pATLKEnv->EnableRouting(m_pATLKEnv_PP->FRoutingEnabled()); m_pATLKEnv->SetDefaultPort(m_pATLKEnv_PP->SzDefaultPort()); m_pATLKEnv->SetDesiredZone(m_pATLKEnv_PP->SzDesiredZone()); m_pATLKEnv->SetRouterChanged(m_pATLKEnv_PP->FRouterChanged()); m_pATLKEnv->SetDefAdapterChanged(m_pATLKEnv_PP->FDefAdapterChanged());
// Delete the property pages enviroment block
delete m_pATLKEnv_PP; m_pATLKEnv_PP = NULL;
// Properties changed
m_fPropertyChange = TRUE; return S_OK; }
// INetCfgBindNotify
STDMETHODIMP CATlkObj::QueryBindingPath ( DWORD dwChangeFlag, INetCfgBindingPath* pncbpItem ) { Validate_INetCfgBindNotify_QueryBindingPath( dwChangeFlag, pncbpItem ); return S_OK; }
STDMETHODIMP CATlkObj::NotifyBindingPath ( DWORD dwChangeFlag, INetCfgBindingPath* pncbpItem ) { HRESULT hr = S_OK; INetCfgComponent *pnccFound = NULL;
Validate_INetCfgBindNotify_NotifyBindingPath( dwChangeFlag, pncbpItem );
Assert(NULL != m_pATLKEnv);
// Only Interested in lower binding Add's and Remove's
if (dwChangeFlag & (NCN_ADD | NCN_REMOVE | NCN_ENABLE | NCN_DISABLE)) { CIterNetCfgBindingInterface ncbiIter(pncbpItem); INetCfgBindingInterface *pncbi;
// Enumerate the binding interfaces looking for the last Adapter
while (SUCCEEDED(hr) && (S_OK == (hr = ncbiIter.HrNext (&pncbi)))) { INetCfgComponent *pncc;
hr = pncbi->GetLowerComponent(&pncc); if (S_OK == hr) { GUID guidClass; hr = pncc->GetClassGuid(&guidClass); if ((S_OK == hr) && (GUID_DEVCLASS_NET == guidClass)) { ULONG ulStatus = 0; hr = pncc->GetDeviceStatus(&ulStatus);
if(S_OK == hr) { ReleaseObj(pnccFound); pnccFound = pncc; // Transfer Ownership
pncc = NULL; } else { ReleaseObj(pncc); } } else { ReleaseObj(pncc); } }
ReleaseObj(pncbi); }
if (FAILED(hr)) { goto Error; }
// Did we find the Adapter?
if (pnccFound) { BOOL fFound = FALSE; PWSTR pszBindName = NULL; CAdapterInfo * pAI; ATLK_ADAPTER_INFO_LIST::iterator iterAdapterInfo;
Assert(NULL != m_pATLKEnv); ATLK_ADAPTER_INFO_LIST pAI_List = m_pATLKEnv->AdapterInfoList();
hr = pnccFound->GetBindName(&pszBindName); if (S_OK != hr) { goto Error; }
// Search the adapter list
for (iterAdapterInfo = pAI_List.begin(); iterAdapterInfo != pAI_List.end(); iterAdapterInfo++) { pAI = *iterAdapterInfo; if (0 == lstrcmpiW(pszBindName, pAI->SzBindName())) { fFound = TRUE; break; } }
Assert(NULL != pszBindName); CoTaskMemFree(pszBindName);
// Apply the appropriate delta to the adapter list
if (fFound && (dwChangeFlag & NCN_REMOVE)) { // Delete the adapter from the list
pAI->SetDeletePending(TRUE); m_fAdapterListChanged = TRUE; } else if (!fFound && (dwChangeFlag & NCN_ADD)) { // Add the adapter to the list
hr = m_pATLKEnv->HrAddAdapter(pnccFound); m_fAdapterListChanged = TRUE; } else if (fFound && (dwChangeFlag & NCN_ADD)) { // Re-enable the adapters existance
pAI->SetDeletePending(FALSE); }
if (fFound) { if (dwChangeFlag & NCN_ENABLE) { pAI->SetDisabled(FALSE); m_fAdapterListChanged = TRUE; } else if (dwChangeFlag & NCN_DISABLE) { pAI->SetDisabled(TRUE); m_fAdapterListChanged = TRUE; } } }
if (SUCCEEDED(hr)) { hr = S_OK; // Normalize return value
} }
Error: ::ReleaseObj(pnccFound); TraceError("CATlkObj::NotifyBindingPath",hr); return hr; }
//
// Function: CATlkObj::HrCommitInstall
//
// Purpose: Commit Installation registry changes to the registry
//
// Parameters: None
//
// Returns: HRESULT, S_OK on success
//
//
HRESULT CATlkObj::HrCommitInstall() { HRESULT hr;
Assert(NULL != m_pATLKEnv); hr = m_pATLKEnv->HrUpdateRegistry();
TraceError("CATlkObj::HrCommitInstall",hr); return hr; }
//
// Function: CATlkObj::HrCommitRemove
//
// Purpose: Remove from the registry settings which were created by this
// component's installation.
//
// Parameters: None
//
// Returns: HRESULT, S_OK on success
//
//
HRESULT CATlkObj::HrCommitRemove() { // Everything is removed via the inf file presently
return S_OK; }
//
// Function: CATLKEnv::HrCreate
//
// Purpose: Construct the AppleTalk Enviroment tracking object
//
// Paramaters: ppATLKEnv [out] - AppleTalk Enviroment Object created
// pmsc [in] - AppleTalk notification object
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrCreate(CATLKEnv **ppATLKEnv, CATlkObj *pmsc) { HRESULT hr = S_OK; CATLKEnv *pATLKEnv = NULL;
*ppATLKEnv = NULL;
// Construct the new enviroment object
pATLKEnv = new CATLKEnv(pmsc);
if (pATLKEnv == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
// Read AppleTalk Info
hr = pATLKEnv->HrReadAppleTalkInfo(); if (FAILED(hr)) { goto Error; }
*ppATLKEnv = pATLKEnv;
Done: return hr;
Error: TraceError("CATLKEnv::HrCreate",hr); delete pATLKEnv; goto Done; }
//
// Function: CATLKEnv::CATLKEnv
//
// Purpose: ctor for the CATLKEnv class
//
// Parameters: none
//
// Returns: none
//
CATLKEnv::CATLKEnv(CATlkObj *pmsc) : m_pmsc(pmsc), m_fATrunning(FALSE), m_dwDefaultAdaptersMediaType(MEDIATYPE_ETHERNET), m_fRouterChanged(FALSE), m_fDefAdapterChanged(FALSE) { ZeroMemory(&m_Params, sizeof(m_Params)); }
//
// Function: CATLKEnv::~CATLKEnv
//
// Purpose: dtor for the CATLKEnv class
//
// Parameters: none
//
// Returns: none
//
CATLKEnv::~CATLKEnv() { // Cleanup the AppleTalk\Parameters internal data structure
delete [] m_Params.szDefaultPort; delete [] m_Params.szDesiredZone;
// Cleanup the contents of the Adapter Info List
while (!m_lstpAdapters.empty()) { delete m_lstpAdapters.front(); m_lstpAdapters.pop_front(); } }
//
// Function: CATLKEnv::HrCopy
//
// Purpose: Creates a copy of the current Enviroment
//
// Parameters: ppEnv [out] - If the function succeeds, ppEnv will contain a
// copy of the enviroment.
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrCopy(CATLKEnv **ppEnv) { HRESULT hr = S_OK; CATLKEnv * pEnv;
// Allocate a new enviroment object
*ppEnv = NULL; pEnv = new CATLKEnv(m_pmsc); if (NULL != pEnv) { // Copy the members
pEnv->m_fATrunning = m_fATrunning; pEnv->SetDefaultMediaType(DwDefaultAdaptersMediaType()); pEnv->EnableRouting(FRoutingEnabled()); pEnv->SetDefaultPort(SzDefaultPort()); pEnv->SetDesiredZone(SzDesiredZone()); pEnv->SetRouterChanged(FRouterChanged()); pEnv->SetDefAdapterChanged(FDefAdapterChanged());
*ppEnv = pEnv; } else { hr = E_OUTOFMEMORY; }
TraceError("CATLKEnv::HrCopy",hr); return S_OK; }
//
// Function: CATLKEnv::HrReadAppleTalkInfo
//
// Purpose: Retrieve the AppleTalk registry Settings
//
// Parameters: none
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrReadAppleTalkInfo() { HRESULT hr;
// Read the AppleTalk\Parameters values
RegReadValues(celems(regbatchATLKParams), regbatchATLKParams, (BYTE *)&m_Params, KEY_READ);
// Read info for each adapter listed under AppleTalk\Parameters\Adapters
hr = HrGetAdapterInfo();
TraceError("CATLKEnv::HrReadAppleTalkInfo",hr); return hr; }
//
// Function: CATLKEnv::HrGetOneAdaptersInfo
//
// Purpose: Retrieve the AppleTalk Adapter information for one adapter
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrGetOneAdaptersInfo(INetCfgComponent* pncc, CAdapterInfo **ppAI) { HKEY hkeyAdapterRoot = NULL; HKEY hkeyAdapter = NULL; HRESULT hr; INT idx; CAdapterInfo * pAI = NULL; REGBATCH regbatch; tstring strKey; tstring strKeyPath = c_szATLKAdapters;
*ppAI = NULL;
// Construct the adapter info object
pAI = new CAdapterInfo;
if (pAI == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
// Get the adapter component info (media type, description, ...)
hr = ::HrQueryAdapterComponentInfo(pncc, pAI); if (FAILED(hr)) { goto Error; }
hr = ::HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, strKeyPath.c_str(), KEY_READ, &hkeyAdapterRoot); if (S_OK == hr) { strKey = pAI->SzBindName();
// Try to open the key for this specific adapter
hr = ::HrRegOpenKeyEx(hkeyAdapterRoot, pAI->SzBindName(), KEY_READ, &hkeyAdapter); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { // We weren't able to find this in the registry, write it out
// when we can (self repair)
pAI->SetDirty(TRUE); }
strKeyPath += c_szBackslash; strKeyPath += strKey.c_str();
// If we located the key query the data
if (S_OK == hr) { hr = HrRegQueryColString(hkeyAdapter, c_szZoneList, &pAI->LstpstrZoneList());
// Since CAdapterInfo defaults allocations, need to free
// them before RegReadValues writes over them and causes a leak.
//
delete [] pAI->m_AdapterInfo.m_szDefaultZone; delete [] pAI->m_AdapterInfo.m_szPortName; pAI->m_AdapterInfo.m_szDefaultZone = NULL; pAI->m_AdapterInfo.m_szPortName = NULL;
// Read the adapter information
for (idx=0; idx<celems(regbatchATLKAdapters); idx++) { regbatch = regbatchATLKAdapters[idx]; regbatch.pszSubkey = strKeyPath.c_str();
RegReadValues(1, ®batch, (BYTE *)pAI->PAdapterInfo(), KEY_READ); } } }
if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)) { // Something other than a "not found" error
goto Error; }
// Normalize return value
hr = S_OK;
// If the port name was not found then generate one
if (0 == wcslen(pAI->SzPortName())) { tstring str; hr = ::HrPortNameFromAdapter(pncc, &str); if (FAILED(hr)) { goto Error; }
pAI->SetPortName(str.c_str()); }
// Set the return value
*ppAI = pAI;
Done: ::RegSafeCloseKey(hkeyAdapter); ::RegSafeCloseKey(hkeyAdapterRoot); return hr;
Error: TraceError("CATLKEnv::HrGetOneAdaptersInfo",hr); delete pAI; goto Done; }
//
// Function: CATLKEnv::HrGetAdapterInfo
//
// Purpose: Retrieve the AppleTalk Adapter information
//
// Parameters: none
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrGetAdapterInfo() { HRESULT hr = S_OK; CAdapterInfo * pAI = NULL; INetCfgComponent* pncc = NULL; INetCfgComponent* pnccUse = NULL;
// Find each netcard, to do so, trace the bindings to their end
// If the endpoint is a netcard then add it to the list
CIterNetCfgBindingPath ncbpIter(m_pmsc->PNCComponent()); INetCfgBindingPath* pncbp;
while (SUCCEEDED(hr) && (S_OK == (hr = ncbpIter.HrNext (&pncbp)))) { // Iterate the binding interfaces of this path.
CIterNetCfgBindingInterface ncbiIter(pncbp); INetCfgBindingInterface* pncbi;
while (SUCCEEDED(hr) && (S_OK == (hr = ncbiIter.HrNext (&pncbi)))) { // Retrieve the lower component
hr = pncbi->GetLowerComponent(&pncc); if (S_OK == hr) { GUID guidClass;
// Is it an Adapter?
hr = pncc->GetClassGuid(&guidClass); if ((S_OK == hr) && (guidClass == GUID_DEVCLASS_NET)) { ULONG ulStatus = 0; hr = pncc->GetDeviceStatus(&ulStatus); if(SUCCEEDED(hr)) { ReleaseObj(pnccUse); pnccUse = pncc; pncc = NULL; } else { // Release the lower component
ReleaseObj(pncc); hr = S_OK; break; } } else { // Release the lower component
ReleaseObj(pncc); } }
// Release the binding interface
ReleaseObj (pncbi); }
if (NULL != pnccUse) { // Query the Adapter information
hr = HrGetOneAdaptersInfo(pnccUse, &pAI); if (SUCCEEDED(hr)) { if (S_FALSE == pncbp->IsEnabled()) { pAI->SetDisabled(TRUE); }
// Add this Adapter to the list
m_lstpAdapters.push_back(pAI); }
ReleaseObj(pnccUse); pnccUse = NULL; }
// Release the binding path
ReleaseObj (pncbp); }
if (FAILED(hr)) { goto Error; }
// Initialize the default port, etc
InitDefaultPort();
// Normalize the HRESULT. (i.e. don't return S_FALSE)
hr = S_OK;
Error: TraceError("CATLKEnv::HrGetAdapterInfo",hr); return hr; }
//
// Function: CATLKEnv::HrGetAppleTalkInfoFromNetwork
//
// Purpose: ???
//
// Parameters: none
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrGetAppleTalkInfoFromNetwork(CAdapterInfo * pAI) { SOCKADDR_AT address; HRESULT hr = S_FALSE; BOOL fWSInitialized = FALSE; SOCKET mysocket = INVALID_SOCKET; WSADATA wsadata; DWORD wsaerr = 0; tstring strPortName;
// Create the socket/bind
wsaerr = WSAStartup(0x0101, &wsadata); if (0 != wsaerr) { goto Error; }
// Winsock successfully initialized
fWSInitialized = TRUE;
mysocket = socket(AF_APPLETALK, SOCK_DGRAM, DDPPROTO_ZIP); if (INVALID_SOCKET == mysocket) { goto Error; }
address.sat_family = AF_APPLETALK; address.sat_net = 0; address.sat_node = 0; address.sat_socket = 0;
wsaerr = bind(mysocket, (struct sockaddr *)&address, sizeof(address)); if (wsaerr != 0) { goto Error; }
// Mark AppleTalk as running
SetATLKRunning(TRUE);
// For each known adapter, create a device name by merging the "\\device\\"
// prefix and the adapter's bind name.
strPortName = c_szDevice; strPortName += pAI->SzBindName();
// Failures from query the zone list for a given adapter can be from
// the adapter not connected to the network, zone seeder not running, etc.
// Because we want to process all the adapters, we ignore these errors.
(void)pAI->HrGetAndSetNetworkInformation(mysocket,strPortName.c_str());
// Success, or at least not a critical failure
hr = S_OK;
Done: if (INVALID_SOCKET != mysocket) { closesocket(mysocket); }
if (fWSInitialized) { WSACleanup(); }
TraceError("CATLKEnv::HrGetAppleTalkInfoFromNetwork",(S_FALSE == hr ? S_OK : hr)); return hr;
Error: wsaerr = ::WSAGetLastError(); goto Done; }
//
// Function: CATLKEnv::HrAddAdapter
//
// Purpose: Add and adapter to the list of currently bound adapters
//
// Parameters: pnccFound - Notification object for the bound adapter to add
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrAddAdapter(INetCfgComponent * pnccFound) { HRESULT hr; CAdapterInfo * pAI = NULL;
Assert(NULL != pnccFound);
// Create an AdapterInfo instance for the adapter
hr = HrGetOneAdaptersInfo(pnccFound, &pAI); if (FAILED(hr)) { goto Error; }
// Add this Adapter to the list
m_lstpAdapters.push_back(pAI); pAI->SetDirty(TRUE);
// If there is now only one adapter in the list, update the defaults
if (1 == m_lstpAdapters.size()) { tstring str; str = c_szDevice; str += m_lstpAdapters.front()->SzBindName(); SetDefaultPort(str.c_str()); SetDefaultMediaType(m_lstpAdapters.front()->DwMediaType()); }
Error: TraceError("CATLKEnv::HrAddAdapter",hr); return hr; }
//
// Function: CATLKEnv::SetDefaultPort
//
// Purpose: Change the default port name
//
// Parameters: psz [in] - The new default port name
//
// Returns: HRESULT, S_OK on success
//
void CATLKEnv::SetDefaultPort(PCWSTR psz) { Assert(psz); delete [] m_Params.szDefaultPort; m_Params.szDefaultPort = new WCHAR[wcslen(psz)+1]; wcscpy(m_Params.szDefaultPort, psz); }
//
// Function: CATLKEnv::SetDesiredZone
//
// Purpose: Change the desired zone
//
// Parameters: sz [in] - The new desired zone
//
// Returns: HRESULT, S_OK on success
//
void CATLKEnv::SetDesiredZone(PCWSTR psz) { Assert(psz); delete [] m_Params.szDesiredZone; m_Params.szDesiredZone = new WCHAR[wcslen(psz)+1]; wcscpy(m_Params.szDesiredZone, psz); }
CAdapterInfo * CATLKEnv::PAIFindDefaultPort() { CAdapterInfo * pAI = NULL; ATLK_ADAPTER_INFO_LIST::iterator iter;
// Find the default port
//
for (iter = m_lstpAdapters.begin(); iter != m_lstpAdapters.end(); iter++) { tstring strPortName;
pAI = *iter;
// Retain adapter selection as the default port
strPortName = c_szDevice; strPortName += pAI->SzBindName();
if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() || pAI->IsRasAdapter()) { continue; }
if (0 == _wcsicmp(SzDefaultPort(), strPortName.c_str())) { return pAI; } }
return NULL; }
//
// Function: CATLKEnv::HrUpdateRegistry
//
// Purpose: Write the AppleTalk local (internal) data back to the registry
//
// Parameters: none
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrUpdateRegistry() { HRESULT hr = S_OK; CAdapterInfo * pAI = NULL; HKEY hkeyAdapter; DWORD dwDisposition; ATLK_ADAPTER_INFO_LIST::iterator iter;
// If the current default port is unavailable, find an alternate
pAI = PAIFindDefaultPort(); if (NULL == pAI) { InitDefaultPort(); pAI = PAIFindDefaultPort(); }
// If the default adapter changed then three specific values for that
// adapter need to be reset to zero.
//
if (pAI && FDefAdapterChanged()) { pAI->ZeroSpecialParams(); pAI->SetDirty(TRUE); }
// Commit the registry changes
hr = ::HrRegWriteValues(celems(regbatchATLKParams), regbatchATLKParams, (BYTE *)&m_Params, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS); if (S_OK != hr) { goto Error; }
// Create the Adapters key AppleTalk\Parameters\Adapters)
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szATLKAdapters, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAdapter, &dwDisposition); if (S_OK == hr) { // Enumerate the bound adapters and write the internal adapter list
for (iter = m_lstpAdapters.begin(); (iter != m_lstpAdapters.end()) && (SUCCEEDED(hr)); iter++) { pAI = *iter;
if (pAI->FDeletePending()) { // Remove the AppleTalk\Adapter\{bindname} tree
hr = ::HrRegDeleteKeyTree(hkeyAdapter, pAI->SzBindName()); if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)) { goto Error; } } else if (pAI->IsDirty()) { hr = HrWriteOneAdapter(pAI); } }
RegCloseKey (hkeyAdapter); }
Error: TraceError("CATLKEnv::HrUpdateRegistry",hr); return hr; }
//
// Function: CATLKEnv::HrWriteOneAdapter
//
// Purpose: Write one adapter instance to the registry
//
// Parameters: pAI [in] - The adapter to presist in the registry
//
// Returns: HRESULT, S_OK on success
//
HRESULT CATLKEnv::HrWriteOneAdapter(CAdapterInfo *pAI) { DWORD dwDisposition; HKEY hkeyAdapter = NULL; HRESULT hr; INT idx; REGBATCH regbatch; tstring str;
str = c_szATLKAdapters; str += c_szBackslash; str += pAI->SzBindName();
// Create the key described in str (AppleTalk\Parameters\Adapters\<adapter>)
hr = ::HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, str.c_str(), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyAdapter, &dwDisposition); if (FAILED(hr)) { goto Error; }
// Write out the adapter parameters
for (idx = 0; idx < celems(regbatchATLKAdapters); idx++) { regbatch = regbatchATLKAdapters[idx]; regbatch.pszSubkey = str.c_str();
hr = ::HrRegWriteValues(1, ®batch, (BYTE *)pAI->PAdapterInfo(), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS); if (FAILED(hr)) { goto Error; } }
// Write out the zone list multi-sz (managed seperately)
hr = ::HrRegSetColString(hkeyAdapter, c_szZoneList, pAI->LstpstrZoneList());
Error: ::RegSafeCloseKey(hkeyAdapter); TraceError("CATLKEnv::HrWriteOneAdapter",hr); return S_OK; }
//
// Function: CATLKEnv::DwMediaPriority
//
// Purpose: When determining the appropriate adapter for use as the
// "DefaultPort" certain mediatype's are faster. So all
// other things being equal, selecting a faster mediatype
// benefits the user the most.
//
// Parameters: dwMediaType [in] - MediaType used to determine priority ranking
//
// Returns: DWORD, value (1-5) with the lowest value representing the
// highest priority.
//
DWORD CATLKEnv::DwMediaPriority(DWORD dwMediaType) { switch(dwMediaType) { case MEDIATYPE_ETHERNET: return 2; case MEDIATYPE_TOKENRING: return 3; case MEDIATYPE_FDDI: return 1; case MEDIATYPE_LOCALTALK: return 4; default: return 5; } }
//
// Function: CATLKEnv::InitDefaultPort
//
// Purpose: Select a default port if none yet has been selected. Retain
// some select information for assisting in dialog display issues.
//
// Parameters: none
//
// Returns: nothing
//
void CATLKEnv::InitDefaultPort() { CAdapterInfo * pAI = NULL; tstring str;
ATLK_ADAPTER_INFO_LIST::iterator iter;
// If DefaultPort is set, does the associated adapter exist?
if (wcslen(SzDefaultPort())) { // Search for the adapter in the list
for (iter = AdapterInfoList().begin(); iter != AdapterInfoList().end(); iter++) { pAI = *iter;
if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() || pAI->IsRasAdapter()) { pAI = NULL; continue; }
str = c_szDevice; str += pAI->SzBindName(); if (0 == wcscmp(str.c_str(), SzDefaultPort())) { break; }
pAI = NULL; } }
// If DefaultPort is not set locate the best candidate
if (NULL == pAI) { CAdapterInfo * pAIBest = NULL; SetDefaultPort(c_szEmpty);
// Search through the adapter list for the adapter
// with the fastest media type.
for (iter = AdapterInfoList().begin(); iter != AdapterInfoList().end(); iter++) { pAI = *iter;
if (pAI->FDeletePending() || pAI->FDisabled() || pAI->FHidden() || pAI->IsRasAdapter()) { continue; }
if ((NULL == pAIBest) || (DwMediaPriority(pAIBest->DwMediaType()) > DwMediaPriority(pAI->DwMediaType()))) { SetDefAdapterChanged(TRUE); pAIBest = pAI; } }
pAI = pAIBest; }
if (NULL != pAI) { // retain the selected adapter as the default port
str = c_szDevice; str += pAI->SzBindName(); SetDefaultPort(str.c_str());
// retain the default media type
SetDefaultMediaType(pAI->DwMediaType()); } else { SetDefaultPort(c_szEmpty); } }
//
// Function: CAdapterInfo::CAdapterInfo
//
// Purpose: ctor for the CAdapters class
//
// Parameters: none
//
// Returns: nothing
//
CAdapterInfo::CAdapterInfo() : m_fDeletePending(FALSE), m_fDisabled(FALSE), m_fDirty(FALSE), m_fRasAdapter(FALSE), m_fRouterOnNetwork(FALSE), m_fZoneListValid(FALSE), m_dwNetworkUpper(0), m_dwNetworkLower(0), m_dwCharacteristics(0) { ZeroMemory(&m_guidInstance, sizeof(m_guidInstance));
// Initialize the AdapterInfo default values
ZeroMemory(&m_AdapterInfo, sizeof(m_AdapterInfo)); m_AdapterInfo.m_dwAarpRetries = c_dwTen; m_AdapterInfo.m_dwMediaType = MEDIATYPE_ETHERNET; SetDefaultZone(c_szEmpty); SetPortName(c_szEmpty); }
//
// Function: CAdapterInfo::~CAdapterInfo
//
// Purpose: ctor for the CAdapters class
//
// Parameters: none
//
// Returns: nothing
//
CAdapterInfo::~CAdapterInfo() { // Cleanup the AppleTalk\Adapters\<adapter> internal data structure
delete [] m_AdapterInfo.m_szDefaultZone; delete [] m_AdapterInfo.m_szPortName;
DeleteColString(&m_lstpstrDesiredZoneList); DeleteColString(&m_lstpstrZoneList); }
//
// Function: CAdapterInfo::SetDefaultZone
//
// Purpose: Set the default zone for this adapter
//
// Parameters: sz - The new default zone
//
// Returns: nothing
//
void CAdapterInfo::SetDefaultZone(PCWSTR psz) { Assert(psz); delete [] m_AdapterInfo.m_szDefaultZone; m_AdapterInfo.m_szDefaultZone = NULL; m_AdapterInfo.m_szDefaultZone = new WCHAR[wcslen(psz)+1]; wcscpy(m_AdapterInfo.m_szDefaultZone, psz); }
//
// Function: CAdapterInfo::SetPortName
//
// Purpose: Set the port name for this adapter
//
// Parameters: sz - The new port name
//
// Returns: nothing
//
void CAdapterInfo::SetPortName(PCWSTR psz) { Assert(psz); delete [] m_AdapterInfo.m_szPortName; m_AdapterInfo.m_szPortName = NULL; m_AdapterInfo.m_szPortName = new WCHAR[wcslen(psz)+1]; wcscpy(m_AdapterInfo.m_szPortName, psz); }
//
// Function: CAdapterInfo::HrGetAndSetNetworkInformation
//
// Purpose:
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
#define PARM_BUF_LEN 512
#define ASTERISK_CHAR "*"
HRESULT CAdapterInfo::HrGetAndSetNetworkInformation ( SOCKET socket, PCWSTR pszDevName) { HRESULT hr = FALSE; CHAR *pZoneBuffer = NULL; CHAR *pDefParmsBuffer = NULL; CHAR *pZoneListStart; INT BytesNeeded ; WCHAR *pwDefZone = NULL; tstring strTmpZone; INT ZoneLen = 0; DWORD wsaerr = 0; CHAR *pDefZone = NULL;
PWSH_LOOKUP_ZONES pGetNetZones; PWSH_LOOKUP_NETDEF_ON_ADAPTER pGetNetDefaults;
Assert(pszDevName);
pZoneBuffer = new CHAR [ZONEBUFFER_LEN + sizeof(WSH_LOOKUP_ZONES)]; Assert(pZoneBuffer);
if (pZoneBuffer == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
pGetNetZones = (PWSH_LOOKUP_ZONES)pZoneBuffer;
wcscpy((WCHAR *)(pGetNetZones+1), pszDevName);
BytesNeeded = ZONEBUFFER_LEN;
wsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_ZONES_ON_ADAPTER, (char *)pZoneBuffer, &BytesNeeded); if (0 != wsaerr) { //$ REVIEW - error mapping
#ifdef DBG
DWORD dwErr = WSAGetLastError(); TraceTag(ttidError, "CAdapterInfo::HrGetAndSetNetworkInformation getsocketopt returned: %08X",dwErr); #endif
hr = E_UNEXPECTED; goto Error; }
pZoneListStart = pZoneBuffer + sizeof(WSH_LOOKUP_ZONES); if (!lstrcmpA(pZoneListStart, ASTERISK_CHAR)) { // Success, wildcard zone set.
goto Done; }
hr = HrConvertZoneListAndAddToPortInfo(pZoneListStart, ((PWSH_LOOKUP_ZONES)pZoneBuffer)->NoZones); if (FAILED(hr)) { goto Error; }
SetRouterOnNetwork(TRUE);
//
// Get the DefaultZone/NetworkRange Information
pDefParmsBuffer = new CHAR[PARM_BUF_LEN+sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER)]; Assert(pDefParmsBuffer);
if (pDefParmsBuffer == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
pGetNetDefaults = (PWSH_LOOKUP_NETDEF_ON_ADAPTER)pDefParmsBuffer; BytesNeeded = PARM_BUF_LEN + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER);
wcscpy((WCHAR*)(pGetNetDefaults+1), pszDevName); pGetNetDefaults->NetworkRangeLowerEnd = pGetNetDefaults->NetworkRangeUpperEnd = 0;
wsaerr = getsockopt(socket, SOL_APPLETALK, SO_LOOKUP_NETDEF_ON_ADAPTER, (char*)pDefParmsBuffer, &BytesNeeded); if (0 != wsaerr) { #ifdef DBG
DWORD dwErr = WSAGetLastError(); #endif
hr = E_UNEXPECTED; goto Error; }
// Save the default information to PORT_INFO
SetExistingNetRange(pGetNetDefaults->NetworkRangeLowerEnd, pGetNetDefaults->NetworkRangeUpperEnd);
pDefZone = pDefParmsBuffer + sizeof(WSH_LOOKUP_NETDEF_ON_ADAPTER); ZoneLen = lstrlenA(pDefZone) + 1;
pwDefZone = new WCHAR [sizeof(WCHAR) * ZoneLen]; Assert(NULL != pwDefZone);
if (pwDefZone == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
mbstowcs(pwDefZone, pDefZone, ZoneLen);
strTmpZone = pwDefZone;
SetNetDefaultZone(strTmpZone.c_str());
if (pZoneBuffer != NULL) { delete [] pZoneBuffer; }
if (pwDefZone != NULL) { delete [] pwDefZone; }
if (pDefParmsBuffer != NULL) { delete [] pDefParmsBuffer; }
Done: Error: TraceError("CAdapterInfo::HrGetAndSetNetworkInformation",hr); return hr; }
//
// Function: CAdapterInfo::HrConvertZoneListAndAddToPortInfo
//
// Purpose:
//
// Parameters:
//
// Returns: HRESULT, S_OK on success
//
HRESULT CAdapterInfo::HrConvertZoneListAndAddToPortInfo(CHAR * szZoneList, ULONG NumZones) { INT cbAscii = 0; WCHAR *pszZone = NULL; tstring *pstr;
Assert(NULL != szZoneList); DeleteColString(&m_lstpstrDesiredZoneList);
while(NumZones--) { cbAscii = lstrlenA(szZoneList) + 1;
pszZone = new WCHAR [sizeof(WCHAR) * cbAscii]; Assert(NULL != pszZone);
if (pszZone == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
mbstowcs(pszZone, szZoneList, cbAscii);
pstr = new tstring(pszZone); Assert(NULL != pstr);
m_lstpstrDesiredZoneList.push_back(pstr); szZoneList += cbAscii;
delete [] pszZone; }
return S_OK; }
//
// Function: CAdapterInfo::HrCopy
//
// Purpose: Create a duplicate copy of 'this'
//
// Parameters: ppAI [out] - if the function succeeds, ppAI will contain the
// copy of 'this'.
//
// Returns: HRESULT, S_OK on success
//
HRESULT CAdapterInfo::HrCopy(CAdapterInfo ** ppAI) { CAdapterInfo *pAI; list<tstring*>::iterator iter; tstring * pstr;
Assert(NULL != ppAI);
// Create an adapter info structure
pAI = new CAdapterInfo; Assert(pAI);
if (pAI == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
// Make a copy of everything
pAI->SetDisabled(FDisabled()); pAI->SetDeletePending(FDeletePending()); pAI->SetCharacteristics(GetCharacteristics()); pAI->SetMediaType(DwMediaType()); pAI->SetBindName(SzBindName()); pAI->SetDisplayName(SzDisplayName()); pAI->SetNetDefaultZone(SzNetDefaultZone()); pAI->SetRouterOnNetwork(FRouterOnNetwork()); pAI->SetExistingNetRange(DwQueryNetworkLower(), DwQueryNetworkUpper()); pAI->SetDirty(IsDirty()); pAI->SetRasAdapter(IsRasAdapter());
// Free the default data set by the constructor before overwriting it.
// (this whole thing is not a very good approach.)
//
delete [] pAI->m_AdapterInfo.m_szDefaultZone; delete [] pAI->m_AdapterInfo.m_szPortName;
pAI->m_AdapterInfo = m_AdapterInfo;
// Cleanup the 'allocated' data cause by the bit copy
// so that SetDefaultZone and SetPortName don't try to free bogus
// stuff. (more "programming by side-affect")
//
pAI->m_AdapterInfo.m_szDefaultZone = NULL; pAI->m_AdapterInfo.m_szPortName = NULL;
// Now copy the 'allocated' data
pAI->SetDefaultZone(SzDefaultZone()); pAI->SetPortName(SzPortName());
for (iter = LstpstrZoneList().begin(); iter != LstpstrZoneList().end(); iter++) { pstr = *iter; pAI->LstpstrZoneList().push_back(new tstring(pstr->c_str())); }
for (iter = LstpstrDesiredZoneList().begin(); iter != LstpstrDesiredZoneList().end(); iter++) { pstr = *iter; pAI->LstpstrDesiredZoneList().push_back(new tstring(pstr->c_str())); }
*ppAI = pAI; return S_OK; }
//
// Function: HrQueryAdapterComponentInfo
//
// Purpose: Fill out an CAdapterInfo instance with the data retrieved
// specifically from the component itself.
//
// Parameters: pncc [in] - The component object (adapter) to query
// pAI [in/out] - Where to place the queried info
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrQueryAdapterComponentInfo(INetCfgComponent *pncc, CAdapterInfo * pAI) { PWSTR psz = NULL; DWORD dwCharacteristics; HRESULT hr;
Assert(NULL != pncc); Assert(NULL != pAI);
// Retrieve the component's name
hr = pncc->GetBindName(&psz); if (FAILED(hr)) { goto Error; }
Assert(psz && *psz); pAI->SetBindName(psz); CoTaskMemFree(psz); psz = NULL;
hr = pncc->GetInstanceGuid(pAI->PInstanceGuid()); if (FAILED(hr)) { goto Error; }
// Get the Adapter's display name
hr = pncc->GetDisplayName(&psz); if (FAILED(hr)) { goto Error; }
Assert(psz); pAI->SetDisplayName(psz); CoTaskMemFree(psz); psz = NULL;
// Get the Component ID so we can check if this is a RAS adapter
//
hr = pncc->GetId(&psz); if (FAILED(hr)) { goto Error; }
Assert(psz && *psz); pAI->SetRasAdapter(0 == _wcsicmp(c_szInfId_MS_NdisWanAtalk, psz)); CoTaskMemFree(psz); psz = NULL;
// Failure is non-fatal
hr = pncc->GetCharacteristics(&dwCharacteristics); if (SUCCEEDED(hr)) { pAI->SetCharacteristics(dwCharacteristics); }
// Get the media type (Optional key)
{ DWORD dwMediaType = MEDIATYPE_ETHERNET ; INetCfgComponentBindings* pnccBindings = NULL;
hr = pncc->QueryInterface(IID_INetCfgComponentBindings, reinterpret_cast<void**>(&pnccBindings)); if (S_OK == hr) { static const struct { PCWSTR pszInterface; DWORD dwInterface; DWORD dwFlags; } InterfaceMap[] = {{L"ethernet", MEDIATYPE_ETHERNET, NCF_LOWER}, {L"tokenring", MEDIATYPE_TOKENRING, NCF_LOWER}, {L"fddi", MEDIATYPE_FDDI, NCF_LOWER}, {L"localtalk", MEDIATYPE_LOCALTALK, NCF_LOWER}, {L"wan", MEDIATYPE_WAN, NCF_LOWER}};
for (UINT nIdx=0; nIdx < celems(InterfaceMap); nIdx++) { hr = pnccBindings->SupportsBindingInterface(InterfaceMap[nIdx].dwFlags, InterfaceMap[nIdx].pszInterface); if (S_OK == hr) { dwMediaType = InterfaceMap[nIdx].dwInterface; break; } }
::ReleaseObj(pnccBindings); }
pAI->SetMediaType(dwMediaType); hr = S_OK; }
Error: TraceError("HrQueryAdapterComponentInfo",hr); return hr; }
//
// Function: HrPortNameFromAdapter
//
// Purpose: Create a port name, for use as an adapters PortName
//
// Parameters: pncc [in] - The component object (adapter) to query
// pstr [in/out] - On success will contain the PortName
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrPortNameFromAdapter(INetCfgComponent *pncc, tstring * pstr) { HRESULT hr; PWSTR psz; PWSTR pszBindName = NULL; WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwSize = sizeof(szComputerName) / sizeof(WCHAR);
Assert(NULL != pstr); Assert(NULL != pncc);
if (!GetComputerName(szComputerName, &dwSize)) { hr = ::HrFromLastWin32Error(); goto Error; }
hr = pncc->GetBindName(&pszBindName); if (FAILED(hr)) { goto Error; }
// Replace the instances of '-' and '{' with '0' so the constructed
// portname is of the form [a-zA-Z0-9]*@<Computer Name> and is less
// than MAX_ZONE_NAME_LEN long.
psz = pszBindName; while (*psz) { if ((*psz == L'-') || (*psz == L'{')) { *psz = L'0'; } psz++; }
*pstr = pszBindName; if (pstr->size() + 1 + dwSize > MAX_ZONE_NAME_LEN) { pstr->resize(MAX_ZONE_NAME_LEN - (dwSize + 1)); }
*pstr += c_chAt; *pstr += szComputerName; Assert( MAX_ZONE_NAME_LEN >= pstr->size());
Error: CoTaskMemFree(pszBindName); TraceError("HrPortNameFromAdapter",hr); return hr; }
HRESULT CATlkObj::HrAtlkReconfig() { CServiceManager csm; CService svr; HRESULT hr = S_OK; HRESULT hrRet; BOOL fDirty = FALSE; CAdapterInfo * pAI; CAdapterInfo * pAIDefault = NULL; ATLK_ADAPTER_INFO_LIST::iterator iter; ATALK_PNP_EVENT Config;
if (m_pATLKEnv->AdapterInfoList().empty()) { return hr; }
ZeroMemory(&Config, sizeof(Config));
// If routing changed notify appletalk and return. No need to do the
// per adapter notifications.
if (m_pATLKEnv->FRouterChanged()) { // notify atlk
Config.PnpMessage = AT_PNP_SWITCH_ROUTING; hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, c_szEmpty, &Config, sizeof(ATALK_PNP_EVENT)); if (FAILED(hrRet) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet)) { hr = NETCFG_S_REBOOT; }
m_pATLKEnv->SetRouterChanged(FALSE);
return hr; }
// Find the default adapter and also if any adapter's have changed
for (iter = m_pATLKEnv->AdapterInfoList().begin(); iter != m_pATLKEnv->AdapterInfoList().end(); iter++) { pAI = *iter;
tstring strPortName = c_szDevice; strPortName += pAI->SzBindName();
if (pAI->FDeletePending() || pAI->FDisabled()) { continue; }
// Locate the default port
if (0 == _wcsicmp(strPortName.c_str(), m_pATLKEnv->SzDefaultPort())) { pAIDefault = pAI; }
if (pAI->IsDirty()) { fDirty = TRUE; } }
if ((NULL != pAIDefault) && m_pATLKEnv->FDefAdapterChanged()) { // notify atlk
Config.PnpMessage = AT_PNP_SWITCH_DEFAULT_ADAPTER; hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, NULL, &Config, sizeof(ATALK_PNP_EVENT)); if (FAILED(hrRet) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet)) { hr = NETCFG_S_REBOOT; }
// Clear the dirty state
m_pATLKEnv->SetDefAdapterChanged(FALSE); pAIDefault->SetDirty(FALSE); }
Config.PnpMessage = AT_PNP_RECONFIGURE_PARMS; for (iter = m_pATLKEnv->AdapterInfoList().begin(); iter != m_pATLKEnv->AdapterInfoList().end(); iter++) { pAI = *iter;
if (pAI->FDeletePending() || pAI->FDisabled()) { continue; }
if (pAI->IsDirty()) { // Now submit the reconfig notification
hrRet = HrSendNdisPnpReconfig(NDIS, c_szAtlk, pAI->SzBindName(), &Config, sizeof(ATALK_PNP_EVENT)); if (FAILED(hrRet) && (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrRet)) { hr = NETCFG_S_REBOOT; }
// Clear the dirty state
pAI->SetDirty(FALSE); } }
TraceError("CATLKObj::HrAtlkReconfig",hr); return hr; }
|