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.
2422 lines
51 KiB
2422 lines
51 KiB
/*++
|
|
|
|
Copyright (c) 1999-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
regfig.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) API
|
|
|
|
Configuration routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) September 1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
|
|
|
|
//
|
|
// Table for quick lookup of DWORD\BOOL reg values
|
|
//
|
|
// DCR: read directly to config BLOB with regID indexes
|
|
// you can't screw that up
|
|
//
|
|
|
|
#define DWORD_PTR_ARRAY_END ((PDWORD) (DWORD_PTR)(-1))
|
|
|
|
PDWORD RegDwordPtrArray[] =
|
|
{
|
|
// basic -- not DWORDs
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
// query
|
|
|
|
(PDWORD) &g_QueryAdapterName,
|
|
(PDWORD) &g_UseNameDevolution,
|
|
(PDWORD) &g_PrioritizeRecordData,
|
|
(PDWORD) &g_AllowUnqualifiedQuery,
|
|
(PDWORD) &g_AppendToMultiLabelName,
|
|
(PDWORD) &g_ScreenBadTlds,
|
|
(PDWORD) &g_ScreenUnreachableServers,
|
|
(PDWORD) &g_FilterClusterIp,
|
|
(PDWORD) &g_WaitForNameErrorOnAll,
|
|
(PDWORD) &g_UseEdns,
|
|
(PDWORD) &g_QueryIpMatching,
|
|
|
|
// update
|
|
|
|
(PDWORD) &g_RegistrationEnabled,
|
|
(PDWORD) &g_RegisterPrimaryName,
|
|
(PDWORD) &g_RegisterAdapterName,
|
|
(PDWORD) &g_RegisterReverseLookup,
|
|
(PDWORD) &g_RegisterWanAdapters,
|
|
(PDWORD) &g_RegistrationTtl,
|
|
(PDWORD) &g_RegistrationRefreshInterval,
|
|
(PDWORD) &g_RegistrationMaxAddressCount,
|
|
(PDWORD) &g_UpdateSecurityLevel,
|
|
(PDWORD) &g_UpdateZoneExcludeFile,
|
|
(PDWORD) &g_UpdateTopLevelDomains,
|
|
|
|
// backcompat
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
// micellaneous
|
|
|
|
NULL, //g_InNTSetupMode, // not in standard location
|
|
(PDWORD) &g_DnsTestMode,
|
|
NULL, // remote resolver not a DWORD
|
|
|
|
// resolver
|
|
|
|
(PDWORD) &g_MaxCacheSize,
|
|
(PDWORD) &g_MaxCacheTtl,
|
|
(PDWORD) &g_MaxNegativeCacheTtl,
|
|
(PDWORD) &g_AdapterTimeoutLimit,
|
|
(PDWORD) &g_ServerPriorityTimeLimit,
|
|
(PDWORD) &g_MaxCachedSockets,
|
|
|
|
// multicast resolver
|
|
|
|
(PDWORD) &g_MulticastListenLevel,
|
|
(PDWORD) &g_MulticastSendLevel,
|
|
|
|
// termination
|
|
|
|
DWORD_PTR_ARRAY_END
|
|
};
|
|
|
|
//
|
|
// Array indicating which registry values
|
|
// were read versus defaulted
|
|
//
|
|
|
|
DWORD RegValueWasReadArray[ RegIdValueCount ];
|
|
|
|
|
|
//
|
|
// Check for empty reg value (string)
|
|
//
|
|
// DCR: consider more detailed white space check
|
|
//
|
|
|
|
#define IS_EMPTY_STRING(psz) (*(psz)==0)
|
|
|
|
|
|
|
|
|
|
//
|
|
// General registry\config utils
|
|
//
|
|
|
|
VOID
|
|
PrintConfigGlobals(
|
|
IN PSTR pszHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print config globals.
|
|
|
|
Arguments:
|
|
|
|
pszHeader -- header to print with
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD propId;
|
|
|
|
//
|
|
// print each property
|
|
//
|
|
|
|
DnsDbg_Lock();
|
|
|
|
DnsDbg_Printf(
|
|
"%s\n",
|
|
pszHeader ? pszHeader : "Registry Globals:" );
|
|
|
|
propId = 0;
|
|
|
|
for( propId=0; propId<=RegIdValueGlobalMax; propId++ )
|
|
{
|
|
PDWORD pdword = RegDwordPtrArray[propId];
|
|
|
|
// separators
|
|
|
|
if ( propId == RegIdQueryAdapterName )
|
|
{
|
|
DnsDbg_Printf( "\t-- Query:\n" );
|
|
}
|
|
else if ( propId == RegIdRegistrationEnabled )
|
|
{
|
|
DnsDbg_Printf( "\t-- Update:\n" );
|
|
}
|
|
else if ( propId == RegIdSetupMode )
|
|
{
|
|
DnsDbg_Printf( "\t-- Miscellaneous:\n" );
|
|
}
|
|
else if ( propId == RegIdMaxCacheSize )
|
|
{
|
|
DnsDbg_Printf( "\t-- Resolver\n" );
|
|
}
|
|
|
|
// NULL indicates not DWORD or not standard
|
|
|
|
if ( !pdword )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// terminate on bogus ptr
|
|
|
|
if ( pdword == DWORD_PTR_ARRAY_END )
|
|
{
|
|
ASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
DnsDbg_Printf(
|
|
"\t%-36S= %8d (read=%d)\n",
|
|
REGPROP_NAME( propId ),
|
|
* pdword,
|
|
RegValueWasReadArray[ propId ] );
|
|
}
|
|
|
|
DnsDbg_Printf(
|
|
"\t-- Random:\n"
|
|
"\tIsDnsServer = %d\n"
|
|
"\tInNTSetupMode = %d\n"
|
|
"\tDnsTestMode = %08x\n\n",
|
|
g_IsDnsServer,
|
|
g_InNTSetupMode,
|
|
g_DnsTestMode
|
|
);
|
|
|
|
DnsDbg_Unlock();
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_ReadGlobalsEx(
|
|
IN DWORD dwFlag,
|
|
IN PVOID pRegSession OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read globals from registry.
|
|
|
|
Arguments:
|
|
|
|
dwFlag -- flag indicating read level
|
|
|
|
//
|
|
// DCR: reg read flag unimplemented
|
|
//
|
|
// note: should have option to NOT read some registry
|
|
// values for case when cache off, then could
|
|
// skip useless cache info when building local
|
|
// networkinfo blob
|
|
//
|
|
|
|
pRegSession -- ptr to existing registry session
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD propId;
|
|
REG_SESSION regSession;
|
|
PREG_SESSION psession;
|
|
DNS_STATUS status;
|
|
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_ReadGlobalsEx( %08x, %p )\n",
|
|
dwFlag,
|
|
pRegSession ));
|
|
|
|
//
|
|
// basic registry init
|
|
// - includes system global
|
|
//
|
|
|
|
Reg_Init();
|
|
|
|
//
|
|
// code validity check
|
|
// property table should have entry for every reg value plus an
|
|
// extra one for the terminator
|
|
//
|
|
|
|
#if DBG
|
|
DNS_ASSERT( (RegIdValueCount+1)*sizeof(PDWORD) ==
|
|
sizeof(RegDwordPtrArray) );
|
|
#endif
|
|
|
|
//
|
|
// open registry session -- if not passed in
|
|
//
|
|
|
|
psession = (PREG_SESSION) pRegSession;
|
|
|
|
if ( !psession )
|
|
{
|
|
psession = ®Session;
|
|
status = Reg_OpenSession( psession, 0, 0 );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
return( status );
|
|
}
|
|
}
|
|
|
|
//
|
|
// clear "value was read" array
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
RegValueWasReadArray,
|
|
sizeof( RegValueWasReadArray ) );
|
|
|
|
//
|
|
// MS DNS?
|
|
//
|
|
|
|
g_IsDnsServer = Reg_IsMicrosoftDnsServer();
|
|
|
|
//
|
|
// remote resolver?
|
|
// - not currently enabled
|
|
//
|
|
|
|
//g_pwsRemoteResolver = DnsGetResolverAddress();
|
|
g_pwsRemoteResolver = NULL;
|
|
|
|
|
|
//
|
|
// read\set each DWORD\BOOL registry value
|
|
//
|
|
|
|
propId = 0;
|
|
|
|
for( propId=0; propId<=RegIdValueGlobalMax; propId++ )
|
|
{
|
|
PDWORD pdword = RegDwordPtrArray[propId];
|
|
|
|
// NULL indicates not DWORD or not standard
|
|
|
|
if ( !pdword )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// terminate on bogus ptr
|
|
|
|
if ( pdword == DWORD_PTR_ARRAY_END )
|
|
{
|
|
ASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
status = Reg_GetDword(
|
|
psession, // reg session
|
|
NULL, // no key
|
|
NULL, // standard location
|
|
propId, // index is property id
|
|
pdword );
|
|
|
|
// set fRead flag if value found in registry
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
RegValueWasReadArray[propId] = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// registration refresh defaults are different for DC
|
|
//
|
|
|
|
if ( !RegValueWasReadArray[ RegIdRegistrationRefreshInterval ] )
|
|
{
|
|
if ( g_IsDomainController )
|
|
{
|
|
g_RegistrationRefreshInterval = REGDEF_REGISTRATION_REFRESH_INTERVAL_DC;
|
|
}
|
|
ELSE_ASSERT( g_RegistrationRefreshInterval == REGDEF_REGISTRATION_REFRESH_INTERVAL );
|
|
}
|
|
|
|
//
|
|
// non-standard registry values
|
|
// - setup mode
|
|
//
|
|
|
|
Reg_GetDword(
|
|
psession,
|
|
NULL, // no key
|
|
REGKEY_SETUP_MODE_LOCATION,
|
|
RegIdSetupMode,
|
|
(PDWORD) &g_InNTSetupMode );
|
|
|
|
//
|
|
// DCR: flip in policy globals and do single read here
|
|
// or since they are only relevant to adapter
|
|
// list and registration, keep separate
|
|
//
|
|
// fundamentally the question is how separate is the
|
|
// adapter list read from other globals?
|
|
//
|
|
|
|
|
|
// close local session registry handles
|
|
|
|
if ( psession == ®Session )
|
|
{
|
|
Reg_CloseSession( psession );
|
|
}
|
|
|
|
IF_DNSDBG( INIT )
|
|
{
|
|
PrintConfigGlobals( "Read Registry Globals" );
|
|
}
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_RefreshUpdateConfig(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read\refresh update config.
|
|
|
|
This routine encapsulates getting all update config info
|
|
current before any update operation.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// read all global DWORDs if haven't been read "recently"
|
|
//
|
|
// note: adapter specific stuff is read building network config;
|
|
// here were are just insuring that we have top level globals
|
|
// current; specifically test was blocked because the
|
|
// update TLD flag was not being reread
|
|
//
|
|
// DCR: when have change\notify this should just tie into
|
|
// global config read
|
|
//
|
|
|
|
return Reg_ReadGlobalsEx( 0, NULL );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Special DNS property routines
|
|
//
|
|
|
|
DNS_STATUS
|
|
Reg_ReadPrimaryDomainName(
|
|
IN PREG_SESSION pRegSession, OPTIONAL
|
|
IN HKEY hRegKey, OPTIONAL
|
|
OUT PWSTR * ppPrimaryDomainName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read primary domain name.
|
|
|
|
Arguments:
|
|
|
|
|
|
pRegSession -- ptr to registry session, OPTIONAL
|
|
|
|
hRegKey -- handle to open regkey OPTIONAL (currently unimplemented)
|
|
|
|
ppPrimaryDomainName -- addr to recv ptr to PDN
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
REG_SESSION session;
|
|
PREG_SESSION psession = NULL;
|
|
PWSTR pdomainName = NULL;
|
|
HKEY holdPolicyKey = NULL;
|
|
HKEY hkeyPolicy;
|
|
|
|
DNSDBG( TRACE, ( "Reg_ReadPrimaryDomainName()\n" ));
|
|
|
|
ASSERT( !hRegKey );
|
|
|
|
//
|
|
// open reg handle if not open
|
|
//
|
|
// note: worth doing here, because if we default the open
|
|
// in the calls below, we will make unnecessary reg calls
|
|
// -- won't be able to screen for policy existence
|
|
// so policy PDN name will be looked for in TCPIP
|
|
// -- the second call for the TCPIP domain name, will also
|
|
// check in the policy area (if exists)
|
|
//
|
|
|
|
psession = pRegSession;
|
|
|
|
if ( !psession )
|
|
{
|
|
psession = &session;
|
|
status = Reg_OpenSession(
|
|
psession,
|
|
0, // standard level
|
|
0 // no specific value, open both
|
|
);
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// try policy
|
|
// - no policy pickup for DCs
|
|
// - first try new WindowsNT policy
|
|
// - if not found, try policy used in Win2K
|
|
//
|
|
|
|
hkeyPolicy = psession->hPolicy;
|
|
|
|
if ( hkeyPolicy )
|
|
{
|
|
status = Reg_GetValue(
|
|
NULL, // don't send whole session
|
|
hkeyPolicy, // use explicit policy key
|
|
RegIdPrimaryDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pdomainName
|
|
);
|
|
if ( pdomainName )
|
|
{
|
|
goto Found;
|
|
}
|
|
}
|
|
|
|
//
|
|
// not found in new, open old policy
|
|
//
|
|
|
|
status = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
DNS_POLICY_WIN2K_KEY,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
& holdPolicyKey );
|
|
|
|
if ( holdPolicyKey )
|
|
{
|
|
status = Reg_GetValue(
|
|
NULL, // don't send whole session
|
|
holdPolicyKey, // use explicit policy key
|
|
RegIdPrimaryDnsSuffix,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pdomainName
|
|
);
|
|
|
|
RegCloseKey( holdPolicyKey );
|
|
if ( pdomainName )
|
|
{
|
|
goto Found;
|
|
}
|
|
}
|
|
|
|
//
|
|
// no policy name
|
|
// - try DNS client
|
|
// - try standard TCPIP location
|
|
// note under TCPIP it's "Domain"
|
|
//
|
|
|
|
#ifdef DNSCLIENTKEY
|
|
if ( psession->hClient )
|
|
{
|
|
status = Reg_GetValue(
|
|
NULL, // don't send whole session
|
|
psession->hClient, // send client key explicitly
|
|
RegIdPrimaryDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pdomainName );
|
|
if ( pdomainName )
|
|
{
|
|
goto Found;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
status = Reg_GetValue(
|
|
NULL, // don't send whole session
|
|
psession->hTcpip, // send TCPIP key explicitly
|
|
RegIdDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pdomainName );
|
|
|
|
|
|
Found:
|
|
|
|
// dump name if empty\useless
|
|
|
|
if ( pdomainName &&
|
|
( wcslen( pdomainName ) == 0 ) )
|
|
{
|
|
FREE_HEAP( pdomainName );
|
|
pdomainName = NULL;
|
|
}
|
|
|
|
|
|
Done:
|
|
|
|
DNSDBG( TRACE, ( "Read PDN = %S\n", pdomainName ));
|
|
|
|
// set domain name OUT param
|
|
|
|
*ppPrimaryDomainName = pdomainName;
|
|
|
|
// cleanup any regkey's opened
|
|
|
|
if ( psession == &session )
|
|
{
|
|
Reg_CloseSession( psession );
|
|
}
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
Reg_IsMicrosoftDnsServer(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read registry to determine if MS DNS server.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
HKEY hkey = NULL;
|
|
|
|
//
|
|
// open services key to determine whether the DNS server is installed.
|
|
//
|
|
// DCR: read DNS server only once
|
|
// - however need some sort of callback so we can pick this up
|
|
// after install
|
|
//
|
|
|
|
status = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
DNS_SERVER_KEY,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkey );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Reg info read.
|
|
// These are read routines for info beyond flat globals.
|
|
//
|
|
// Three types of info:
|
|
// - global
|
|
// - adapter specific
|
|
// - update
|
|
//
|
|
|
|
DNS_STATUS
|
|
Reg_ReadGlobalInfo(
|
|
IN PREG_SESSION pRegSession,
|
|
OUT PREG_GLOBAL_INFO pRegInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read DNS registry info, not read in flat read.
|
|
|
|
This covers all the allocated stuff, plus policy
|
|
stuff for adapter info.
|
|
|
|
-- primary domain name
|
|
-- adapter policy
|
|
- domain name
|
|
- DNS servers
|
|
- flag overrides
|
|
|
|
Arguments:
|
|
|
|
pRegSession -- registry session
|
|
|
|
pRegInfo -- blob to hold reg info
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
REG_SESSION regSession;
|
|
PREG_SESSION pregSession = pRegSession;
|
|
HKEY hkeyPolicy = NULL;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_ReadGlobalInfo( %p, %p )\n",
|
|
pRegSession,
|
|
pRegInfo ));
|
|
|
|
//
|
|
// clear reg info blob
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
pRegInfo,
|
|
sizeof( *pRegInfo ) );
|
|
|
|
//
|
|
// open the registry
|
|
//
|
|
|
|
if ( !pregSession )
|
|
{
|
|
pregSession = ®Session;
|
|
|
|
status = Reg_OpenSession(
|
|
pregSession,
|
|
0,
|
|
0 );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
return( status );
|
|
}
|
|
}
|
|
|
|
//
|
|
// if not read force registry read
|
|
//
|
|
|
|
status = Reg_ReadGlobalsEx(
|
|
0, // no flag, read it all
|
|
pregSession
|
|
);
|
|
|
|
//
|
|
// primary domain name
|
|
//
|
|
|
|
Reg_ReadPrimaryDomainName(
|
|
pregSession,
|
|
NULL, // no specific key
|
|
& pRegInfo->pszPrimaryDomainName
|
|
);
|
|
|
|
//
|
|
// host name
|
|
//
|
|
|
|
Reg_GetValue(
|
|
pregSession,
|
|
NULL, // no key
|
|
RegIdHostName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pRegInfo->pszHostName
|
|
);
|
|
|
|
//
|
|
// pick up required registry values from globals
|
|
//
|
|
|
|
pRegInfo->fUseNameDevolution = g_UseNameDevolution;
|
|
|
|
//
|
|
// policy overrides for adapter info
|
|
// - enable adapter registration
|
|
// - DNS servers
|
|
// - domain name
|
|
//
|
|
// note, we need both value and found\not-found flag
|
|
// as value overrides only when it exists
|
|
//
|
|
|
|
hkeyPolicy = pregSession->hPolicy;
|
|
if ( !hkeyPolicy )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// policy for register adapter name?
|
|
//
|
|
|
|
status = Reg_GetDword(
|
|
NULL, // no session
|
|
hkeyPolicy, // policy
|
|
NULL, // no adapter
|
|
RegIdRegisterAdapterName,
|
|
& pRegInfo->fRegisterAdapterName
|
|
);
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
pRegInfo->fPolicyRegisterAdapterName = TRUE;
|
|
}
|
|
|
|
//
|
|
// policy for adapter domain name?
|
|
//
|
|
|
|
status = Reg_GetValue(
|
|
NULL, // no session
|
|
hkeyPolicy,
|
|
RegIdAdapterDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pRegInfo->pszAdapterDomainName
|
|
);
|
|
|
|
//
|
|
// policy for adapter DNS server lists
|
|
//
|
|
|
|
status = Reg_GetIpArray(
|
|
NULL, // no session
|
|
hkeyPolicy,
|
|
NULL, // no adapter
|
|
RegIdDnsServers,
|
|
REG_SZ,
|
|
&pRegInfo->pDnsServerArray
|
|
);
|
|
|
|
Done:
|
|
|
|
// if opened session -- close
|
|
|
|
if ( pregSession && !pRegSession )
|
|
{
|
|
Reg_CloseSession( pregSession );
|
|
}
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Reg_ReadGlobalInfo()\n"
|
|
"\tPDN = %S\n"
|
|
"\tPolicy:\n"
|
|
"\t\tRegister Adapter = %d\n"
|
|
"\t\tAdapterName = %S\n"
|
|
"\t\tDNS servers = %p\n",
|
|
pRegInfo->pszPrimaryDomainName,
|
|
pRegInfo->fRegisterAdapterName,
|
|
pRegInfo->pszAdapterDomainName,
|
|
pRegInfo->pDnsServerArray
|
|
));
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
Reg_FreeGlobalInfo(
|
|
IN OUT PREG_GLOBAL_INFO pRegInfo,
|
|
IN BOOL fFreeBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free registry adapter policy info blob.
|
|
|
|
Arguments:
|
|
|
|
pRegInfo -- adapter policy blob to free
|
|
|
|
fFreeBlob -- flag to free blob itself
|
|
FALSE -- just free allocated data fields
|
|
TRUE -- also free blob itself
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNSDBG( TRACE, (
|
|
"Reg_FreeGlobalInfo( %p )\n",
|
|
pRegInfo ));
|
|
|
|
// allow sloppy cleanup
|
|
|
|
if ( !pRegInfo )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// free data
|
|
// - primary DNS name
|
|
// - policy adapter name
|
|
// - policy DNS server list
|
|
//
|
|
|
|
if ( pRegInfo->pszPrimaryDomainName )
|
|
{
|
|
FREE_HEAP( pRegInfo->pszPrimaryDomainName );
|
|
}
|
|
if ( pRegInfo->pszHostName )
|
|
{
|
|
FREE_HEAP( pRegInfo->pszHostName );
|
|
}
|
|
if ( pRegInfo->pszAdapterDomainName )
|
|
{
|
|
FREE_HEAP( pRegInfo->pszAdapterDomainName );
|
|
}
|
|
if ( pRegInfo->pDnsServerArray )
|
|
{
|
|
FREE_HEAP( pRegInfo->pDnsServerArray );
|
|
}
|
|
|
|
// free blob itself
|
|
|
|
if ( fFreeBlob )
|
|
{
|
|
FREE_HEAP( pRegInfo );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_ReadAdapterInfo(
|
|
IN PWSTR pszAdapterName,
|
|
IN PREG_SESSION pRegSession,
|
|
IN PREG_GLOBAL_INFO pRegInfo,
|
|
OUT PREG_ADAPTER_INFO pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read adapter registry info.
|
|
|
|
Arguments:
|
|
|
|
pszAdapterName -- adapter name (registry name)
|
|
|
|
pRegSession -- registry session
|
|
|
|
pRegInfo -- registry global info
|
|
|
|
pBlob -- adapter info blob to fill in
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
HKEY hkeyAdapter = NULL;
|
|
PWSTR padapterDomainName = NULL;
|
|
WCHAR adapterParamKey[ MAX_PATH+1 ];
|
|
|
|
DNSDBG( TRACE, (
|
|
"ReadRegAdapterInfo( %S, %p, %p, %p )\n",
|
|
pszAdapterName,
|
|
pRegSession,
|
|
pRegInfo,
|
|
pBlob ));
|
|
|
|
//
|
|
// clear adapter blob
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
pBlob,
|
|
sizeof(*pBlob) );
|
|
|
|
//
|
|
// bail if no adapter
|
|
//
|
|
// note: this check\bail is only in place to allow call to
|
|
// Reg_ReadUpdateInfo() to be made in asyncreg.c without
|
|
// specifying an adapter; this allows us to make the call
|
|
// before the adapter check and therefore skip a separate
|
|
// registry op to get current g_IsDnsServer global;
|
|
// no actual use will be made of REG_ADAPTER_INFO blob
|
|
|
|
if ( !pszAdapterName )
|
|
{
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// open adapter key for read
|
|
//
|
|
// DCR: fail on adapter key name overflow
|
|
// DCR: this may be backwards -- ie need %s%s
|
|
//
|
|
|
|
_snwprintf(
|
|
adapterParamKey,
|
|
MAX_PATH,
|
|
L"%s%s",
|
|
TCPIP_INTERFACES_KEY,
|
|
pszAdapterName );
|
|
|
|
adapterParamKey[ MAX_PATH ] = 0;
|
|
|
|
status = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
adapterParamKey,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyAdapter );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
DNSDBG( ANY, (
|
|
"Failed open of adapter key %S!\n",
|
|
adapterParamKey ));
|
|
return( status );
|
|
}
|
|
|
|
//
|
|
// query with adapter name
|
|
// - OFF global overrides
|
|
//
|
|
|
|
pBlob->fQueryAdapterName = g_QueryAdapterName;
|
|
|
|
if ( g_QueryAdapterName )
|
|
{
|
|
Reg_GetDword(
|
|
NULL, // no session,
|
|
hkeyAdapter, // explicit key
|
|
NULL, // no adapter name
|
|
RegIdQueryAdapterName,
|
|
& pBlob->fQueryAdapterName );
|
|
}
|
|
|
|
//
|
|
// check if adapter IPs get registered
|
|
// - OFF global overrides
|
|
//
|
|
|
|
pBlob->fRegistrationEnabled = g_RegistrationEnabled;
|
|
|
|
if ( g_RegistrationEnabled )
|
|
{
|
|
Reg_GetDword(
|
|
NULL, // no session,
|
|
hkeyAdapter, // explicit key
|
|
NULL, // no adapter name
|
|
RegIdRegistrationEnabled,
|
|
& pBlob->fRegistrationEnabled );
|
|
}
|
|
|
|
//
|
|
// adapter name registration
|
|
// - policy may override
|
|
// - OFF global overrides
|
|
// - then adapter
|
|
//
|
|
|
|
if ( pRegInfo->fPolicyRegisterAdapterName )
|
|
{
|
|
pBlob->fRegisterAdapterName = pRegInfo->fRegisterAdapterName;
|
|
}
|
|
else
|
|
{
|
|
pBlob->fRegisterAdapterName = g_RegisterAdapterName;
|
|
|
|
if ( g_RegisterAdapterName )
|
|
{
|
|
Reg_GetDword(
|
|
NULL, // no open session,
|
|
hkeyAdapter, // open key
|
|
NULL, // no adapter name
|
|
RegIdRegisterAdapterName,
|
|
& pBlob->fRegisterAdapterName );
|
|
}
|
|
}
|
|
|
|
//
|
|
// max addresses to register
|
|
//
|
|
// DCR: RegistrationAddrCount -- adapter or global sets high\low?
|
|
//
|
|
|
|
if ( pBlob->fRegistrationEnabled )
|
|
{
|
|
Reg_GetDword(
|
|
NULL, // no session,
|
|
hkeyAdapter, // explicit key
|
|
NULL, // no adapter name
|
|
RegIdRegistrationMaxAddressCount,
|
|
& pBlob->RegistrationMaxAddressCount );
|
|
#if 0
|
|
if ( g_RegistrationMaxAddressCount >
|
|
pBlob->RegistrationMaxAddressCount )
|
|
{
|
|
pBlob->RegistrationMaxAddressCount = g_RegistrationMaxAddressCount;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// get adapter name
|
|
// - policy may override AND
|
|
// allow policy to override with NULL string to kill domain name
|
|
//
|
|
|
|
padapterDomainName = pRegInfo->pszAdapterDomainName;
|
|
|
|
if ( padapterDomainName )
|
|
{
|
|
if ( IS_EMPTY_STRING( padapterDomainName ) )
|
|
{
|
|
padapterDomainName = NULL;
|
|
}
|
|
else
|
|
{
|
|
padapterDomainName = Dns_CreateStringCopy_W( padapterDomainName );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// static domain name set on adapter?
|
|
//
|
|
|
|
status = Reg_GetValueEx(
|
|
NULL, // no session
|
|
hkeyAdapter,
|
|
NULL, // no adapter name
|
|
RegIdStaticDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
DNSREG_FLAG_DUMP_EMPTY, // dump empty string
|
|
(PBYTE *) &padapterDomainName
|
|
);
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
DNS_ASSERT( padapterDomainName == NULL );
|
|
padapterDomainName = NULL;
|
|
}
|
|
|
|
//
|
|
// if no static name, use DHCP name
|
|
//
|
|
|
|
if ( ! padapterDomainName )
|
|
{
|
|
status = Reg_GetValueEx(
|
|
NULL, // no session
|
|
hkeyAdapter,
|
|
NULL, // no adapter
|
|
RegIdDhcpDomainName,
|
|
REGTYPE_DNS_NAME,
|
|
DNSREG_FLAG_DUMP_EMPTY, // dump if empty string
|
|
(PBYTE *) &padapterDomainName );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
DNS_ASSERT( padapterDomainName == NULL );
|
|
padapterDomainName = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// set adapter name in info blob
|
|
//
|
|
|
|
pBlob->pszAdapterDomainName = padapterDomainName;
|
|
|
|
//
|
|
// cleanup
|
|
//
|
|
|
|
if ( hkeyAdapter )
|
|
{
|
|
RegCloseKey( hkeyAdapter );
|
|
}
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Reg_ReadAdapterInfo()\n"
|
|
"\tDomainName = %S\n"
|
|
"\tQueryAdapterName = %d\n"
|
|
"\tRegistrationEnabled = %d\n"
|
|
"\tRegisterAdapterName = %d\n"
|
|
"\tRegisterAddrCount = %d\n",
|
|
pBlob->pszAdapterDomainName,
|
|
pBlob->fQueryAdapterName,
|
|
pBlob->fRegistrationEnabled,
|
|
pBlob->fRegisterAdapterName,
|
|
pBlob->RegistrationMaxAddressCount
|
|
));
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_DefaultAdapterInfo(
|
|
OUT PREG_ADAPTER_INFO pBlob,
|
|
IN PREG_GLOBAL_INFO pRegInfo,
|
|
IN PIP_ADAPTER_ADDRESSES pIpAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Default adapter info, when reg read fails.
|
|
|
|
Use for building netinfo on IP6 only adapters that
|
|
don't show in TCPIP adapters.
|
|
|
|
Arguments:
|
|
|
|
pBlob -- adapter info blob to fill in
|
|
|
|
pRegInfo -- registry global info
|
|
|
|
pIPAdapter -- IP help adapter info
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
PWSTR padapterDomainName = NULL;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_DefaultAdapterInfo( %p, %p, %p )\n",
|
|
pBlob,
|
|
pRegInfo,
|
|
pIpAdapter ));
|
|
|
|
if ( !pBlob || !pRegInfo || !pIpAdapter )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// clear adapter blob
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
pBlob,
|
|
sizeof(*pBlob) );
|
|
|
|
|
|
//
|
|
// query with adapter name
|
|
// - OFF global overrides
|
|
//
|
|
|
|
pBlob->fQueryAdapterName = g_QueryAdapterName;
|
|
|
|
//
|
|
// check if adapter IPs get registered
|
|
// - OFF global overrides
|
|
//
|
|
|
|
pBlob->fRegistrationEnabled = g_RegistrationEnabled;
|
|
|
|
//
|
|
// adapter name registration
|
|
// - policy may override
|
|
// - OFF global overrides
|
|
// - then adapter
|
|
//
|
|
|
|
if ( pRegInfo->fPolicyRegisterAdapterName )
|
|
{
|
|
pBlob->fRegisterAdapterName = pRegInfo->fRegisterAdapterName;
|
|
}
|
|
else
|
|
{
|
|
pBlob->fRegisterAdapterName = g_RegisterAdapterName;
|
|
}
|
|
|
|
//
|
|
// max addresses to register
|
|
//
|
|
|
|
if ( pBlob->fRegistrationEnabled )
|
|
{
|
|
pBlob->RegistrationMaxAddressCount = g_RegistrationMaxAddressCount;
|
|
}
|
|
|
|
//
|
|
// get adapter name
|
|
// - policy may override AND
|
|
// allow policy to override with NULL string to kill domain name
|
|
//
|
|
|
|
padapterDomainName = pRegInfo->pszAdapterDomainName;
|
|
|
|
if ( !padapterDomainName )
|
|
{
|
|
padapterDomainName = pIpAdapter->DnsSuffix;
|
|
}
|
|
|
|
if ( padapterDomainName )
|
|
{
|
|
if ( IS_EMPTY_STRING( padapterDomainName ) )
|
|
{
|
|
padapterDomainName = NULL;
|
|
}
|
|
else
|
|
{
|
|
padapterDomainName = Dns_CreateStringCopy_W( padapterDomainName );
|
|
}
|
|
pBlob->pszAdapterDomainName = padapterDomainName;
|
|
}
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Reg_DefaultAdapterInfo()\n"
|
|
"\tDomainName = %S\n"
|
|
"\tQueryAdapterName = %d\n"
|
|
"\tRegistrationEnabled = %d\n"
|
|
"\tRegisterAdapterName = %d\n"
|
|
"\tRegisterAddrCount = %d\n",
|
|
pBlob->pszAdapterDomainName,
|
|
pBlob->fQueryAdapterName,
|
|
pBlob->fRegistrationEnabled,
|
|
pBlob->fRegisterAdapterName,
|
|
pBlob->RegistrationMaxAddressCount
|
|
));
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_ReadAdapterInfoA(
|
|
IN PSTR pszAdapterName,
|
|
IN PREG_SESSION pRegSession,
|
|
IN PREG_GLOBAL_INFO pRegInfo,
|
|
OUT PREG_ADAPTER_INFO pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read adapter registry info. ANSI version.
|
|
|
|
This is available simply for use with IPHelp
|
|
PIP_ADAPTER_ADDRESSES structure which has
|
|
ANSI adapter name (for some reason).
|
|
|
|
Arguments:
|
|
|
|
pszAdapterName -- adapter name (registry name)
|
|
|
|
pRegSession -- registry session
|
|
|
|
pRegInfo -- registry global info
|
|
|
|
pBlob -- adapter info blob to fill in
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD nameBufLength = MAX_PATH * sizeof(WCHAR);
|
|
WCHAR wideName[ MAX_PATH ];
|
|
|
|
DNSDBG( TRACE, (
|
|
"ReadRegAdapterInfoA( %s, %p, %p, %p )\n",
|
|
pszAdapterName,
|
|
pRegSession,
|
|
pRegInfo,
|
|
pBlob ));
|
|
|
|
//
|
|
// convert adapter name to unicode
|
|
//
|
|
|
|
if ( ! pszAdapterName ||
|
|
! Dns_StringCopy(
|
|
(PCHAR) wideName,
|
|
& nameBufLength,
|
|
pszAdapterName,
|
|
0,
|
|
DnsCharSetAnsi,
|
|
DnsCharSetUnicode ) )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return Reg_ReadAdapterInfo(
|
|
wideName,
|
|
pRegSession,
|
|
pRegInfo,
|
|
pBlob );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
Reg_FreeAdapterInfo(
|
|
IN OUT PREG_ADAPTER_INFO pRegAdapterInfo,
|
|
IN BOOL fFreeBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free registry adapter info blob.
|
|
|
|
Arguments:
|
|
|
|
pRegAdapterInfo -- adapter registry info blob to free
|
|
|
|
fFreeBlob -- flag to free blob itself
|
|
FALSE -- just free allocated data fields
|
|
TRUE -- also free blob itself
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNSDBG( TRACE, (
|
|
"FreeRegAdapterInfo( %p )\n",
|
|
pRegAdapterInfo ));
|
|
|
|
//
|
|
// free data
|
|
// - adapter domain name
|
|
//
|
|
|
|
if ( pRegAdapterInfo->pszAdapterDomainName )
|
|
{
|
|
FREE_HEAP( pRegAdapterInfo->pszAdapterDomainName );
|
|
pRegAdapterInfo->pszAdapterDomainName = NULL;
|
|
}
|
|
|
|
// free blob itself
|
|
|
|
if ( fFreeBlob )
|
|
{
|
|
FREE_HEAP( pRegAdapterInfo );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Reg_ReadUpdateInfo(
|
|
IN PWSTR pszAdapterName,
|
|
OUT PREG_UPDATE_INFO pUpdateInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read update info.
|
|
|
|
//
|
|
// DCR: shouldn't need this routine, just get NETINFO
|
|
// this blob is just mix of global stuff and
|
|
// mostly adapter stuff
|
|
// even if want in single blob for update routines --
|
|
// ok, but not ideal --
|
|
// should be getting blob from resolver and reformatting
|
|
// info;
|
|
// reg read should happen just once producing network
|
|
// info in resolver
|
|
//
|
|
|
|
Arguments:
|
|
|
|
pszAdapterName -- adapter name
|
|
|
|
pUpdateInfo -- blob to hold reg info
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
REG_SESSION regSession;
|
|
PREG_SESSION pregSession;
|
|
REG_GLOBAL_INFO regInfo;
|
|
REG_ADAPTER_INFO regAdapterInfo;
|
|
BOOL freadRegInfo = FALSE;
|
|
BOOL freadRegAdapterInfo = FALSE;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_ReadUpdateInfo( %S, %p )\n",
|
|
pszAdapterName,
|
|
pUpdateInfo ));
|
|
|
|
//
|
|
// clear update info blob
|
|
//
|
|
|
|
RtlZeroMemory(
|
|
pUpdateInfo,
|
|
sizeof( *pUpdateInfo ) );
|
|
|
|
//
|
|
// open the registry
|
|
//
|
|
|
|
pregSession = ®Session;
|
|
|
|
status = Reg_OpenSession(
|
|
pregSession,
|
|
0,
|
|
0 );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
return( status );
|
|
}
|
|
|
|
//
|
|
// read registry
|
|
// - global DWORDs
|
|
// - global info
|
|
// - adapter specific info
|
|
//
|
|
// DCR_PERF: global read should be RPC
|
|
// DCR_REG: fix this with reg read
|
|
// have flag for IN caching resolver process (skip RPC)
|
|
// have cookie for last read
|
|
//
|
|
|
|
#if 0
|
|
// Reg_ReadGlobalInfo() calls Reg_ReadGlobalsEx()
|
|
status = Reg_ReadGlobalsEx(
|
|
0, // no flag, update variables desired
|
|
pregSession
|
|
);
|
|
#endif
|
|
|
|
status = Reg_ReadGlobalInfo(
|
|
pregSession,
|
|
& regInfo );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
freadRegInfo = TRUE;
|
|
|
|
status = Reg_ReadAdapterInfo(
|
|
pszAdapterName,
|
|
pregSession,
|
|
& regInfo,
|
|
& regAdapterInfo );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
freadRegAdapterInfo = TRUE;
|
|
|
|
//
|
|
// alternate computer name
|
|
//
|
|
|
|
Reg_GetValue(
|
|
pregSession,
|
|
NULL, // no key
|
|
RegIdAlternateNames,
|
|
REGTYPE_ALTERNATE_NAMES,
|
|
(PBYTE *) &pUpdateInfo->pmszAlternateNames
|
|
);
|
|
|
|
//
|
|
// set update results
|
|
// - PDN always needed
|
|
// - adapter domain if policy override
|
|
// - DNS servers if policy override
|
|
//
|
|
// note, in all cases we don't realloc, we steal the
|
|
// info and NULL it out so not freed on cleanup
|
|
//
|
|
|
|
pUpdateInfo->pszPrimaryDomainName = regInfo.pszPrimaryDomainName;
|
|
regInfo.pszPrimaryDomainName = NULL;
|
|
|
|
pUpdateInfo->pszAdapterDomainName = regInfo.pszAdapterDomainName;
|
|
regInfo.pszAdapterDomainName = NULL;
|
|
|
|
pUpdateInfo->pDnsServerArray = regInfo.pDnsServerArray;
|
|
regInfo.pDnsServerArray = NULL;
|
|
|
|
pUpdateInfo->pDnsServerIp6Array = regInfo.pDnsServerIp6Array;
|
|
regInfo.pDnsServerIp6Array = NULL;
|
|
|
|
// update flags
|
|
|
|
pUpdateInfo->fRegistrationEnabled = regAdapterInfo.fRegistrationEnabled;
|
|
pUpdateInfo->fRegisterAdapterName = regAdapterInfo.fRegisterAdapterName;
|
|
pUpdateInfo->RegistrationMaxAddressCount =
|
|
regAdapterInfo.RegistrationMaxAddressCount;
|
|
|
|
Done:
|
|
|
|
//
|
|
// cleanup
|
|
//
|
|
|
|
if ( pregSession )
|
|
{
|
|
Reg_CloseSession( pregSession );
|
|
}
|
|
|
|
// don't free blobs -- they're on stack
|
|
|
|
if ( freadRegInfo )
|
|
{
|
|
Reg_FreeGlobalInfo( ®Info, FALSE );
|
|
}
|
|
if ( freadRegAdapterInfo )
|
|
{
|
|
Reg_FreeAdapterInfo( ®AdapterInfo, FALSE );
|
|
}
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Reg_ReadUpdateInfo( %S )\n"
|
|
"\tPDN = %S\n"
|
|
"\tAlternateNames = %S\n"
|
|
"\tAdapterDomainName = %S\n"
|
|
"\tDNS servers = %p\n"
|
|
"\tDNS servers IP6 = %p\n"
|
|
"\tRegister = %d\n"
|
|
"\tRegisterAdapterName = %d\n"
|
|
"\tRegisterAddrCount = %d\n",
|
|
pszAdapterName,
|
|
pUpdateInfo->pszPrimaryDomainName,
|
|
pUpdateInfo->pmszAlternateNames,
|
|
pUpdateInfo->pszAdapterDomainName,
|
|
pUpdateInfo->pDnsServerArray,
|
|
pUpdateInfo->pDnsServerIp6Array,
|
|
pUpdateInfo->fRegistrationEnabled,
|
|
pUpdateInfo->fRegisterAdapterName,
|
|
pUpdateInfo->RegistrationMaxAddressCount
|
|
));
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
Reg_FreeUpdateInfo(
|
|
IN OUT PREG_UPDATE_INFO pUpdateInfo,
|
|
IN BOOL fFreeBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free registry update info blob.
|
|
|
|
Arguments:
|
|
|
|
pUpdateInfo -- update registry info blob to free
|
|
|
|
fFreeBlob -- flag to free blob itself
|
|
FALSE -- just free allocated data fields
|
|
TRUE -- also free blob itself
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNSDBG( TRACE, (
|
|
"FreeRegUpdateInfo( %p )\n",
|
|
pUpdateInfo ));
|
|
|
|
//
|
|
// free data
|
|
// - PDN
|
|
// - adapter domain name
|
|
// - DNS server lists
|
|
//
|
|
|
|
if ( pUpdateInfo->pszPrimaryDomainName )
|
|
{
|
|
FREE_HEAP( pUpdateInfo->pszPrimaryDomainName );
|
|
}
|
|
if ( pUpdateInfo->pmszAlternateNames )
|
|
{
|
|
FREE_HEAP( pUpdateInfo->pmszAlternateNames );
|
|
}
|
|
if ( pUpdateInfo->pszAdapterDomainName )
|
|
{
|
|
FREE_HEAP( pUpdateInfo->pszAdapterDomainName );
|
|
}
|
|
if ( pUpdateInfo->pDnsServerArray )
|
|
{
|
|
FREE_HEAP( pUpdateInfo->pDnsServerArray );
|
|
}
|
|
if ( pUpdateInfo->pDnsServerIp6Array )
|
|
{
|
|
FREE_HEAP( pUpdateInfo->pDnsServerIp6Array );
|
|
}
|
|
|
|
// free blob itself
|
|
|
|
if ( fFreeBlob )
|
|
{
|
|
FREE_HEAP( pUpdateInfo );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Special
|
|
//
|
|
|
|
DNS_STATUS
|
|
Reg_WriteLoopbackDnsServerList(
|
|
IN PWSTR pszAdapterName,
|
|
IN PREG_SESSION pRegSession
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write loopback IP as DNS server list.
|
|
|
|
Arguments:
|
|
|
|
pszAdapterName -- adapter name (registry name)
|
|
|
|
pRegSession -- registry session
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
Error code on failure.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
HKEY hkeyAdapter = NULL;
|
|
WCHAR adapterParamKey[ MAX_PATH+1 ];
|
|
PWSTR pstring;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_WriteLookupbackDnsServerList( %S )\n",
|
|
pszAdapterName ));
|
|
|
|
//
|
|
// open adapter key for write
|
|
//
|
|
// DCR: fail on adapter key name overflow
|
|
//
|
|
|
|
if ( !pszAdapterName )
|
|
{
|
|
return ERROR_INVALID_NAME;
|
|
}
|
|
|
|
_snwprintf(
|
|
adapterParamKey,
|
|
MAX_PATH,
|
|
L"%s%s",
|
|
TCPIP_INTERFACES_KEY,
|
|
pszAdapterName );
|
|
|
|
adapterParamKey[ MAX_PATH ] = 0;
|
|
|
|
status = RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
adapterParamKey,
|
|
0,
|
|
KEY_READ | KEY_WRITE,
|
|
& hkeyAdapter );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
return( status );
|
|
}
|
|
|
|
//
|
|
// write loopback address
|
|
//
|
|
|
|
pstring = L"127.0.0.1";
|
|
|
|
status = RegSetValueExW(
|
|
hkeyAdapter,
|
|
DNS_SERVERS,
|
|
0,
|
|
REGTYPE_DNS_SERVER,
|
|
(PBYTE) pstring,
|
|
(wcslen(pstring)+1) * sizeof(WCHAR) );
|
|
|
|
RegCloseKey( hkeyAdapter );
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// PDN Query
|
|
//
|
|
|
|
PSTR
|
|
WINAPI
|
|
Reg_GetPrimaryDomainName(
|
|
IN DNS_CHARSET CharSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get primary domain name (PDN).
|
|
|
|
Arguments:
|
|
|
|
CharSet -- desired char set.
|
|
|
|
Return Value:
|
|
|
|
Ptr to primary domain name in desired charset.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
PWSTR pnameW = NULL;
|
|
PSTR pnameReturn;
|
|
|
|
status = Reg_ReadPrimaryDomainName(
|
|
NULL, // no session
|
|
NULL, // no regkey
|
|
&pnameW );
|
|
|
|
if ( !pnameW )
|
|
{
|
|
SetLastError( status );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// convert to desired char set
|
|
//
|
|
|
|
if ( CharSet == DnsCharSetUnicode )
|
|
{
|
|
return (PSTR) pnameW;
|
|
}
|
|
else
|
|
{
|
|
pnameReturn = Dns_NameCopyAllocate(
|
|
(PBYTE) pnameW,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSet );
|
|
|
|
FREE_HEAP( pnameW );
|
|
return pnameReturn;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Hostname query
|
|
//
|
|
|
|
PSTR
|
|
WINAPI
|
|
Reg_GetHostName(
|
|
IN DNS_CHARSET CharSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get host name.
|
|
|
|
Arguments:
|
|
|
|
CharSet -- desired char set.
|
|
|
|
Return Value:
|
|
|
|
Ptr to host name in desired charset.
|
|
|
|
--*/
|
|
{
|
|
PWSTR pnameW = NULL;
|
|
PSTR pnameReturn;
|
|
DNS_STATUS status;
|
|
|
|
//
|
|
// get hostname from registry
|
|
//
|
|
|
|
status = Reg_GetValue(
|
|
NULL, // no session
|
|
NULL, // no key
|
|
RegIdHostName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pnameW
|
|
);
|
|
|
|
if ( !pnameW )
|
|
{
|
|
SetLastError( status );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// convert to desired char set
|
|
//
|
|
|
|
if ( CharSet == DnsCharSetUnicode )
|
|
{
|
|
return (PSTR) pnameW;
|
|
}
|
|
else
|
|
{
|
|
pnameReturn = Dns_NameCopyAllocate(
|
|
(PBYTE) pnameW,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSet );
|
|
|
|
FREE_HEAP( pnameW );
|
|
return pnameReturn;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PSTR
|
|
WINAPI
|
|
Reg_GetFullHostName(
|
|
IN DNS_CHARSET CharSet
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get full host name.
|
|
|
|
Arguments:
|
|
|
|
CharSet -- desired char set.
|
|
|
|
Return Value:
|
|
|
|
Ptr to full host name in desired charset.
|
|
|
|
--*/
|
|
{
|
|
PWSTR pnameW = NULL;
|
|
PWSTR pdomainW = NULL;
|
|
PSTR presult = NULL;
|
|
DNS_STATUS status;
|
|
WCHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH+4 ];
|
|
|
|
//
|
|
// get hostname from registry
|
|
//
|
|
|
|
status = Reg_GetValue(
|
|
NULL, // no session
|
|
NULL, // no key
|
|
RegIdHostName,
|
|
REGTYPE_DNS_NAME,
|
|
(PBYTE *) &pnameW
|
|
);
|
|
if ( !pnameW )
|
|
{
|
|
SetLastError( status );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// get domain name from registry
|
|
//
|
|
|
|
status = Reg_ReadPrimaryDomainName(
|
|
NULL, // no session
|
|
NULL, // no regkey
|
|
&pdomainW );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
SetLastError( status );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// create appended name
|
|
// - wire format is narrow
|
|
//
|
|
// allocate result in desired char set
|
|
//
|
|
|
|
if ( pdomainW )
|
|
{
|
|
if ( Dns_NameAppend_W(
|
|
nameBuffer,
|
|
DNS_MAX_NAME_BUFFER_LENGTH,
|
|
pnameW,
|
|
pdomainW ) )
|
|
{
|
|
presult = Dns_NameCopyAllocate(
|
|
(PBYTE) nameBuffer,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSet );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
presult = Dns_NameCopyAllocate(
|
|
(PBYTE) pnameW,
|
|
0,
|
|
DnsCharSetUnicode,
|
|
CharSet );
|
|
}
|
|
|
|
//
|
|
// free registry allocations
|
|
//
|
|
|
|
FREE_HEAP( pnameW );
|
|
FREE_HEAP( pdomainW );
|
|
|
|
return presult;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// DWORD Get\Set
|
|
//
|
|
|
|
DWORD
|
|
Reg_ReadDwordValueFromGlobal(
|
|
IN DWORD PropId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read DWORD from global.
|
|
|
|
This is direct access to global through RegId,
|
|
rather than by name.
|
|
|
|
Arguments:
|
|
|
|
PropId -- property ID of desired value
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
PDWORD pdword;
|
|
|
|
//
|
|
// validate PropId -- within DWORD array
|
|
//
|
|
|
|
if ( PropId > RegIdValueGlobalMax )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
return( 0 );
|
|
}
|
|
|
|
//
|
|
// get DWORD ptr and read value (if exists)
|
|
//
|
|
|
|
pdword = RegDwordPtrArray[ PropId ];
|
|
|
|
if ( !pdword )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
return( 0 );
|
|
}
|
|
|
|
return( *pdword );
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
Reg_ReadDwordProperty(
|
|
IN DNS_REGID RegId,
|
|
IN PWSTR pwsAdapterName OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read through to registry for DWORD\BOOL value.
|
|
|
|
Simplified interface for DWORD reads.
|
|
|
|
Arguments:
|
|
|
|
RegId -- registry ID of value
|
|
|
|
pwsAdapterName -- adapter name if adapter specific registration
|
|
value is desired
|
|
|
|
Return Value:
|
|
|
|
Value for global -- from registry or defaulted
|
|
|
|
--*/
|
|
{
|
|
DWORD value;
|
|
|
|
//
|
|
// read value
|
|
//
|
|
|
|
Reg_GetDword(
|
|
NULL, // no session
|
|
NULL, // no key given
|
|
pwsAdapterName,
|
|
RegId,
|
|
& value );
|
|
|
|
return( value );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
WINAPI
|
|
Reg_SetDwordPropertyAndAlertCache(
|
|
IN PWSTR pwsKey,
|
|
IN DWORD RegId,
|
|
IN DWORD dwValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write DWORD property -- cause cache to reload config.
|
|
|
|
Arguments:
|
|
|
|
pwsRey -- key or adapater name to set
|
|
|
|
RegId -- reg id
|
|
|
|
dwValue -- value to set
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status;
|
|
|
|
// set value
|
|
|
|
status = Reg_SetDwordValue(
|
|
NULL, // reserved
|
|
NULL, // no open key
|
|
pwsKey,
|
|
RegId,
|
|
dwValue );
|
|
|
|
//
|
|
// if reg write successful
|
|
// - poke cache
|
|
// - mark any local netinfo dirty
|
|
//
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
DnsNotifyResolverEx(
|
|
POKE_OP_UPDATE_NETINFO,
|
|
0,
|
|
POKE_COOKIE_UPDATE_NETINFO,
|
|
NULL );
|
|
|
|
NetInfo_MarkDirty();
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Environment variable configuration
|
|
//
|
|
|
|
BOOL
|
|
Reg_ReadDwordEnvar(
|
|
IN DWORD Id,
|
|
OUT PENVAR_DWORD_INFO pEnvar
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read DWORD environment variable.
|
|
|
|
Note: this function read environment variables that allow
|
|
per process control of registry configurable params.
|
|
The environment variable is assumed to be the same
|
|
as the regkey with Dns prepended ( Dns<regvalue name> ).
|
|
|
|
Ex. FilterClusterIp controlled with envar DnsFilterClusterIp.
|
|
|
|
Arguments:
|
|
|
|
Id -- registry ID (registry.h) of environment value to read
|
|
|
|
pEnvar -- ptr to blob to hold results
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD count;
|
|
PWSTR pnameBuffer;
|
|
PWSTR pvarBuffer;
|
|
BOOL found = FALSE;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_ReadDwordEnvar( %d, %p )\n",
|
|
Id,
|
|
pEnvar ));
|
|
|
|
if ( Id > RegIdValueGlobalMax )
|
|
{
|
|
DNS_ASSERT( FALSE );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// init struct (for not found)
|
|
//
|
|
|
|
pEnvar->Id = Id;
|
|
pEnvar->Value = 0;
|
|
pEnvar->fFound = FALSE;
|
|
|
|
//
|
|
// prepend "Dns" to reg value name to create environment var name
|
|
//
|
|
|
|
pnameBuffer = (PWSTR) ALLOCATE_HEAP( 2 * (sizeof(WCHAR) * MAX_PATH) );
|
|
if ( !pnameBuffer )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pvarBuffer = pnameBuffer + MAX_PATH;
|
|
|
|
wcscpy( pnameBuffer, L"Dns" );
|
|
wcscpy( &pnameBuffer[3], REGPROP_NAME(Id) );
|
|
|
|
//
|
|
// lookup
|
|
//
|
|
// note: no handling of values greater than MAX_PATH
|
|
// assuming busted string
|
|
//
|
|
// DCR: could add base discrimination (scan for non-digit)
|
|
// or try decimal first
|
|
//
|
|
|
|
DNSDBG( TRACE, (
|
|
"Reg_ReadDwordEnvar() looking up %S.\n",
|
|
pnameBuffer ));
|
|
|
|
count = GetEnvironmentVariableW(
|
|
pnameBuffer,
|
|
pvarBuffer,
|
|
MAX_PATH );
|
|
|
|
if ( count && count < MAX_PATH )
|
|
{
|
|
pEnvar->Value = wcstoul( pvarBuffer, NULL, 10 );
|
|
found = TRUE;
|
|
}
|
|
|
|
pEnvar->fFound = found;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Leave Reg_ReadDwordEnvar() %S found=%d, value=%d.\n",
|
|
pnameBuffer,
|
|
pEnvar->fFound,
|
|
pEnvar->Value ));
|
|
|
|
FREE_HEAP( pnameBuffer );
|
|
|
|
return found;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
//
|
|
// Remote resolver not currently supported
|
|
//
|
|
|
|
PWSTR
|
|
Reg_GetResolverAddress(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get address (string form) of remote resolver.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Ptr to string of remote resolver name.
|
|
|
|
--*/
|
|
{
|
|
PWSTR pnameResolver = NULL;
|
|
|
|
Reg_GetValueEx(
|
|
NULL, // no session
|
|
NULL, // no key
|
|
NULL, // no adapter
|
|
RegIdRemoteResolver,
|
|
REGTYPE_DNS_NAME,
|
|
DNSREG_FLAG_GET_UNICODE | DNSREG_FLAG_DUMP_EMPTY,
|
|
(PBYTE *) &pnameResolver
|
|
);
|
|
|
|
return pnameResolver;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// End regfig.c
|
|
//
|