//+---------------------------------------------------------------------------
//
//  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))
                {
                    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 (SUCCEEDED(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:   HrGetRegInstanceKeyForAdapter
//
//  Purpose:    Get the path to the PnP Instance key for a given adapter.
//
//  Arguments:
//              IN LPGUID pguidId           -  Guid for the Adapter
//              OUT LPWSTR lpszRegInstance  -  String containing regpath to the
//                                             the adapter's instance key.
//  Returns:    HRESULT indicating success or failure
//
//  Author:     ckotze   11 Jan 2001
//
//  Notes:      
//              
//  
//              
//
HRESULT HrGetRegInstanceKeyForAdapter(IN LPGUID pguidId, OUT LPWSTR lpszRegInstance)
{
    HRESULT hr = E_FAIL;
    HKEY hkeyNetworkAdapters;
    WCHAR szSubKey[MAX_PATH];
    DWORD cchSubKey = MAX_PATH;
    
    hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyNetworkAdapters, KEY_READ, &hkeyNetworkAdapters);
    if (SUCCEEDED(hr))
    {
        DWORD dwIndex = 0;

        wcscpy(lpszRegInstance, c_szRegKeyNetworkAdapters);
        wcscat(lpszRegInstance, L"\\");

        while (hr = HrRegEnumKey(hkeyNetworkAdapters, dwIndex++, szSubKey, cchSubKey) == S_OK)
        {
            HKEY hkeySubKey;

            hr = HrRegOpenKeyEx(hkeyNetworkAdapters, szSubKey, KEY_READ, &hkeySubKey);
            if (SUCCEEDED(hr))
            {
                WCHAR szValue[MAX_PATH];
                WCHAR szGuid[MAX_PATH];
                DWORD dwType = REG_SZ;
                DWORD cchData = MAX_PATH;

                StringFromGUID2(*pguidId, szGuid, MAX_PATH);

                HrRegQueryValueEx(hkeySubKey, c_szRegValueNetCfgInstanceId, &dwType, reinterpret_cast<LPBYTE>(szValue), &cchData);

                if (wcscmp(szValue, szGuid) == 0)
                {
                    wcscat(lpszRegInstance, szSubKey);
                    RegCloseKey(hkeySubKey);
                    hr = S_OK;
                    break;
                }
            }
            RegCloseKey(hkeySubKey);
        }
        RegCloseKey(hkeyNetworkAdapters);
    }
    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);

    if (ERROR_SUCCESS == 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;
}