mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00

- Create a branch to do a proper merge of USB work from a trunk base instead of from cmake-bringup - In the future, DO NOT under any circumstances branch another branch. This leads to merge problems! svn path=/branches/usb-bringup-trunk/; revision=55018
773 lines
19 KiB
C
773 lines
19 KiB
C
#include <precomp.h>
|
|
|
|
typedef struct tagINetConnectionItem
|
|
{
|
|
struct tagINetConnectionItem * Next;
|
|
DWORD dwAdapterIndex;
|
|
NETCON_PROPERTIES Props;
|
|
}INetConnectionItem, *PINetConnectionItem;
|
|
|
|
typedef struct
|
|
{
|
|
const INetConnectionManagerVtbl * lpVtbl;
|
|
const IEnumNetConnectionVtbl * lpVtblNetConnection;
|
|
LONG ref;
|
|
PINetConnectionItem pHead;
|
|
PINetConnectionItem pCurrent;
|
|
|
|
} INetConnectionManagerImpl, *LPINetConnectionManagerImpl;
|
|
|
|
typedef struct
|
|
{
|
|
const INetConnectionVtbl * lpVtbl;
|
|
LONG ref;
|
|
NETCON_PROPERTIES Props;
|
|
DWORD dwAdapterIndex;
|
|
} INetConnectionImpl, *LPINetConnectionImpl;
|
|
|
|
|
|
static __inline LPINetConnectionManagerImpl impl_from_EnumNetConnection(IEnumNetConnection *iface)
|
|
{
|
|
return (LPINetConnectionManagerImpl)((char *)iface - FIELD_OFFSET(INetConnectionManagerImpl, lpVtblNetConnection));
|
|
}
|
|
|
|
VOID NormalizeOperStatus(MIB_IFROW *IfEntry, NETCON_PROPERTIES * Props);
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnectionManager_fnQueryInterface(
|
|
INetConnectionManager * iface,
|
|
REFIID iid,
|
|
LPVOID * ppvObj)
|
|
{
|
|
INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID (iid, &IID_IUnknown) ||
|
|
IsEqualIID (iid, &IID_INetConnectionManager))
|
|
{
|
|
*ppvObj = This;
|
|
INetConnectionManager_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
INetConnectionManager_fnAddRef(
|
|
INetConnectionManager * iface)
|
|
{
|
|
INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
INetConnectionManager_fnRelease(
|
|
INetConnectionManager * iface)
|
|
{
|
|
INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
|
|
ULONG refCount = InterlockedDecrement(&This->ref);
|
|
|
|
if (!refCount)
|
|
{
|
|
CoTaskMemFree (This);
|
|
}
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnectionManager_fnEnumConnections(
|
|
INetConnectionManager * iface,
|
|
NETCONMGR_ENUM_FLAGS Flags,
|
|
IEnumNetConnection **ppEnum)
|
|
{
|
|
INetConnectionManagerImpl * This = (INetConnectionManagerImpl*)iface;
|
|
|
|
if (!ppEnum)
|
|
return E_POINTER;
|
|
|
|
if (Flags != NCME_DEFAULT)
|
|
return E_FAIL;
|
|
|
|
*ppEnum = (IEnumNetConnection *)&This->lpVtblNetConnection;
|
|
INetConnectionManager_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static const INetConnectionManagerVtbl vt_NetConnectionManager =
|
|
{
|
|
INetConnectionManager_fnQueryInterface,
|
|
INetConnectionManager_fnAddRef,
|
|
INetConnectionManager_fnRelease,
|
|
INetConnectionManager_fnEnumConnections,
|
|
};
|
|
|
|
/***************************************************************
|
|
* INetConnection Interface
|
|
*/
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnQueryInterface(
|
|
INetConnection * iface,
|
|
REFIID iid,
|
|
LPVOID * ppvObj)
|
|
{
|
|
INetConnectionImpl * This = (INetConnectionImpl*)iface;
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID (iid, &IID_IUnknown) ||
|
|
IsEqualIID (iid, &IID_INetConnection))
|
|
{
|
|
*ppvObj = This;
|
|
INetConnection_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
INetConnection_fnAddRef(
|
|
INetConnection * iface)
|
|
{
|
|
INetConnectionImpl * This = (INetConnectionImpl*)iface;
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
INetConnection_fnRelease(
|
|
INetConnection * iface)
|
|
{
|
|
INetConnectionImpl * This = (INetConnectionImpl*)iface;
|
|
ULONG refCount = InterlockedDecrement(&This->ref);
|
|
|
|
if (!refCount)
|
|
{
|
|
CoTaskMemFree(This->Props.pszwName);
|
|
CoTaskMemFree(This->Props.pszwDeviceName);
|
|
CoTaskMemFree(This);
|
|
}
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnConnect(
|
|
INetConnection * iface)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnDisconnect(
|
|
INetConnection * iface)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnDelete(
|
|
INetConnection * iface)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnDuplicate(
|
|
INetConnection * iface,
|
|
LPCWSTR pszwDuplicateName,
|
|
INetConnection **ppCon)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnGetProperties(
|
|
INetConnection * iface,
|
|
NETCON_PROPERTIES **ppProps)
|
|
{
|
|
MIB_IFROW IfEntry;
|
|
HKEY hKey;
|
|
LPOLESTR pStr;
|
|
WCHAR szName[140];
|
|
DWORD dwShowIcon, dwType, dwSize;
|
|
NETCON_PROPERTIES * pProperties;
|
|
HRESULT hr;
|
|
|
|
INetConnectionImpl * This = (INetConnectionImpl*)iface;
|
|
|
|
if (!ppProps)
|
|
return E_POINTER;
|
|
|
|
pProperties = CoTaskMemAlloc(sizeof(NETCON_PROPERTIES));
|
|
if (!pProperties)
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
CopyMemory(pProperties, &This->Props, sizeof(NETCON_PROPERTIES));
|
|
pProperties->pszwName = NULL;
|
|
|
|
if (This->Props.pszwDeviceName)
|
|
{
|
|
pProperties->pszwDeviceName = CoTaskMemAlloc((wcslen(This->Props.pszwDeviceName)+1)*sizeof(WCHAR));
|
|
if (pProperties->pszwDeviceName)
|
|
wcscpy(pProperties->pszwDeviceName, This->Props.pszwDeviceName);
|
|
}
|
|
|
|
*ppProps = pProperties;
|
|
|
|
/* get updated adapter characteristics */
|
|
ZeroMemory(&IfEntry, sizeof(IfEntry));
|
|
IfEntry.dwIndex = This->dwAdapterIndex;
|
|
if(GetIfEntry(&IfEntry) != NO_ERROR)
|
|
return NOERROR;
|
|
|
|
NormalizeOperStatus(&IfEntry, pProperties);
|
|
|
|
|
|
hr = StringFromCLSID(&This->Props.guidId, &pStr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wcscpy(szName, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
|
|
wcscat(szName, pStr);
|
|
wcscat(szName, L"\\Connection");
|
|
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(dwShowIcon);
|
|
if (RegQueryValueExW(hKey, L"ShowIcon", NULL, &dwType, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS && dwType == REG_DWORD)
|
|
{
|
|
if (dwShowIcon)
|
|
pProperties->dwCharacter |= NCCF_SHOW_ICON;
|
|
else
|
|
pProperties->dwCharacter &= ~NCCF_SHOW_ICON;
|
|
}
|
|
dwSize = sizeof(szName);
|
|
if (RegQueryValueExW(hKey, L"Name", NULL, &dwType, (LPBYTE)szName, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
/* use updated name */
|
|
dwSize = wcslen(szName) + 1;
|
|
pProperties->pszwName = CoTaskMemAlloc(dwSize * sizeof(WCHAR));
|
|
if (pProperties->pszwName)
|
|
CopyMemory(pProperties->pszwName, szName, dwSize * sizeof(WCHAR));
|
|
}
|
|
else
|
|
{
|
|
/* use cached name */
|
|
if (This->Props.pszwName)
|
|
{
|
|
pProperties->pszwName = CoTaskMemAlloc((wcslen(This->Props.pszwName)+1)*sizeof(WCHAR));
|
|
if (pProperties->pszwName)
|
|
wcscpy(pProperties->pszwName, This->Props.pszwName);
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
CoTaskMemFree(pStr);
|
|
}
|
|
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnGetUiObjectClassId(
|
|
INetConnection * iface,
|
|
CLSID *pclsid)
|
|
{
|
|
|
|
INetConnectionImpl * This = (INetConnectionImpl*)iface;
|
|
|
|
if (This->Props.MediaType == NCM_LAN)
|
|
{
|
|
CopyMemory(pclsid, &CLSID_LANConnectUI, sizeof(CLSID));
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
INetConnection_fnRename(
|
|
INetConnection * iface,
|
|
LPCWSTR pszwDuplicateName)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
static const INetConnectionVtbl vt_NetConnection =
|
|
{
|
|
INetConnection_fnQueryInterface,
|
|
INetConnection_fnAddRef,
|
|
INetConnection_fnRelease,
|
|
INetConnection_fnConnect,
|
|
INetConnection_fnDisconnect,
|
|
INetConnection_fnDelete,
|
|
INetConnection_fnDuplicate,
|
|
INetConnection_fnGetProperties,
|
|
INetConnection_fnGetUiObjectClassId,
|
|
INetConnection_fnRename
|
|
};
|
|
|
|
HRESULT WINAPI IConnection_Constructor (INetConnection **ppv, PINetConnectionItem pItem)
|
|
{
|
|
INetConnectionImpl *This;
|
|
|
|
if (!ppv)
|
|
return E_POINTER;
|
|
|
|
This = (INetConnectionImpl *) CoTaskMemAlloc(sizeof (INetConnectionImpl));
|
|
if (!This)
|
|
return E_OUTOFMEMORY;
|
|
|
|
This->ref = 1;
|
|
This->lpVtbl = &vt_NetConnection;
|
|
This->dwAdapterIndex = pItem->dwAdapterIndex;
|
|
CopyMemory(&This->Props, &pItem->Props, sizeof(NETCON_PROPERTIES));
|
|
|
|
if (pItem->Props.pszwName)
|
|
{
|
|
This->Props.pszwName = CoTaskMemAlloc((wcslen(pItem->Props.pszwName)+1)*sizeof(WCHAR));
|
|
if (This->Props.pszwName)
|
|
wcscpy(This->Props.pszwName, pItem->Props.pszwName);
|
|
}
|
|
|
|
if (pItem->Props.pszwDeviceName)
|
|
{
|
|
This->Props.pszwDeviceName = CoTaskMemAlloc((wcslen(pItem->Props.pszwDeviceName)+1)*sizeof(WCHAR));
|
|
if (This->Props.pszwDeviceName)
|
|
wcscpy(This->Props.pszwDeviceName, pItem->Props.pszwDeviceName);
|
|
}
|
|
|
|
*ppv = (INetConnection *)This;
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/***************************************************************
|
|
* IEnumNetConnection Interface
|
|
*/
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
IEnumNetConnection_fnQueryInterface(
|
|
IEnumNetConnection * iface,
|
|
REFIID iid,
|
|
LPVOID * ppvObj)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID (iid, &IID_IUnknown) ||
|
|
IsEqualIID (iid, &IID_INetConnectionManager))
|
|
{
|
|
*ppvObj = This;
|
|
INetConnectionManager_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
IEnumNetConnection_fnAddRef(
|
|
IEnumNetConnection * iface)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
WINAPI
|
|
IEnumNetConnection_fnRelease(
|
|
IEnumNetConnection * iface)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
ULONG refCount = InterlockedDecrement(&This->ref);
|
|
|
|
if (!refCount)
|
|
{
|
|
CoTaskMemFree (This);
|
|
}
|
|
return refCount;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
IEnumNetConnection_fnNext(
|
|
IEnumNetConnection * iface,
|
|
ULONG celt,
|
|
INetConnection **rgelt,
|
|
ULONG *pceltFetched)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
HRESULT hr;
|
|
|
|
if (!pceltFetched || !rgelt)
|
|
return E_POINTER;
|
|
|
|
if (celt != 1)
|
|
return E_FAIL;
|
|
|
|
if (!This->pCurrent)
|
|
return S_FALSE;
|
|
|
|
hr = IConnection_Constructor(rgelt, This->pCurrent);
|
|
This->pCurrent = This->pCurrent->Next;
|
|
|
|
return hr;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
IEnumNetConnection_fnSkip(
|
|
IEnumNetConnection * iface,
|
|
ULONG celt)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
|
|
while(This->pCurrent && celt-- > 0)
|
|
This->pCurrent = This->pCurrent->Next;
|
|
|
|
if (celt)
|
|
return S_FALSE;
|
|
else
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
IEnumNetConnection_fnReset(
|
|
IEnumNetConnection * iface)
|
|
{
|
|
INetConnectionManagerImpl * This = impl_from_EnumNetConnection(iface);
|
|
|
|
This->pCurrent = This->pHead;
|
|
return NOERROR;
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
WINAPI
|
|
IEnumNetConnection_fnClone(
|
|
IEnumNetConnection * iface,
|
|
IEnumNetConnection **ppenum)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IEnumNetConnectionVtbl vt_EnumNetConnection =
|
|
{
|
|
IEnumNetConnection_fnQueryInterface,
|
|
IEnumNetConnection_fnAddRef,
|
|
IEnumNetConnection_fnRelease,
|
|
IEnumNetConnection_fnNext,
|
|
IEnumNetConnection_fnSkip,
|
|
IEnumNetConnection_fnReset,
|
|
IEnumNetConnection_fnClone
|
|
};
|
|
|
|
|
|
BOOL
|
|
GetAdapterIndexFromNetCfgInstanceId(PIP_ADAPTER_INFO pAdapterInfo, LPWSTR szNetCfg, PDWORD pIndex)
|
|
{
|
|
WCHAR szBuffer[50];
|
|
IP_ADAPTER_INFO * pCurrentAdapter;
|
|
|
|
pCurrentAdapter = pAdapterInfo;
|
|
while(pCurrentAdapter)
|
|
{
|
|
szBuffer[0] = L'\0';
|
|
if (MultiByteToWideChar(CP_ACP, 0, pCurrentAdapter->AdapterName, -1, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0])))
|
|
{
|
|
szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
|
|
}
|
|
if (!_wcsicmp(szBuffer, szNetCfg))
|
|
{
|
|
*pIndex = pCurrentAdapter->Index;
|
|
return TRUE;
|
|
}
|
|
pCurrentAdapter = pCurrentAdapter->Next;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
NormalizeOperStatus(
|
|
MIB_IFROW *IfEntry,
|
|
NETCON_PROPERTIES * Props)
|
|
{
|
|
switch(IfEntry->dwOperStatus)
|
|
{
|
|
case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
|
|
Props->Status = NCS_HARDWARE_DISABLED;
|
|
break;
|
|
case MIB_IF_OPER_STATUS_UNREACHABLE:
|
|
Props->Status = NCS_DISCONNECTED;
|
|
break;
|
|
case MIB_IF_OPER_STATUS_DISCONNECTED:
|
|
Props->Status = NCS_MEDIA_DISCONNECTED;
|
|
break;
|
|
case MIB_IF_OPER_STATUS_CONNECTING:
|
|
Props->Status = NCS_CONNECTING;
|
|
break;
|
|
case MIB_IF_OPER_STATUS_CONNECTED:
|
|
Props->Status = NCS_CONNECTED;
|
|
break;
|
|
case MIB_IF_OPER_STATUS_OPERATIONAL:
|
|
Props->Status = NCS_CONNECTED;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static
|
|
BOOL
|
|
EnumerateINetConnections(INetConnectionManagerImpl *This)
|
|
{
|
|
DWORD dwSize, dwResult, dwIndex, dwAdapterIndex, dwShowIcon;
|
|
MIB_IFTABLE *pIfTable;
|
|
MIB_IFROW IfEntry;
|
|
IP_ADAPTER_INFO * pAdapterInfo;
|
|
HDEVINFO hInfo;
|
|
SP_DEVINFO_DATA DevInfo;
|
|
HKEY hSubKey;
|
|
WCHAR szNetCfg[50];
|
|
WCHAR szAdapterNetCfg[50];
|
|
WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
|
|
WCHAR szName[130] = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
|
|
PINetConnectionItem pNew;
|
|
PINetConnectionItem pCurrent = NULL;
|
|
|
|
/* get the IfTable */
|
|
dwSize = 0;
|
|
if (GetIfTable(NULL, &dwSize, TRUE) != ERROR_INSUFFICIENT_BUFFER)
|
|
return FALSE;
|
|
|
|
pIfTable = (PMIB_IFTABLE)CoTaskMemAlloc(dwSize);
|
|
if (!pIfTable)
|
|
return FALSE;
|
|
|
|
dwResult = GetIfTable(pIfTable, &dwSize, TRUE);
|
|
if (dwResult != NO_ERROR)
|
|
{
|
|
CoTaskMemFree(pIfTable);
|
|
return FALSE;
|
|
}
|
|
|
|
dwSize = 0;
|
|
dwResult = GetAdaptersInfo(NULL, &dwSize);
|
|
if (dwResult!= ERROR_BUFFER_OVERFLOW)
|
|
{
|
|
CoTaskMemFree(pIfTable);
|
|
return FALSE;
|
|
}
|
|
|
|
pAdapterInfo = (PIP_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
|
|
if (!pAdapterInfo)
|
|
{
|
|
CoTaskMemFree(pIfTable);
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
|
|
{
|
|
CoTaskMemFree(pIfTable);
|
|
CoTaskMemFree(pAdapterInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
hInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
|
|
if (!hInfo)
|
|
{
|
|
CoTaskMemFree(pIfTable);
|
|
CoTaskMemFree(pAdapterInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
dwIndex = 0;
|
|
do
|
|
{
|
|
|
|
ZeroMemory(&DevInfo, sizeof(SP_DEVINFO_DATA));
|
|
DevInfo.cbSize = sizeof(DevInfo);
|
|
|
|
/* get device info */
|
|
if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, &DevInfo))
|
|
break;
|
|
|
|
/* get device software registry path */
|
|
if (!SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
|
|
break;
|
|
|
|
/* open device registry key */
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
|
|
break;
|
|
|
|
/* query NetCfgInstanceId for current device */
|
|
dwSize = sizeof(szNetCfg);
|
|
if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hSubKey);
|
|
break;
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
|
|
/* get the current adapter index from NetCfgInstanceId */
|
|
if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, szNetCfg, &dwAdapterIndex))
|
|
continue;
|
|
|
|
/* get detailed adapter info */
|
|
ZeroMemory(&IfEntry, sizeof(IfEntry));
|
|
IfEntry.dwIndex = dwAdapterIndex;
|
|
if(GetIfEntry(&IfEntry) != NO_ERROR)
|
|
break;
|
|
|
|
/* allocate new INetConnectionItem */
|
|
pNew = CoTaskMemAlloc(sizeof(INetConnectionItem));
|
|
if (!pNew)
|
|
break;
|
|
|
|
ZeroMemory(pNew, sizeof(INetConnectionItem));
|
|
pNew->dwAdapterIndex = dwAdapterIndex;
|
|
/* store NetCfgInstanceId */
|
|
CLSIDFromString(szNetCfg, &pNew->Props.guidId);
|
|
NormalizeOperStatus(&IfEntry, &pNew->Props);
|
|
|
|
switch(IfEntry.dwType)
|
|
{
|
|
case IF_TYPE_ETHERNET_CSMACD:
|
|
pNew->Props.MediaType = NCM_LAN;
|
|
break;
|
|
case IF_TYPE_IEEE80211:
|
|
pNew->Props.MediaType = NCM_SHAREDACCESSHOST_RAS;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
/* open network connections details */
|
|
wcscpy(&szName[80], szNetCfg);
|
|
wcscpy(&szName[118], L"\\Connection");
|
|
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
|
|
{
|
|
/* retrieve name of connection */
|
|
dwSize = sizeof(szAdapterNetCfg);
|
|
if (RegQueryValueExW(hSubKey, L"Name", NULL, NULL, (LPBYTE)szAdapterNetCfg, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
pNew->Props.pszwName = CoTaskMemAlloc((wcslen(szAdapterNetCfg)+1) * sizeof(WCHAR));
|
|
if (pNew->Props.pszwName)
|
|
wcscpy(pNew->Props.pszwName, szAdapterNetCfg);
|
|
}
|
|
dwSize = sizeof(dwShowIcon);
|
|
if (RegQueryValueExW(hSubKey, L"ShowIcon", NULL, NULL, (LPBYTE)&dwShowIcon, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if (dwShowIcon)
|
|
pNew->Props.dwCharacter |= NCCF_SHOW_ICON;
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
if (SetupDiGetDeviceRegistryPropertyW(hInfo, &DevInfo, SPDRP_DEVICEDESC, NULL, (PBYTE)szNetCfg, sizeof(szNetCfg)/sizeof(WCHAR), &dwSize))
|
|
{
|
|
szNetCfg[(sizeof(szNetCfg)/sizeof(WCHAR))-1] = L'\0';
|
|
pNew->Props.pszwDeviceName = CoTaskMemAlloc((wcslen(szNetCfg)+1) * sizeof(WCHAR));
|
|
if (pNew->Props.pszwDeviceName)
|
|
wcscpy(pNew->Props.pszwDeviceName, szNetCfg);
|
|
}
|
|
|
|
if (pCurrent)
|
|
pCurrent->Next = pNew;
|
|
else
|
|
This->pHead = pNew;
|
|
|
|
pCurrent = pNew;
|
|
}while(TRUE);
|
|
|
|
CoTaskMemFree(pIfTable);
|
|
CoTaskMemFree(pAdapterInfo);
|
|
SetupDiDestroyDeviceInfoList(hInfo);
|
|
|
|
This->pCurrent = This->pHead;
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT WINAPI INetConnectionManager_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
|
|
{
|
|
INetConnectionManagerImpl *sf;
|
|
|
|
if (!ppv)
|
|
return E_POINTER;
|
|
if (pUnkOuter)
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
sf = (INetConnectionManagerImpl *) CoTaskMemAlloc(sizeof (INetConnectionManagerImpl));
|
|
if (!sf)
|
|
return E_OUTOFMEMORY;
|
|
|
|
sf->ref = 1;
|
|
sf->lpVtbl = &vt_NetConnectionManager;
|
|
sf->lpVtblNetConnection = &vt_EnumNetConnection;
|
|
sf->pHead = NULL;
|
|
sf->pCurrent = NULL;
|
|
|
|
|
|
if (!SUCCEEDED (INetConnectionManager_QueryInterface ((INetConnectionManager*)sf, riid, ppv)))
|
|
{
|
|
INetConnectionManager_Release((INetConnectionManager*)sf);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
INetConnectionManager_Release((INetConnectionManager*)sf);
|
|
EnumerateINetConnections(sf);
|
|
return S_OK;
|
|
}
|
|
|
|
|