You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
675 lines
13 KiB
675 lines
13 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
iphlpapi\lanmap.c
|
|
|
|
Abstract:
|
|
|
|
This module maps lan adapter GUIDs to friendly names.
|
|
|
|
Revision History:
|
|
|
|
AmritanR Created
|
|
|
|
--*/
|
|
|
|
#include "inc.h"
|
|
|
|
LIST_ENTRY g_LanGuidHashTable[LAN_HASH_TABLE_SIZE];
|
|
LIST_ENTRY g_LanNameHashTable[LAN_HASH_TABLE_SIZE];
|
|
CRITICAL_SECTION g_LanTableLock;
|
|
|
|
|
|
ULONG
|
|
__inline
|
|
LAN_NAME_HASH(
|
|
IN PWCHAR pwszName
|
|
)
|
|
{
|
|
ULONG ulLen, ulNumChars, i, ulIndex = 0;
|
|
|
|
ulLen = (ULONG)wcslen(pwszName);
|
|
|
|
ulNumChars = ulLen < 6 ? ulLen : 6;
|
|
|
|
ulLen--;
|
|
|
|
for(i = 0; i < ulNumChars; i++)
|
|
{
|
|
ulIndex += pwszName[i];
|
|
ulIndex += pwszName[ulLen - i];
|
|
}
|
|
|
|
return ulIndex % LAN_HASH_TABLE_SIZE;
|
|
}
|
|
|
|
DWORD
|
|
InitLanNameMapper(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
for(i = 0; i < LAN_HASH_TABLE_SIZE; i ++)
|
|
{
|
|
InitializeListHead(&(g_LanGuidHashTable[i]));
|
|
InitializeListHead(&(g_LanNameHashTable[i]));
|
|
}
|
|
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&g_LanTableLock);
|
|
}
|
|
__except((GetExceptionCode() == STATUS_NO_MEMORY)
|
|
? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
DeinitLanNameMapper(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
for(i = 0; i < LAN_HASH_TABLE_SIZE; i ++)
|
|
{
|
|
while(!IsListEmpty(&(g_LanGuidHashTable[i])))
|
|
{
|
|
PLIST_ENTRY pleNode;
|
|
|
|
pleNode = RemoveHeadList(&(g_LanGuidHashTable[i]));
|
|
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
pleNode);
|
|
}
|
|
}
|
|
|
|
DeleteCriticalSection(&g_LanTableLock);
|
|
}
|
|
|
|
|
|
DWORD
|
|
OpenConnectionKey(
|
|
IN GUID *pGuid,
|
|
OUT PHKEY phkey
|
|
)
|
|
{
|
|
WCHAR wszGuid[40];
|
|
WCHAR wszRegPath[RTL_NUMBER_OF(CONN_KEY_FORMAT_W) +
|
|
RTL_NUMBER_OF(wszGuid) + 2];
|
|
DWORD dwResult;
|
|
|
|
*phkey = NULL;
|
|
|
|
ConvertGuidToString(pGuid,
|
|
wszGuid);
|
|
|
|
wsprintfW(wszRegPath,
|
|
CONN_KEY_FORMAT_W,
|
|
wszGuid);
|
|
|
|
dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
wszRegPath,
|
|
0,
|
|
KEY_READ,
|
|
phkey);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
NhiGetLanConnectionNameFromGuid(
|
|
IN GUID *pGuid,
|
|
OUT PWCHAR pwszBuffer,
|
|
IN OUT PULONG pulBufferLength,
|
|
IN BOOL bRefresh,
|
|
IN BOOL bCache
|
|
)
|
|
{
|
|
DWORD dwType, dwResult;
|
|
HKEY hkey;
|
|
PLAN_NODE pNode;
|
|
|
|
if(*pulBufferLength < (MAX_INTERFACE_NAME_LEN * sizeof(WCHAR)))
|
|
{
|
|
*pulBufferLength = MAX_INTERFACE_NAME_LEN * sizeof(WCHAR);
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
if(!bCache)
|
|
{
|
|
dwResult = OpenConnectionKey(pGuid,
|
|
&hkey);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
return dwResult;
|
|
}
|
|
|
|
dwResult = RegQueryValueExW(hkey,
|
|
REG_VALUE_CONN_NAME_W,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)pwszBuffer,
|
|
pulBufferLength);
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
return dwResult;
|
|
}
|
|
|
|
if(dwType isnot REG_SZ)
|
|
{
|
|
return ERROR_REGISTRY_CORRUPT;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Lock the table
|
|
//
|
|
|
|
EnterCriticalSection(&g_LanTableLock);
|
|
|
|
if(bRefresh)
|
|
{
|
|
//
|
|
// refresh the cache
|
|
//
|
|
|
|
dwResult = UpdateLanLookupTable();
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return dwResult;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now lookup the table
|
|
//
|
|
|
|
pNode = LookupLanNodeByGuid(pGuid);
|
|
|
|
if(pNode is NULL)
|
|
{
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return ERROR_NOT_FOUND;
|
|
}
|
|
|
|
wcscpy(pwszBuffer,
|
|
pNode->rgwcName);
|
|
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
NhiGetGuidFromLanConnectionName(
|
|
IN PWCHAR pwszName,
|
|
OUT GUID *pGuid,
|
|
IN BOOL bRefresh,
|
|
IN BOOL bCache
|
|
)
|
|
{
|
|
DWORD dwResult;
|
|
PLAN_NODE pNode;
|
|
|
|
UNREFERENCED_PARAMETER(bCache);
|
|
|
|
//
|
|
// Lock the table
|
|
//
|
|
|
|
EnterCriticalSection(&g_LanTableLock);
|
|
|
|
if(bRefresh)
|
|
{
|
|
//
|
|
// refresh the cache
|
|
//
|
|
|
|
dwResult = UpdateLanLookupTable();
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return dwResult;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now lookup the table
|
|
//
|
|
|
|
pNode = LookupLanNodeByName(pwszName);
|
|
|
|
if(pNode is NULL)
|
|
{
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return ERROR_NOT_FOUND;
|
|
}
|
|
|
|
*pGuid = pNode->Guid;
|
|
|
|
LeaveCriticalSection(&g_LanTableLock);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
NhiGetLanConnectionDescriptionFromGuid(
|
|
IN GUID *pGuid,
|
|
OUT PWCHAR pwszBuffer,
|
|
IN OUT PULONG pulBufferSize,
|
|
IN BOOL bCache,
|
|
IN BOOL bRefresh
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(pGuid);
|
|
UNREFERENCED_PARAMETER(pwszBuffer);
|
|
UNREFERENCED_PARAMETER(pulBufferSize);
|
|
UNREFERENCED_PARAMETER(bCache);
|
|
UNREFERENCED_PARAMETER(bRefresh);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
PLAN_NODE
|
|
LookupLanNodeByGuid(
|
|
IN GUID *pGuid
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Looks up the ipip node in the hash table
|
|
|
|
Locks:
|
|
|
|
Called with the ipip table lock held
|
|
|
|
Arguments:
|
|
|
|
pGuid Guid for the node
|
|
|
|
Return Value:
|
|
|
|
LanNode if found
|
|
NULL otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ulIndex;
|
|
PLIST_ENTRY pleNode;
|
|
|
|
ulIndex = LAN_GUID_HASH(pGuid);
|
|
|
|
for(pleNode = g_LanGuidHashTable[ulIndex].Flink;
|
|
pleNode isnot &(g_LanGuidHashTable[ulIndex]);
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
PLAN_NODE pLanNode;
|
|
|
|
pLanNode = CONTAINING_RECORD(pleNode,
|
|
LAN_NODE,
|
|
leGuidLink);
|
|
|
|
if(IsEqualGUID(&(pLanNode->Guid),
|
|
pGuid))
|
|
{
|
|
return pLanNode;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
PLAN_NODE
|
|
LookupLanNodeByName(
|
|
IN PWCHAR pwszName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Looks up the ipip node in the hash table
|
|
|
|
Locks:
|
|
|
|
Called with the ipip table lock held
|
|
|
|
Arguments:
|
|
|
|
pwszName Name of the phonebook entry
|
|
|
|
Return Value:
|
|
|
|
RasNode if found
|
|
NULL otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ulIndex;
|
|
PLIST_ENTRY pleNode;
|
|
|
|
ulIndex = LAN_NAME_HASH(pwszName);
|
|
|
|
for(pleNode = g_LanNameHashTable[ulIndex].Flink;
|
|
pleNode isnot &(g_LanNameHashTable[ulIndex]);
|
|
pleNode = pleNode->Flink)
|
|
{
|
|
PLAN_NODE pLanNode;
|
|
|
|
pLanNode = CONTAINING_RECORD(pleNode,
|
|
LAN_NODE,
|
|
leNameLink);
|
|
|
|
if(_wcsicmp(pLanNode->rgwcName,
|
|
pwszName) is 0)
|
|
{
|
|
return pLanNode;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
AddLanNode(
|
|
IN GUID *pGuid,
|
|
IN PWCHAR pwszName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a node in the hash table for the given ipip info
|
|
|
|
Locks:
|
|
|
|
Called with the LAN table lock held
|
|
|
|
Arguments:
|
|
|
|
pInfo Lan name info
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
ERROR_NOT_ENOUGH_MEMORY
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ulGuidIndex, ulNameIndex;
|
|
PLAN_NODE pLanNode;
|
|
|
|
pLanNode = HeapAlloc(g_hPrivateHeap,
|
|
0,
|
|
sizeof(LAN_NODE));
|
|
|
|
if(pLanNode is NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pLanNode->Guid = *pGuid;
|
|
|
|
wcscpy(pLanNode->rgwcName,
|
|
pwszName);
|
|
|
|
ulGuidIndex = LAN_GUID_HASH(pGuid);
|
|
ulNameIndex = LAN_NAME_HASH(pwszName);
|
|
|
|
InsertHeadList(&(g_LanGuidHashTable[ulGuidIndex]),
|
|
&(pLanNode->leGuidLink));
|
|
|
|
InsertHeadList(&(g_LanNameHashTable[ulNameIndex]),
|
|
&(pLanNode->leNameLink));
|
|
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
RemoveLanNode(
|
|
IN PLAN_NODE pNode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes the given node from the hash tables
|
|
|
|
Locks:
|
|
|
|
Called with the LAN table lock held
|
|
|
|
Arguments:
|
|
|
|
pNode Node to remove
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
RemoveEntryList(&(pNode->leGuidLink));
|
|
RemoveEntryList(&(pNode->leNameLink));
|
|
}
|
|
|
|
|
|
DWORD
|
|
UpdateLanLookupTable(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to retrieve an array of LAN connections,
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
DWORD - Win32 status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN bCleanupOle = TRUE;
|
|
ULONG ulConCount;
|
|
HRESULT hrErr;
|
|
ULONG i, j;
|
|
DWORD dwResult;
|
|
|
|
INetConnection *rgpConArray[32];
|
|
NETCON_PROPERTIES *pLanProps;
|
|
INetConnectionManager *pConMan = NULL;
|
|
IEnumNetConnection *pEnumCon = NULL;
|
|
|
|
|
|
hrErr = CoInitializeEx(NULL,
|
|
COINIT_MULTITHREADED|COINIT_DISABLE_OLE1DDE);
|
|
|
|
if(!SUCCEEDED(hrErr))
|
|
{
|
|
if(hrErr is RPC_E_CHANGED_MODE)
|
|
{
|
|
bCleanupOle = FALSE;
|
|
}
|
|
else
|
|
{
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
}
|
|
|
|
i = 0;
|
|
|
|
for (;;)
|
|
{
|
|
//
|
|
// Instantiate the connection manager
|
|
//
|
|
|
|
hrErr = CoCreateInstance(&CLSID_ConnectionManager,
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
&IID_INetConnectionManager,
|
|
(PVOID*)&pConMan);
|
|
|
|
if(!SUCCEEDED(hrErr))
|
|
{
|
|
pConMan = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Instantiate a connection-enumerator
|
|
//
|
|
|
|
hrErr = INetConnectionManager_EnumConnections(pConMan,
|
|
NCME_DEFAULT,
|
|
&pEnumCon);
|
|
|
|
if(!SUCCEEDED(hrErr))
|
|
{
|
|
pEnumCon = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
hrErr = CoSetProxyBlanket((IUnknown*)pEnumCon,
|
|
RPC_C_AUTHN_WINNT,
|
|
RPC_C_AUTHN_NONE,
|
|
NULL,
|
|
RPC_C_AUTHN_LEVEL_CALL,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL,
|
|
EOAC_NONE);
|
|
|
|
//
|
|
// Enumerate the items
|
|
//
|
|
|
|
for (;;)
|
|
{
|
|
hrErr = IEnumNetConnection_Next(pEnumCon,
|
|
sizeof(rgpConArray)/sizeof(rgpConArray[0]),
|
|
rgpConArray,
|
|
&ulConCount);
|
|
|
|
if(!SUCCEEDED(hrErr) or
|
|
!ulConCount)
|
|
{
|
|
hrErr = S_OK;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Examine the properties for the connections retrieved
|
|
//
|
|
|
|
for(j = 0; j < ulConCount; j++)
|
|
{
|
|
hrErr = INetConnection_GetProperties(rgpConArray[j],
|
|
&pLanProps);
|
|
|
|
INetConnection_Release(rgpConArray[j]);
|
|
|
|
if (!SUCCEEDED(hrErr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(pLanProps->MediaType is NCM_LAN)
|
|
{
|
|
PLAN_NODE pNode;
|
|
|
|
pNode = LookupLanNodeByGuid(&(pLanProps->guidId));
|
|
|
|
if(!pNode)
|
|
{
|
|
dwResult = AddLanNode(&(pLanProps->guidId),
|
|
pLanProps->pszwName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Node exists, if different remove and re-add
|
|
//
|
|
|
|
if(_wcsicmp(pNode->rgwcName,
|
|
pLanProps->pszwName) isnot 0)
|
|
{
|
|
RemoveLanNode(pNode);
|
|
|
|
dwResult = AddLanNode(&(pLanProps->guidId),
|
|
pLanProps->pszwName);
|
|
}
|
|
}
|
|
}
|
|
|
|
CoTaskMemFree(pLanProps->pszwName);
|
|
CoTaskMemFree(pLanProps->pszwDeviceName);
|
|
CoTaskMemFree(pLanProps);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if(pEnumCon)
|
|
{
|
|
IEnumNetConnection_Release(pEnumCon);
|
|
}
|
|
|
|
if(pConMan)
|
|
{
|
|
INetConnectionManager_Release(pConMan);
|
|
}
|
|
|
|
if(bCleanupOle)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|