|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: L A N C M N . C P P
//
// Contents: Implementation of LAN Connection related functions common
// to the shell and netman.
//
// Notes:
//
// Author: danielwe 7 Oct 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include <winsock2.h>
#include <mswsock.h>
#include <iphlpapi.h>
#include "lancmn.h"
#include "ncnetcfg.h"
#include "ncnetcon.h"
#include "ncreg.h"
#include "ncstring.h"
#include "netconp.h"
#include "ndispnp.h"
#include "naming.h"
extern const DECLSPEC_SELECTANY WCHAR c_szConnName[] = L"Name"; extern const DECLSPEC_SELECTANY WCHAR c_szRegKeyConFmt[] = L"System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection"; extern const DECLSPEC_SELECTANY WCHAR c_szRegKeyIrdaFmt[] = L"System\\CurrentControlSet\\Control\\Network\\{6BDD1FC5-810F-11D0-BEC7-08002BE2092F}\\%s\\Connection"; extern const DECLSPEC_SELECTANY WCHAR c_szRegKeyHwConFmt[] = L"System\\CurrentControlSet\\Control\\Network\\Connections\\%s"; extern const DECLSPEC_SELECTANY WCHAR c_szRegValuePnpInstanceId[] = L"PnpInstanceID"; extern const DECLSPEC_SELECTANY WCHAR c_szRegKeyNetworkAdapters[] = L"System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"; extern const DECLSPEC_SELECTANY WCHAR c_szRegValueNetCfgInstanceId[] = L"NetCfgInstanceId"; extern const DECLSPEC_SELECTANY WCHAR c_szRegValueMediaSubType[] = L"MediaSubType";
//
// Helper functions
//
//+---------------------------------------------------------------------------
//
// Function: HrOpenConnectionKey
//
// Purpose: Opens the "Connection" subkey under the gievn connection
// GUID.
//
// Arguments:
// pguid [in] GUID of net card in use by the connection
// pszGuid [in] String version of GUID of net card in use by
// the connection
// sam [in] SAM desired
// occFlags [in] Flags determining how to open the key
// pszPnpId [in] The Pnp id of the net card in use by the
// connection. This is used if the key is created.
// phkey [out] Returns hkey of connection subkey
//
// Returns: S_OK if success, OLE or Win32 error otherwise.
//
// Author: danielwe 7 Oct 1997
//
// Notes: Only pguid or pszGuid should be specified, not both. Specifying
// both will result in an E_INVALIDARG error
//
//
HRESULT HrOpenConnectionKey ( IN const GUID* pguid, IN PCWSTR pszGuid, IN REGSAM sam, IN OCC_FLAGS occFlags, IN PCWSTR pszPnpId, OUT HKEY *phkey) { HRESULT hr = S_OK; WCHAR szRegPath[256]; WCHAR szGuid[c_cchGuidWithTerm];
Assert(phkey); Assert(pguid || (pszGuid && *pszGuid)); Assert(!(pguid && pszGuid)); Assert (FImplies (OCCF_CREATE_IF_NOT_EXIST == occFlags, pszPnpId && *pszPnpId));
*phkey = NULL;
if (pguid) { StringFromGUID2(*pguid, szGuid, c_cchGuidWithTerm); pszGuid = szGuid; }
wsprintfW(szRegPath, c_szRegKeyConFmt, pszGuid);
if (occFlags & OCCF_CREATE_IF_NOT_EXIST) { DWORD dwDisp;
hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, szRegPath, 0, sam, NULL, phkey, &dwDisp);
if ((S_OK == hr)) { DWORD dwMediaSubType; // Store the pnp instance id as our back pointer to the pnp tree.
//
hr = HrRegSetSz (*phkey, c_szRegValuePnpInstanceId, pszPnpId);
TraceError("HrRegSetSz in HrOpenConnectionKey failed.", hr); HRESULT hrT = HrRegQueryDword(*phkey, c_szRegValueMediaSubType, &dwMediaSubType); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hrT) { CIntelliName inName(NULL, NULL); NETCON_MEDIATYPE ncMediaType = NCM_NONE; NETCON_SUBMEDIATYPE ncMediaSubType = NCSM_NONE; hrT = inName.HrGetPseudoMediaTypes(*pguid, &ncMediaType, &ncMediaSubType); if (SUCCEEDED(hrT) && (NCSM_LAN != ncMediaSubType) ) { hrT = HrRegSetDword(*phkey, c_szRegValueMediaSubType, ncMediaSubType); } } TraceError("Could not set media subtype for adapter", hrT); } } else if (occFlags & OCCF_DELETE_IF_EXIST) { if (wcslen(szGuid) > 0) { wcscpy(szRegPath, c_szRegKeyNetworkAdapters); wcscat(szRegPath, L"\\"); wcscat(szRegPath, szGuid); hr = HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, szRegPath); } } else { hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, sam, phkey); }
TraceErrorOptional("HrOpenConnectionKey", hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrOpenHwConnectionKey
//
// Purpose: Opens the per-hardware profile registry key for this connection
//
// Arguments:
// refGuid [in] GUID of net card in use by the connection
// sam [in] SAM desired
// occFlags [in] Flags determining how to open the key
// phkey [out] Returns hkey of connection subkey
//
// Returns: S_OK if success, OLE or Win32 error otherwise.
//
// Author: danielwe 9 Oct 1997
//
// Notes:
//
HRESULT HrOpenHwConnectionKey( REFGUID refGuid, REGSAM sam, OCC_FLAGS occFlags, HKEY *phkey) { HRESULT hr = S_OK; WCHAR szRegPath[256]; WCHAR szGuid[c_cchGuidWithTerm];
Assert(phkey);
*phkey = NULL;
StringFromGUID2(refGuid, szGuid, c_cchGuidWithTerm); wsprintfW(szRegPath, c_szRegKeyHwConFmt, szGuid);
if (occFlags & OCCF_CREATE_IF_NOT_EXIST) { DWORD dwDisp;
hr = HrRegCreateKeyEx(HKEY_CURRENT_CONFIG, szRegPath, 0, sam, NULL, phkey, &dwDisp); } else { hr = HrRegOpenKeyEx(HKEY_CURRENT_CONFIG, szRegPath, sam, phkey); }
TraceError("HrOpenHwConnectionKey", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrIsConnectionNameUnique
//
// Purpose: Returns whether or not the given connection name is unique.
//
// Arguments:
// guidExclude [in,ref] Device GUID of Connection to exclude from
// consideration (can be {0})
// pszName [in] Name to verify for uniqueness
//
// Returns: S_OK if name is unique, S_FALSE if it is a duplicate, or OLE
// or Win32 error otherwise
//
// Author: danielwe 14 Nov 1997
//
// Notes:
//
HRESULT HrIsConnectionNameUnique( REFGUID guidExclude, PCWSTR pszName) { Assert(pszName);
BOOL fDupe = FALSE;
// Iterate all LAN connections
//
INetConnectionManager * pconMan; HRESULT hr = HrCreateInstance(CLSID_LanConnectionManager, CLSCTX_SERVER | CLSCTX_NO_CODE_DOWNLOAD, &pconMan);
TraceHr(ttidError, FAL, hr, FALSE, "HrCreateInstance");
if (SUCCEEDED(hr)) { CIterNetCon ncIter(pconMan, NCME_DEFAULT); INetConnection * pconn; while (SUCCEEDED(hr) && !fDupe && (S_OK == (ncIter.HrNext(&pconn)))) { // Exclude if GUID passed in matches this connection's GUID.
//
if (!FPconnEqualGuid(pconn, guidExclude)) { NETCON_PROPERTIES* pProps; hr = pconn->GetProperties(&pProps); if (SUCCEEDED(hr)) { AssertSz(pProps->pszwName, "NULL pszwName!");
if (!lstrcmpiW(pProps->pszwName, pszName)) { // Names match.. This is a dupe.
fDupe = TRUE; }
FreeNetconProperties(pProps); } }
ReleaseObj(pconn); } ReleaseObj(pconMan); }
if (SUCCEEDED(hr)) { hr = fDupe ? S_FALSE : S_OK; }
TraceErrorOptional("HrIsConnectionNameUnique", hr, (S_FALSE == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrLanConnectionNameFromGuidOrPath
//
// Purpose: Retrieves the display-name of a LAN connection given its GUID.
//
// Arguments:
// guid [in] GUID of net card in question
// pszPath [in] Bind path that contains the GUID of the net
// card in question
// pszName [out] receives the retrieved name
// pcchMax [inout] indicates the capacity of 'pszName' on input,
// contains the required capacity on output.
//
// Returns: S_OK if success, OLE or Win32 error otherwise.
//
// Author: aboladeg 30 May 1998
//
// Notes: Only pguid or pszGuidPath should be specified, not both.
// Specifying both will result in an E_INVALIDARG error
//
EXTERN_C HRESULT WINAPI HrLanConnectionNameFromGuidOrPath( const GUID* pguid, PCWSTR pszPath, PWSTR pszName, LPDWORD pcchMax) { HRESULT hr = S_OK;
Assert(pcchMax);
// If neither a guid nor a path was specified then return an error.
//
if (!pguid && (!pszPath || !*pszPath)) { hr = E_INVALIDARG; } // If both pguid and a path were specified then return an error.
//
else if (pguid && (pszPath && *pszPath)) { hr = E_INVALIDARG; } else { WCHAR szGuid [c_cchGuidWithTerm]; PCWSTR pszGuid = NULL;
// If we don't have pguid, it means we are to parset if from
// pszPath.
//
if (!pguid) { Assert(pszPath && *pszPath);
// Search for the beginning brace of the supposed GUID and
// copy the remaining characters into szGuid.
// If no guid is found, return file not found since
// there will be no connection name found.
//
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); for (const WCHAR* pch = pszPath; *pch; pch++) { if (*pch == L'{') { wcsncpy (szGuid, pch, celems(szGuid)-1); szGuid[celems(szGuid)-1] = 0; pszGuid = szGuid; hr = S_OK; break; } } }
if (S_OK == hr) { HKEY hkey;
hr = HrOpenConnectionKey(pguid, pszGuid, KEY_READ, OCCF_NONE, NULL, &hkey); if (S_OK == hr) { DWORD dwType;
*pcchMax *= sizeof(WCHAR); hr = HrRegQueryValueEx(hkey, c_szConnName, &dwType, (LPBYTE)pszName, pcchMax); *pcchMax /= sizeof(WCHAR);
RegCloseKey(hkey); } } }
TraceError("HrLanConnectionNameFromGuid", (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ? S_OK : hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrPnccFromGuid
//
// Purpose: Given a GUID of an adapter, returns the INetCfgComponent
// that corresponds to it.
//
// Arguments:
// pnc [in] INetCfg to work with
// refGuid [in] GUID of adapter to look for
// ppncc [out] Returns INetCfgComponent already AddRef'd
//
// Returns: S_OK if found, S_FALSE if not (out param will be NULL), or
// OLE or Win32 error otherwise
//
// Author: danielwe 6 Nov 1997
//
// Notes: Caller should ReleaseObj the returned pointer
//
HRESULT HrPnccFromGuid(INetCfg *pnc, const GUID &refGuid, INetCfgComponent **ppncc) { HRESULT hr = S_OK;
Assert(pnc);
if (!ppncc) { hr = E_POINTER; } else { *ppncc = NULL;
BOOL fFound = FALSE; CIterNetCfgComponent nccIter(pnc, &GUID_DEVCLASS_NET); INetCfgComponent * pncc;
while (!fFound && SUCCEEDED(hr) && S_OK == (hr = nccIter.HrNext(&pncc))) { GUID guidTest;
hr = pncc->GetInstanceGuid(&guidTest); if (S_OK == hr) { if (guidTest == refGuid) { // Found our adapter
fFound = TRUE;
// Give another reference so it's not released down below
AddRefObj(pncc); *ppncc = pncc; Assert (S_OK == hr); } }
ReleaseObj(pncc); }
if (SUCCEEDED(hr) && !fFound) { hr = S_FALSE; } }
TraceErrorOptional("HrPnccFromGuid", hr, (S_FALSE == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrIsConnection
//
// Purpose: Determines whether the given component has an associated
// LAN connection.
//
// Arguments:
// pncc [in] Component to test
//
// Returns: S_OK if it does, S_FALSE if not, otherwise a Win32 error code
//
// Author: danielwe 2 Oct 1997
//
// Notes:
//
HRESULT HrIsConnection(INetCfgComponent *pncc) { HRESULT hr = S_FALSE; GUID guid;
Assert(pncc);
// Get the component instance GUID
//
hr = pncc->GetInstanceGuid(&guid); if (SUCCEEDED(hr)) { HKEY hkey;
// Check for the existence of the connection sub-key
hr = HrOpenConnectionKey(&guid, NULL, KEY_READ, OCCF_NONE, NULL, &hkey); if (SUCCEEDED(hr)) { RegCloseKey(hkey); } else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { // Key not there, return FALSE
hr = S_FALSE; } }
TraceErrorOptional("HrIsConnection", hr, (S_FALSE == hr)); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetDeviceGuid
//
// Purpose: Given a LAN connection object, returns the device GUID
// associated with it.
//
// Arguments:
// pconn [in] LAN connection object
// pguid [out] Returns device GUID
//
// Returns: S_OK if success, OLE or Win32 error if failed
//
// Author: danielwe 23 Dec 1997
//
// Notes:
//
HRESULT HrGetDeviceGuid(INetConnection *pconn, GUID *pguid) { HRESULT hr = S_OK; INetLanConnection * plan = NULL;
Assert(pguid);
hr = HrQIAndSetProxyBlanket(pconn, &plan);
if (SUCCEEDED(hr)) { hr = plan->GetDeviceGuid(pguid);
ReleaseObj(plan); }
TraceError("HrGetDeviceGuid", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: FPconnEqualGuid
//
// Purpose: Determines if the given connection's device GUID matches the
// guid passed in.
//
// Arguments:
// pconn [in] Connection object to examine (must be a LAN connection)
// guid [in,ref] Guid to compare with
//
// Returns: TRUE if connection's device guid matches passed in guid, FALSE
// if not.
//
// Author: danielwe 23 Dec 1997
//
// Notes:
//
BOOL FPconnEqualGuid(INetConnection *pconn, REFGUID guid) { HRESULT hr = S_OK; GUID guidDev; BOOL fRet = FALSE;
hr = HrGetDeviceGuid(pconn, &guidDev); if (SUCCEEDED(hr)) { fRet = (guidDev == guid); }
TraceError("FPconnEqualGuid", hr); return fRet; }
//+---------------------------------------------------------------------------
//
// Function: HrPnpInstanceIdFromGuid
//
// Purpose: Given a GUID of a network device, returns its PnP Instance ID
//
// Arguments:
// pguid [in] NetCfg instance GUID of device
// pszInstance [out] PnP instance ID (string)
//
// Returns: S_OK if success, Win32 error code otherwise
//
// Author: danielwe 30 Oct 1998
//
// Notes:
//
HRESULT HrPnpInstanceIdFromGuid( const GUID* pguid, PWSTR pszInstance, UINT cchInstance) { HRESULT hr = S_OK; WCHAR szRegPath[MAX_PATH]; HKEY hkey; DWORD cb; WCHAR szGuid[c_cchGuidWithTerm];
StringFromGUID2(*pguid, szGuid, c_cchGuidWithTerm);
wsprintfW(szRegPath, c_szRegKeyConFmt, szGuid);
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, KEY_READ, &hkey); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) { wsprintfW(szRegPath, c_szRegKeyIrdaFmt, szGuid); hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegPath, KEY_READ, &hkey); }
if (S_OK == hr) { cb = cchInstance * sizeof(WCHAR);
hr = HrRegQuerySzBuffer(hkey, c_szRegValuePnpInstanceId, pszInstance, &cb); RegCloseKey(hkey); } #ifdef ENABLETRACE
if (FAILED(hr)) { TraceHr (ttidError, FAL, hr, IsEqualGUID(*pguid, GUID_NULL), "HrPnpInstanceIdFromGuid " "failed getting id for %S", szGuid); } #endif
TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr, "HrPnpInstanceIdFromGuid"); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetPnpDeviceStatus
//
// Purpose: Given a network device GUID, returns its status
//
// Arguments:
// pguid [in] NetCfg instance GUID of network device
// pStatus [out] Status of device
//
// Returns: S_OK if success, Win32 error code otherwise
//
// Author: danielwe 30 Oct 1998
//
// Notes:
//
EXTERN_C HRESULT WINAPI HrGetPnpDeviceStatus( const GUID* pguid, NETCON_STATUS *pStatus) { HRESULT hr = S_OK;
if (!pStatus || !pguid) { hr = E_POINTER; goto err; }
WCHAR szInstance[MAX_PATH];
hr = HrPnpInstanceIdFromGuid(pguid, szInstance, celems(szInstance)); if (SUCCEEDED(hr)) { DEVINST devinst; CONFIGRET cr;
cr = CM_Locate_DevNode(&devinst, szInstance, CM_LOCATE_DEVNODE_NORMAL); if (CR_SUCCESS == cr) { hr = HrGetDevInstStatus(devinst, pguid, pStatus); } else if (CR_NO_SUCH_DEVNODE == cr) { // If the devnode doesn't exist, the hardware is not physically
// present
//
*pStatus = NCS_HARDWARE_NOT_PRESENT; } }
err: TraceError("HrGetPnpDeviceStatus", hr); return hr; }
extern const WCHAR c_szDevice[];
//+---------------------------------------------------------------------------
//
// Function: HrQueryLanMediaState
//
// Purpose: Determines as best as can be basically whether the cable is
// plugged in to the network card.
//
// Arguments:
// pguid [in] GUID of device to tes
// pfEnabled [out] Returns TRUE if media is connected, FALSE if not
//
// Returns: S_OK if success, Win32 error otherwise
//
// Author: danielwe 13 Nov 1998
//
// Notes:
//
EXTERN_C HRESULT WINAPI HrQueryLanMediaState( const GUID* pguid, BOOL* pfEnabled) { HRESULT hr = S_OK;
if (!pfEnabled) { hr = E_POINTER; } else { UINT uiRet = 0; NIC_STATISTICS nsNewLanStats = {0}; tstring strDevice; UNICODE_STRING ustrDevice; WCHAR szGuid[c_cchGuidWithTerm];
// Initialize to TRUE
//
*pfEnabled = TRUE;
StringFromGUID2(*pguid, szGuid, c_cchGuidWithTerm);
strDevice = c_szDevice; strDevice.append(szGuid);
RtlInitUnicodeString(&ustrDevice, strDevice.c_str());
nsNewLanStats.Size = sizeof(NIC_STATISTICS); uiRet = NdisQueryStatistics(&ustrDevice, &nsNewLanStats); if (uiRet) { *pfEnabled = (nsNewLanStats.MediaState == MEDIA_STATE_CONNECTED); } else { hr = HrFromLastWin32Error(); } }
TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr, "HrQueryLanMediaState"); return hr; }
//+---------------------------------------------------------------------------
//
// Function: FIsMediaPresent
//
// Purpose: Determines as best as can be basically whether the cable is
// plugged in to the network card.
//
// Arguments:
// pGuid [in] GUID of device to test
//
// Returns: TRUE if media is connected, FALSE otherwise
//
// Author: danielwe 30 Oct 1998
//
// Notes:
//
BOOL FIsMediaPresent( const GUID *pguid) { BOOL fEnabled;
if (SUCCEEDED(HrQueryLanMediaState(pguid, &fEnabled))) { return fEnabled; }
// Assume media is connected on failure
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: HrGetDevInstStatus
//
// Purpose: Determines status of the given Pnp device instance
//
// Arguments:
// devinst [in] PnP device instance
// pGuid [in] GUID of said device
// pStatus [out] Status of device
//
// Returns: S_OK if success, Win32 error code otherwise
//
// Author: danielwe 30 Oct 1998
//
// Notes:
//
HRESULT HrGetDevInstStatus( DEVINST devinst, const GUID* pguid, NETCON_STATUS* pStatus) { HRESULT hr = S_OK; ULONG ulStatus; ULONG ulProblem; CONFIGRET cfgRet;
if (!pguid) { return E_INVALIDARG; }
if (!pStatus) { return E_POINTER; }
cfgRet = CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblem, devinst, 0, NULL);
if (CR_SUCCESS == cfgRet) { TraceTag(ttidLanCon, "CM_Get_DevNode_Status_Ex: ulProblem " "= 0x%08X, ulStatus = 0x%08X.", ulProblem, ulStatus);
switch (ulProblem) { case 0: // No problem, we're connected
*pStatus = NCS_CONNECTED; break;
case CM_PROB_DEVICE_NOT_THERE: case CM_PROB_MOVED: // Device not present
*pStatus = NCS_HARDWARE_NOT_PRESENT; break;
case CM_PROB_HARDWARE_DISABLED: // Device was disabled via Device Manager
*pStatus = NCS_HARDWARE_DISABLED; break;
case CM_PROB_DISABLED: // Device was disconnected
*pStatus = NCS_DISCONNECTED; break;
default: // All other problems
*pStatus = NCS_HARDWARE_MALFUNCTION; break; }
if (*pStatus == NCS_CONNECTED) { // Check DeviceState and MediaState from NdisQueryStatistics
UINT uiRet = 0; NIC_STATISTICS nsNewLanStats = {0}; tstring strDevice; UNICODE_STRING ustrDevice; WCHAR szGuid[c_cchGuidWithTerm];
StringFromGUID2(*pguid, szGuid, c_cchGuidWithTerm);
strDevice = c_szDevice; strDevice.append(szGuid);
RtlInitUnicodeString(&ustrDevice, strDevice.c_str());
nsNewLanStats.Size = sizeof(NIC_STATISTICS); uiRet = NdisQueryStatistics(&ustrDevice, &nsNewLanStats);
if (uiRet) { // Check MediaState
if (nsNewLanStats.MediaState == MEDIA_STATE_DISCONNECTED) { TraceTag(ttidLanCon, "NdisQueryStatistics reports MediaState of " "device %S is disconnected.", szGuid);
*pStatus = NCS_MEDIA_DISCONNECTED; } else { HRESULT hrTmp;
BOOL fValidAddress = TRUE;
hrTmp = HrGetAddressStatusForAdapter(pguid, &fValidAddress); if (SUCCEEDED(hrTmp)) { if (!fValidAddress) { *pStatus = NCS_INVALID_ADDRESS;
INetCfg *pNetCfg = NULL; BOOL fInitCom = TRUE;
HRESULT hrT = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_MULTITHREADED); if (RPC_E_CHANGED_MODE == hrT) { hrT = S_OK; fInitCom = FALSE; }
if (SUCCEEDED(hrT)) { HRESULT hrT = HrCreateAndInitializeINetCfg(NULL, &pNetCfg, FALSE, 0, NULL, NULL); if (SUCCEEDED(hrT)) { INetCfgComponent *pNetCfgComponent = NULL; hrT = HrPnccFromGuid(pNetCfg, *pguid, &pNetCfgComponent); if (S_OK == hrT) { DWORD dwCharacteristics = 0; pNetCfgComponent->GetCharacteristics(&dwCharacteristics);
if (NCF_VIRTUAL & dwCharacteristics) { *pStatus = NCS_CONNECTED;
TraceTag(ttidLanCon, "NCS_INVALID_ADDRESS status ignored for NCF_VIRTUAL device: %S", szGuid); }
pNetCfgComponent->Release(); }
HrUninitializeAndReleaseINetCfg(FALSE, pNetCfg, FALSE); } if (fInitCom) { CoUninitialize(); } } TraceError("Error retrieving adapter Characteristics", hrT); } } } } else { // $REVIEW(tongl 11/25/98): This is added to display proper state
// for ATM ELAN virtual miniports (Raid #253972, 256355).
//
// If we get here for a physical adapter, this means NdisQueryStatistics
// returned different device state from CM_Get_DevNode_Status_Ex, we may
// have a problem.
hr = HrFromLastWin32Error();
if ((HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) && (nsNewLanStats.DeviceState == DEVICE_STATE_DISCONNECTED)) { Assert(nsNewLanStats.MediaState == MEDIA_STATE_UNKNOWN);
TraceTag(ttidLanCon, "NdisQueryStatistics reports DeviceState of " "device %S is disconnected.", szGuid);
*pStatus = NCS_DISCONNECTED; hr = S_OK; } else if (HRESULT_FROM_WIN32(ERROR_NOT_READY) == hr) { // This error means that the device went into power
// management induced sleep and so we should report this
// case as media disconnected, not connection disconnected
TraceTag(ttidLanCon, "NdisQueryStatistics reports device" " %S is asleep. Returning status of media " "disconnected.", szGuid);
*pStatus = NCS_MEDIA_DISCONNECTED; hr = S_OK; } else if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr) { TraceTag(ttidLanCon, "NdisQueryStatistics reports device %S is still connecting.", szGuid);
*pStatus = NCS_CONNECTING; hr = S_OK; } else { // Treat as disconected, if we return failure the folder will
// not display this connection at all.
TraceHr (ttidLanCon, FAL, hr, FALSE, "NdisQueryStatistics reports error on device %S", szGuid);
*pStatus = NCS_DISCONNECTED; hr = S_OK; } } } }
TraceError("HrGetDevInstStatus", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HasValidAddress
//
// Purpose: Verifies that the given adapter has a valid address
//
// Arguments:
// IN PIP_ADAPTER_INFO pAdapterInfo - Adapter Info structure
// containing addresses
//
// Returns: True if Valid address, False otherwise
//
// Author: ckotze 11 Jan 2001
//
// Notes:
//
//
//
BOOL HasValidAddress(IN PIP_ADAPTER_INFO pAdapterInfo) { PIP_ADDR_STRING pAddrString; unsigned int addr;
TraceFileFunc(ttidConman);
for(pAddrString = &pAdapterInfo->IpAddressList; pAddrString != NULL; pAddrString = pAddrString->Next) { TraceTag(ttidConman, "IP Address: %s", pAddrString->IpAddress.String);
addr = inet_addr(pAddrString->IpAddress.String); if(!addr) { return FALSE; } }
return TRUE; }
//+---------------------------------------------------------------------------
//
// Function: HrGetAddressStatusForAdapter
//
// Purpose: Verifies that the given adapter has a valid address
//
// Arguments:
// IN LPCGUID pguidAdapter - Guid for the adapter
// OUT BOOL* pbValidAddress - BOOL indicating if it has
// has Valid Address
//
// Returns: True if Valid address, False otherwise
//
// Author: ckotze 11 Jan 2001
//
// Notes:
//
//
//
HRESULT HrGetAddressStatusForAdapter(IN LPCGUID pguidAdapter, OUT BOOL* pbValidAddress) { HRESULT hr = E_FAIL; GUID guidId = GUID_NULL; PIP_ADAPTER_INFO pAdapterInfo = NULL; PIP_ADAPTER_INFO pAdapters = NULL; ULONG ulSize = 0; PIP_ADAPTER_INFO p = NULL; WCHAR lpszInstanceId[50]; WCHAR szAdapterGUID[MAX_PATH]; WCHAR szAdapterID[MAX_PATH];
if (!pguidAdapter) { return E_INVALIDARG; } if (!pbValidAddress) { return E_POINTER; }
ZeroMemory(szAdapterGUID, sizeof(WCHAR)*MAX_PATH); ZeroMemory(szAdapterID, sizeof(WCHAR)*MAX_PATH);
StringFromGUID2(*pguidAdapter, szAdapterGUID, MAX_PATH);
// GetAdaptersInfo returns ERROR_BUFFER_OVERFLOW when it is filling in the size
if ( ERROR_BUFFER_OVERFLOW == GetAdaptersInfo(NULL, &ulSize) ) { pAdapters = reinterpret_cast<PIP_ADAPTER_INFO>(new BYTE[ulSize]); if (pAdapters) { if(ERROR_SUCCESS == GetAdaptersInfo(pAdapters, &ulSize)) { for (p = pAdapters; p != NULL; p = p->Next) { MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, p->AdapterName, strlen(p->AdapterName), szAdapterID, MAX_PATH); if (wcscmp(szAdapterGUID, szAdapterID) == 0) { TraceTag(ttidConman, "Found Adapter: %s", p->AdapterName); pAdapterInfo = p;
*pbValidAddress = HasValidAddress(pAdapterInfo);
hr = S_OK;
TraceTag(ttidConman, "Valid Address: %s", (*pbValidAddress) ? "Yes" : "No"); TraceTag(ttidConman, "DHCP: %s", (pAdapterInfo->DhcpEnabled) ? "Yes" : "No"); } } } delete[] reinterpret_cast<BYTE*>(pAdapters); } else { hr = E_OUTOFMEMORY; } }
return hr; }
HRESULT HrGetPseudoMediaTypeFromConnection(IN REFGUID guidConn, OUT NETCON_SUBMEDIATYPE *pncsm) { HRESULT hr = S_OK; HKEY hkeyConnection;
hr = HrOpenConnectionKey(&guidConn, NULL, KEY_READ, OCCF_NONE, NULL, &hkeyConnection);
if (SUCCEEDED(hr)) { DWORD dwMediaSubType;
hr = HrRegQueryDword(hkeyConnection, c_szRegValueMediaSubType, &dwMediaSubType); if (SUCCEEDED(hr)) { *pncsm = static_cast<NETCON_SUBMEDIATYPE>(dwMediaSubType); } else { *pncsm = NCSM_LAN; } RegCloseKey(hkeyConnection); }
return hr; }
|