Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1792 lines
61 KiB

/*++
Copyright (c) 1987-1996 Microsoft Corporation
Module Name:
parse.c
Abstract:
Routine to parse the command line.
Author:
Ported from Lan Man 2.0
Environment:
User mode only.
Contains NT-specific code.
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
01-Aug-1991 (cliffv)
Ported to NT. Converted to NT style.
09-May-1992 JohnRo
Enable use of win32 registry.
Use net config helpers for NetLogon.
Fixed UNICODE bug handling debug file name.
Use <prefix.h> equates.
--*/
//
// Common include files.
//
#include "logonsrv.h" // Include files common to entire service
#pragma hdrstop
#include <configp.h> // USE_WIN32_CONFIG (if defined), etc.
#include <prefix.h> // PREFIX_ equates.
//
// Include files specific to this .c file
//
#include <string.h> // strnicmp
NET_API_STATUS
NlParseOne(
IN LPNET_CONFIG_HANDLE SectionHandle,
IN BOOL GpSection,
IN LPWSTR Keyword,
IN ULONG DefaultValue,
IN ULONG MinimumValue,
IN ULONG MaximumValue,
OUT PULONG Value
)
/*++
Routine Description:
Get a single numeric parameter from the netlogon section of the registry.
Arguments:
SectionHandle - Handle into the registry.
GpSection - TRUE iff the section is the group policy section.
Keyword - Name of the value to read.
DefaultValue - Default value if parameter doesn't exist.
MinimumValue - Minumin valid value.
MaximumValue - Maximum valid value.
Value - Returns the value parsed.
Return Value:
Status of the operation
--*/
{
NET_API_STATUS NetStatus;
LPWSTR ValueT = NULL;
//
// Always return a reasonable value.
//
*Value = DefaultValue;
//
// Determine if the value is specified in the registry at all.
//
NetStatus = NetpGetConfigValue (
SectionHandle,
Keyword,
&ValueT );
if( ValueT != NULL ) {
NetApiBufferFree( ValueT );
ValueT = NULL;
}
//
// If the value wasn't specified,
// use the default.
//
if ( NetStatus == NERR_CfgParamNotFound ) {
*Value = DefaultValue;
//
// If the value was specifed,
// get it from the registry.
//
} else {
NetStatus = NetpGetConfigDword (
SectionHandle,
Keyword, // keyword wanted
DefaultValue,
Value );
if (NetStatus == NO_ERROR) {
if ( *Value > MaximumValue || *Value < MinimumValue ) {
ULONG InvalidValue;
LPWSTR MsgStrings[6];
// Each byte of the status code will transform into one character 0-F
WCHAR InvalidValueString[sizeof(WCHAR) * (sizeof(InvalidValue) + 1)];
WCHAR MinimumValueString[sizeof(WCHAR) * (sizeof(MinimumValue) + 1)];
WCHAR MaximumValueString[sizeof(WCHAR) * (sizeof(MaximumValue) + 1)];
WCHAR AssignedValueString[sizeof(WCHAR) * (sizeof(*Value) + 1)];
InvalidValue = *Value;
if ( *Value > MaximumValue ) {
*Value = MaximumValue;
} else if ( *Value < MinimumValue ) {
*Value = MinimumValue;
}
swprintf( InvalidValueString, L"%lx", InvalidValue );
swprintf( MinimumValueString, L"%lx", MinimumValue );
swprintf( MaximumValueString, L"%lx", MaximumValue );
swprintf( AssignedValueString, L"%lx", *Value );
if ( GpSection ) {
MsgStrings[0] = L"Group Policy";
} else {
MsgStrings[0] = L"Parameters";
}
MsgStrings[1] = InvalidValueString;
MsgStrings[2] = Keyword;
MsgStrings[3] = MinimumValueString;
MsgStrings[4] = MaximumValueString;
MsgStrings[5] = AssignedValueString;
NlpWriteEventlog( NELOG_NetlogonInvalidDwordParameterValue,
EVENTLOG_WARNING_TYPE,
NULL,
0,
MsgStrings,
6 );
}
} else {
return NetStatus;
}
}
return NERR_Success;
}
NET_API_STATUS
NlParseOnePath(
IN LPNET_CONFIG_HANDLE SectionHandle,
IN LPWSTR Keyword,
IN LPWSTR DefaultValue1 OPTIONAL,
OUT LPWSTR *Value
)
/*++
Routine Description:
Get a single path parameter from the netlogon section of the registry.
Arguments:
SectionHandle - Handle into the registry.
Keyword - Name of the value to read.
DefaultValue1 - Default value if parameter doesn't exist.
If NULL, Value will be set to NULL to indicate there is no default.
Value - Returns the value parsed.
Must be freed using NetApiBufferFree.
Return Value:
Status of the operation
--*/
{
NET_API_STATUS NetStatus;
WCHAR OutPathname[MAX_PATH+1];
WCHAR TempPathname[MAX_PATH*2+1];
LPWSTR ValueT = NULL;
ULONG type;
//
// Get the configured parameter
//
*Value = NULL;
NetStatus = NetpGetConfigValue (
SectionHandle,
Keyword, // key wanted
&ValueT ); // Must be freed by NetApiBufferFree().
if (NetStatus != NO_ERROR) {
//
// Handle the default
//
if (NetStatus == NERR_CfgParamNotFound) {
//
// If there is no default,
// we're done.
//
if ( DefaultValue1 == NULL ) {
*Value = NULL;
NetStatus = NO_ERROR;
goto Cleanup;
}
//
// Build the default value.
//
ValueT = NetpAllocWStrFromWStr( DefaultValue1 );
if ( ValueT == NULL ) {
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
} else {
goto Cleanup;
}
}
NlAssert( ValueT != NULL );
//
// Convert the configured sysvol path to a full pathname.
//
type = 0; // Let the API figure out the type.
NetStatus = I_NetPathCanonicalize( NULL,
ValueT,
OutPathname,
sizeof(OutPathname),
NULL,
&type,
0L );
if (NetStatus != NERR_Success ) {
goto Cleanup;
}
if (type == ITYPE_PATH_ABSD) {
NetpCopyTStrToWStr(TempPathname, OutPathname);
} else if (type == ITYPE_PATH_RELND) {
if ( !GetSystemWindowsDirectoryW(
TempPathname,
sizeof(TempPathname)/sizeof(WCHAR) ) ) {
NetStatus = GetLastError();
goto Cleanup;
}
wcscat( TempPathname, L"\\" );
wcscat( TempPathname, OutPathname );
} else {
NetStatus = NERR_BadComponent;
goto Cleanup;
}
//
// Return the pathname in an allocated buffer
//
*Value = NetpAllocWStrFromWStr( TempPathname );
if ( *Value == NULL ) {
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
Cleanup:
if ( ValueT != NULL ) {
(VOID) NetApiBufferFree( ValueT );
}
return NetStatus;
}
//
// Table of numeric parameters to parse.
//
#define getoffset( _x ) offsetof( NETLOGON_PARAMETERS, _x )
struct {
LPWSTR Keyword;
ULONG DefaultValue;
ULONG MinimumValue;
ULONG MaximumValue;
ULONG ValueOffset;
BOOLEAN ChangesDnsRegistration;
} ParseTable[] =
{
{ NETLOGON_KEYWORD_PULSE, DEFAULT_PULSE, MIN_PULSE, MAX_PULSE, getoffset( Pulse ), FALSE },
{ NETLOGON_KEYWORD_RANDOMIZE, DEFAULT_RANDOMIZE, MIN_RANDOMIZE, MAX_RANDOMIZE, getoffset( Randomize ), FALSE },
{ NETLOGON_KEYWORD_PULSEMAXIMUM, DEFAULT_PULSEMAXIMUM, MIN_PULSEMAXIMUM, MAX_PULSEMAXIMUM, getoffset( PulseMaximum ), FALSE },
{ NETLOGON_KEYWORD_PULSECONCURRENCY, DEFAULT_PULSECONCURRENCY, MIN_PULSECONCURRENCY, MAX_PULSECONCURRENCY, getoffset( PulseConcurrency ), FALSE },
{ NETLOGON_KEYWORD_PULSETIMEOUT1, DEFAULT_PULSETIMEOUT1, MIN_PULSETIMEOUT1, MAX_PULSETIMEOUT1, getoffset( PulseTimeout1 ), FALSE },
{ NETLOGON_KEYWORD_PULSETIMEOUT2, DEFAULT_PULSETIMEOUT2, MIN_PULSETIMEOUT2, MAX_PULSETIMEOUT2, getoffset( PulseTimeout2 ), FALSE },
{ NETLOGON_KEYWORD_MAXIMUMMAILSLOTMESSAGES, DEFAULT_MAXIMUMMAILSLOTMESSAGES, MIN_MAXIMUMMAILSLOTMESSAGES, MAX_MAXIMUMMAILSLOTMESSAGES, getoffset( MaximumMailslotMessages ), FALSE },
{ NETLOGON_KEYWORD_MAILSLOTMESSAGETIMEOUT, DEFAULT_MAILSLOTMESSAGETIMEOUT, MIN_MAILSLOTMESSAGETIMEOUT, MAX_MAILSLOTMESSAGETIMEOUT, getoffset( MailslotMessageTimeout ), FALSE },
{ NETLOGON_KEYWORD_MAILSLOTDUPLICATETIMEOUT,DEFAULT_MAILSLOTDUPLICATETIMEOUT,MIN_MAILSLOTDUPLICATETIMEOUT,MAX_MAILSLOTDUPLICATETIMEOUT,getoffset( MailslotDuplicateTimeout ),FALSE },
{ NETLOGON_KEYWORD_EXPECTEDDIALUPDELAY, DEFAULT_EXPECTEDDIALUPDELAY, MIN_EXPECTEDDIALUPDELAY, MAX_EXPECTEDDIALUPDELAY, getoffset( ExpectedDialupDelay ), FALSE },
{ NETLOGON_KEYWORD_SCAVENGEINTERVAL, DEFAULT_SCAVENGEINTERVAL, MIN_SCAVENGEINTERVAL, MAX_SCAVENGEINTERVAL, getoffset( ScavengeInterval ), FALSE },
{ NETLOGON_KEYWORD_MAXIMUMPASSWORDAGE, DEFAULT_MAXIMUMPASSWORDAGE, MIN_MAXIMUMPASSWORDAGE, MAX_MAXIMUMPASSWORDAGE, getoffset( MaximumPasswordAge ), FALSE },
{ NETLOGON_KEYWORD_LDAPSRVPRIORITY, DEFAULT_LDAPSRVPRIORITY, MIN_LDAPSRVPRIORITY, MAX_LDAPSRVPRIORITY, getoffset( LdapSrvPriority ), TRUE },
{ NETLOGON_KEYWORD_LDAPSRVWEIGHT, DEFAULT_LDAPSRVWEIGHT, MIN_LDAPSRVWEIGHT, MAX_LDAPSRVWEIGHT, getoffset( LdapSrvWeight ), TRUE },
{ NETLOGON_KEYWORD_LDAPSRVPORT, DEFAULT_LDAPSRVPORT, MIN_LDAPSRVPORT, MAX_LDAPSRVPORT, getoffset( LdapSrvPort ), TRUE },
{ NETLOGON_KEYWORD_LDAPGCSRVPORT, DEFAULT_LDAPGCSRVPORT, MIN_LDAPGCSRVPORT, MAX_LDAPGCSRVPORT, getoffset( LdapGcSrvPort ), TRUE },
{ L"KdcSrvPort", DEFAULT_KDCSRVPORT, MIN_KDCSRVPORT, MAX_KDCSRVPORT, getoffset( KdcSrvPort ), TRUE },
{ NETLOGON_KEYWORD_KERBISDDONEWITHJOIN, DEFAULT_KERBISDDONEWITHJOIN, MIN_KERBISDDONEWITHJOIN, MAX_KERBISDDONEWITHJOIN, getoffset( KerbIsDoneWithJoinDomainEntry),FALSE},
{ NETLOGON_KEYWORD_DNSTTL, DEFAULT_DNSTTL, MIN_DNSTTL, MAX_DNSTTL, getoffset( DnsTtl ), TRUE },
{ NETLOGON_KEYWORD_DNSREFRESHINTERVAL, DEFAULT_DNSREFRESHINTERVAL, MIN_DNSREFRESHINTERVAL, MAX_DNSREFRESHINTERVAL, getoffset( DnsRefreshInterval ), TRUE },
{ L"CloseSiteTimeout", DEFAULT_CLOSESITETIMEOUT, MIN_CLOSESITETIMEOUT, MAX_CLOSESITETIMEOUT, getoffset( CloseSiteTimeout ), FALSE },
{ L"SiteNameTimeout", DEFAULT_SITENAMETIMEOUT, MIN_SITENAMETIMEOUT, MAX_SITENAMETIMEOUT, getoffset( SiteNameTimeout ), FALSE },
{ L"DuplicateEventlogTimeout", DEFAULT_DUPLICATEEVENTLOGTIMEOUT,MIN_DUPLICATEEVENTLOGTIMEOUT,MAX_DUPLICATEEVENTLOGTIMEOUT,getoffset( DuplicateEventlogTimeout ),FALSE },
{ L"MaxConcurrentApi", DEFAULT_MAXCONCURRENTAPI, MIN_MAXCONCURRENTAPI, MAX_MAXCONCURRENTAPI, getoffset( MaxConcurrentApi ), FALSE },
{ L"NegativeCachePeriod", DEFAULT_NEGATIVECACHEPERIOD, MIN_NEGATIVECACHEPERIOD, MAX_NEGATIVECACHEPERIOD, getoffset( NegativeCachePeriod ), FALSE },
{ L"BackgroundRetryInitialPeriod", DEFAULT_BACKGROUNDRETRYINITIALPERIOD,MIN_BACKGROUNDRETRYINITIALPERIOD,MAX_BACKGROUNDRETRYINITIALPERIOD,getoffset( BackgroundRetryInitialPeriod ),FALSE },
{ L"BackgroundRetryMaximumPeriod", DEFAULT_BACKGROUNDRETRYMAXIMUMPERIOD,MIN_BACKGROUNDRETRYMAXIMUMPERIOD,MAX_BACKGROUNDRETRYMAXIMUMPERIOD,getoffset( BackgroundRetryMaximumPeriod ),FALSE },
{ L"BackgroundRetryQuitTime", DEFAULT_BACKGROUNDRETRYQUITTIME, MIN_BACKGROUNDRETRYQUITTIME, MAX_BACKGROUNDRETRYQUITTIME, getoffset( BackgroundRetryQuitTime ), FALSE },
{ L"BackgroundSuccessfulRefreshPeriod", DEFAULT_BACKGROUNDREFRESHPERIOD, MIN_BACKGROUNDREFRESHPERIOD, MAX_BACKGROUNDREFRESHPERIOD, getoffset( BackgroundSuccessfulRefreshPeriod ), FALSE },
{ L"NonBackgroundSuccessfulRefreshPeriod", DEFAULT_NONBACKGROUNDREFRESHPERIOD, MIN_NONBACKGROUNDREFRESHPERIOD, MAX_NONBACKGROUNDREFRESHPERIOD, getoffset( NonBackgroundSuccessfulRefreshPeriod ), FALSE },
{ L"DnsFailedDeregisterTimeout", DEFAULT_DNSFAILEDDEREGTIMEOUT, MIN_DNSFAILEDDEREGTIMEOUT, MAX_DNSFAILEDDEREGTIMEOUT, getoffset( DnsFailedDeregisterTimeout ), FALSE },
{ L"MaxLdapServersPinged", DEFAULT_MAXLDAPSERVERSPINGED, MIN_MAXLDAPSERVERSPINGED, MAX_MAXLDAPSERVERSPINGED, getoffset( MaxLdapServersPinged ), FALSE },
{ L"SiteCoverageRefreshInterval", DEFAULT_SITECOVERAGEREFRESHINTERVAL, MIN_SITECOVERAGEREFRESHINTERVAL, MAX_SITECOVERAGEREFRESHINTERVAL, getoffset( SiteCoverageRefreshInterval ), TRUE },
{ L"FtInfoUpdateInterval", DEFAULT_FTINFO_UPDATE_INTERVAL, MIN_FTINFO_UPDATE_INTERVAL, MAX_FTINFO_UPDATE_INTERVAL, getoffset( FtInfoUpdateInterval ), FALSE },
#if NETLOGONDBG
{ NETLOGON_KEYWORD_DBFLAG, 0, 0, 0xFFFFFFFF, getoffset( DbFlag ), FALSE },
{ NETLOGON_KEYWORD_MAXIMUMLOGFILESIZE, DEFAULT_MAXIMUM_LOGFILE_SIZE, 0, 0xFFFFFFFF, getoffset( LogFileMaxSize ), FALSE },
#endif // NETLOGONDBG
};
//
// Table of boolean to parse.
//
struct {
LPWSTR Keyword;
BOOL DefaultValue;
ULONG ValueOffset;
BOOLEAN ChangesDnsRegistration;
} BoolParseTable[] =
{
#ifdef _DC_NETLOGON
{ NETLOGON_KEYWORD_REFUSEPASSWORDCHANGE, DEFAULT_REFUSE_PASSWORD_CHANGE, getoffset( RefusePasswordChange ), FALSE },
{ NETLOGON_KEYWORD_ALLOWREPLINNONMIXED, DEFAULT_ALLOWREPLINNONMIXED, getoffset( AllowReplInNonMixed ), FALSE },
{ L"AvoidSamRepl", TRUE, getoffset( AvoidSamRepl ), FALSE },
{ L"AvoidLsaRepl", TRUE, getoffset( AvoidLsaRepl ), FALSE },
{ L"SignSecureChannel", TRUE, getoffset( SignSecureChannel ), FALSE },
{ L"SealSecureChannel", TRUE, getoffset( SealSecureChannel ), FALSE },
{ L"RequireSignOrSeal", FALSE, getoffset( RequireSignOrSeal ), FALSE },
{ L"RequireStrongKey", FALSE, getoffset( RequireStrongKey ), FALSE },
{ L"SysVolReady", TRUE, getoffset( SysVolReady ), FALSE },
{ L"UseDynamicDns", TRUE, getoffset( UseDynamicDns ), TRUE },
{ L"RegisterDnsARecords", TRUE, getoffset( RegisterDnsARecords ), TRUE },
{ L"AvoidPdcOnWan", FALSE, getoffset( AvoidPdcOnWan ), FALSE },
{ L"AutoSiteCoverage", TRUE, getoffset( AutoSiteCoverage ), TRUE },
{ L"AvoidDnsDeregOnShutdown", TRUE, getoffset(AvoidDnsDeregOnShutdown), TRUE },
{ L"DnsUpdateOnAllAdapters", FALSE, getoffset(DnsUpdateOnAllAdapters), TRUE },
{ NETLOGON_KEYWORD_NT4EMULATOR, FALSE, getoffset(Nt4Emulator), FALSE },
#endif // _DC_NETLOGON
{ NETLOGON_KEYWORD_DISABLEPASSWORDCHANGE, DEFAULT_DISABLE_PASSWORD_CHANGE, getoffset( DisablePasswordChange ), FALSE },
{ NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR, FALSE,/* default is set later */ getoffset( NeutralizeNt4Emulator ), FALSE },
{ L"AllowSingleLabelDnsDomain", FALSE, getoffset(AllowSingleLabelDnsDomain), FALSE },
{ L"AllowExclusiveSysvolShareAccess", FALSE, getoffset(AllowExclusiveSysvolShareAccess), FALSE },
{ L"AllowExclusiveScriptsShareAccess", FALSE, getoffset(AllowExclusiveScriptsShareAccess), FALSE },
{ L"AvoidLocatorAccountLookup", FALSE, getoffset(AvoidLocatorAccountLookup), FALSE },
};
VOID
NlParseRecompute(
IN PNETLOGON_PARAMETERS NlParameters
)
/*++
Routine Description:
This routine recomputes globals that are simple functions of registry
parameters.
Arguments:
NlParameters - Structure describing all parameters
Return Value:
None.
--*/
{
ULONG RandomMinutes;
//
// Adjust values that are functions of each other.
//
if ( NlParameters->BackgroundRetryInitialPeriod < NlParameters->NegativeCachePeriod ) {
NlParameters->BackgroundRetryInitialPeriod = NlParameters->NegativeCachePeriod;
}
if ( NlParameters->BackgroundRetryMaximumPeriod < NlParameters->BackgroundRetryInitialPeriod ) {
NlParameters->BackgroundRetryMaximumPeriod = NlParameters->BackgroundRetryInitialPeriod;
}
if ( NlParameters->BackgroundRetryQuitTime != 0 &&
NlParameters->BackgroundRetryQuitTime < NlParameters->BackgroundRetryMaximumPeriod ) {
NlParameters->BackgroundRetryQuitTime = NlParameters->BackgroundRetryMaximumPeriod;
}
//
// Convert from seconds to 100ns
//
NlParameters->PulseMaximum_100ns.QuadPart =
Int32x32To64( NlParameters->PulseMaximum, 10000000 );
NlParameters->PulseTimeout1_100ns.QuadPart =
Int32x32To64( NlParameters->PulseTimeout1, 10000000 );
NlParameters->PulseTimeout2_100ns.QuadPart =
Int32x32To64( NlParameters->PulseTimeout2, 10000000 );
NlParameters->MailslotMessageTimeout_100ns.QuadPart =
Int32x32To64( NlParameters->MailslotMessageTimeout, 10000000 );
NlParameters->MailslotDuplicateTimeout_100ns.QuadPart =
Int32x32To64( NlParameters->MailslotDuplicateTimeout, 10000000 );
NlParameters->BackgroundRetryQuitTime_100ns.QuadPart =
Int32x32To64( NlParameters->BackgroundRetryQuitTime, 10000000 );
//
// Convert from days to 100ns
//
NlParameters->MaximumPasswordAge_100ns.QuadPart =
((LONGLONG) NlParameters->MaximumPasswordAge) *
((LONGLONG) 10000000) *
((LONGLONG) 24*60*60);
//
// Add a fraction of a day to prevent all machines created at the same time
// from changing their password at the same time.
RandomMinutes = (DWORD) rand() % (24*60);
NlParameters->MaximumPasswordAge_100ns.QuadPart +=
((LONGLONG) RandomMinutes) *
((LONGLONG) 10000000) *
((LONGLONG) 60);
#ifdef notdef
NlPrint((NL_INIT," RandomMinutes = %lu (0x%lx)\n",
RandomMinutes,
RandomMinutes ));
#endif // notdef
NlParameters->ShortApiCallPeriod =
SHORT_API_CALL_PERIOD + NlParameters->ExpectedDialupDelay * 1000;
NlParameters->DnsRefreshIntervalPeriod =
NlParameters->DnsRefreshInterval * 1000;
if ( NlParameters->RequireSignOrSeal ) {
NlParameters->SignSecureChannel = TRUE;
}
}
NET_API_STATUS
NlParseTStr(
IN LPNET_CONFIG_HANDLE SectionHandle,
IN LPWSTR Keyword,
IN BOOL MultivaluedParameter,
IN OUT LPWSTR *DefaultValue,
OUT LPWSTR *Parameter
)
/*++
Routine Description:
This routine parses a null or doubly-null terminated string
Arguments:
SectionHandle - Handle to a section in registry
Keyword - The name of the parameter to read
MultivaluedParameter - If TRUE, the keyword is a multiple
string where elements are separated by a single null
character and the array is ended with two null characters.
If FALSE, the keyword is a single string ended with one
null terminator.
DefaultValue - The default value of the parameter.
If NULL, the section handle passed is that of the Netlogon Parameters section.
If non-NULL, the section handle passed is that of the GP section.
If specified and used by this routine, it is set to NULL to indicate
that it has been consumed by this routine.
Parameter - Returns the parameter read.
Return Value:
Status returned by NetpGetConfigTStrArray.
--*/
{
NET_API_STATUS NetStatus;
//
// Get the configured parameter
//
// GP doesn't support multivalued strings. Instead a single
// string is used where individual strings are separated
// by spaces.
//
if ( MultivaluedParameter && DefaultValue == NULL ) {
NetStatus = NetpGetConfigTStrArray (
SectionHandle,
Keyword,
Parameter ); // Must be freed by NetApiBufferFree().
} else {
NetStatus = NetpGetConfigValue (
SectionHandle,
Keyword,
Parameter ); // Must be freed by NetApiBufferFree().
}
//
// If the parameter is empty string,
// set it to NULL
//
if ( NetStatus == NERR_Success &&
(*Parameter)[0] == UNICODE_NULL ) {
NetApiBufferFree( *Parameter );
*Parameter = NULL;
NetStatus = NERR_CfgParamNotFound;
}
//
// Convert the single valued string into the multivalued form
//
if ( NetStatus == NERR_Success && // we successfully read the registry
MultivaluedParameter && // this is multivalued parameter
DefaultValue != NULL ) { // we are parsing the GP section
ULONG ParameterLength = 0;
LPWSTR LocalParameter = NULL;
//
// The multivalued string will have two NULL terminator
// characters at the end, so allocate enough storage
//
ParameterLength = wcslen(*Parameter);
NetStatus = NetApiBufferAllocate( (ParameterLength + 2) * sizeof(WCHAR),
&LocalParameter );
if ( NetStatus == NO_ERROR ) {
LPWSTR ParameterPtr = NULL;
LPWSTR LocalParameterPtr = NULL;
RtlZeroMemory( LocalParameter, (ParameterLength + 2) * sizeof(WCHAR) );
ParameterPtr = *Parameter;
LocalParameterPtr = LocalParameter;
while ( *ParameterPtr != UNICODE_NULL ) {
//
// Disregard spaces in the input string. Note that
// the user may have used several spaces to separate
// two adjacent strings.
//
while ( *ParameterPtr == L' ' && *ParameterPtr != UNICODE_NULL ) {
ParameterPtr ++;
}
//
// Copy non-space characters
//
while ( *ParameterPtr != L' ' && *ParameterPtr != UNICODE_NULL ) {
*LocalParameterPtr++ = *ParameterPtr++;
}
//
// Insert one NULL character between single values
//
*LocalParameterPtr++ = UNICODE_NULL;
}
//
// Free the value read from registry
//
NetApiBufferFree( *Parameter );
*Parameter = NULL;
//
// If the resulting multivalued string is not empty,
// use it. The resulting string may need smaller
// storage that we have allocated, so allocate again
// exactly what's needed to (potentially) save memory.
//
ParameterLength = NetpTStrArraySize( LocalParameter ); // this includes all storage
if ( ParameterLength > 2*sizeof(WCHAR) ) {
NetStatus = NetApiBufferAllocate( ParameterLength, Parameter );
if ( NetStatus == NO_ERROR ) {
RtlCopyMemory( *Parameter, LocalParameter, ParameterLength );
}
} else {
NetStatus = ERROR_INVALID_PARAMETER;
}
if ( LocalParameter != NULL ) {
NetApiBufferFree( LocalParameter );
LocalParameter = NULL;
}
}
}
//
// Handle the default
//
if ( NetStatus != NERR_Success ) {
if ( DefaultValue == NULL ) {
*Parameter = NULL;
} else {
*Parameter = *DefaultValue;
//
// Indicate that we have consumed the
// value from the default parameters
//
*DefaultValue = NULL;
}
}
//
// Write event log on error
//
if ( NetStatus != NERR_Success && NetStatus != NERR_CfgParamNotFound ) {
LPWSTR MsgStrings[3];
if ( DefaultValue == NULL ) {
MsgStrings[0] = L"Parameters";
} else {
MsgStrings[0] = L"Group Policy";
}
MsgStrings[1] = Keyword;
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
/* Not Fatal */
}
return NetStatus;
}
BOOL
Nlparse(
IN PNETLOGON_PARAMETERS NlParameters,
IN PNETLOGON_PARAMETERS DefaultParameters OPTIONAL,
IN BOOLEAN IsChangeNotify
)
/*++
Routine Description:
Get parameters from the group policy or registry.
All of the parameters are described in iniparm.h.
Arguments:
NlParameters - Structure describing all parameters
DefaultParameters - Structure describing default values for all parameters
If NULL, the values are read from the Netlogon Parameters section and
the default values specified in the parse table are used. If non-NULL,
the values are read from the Group Policy section and the specified
defaults are used.
IsChangeNotify - TRUE if this call is the result of a change notification
Return Value:
TRUE -- the registry was opened successfully and parameters
were read.
FALSE -- iff we couldn't open the appropriate registry section
--*/
{
BOOLEAN RetVal = TRUE;
NET_API_STATUS NetStatus;
NET_API_STATUS TempNetStatus;
LPWSTR ValueT = NULL;
LPWSTR Keyword = NULL;
LPWSTR MsgStrings[3];
ULONG i;
//
// Variables for scanning the configuration data.
//
LPNET_CONFIG_HANDLE SectionHandle = NULL;
LPNET_CONFIG_HANDLE WriteSectionHandle = NULL;
RtlZeroMemory( NlParameters, sizeof(NlParameters) );
//
// Open the appropriate configuration section
//
NetStatus = NetpOpenConfigDataWithPathEx(
&SectionHandle,
NULL, // no server name.
(DefaultParameters == NULL) ?
L"SYSTEM\\CurrentControlSet\\Services\\Netlogon" :
TEXT(NL_GP_KEY),
NULL, // default Parameters area
TRUE ); // we only want readonly access
if ( NetStatus != NO_ERROR ) {
SectionHandle = NULL;
//
// The Netlogon Parameters section must always
// exist. Write event log if we can't open it.
//
if ( DefaultParameters == NULL ) {
MsgStrings[0] = L"Parameters";
MsgStrings[1] = L"Parameters";
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
}
RetVal = FALSE;
goto Cleanup;
}
//
// Loop parsing all the numeric parameters.
//
for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
NetStatus = NlParseOne(
SectionHandle,
(DefaultParameters != NULL),
ParseTable[i].Keyword,
(DefaultParameters == NULL) ?
ParseTable[i].DefaultValue :
*((PULONG)(((LPBYTE)DefaultParameters)+ParseTable[i].ValueOffset)),
ParseTable[i].MinimumValue,
ParseTable[i].MaximumValue,
(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) );
if ( NetStatus != NERR_Success ) {
if ( DefaultParameters == NULL ) {
MsgStrings[0] = L"Parameters";
} else {
MsgStrings[0] = L"Group Policy";
}
MsgStrings[1] = ParseTable[i].Keyword;
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
/* Not Fatal */
}
}
//
// Loop parsing all the boolean parameters.
//
for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
NetStatus = NetpGetConfigBool (
SectionHandle,
BoolParseTable[i].Keyword,
(DefaultParameters == NULL) ?
BoolParseTable[i].DefaultValue :
*((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset)),
(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) );
//
// NeutralizeNt4Emulator is a special case: it must be TRUE on DC
//
if ( NetStatus == NO_ERROR &&
!NlGlobalMemberWorkstation &&
wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 &&
!(*((PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset))) ) {
//
// The code below will handle this error
//
NetStatus = ERROR_INVALID_PARAMETER;
}
if (NetStatus != NO_ERROR) {
// Use a reasonable default
if ( DefaultParameters == NULL ) {
*(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
BoolParseTable[i].DefaultValue;
} else {
*(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
*((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset));
}
if ( DefaultParameters == NULL ) {
MsgStrings[0] = L"Parameters";
} else {
MsgStrings[0] = L"Group Policy";
}
MsgStrings[1] = BoolParseTable[i].Keyword;
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
/* Not Fatal */
}
}
#ifdef _DC_NETLOGON
//
// Get the "SysVol" configured parameter
//
NetStatus = NlParseOnePath(
SectionHandle,
NETLOGON_KEYWORD_SYSVOL, // key wanted
(DefaultParameters == NULL) ?
DEFAULT_SYSVOL :
DefaultParameters->UnicodeSysvolPath,
&NlParameters->UnicodeSysvolPath );
if ( NetStatus != NO_ERROR ) {
NlParameters->UnicodeSysvolPath = NULL;
if ( DefaultParameters == NULL ) {
MsgStrings[0] = L"Parameters";
} else {
MsgStrings[0] = L"Group Policy";
}
MsgStrings[1] = NETLOGON_KEYWORD_SYSVOL;
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
/* Not Fatal */
}
//
// Get the "SCRIPTS" configured parameter
//
// Default Script path is relative to Sysvol
//
NetStatus = NlParseOnePath(
SectionHandle,
NETLOGON_KEYWORD_SCRIPTS, // key wanted
(DefaultParameters == NULL) ?
NULL : // No default (Default computed later)
DefaultParameters->UnicodeScriptPath,
&NlParameters->UnicodeScriptPath );
if ( NetStatus != NO_ERROR ) {
NlParameters->UnicodeScriptPath = NULL;
if ( DefaultParameters == NULL ) {
MsgStrings[0] = L"Parameters";
} else {
MsgStrings[0] = L"Group Policy";
}
MsgStrings[1] = NETLOGON_KEYWORD_SCRIPTS;
MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
EVENTLOG_WARNING_TYPE,
(LPBYTE)&NetStatus,
sizeof(NetStatus),
MsgStrings,
3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
/* Not Fatal */
}
//
// Get the "SiteName" configured parameter
//
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_SITENAME,
FALSE, // single valued parameter
(DefaultParameters == NULL) ?
NULL :
&DefaultParameters->SiteName,
&NlParameters->SiteName );
NlParameters->SiteNameConfigured = (NetStatus == NO_ERROR);
//
// If we are reading the Netlogon Parameters section ...
//
if ( DefaultParameters == NULL ) {
//
// If the site name is not configured, default it to the
// dynamic site name determined by Netlogon
//
if ( NetStatus == NERR_CfgParamNotFound ) {
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_DYNAMICSITENAME,
FALSE, // single valued parameter
NULL,
&NlParameters->SiteName );
}
//
// If we are reading the GP section ...
//
} else {
//
// If the site name is not configured in the GP section,
// may be it was configured in the Netlogon parameters section
//
if ( !NlParameters->SiteNameConfigured ) {
NlParameters->SiteNameConfigured = DefaultParameters->SiteNameConfigured;
}
}
//
// Get the "SiteCoverage" configured parameter
//
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_SITECOVERAGE,
TRUE, // multivalued parameter
(DefaultParameters == NULL) ?
NULL :
&DefaultParameters->SiteCoverage,
&NlParameters->SiteCoverage );
//
// Get the "GcSiteCoverage" configured parameter
//
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_GCSITECOVERAGE,
TRUE, // multivalued parameter
(DefaultParameters == NULL) ?
NULL :
&DefaultParameters->GcSiteCoverage,
&NlParameters->GcSiteCoverage );
//
// Get the "NdncSiteCoverage" configured parameter
//
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_NDNCSITECOVERAGE,
TRUE, // multivalued parameter
(DefaultParameters == NULL) ?
NULL :
&DefaultParameters->NdncSiteCoverage,
&NlParameters->NdncSiteCoverage );
//
// Get the "DnsAvoidRegisterRecords" configured parameter
//
NetStatus = NlParseTStr( SectionHandle,
NETLOGON_KEYWORD_DNSAVOIDNAME,
TRUE, // multivalued parameter
(DefaultParameters == NULL) ?
NULL :
&DefaultParameters->DnsAvoidRegisterRecords,
&NlParameters->DnsAvoidRegisterRecords );
#endif // _DC_NETLOGON
//
// Convert parameters to a more convenient form.
//
NlParseRecompute( NlParameters );
//
// If the KerbIsDoneWithJoinDomainEntry key value is 1, delete the
// Netlogon\JoinDomain entry. Also delete this entry if this machine is
// a DC in which case neither we nor Kerberos needs this entry. (As a
// matter of fact, Kerberos won't even create KerbIsDoneWithJoinDomainEntry
// on a DC.)
// Always delete KerbIsDoneWithJoinDomainEntry
// Ignore errors
//
// Do this only on the change notify since netlogon needs this info
// to set the client session first time after a reboot.
//
if ( IsChangeNotify &&
DefaultParameters == NULL ) { // KerbIsDoneWithJoinDomainEntry is in netlogon params
if ( NlParameters->KerbIsDoneWithJoinDomainEntry == 1 ||
!NlGlobalMemberWorkstation )
{
ULONG WinError = ERROR_SUCCESS;
HKEY hJoinKey = NULL;
WinError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
NETSETUPP_NETLOGON_JD_PATH,
0,
KEY_ALL_ACCESS,
&hJoinKey);
if ( WinError == ERROR_SUCCESS)
{
WinError = RegDeleteKey( hJoinKey,
NETSETUPP_NETLOGON_JD );
if ( WinError == ERROR_SUCCESS ) {
NlPrint(( NL_INIT, "NlParse: Deleted JoinDomain reg key\n" ));
}
if (hJoinKey)
{
WinError = RegCloseKey(hJoinKey);
}
}
}
TempNetStatus = NetpOpenConfigData(
&WriteSectionHandle,
NULL, // no server name.
SERVICE_NETLOGON,
FALSE); // writable, we are deleting it.
if ( TempNetStatus == NO_ERROR ) {
TempNetStatus = NetpDeleteConfigKeyword ( WriteSectionHandle,
NETLOGON_KEYWORD_KERBISDDONEWITHJOIN );
}
}
NetStatus = NERR_Success;
Cleanup:
//
// Free any locally used resources
//
if ( ValueT != NULL) {
(VOID) NetApiBufferFree( ValueT );
}
if ( SectionHandle != NULL ) {
(VOID) NetpCloseConfigData( SectionHandle );
}
if ( WriteSectionHandle != NULL ) {
(VOID) NetpCloseConfigData( WriteSectionHandle );
}
return RetVal;
}
BOOL
NlparseAllSections(
IN PNETLOGON_PARAMETERS NlParameters,
IN BOOLEAN IsChangeNotify
)
/*++
Routine Description:
Get parameters from both the Group Policy and the
Netlogon Parameters registry sections.
Arguments:
NlParameters - Structure describing all parameters
IsChangeNotify - TRUE if this call is the result of a change notification
Return Value:
TRUE -- iff the parse was successful.
--*/
{
NETLOGON_PARAMETERS NlLocalParameters;
NETLOGON_PARAMETERS GpParameters;
RtlZeroMemory( &NlLocalParameters, sizeof(NlLocalParameters) );
RtlZeroMemory( &GpParameters, sizeof(GpParameters) );
//
// Do the one time initialization here
//
if ( !IsChangeNotify ) {
NT_PRODUCT_TYPE NtProductType;
ULONG i;
//
// Flag if this is a workstation (or member server)
//
if ( !RtlGetNtProductType( &NtProductType ) ) {
NtProductType = NtProductWinNt;
}
if ( NtProductType == NtProductLanManNt ) {
NlGlobalMemberWorkstation = FALSE;
} else {
NlGlobalMemberWorkstation = TRUE;
}
//
// Set the right default for NeutralizeNt4Emulator that depends
// on whether we are a DC or not
//
for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
if ( wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 ) {
if ( NlGlobalMemberWorkstation ) {
BoolParseTable[i].DefaultValue = FALSE; // FALSE for a workstation
} else {
BoolParseTable[i].DefaultValue = TRUE; // TRUE for a DC
}
break;
}
}
}
//
// First parse the new parameters from the Netlogon Parameters section
//
if ( !Nlparse( &NlLocalParameters, NULL, IsChangeNotify ) ) {
return FALSE; // error here is critical
}
//
// Next parse from the GP section using the parameters from the
// Netlogon Parameters section as default
//
if ( !Nlparse( &GpParameters, &NlLocalParameters, IsChangeNotify ) ) {
//
// If the GP is not defined, use the parameters from
// the Netlogon Parameters section
//
*NlParameters = NlLocalParameters;
NlPrint((NL_INIT, "Group Policy is not defined for Netlogon\n"));
} else {
*NlParameters = GpParameters;
NlPrint((NL_INIT, "Group Policy is defined for Netlogon\n"));
//
// Free whatever is left in the local Netlogon parameters
//
NlParseFree( &NlLocalParameters );
}
#if NETLOGONDBG
//
// Dump all the values on first invocation
//
if ( !IsChangeNotify ) {
ULONG i;
//
// Be Verbose
//
NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
NlParameters->UnicodeSysvolPath));
NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
NlParameters->UnicodeScriptPath));
NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
NlParameters->SiteNameConfigured,
NlParameters->SiteName ));
{
LPTSTR_ARRAY TStrArray;
if ( NlParameters->SiteCoverage != NULL ) {
NlPrint((NL_INIT," SiteCoverage = " ));
TStrArray = NlParameters->SiteCoverage;
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
NlPrint((NL_INIT,"\n" ));
}
}
{
LPTSTR_ARRAY TStrArray;
if ( NlParameters->GcSiteCoverage != NULL ) {
NlPrint((NL_INIT," GcSiteCoverage = " ));
TStrArray = NlParameters->GcSiteCoverage;
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
NlPrint((NL_INIT,"\n" ));
}
}
{
LPTSTR_ARRAY TStrArray;
if ( NlParameters->NdncSiteCoverage != NULL ) {
NlPrint((NL_INIT," NdncSiteCoverage = " ));
TStrArray = NlParameters->NdncSiteCoverage;
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
NlPrint((NL_INIT,"\n" ));
}
}
{
LPTSTR_ARRAY TStrArray;
if ( NlParameters->DnsAvoidRegisterRecords != NULL ) {
NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
TStrArray = NlParameters->DnsAvoidRegisterRecords;
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
NlPrint((NL_INIT,"\n" ));
}
}
for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
NlPrint((NL_INIT,
" %ws = %lu (0x%lx)\n",
ParseTable[i].Keyword,
*(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset),
*(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) ));
}
for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
NlPrint(( NL_INIT,
" %ws = %s\n",
BoolParseTable[i].Keyword,
(*(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset)) ?
"TRUE":"FALSE" ));
}
}
#endif // NETLOGONDBG
return TRUE;
}
VOID
NlParseFree(
IN PNETLOGON_PARAMETERS NlParameters
)
/*++
Routine Description:
Free any allocated parameters.
Arguments:
NlParameters - Structure describing all parameters
Return Value:
None.
--*/
{
if ( NlParameters->SiteName != NULL) {
(VOID) NetApiBufferFree( NlParameters->SiteName );
NlParameters->SiteName = NULL;
}
if ( NlParameters->SiteCoverage != NULL) {
(VOID) NetApiBufferFree( NlParameters->SiteCoverage );
NlParameters->SiteCoverage = NULL;
}
if ( NlParameters->GcSiteCoverage != NULL) {
(VOID) NetApiBufferFree( NlParameters->GcSiteCoverage );
NlParameters->GcSiteCoverage = NULL;
}
if ( NlParameters->NdncSiteCoverage != NULL) {
(VOID) NetApiBufferFree( NlParameters->NdncSiteCoverage );
NlParameters->NdncSiteCoverage = NULL;
}
if ( NlParameters->DnsAvoidRegisterRecords != NULL) {
(VOID) NetApiBufferFree( NlParameters->DnsAvoidRegisterRecords );
NlParameters->DnsAvoidRegisterRecords = NULL;
}
if ( NlParameters->UnicodeScriptPath != NULL) {
(VOID) NetApiBufferFree( NlParameters->UnicodeScriptPath );
NlParameters->UnicodeScriptPath = NULL;
}
if ( NlParameters->UnicodeSysvolPath != NULL) {
(VOID) NetApiBufferFree( NlParameters->UnicodeSysvolPath );
NlParameters->UnicodeSysvolPath = NULL;
}
}
VOID
NlReparse(
VOID
)
/*++
Routine Description:
This routine handle a registry change notification.
Arguments:
None.
Return Value:
None
--*/
{
NETLOGON_PARAMETERS LocalParameters;
ULONG i;
LPWSTR TempString;
BOOLEAN UpdateDns = FALSE;
BOOLEAN UpdateShares = FALSE;
BOOLEAN UpdateSiteName = FALSE;
ULONG OldDnsTtl;
BOOL OldSysVolReady;
BOOL OldDisablePasswordChange;
ULONG OldScavengeInterval;
ULONG OldMaximumPasswordAge;
//
// Grab any old values that might be interesting.
//
OldDnsTtl = NlGlobalParameters.DnsTtl;
OldSysVolReady = NlGlobalParameters.SysVolReady;
OldDisablePasswordChange = NlGlobalParameters.DisablePasswordChange;
OldScavengeInterval = NlGlobalParameters.ScavengeInterval;
OldMaximumPasswordAge = NlGlobalParameters.MaximumPasswordAge;
//
// Parse both sections in registry relevant to us
//
if (! NlparseAllSections( &LocalParameters, TRUE ) ) {
return;
}
//
// Be Verbose
//
NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
if ( (LocalParameters.UnicodeSysvolPath == NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) ||
(LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath == NULL ) ||
(LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) && _wcsicmp( LocalParameters.UnicodeSysvolPath, NlGlobalParameters.UnicodeSysvolPath) != 0 ) {
NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
LocalParameters.UnicodeSysvolPath));
// We can get away with this since only Netlogon's main thread touches
// this variable.
TempString = LocalParameters.UnicodeSysvolPath;
LocalParameters.UnicodeSysvolPath = NlGlobalParameters.UnicodeSysvolPath;
NlGlobalParameters.UnicodeSysvolPath = TempString;
UpdateShares = TRUE;
}
if ( (LocalParameters.UnicodeScriptPath == NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) ||
(LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath == NULL ) ||
(LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) && _wcsicmp( LocalParameters.UnicodeScriptPath, NlGlobalParameters.UnicodeScriptPath) != 0 ) {
NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
LocalParameters.UnicodeScriptPath));
// We can get away with this since only Netlogon's main thread touches
// this variable.
TempString = LocalParameters.UnicodeScriptPath;
LocalParameters.UnicodeScriptPath = NlGlobalParameters.UnicodeScriptPath;
NlGlobalParameters.UnicodeScriptPath = TempString;
UpdateShares = TRUE;
}
//
// Check whether the exclusive share access to Sysvol share needs update
//
if ( LocalParameters.AllowExclusiveSysvolShareAccess ) {
if ( !NlGlobalParameters.AllowExclusiveSysvolShareAccess ) {
UpdateShares = TRUE;
}
} else {
if ( NlGlobalParameters.AllowExclusiveSysvolShareAccess ) {
UpdateShares = TRUE;
}
}
//
// Check whether the exclusive share access to Scripts share needs update
//
if ( LocalParameters.AllowExclusiveScriptsShareAccess ) {
if ( !NlGlobalParameters.AllowExclusiveScriptsShareAccess ) {
UpdateShares = TRUE;
}
} else {
if ( NlGlobalParameters.AllowExclusiveScriptsShareAccess ) {
UpdateShares = TRUE;
}
}
if ( (LocalParameters.SiteNameConfigured != NlGlobalParameters.SiteNameConfigured ) ||
(LocalParameters.SiteName == NULL && NlGlobalParameters.SiteName != NULL ) ||
(LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName == NULL ) ||
(LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName != NULL ) && _wcsicmp( LocalParameters.SiteName, NlGlobalParameters.SiteName) != 0 ) {
NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
LocalParameters.SiteNameConfigured,
LocalParameters.SiteName ));
// We can get away with this since only Netlogon's main thread touches
// this variable.
TempString = LocalParameters.SiteName;
LocalParameters.SiteName = NlGlobalParameters.SiteName;
NlGlobalParameters.SiteName = TempString;
NlGlobalParameters.SiteNameConfigured = LocalParameters.SiteNameConfigured;
UpdateSiteName = TRUE;
}
//
// Handle SiteCoverage changing
//
if ( NlSitesSetSiteCoverageParam( DOM_REAL_DOMAIN, LocalParameters.SiteCoverage ) ) {
LPTSTR_ARRAY TStrArray;
NlPrint((NL_INIT," SiteCoverage = " ));
TStrArray = LocalParameters.SiteCoverage;
if ( TStrArray == NULL ) {
NlPrint((NL_INIT,"<NULL>" ));
} else {
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
}
NlPrint((NL_INIT,"\n" ));
// NlSitesSetSiteCoverageParam used this allocated buffer
LocalParameters.SiteCoverage = NULL;
UpdateDns = TRUE;
}
//
// Handle GcSiteCoverage changing
//
if ( NlSitesSetSiteCoverageParam( DOM_FOREST, LocalParameters.GcSiteCoverage ) ) {
LPTSTR_ARRAY TStrArray;
NlPrint((NL_INIT," GcSiteCoverage = " ));
TStrArray = LocalParameters.GcSiteCoverage;
if ( TStrArray == NULL ) {
NlPrint((NL_INIT,"<NULL>" ));
} else {
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
}
NlPrint((NL_INIT,"\n" ));
// NlSitesSetSiteCoverageParam used this allocated buffer
LocalParameters.GcSiteCoverage = NULL;
UpdateDns = TRUE;
}
//
// Handle NdncSiteCoverage changing
//
if ( NlSitesSetSiteCoverageParam( DOM_NON_DOMAIN_NC, LocalParameters.NdncSiteCoverage ) ) {
LPTSTR_ARRAY TStrArray;
NlPrint((NL_INIT," NdncSiteCoverage = " ));
TStrArray = LocalParameters.NdncSiteCoverage;
if ( TStrArray == NULL ) {
NlPrint((NL_INIT,"<NULL>" ));
} else {
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
}
NlPrint((NL_INIT,"\n" ));
// NlSitesSetSiteCoverageParam used this allocated buffer
LocalParameters.NdncSiteCoverage = NULL;
UpdateDns = TRUE;
}
//
// Handle DnsAvoidRegisterRecords changing
//
if ( NlDnsSetAvoidRegisterNameParam( LocalParameters.DnsAvoidRegisterRecords ) ) {
LPTSTR_ARRAY TStrArray;
NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
TStrArray = LocalParameters.DnsAvoidRegisterRecords;
if ( TStrArray == NULL ) {
NlPrint((NL_INIT,"<NULL>" ));
} else {
while (!NetpIsTStrArrayEmpty(TStrArray)) {
NlPrint((NL_INIT," '%ws'", TStrArray ));
TStrArray = NetpNextTStrArrayEntry(TStrArray);
}
}
NlPrint((NL_INIT,"\n" ));
// NlSitesSetSiteCoverageParam used this allocated buffer
LocalParameters.DnsAvoidRegisterRecords = NULL;
UpdateDns = TRUE;
}
//
// Install all the numeric parameters.
//
for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) !=
*(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) ) ) {
NlPrint((NL_INIT,
" %ws = %lu (0x%lx)\n",
ParseTable[i].Keyword,
*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset),
*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) ));
//
// Actually set the value
//
*(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) =
*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset);
//
// If this changed value affects DNS,
// note that fact.
//
if ( ParseTable[i].ChangesDnsRegistration ) {
UpdateDns = TRUE;
}
}
}
for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset) !=
*(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) ) ) {
NlPrint(( NL_INIT,
" %ws = %s\n",
BoolParseTable[i].Keyword,
(*(PBOOL)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset)) ?
"TRUE":"FALSE" ));
//
// Actually set the value
//
*(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) =
*(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset);
//
// If this changed value affects DNS,
// note that fact.
//
if ( BoolParseTable[i].ChangesDnsRegistration ) {
UpdateDns = TRUE;
}
//
// If this changed value affects LSA, inform it
//
if ( !NlGlobalMemberWorkstation &&
wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NT4EMULATOR) == 0 ) {
LsaINotifyNetlogonParametersChangeW(
LsaEmulateNT4,
REG_DWORD,
(PWSTR)&NlGlobalParameters.Nt4Emulator,
sizeof(NlGlobalParameters.Nt4Emulator) );
}
}
}
//
// Convert parameters to a more convenient form.
//
NlParseRecompute( &NlGlobalParameters );
//
// Notify other components of parameters that have changed.
//
//
// Enable detection of duplicate event log messages
//
NetpEventlogSetTimeout ( NlGlobalEventlogHandle,
NlGlobalParameters.DuplicateEventlogTimeout*1000 );
//
// Do member workstation specific updates
//
if ( NlGlobalMemberWorkstation ) {
//
// Update site name
//
if ( UpdateSiteName ) {
(VOID) NlSetSiteName( NlGlobalParameters.SiteName, NULL );
}
//
// Do DC specific updates
//
} else {
//
// Re-register DNS records
//
// If DnsTtl has changed,
// force all records to be registered.
//
if ( UpdateDns ) {
NlDnsForceScavenge( TRUE, // refresh domain records
NlGlobalParameters.DnsTtl != OldDnsTtl );
}
//
// Update the Netlogon and Sysvol shares
//
if ( UpdateShares || OldSysVolReady != NlGlobalParameters.SysVolReady ) {
NlCreateSysvolShares();
}
}
//
// If the settings that affect the scavenger have changed,
// trigger it now.
//
if ( OldDisablePasswordChange != NlGlobalParameters.DisablePasswordChange ||
OldScavengeInterval != NlGlobalParameters.ScavengeInterval ||
OldMaximumPasswordAge != NlGlobalParameters.MaximumPasswordAge ) {
//
// We don't need to set NlGlobalTimerEvent since we're already processing
// a registry notification event. That'll make NlMainLoop notice the change.
//
EnterCriticalSection( &NlGlobalScavengerCritSect );
NlGlobalScavengerTimer.Period = 0;
LeaveCriticalSection( &NlGlobalScavengerCritSect );
}
// Cleanup:
NlParseFree( &LocalParameters );
return;
}