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.
1466 lines
32 KiB
1466 lines
32 KiB
/*++
|
|
|
|
Copyright (c) 1999-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) API
|
|
|
|
Configuration routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) September 1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
|
|
|
|
|
|
|
|
//
|
|
// Config mapping table.
|
|
//
|
|
// Maps config IDs into corresponding registry lookups.
|
|
//
|
|
|
|
typedef struct _ConfigMapping
|
|
{
|
|
DWORD ConfigId;
|
|
DWORD RegId;
|
|
BOOLEAN fAdapterAllowed;
|
|
BOOLEAN fAdapterRequired;
|
|
BYTE CharSet;
|
|
//BYTE Reserved;
|
|
}
|
|
CONFIG_MAPPING, *PCONFIG_MAPPING;
|
|
|
|
//
|
|
// Mapping table
|
|
//
|
|
|
|
CONFIG_MAPPING ConfigMappingArray[] =
|
|
{
|
|
// In Win2K
|
|
|
|
DnsConfigPrimaryDomainName_W,
|
|
RegIdPrimaryDomainName,
|
|
0,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
|
|
DnsConfigPrimaryDomainName_A,
|
|
RegIdPrimaryDomainName,
|
|
0,
|
|
0,
|
|
DnsCharSetAnsi,
|
|
|
|
DnsConfigPrimaryDomainName_UTF8,
|
|
RegIdPrimaryDomainName,
|
|
0,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
|
|
// Not available
|
|
|
|
DnsConfigAdapterDomainName_W,
|
|
RegIdAdapterDomainName,
|
|
1,
|
|
1,
|
|
DnsCharSetUnicode,
|
|
|
|
DnsConfigAdapterDomainName_A,
|
|
RegIdAdapterDomainName,
|
|
1,
|
|
1,
|
|
DnsCharSetAnsi,
|
|
|
|
DnsConfigAdapterDomainName_UTF8,
|
|
RegIdAdapterDomainName,
|
|
1,
|
|
1,
|
|
DnsCharSetUtf8,
|
|
|
|
// In Win2K
|
|
|
|
DnsConfigDnsServerList,
|
|
RegIdDnsServers,
|
|
1, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
|
|
// Not available
|
|
|
|
DnsConfigSearchList,
|
|
RegIdSearchList,
|
|
0, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
|
|
DnsConfigAdapterInfo,
|
|
0, // no reg mapping
|
|
0, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
|
|
// In Win2K
|
|
|
|
DnsConfigPrimaryHostNameRegistrationEnabled,
|
|
RegIdRegisterPrimaryName,
|
|
1, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
DnsConfigAdapterHostNameRegistrationEnabled,
|
|
RegIdRegisterAdapterName,
|
|
1, // adapter allowed
|
|
0, // adapter note required
|
|
0,
|
|
DnsConfigAddressRegistrationMaxCount,
|
|
RegIdRegistrationMaxAddressCount,
|
|
1, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
|
|
// In WindowsXP
|
|
|
|
DnsConfigHostName_W,
|
|
RegIdHostName,
|
|
0,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
|
|
DnsConfigHostName_A,
|
|
RegIdHostName,
|
|
0,
|
|
0,
|
|
DnsCharSetAnsi,
|
|
|
|
DnsConfigHostName_UTF8,
|
|
RegIdHostName,
|
|
0,
|
|
0,
|
|
DnsCharSetUtf8,
|
|
|
|
// In WindowsXP
|
|
|
|
|
|
|
|
//
|
|
// System Public -- Windows XP
|
|
//
|
|
|
|
DnsConfigRegistrationEnabled,
|
|
RegIdRegistrationEnabled,
|
|
1, // adapter allowed
|
|
0, // not required
|
|
0,
|
|
|
|
DnsConfigWaitForNameErrorOnAll,
|
|
RegIdWaitForNameErrorOnAll,
|
|
0, // no adapter
|
|
0, // not required
|
|
0,
|
|
|
|
// These exist in system-public space but are
|
|
// not DWORDs and table is never used for them
|
|
//
|
|
// DnsConfigNetworkInformation:
|
|
// DnsConfigSearchInformation:
|
|
// DnsConfigNetInfo:
|
|
|
|
};
|
|
|
|
#define LAST_CONFIG_MAPPED (DnsConfigHostName_UTF8)
|
|
|
|
#define CONFIG_TABLE_LENGTH (sizeof(ConfigMappingArray) / sizeof(CONFIG_MAPPING))
|
|
|
|
|
|
|
|
PCONFIG_MAPPING
|
|
GetConfigToRegistryMapping(
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN PCWSTR pwsAdapterName,
|
|
IN BOOL fCheckAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get registry enum type for config enum type.
|
|
|
|
Purpose of this is to do mapping -- thus hiding internal
|
|
registry implemenation -- AND to do check on whether
|
|
adapter info is allowed or required for the config type.
|
|
|
|
Arguments:
|
|
|
|
ConfigId -- config type
|
|
|
|
pwsAdapterName -- adapter name
|
|
|
|
Return Value:
|
|
|
|
Ptr to config to registry mapping -- if found.
|
|
|
|
--*/
|
|
{
|
|
DWORD iter = 0;
|
|
PCONFIG_MAPPING pfig;
|
|
|
|
//
|
|
// find config
|
|
//
|
|
// note, using loop through config IDs; this allows
|
|
// use to have gap in config table allowing private
|
|
// ids well separated from public id space
|
|
//
|
|
|
|
while ( iter < CONFIG_TABLE_LENGTH )
|
|
{
|
|
pfig = & ConfigMappingArray[ iter ];
|
|
if ( pfig->ConfigId != (DWORD)ConfigId )
|
|
{
|
|
iter++;
|
|
continue;
|
|
}
|
|
goto Found;
|
|
}
|
|
goto Invalid;
|
|
|
|
|
|
Found:
|
|
|
|
//
|
|
// verify adapter info is appropriate to config type
|
|
//
|
|
|
|
if ( fCheckAdapter )
|
|
{
|
|
if ( pwsAdapterName )
|
|
{
|
|
if ( !pfig->fAdapterAllowed )
|
|
{
|
|
goto Invalid;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pfig->fAdapterRequired )
|
|
{
|
|
goto Invalid;
|
|
}
|
|
}
|
|
}
|
|
return pfig;
|
|
|
|
|
|
Invalid:
|
|
|
|
DNS_ASSERT( FALSE );
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
LookupDwordConfigValue(
|
|
OUT PDWORD pResult,
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN PWSTR pwsAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get registry enum type for config enum type.
|
|
|
|
Purpose of this is to do mapping -- thus hiding internal
|
|
registry implemenation -- AND to do check on whether
|
|
adapter info is allowed or required for the config type.
|
|
|
|
Arguments:
|
|
|
|
pResult -- address to recv DWORD result
|
|
|
|
ConfigId -- config type
|
|
|
|
pwsAdapter -- adapter name
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS on successful read.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
PCONFIG_MAPPING pfig;
|
|
DNS_STATUS status;
|
|
|
|
//
|
|
// verify config is known and mapped
|
|
//
|
|
|
|
pfig = GetConfigToRegistryMapping(
|
|
ConfigId,
|
|
pwsAdapter,
|
|
TRUE // check adapter validity
|
|
);
|
|
if ( !pfig )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// lookup in registry
|
|
//
|
|
|
|
status = Reg_GetDword(
|
|
NULL, // no session
|
|
NULL, // no key given
|
|
pwsAdapter,
|
|
pfig->RegId, // reg id for config type
|
|
pResult );
|
|
#if DBG
|
|
if ( status != NO_ERROR )
|
|
{
|
|
if ( status == ERROR_FILE_NOT_FOUND )
|
|
{
|
|
DNSDBG( REGISTRY, (
|
|
"Reg_GetDword() defaulted for config lookup!\n"
|
|
"\tConfigId = %d\n"
|
|
"\tRedId = %d\n"
|
|
"\tpwsAdapter = %S\n"
|
|
"\tValue = %d\n",
|
|
ConfigId,
|
|
pfig->RegId,
|
|
pwsAdapter,
|
|
*pResult ));
|
|
}
|
|
else
|
|
{
|
|
DNSDBG( ANY, (
|
|
"Reg_GetDword() failed for config lookup!\n"
|
|
"\tstatus = %d\n"
|
|
"\tConfigId = %d\n"
|
|
"\tRedId = %d\n"
|
|
"\tpwsAdapter = %S\n",
|
|
status,
|
|
ConfigId,
|
|
pfig->RegId,
|
|
pwsAdapter ));
|
|
|
|
ASSERT( status == NO_ERROR );
|
|
}
|
|
}
|
|
#endif
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Public Configuration API
|
|
//
|
|
|
|
DNS_STATUS
|
|
DnsQueryConfig(
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN DWORD Flag,
|
|
IN PWSTR pwsAdapterName,
|
|
IN PVOID pReserved,
|
|
OUT PVOID pBuffer,
|
|
IN OUT PDWORD pBufferLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get DNS configuration info.
|
|
|
|
Arguments:
|
|
|
|
ConfigId -- type of config info desired
|
|
|
|
Flag -- flags to query
|
|
|
|
pAdapterName -- name of adapter; NULL if no specific adapter
|
|
|
|
pReserved -- reserved parameter, should be NULL
|
|
|
|
pBuffer -- buffer to receive config info
|
|
|
|
pBufferLength -- addr of DWORD containing buffer length; on return
|
|
contains length
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS -- if query successful
|
|
ERROR_MORE_DATA -- if not enough space in buffer
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD bufLength = 0;
|
|
DWORD resultLength = 0;
|
|
PBYTE presult;
|
|
PBYTE pallocResult = NULL;
|
|
BOOL boolData;
|
|
DWORD dwordData;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"DnsQueryConfig()\n"
|
|
"\tconfig = %d\n"
|
|
"\tconfig = %08x\n"
|
|
"\tflag = %08x\n"
|
|
"\tadapter = %S\n"
|
|
"\tpBuffer = %p\n",
|
|
ConfigId,
|
|
ConfigId,
|
|
Flag,
|
|
pwsAdapterName,
|
|
pBuffer
|
|
));
|
|
|
|
//
|
|
// check out param setup
|
|
//
|
|
|
|
if ( !pBufferLength )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
if ( pBuffer )
|
|
{
|
|
bufLength = *pBufferLength;
|
|
}
|
|
|
|
//
|
|
// find specific configuration data requested
|
|
//
|
|
|
|
switch( ConfigId )
|
|
{
|
|
|
|
case DnsConfigPrimaryDomainName_W:
|
|
|
|
presult = (PBYTE) Reg_GetPrimaryDomainName( DnsCharSetUnicode );
|
|
goto WideString;
|
|
|
|
case DnsConfigPrimaryDomainName_A:
|
|
|
|
presult = (PBYTE) Reg_GetPrimaryDomainName( DnsCharSetAnsi );
|
|
goto NarrowString;
|
|
|
|
case DnsConfigPrimaryDomainName_UTF8:
|
|
|
|
presult = (PBYTE) Reg_GetPrimaryDomainName( DnsCharSetUtf8 );
|
|
goto NarrowString;
|
|
|
|
|
|
case DnsConfigDnsServerList:
|
|
|
|
presult = (PBYTE) Config_GetDnsServerListIp4(
|
|
pwsAdapterName,
|
|
TRUE // force registry read
|
|
);
|
|
if ( !presult )
|
|
{
|
|
status = GetLastError();
|
|
if ( status == NO_ERROR )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
}
|
|
goto Done;
|
|
}
|
|
pallocResult = presult;
|
|
resultLength = Dns_SizeofIpArray( (PIP4_ARRAY)presult );
|
|
goto Process;
|
|
|
|
|
|
case DnsConfigDnsServers:
|
|
case DnsConfigDnsServersIp4:
|
|
case DnsConfigDnsServersIp6:
|
|
|
|
{
|
|
DWORD family = 0;
|
|
|
|
if ( ConfigId == DnsConfigDnsServersIp4 )
|
|
{
|
|
family = AF_INET;
|
|
}
|
|
else if ( ConfigId == DnsConfigDnsServersIp6 )
|
|
{
|
|
family = AF_INET6;
|
|
}
|
|
|
|
presult = (PBYTE) Config_GetDnsServerList(
|
|
pwsAdapterName,
|
|
family, // desired address family
|
|
TRUE // force registry read
|
|
);
|
|
if ( !presult )
|
|
{
|
|
status = GetLastError();
|
|
if ( status == NO_ERROR )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
}
|
|
goto Done;
|
|
}
|
|
pallocResult = presult;
|
|
resultLength = DnsAddrArray_Sizeof( (PDNS_ADDR_ARRAY)presult );
|
|
goto Process;
|
|
}
|
|
|
|
case DnsConfigPrimaryHostNameRegistrationEnabled:
|
|
case DnsConfigAdapterHostNameRegistrationEnabled:
|
|
case DnsConfigAddressRegistrationMaxCount:
|
|
|
|
goto Dword;
|
|
|
|
//case DnsConfigAdapterDomainName:
|
|
//case DnsConfigAdapterInfo:
|
|
//case DnsConfigSearchList:
|
|
|
|
case DnsConfigHostName_W:
|
|
|
|
presult = (PBYTE) Reg_GetHostName( DnsCharSetUnicode );
|
|
goto WideString;
|
|
|
|
case DnsConfigHostName_A:
|
|
|
|
presult = (PBYTE) Reg_GetHostName( DnsCharSetAnsi );
|
|
goto NarrowString;
|
|
|
|
case DnsConfigHostName_UTF8:
|
|
|
|
presult = (PBYTE) Reg_GetHostName( DnsCharSetUtf8 );
|
|
goto NarrowString;
|
|
|
|
case DnsConfigFullHostName_W:
|
|
|
|
presult = (PBYTE) Reg_GetFullHostName( DnsCharSetUnicode );
|
|
goto WideString;
|
|
|
|
case DnsConfigFullHostName_A:
|
|
|
|
presult = (PBYTE) Reg_GetFullHostName( DnsCharSetAnsi );
|
|
goto NarrowString;
|
|
|
|
case DnsConfigFullHostName_UTF8:
|
|
|
|
presult = (PBYTE) Reg_GetFullHostName( DnsCharSetUtf8 );
|
|
goto NarrowString;
|
|
|
|
default:
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// setup return info for common types
|
|
//
|
|
// this just avoids code duplication above
|
|
//
|
|
|
|
Dword:
|
|
|
|
status = LookupDwordConfigValue(
|
|
& dwordData,
|
|
ConfigId,
|
|
pwsAdapterName );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
goto Done;
|
|
}
|
|
presult = (PBYTE) &dwordData;
|
|
resultLength = sizeof(DWORD);
|
|
goto Process;
|
|
|
|
|
|
NarrowString:
|
|
|
|
if ( !presult )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
pallocResult = presult;
|
|
resultLength = strlen( (PSTR)presult ) + 1;
|
|
goto Process;
|
|
|
|
|
|
WideString:
|
|
|
|
if ( !presult )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
pallocResult = presult;
|
|
resultLength = (wcslen( (PWSTR)presult ) + 1) * sizeof(WCHAR);
|
|
goto Process;
|
|
|
|
|
|
Process:
|
|
|
|
//
|
|
// return results -- three basic programs
|
|
// - no buffer => only return length required
|
|
// - allocate => return allocated result
|
|
// - supplied buffer => copy result into buffer
|
|
//
|
|
// note, this section only handles simple flag datablobs to aVOID
|
|
// duplicating code for specific config types above;
|
|
// when we add config types that require nested pointers, they must
|
|
// roll their own return-results code and jump to Done
|
|
//
|
|
|
|
//
|
|
// no buffer
|
|
// - no-op, length is set below
|
|
|
|
if ( !pBuffer )
|
|
{
|
|
}
|
|
|
|
//
|
|
// allocated result
|
|
// - return buffer gets ptr
|
|
// - allocate copy of result if not allocated
|
|
//
|
|
|
|
else if ( Flag & DNS_CONFIG_FLAG_ALLOC )
|
|
{
|
|
PBYTE pheap;
|
|
|
|
if ( bufLength < sizeof(PVOID) )
|
|
{
|
|
resultLength = sizeof(PVOID);
|
|
status = ERROR_MORE_DATA;
|
|
goto Done;
|
|
}
|
|
|
|
// create local alloc buffer
|
|
|
|
pheap = LocalAlloc( 0, resultLength );
|
|
if ( !pheap )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
RtlCopyMemory(
|
|
pheap,
|
|
presult,
|
|
resultLength );
|
|
|
|
// return ptr to allocated result
|
|
|
|
* (PVOID*) pBuffer = pheap;
|
|
}
|
|
|
|
//
|
|
// allocated result -- but dnsapi alloc
|
|
//
|
|
|
|
else if ( Flag & DNS_CONFIG_FLAG_DNSAPI_ALLOC )
|
|
{
|
|
if ( bufLength < sizeof(PVOID) )
|
|
{
|
|
resultLength = sizeof(PVOID);
|
|
status = ERROR_MORE_DATA;
|
|
goto Done;
|
|
}
|
|
|
|
// if result not allocated, alloc and copy it
|
|
|
|
if ( ! pallocResult )
|
|
{
|
|
pallocResult = ALLOCATE_HEAP( resultLength );
|
|
if ( !pallocResult )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
pallocResult,
|
|
presult,
|
|
resultLength );
|
|
}
|
|
|
|
// return ptr to allocated result
|
|
|
|
* (PVOID*) pBuffer = pallocResult;
|
|
|
|
// clear pallocResult, so not freed in generic cleanup
|
|
|
|
pallocResult = NULL;
|
|
}
|
|
|
|
//
|
|
// copy result to caller buffer
|
|
//
|
|
|
|
else
|
|
{
|
|
if ( bufLength < resultLength )
|
|
{
|
|
status = ERROR_MORE_DATA;
|
|
goto Done;
|
|
}
|
|
RtlCopyMemory(
|
|
pBuffer,
|
|
presult,
|
|
resultLength );
|
|
}
|
|
|
|
|
|
Done:
|
|
|
|
//
|
|
// set result length
|
|
// cleanup any allocated (but not returned) data
|
|
//
|
|
|
|
*pBufferLength = resultLength;
|
|
|
|
if ( pallocResult )
|
|
{
|
|
FREE_HEAP( pallocResult );
|
|
}
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// System Public Configuration API
|
|
//
|
|
|
|
PVOID
|
|
WINAPI
|
|
DnsQueryConfigAllocEx(
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN PWSTR pwsAdapterName,
|
|
IN BOOL fLocalAlloc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get DNS configuration info.
|
|
|
|
Allocate DNS configuration info.
|
|
This is the cover API both handling the system public API
|
|
DnsQueryConfigAlloc() below and the backward compatible
|
|
macros for the old hostname and PDN alloc routines (see dnsapi.h)
|
|
|
|
Arguments:
|
|
|
|
ConfigId -- type of config info desired
|
|
|
|
pAdapterName -- name of adapter; NULL if no specific adapter
|
|
|
|
fLocalAlloc -- allocate with LocalAlloc
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS -- if query successful
|
|
ERROR_MORE_DATA -- if not enough space in buffer
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD bufLength = sizeof(PVOID);
|
|
PBYTE presult = NULL;
|
|
|
|
DNSDBG( TRACE, (
|
|
"DnsQueryConfigAllocEx()\n"
|
|
"\tconfig = %d\n"
|
|
"\tconfig = %08x\n"
|
|
"\tadapter = %S\n"
|
|
"\tflocal = %d\n",
|
|
ConfigId,
|
|
ConfigId,
|
|
pwsAdapterName,
|
|
fLocalAlloc
|
|
));
|
|
|
|
|
|
//
|
|
// DCR: flags on config reading (resolver, cached, etc.)
|
|
//
|
|
|
|
|
|
//
|
|
// SDK-public types
|
|
//
|
|
|
|
if ( ConfigId < DnsConfigSystemBase )
|
|
{
|
|
//
|
|
// DCR: could screen here for alloc types
|
|
//
|
|
// DnsConfigPrimaryDomainName_W:
|
|
// DnsConfigPrimaryDomainName_A:
|
|
// DnsConfigPrimaryDomainName_UTF8:
|
|
// DnsConfigHostname_W:
|
|
// DnsConfigHostname_A:
|
|
// DnsConfigHostname_UTF8:
|
|
// DnsConfigDnsServerList:
|
|
//
|
|
|
|
status = DnsQueryConfig(
|
|
ConfigId,
|
|
fLocalAlloc
|
|
? DNS_CONFIG_FLAG_LOCAL_ALLOC
|
|
: DNS_CONFIG_FLAG_DNSAPI_ALLOC,
|
|
pwsAdapterName,
|
|
NULL, // reserved
|
|
& presult,
|
|
& bufLength );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
SetLastError( status );
|
|
return NULL;
|
|
}
|
|
return presult;
|
|
}
|
|
|
|
//
|
|
// System public types
|
|
//
|
|
|
|
if ( fLocalAlloc )
|
|
{
|
|
goto Invalid;
|
|
}
|
|
|
|
switch ( ConfigId )
|
|
{
|
|
|
|
// old public config blobs
|
|
|
|
case DnsConfigNetworkInformation:
|
|
|
|
return DnsNetworkInformation_Get();
|
|
|
|
case DnsConfigSearchInformation:
|
|
|
|
return DnsSearchInformation_Get();
|
|
|
|
// new public config blobs
|
|
|
|
case DnsConfigNetworkInfoA:
|
|
|
|
return DnsNetworkInfo_Get( DnsCharSetAnsi );
|
|
|
|
case DnsConfigSearchListA:
|
|
|
|
return DnsSearchList_Get( DnsCharSetAnsi );
|
|
|
|
case DnsConfigNetworkInfoW:
|
|
|
|
return DnsNetworkInfo_Get( DnsCharSetUnicode );
|
|
|
|
case DnsConfigSearchListW:
|
|
|
|
return DnsSearchList_Get( DnsCharSetUnicode );
|
|
|
|
case DnsConfigDwordGlobals:
|
|
|
|
//
|
|
// DCR: flags on config reading (resolver, cached, etc.)
|
|
//
|
|
|
|
//
|
|
// get globals
|
|
// not forcing registry read
|
|
// using from resolver if found
|
|
// then current (if netinfo blob cached)
|
|
//
|
|
// note, that whatever we return, even if from resolver, is
|
|
// (becomes) the current set for dnsapi.dll
|
|
//
|
|
|
|
return Config_GetDwordGlobals(
|
|
( NIFLAG_READ_RESOLVER_FIRST | NIFLAG_READ_PROCESS_CACHE ),
|
|
0 // default cache timeout
|
|
);
|
|
|
|
#if 0
|
|
case DnsConfigNetInfo:
|
|
|
|
return NetInfo_Get(
|
|
TRUE, // force
|
|
TRUE // include IP addresses
|
|
);
|
|
#endif
|
|
|
|
case DnsConfigIp4AddressArray:
|
|
|
|
// this called by gethostname( NULL ) => myhostent()
|
|
// - so handle cluster based on environment varaible
|
|
|
|
return NetInfo_GetLocalAddrArrayIp4(
|
|
pwsAdapterName,
|
|
DNS_CONFIG_FLAG_ADDR_PUBLIC |
|
|
DNS_CONFIG_FLAG_ADDR_PRIVATE |
|
|
DNS_CONFIG_FLAG_READ_CLUSTER_ENVAR,
|
|
FALSE // no force, accept from resolver
|
|
);
|
|
|
|
case DnsConfigLocalAddrsIp6:
|
|
case DnsConfigLocalAddrsIp4:
|
|
case DnsConfigLocalAddrs:
|
|
|
|
{
|
|
DWORD family = 0;
|
|
|
|
if ( ConfigId == DnsConfigLocalAddrsIp6 )
|
|
{
|
|
family = AF_INET6;
|
|
}
|
|
else if ( ConfigId == DnsConfigLocalAddrsIp4 )
|
|
{
|
|
family = AF_INET;
|
|
}
|
|
|
|
return NetInfo_GetLocalAddrArray(
|
|
NULL, // no existing netinfo
|
|
pwsAdapterName,
|
|
family, // address family
|
|
DNS_CONFIG_FLAG_ADDR_ALL, // all addrs
|
|
TRUE // force rebuild
|
|
);
|
|
}
|
|
|
|
// unknown falls through to invalid
|
|
}
|
|
|
|
Invalid:
|
|
|
|
DNS_ASSERT( FALSE );
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// DWORD system-public config
|
|
//
|
|
|
|
DWORD
|
|
DnsQueryConfigDword(
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN PWSTR pwsAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get DNS DWORD configuration value.
|
|
|
|
This is system public routine.
|
|
|
|
Arguments:
|
|
|
|
ConfigId -- type of config info desired
|
|
|
|
pwsAdapter -- name of adapter; NULL if no specific adapter
|
|
|
|
Return Value:
|
|
|
|
DWORD config value.
|
|
Zero if no such config.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
DWORD value = 0;
|
|
|
|
DNSDBG( TRACE, (
|
|
"DnsQueryConfigDword()\n"
|
|
"\tconfig = %d\n"
|
|
"\tadapter = %S\n",
|
|
ConfigId,
|
|
pwsAdapter
|
|
));
|
|
|
|
status = LookupDwordConfigValue(
|
|
& value,
|
|
ConfigId,
|
|
pwsAdapter );
|
|
|
|
#if DBG
|
|
if ( status != NO_ERROR &&
|
|
status != ERROR_FILE_NOT_FOUND )
|
|
{
|
|
DNSDBG( ANY, (
|
|
"LookupDwordConfigValue() failed for config lookup!\n"
|
|
"\tstatus = %d\n"
|
|
"\tConfigId = %d\n"
|
|
"\tpwsAdapter = %S\n",
|
|
status,
|
|
ConfigId,
|
|
pwsAdapter ));
|
|
|
|
DNS_ASSERT( status == NO_ERROR );
|
|
}
|
|
#endif
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave DnsQueryConfigDword() => %08x (%d)\n"
|
|
"\tconfig = %d\n"
|
|
"\tadapter = %S\n",
|
|
value,
|
|
value,
|
|
ConfigId,
|
|
pwsAdapter
|
|
));
|
|
|
|
return( value );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
DnsSetConfigDword(
|
|
IN DNS_CONFIG_TYPE ConfigId,
|
|
IN PWSTR pwsAdapter,
|
|
IN DWORD NewValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set DNS DWORD configuration value.
|
|
|
|
This is system public routine.
|
|
|
|
Arguments:
|
|
|
|
ConfigId -- type of config info desired
|
|
|
|
pwsAdapter -- name of adapter; NULL if no specific adapter
|
|
|
|
NewValue -- new value for parameter
|
|
|
|
Return Value:
|
|
|
|
DWORD config value.
|
|
Zero if no such config.
|
|
|
|
--*/
|
|
{
|
|
PCONFIG_MAPPING pfig;
|
|
|
|
DNSDBG( TRACE, (
|
|
"DnsSetConfigDword()\n"
|
|
"\tconfig = %d\n"
|
|
"\tadapter = %S\n"
|
|
"\tvalue = %d (%08x)\n",
|
|
ConfigId,
|
|
pwsAdapter,
|
|
NewValue, NewValue
|
|
));
|
|
|
|
//
|
|
// verify config is known and mapped
|
|
//
|
|
|
|
pfig = GetConfigToRegistryMapping(
|
|
ConfigId,
|
|
pwsAdapter,
|
|
TRUE // check adapter validity
|
|
);
|
|
if ( !pfig )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// set in registry
|
|
//
|
|
|
|
return Reg_SetDwordPropertyAndAlertCache(
|
|
pwsAdapter, // adapter name key (if any)
|
|
pfig->RegId,
|
|
NewValue );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Config data free
|
|
//
|
|
|
|
VOID
|
|
WINAPI
|
|
DnsFreeConfigStructure(
|
|
IN OUT PVOID pData,
|
|
IN DNS_CONFIG_TYPE ConfigId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free config data
|
|
|
|
This routine simply handles the mapping between config IDs
|
|
and the free type.
|
|
|
|
Arguments:
|
|
|
|
pData -- data to free
|
|
|
|
ConfigId -- config id
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DNS_FREE_TYPE freeType = DnsFreeFlat;
|
|
|
|
DNSDBG( TRACE, (
|
|
"DnsFreeConfigStructure( %p, %d )\n",
|
|
pData,
|
|
ConfigId ));
|
|
|
|
//
|
|
// find any unflat config types
|
|
//
|
|
// note: currently all config types that are not flat
|
|
// are system-public only and the config ID is also
|
|
// the free type (for convenience); if we start
|
|
// exposing some of these bringing them into the low
|
|
// space, then this will change
|
|
//
|
|
// unfortunately these types can NOT be identical because
|
|
// the space conflicts in shipped Win2K (FreeType==1 is
|
|
// record list)
|
|
//
|
|
|
|
if ( ConfigId > DnsConfigSystemBase &&
|
|
(
|
|
ConfigId == DnsConfigNetworkInfoW ||
|
|
ConfigId == DnsConfigSearchListW ||
|
|
ConfigId == DnsConfigAdapterInfoW ||
|
|
ConfigId == DnsConfigNetworkInfoA ||
|
|
ConfigId == DnsConfigSearchListA ||
|
|
ConfigId == DnsConfigAdapterInfoA ||
|
|
|
|
// ConfigId == DnsConfigNetInfo ||
|
|
|
|
ConfigId == DnsConfigNetworkInformation ||
|
|
ConfigId == DnsConfigSearchInformation ||
|
|
ConfigId == DnsConfigAdapterInformation
|
|
) )
|
|
{
|
|
freeType = (DNS_FREE_TYPE) ConfigId;
|
|
}
|
|
|
|
DnsFree(
|
|
pData,
|
|
freeType );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Config routines for specific types
|
|
//
|
|
|
|
PADDR_ARRAY
|
|
Config_GetDnsServerList(
|
|
IN PWSTR pwsAdapterName,
|
|
IN DWORD AddrFamily,
|
|
IN BOOL fForce
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get DNS server list as IP array.
|
|
|
|
Arguments:
|
|
|
|
fForce -- force reread from registry
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
PDNS_NETINFO pnetInfo = NULL;
|
|
PADDR_ARRAY parray = NULL;
|
|
DNS_STATUS status = NO_ERROR;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Config_GetDnsServerList()\n"
|
|
"\tadapter = %S\n"
|
|
"\tfamily = %d\n"
|
|
"\tforce = %d\n",
|
|
pwsAdapterName,
|
|
AddrFamily,
|
|
fForce
|
|
));
|
|
|
|
//
|
|
// get network info to make list from
|
|
// - don't need IP address lists
|
|
//
|
|
// DCR: force reread for DNS servers unnecessary once notify on it
|
|
//
|
|
|
|
pnetInfo = NetInfo_Get(
|
|
NIFLAG_FORCE_REGISTRY_READ,
|
|
0
|
|
);
|
|
if ( !pnetInfo )
|
|
{
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// convert network info to IP4_ARRAY
|
|
//
|
|
|
|
parray = NetInfo_ConvertToAddrArray(
|
|
pnetInfo,
|
|
pwsAdapterName,
|
|
AddrFamily );
|
|
|
|
if ( !parray )
|
|
{
|
|
status = GetLastError();
|
|
goto Done;
|
|
}
|
|
|
|
// if no servers read, return
|
|
|
|
if ( parray->AddrCount == 0 )
|
|
{
|
|
DNS_PRINT((
|
|
"Dns_GetDnsServerList() failed: no DNS servers found\n"
|
|
"\tstatus = %d\n" ));
|
|
status = DNS_ERROR_NO_DNS_SERVERS;
|
|
goto Done;
|
|
}
|
|
|
|
IF_DNSDBG( NETINFO )
|
|
{
|
|
DNS_PRINT(( "Leaving Config_GetDnsServerList()\n" ));
|
|
DnsDbg_DnsAddrArray(
|
|
"DNS server list",
|
|
"server",
|
|
parray );
|
|
}
|
|
|
|
Done:
|
|
|
|
NetInfo_Free( pnetInfo );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
FREE_HEAP( parray );
|
|
parray = NULL;
|
|
SetLastError( status );
|
|
}
|
|
|
|
return( parray );
|
|
}
|
|
|
|
|
|
|
|
PIP4_ARRAY
|
|
Config_GetDnsServerListIp4(
|
|
IN PWSTR pwsAdapterName,
|
|
IN BOOL fForce
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get DNS server list as IP array.
|
|
|
|
Arguments:
|
|
|
|
fForce -- force reread from registry
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
PADDR_ARRAY parray;
|
|
PIP4_ARRAY parray4 = NULL;
|
|
DNS_STATUS status = NO_ERROR;
|
|
|
|
DNSDBG( TRACE, ( "Config_GetDnsServerListIp4()\n" ));
|
|
|
|
//
|
|
// get DNS server list
|
|
//
|
|
|
|
parray = Config_GetDnsServerList(
|
|
pwsAdapterName,
|
|
AF_INET,
|
|
fForce );
|
|
if ( !parray )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// convert array to IP4 array
|
|
//
|
|
|
|
parray4 = DnsAddrArray_CreateIp4Array( parray );
|
|
if ( !parray4 )
|
|
{
|
|
status = DNS_ERROR_NO_MEMORY;
|
|
goto Done;
|
|
}
|
|
|
|
DNS_ASSERT( parray4->AddrCount > 0 );
|
|
|
|
IF_DNSDBG( NETINFO )
|
|
{
|
|
DnsDbg_Ip4Array(
|
|
"DNS server list",
|
|
"server",
|
|
parray4 );
|
|
}
|
|
|
|
Done:
|
|
|
|
DnsAddrArray_Free( parray );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
SetLastError( status );
|
|
}
|
|
return( parray4 );
|
|
}
|
|
|
|
|
|
|
|
PDNS_GLOBALS_BLOB
|
|
Config_GetDwordGlobals(
|
|
IN DWORD Flag,
|
|
IN DWORD AcceptLocalCacheTime OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read DNS network info from registry.
|
|
|
|
This is in process, limited caching version.
|
|
Note, this is macro'd as GetNetworkInfo() with parameters
|
|
NetInfo_Get( FALSE, TRUE ) throughout dnsapi code.
|
|
|
|
Arguments:
|
|
|
|
Flag -- flag; read order and IP
|
|
NIFLAG_GET_LOCAL_ADDRS
|
|
NIFLAG_FORCE_REGISTRY_READ
|
|
NIFLAG_READ_RESOLVER_FIRST
|
|
NIFLAG_READ_RESOLVER
|
|
NIFLAG_READ_PROCESS_CACHE
|
|
|
|
AcceptLocalCacheTime -- acceptable cache time on in process copy
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_NETINFO pnetInfo = NULL;
|
|
PDNS_GLOBALS_BLOB pblob = NULL;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Config_GetDwordGlobals( %08x %08x)\n",
|
|
Flag,
|
|
AcceptLocalCacheTime ));
|
|
|
|
|
|
//
|
|
// read info -- from resolver or locally
|
|
// reading netinfo will force update of globals
|
|
//
|
|
// DCR: extra work being done here;
|
|
// if UpdateNetworkInfo() fails to contact resolver
|
|
// or if resolver not trusted, can get away with simple
|
|
// reg read, don't need entire network info deal
|
|
//
|
|
|
|
pnetInfo = NetInfo_Get(
|
|
Flag,
|
|
AcceptLocalCacheTime );
|
|
|
|
//
|
|
// global info now up to date
|
|
//
|
|
// note, that whatever we return, even if from resolver, is
|
|
// (becomes) the current set for dnsapi.dll
|
|
//
|
|
// DCR: copy outside of API?
|
|
//
|
|
|
|
pblob = ALLOCATE_HEAP( sizeof(*pblob) );
|
|
if ( pblob )
|
|
{
|
|
RtlCopyMemory(
|
|
pblob,
|
|
& DnsGlobals,
|
|
sizeof(DnsGlobals) );
|
|
}
|
|
|
|
//
|
|
// cleanup netinfo
|
|
//
|
|
|
|
NetInfo_Free( pnetInfo );
|
|
|
|
return pblob;
|
|
}
|
|
|
|
//
|
|
// End config.c
|
|
//
|
|
|
|
|
|
|