1574 lines
42 KiB
C
1574 lines
42 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
netcfg.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
System network configuration grovelling routines
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mike Massa (mikemas) May 19, 1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Who When What
|
|||
|
-------- -------- ----------------------------------------------
|
|||
|
mikemas 05-19-97 created
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <winsock2.h>
|
|||
|
|
|||
|
#include <cluster.h>
|
|||
|
#include <objbase.h>
|
|||
|
#include <devguid.h>
|
|||
|
|
|||
|
#include <netcon.h>
|
|||
|
#include <regstr.h>
|
|||
|
|
|||
|
#include <iphlpapi.h>
|
|||
|
|
|||
|
//
|
|||
|
// Private Constants
|
|||
|
//
|
|||
|
#define TCPIP_INTERFACES_KEY L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
|
|||
|
#define STRING_ARRAY_DELIMITERS " \t,;"
|
|||
|
|
|||
|
//
|
|||
|
// Allocing and cloning helper functions
|
|||
|
//
|
|||
|
|
|||
|
#define AllocGracefully(status, result, len, name) \
|
|||
|
result = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, len); \
|
|||
|
if (!result) { \
|
|||
|
status = GetLastError(); \
|
|||
|
ClRtlLogPrint(LOG_CRITICAL, \
|
|||
|
"[ClNet] alloc of %1!hs! (%2!d! bytes) failed, status %3!d!\n", \
|
|||
|
name,len,status); \
|
|||
|
goto exit_gracefully; \
|
|||
|
} else { \
|
|||
|
status = ERROR_SUCCESS; \
|
|||
|
}
|
|||
|
|
|||
|
#define CloneAnsiString(Status,AnsiStr,WideResult) { \
|
|||
|
SIZE_T len = _mbstrlen(AnsiStr) + 1; \
|
|||
|
AllocGracefully(status, WideResult, len * sizeof(WCHAR), # AnsiStr); \
|
|||
|
mbstowcs(WideResult, AnsiStr, len); \
|
|||
|
}
|
|||
|
|
|||
|
#define CloneWideString(Status,WideStr,WideResult) { \
|
|||
|
SIZE_T _size = (wcslen(WideStr) + 1) * sizeof(WCHAR); \
|
|||
|
AllocGracefully(Status, WideResult, _size * sizeof(WCHAR), # WideStr); \
|
|||
|
memcpy(WideResult, WideStr, _size); \
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
ClRtlpDeleteInterfaceInfo(
|
|||
|
PCLRTL_NET_INTERFACE_INFO InterfaceInfo
|
|||
|
)
|
|||
|
{
|
|||
|
if (InterfaceInfo) {
|
|||
|
LocalFree(InterfaceInfo->InterfaceAddressString);
|
|||
|
LocalFree(InterfaceInfo->NetworkAddressString);
|
|||
|
LocalFree(InterfaceInfo->NetworkMaskString);
|
|||
|
|
|||
|
LocalFree(InterfaceInfo);
|
|||
|
}
|
|||
|
} // DeleteInterfaceInfo
|
|||
|
|
|||
|
PCLRTL_NET_INTERFACE_INFO
|
|||
|
ClRtlpCreateInterfaceInfo(
|
|||
|
IN CONST PIP_ADDR_STRING IpAddr
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
PCLRTL_NET_INTERFACE_INFO This = 0;
|
|||
|
ULONG Addr, Mask, Network;
|
|||
|
|
|||
|
Addr = inet_addr(IpAddr->IpAddress.String);
|
|||
|
Mask = inet_addr(IpAddr->IpMask.String);
|
|||
|
Network = Addr & Mask;
|
|||
|
|
|||
|
if ( (INADDR_NONE == Addr) ||
|
|||
|
(INADDR_NONE == Mask) ||
|
|||
|
((0 == Network) && Addr && Mask)
|
|||
|
)
|
|||
|
{
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] Bad ip addr/mask: %1!X! %2!X! %3!X!\n",
|
|||
|
Addr,
|
|||
|
Mask,
|
|||
|
Network
|
|||
|
);
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
AllocGracefully(
|
|||
|
status,
|
|||
|
This,
|
|||
|
sizeof(CLRTL_NET_INTERFACE_INFO),
|
|||
|
"CLRTL_NET_INTERFACE_INFO"
|
|||
|
);
|
|||
|
|
|||
|
This->Context = IpAddr -> Context;
|
|||
|
|
|||
|
This->InterfaceAddress = Addr;
|
|||
|
This->NetworkMask = Mask;
|
|||
|
This->NetworkAddress = Network;
|
|||
|
|
|||
|
CloneAnsiString(
|
|||
|
status,
|
|||
|
IpAddr->IpAddress.String,
|
|||
|
This->InterfaceAddressString
|
|||
|
);
|
|||
|
CloneAnsiString(
|
|||
|
status,
|
|||
|
IpAddr->IpMask.String,
|
|||
|
This->NetworkMaskString
|
|||
|
);
|
|||
|
|
|||
|
status = ClRtlTcpipAddressToString(
|
|||
|
Network,
|
|||
|
&(This->NetworkAddressString)
|
|||
|
);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] ClRtlTcpipAddressToString of %1!X! failed, "
|
|||
|
"status %2!d!\n",
|
|||
|
Network,
|
|||
|
status
|
|||
|
);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
SetLastError(status);
|
|||
|
if (This) {
|
|||
|
ClRtlpDeleteInterfaceInfo(This);
|
|||
|
This = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return This;
|
|||
|
} // CreateInterfaceInfo
|
|||
|
|
|||
|
VOID
|
|||
|
ClRtlpDeleteAdapter(
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo
|
|||
|
)
|
|||
|
{
|
|||
|
if (adapterInfo) {
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
interfaceInfo = adapterInfo->InterfaceList;
|
|||
|
|
|||
|
while (interfaceInfo != NULL) {
|
|||
|
PCLRTL_NET_INTERFACE_INFO next = interfaceInfo->Next;
|
|||
|
|
|||
|
ClRtlpDeleteInterfaceInfo(interfaceInfo);
|
|||
|
|
|||
|
interfaceInfo = next;
|
|||
|
}
|
|||
|
|
|||
|
LocalFree(adapterInfo->DeviceGuid);
|
|||
|
LocalFree(adapterInfo->ConnectoidName);
|
|||
|
LocalFree(adapterInfo->DeviceName);
|
|||
|
LocalFree(adapterInfo->AdapterDomainName);
|
|||
|
LocalFree(adapterInfo->DnsServerList);
|
|||
|
|
|||
|
LocalFree(adapterInfo);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
} // DeleteAdapter
|
|||
|
|
|||
|
DWORD
|
|||
|
ClRtlpCreateAdapter(
|
|||
|
IN PIP_ADAPTER_INFO AdapterInfo,
|
|||
|
OUT PCLRTL_NET_ADAPTER_INFO * ppAdapter)
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapter = 0;
|
|||
|
*ppAdapter = 0;
|
|||
|
|
|||
|
AllocGracefully(status, adapter, sizeof(*adapter), "NET_ADAPTER_INFO");
|
|||
|
ZeroMemory(adapter, sizeof(*adapter));
|
|||
|
|
|||
|
//
|
|||
|
// Assumption here is that:
|
|||
|
//
|
|||
|
// AdapterName contains Guid in the form {4082164E-A4B5-11D2-89C3-E37CB6BB13FC}
|
|||
|
// We need to store it without curly brackets
|
|||
|
//
|
|||
|
|
|||
|
{
|
|||
|
SIZE_T len = _mbstrlen(AdapterInfo->AdapterName); // not including 0, but including { and } //
|
|||
|
AllocGracefully(status, adapter->DeviceGuid,
|
|||
|
sizeof(WCHAR) * (len - 1), "adapter->DeviceGuid");
|
|||
|
mbstowcs(adapter->DeviceGuid, AdapterInfo->AdapterName+1, len-1);
|
|||
|
adapter->DeviceGuid[len - 2] = UNICODE_NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
adapter->Index = AdapterInfo->Index;
|
|||
|
{
|
|||
|
PIP_ADDR_STRING IpAddr = &AdapterInfo->IpAddressList;
|
|||
|
while ( IpAddr ) {
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
interfaceInfo = ClRtlpCreateInterfaceInfo(IpAddr);
|
|||
|
|
|||
|
if (!interfaceInfo) {
|
|||
|
// CreateInterfaceInfo logs the error message //
|
|||
|
// clean up will be done by DeleteAdapter //
|
|||
|
status = GetLastError();
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
interfaceInfo->Next = adapter->InterfaceList;
|
|||
|
adapter->InterfaceList = interfaceInfo;
|
|||
|
++(adapter->InterfaceCount);
|
|||
|
|
|||
|
IpAddr = IpAddr -> Next;
|
|||
|
}
|
|||
|
|
|||
|
if (adapter->InterfaceList) {
|
|||
|
adapter->InterfaceList->Flags |= CLRTL_NET_INTERFACE_PRIMARY;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
ClRtlpDeleteAdapter(adapter);
|
|||
|
} else {
|
|||
|
*ppAdapter = adapter;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
} // CreateAdapter
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_ADAPTER_ENUM
|
|||
|
ClRtlpCreateAdapterEnum()
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
DWORD len;
|
|||
|
|
|||
|
PIP_ADAPTER_INFO SingleAdapter = 0;
|
|||
|
PIP_ADAPTER_INFO AdapterInfo = 0;
|
|||
|
PCLRTL_NET_ADAPTER_ENUM AdapterEnum = 0;
|
|||
|
|
|||
|
len = 0;
|
|||
|
for(;;) {
|
|||
|
status = GetAdaptersInfo(AdapterInfo, &len);
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
break;
|
|||
|
}
|
|||
|
if (status != ERROR_BUFFER_OVERFLOW) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] GetAdaptersInfo returned %1!d!\n", status);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
LocalFree(AdapterInfo); // LocalFree(0) is OK //
|
|||
|
AllocGracefully(status, AdapterInfo, len, "IP_ADAPTER_INFO");
|
|||
|
}
|
|||
|
|
|||
|
AllocGracefully(status, AdapterEnum,
|
|||
|
sizeof(*AdapterEnum), "PCLRTL_NET_ADAPTER_ENUM");
|
|||
|
ZeroMemory(AdapterEnum, sizeof(*AdapterEnum));
|
|||
|
|
|||
|
SingleAdapter = AdapterInfo;
|
|||
|
|
|||
|
while (SingleAdapter) {
|
|||
|
if (SingleAdapter->Type != MIB_IF_TYPE_LOOPBACK &&
|
|||
|
SingleAdapter->Type != MIB_IF_TYPE_PPP &&
|
|||
|
SingleAdapter->Type != MIB_IF_TYPE_SLIP )
|
|||
|
{
|
|||
|
PCLRTL_NET_ADAPTER_INFO Adapter = 0;
|
|||
|
|
|||
|
status = ClRtlpCreateAdapter(SingleAdapter, &Adapter);
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] CreateAdapter %1!d! failed, status %2!d!\n",
|
|||
|
AdapterEnum->AdapterCount, status);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Push the adapter into Enumeration List
|
|||
|
//
|
|||
|
Adapter->Next = AdapterEnum->AdapterList;
|
|||
|
AdapterEnum->AdapterList = Adapter;
|
|||
|
++(AdapterEnum->AdapterCount);
|
|||
|
}
|
|||
|
|
|||
|
SingleAdapter = SingleAdapter->Next;
|
|||
|
}
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
SetLastError(status);
|
|||
|
ClRtlFreeNetAdapterEnum(AdapterEnum);
|
|||
|
AdapterEnum = 0;
|
|||
|
}
|
|||
|
|
|||
|
LocalFree(AdapterInfo);
|
|||
|
return AdapterEnum;
|
|||
|
} // CreateAdapterEnum
|
|||
|
|
|||
|
|
|||
|
HKEY
|
|||
|
ClRtlpFindAdapterKey(
|
|||
|
HKEY TcpInterfacesKey,
|
|||
|
LPWSTR AdapterGuidString
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given the adapter GUID, look through the key names under
|
|||
|
TCP's Interfaces key and see if a match can be found. The
|
|||
|
key names should have the GUID as some part of the name.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TcpInterfacesKey - handle to TCP's interfaces area
|
|||
|
|
|||
|
AdapterGuidString - pointer to string representing adapter's GUID
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Handle to the interface key; otherwise NULL
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HKEY AdapterInterfaceKey = NULL;
|
|||
|
WCHAR KeyName[REGSTR_MAX_VALUE_LENGTH + 1];
|
|||
|
DWORD KeyLength = sizeof( KeyName )/sizeof(TCHAR);
|
|||
|
DWORD index = 0;
|
|||
|
BOOL FoundMatch = FALSE;
|
|||
|
size_t SubStringPos;
|
|||
|
DWORD Status;
|
|||
|
FILETIME FileTime;
|
|||
|
|
|||
|
//
|
|||
|
// enum the key names under the interfaces
|
|||
|
//
|
|||
|
do {
|
|||
|
Status = RegEnumKeyEx(TcpInterfacesKey,
|
|||
|
index,
|
|||
|
KeyName,
|
|||
|
&KeyLength,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&FileTime);
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// find the beginning of the match
|
|||
|
//
|
|||
|
_wcsupr( KeyName );
|
|||
|
if (wcsstr( KeyName, AdapterGuidString )) {
|
|||
|
FoundMatch = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
++index;
|
|||
|
KeyLength = sizeof( KeyName );
|
|||
|
} while ( TRUE );
|
|||
|
|
|||
|
if ( FoundMatch ) {
|
|||
|
|
|||
|
Status = RegOpenKeyW(TcpInterfacesKey,
|
|||
|
KeyName,
|
|||
|
&AdapterInterfaceKey);
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
AdapterInterfaceKey = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return AdapterInterfaceKey;
|
|||
|
} // FindAdapterKey
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ClRtlpConvertIPAddressString(
|
|||
|
LPSTR DnsServerString,
|
|||
|
PDWORD ServerCount,
|
|||
|
PDWORD * ServerList)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Convert the string of DNS server addresses to binary
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DnsServerString - concat'ed string of IP addresses that can be separated
|
|||
|
by white space of commas
|
|||
|
|
|||
|
ServerCount - pointer to DWORD that receives # of addresses detected
|
|||
|
|
|||
|
ServerList - pointer to DWORD array of converted IP addresses
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if everything went ok
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
#define MAX_DNS_SERVER_ADDRESSES 100
|
|||
|
|
|||
|
PCHAR stringPointer = DnsServerString;
|
|||
|
DWORD stringCount = 0;
|
|||
|
PDWORD serverList = NULL;
|
|||
|
LPSTR stringAddress[ MAX_DNS_SERVER_ADDRESSES ];
|
|||
|
|
|||
|
//
|
|||
|
// count how many addresses are in the string and null terminate them for
|
|||
|
// inet_addr
|
|||
|
//
|
|||
|
|
|||
|
stringPointer += strspn(stringPointer, STRING_ARRAY_DELIMITERS);
|
|||
|
stringAddress[0] = stringPointer;
|
|||
|
stringCount = 1;
|
|||
|
|
|||
|
while (stringCount < MAX_DNS_SERVER_ADDRESSES &&
|
|||
|
(stringPointer = strpbrk(stringPointer, STRING_ARRAY_DELIMITERS)))
|
|||
|
{
|
|||
|
*stringPointer++ = '\0';
|
|||
|
stringPointer += strspn(stringPointer, STRING_ARRAY_DELIMITERS);
|
|||
|
stringAddress[stringCount] = stringPointer;
|
|||
|
if (*stringPointer) {
|
|||
|
++stringCount;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
serverList = LocalAlloc( LMEM_FIXED, stringCount * sizeof( DWORD ));
|
|||
|
if ( serverList == NULL ) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
*ServerCount = stringCount;
|
|||
|
*ServerList = serverList;
|
|||
|
|
|||
|
while ( stringCount-- ) {
|
|||
|
serverList[ stringCount ] = inet_addr( stringAddress[ stringCount ]);
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
} // ConvertIPAddressString
|
|||
|
|
|||
|
|
|||
|
typedef BOOLEAN (*ENUM_CALLBACK)(NETCON_PROPERTIES *,
|
|||
|
INetConnection*,
|
|||
|
PVOID Context);
|
|||
|
HRESULT
|
|||
|
ClRtlpHrEnumConnections(
|
|||
|
IN ENUM_CALLBACK enumCallback,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enumerate Connection Manager Connections
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
enumCallback - callback to be called for every connection
|
|||
|
Context - to be passed to a callback
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
S_OK or HRESULT error code
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
INetConnectionManager * NcManager = NULL;
|
|||
|
IEnumNetConnection * EnumNc = NULL;
|
|||
|
INetConnection * NetConnection = NULL;
|
|||
|
NETCON_PROPERTIES * NcProps = NULL;
|
|||
|
DWORD dwNumConnectionsReturned;
|
|||
|
LPWSTR deviceGuidString = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// instantiate a connection mgr object and enum the connections
|
|||
|
//
|
|||
|
hr = CoCreateInstance((REFCLSID)&CLSID_ConnectionManager,
|
|||
|
NULL,
|
|||
|
CLSCTX_LOCAL_SERVER,
|
|||
|
(REFIID)&IID_INetConnectionManager,
|
|||
|
&NcManager);
|
|||
|
if (FAILED(hr)) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] INetConnectionManager_CoCreateInstance failed, status %1!X!\n",
|
|||
|
hr);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
hr = INetConnectionManager_EnumConnections(NcManager,
|
|||
|
NCME_DEFAULT,
|
|||
|
&EnumNc);
|
|||
|
if (FAILED(hr)) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] INetConnectionManager_EnumConnections failed, status %1!X!\n",
|
|||
|
hr);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
IEnumNetConnection_Reset( EnumNc );
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
hr = IEnumNetConnection_Next(EnumNc,
|
|||
|
1,
|
|||
|
&NetConnection,
|
|||
|
&dwNumConnectionsReturned);
|
|||
|
if (FAILED(hr)) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] IEnumNetConnection_Next failed, status %1!X!\n",
|
|||
|
hr);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
if ( dwNumConnectionsReturned == 0 ) {
|
|||
|
hr = S_OK;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
hr = INetConnection_GetProperties(NetConnection, &NcProps);
|
|||
|
if (SUCCEEDED( hr )) {
|
|||
|
BOOLEAN bCont;
|
|||
|
|
|||
|
bCont = enumCallback(NcProps, NetConnection, Context);
|
|||
|
|
|||
|
NcFreeNetconProperties(NcProps);
|
|||
|
NcProps = 0;
|
|||
|
if (!bCont) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
INetConnection_Release( NetConnection ); NetConnection = NULL;
|
|||
|
}
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
|
|||
|
if (EnumNc != NULL) {
|
|||
|
IEnumNetConnection_Release( EnumNc );
|
|||
|
}
|
|||
|
|
|||
|
if (NcManager != NULL) {
|
|||
|
INetConnectionManager_Release( NcManager );
|
|||
|
}
|
|||
|
|
|||
|
return hr;
|
|||
|
|
|||
|
} // HrEnumConnections
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClRtlpProcessNetConfigurationAdapter(
|
|||
|
HKEY TcpInterfacesKey,
|
|||
|
PCLRTL_NET_ADAPTER_ENUM adapterEnum,
|
|||
|
NETCON_PROPERTIES * NCProps,
|
|||
|
LPWSTR DeviceGuidString
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
For a given conn mgr object, determine if it is in use by
|
|||
|
TCP. This is acheived by comparing the adapter ID in the tcpip
|
|||
|
adapter enumeration with the connection object's guid.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TcpInterfacessKey - handle to the root of the TCP\Parameters\Interfaces area
|
|||
|
|
|||
|
adapterEnum - pointer to enumeration of adapters and their interfaces
|
|||
|
actually in use by TCP
|
|||
|
|
|||
|
NCProps - Connectoid properties.
|
|||
|
|
|||
|
DeviceGuidString - Guid for the connectoid (and for the associated adapter).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HKEY AdaptersKey;
|
|||
|
HKEY DHCPAdaptersKey = NULL;
|
|||
|
HKEY InterfacesKey = NULL;
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
|
|||
|
DWORD valueSize;
|
|||
|
DWORD valueType;
|
|||
|
LPWSTR valueName;
|
|||
|
LPSTR ansiValueName;
|
|||
|
BOOL ignoreAdapter = FALSE;
|
|||
|
DWORD NTEContext;
|
|||
|
DWORD Status;
|
|||
|
BOOL dhcpEnabled;
|
|||
|
|
|||
|
//
|
|||
|
// Get the TCP/IP interfaces registry key for this adapter.
|
|||
|
//
|
|||
|
InterfacesKey = ClRtlpFindAdapterKey(
|
|||
|
TcpInterfacesKey,
|
|||
|
DeviceGuidString
|
|||
|
);
|
|||
|
|
|||
|
if (InterfacesKey == NULL) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] No Interfaces key for %1!ws!\n",
|
|||
|
DeviceGuidString
|
|||
|
);
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// see if we should be ignoring this adapter per the registry
|
|||
|
//
|
|||
|
valueSize = sizeof(DWORD);
|
|||
|
Status = RegQueryValueExW(InterfacesKey,
|
|||
|
L"MSCSHidden",
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE) &ignoreAdapter,
|
|||
|
&valueSize);
|
|||
|
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
ignoreAdapter = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Search the enum for this adapter.
|
|||
|
//
|
|||
|
adapterInfo = ClRtlFindNetAdapterById(adapterEnum, DeviceGuidString);
|
|||
|
|
|||
|
if (adapterInfo != NULL) {
|
|||
|
CloneWideString(Status, NCProps->pszwDeviceName, adapterInfo->DeviceName);
|
|||
|
CloneWideString(Status, NCProps->pszwName, adapterInfo->ConnectoidName);
|
|||
|
|
|||
|
//
|
|||
|
// Check if this is a hidden netcard.
|
|||
|
//
|
|||
|
if ( ignoreAdapter ) {
|
|||
|
adapterInfo->Flags |= CLRTL_NET_ADAPTER_HIDDEN;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Store the NCStatus in the adapter info structure
|
|||
|
//
|
|||
|
adapterInfo->NCStatus = NCProps->Status;
|
|||
|
|
|||
|
//
|
|||
|
// get the domain name and DHCP server list (if any) associated
|
|||
|
// with this adapter. The Domain value has precedence over
|
|||
|
// DhcpDomain. If that value is empty/doesn't exist, then use
|
|||
|
// DhcpDomain only if EnableDHCP is set to one.
|
|||
|
//
|
|||
|
Status = ClRtlRegQueryDword(InterfacesKey,
|
|||
|
L"EnableDHCP",
|
|||
|
&dhcpEnabled,
|
|||
|
NULL);
|
|||
|
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
dhcpEnabled = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
valueName = L"Domain";
|
|||
|
valueSize = 0;
|
|||
|
Status = RegQueryValueExW(InterfacesKey,
|
|||
|
valueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)NULL,
|
|||
|
&valueSize);
|
|||
|
|
|||
|
if ( Status != ERROR_SUCCESS || valueSize == sizeof(UNICODE_NULL)) {
|
|||
|
|
|||
|
//
|
|||
|
// it didn't exist or the value was NULL. if were using DHCP,
|
|||
|
// then check to see if DHCP supplied domain name was
|
|||
|
// specified
|
|||
|
//
|
|||
|
if ( dhcpEnabled ) {
|
|||
|
valueName = L"DhcpDomain";
|
|||
|
Status = RegQueryValueExW(InterfacesKey,
|
|||
|
valueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)NULL,
|
|||
|
&valueSize);
|
|||
|
} else {
|
|||
|
Status = ERROR_FILE_NOT_FOUND;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS && valueSize > sizeof(UNICODE_NULL)) {
|
|||
|
|
|||
|
//
|
|||
|
// legit domain name was found (somewhere). store it in the
|
|||
|
// adapter info
|
|||
|
//
|
|||
|
adapterInfo->AdapterDomainName = LocalAlloc(LMEM_FIXED,
|
|||
|
valueSize +
|
|||
|
sizeof(UNICODE_NULL));
|
|||
|
|
|||
|
if ( adapterInfo->AdapterDomainName != NULL ) {
|
|||
|
|
|||
|
Status = RegQueryValueExW(InterfacesKey,
|
|||
|
valueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)adapterInfo->AdapterDomainName,
|
|||
|
&valueSize);
|
|||
|
|
|||
|
if ( Status != ERROR_SUCCESS ) {
|
|||
|
|
|||
|
LocalFree( adapterInfo->AdapterDomainName );
|
|||
|
adapterInfo->AdapterDomainName = NULL;
|
|||
|
}
|
|||
|
#if CLUSTER_BETA
|
|||
|
else {
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
" %1!ws! key: %2!ws!\n",
|
|||
|
valueName,
|
|||
|
adapterInfo->AdapterDomainName);
|
|||
|
}
|
|||
|
#endif
|
|||
|
} else {
|
|||
|
Status = GetLastError();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// now get the DNS server list in a similar fashion. The
|
|||
|
// NameServer value has precedence over DhcpNameServer but we only
|
|||
|
// check the DHCP values if DHCP is enabled (just like
|
|||
|
// above). Note that we use the Ansi APIs since we need to convert
|
|||
|
// the IP addresses into binary form and there is no wide char
|
|||
|
// form of inet_addr.
|
|||
|
//
|
|||
|
ansiValueName = "NameServer";
|
|||
|
valueSize = 0;
|
|||
|
Status = RegQueryValueExA(InterfacesKey,
|
|||
|
ansiValueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)NULL,
|
|||
|
&valueSize);
|
|||
|
|
|||
|
if ( Status != ERROR_SUCCESS || valueSize == 1 ) {
|
|||
|
if ( dhcpEnabled ) {
|
|||
|
ansiValueName = "DhcpNameServer";
|
|||
|
Status = RegQueryValueExA(InterfacesKey,
|
|||
|
ansiValueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)NULL,
|
|||
|
&valueSize);
|
|||
|
} else {
|
|||
|
Status = ERROR_FILE_NOT_FOUND;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS && valueSize > 0 ) {
|
|||
|
PCHAR nameServerString;
|
|||
|
|
|||
|
nameServerString = LocalAlloc( LMEM_FIXED, valueSize + 1 );
|
|||
|
|
|||
|
if ( nameServerString != NULL ) {
|
|||
|
|
|||
|
Status = RegQueryValueExA(InterfacesKey,
|
|||
|
ansiValueName,
|
|||
|
NULL,
|
|||
|
&valueType,
|
|||
|
(LPBYTE)nameServerString,
|
|||
|
&valueSize);
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS ) {
|
|||
|
DWORD serverCount;
|
|||
|
PDWORD serverList;
|
|||
|
|
|||
|
#if CLUSTER_BETA
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
" %1!hs! key: %2!hs!\n",
|
|||
|
ansiValueName,
|
|||
|
nameServerString);
|
|||
|
#endif
|
|||
|
Status = ClRtlpConvertIPAddressString(
|
|||
|
nameServerString,
|
|||
|
&serverCount,
|
|||
|
&serverList
|
|||
|
);
|
|||
|
|
|||
|
if ( Status == ERROR_SUCCESS ) {
|
|||
|
adapterInfo->DnsServerCount = serverCount;
|
|||
|
adapterInfo->DnsServerList = serverList;
|
|||
|
} else {
|
|||
|
adapterInfo->DnsServerCount = 0;
|
|||
|
adapterInfo->DnsServerList = NULL;
|
|||
|
}
|
|||
|
} else {
|
|||
|
adapterInfo->DnsServerCount = 0;
|
|||
|
adapterInfo->DnsServerList = NULL;
|
|||
|
}
|
|||
|
|
|||
|
LocalFree( nameServerString );
|
|||
|
} else {
|
|||
|
Status = GetLastError();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( adapterInfo == NULL ) {
|
|||
|
//
|
|||
|
// TCP/IP is not bound to this adapter right now. PnP?
|
|||
|
//
|
|||
|
ClRtlLogPrint(LOG_UNUSUAL,
|
|||
|
"[ClNet] Tcpip is not bound to adapter %1!ws!.\n",
|
|||
|
DeviceGuidString
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
|
|||
|
if (InterfacesKey != NULL) {
|
|||
|
RegCloseKey( InterfacesKey );
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
} // ProcessNetConfigurationAdapter
|
|||
|
|
|||
|
|
|||
|
typedef struct _CONFIGURATION_CONTEXT
|
|||
|
{
|
|||
|
PCLRTL_NET_ADAPTER_ENUM adapterEnum;
|
|||
|
HKEY TcpInterfacesKey;
|
|||
|
}
|
|||
|
CONFIGURATION_CONTEXT, *PCONFIGURATION_CONTEXT;
|
|||
|
|
|||
|
typedef WCHAR GUIDSTR[32 * 3];
|
|||
|
VOID GuidToStr(LPGUID Guid, PWCHAR buf)
|
|||
|
{
|
|||
|
//
|
|||
|
// GUIDs look like this: 4082164E-A4B5-11D2-89C3-E37CB6BB13FC
|
|||
|
//
|
|||
|
wsprintfW(
|
|||
|
buf,
|
|||
|
L"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
|||
|
Guid->Data1, Guid->Data2, Guid->Data3,
|
|||
|
Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3],
|
|||
|
Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ClRtlpProcessConfigurationCallback(
|
|||
|
NETCON_PROPERTIES * NCProps,
|
|||
|
INetConnection * NetConnection,
|
|||
|
PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
PCONFIGURATION_CONTEXT Ctx =
|
|||
|
(PCONFIGURATION_CONTEXT) Context;
|
|||
|
|
|||
|
if ( NCProps->MediaType == NCM_LAN &&
|
|||
|
NCProps->Status != NCS_HARDWARE_NOT_PRESENT &&
|
|||
|
NCProps->Status != NCS_HARDWARE_DISABLED &&
|
|||
|
NCProps->Status != NCS_HARDWARE_MALFUNCTION)
|
|||
|
{
|
|||
|
GUIDSTR deviceGuidString;
|
|||
|
GuidToStr(&NCProps->guidId, deviceGuidString);
|
|||
|
|
|||
|
ClRtlpProcessNetConfigurationAdapter(
|
|||
|
Ctx->TcpInterfacesKey,
|
|||
|
Ctx->adapterEnum,
|
|||
|
NCProps,
|
|||
|
deviceGuidString
|
|||
|
);
|
|||
|
//
|
|||
|
// the strings in the properties struct are either kept or
|
|||
|
// or freed in ProcessNetConfigurationAdapter. If they are
|
|||
|
// used, then they are freed when the adapter enum is freed
|
|||
|
//
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
} // ProcessConfigurationCallback
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_ADAPTER_ENUM
|
|||
|
ClRtlEnumNetAdapters(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enumerates all of the installed network adapters to which TCP/IP
|
|||
|
is bound.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A pointer to a network adapter enumeration, if successful.
|
|||
|
NULL if unsuccessful. Extended error information is available from
|
|||
|
GetLastError().
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
|
|||
|
CONFIGURATION_CONTEXT Ctx;
|
|||
|
PVOID wTimer;
|
|||
|
|
|||
|
ZeroMemory(&Ctx, sizeof(Ctx));
|
|||
|
|
|||
|
//
|
|||
|
// First get the list of bound adapters & interfaces from the
|
|||
|
// tcpip stack.
|
|||
|
//
|
|||
|
Ctx.adapterEnum = ClRtlpCreateAdapterEnum();
|
|||
|
if (Ctx.adapterEnum == NULL) {
|
|||
|
status = GetLastError();
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] GetTcpipAdaptersAndInterfaces failed %1!u!\n", status);
|
|||
|
|
|||
|
SetLastError(status);
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Open the Services portion of the registry
|
|||
|
//
|
|||
|
status = RegOpenKeyW(HKEY_LOCAL_MACHINE,
|
|||
|
TCPIP_INTERFACES_KEY,
|
|||
|
&Ctx.TcpInterfacesKey);
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] Open of TCP Params key failed - %1!u!\n",
|
|||
|
status
|
|||
|
);
|
|||
|
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
// This function might hang, so setting the watchdog timer to 2 mins (2 * 60 * 1000) ms
|
|||
|
wTimer = ClRtlSetWatchdogTimer(120000, L"Calling EnumConnections");
|
|||
|
|
|||
|
status = ClRtlpHrEnumConnections(
|
|||
|
ClRtlpProcessConfigurationCallback,
|
|||
|
&Ctx
|
|||
|
);
|
|||
|
|
|||
|
ClRtlCancelWatchdogTimer(wTimer);
|
|||
|
|
|||
|
if (status != S_OK) {
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Finally, ensure that we found a name for each adapter in the enum.
|
|||
|
//
|
|||
|
for (adapterInfo = Ctx.adapterEnum->AdapterList;
|
|||
|
adapterInfo != NULL;
|
|||
|
adapterInfo = adapterInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (adapterInfo->ConnectoidName == NULL) {
|
|||
|
if ( adapterInfo->InterfaceCount > 0 ) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] No installed adapter was found for IP address %1!ws!\n",
|
|||
|
adapterInfo->InterfaceList->InterfaceAddressString
|
|||
|
);
|
|||
|
} else {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[ClNet] No installed adapter was found for Tcpip IF entity %1!u!\n",
|
|||
|
adapterInfo->Index
|
|||
|
);
|
|||
|
}
|
|||
|
status = ERROR_FILE_NOT_FOUND;
|
|||
|
goto exit_gracefully;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if CLUSTER_BETA
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[ClNet] Successfully enumerated all adapters and interfaces\n");
|
|||
|
#endif
|
|||
|
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
|
|||
|
exit_gracefully:
|
|||
|
|
|||
|
if (Ctx.TcpInterfacesKey != NULL) {
|
|||
|
RegCloseKey(Ctx.TcpInterfacesKey);
|
|||
|
}
|
|||
|
|
|||
|
if (status != ERROR_SUCCESS) {
|
|||
|
if (Ctx.adapterEnum != NULL) {
|
|||
|
ClRtlFreeNetAdapterEnum(Ctx.adapterEnum);
|
|||
|
Ctx.adapterEnum = NULL;
|
|||
|
}
|
|||
|
|
|||
|
SetLastError(status);
|
|||
|
}
|
|||
|
|
|||
|
return(Ctx.adapterEnum);
|
|||
|
|
|||
|
} // ClRtlEnumNetAdapters
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ClRtlFreeNetAdapterEnum(
|
|||
|
IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Frees a network adapter enumeration structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AdapterEnum - A pointer to the structure to be freed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if (AdapterEnum) {
|
|||
|
PCLRTL_NET_ADAPTER_INFO p = AdapterEnum -> AdapterList;
|
|||
|
while (p) {
|
|||
|
PCLRTL_NET_ADAPTER_INFO next = p->Next;
|
|||
|
ClRtlpDeleteAdapter(p);
|
|||
|
p = next;
|
|||
|
}
|
|||
|
LocalFree(AdapterEnum);
|
|||
|
}
|
|||
|
} // ClRtlFreeNetAdapterEnum
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_ADAPTER_INFO
|
|||
|
ClRtlFindNetAdapterById(
|
|||
|
PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
|
|||
|
LPWSTR AdapterId
|
|||
|
)
|
|||
|
{
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo;
|
|||
|
|
|||
|
|
|||
|
for ( adapterInfo = AdapterEnum->AdapterList;
|
|||
|
adapterInfo != NULL;
|
|||
|
adapterInfo = adapterInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (wcscmp(AdapterId, adapterInfo->DeviceGuid) == 0) {
|
|||
|
if (!adapterInfo->Ignore) {
|
|||
|
return(adapterInfo);
|
|||
|
}
|
|||
|
else {
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
} // ClRtlFindNetAdapterById
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_INTERFACE_INFO
|
|||
|
ClRtlFindNetInterfaceByNetworkAddress(
|
|||
|
IN PCLRTL_NET_ADAPTER_INFO AdapterInfo,
|
|||
|
IN LPWSTR NetworkAddress
|
|||
|
)
|
|||
|
{
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
for (interfaceInfo = AdapterInfo->InterfaceList;
|
|||
|
interfaceInfo != NULL;
|
|||
|
interfaceInfo = interfaceInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (interfaceInfo->Ignore == FALSE) {
|
|||
|
//
|
|||
|
// We only look at the primary interface on the
|
|||
|
// adapter right now.
|
|||
|
//
|
|||
|
if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY)
|
|||
|
{
|
|||
|
if ( wcscmp(
|
|||
|
interfaceInfo->NetworkAddressString,
|
|||
|
NetworkAddress
|
|||
|
) == 0 )
|
|||
|
{
|
|||
|
return(interfaceInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
} // ClRtlFindNetInterfaceByNetworkAddress
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_ADAPTER_INFO
|
|||
|
ClRtlFindNetAdapterByNetworkAddress(
|
|||
|
IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
|
|||
|
IN LPWSTR NetworkAddress,
|
|||
|
OUT PCLRTL_NET_INTERFACE_INFO * InterfaceInfo
|
|||
|
)
|
|||
|
{
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo;
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
|
|||
|
for ( adapterInfo = AdapterEnum->AdapterList;
|
|||
|
adapterInfo != NULL;
|
|||
|
adapterInfo = adapterInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (adapterInfo->Ignore == FALSE) {
|
|||
|
for (interfaceInfo = adapterInfo->InterfaceList;
|
|||
|
interfaceInfo != NULL;
|
|||
|
interfaceInfo = interfaceInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (interfaceInfo->Ignore == FALSE) {
|
|||
|
//
|
|||
|
// We only look at the primary interface on the
|
|||
|
// adapter right now.
|
|||
|
//
|
|||
|
if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY) {
|
|||
|
if ( wcscmp(
|
|||
|
interfaceInfo->NetworkAddressString,
|
|||
|
NetworkAddress
|
|||
|
) == 0 )
|
|||
|
{
|
|||
|
*InterfaceInfo = interfaceInfo;
|
|||
|
|
|||
|
return(adapterInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*InterfaceInfo = NULL;
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
} // ClRtlFindNetAdapterByNetworkAddress
|
|||
|
|
|||
|
|
|||
|
PCLRTL_NET_ADAPTER_INFO
|
|||
|
ClRtlFindNetAdapterByInterfaceAddress(
|
|||
|
IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
|
|||
|
IN LPWSTR InterfaceAddressString,
|
|||
|
OUT PCLRTL_NET_INTERFACE_INFO * InterfaceInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
For a given IP interface address, find the
|
|||
|
adapter that is hosting that address.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCLRTL_NET_ADAPTER_INFO adapterInfo;
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
for ( adapterInfo = AdapterEnum->AdapterList;
|
|||
|
adapterInfo != NULL;
|
|||
|
adapterInfo = adapterInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (adapterInfo->Ignore == FALSE) {
|
|||
|
for (interfaceInfo = adapterInfo->InterfaceList;
|
|||
|
interfaceInfo != NULL;
|
|||
|
interfaceInfo = interfaceInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (interfaceInfo->Ignore == FALSE ) {
|
|||
|
|
|||
|
if ( wcscmp( interfaceInfo->InterfaceAddressString,
|
|||
|
InterfaceAddressString ) == 0 ) {
|
|||
|
*InterfaceInfo = interfaceInfo;
|
|||
|
return(adapterInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*InterfaceInfo = NULL;
|
|||
|
return(NULL);
|
|||
|
|
|||
|
} // ClRtlFindNetAdapterByInterfaceAddress
|
|||
|
|
|||
|
PCLRTL_NET_INTERFACE_INFO
|
|||
|
ClRtlGetPrimaryNetInterface(
|
|||
|
IN PCLRTL_NET_ADAPTER_INFO AdapterInfo
|
|||
|
)
|
|||
|
{
|
|||
|
PCLRTL_NET_INTERFACE_INFO interfaceInfo;
|
|||
|
|
|||
|
|
|||
|
for (interfaceInfo = AdapterInfo->InterfaceList;
|
|||
|
interfaceInfo != NULL;
|
|||
|
interfaceInfo = interfaceInfo->Next
|
|||
|
)
|
|||
|
{
|
|||
|
if (interfaceInfo->Flags & CLRTL_NET_INTERFACE_PRIMARY) {
|
|||
|
if (!interfaceInfo->Ignore) {
|
|||
|
return(interfaceInfo);
|
|||
|
}
|
|||
|
else {
|
|||
|
return(NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(NULL);
|
|||
|
|
|||
|
} // ClRtlGetPrimaryNetInterface
|
|||
|
|
|||
|
|
|||
|
LPWSTR
|
|||
|
ClRtlGetConnectoidName(
|
|||
|
INetConnection * NetConnection
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
NETCON_PROPERTIES * NcProps = NULL;
|
|||
|
LPWSTR name = NULL;
|
|||
|
|
|||
|
|
|||
|
status = INetConnection_GetProperties(NetConnection, &NcProps);
|
|||
|
|
|||
|
if (SUCCEEDED( status )) {
|
|||
|
DWORD nameLength = (lstrlenW(NcProps->pszwName) * sizeof(WCHAR)) +
|
|||
|
sizeof(UNICODE_NULL);
|
|||
|
|
|||
|
name = LocalAlloc(LMEM_FIXED, nameLength);
|
|||
|
|
|||
|
if (name != NULL) {
|
|||
|
lstrcpyW(name, NcProps->pszwName);
|
|||
|
}
|
|||
|
else {
|
|||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|||
|
}
|
|||
|
|
|||
|
NcFreeNetconProperties( NcProps );
|
|||
|
}
|
|||
|
else {
|
|||
|
SetLastError(status);
|
|||
|
}
|
|||
|
|
|||
|
return(name);
|
|||
|
|
|||
|
} // ClRtlGetConnectoidName
|
|||
|
|
|||
|
|
|||
|
typedef struct _FIND_CONNECTOID_CONTEXT
|
|||
|
{
|
|||
|
GUID ConnectoidGuid;
|
|||
|
LPCWSTR ConnectoidName;
|
|||
|
INetConnection * NetConnection;
|
|||
|
}
|
|||
|
FIND_CONNECTOID_CONTEXT, *PFIND_CONNECTOID_CONTEXT;
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ClRtlpFindConnectoidByGuidCallback(
|
|||
|
NETCON_PROPERTIES * NcProp,
|
|||
|
INetConnection * NetConnection,
|
|||
|
PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
PFIND_CONNECTOID_CONTEXT Ctx =
|
|||
|
(PFIND_CONNECTOID_CONTEXT) Context;
|
|||
|
|
|||
|
if ( IsEqualGUID(&Ctx->ConnectoidGuid, &NcProp->guidId) ) {
|
|||
|
INetConnection_AddRef(NetConnection);
|
|||
|
Ctx->NetConnection = NetConnection;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
} // FindConnectoidByGuidCallback
|
|||
|
|
|||
|
INetConnection *
|
|||
|
ClRtlFindConnectoidByGuid(
|
|||
|
LPWSTR ConnectoidGuidStr
|
|||
|
)
|
|||
|
{
|
|||
|
FIND_CONNECTOID_CONTEXT Ctx;
|
|||
|
HRESULT hr;
|
|||
|
RPC_STATUS rpcStatus;
|
|||
|
ZeroMemory(&Ctx, sizeof(Ctx));
|
|||
|
|
|||
|
rpcStatus = UuidFromStringW (
|
|||
|
(LPWSTR)ConnectoidGuidStr,
|
|||
|
&Ctx.ConnectoidGuid);
|
|||
|
if (rpcStatus != ERROR_SUCCESS) {
|
|||
|
SetLastError( HRESULT_FROM_WIN32(rpcStatus) );
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
hr = ClRtlpHrEnumConnections(ClRtlpFindConnectoidByGuidCallback, &Ctx);
|
|||
|
if (hr != S_OK) {
|
|||
|
SetLastError(hr);
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
return Ctx.NetConnection;
|
|||
|
}
|
|||
|
} // ClRtlFindConnectoidByGuid
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ClRtlpFindConnectoidByNameCallback(
|
|||
|
NETCON_PROPERTIES * NcProp,
|
|||
|
INetConnection * NetConnection,
|
|||
|
PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
PFIND_CONNECTOID_CONTEXT Ctx =
|
|||
|
(PFIND_CONNECTOID_CONTEXT) Context;
|
|||
|
|
|||
|
if ( lstrcmpiW(Ctx->ConnectoidName, NcProp->pszwName) == 0 ) {
|
|||
|
INetConnection_AddRef(NetConnection);
|
|||
|
Ctx->NetConnection = NetConnection;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
} // FindConnectoidByNameCallback
|
|||
|
|
|||
|
INetConnection *
|
|||
|
ClRtlFindConnectoidByName(
|
|||
|
LPCWSTR ConnectoidName
|
|||
|
)
|
|||
|
{
|
|||
|
FIND_CONNECTOID_CONTEXT Ctx;
|
|||
|
HRESULT hr;
|
|||
|
ZeroMemory(&Ctx, sizeof(Ctx));
|
|||
|
|
|||
|
Ctx.ConnectoidName = ConnectoidName;
|
|||
|
|
|||
|
hr = ClRtlpHrEnumConnections(ClRtlpFindConnectoidByNameCallback, &Ctx);
|
|||
|
if (hr != S_OK) {
|
|||
|
SetLastError(hr);
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
return Ctx.NetConnection;
|
|||
|
}
|
|||
|
} // ClRtlFindConnectoidByName
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ClRtlSetConnectoidName(
|
|||
|
INetConnection * NetConnection,
|
|||
|
LPWSTR NewConnectoidName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Set the conn mgr object in the connections folder to the
|
|||
|
supplied name. This routine must deal with collisions since
|
|||
|
the name change could be the result of a node joining the
|
|||
|
cluster whose conn obj name in the connection folder had
|
|||
|
changed while the cluster service was stopped on that node.
|
|||
|
|
|||
|
If a collision is detected, the existing name is changed to
|
|||
|
have an "(previous)" appended to it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NetConnection - Connect object to set.
|
|||
|
|
|||
|
NewConnectoidName - new name
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Win32 error status
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD status = E_UNEXPECTED;
|
|||
|
INetConnection * connectoidObj;
|
|||
|
LPWSTR tempName;
|
|||
|
ULONG iteration = 2;
|
|||
|
GUIDSTR connectoidGuid;
|
|||
|
|
|||
|
//
|
|||
|
// first see if there is a collision with the new name. If so,
|
|||
|
// we'll rename the collided name, since we need to make all
|
|||
|
// the cluster connectoids the same.
|
|||
|
//
|
|||
|
connectoidObj = ClRtlFindConnectoidByName( NewConnectoidName );
|
|||
|
|
|||
|
if ( connectoidObj != NULL ) {
|
|||
|
NETCON_PROPERTIES * NcProps = NULL;
|
|||
|
|
|||
|
|
|||
|
status = INetConnection_GetProperties(connectoidObj, &NcProps);
|
|||
|
|
|||
|
if (SUCCEEDED( status )) {
|
|||
|
|
|||
|
GuidToStr(&NcProps->guidId, connectoidGuid);
|
|||
|
NcFreeNetconProperties( NcProps );
|
|||
|
}
|
|||
|
else {
|
|||
|
wsprintf(
|
|||
|
&(connectoidGuid[0]),
|
|||
|
L"????????-????-????-????-??????????????"
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
ClRtlLogPrint(LOG_UNUSUAL,
|
|||
|
"[ClNet] New connectoid name '%1!ws!' collides with name of "
|
|||
|
"existing connectoid (%2!ws!). Renaming existing connectoid.\n",
|
|||
|
NewConnectoidName,
|
|||
|
connectoidGuid
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// allocate enough space for the connectoid name with a trailing
|
|||
|
// "(ddd)". 3 digits for the number should be enough
|
|||
|
//
|
|||
|
tempName = LocalAlloc(
|
|||
|
LMEM_FIXED,
|
|||
|
(wcslen( NewConnectoidName ) + 6) * sizeof(WCHAR)
|
|||
|
);
|
|||
|
|
|||
|
if ( tempName == NULL ) {
|
|||
|
INetConnection_Release( connectoidObj );
|
|||
|
return ERROR_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
do {
|
|||
|
wsprintf( tempName, L"%s(%u)", NewConnectoidName, iteration++ );
|
|||
|
status = INetConnection_Rename( connectoidObj, tempName );
|
|||
|
} while ( !SUCCEEDED( status ) && iteration <= 999 );
|
|||
|
|
|||
|
if ( iteration > 999 ) {
|
|||
|
ClRtlLogPrint(LOG_UNUSUAL,
|
|||
|
"[ClNet] Failed to create a unique name for connectoid "
|
|||
|
"'%1!ws!' (%2!ws!)\n",
|
|||
|
NewConnectoidName,
|
|||
|
connectoidGuid
|
|||
|
);
|
|||
|
|
|||
|
INetConnection_Release( connectoidObj );
|
|||
|
|
|||
|
return(ERROR_DUP_NAME);
|
|||
|
}
|
|||
|
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[ClNet] Renamed existing connectoid '%1!ws!' (%2!ws!) to '%3!ws!' "
|
|||
|
"due to a collision with the name of cluster network.\n",
|
|||
|
NewConnectoidName,
|
|||
|
connectoidGuid,
|
|||
|
tempName
|
|||
|
);
|
|||
|
|
|||
|
INetConnection_Release( connectoidObj );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// now set the connectoid to the new name
|
|||
|
//
|
|||
|
status = INetConnection_Rename( NetConnection, NewConnectoidName );
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
} // ClRtlSetConnectoidName
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ClRtlFindConnectoidByNameAndSetName(
|
|||
|
LPWSTR ConnectoidName,
|
|||
|
LPWSTR NewConnectoidName
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD status = E_UNEXPECTED;
|
|||
|
INetConnection * connectoidObj;
|
|||
|
|
|||
|
connectoidObj = ClRtlFindConnectoidByName( ConnectoidName );
|
|||
|
|
|||
|
if ( connectoidObj != NULL ) {
|
|||
|
status = ClRtlSetConnectoidName(connectoidObj, NewConnectoidName);
|
|||
|
|
|||
|
INetConnection_Release( connectoidObj );
|
|||
|
}
|
|||
|
else {
|
|||
|
status = GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
return(status);
|
|||
|
|
|||
|
} // ClRtlFindConnectoidByNameAndSetName
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ClRtlFindConnectoidByGuidAndSetName(
|
|||
|
LPWSTR ConnectoidGuid,
|
|||
|
LPWSTR NewConnectoidName
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD status = E_UNEXPECTED;
|
|||
|
INetConnection * connectoidObj;
|
|||
|
|
|||
|
connectoidObj = ClRtlFindConnectoidByGuid( ConnectoidGuid );
|
|||
|
|
|||
|
if ( connectoidObj != NULL ) {
|
|||
|
status = ClRtlSetConnectoidName(connectoidObj, NewConnectoidName);
|
|||
|
|
|||
|
INetConnection_Release( connectoidObj );
|
|||
|
}
|
|||
|
else {
|
|||
|
status = GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
return(status);
|
|||
|
|
|||
|
} // ClRtlFindConnectoidByGuidAndSetName
|
|||
|
|
|||
|
|