[IPHLPAPI]

- Rewrite name server enumeration routines
- Check if static dns entries are present before checking for dynamic dns entries
- Fixes static dns entries
[NETCFGX]
- GetPerAdapterInfo requires IP_PER_ADAPTER_INFO struct
- Fix reading static dns entries
- Delete static name server key, when changing dns servers to automatic (dhcp)
- Don't delete DhcpNameServer key yet, as more interaction is needed with dhcp service when changing from static dns to dynamic dhcp
- Should finally fix static dns when dhcp is active

svn path=/trunk/; revision=50257
This commit is contained in:
Johannes Anderwald
2011-01-01 21:13:07 +00:00
parent 3062a63e47
commit 3f0d2fffb3
4 changed files with 320 additions and 162 deletions
+5 -1
View File
@@ -1622,7 +1622,11 @@ DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterIn
return ERROR_BUFFER_OVERFLOW;
}
if(RegQueryValueExW(hkey, L"DHCPNameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
if(RegQueryValueExW(hkey, L"NameServer", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS)
{
pPerAdapterInfo->AutoconfigActive = FALSE;
}
else
{
pPerAdapterInfo->AutoconfigActive = TRUE;
}
@@ -147,7 +147,7 @@ BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe );
typedef VOID (*EnumNameServersFunc)( PWCHAR Interface,
PWCHAR NameServer,
PVOID Data );
void EnumNameServers( HANDLE RegHandle, PWCHAR Interface, PVOID Data, EnumNameServersFunc cb );
LSTATUS EnumNameServers( HKEY RegHandle, LPWSTR Interface, PVOID Data, EnumNameServersFunc cb );
NTSTATUS getIPAddrEntryForIf(HANDLE tcpFile,
char *name,
DWORD index,
+302 -151
View File
@@ -52,197 +52,348 @@ typedef struct _NAME_SERVER_LIST_PRIVATE {
IP_ADDR_STRING * pCurrent;
} NAME_SERVER_LIST_PRIVATE, *PNAME_SERVER_LIST_PRIVATE;
NTSYSAPI
PVOID
NTAPI
RtlAllocateHeap (
HANDLE Heap,
ULONG Flags,
SIZE_T Size
);
typedef VOID (*ENUM_INTERFACE_CALLBACK)(
HKEY ChildKeyHandle,
LPWSTR ChildKeyName,
PVOID CallbackContext);
NTSYSAPI
BOOLEAN
NTAPI
RtlFreeHeap (
HANDLE Heap,
ULONG Flags,
PVOID Address
);
LSTATUS
QueryNameServer(
IN HKEY hInterface,
IN LPCWSTR NameServerKey,
OUT LPWSTR * OutNameServer)
{
DWORD dwLength, dwType;
LPWSTR NameServer;
LSTATUS Status;
NTSYSAPI
NTSTATUS
NTAPI
RtlUnicodeToMultiByteN (
PCHAR MbString,
ULONG MbSize,
PULONG ResultSize,
PWCHAR UnicodeString,
ULONG UnicodeSize
);
/* query ns */
dwLength = 0;
Status = RegQueryValueExW(hInterface, NameServerKey, NULL, &dwType, NULL, &dwLength);
typedef VOID (*EnumInterfacesFunc)( HKEY ChildKeyHandle,
PWCHAR ChildKeyName,
PVOID Data );
/*
* EnumInterfaces
*
* Call the enumeration function for each name server.
*/
static void EnumInterfaces( PVOID Data, EnumInterfacesFunc cb ) {
HKEY RegHandle;
HKEY ChildKeyHandle = 0;
PWCHAR RegKeyToEnumerate =
L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
PWCHAR ChildKeyName = 0;
DWORD CurrentInterface;
if (OpenChildKeyRead(HKEY_LOCAL_MACHINE,RegKeyToEnumerate,&RegHandle)) {
return;
}
for (CurrentInterface = 0; TRUE; CurrentInterface++) {
ChildKeyName = GetNthChildKeyName( RegHandle, CurrentInterface );
if (!ChildKeyName) break;
if (OpenChildKeyRead(RegHandle,ChildKeyName,
&ChildKeyHandle) == 0) {
cb( ChildKeyHandle, ChildKeyName, Data );
RegCloseKey( ChildKeyHandle );
}
ConsumeChildKeyName( ChildKeyName );
}
}
/*
* EnumNameServers
*/
void EnumNameServers( HANDLE RegHandle, PWCHAR Interface,
PVOID Data, EnumNameServersFunc cb ) {
PWCHAR NameServerString =
QueryRegistryValueString(RegHandle, L"DhcpNameServer");
if (!NameServerString)
NameServerString = QueryRegistryValueString(RegHandle, L"NameServer");
if (NameServerString) {
/* Now, count the non-empty comma separated */
DWORD ch;
DWORD LastNameStart = 0;
for (ch = 0; NameServerString[ch]; ch++) {
if (NameServerString[ch] == ',') {
if (ch - LastNameStart > 0) { /* Skip empty entries */
PWCHAR NameServer =
malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
if (NameServer) {
memcpy(NameServer,NameServerString + LastNameStart,
(ch - LastNameStart) * sizeof(WCHAR));
NameServer[ch - LastNameStart] = 0;
cb( Interface, NameServer, Data );
free(NameServer);
LastNameStart = ch +1;
}
}
LastNameStart = ch + 1; /* The first one after the comma */
}
}
if (ch - LastNameStart > 0) { /* A last name? */
PWCHAR NameServer = malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
if (NameServer) {
memcpy(NameServer,NameServerString + LastNameStart,
(ch - LastNameStart) * sizeof(WCHAR));
NameServer[ch - LastNameStart] = 0;
cb( Interface, NameServer, Data );
free(NameServer);
}
}
ConsumeRegValueString(NameServerString);
if (Status != ERROR_SUCCESS)
{
/* failed to retrieve size */
DbgPrint("Status %x\n", Status);
return Status;
}
/* add terminating null */
dwLength += sizeof(WCHAR);
/* allocate name server */
NameServer = HeapAlloc(GetProcessHeap(), 0, dwLength);
if (!NameServer)
{
/* no memory */
return ERROR_OUTOFMEMORY;
}
/* query ns */
Status = RegQueryValueExW(hInterface, NameServerKey, NULL, &dwType, (LPBYTE)NameServer, &dwLength);
if (Status != ERROR_SUCCESS || dwType != REG_SZ)
{
/* failed to retrieve ns */
HeapFree(GetProcessHeap(), 0, NameServer);
return Status;
}
/* null terminate it */
NameServer[dwLength / sizeof(WCHAR)] = L'\0';
/* store result */
*OutNameServer = NameServer;
return STATUS_SUCCESS;
}
static void CreateNameServerListEnumNamesFuncCount( PWCHAR Interface,
PWCHAR Server,
PVOID _Data ) {
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
LSTATUS
EnumNameServers(
IN HKEY hInterface,
IN LPWSTR InterfaceName,
PVOID ServerCallbackContext,
EnumNameServersFunc CallbackRoutine)
{
LSTATUS Status;
LPWSTR NameServer;
WCHAR Buffer[50];
DWORD Length;
LPWSTR Start, Comma;
/* query static assigned name server */
Status = QueryNameServer(hInterface, L"NameServer", &NameServer);
if (Status != ERROR_SUCCESS)
{
/* query dynamic assigned name server */
Status = QueryNameServer(hInterface, L"DhcpNameServer", &NameServer);
if (Status != ERROR_SUCCESS)
{
/* failed to retrieve name servers */
return Status;
}
}
/* enumerate all name servers, terminated by comma */
Start = NameServer;
do
{
/* find next terminator */
Comma = wcschr(Start, L',');
if (Comma)
{
/* calculate length */
Length = Comma - Start;
/* copy name server */
RtlMoveMemory(Buffer, Start, Length * sizeof(WCHAR));
/* null terminate it */
Buffer[Length] = L'\0';
/* perform callback */
CallbackRoutine(InterfaceName, Buffer, ServerCallbackContext);
}
else
{
/* perform callback */
CallbackRoutine(InterfaceName, Start, ServerCallbackContext);
/* last entry */
break;
}
/* increment offset */
Start = Comma + 1;
}while(TRUE);
/* free name server string */
HeapFree(GetProcessHeap(), 0, NameServer);
/* done */
return ERROR_SUCCESS;
}
LSTATUS
EnumInterfaces(
ENUM_INTERFACE_CALLBACK CallbackRoutine,
PVOID InterfaceCallbackContext)
{
HKEY hKey, hInterface;
LSTATUS Status;
DWORD NumInterfaces, InterfaceNameLen, Index, Length;
LPWSTR InterfaceName;
/* first open interface key */
Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ, &hKey);
/* check for success */
if (Status != ERROR_SUCCESS)
{
/* failed to open interface key */
return Status;
}
/* now get maximum interface name length and number of interfaces */
Status = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &NumInterfaces, &InterfaceNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (Status != ERROR_SUCCESS)
{
/* failed to get key info */
RegCloseKey(hKey);
return Status;
}
/* RegQueryInfoKey does not include terminating null */
InterfaceNameLen++;
/* allocate interface name */
InterfaceName = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, InterfaceNameLen * sizeof(WCHAR));
if (!InterfaceName)
{
/* no memory */
RegCloseKey(hKey);
return ERROR_OUTOFMEMORY;
}
/* no enumerate all interfaces */
for(Index = 0; Index < NumInterfaces; Index++)
{
/* query interface name */
Length = InterfaceNameLen;
Status = RegEnumKeyExW(hKey, Index, InterfaceName, &Length, NULL, NULL, NULL, NULL);
if (Status == ERROR_SUCCESS)
{
/* make sure it is null terminated */
InterfaceName[Length] = L'\0';
/* now open child key */
Status = RegOpenKeyExW(hKey, InterfaceName, 0, KEY_READ, &hInterface);
if (Status == ERROR_SUCCESS)
{
/* perform enumeration callback */
CallbackRoutine(hInterface, InterfaceName, InterfaceCallbackContext);
/* close interface key */
RegCloseKey(hInterface);
}
}
}
/* free interface name */
HeapFree(GetProcessHeap(), 0, InterfaceName);
/* close root interface key */
RegCloseKey(hKey);
/* done */
return Status;
}
VOID
CountNameServerCallback(
IN LPWSTR InterfaceName,
IN LPWSTR Server,
IN PVOID CallbackContext)
{
/* get context */
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)CallbackContext;
/* increment server count */
Data->NumServers++;
}
static void CreateNameServerListEnumIfFuncCount( HKEY RegHandle,
PWCHAR InterfaceName,
PVOID _Data ) {
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
EnumNameServers(RegHandle,InterfaceName,Data,
CreateNameServerListEnumNamesFuncCount);
VOID
CountServerCallbackTrampoline(
HKEY ChildKeyHandle,
LPWSTR ChildKeyName,
PVOID CallbackContext)
{
EnumNameServers(ChildKeyHandle, ChildKeyName, CallbackContext, CountNameServerCallback);
}
VOID CreateNameServerListEnumNamesFunc(
PWCHAR Interface,
PWCHAR Server,
PVOID _Data )
LSTATUS
CountNameServers(
IN PNAME_SERVER_LIST_PRIVATE PrivateData )
{
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
return EnumInterfaces(CountServerCallbackTrampoline, (PVOID)PrivateData);
}
VOID
CreateNameServerListCallback(
IN LPWSTR InterfaceName,
IN LPWSTR Server,
IN PVOID CallbackContext)
{
/* get context */
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)CallbackContext;
/* convert to ansi ns string */
if (WideCharToMultiByte(CP_ACP, 0, Server, -1, Data->pCurrent->IpAddress.String, 16, NULL, NULL))
{
Data->pCurrent->Next = (struct _IP_ADDR_STRING*)(char*)Data->pCurrent + sizeof(IP_ADDR_STRING);
/* store offset to next name server struct */
Data->pCurrent->Next = (struct _IP_ADDR_STRING*)(Data->pCurrent + 1);
/* move to next entry */
Data->pCurrent = Data->pCurrent->Next;
/* increment server count */
Data->NumServers++;
}
else
{
/* failed to convert dns server */
Data->pCurrent->IpAddress.String[0] = '\0';
}
}
static void CreateNameServerListEnumIfFunc( HKEY RegHandle,
PWCHAR InterfaceName,
PVOID _Data ) {
PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
EnumNameServers(RegHandle,InterfaceName,Data,
CreateNameServerListEnumNamesFunc);
VOID
CreateNameServerListCallbackTrampoline(
HKEY ChildKeyHandle,
LPWSTR ChildKeyName,
PVOID CallbackContext)
{
EnumNameServers(ChildKeyHandle, ChildKeyName, CallbackContext, CreateNameServerListCallback);
}
static int CountNameServers( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
EnumInterfaces(PrivateData,CreateNameServerListEnumIfFuncCount);
return PrivateData->NumServers;
LSTATUS
MakeNameServerList(
PNAME_SERVER_LIST_PRIVATE PrivateData )
{
return EnumInterfaces(CreateNameServerListCallbackTrampoline, (PVOID)PrivateData);
}
static void MakeNameServerList( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
EnumInterfaces(PrivateData,CreateNameServerListEnumIfFunc);
}
PIPHLP_RES_INFO getResInfo() {
DWORD ServerCount;
PIPHLP_RES_INFO
getResInfo()
{
NAME_SERVER_LIST_PRIVATE PrivateNSEnum;
PIPHLP_RES_INFO ResInfo;
IP_ADDR_STRING * DnsList;
IP_ADDR_STRING * DnsList = NULL;
LSTATUS Status;
PrivateNSEnum.NumServers = 0;
ServerCount = CountNameServers( &PrivateNSEnum );
PrivateNSEnum.NumServers = ServerCount;
DnsList = HeapAlloc(GetProcessHeap(), 0, ServerCount * sizeof(IP_ADDR_STRING));
if (!DnsList) return NULL;
/* count name servers */
Status = CountNameServers(&PrivateNSEnum);
ZeroMemory(DnsList, ServerCount * sizeof(IP_ADDR_STRING));
ResInfo = (PIPHLP_RES_INFO)RtlAllocateHeap ( GetProcessHeap(), 0, sizeof(IPHLP_RES_INFO));
if( !ResInfo )
if (Status != ERROR_SUCCESS)
{
HeapFree( GetProcessHeap(), 0, DnsList );
/* failed to enumerate name servers */
return NULL;
}
PrivateNSEnum.NumServers = 0;
PrivateNSEnum.pCurrent = DnsList;
/* are there any servers */
if (PrivateNSEnum.NumServers)
{
/* allocate dns servers */
DnsList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PrivateNSEnum.NumServers * sizeof(IP_ADDR_STRING));
MakeNameServerList( &PrivateNSEnum );
ResInfo->DnsList = DnsList;
ResInfo->riCount = PrivateNSEnum.NumServers;
if (!DnsList)
{
/* no memory */
return NULL;
}
}
/* allocate private struct */
ResInfo = (PIPHLP_RES_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IPHLP_RES_INFO));
if(!ResInfo)
{
/* no memory */
if (DnsList)
{
/* free dns list */
HeapFree( GetProcessHeap(), 0, DnsList);
}
return NULL;
}
/* are there any servers */
if (PrivateNSEnum.NumServers)
{
/* initialize enumeration context */
PrivateNSEnum.NumServers = 0;
PrivateNSEnum.pCurrent = DnsList;
/* enumerate servers */
MakeNameServerList( &PrivateNSEnum );
/* store result */
ResInfo->DnsList = DnsList;
ResInfo->riCount = PrivateNSEnum.NumServers;
}
/* done */
return ResInfo;
}
+12 -9
View File
@@ -2765,11 +2765,12 @@ LoadFilterSettings(
HRESULT
Initialize(TcpipConfNotifyImpl * This)
{
DWORD dwSize;
DWORD dwSize, Status;
WCHAR szBuffer[50];
IP_ADAPTER_INFO * pCurrentAdapter;
IP_ADAPTER_INFO * pInfo;
PIP_PER_ADAPTER_INFO pPerInfo;
IP_PER_ADAPTER_INFO Info;
LPOLESTR pStr;
HRESULT hr;
BOOL bFound;
@@ -2846,13 +2847,17 @@ Initialize(TcpipConfNotifyImpl * This)
CopyIpAddrString(&pCurrentAdapter->IpAddressList, &pCurSettings->Ip, SUBMASK, NULL);
CopyIpAddrString(&pCurrentAdapter->GatewayList, &pCurSettings->Gw, METRIC, NULL); //FIXME
}
uLength = 0;
if (GetPerAdapterInfo(pCurrentAdapter->Index, NULL, &uLength) == ERROR_BUFFER_OVERFLOW)
uLength = sizeof(IP_PER_ADAPTER_INFO);
ZeroMemory(&Info, sizeof(IP_PER_ADAPTER_INFO));
if (GetPerAdapterInfo(pCurrentAdapter->Index, &Info, &uLength) == ERROR_BUFFER_OVERFLOW)
{
pPerInfo = (PIP_PER_ADAPTER_INFO)CoTaskMemAlloc(uLength);
if (pPerInfo)
{
if (GetPerAdapterInfo(pCurrentAdapter->Index, pPerInfo, &uLength) == NOERROR)
Status = GetPerAdapterInfo(pCurrentAdapter->Index, pPerInfo, &uLength);
if (Status == NOERROR)
{
if (!pPerInfo->AutoconfigActive)
{
@@ -2862,9 +2867,8 @@ Initialize(TcpipConfNotifyImpl * This)
}
CoTaskMemFree(pPerInfo);
}
}
if (FAILED(LoadFilterSettings(This)))
return E_FAIL;
@@ -3284,16 +3288,15 @@ INetCfgComponentControl_fnApplyRegistryChanges(
if (!pCurrentConfig->Ns || pCurrentConfig->AutoconfigActive)
{
RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)L"", 1 * sizeof(WCHAR));
RegDeleteValueW(hKey, L"NameServer");
}
else
{
pStr = CreateMultiSzString(pCurrentConfig->Ns, IPADDR, &dwSize, TRUE);
if(pStr)
{
RegSetValueExW(hKey, L"NameServer", 0, REG_SZ, (LPBYTE)pStr, dwSize);
RegDeleteValueW(hKey, L"DhcpNameServer");
//RegDeleteValueW(hKey, L"DhcpNameServer");
CoTaskMemFree(pStr);
}
}