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

  1. /*++
  2. Copyright (c) 1987-1996 Microsoft Corporation
  3. Module Name:
  4. parse.c
  5. Abstract:
  6. Routine to parse the command line.
  7. Author:
  8. Ported from Lan Man 2.0
  9. Environment:
  10. User mode only.
  11. Contains NT-specific code.
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 01-Aug-1991 (cliffv)
  15. Ported to NT. Converted to NT style.
  16. 09-May-1992 JohnRo
  17. Enable use of win32 registry.
  18. Use net config helpers for NetLogon.
  19. Fixed UNICODE bug handling debug file name.
  20. Use <prefix.h> equates.
  21. --*/
  22. //
  23. // Common include files.
  24. //
  25. #include "logonsrv.h" // Include files common to entire service
  26. #pragma hdrstop
  27. #include <configp.h> // USE_WIN32_CONFIG (if defined), etc.
  28. #include <prefix.h> // PREFIX_ equates.
  29. //
  30. // Include files specific to this .c file
  31. //
  32. #include <string.h> // strnicmp
  33. NET_API_STATUS
  34. NlParseOne(
  35. IN LPNET_CONFIG_HANDLE SectionHandle,
  36. IN BOOL GpSection,
  37. IN LPWSTR Keyword,
  38. IN ULONG DefaultValue,
  39. IN ULONG MinimumValue,
  40. IN ULONG MaximumValue,
  41. OUT PULONG Value
  42. )
  43. /*++
  44. Routine Description:
  45. Get a single numeric parameter from the netlogon section of the registry.
  46. Arguments:
  47. SectionHandle - Handle into the registry.
  48. GpSection - TRUE iff the section is the group policy section.
  49. Keyword - Name of the value to read.
  50. DefaultValue - Default value if parameter doesn't exist.
  51. MinimumValue - Minumin valid value.
  52. MaximumValue - Maximum valid value.
  53. Value - Returns the value parsed.
  54. Return Value:
  55. Status of the operation
  56. --*/
  57. {
  58. NET_API_STATUS NetStatus;
  59. LPWSTR ValueT = NULL;
  60. //
  61. // Always return a reasonable value.
  62. //
  63. *Value = DefaultValue;
  64. //
  65. // Determine if the value is specified in the registry at all.
  66. //
  67. NetStatus = NetpGetConfigValue (
  68. SectionHandle,
  69. Keyword,
  70. &ValueT );
  71. if( ValueT != NULL ) {
  72. NetApiBufferFree( ValueT );
  73. ValueT = NULL;
  74. }
  75. //
  76. // If the value wasn't specified,
  77. // use the default.
  78. //
  79. if ( NetStatus == NERR_CfgParamNotFound ) {
  80. *Value = DefaultValue;
  81. //
  82. // If the value was specifed,
  83. // get it from the registry.
  84. //
  85. } else {
  86. NetStatus = NetpGetConfigDword (
  87. SectionHandle,
  88. Keyword, // keyword wanted
  89. DefaultValue,
  90. Value );
  91. if (NetStatus == NO_ERROR) {
  92. if ( *Value > MaximumValue || *Value < MinimumValue ) {
  93. ULONG InvalidValue;
  94. LPWSTR MsgStrings[6];
  95. // Each byte of the status code will transform into one character 0-F
  96. WCHAR InvalidValueString[sizeof(WCHAR) * (sizeof(InvalidValue) + 1)];
  97. WCHAR MinimumValueString[sizeof(WCHAR) * (sizeof(MinimumValue) + 1)];
  98. WCHAR MaximumValueString[sizeof(WCHAR) * (sizeof(MaximumValue) + 1)];
  99. WCHAR AssignedValueString[sizeof(WCHAR) * (sizeof(*Value) + 1)];
  100. InvalidValue = *Value;
  101. if ( *Value > MaximumValue ) {
  102. *Value = MaximumValue;
  103. } else if ( *Value < MinimumValue ) {
  104. *Value = MinimumValue;
  105. }
  106. swprintf( InvalidValueString, L"%lx", InvalidValue );
  107. swprintf( MinimumValueString, L"%lx", MinimumValue );
  108. swprintf( MaximumValueString, L"%lx", MaximumValue );
  109. swprintf( AssignedValueString, L"%lx", *Value );
  110. if ( GpSection ) {
  111. MsgStrings[0] = L"Group Policy";
  112. } else {
  113. MsgStrings[0] = L"Parameters";
  114. }
  115. MsgStrings[1] = InvalidValueString;
  116. MsgStrings[2] = Keyword;
  117. MsgStrings[3] = MinimumValueString;
  118. MsgStrings[4] = MaximumValueString;
  119. MsgStrings[5] = AssignedValueString;
  120. NlpWriteEventlog( NELOG_NetlogonInvalidDwordParameterValue,
  121. EVENTLOG_WARNING_TYPE,
  122. NULL,
  123. 0,
  124. MsgStrings,
  125. 6 );
  126. }
  127. } else {
  128. return NetStatus;
  129. }
  130. }
  131. return NERR_Success;
  132. }
  133. NET_API_STATUS
  134. NlParseOnePath(
  135. IN LPNET_CONFIG_HANDLE SectionHandle,
  136. IN LPWSTR Keyword,
  137. IN LPWSTR DefaultValue1 OPTIONAL,
  138. OUT LPWSTR *Value
  139. )
  140. /*++
  141. Routine Description:
  142. Get a single path parameter from the netlogon section of the registry.
  143. Arguments:
  144. SectionHandle - Handle into the registry.
  145. Keyword - Name of the value to read.
  146. DefaultValue1 - Default value if parameter doesn't exist.
  147. If NULL, Value will be set to NULL to indicate there is no default.
  148. Value - Returns the value parsed.
  149. Must be freed using NetApiBufferFree.
  150. Return Value:
  151. Status of the operation
  152. --*/
  153. {
  154. NET_API_STATUS NetStatus;
  155. WCHAR OutPathname[MAX_PATH+1];
  156. WCHAR TempPathname[MAX_PATH*2+1];
  157. LPWSTR ValueT = NULL;
  158. ULONG type;
  159. //
  160. // Get the configured parameter
  161. //
  162. *Value = NULL;
  163. NetStatus = NetpGetConfigValue (
  164. SectionHandle,
  165. Keyword, // key wanted
  166. &ValueT ); // Must be freed by NetApiBufferFree().
  167. if (NetStatus != NO_ERROR) {
  168. //
  169. // Handle the default
  170. //
  171. if (NetStatus == NERR_CfgParamNotFound) {
  172. //
  173. // If there is no default,
  174. // we're done.
  175. //
  176. if ( DefaultValue1 == NULL ) {
  177. *Value = NULL;
  178. NetStatus = NO_ERROR;
  179. goto Cleanup;
  180. }
  181. //
  182. // Build the default value.
  183. //
  184. ValueT = NetpAllocWStrFromWStr( DefaultValue1 );
  185. if ( ValueT == NULL ) {
  186. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  187. goto Cleanup;
  188. }
  189. } else {
  190. goto Cleanup;
  191. }
  192. }
  193. NlAssert( ValueT != NULL );
  194. //
  195. // Convert the configured sysvol path to a full pathname.
  196. //
  197. type = 0; // Let the API figure out the type.
  198. NetStatus = I_NetPathCanonicalize( NULL,
  199. ValueT,
  200. OutPathname,
  201. sizeof(OutPathname),
  202. NULL,
  203. &type,
  204. 0L );
  205. if (NetStatus != NERR_Success ) {
  206. goto Cleanup;
  207. }
  208. if (type == ITYPE_PATH_ABSD) {
  209. NetpCopyTStrToWStr(TempPathname, OutPathname);
  210. } else if (type == ITYPE_PATH_RELND) {
  211. if ( !GetSystemWindowsDirectoryW(
  212. TempPathname,
  213. sizeof(TempPathname)/sizeof(WCHAR) ) ) {
  214. NetStatus = GetLastError();
  215. goto Cleanup;
  216. }
  217. wcscat( TempPathname, L"\\" );
  218. wcscat( TempPathname, OutPathname );
  219. } else {
  220. NetStatus = NERR_BadComponent;
  221. goto Cleanup;
  222. }
  223. //
  224. // Return the pathname in an allocated buffer
  225. //
  226. *Value = NetpAllocWStrFromWStr( TempPathname );
  227. if ( *Value == NULL ) {
  228. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  229. goto Cleanup;
  230. }
  231. Cleanup:
  232. if ( ValueT != NULL ) {
  233. (VOID) NetApiBufferFree( ValueT );
  234. }
  235. return NetStatus;
  236. }
  237. //
  238. // Table of numeric parameters to parse.
  239. //
  240. #define getoffset( _x ) offsetof( NETLOGON_PARAMETERS, _x )
  241. struct {
  242. LPWSTR Keyword;
  243. ULONG DefaultValue;
  244. ULONG MinimumValue;
  245. ULONG MaximumValue;
  246. ULONG ValueOffset;
  247. BOOLEAN ChangesDnsRegistration;
  248. } ParseTable[] =
  249. {
  250. { NETLOGON_KEYWORD_PULSE, DEFAULT_PULSE, MIN_PULSE, MAX_PULSE, getoffset( Pulse ), FALSE },
  251. { NETLOGON_KEYWORD_RANDOMIZE, DEFAULT_RANDOMIZE, MIN_RANDOMIZE, MAX_RANDOMIZE, getoffset( Randomize ), FALSE },
  252. { NETLOGON_KEYWORD_PULSEMAXIMUM, DEFAULT_PULSEMAXIMUM, MIN_PULSEMAXIMUM, MAX_PULSEMAXIMUM, getoffset( PulseMaximum ), FALSE },
  253. { NETLOGON_KEYWORD_PULSECONCURRENCY, DEFAULT_PULSECONCURRENCY, MIN_PULSECONCURRENCY, MAX_PULSECONCURRENCY, getoffset( PulseConcurrency ), FALSE },
  254. { NETLOGON_KEYWORD_PULSETIMEOUT1, DEFAULT_PULSETIMEOUT1, MIN_PULSETIMEOUT1, MAX_PULSETIMEOUT1, getoffset( PulseTimeout1 ), FALSE },
  255. { NETLOGON_KEYWORD_PULSETIMEOUT2, DEFAULT_PULSETIMEOUT2, MIN_PULSETIMEOUT2, MAX_PULSETIMEOUT2, getoffset( PulseTimeout2 ), FALSE },
  256. { NETLOGON_KEYWORD_MAXIMUMMAILSLOTMESSAGES, DEFAULT_MAXIMUMMAILSLOTMESSAGES, MIN_MAXIMUMMAILSLOTMESSAGES, MAX_MAXIMUMMAILSLOTMESSAGES, getoffset( MaximumMailslotMessages ), FALSE },
  257. { NETLOGON_KEYWORD_MAILSLOTMESSAGETIMEOUT, DEFAULT_MAILSLOTMESSAGETIMEOUT, MIN_MAILSLOTMESSAGETIMEOUT, MAX_MAILSLOTMESSAGETIMEOUT, getoffset( MailslotMessageTimeout ), FALSE },
  258. { NETLOGON_KEYWORD_MAILSLOTDUPLICATETIMEOUT,DEFAULT_MAILSLOTDUPLICATETIMEOUT,MIN_MAILSLOTDUPLICATETIMEOUT,MAX_MAILSLOTDUPLICATETIMEOUT,getoffset( MailslotDuplicateTimeout ),FALSE },
  259. { NETLOGON_KEYWORD_EXPECTEDDIALUPDELAY, DEFAULT_EXPECTEDDIALUPDELAY, MIN_EXPECTEDDIALUPDELAY, MAX_EXPECTEDDIALUPDELAY, getoffset( ExpectedDialupDelay ), FALSE },
  260. { NETLOGON_KEYWORD_SCAVENGEINTERVAL, DEFAULT_SCAVENGEINTERVAL, MIN_SCAVENGEINTERVAL, MAX_SCAVENGEINTERVAL, getoffset( ScavengeInterval ), FALSE },
  261. { NETLOGON_KEYWORD_MAXIMUMPASSWORDAGE, DEFAULT_MAXIMUMPASSWORDAGE, MIN_MAXIMUMPASSWORDAGE, MAX_MAXIMUMPASSWORDAGE, getoffset( MaximumPasswordAge ), FALSE },
  262. { NETLOGON_KEYWORD_LDAPSRVPRIORITY, DEFAULT_LDAPSRVPRIORITY, MIN_LDAPSRVPRIORITY, MAX_LDAPSRVPRIORITY, getoffset( LdapSrvPriority ), TRUE },
  263. { NETLOGON_KEYWORD_LDAPSRVWEIGHT, DEFAULT_LDAPSRVWEIGHT, MIN_LDAPSRVWEIGHT, MAX_LDAPSRVWEIGHT, getoffset( LdapSrvWeight ), TRUE },
  264. { NETLOGON_KEYWORD_LDAPSRVPORT, DEFAULT_LDAPSRVPORT, MIN_LDAPSRVPORT, MAX_LDAPSRVPORT, getoffset( LdapSrvPort ), TRUE },
  265. { NETLOGON_KEYWORD_LDAPGCSRVPORT, DEFAULT_LDAPGCSRVPORT, MIN_LDAPGCSRVPORT, MAX_LDAPGCSRVPORT, getoffset( LdapGcSrvPort ), TRUE },
  266. { L"KdcSrvPort", DEFAULT_KDCSRVPORT, MIN_KDCSRVPORT, MAX_KDCSRVPORT, getoffset( KdcSrvPort ), TRUE },
  267. { NETLOGON_KEYWORD_KERBISDDONEWITHJOIN, DEFAULT_KERBISDDONEWITHJOIN, MIN_KERBISDDONEWITHJOIN, MAX_KERBISDDONEWITHJOIN, getoffset( KerbIsDoneWithJoinDomainEntry),FALSE},
  268. { NETLOGON_KEYWORD_DNSTTL, DEFAULT_DNSTTL, MIN_DNSTTL, MAX_DNSTTL, getoffset( DnsTtl ), TRUE },
  269. { NETLOGON_KEYWORD_DNSREFRESHINTERVAL, DEFAULT_DNSREFRESHINTERVAL, MIN_DNSREFRESHINTERVAL, MAX_DNSREFRESHINTERVAL, getoffset( DnsRefreshInterval ), TRUE },
  270. { L"CloseSiteTimeout", DEFAULT_CLOSESITETIMEOUT, MIN_CLOSESITETIMEOUT, MAX_CLOSESITETIMEOUT, getoffset( CloseSiteTimeout ), FALSE },
  271. { L"SiteNameTimeout", DEFAULT_SITENAMETIMEOUT, MIN_SITENAMETIMEOUT, MAX_SITENAMETIMEOUT, getoffset( SiteNameTimeout ), FALSE },
  272. { L"DuplicateEventlogTimeout", DEFAULT_DUPLICATEEVENTLOGTIMEOUT,MIN_DUPLICATEEVENTLOGTIMEOUT,MAX_DUPLICATEEVENTLOGTIMEOUT,getoffset( DuplicateEventlogTimeout ),FALSE },
  273. { L"MaxConcurrentApi", DEFAULT_MAXCONCURRENTAPI, MIN_MAXCONCURRENTAPI, MAX_MAXCONCURRENTAPI, getoffset( MaxConcurrentApi ), FALSE },
  274. { L"NegativeCachePeriod", DEFAULT_NEGATIVECACHEPERIOD, MIN_NEGATIVECACHEPERIOD, MAX_NEGATIVECACHEPERIOD, getoffset( NegativeCachePeriod ), FALSE },
  275. { L"BackgroundRetryInitialPeriod", DEFAULT_BACKGROUNDRETRYINITIALPERIOD,MIN_BACKGROUNDRETRYINITIALPERIOD,MAX_BACKGROUNDRETRYINITIALPERIOD,getoffset( BackgroundRetryInitialPeriod ),FALSE },
  276. { L"BackgroundRetryMaximumPeriod", DEFAULT_BACKGROUNDRETRYMAXIMUMPERIOD,MIN_BACKGROUNDRETRYMAXIMUMPERIOD,MAX_BACKGROUNDRETRYMAXIMUMPERIOD,getoffset( BackgroundRetryMaximumPeriod ),FALSE },
  277. { L"BackgroundRetryQuitTime", DEFAULT_BACKGROUNDRETRYQUITTIME, MIN_BACKGROUNDRETRYQUITTIME, MAX_BACKGROUNDRETRYQUITTIME, getoffset( BackgroundRetryQuitTime ), FALSE },
  278. { L"BackgroundSuccessfulRefreshPeriod", DEFAULT_BACKGROUNDREFRESHPERIOD, MIN_BACKGROUNDREFRESHPERIOD, MAX_BACKGROUNDREFRESHPERIOD, getoffset( BackgroundSuccessfulRefreshPeriod ), FALSE },
  279. { L"NonBackgroundSuccessfulRefreshPeriod", DEFAULT_NONBACKGROUNDREFRESHPERIOD, MIN_NONBACKGROUNDREFRESHPERIOD, MAX_NONBACKGROUNDREFRESHPERIOD, getoffset( NonBackgroundSuccessfulRefreshPeriod ), FALSE },
  280. { L"DnsFailedDeregisterTimeout", DEFAULT_DNSFAILEDDEREGTIMEOUT, MIN_DNSFAILEDDEREGTIMEOUT, MAX_DNSFAILEDDEREGTIMEOUT, getoffset( DnsFailedDeregisterTimeout ), FALSE },
  281. { L"MaxLdapServersPinged", DEFAULT_MAXLDAPSERVERSPINGED, MIN_MAXLDAPSERVERSPINGED, MAX_MAXLDAPSERVERSPINGED, getoffset( MaxLdapServersPinged ), FALSE },
  282. { L"SiteCoverageRefreshInterval", DEFAULT_SITECOVERAGEREFRESHINTERVAL, MIN_SITECOVERAGEREFRESHINTERVAL, MAX_SITECOVERAGEREFRESHINTERVAL, getoffset( SiteCoverageRefreshInterval ), TRUE },
  283. { L"FtInfoUpdateInterval", DEFAULT_FTINFO_UPDATE_INTERVAL, MIN_FTINFO_UPDATE_INTERVAL, MAX_FTINFO_UPDATE_INTERVAL, getoffset( FtInfoUpdateInterval ), FALSE },
  284. #if NETLOGONDBG
  285. { NETLOGON_KEYWORD_DBFLAG, 0, 0, 0xFFFFFFFF, getoffset( DbFlag ), FALSE },
  286. { NETLOGON_KEYWORD_MAXIMUMLOGFILESIZE, DEFAULT_MAXIMUM_LOGFILE_SIZE, 0, 0xFFFFFFFF, getoffset( LogFileMaxSize ), FALSE },
  287. #endif // NETLOGONDBG
  288. };
  289. //
  290. // Table of boolean to parse.
  291. //
  292. struct {
  293. LPWSTR Keyword;
  294. BOOL DefaultValue;
  295. ULONG ValueOffset;
  296. BOOLEAN ChangesDnsRegistration;
  297. } BoolParseTable[] =
  298. {
  299. #ifdef _DC_NETLOGON
  300. { NETLOGON_KEYWORD_REFUSEPASSWORDCHANGE, DEFAULT_REFUSE_PASSWORD_CHANGE, getoffset( RefusePasswordChange ), FALSE },
  301. { NETLOGON_KEYWORD_ALLOWREPLINNONMIXED, DEFAULT_ALLOWREPLINNONMIXED, getoffset( AllowReplInNonMixed ), FALSE },
  302. { L"AvoidSamRepl", TRUE, getoffset( AvoidSamRepl ), FALSE },
  303. { L"AvoidLsaRepl", TRUE, getoffset( AvoidLsaRepl ), FALSE },
  304. { L"SignSecureChannel", TRUE, getoffset( SignSecureChannel ), FALSE },
  305. { L"SealSecureChannel", TRUE, getoffset( SealSecureChannel ), FALSE },
  306. { L"RequireSignOrSeal", FALSE, getoffset( RequireSignOrSeal ), FALSE },
  307. { L"RequireStrongKey", FALSE, getoffset( RequireStrongKey ), FALSE },
  308. { L"SysVolReady", TRUE, getoffset( SysVolReady ), FALSE },
  309. { L"UseDynamicDns", TRUE, getoffset( UseDynamicDns ), TRUE },
  310. { L"RegisterDnsARecords", TRUE, getoffset( RegisterDnsARecords ), TRUE },
  311. { L"AvoidPdcOnWan", FALSE, getoffset( AvoidPdcOnWan ), FALSE },
  312. { L"AutoSiteCoverage", TRUE, getoffset( AutoSiteCoverage ), TRUE },
  313. { L"AvoidDnsDeregOnShutdown", TRUE, getoffset(AvoidDnsDeregOnShutdown), TRUE },
  314. { L"DnsUpdateOnAllAdapters", FALSE, getoffset(DnsUpdateOnAllAdapters), TRUE },
  315. { NETLOGON_KEYWORD_NT4EMULATOR, FALSE, getoffset(Nt4Emulator), FALSE },
  316. #endif // _DC_NETLOGON
  317. { NETLOGON_KEYWORD_DISABLEPASSWORDCHANGE, DEFAULT_DISABLE_PASSWORD_CHANGE, getoffset( DisablePasswordChange ), FALSE },
  318. { NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR, FALSE,/* default is set later */ getoffset( NeutralizeNt4Emulator ), FALSE },
  319. { L"AllowSingleLabelDnsDomain", FALSE, getoffset(AllowSingleLabelDnsDomain), FALSE },
  320. { L"AllowExclusiveSysvolShareAccess", FALSE, getoffset(AllowExclusiveSysvolShareAccess), FALSE },
  321. { L"AllowExclusiveScriptsShareAccess", FALSE, getoffset(AllowExclusiveScriptsShareAccess), FALSE },
  322. { L"AvoidLocatorAccountLookup", FALSE, getoffset(AvoidLocatorAccountLookup), FALSE },
  323. };
  324. VOID
  325. NlParseRecompute(
  326. IN PNETLOGON_PARAMETERS NlParameters
  327. )
  328. /*++
  329. Routine Description:
  330. This routine recomputes globals that are simple functions of registry
  331. parameters.
  332. Arguments:
  333. NlParameters - Structure describing all parameters
  334. Return Value:
  335. None.
  336. --*/
  337. {
  338. ULONG RandomMinutes;
  339. //
  340. // Adjust values that are functions of each other.
  341. //
  342. if ( NlParameters->BackgroundRetryInitialPeriod < NlParameters->NegativeCachePeriod ) {
  343. NlParameters->BackgroundRetryInitialPeriod = NlParameters->NegativeCachePeriod;
  344. }
  345. if ( NlParameters->BackgroundRetryMaximumPeriod < NlParameters->BackgroundRetryInitialPeriod ) {
  346. NlParameters->BackgroundRetryMaximumPeriod = NlParameters->BackgroundRetryInitialPeriod;
  347. }
  348. if ( NlParameters->BackgroundRetryQuitTime != 0 &&
  349. NlParameters->BackgroundRetryQuitTime < NlParameters->BackgroundRetryMaximumPeriod ) {
  350. NlParameters->BackgroundRetryQuitTime = NlParameters->BackgroundRetryMaximumPeriod;
  351. }
  352. //
  353. // Convert from seconds to 100ns
  354. //
  355. NlParameters->PulseMaximum_100ns.QuadPart =
  356. Int32x32To64( NlParameters->PulseMaximum, 10000000 );
  357. NlParameters->PulseTimeout1_100ns.QuadPart =
  358. Int32x32To64( NlParameters->PulseTimeout1, 10000000 );
  359. NlParameters->PulseTimeout2_100ns.QuadPart =
  360. Int32x32To64( NlParameters->PulseTimeout2, 10000000 );
  361. NlParameters->MailslotMessageTimeout_100ns.QuadPart =
  362. Int32x32To64( NlParameters->MailslotMessageTimeout, 10000000 );
  363. NlParameters->MailslotDuplicateTimeout_100ns.QuadPart =
  364. Int32x32To64( NlParameters->MailslotDuplicateTimeout, 10000000 );
  365. NlParameters->BackgroundRetryQuitTime_100ns.QuadPart =
  366. Int32x32To64( NlParameters->BackgroundRetryQuitTime, 10000000 );
  367. //
  368. // Convert from days to 100ns
  369. //
  370. NlParameters->MaximumPasswordAge_100ns.QuadPart =
  371. ((LONGLONG) NlParameters->MaximumPasswordAge) *
  372. ((LONGLONG) 10000000) *
  373. ((LONGLONG) 24*60*60);
  374. //
  375. // Add a fraction of a day to prevent all machines created at the same time
  376. // from changing their password at the same time.
  377. RandomMinutes = (DWORD) rand() % (24*60);
  378. NlParameters->MaximumPasswordAge_100ns.QuadPart +=
  379. ((LONGLONG) RandomMinutes) *
  380. ((LONGLONG) 10000000) *
  381. ((LONGLONG) 60);
  382. #ifdef notdef
  383. NlPrint((NL_INIT," RandomMinutes = %lu (0x%lx)\n",
  384. RandomMinutes,
  385. RandomMinutes ));
  386. #endif // notdef
  387. NlParameters->ShortApiCallPeriod =
  388. SHORT_API_CALL_PERIOD + NlParameters->ExpectedDialupDelay * 1000;
  389. NlParameters->DnsRefreshIntervalPeriod =
  390. NlParameters->DnsRefreshInterval * 1000;
  391. if ( NlParameters->RequireSignOrSeal ) {
  392. NlParameters->SignSecureChannel = TRUE;
  393. }
  394. }
  395. NET_API_STATUS
  396. NlParseTStr(
  397. IN LPNET_CONFIG_HANDLE SectionHandle,
  398. IN LPWSTR Keyword,
  399. IN BOOL MultivaluedParameter,
  400. IN OUT LPWSTR *DefaultValue,
  401. OUT LPWSTR *Parameter
  402. )
  403. /*++
  404. Routine Description:
  405. This routine parses a null or doubly-null terminated string
  406. Arguments:
  407. SectionHandle - Handle to a section in registry
  408. Keyword - The name of the parameter to read
  409. MultivaluedParameter - If TRUE, the keyword is a multiple
  410. string where elements are separated by a single null
  411. character and the array is ended with two null characters.
  412. If FALSE, the keyword is a single string ended with one
  413. null terminator.
  414. DefaultValue - The default value of the parameter.
  415. If NULL, the section handle passed is that of the Netlogon Parameters section.
  416. If non-NULL, the section handle passed is that of the GP section.
  417. If specified and used by this routine, it is set to NULL to indicate
  418. that it has been consumed by this routine.
  419. Parameter - Returns the parameter read.
  420. Return Value:
  421. Status returned by NetpGetConfigTStrArray.
  422. --*/
  423. {
  424. NET_API_STATUS NetStatus;
  425. //
  426. // Get the configured parameter
  427. //
  428. // GP doesn't support multivalued strings. Instead a single
  429. // string is used where individual strings are separated
  430. // by spaces.
  431. //
  432. if ( MultivaluedParameter && DefaultValue == NULL ) {
  433. NetStatus = NetpGetConfigTStrArray (
  434. SectionHandle,
  435. Keyword,
  436. Parameter ); // Must be freed by NetApiBufferFree().
  437. } else {
  438. NetStatus = NetpGetConfigValue (
  439. SectionHandle,
  440. Keyword,
  441. Parameter ); // Must be freed by NetApiBufferFree().
  442. }
  443. //
  444. // If the parameter is empty string,
  445. // set it to NULL
  446. //
  447. if ( NetStatus == NERR_Success &&
  448. (*Parameter)[0] == UNICODE_NULL ) {
  449. NetApiBufferFree( *Parameter );
  450. *Parameter = NULL;
  451. NetStatus = NERR_CfgParamNotFound;
  452. }
  453. //
  454. // Convert the single valued string into the multivalued form
  455. //
  456. if ( NetStatus == NERR_Success && // we successfully read the registry
  457. MultivaluedParameter && // this is multivalued parameter
  458. DefaultValue != NULL ) { // we are parsing the GP section
  459. ULONG ParameterLength = 0;
  460. LPWSTR LocalParameter = NULL;
  461. //
  462. // The multivalued string will have two NULL terminator
  463. // characters at the end, so allocate enough storage
  464. //
  465. ParameterLength = wcslen(*Parameter);
  466. NetStatus = NetApiBufferAllocate( (ParameterLength + 2) * sizeof(WCHAR),
  467. &LocalParameter );
  468. if ( NetStatus == NO_ERROR ) {
  469. LPWSTR ParameterPtr = NULL;
  470. LPWSTR LocalParameterPtr = NULL;
  471. RtlZeroMemory( LocalParameter, (ParameterLength + 2) * sizeof(WCHAR) );
  472. ParameterPtr = *Parameter;
  473. LocalParameterPtr = LocalParameter;
  474. while ( *ParameterPtr != UNICODE_NULL ) {
  475. //
  476. // Disregard spaces in the input string. Note that
  477. // the user may have used several spaces to separate
  478. // two adjacent strings.
  479. //
  480. while ( *ParameterPtr == L' ' && *ParameterPtr != UNICODE_NULL ) {
  481. ParameterPtr ++;
  482. }
  483. //
  484. // Copy non-space characters
  485. //
  486. while ( *ParameterPtr != L' ' && *ParameterPtr != UNICODE_NULL ) {
  487. *LocalParameterPtr++ = *ParameterPtr++;
  488. }
  489. //
  490. // Insert one NULL character between single values
  491. //
  492. *LocalParameterPtr++ = UNICODE_NULL;
  493. }
  494. //
  495. // Free the value read from registry
  496. //
  497. NetApiBufferFree( *Parameter );
  498. *Parameter = NULL;
  499. //
  500. // If the resulting multivalued string is not empty,
  501. // use it. The resulting string may need smaller
  502. // storage that we have allocated, so allocate again
  503. // exactly what's needed to (potentially) save memory.
  504. //
  505. ParameterLength = NetpTStrArraySize( LocalParameter ); // this includes all storage
  506. if ( ParameterLength > 2*sizeof(WCHAR) ) {
  507. NetStatus = NetApiBufferAllocate( ParameterLength, Parameter );
  508. if ( NetStatus == NO_ERROR ) {
  509. RtlCopyMemory( *Parameter, LocalParameter, ParameterLength );
  510. }
  511. } else {
  512. NetStatus = ERROR_INVALID_PARAMETER;
  513. }
  514. if ( LocalParameter != NULL ) {
  515. NetApiBufferFree( LocalParameter );
  516. LocalParameter = NULL;
  517. }
  518. }
  519. }
  520. //
  521. // Handle the default
  522. //
  523. if ( NetStatus != NERR_Success ) {
  524. if ( DefaultValue == NULL ) {
  525. *Parameter = NULL;
  526. } else {
  527. *Parameter = *DefaultValue;
  528. //
  529. // Indicate that we have consumed the
  530. // value from the default parameters
  531. //
  532. *DefaultValue = NULL;
  533. }
  534. }
  535. //
  536. // Write event log on error
  537. //
  538. if ( NetStatus != NERR_Success && NetStatus != NERR_CfgParamNotFound ) {
  539. LPWSTR MsgStrings[3];
  540. if ( DefaultValue == NULL ) {
  541. MsgStrings[0] = L"Parameters";
  542. } else {
  543. MsgStrings[0] = L"Group Policy";
  544. }
  545. MsgStrings[1] = Keyword;
  546. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  547. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  548. EVENTLOG_WARNING_TYPE,
  549. (LPBYTE)&NetStatus,
  550. sizeof(NetStatus),
  551. MsgStrings,
  552. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  553. /* Not Fatal */
  554. }
  555. return NetStatus;
  556. }
  557. BOOL
  558. Nlparse(
  559. IN PNETLOGON_PARAMETERS NlParameters,
  560. IN PNETLOGON_PARAMETERS DefaultParameters OPTIONAL,
  561. IN BOOLEAN IsChangeNotify
  562. )
  563. /*++
  564. Routine Description:
  565. Get parameters from the group policy or registry.
  566. All of the parameters are described in iniparm.h.
  567. Arguments:
  568. NlParameters - Structure describing all parameters
  569. DefaultParameters - Structure describing default values for all parameters
  570. If NULL, the values are read from the Netlogon Parameters section and
  571. the default values specified in the parse table are used. If non-NULL,
  572. the values are read from the Group Policy section and the specified
  573. defaults are used.
  574. IsChangeNotify - TRUE if this call is the result of a change notification
  575. Return Value:
  576. TRUE -- the registry was opened successfully and parameters
  577. were read.
  578. FALSE -- iff we couldn't open the appropriate registry section
  579. --*/
  580. {
  581. BOOLEAN RetVal = TRUE;
  582. NET_API_STATUS NetStatus;
  583. NET_API_STATUS TempNetStatus;
  584. LPWSTR ValueT = NULL;
  585. LPWSTR Keyword = NULL;
  586. LPWSTR MsgStrings[3];
  587. ULONG i;
  588. //
  589. // Variables for scanning the configuration data.
  590. //
  591. LPNET_CONFIG_HANDLE SectionHandle = NULL;
  592. LPNET_CONFIG_HANDLE WriteSectionHandle = NULL;
  593. RtlZeroMemory( NlParameters, sizeof(NlParameters) );
  594. //
  595. // Open the appropriate configuration section
  596. //
  597. NetStatus = NetpOpenConfigDataWithPathEx(
  598. &SectionHandle,
  599. NULL, // no server name.
  600. (DefaultParameters == NULL) ?
  601. L"SYSTEM\\CurrentControlSet\\Services\\Netlogon" :
  602. TEXT(NL_GP_KEY),
  603. NULL, // default Parameters area
  604. TRUE ); // we only want readonly access
  605. if ( NetStatus != NO_ERROR ) {
  606. SectionHandle = NULL;
  607. //
  608. // The Netlogon Parameters section must always
  609. // exist. Write event log if we can't open it.
  610. //
  611. if ( DefaultParameters == NULL ) {
  612. MsgStrings[0] = L"Parameters";
  613. MsgStrings[1] = L"Parameters";
  614. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  615. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  616. EVENTLOG_WARNING_TYPE,
  617. (LPBYTE)&NetStatus,
  618. sizeof(NetStatus),
  619. MsgStrings,
  620. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  621. }
  622. RetVal = FALSE;
  623. goto Cleanup;
  624. }
  625. //
  626. // Loop parsing all the numeric parameters.
  627. //
  628. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  629. NetStatus = NlParseOne(
  630. SectionHandle,
  631. (DefaultParameters != NULL),
  632. ParseTable[i].Keyword,
  633. (DefaultParameters == NULL) ?
  634. ParseTable[i].DefaultValue :
  635. *((PULONG)(((LPBYTE)DefaultParameters)+ParseTable[i].ValueOffset)),
  636. ParseTable[i].MinimumValue,
  637. ParseTable[i].MaximumValue,
  638. (PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) );
  639. if ( NetStatus != NERR_Success ) {
  640. if ( DefaultParameters == NULL ) {
  641. MsgStrings[0] = L"Parameters";
  642. } else {
  643. MsgStrings[0] = L"Group Policy";
  644. }
  645. MsgStrings[1] = ParseTable[i].Keyword;
  646. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  647. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  648. EVENTLOG_WARNING_TYPE,
  649. (LPBYTE)&NetStatus,
  650. sizeof(NetStatus),
  651. MsgStrings,
  652. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  653. /* Not Fatal */
  654. }
  655. }
  656. //
  657. // Loop parsing all the boolean parameters.
  658. //
  659. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  660. NetStatus = NetpGetConfigBool (
  661. SectionHandle,
  662. BoolParseTable[i].Keyword,
  663. (DefaultParameters == NULL) ?
  664. BoolParseTable[i].DefaultValue :
  665. *((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset)),
  666. (PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) );
  667. //
  668. // NeutralizeNt4Emulator is a special case: it must be TRUE on DC
  669. //
  670. if ( NetStatus == NO_ERROR &&
  671. !NlGlobalMemberWorkstation &&
  672. wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 &&
  673. !(*((PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset))) ) {
  674. //
  675. // The code below will handle this error
  676. //
  677. NetStatus = ERROR_INVALID_PARAMETER;
  678. }
  679. if (NetStatus != NO_ERROR) {
  680. // Use a reasonable default
  681. if ( DefaultParameters == NULL ) {
  682. *(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
  683. BoolParseTable[i].DefaultValue;
  684. } else {
  685. *(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
  686. *((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset));
  687. }
  688. if ( DefaultParameters == NULL ) {
  689. MsgStrings[0] = L"Parameters";
  690. } else {
  691. MsgStrings[0] = L"Group Policy";
  692. }
  693. MsgStrings[1] = BoolParseTable[i].Keyword;
  694. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  695. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  696. EVENTLOG_WARNING_TYPE,
  697. (LPBYTE)&NetStatus,
  698. sizeof(NetStatus),
  699. MsgStrings,
  700. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  701. /* Not Fatal */
  702. }
  703. }
  704. #ifdef _DC_NETLOGON
  705. //
  706. // Get the "SysVol" configured parameter
  707. //
  708. NetStatus = NlParseOnePath(
  709. SectionHandle,
  710. NETLOGON_KEYWORD_SYSVOL, // key wanted
  711. (DefaultParameters == NULL) ?
  712. DEFAULT_SYSVOL :
  713. DefaultParameters->UnicodeSysvolPath,
  714. &NlParameters->UnicodeSysvolPath );
  715. if ( NetStatus != NO_ERROR ) {
  716. NlParameters->UnicodeSysvolPath = NULL;
  717. if ( DefaultParameters == NULL ) {
  718. MsgStrings[0] = L"Parameters";
  719. } else {
  720. MsgStrings[0] = L"Group Policy";
  721. }
  722. MsgStrings[1] = NETLOGON_KEYWORD_SYSVOL;
  723. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  724. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  725. EVENTLOG_WARNING_TYPE,
  726. (LPBYTE)&NetStatus,
  727. sizeof(NetStatus),
  728. MsgStrings,
  729. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  730. /* Not Fatal */
  731. }
  732. //
  733. // Get the "SCRIPTS" configured parameter
  734. //
  735. // Default Script path is relative to Sysvol
  736. //
  737. NetStatus = NlParseOnePath(
  738. SectionHandle,
  739. NETLOGON_KEYWORD_SCRIPTS, // key wanted
  740. (DefaultParameters == NULL) ?
  741. NULL : // No default (Default computed later)
  742. DefaultParameters->UnicodeScriptPath,
  743. &NlParameters->UnicodeScriptPath );
  744. if ( NetStatus != NO_ERROR ) {
  745. NlParameters->UnicodeScriptPath = NULL;
  746. if ( DefaultParameters == NULL ) {
  747. MsgStrings[0] = L"Parameters";
  748. } else {
  749. MsgStrings[0] = L"Group Policy";
  750. }
  751. MsgStrings[1] = NETLOGON_KEYWORD_SCRIPTS;
  752. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  753. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  754. EVENTLOG_WARNING_TYPE,
  755. (LPBYTE)&NetStatus,
  756. sizeof(NetStatus),
  757. MsgStrings,
  758. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  759. /* Not Fatal */
  760. }
  761. //
  762. // Get the "SiteName" configured parameter
  763. //
  764. NetStatus = NlParseTStr( SectionHandle,
  765. NETLOGON_KEYWORD_SITENAME,
  766. FALSE, // single valued parameter
  767. (DefaultParameters == NULL) ?
  768. NULL :
  769. &DefaultParameters->SiteName,
  770. &NlParameters->SiteName );
  771. NlParameters->SiteNameConfigured = (NetStatus == NO_ERROR);
  772. //
  773. // If we are reading the Netlogon Parameters section ...
  774. //
  775. if ( DefaultParameters == NULL ) {
  776. //
  777. // If the site name is not configured, default it to the
  778. // dynamic site name determined by Netlogon
  779. //
  780. if ( NetStatus == NERR_CfgParamNotFound ) {
  781. NetStatus = NlParseTStr( SectionHandle,
  782. NETLOGON_KEYWORD_DYNAMICSITENAME,
  783. FALSE, // single valued parameter
  784. NULL,
  785. &NlParameters->SiteName );
  786. }
  787. //
  788. // If we are reading the GP section ...
  789. //
  790. } else {
  791. //
  792. // If the site name is not configured in the GP section,
  793. // may be it was configured in the Netlogon parameters section
  794. //
  795. if ( !NlParameters->SiteNameConfigured ) {
  796. NlParameters->SiteNameConfigured = DefaultParameters->SiteNameConfigured;
  797. }
  798. }
  799. //
  800. // Get the "SiteCoverage" configured parameter
  801. //
  802. NetStatus = NlParseTStr( SectionHandle,
  803. NETLOGON_KEYWORD_SITECOVERAGE,
  804. TRUE, // multivalued parameter
  805. (DefaultParameters == NULL) ?
  806. NULL :
  807. &DefaultParameters->SiteCoverage,
  808. &NlParameters->SiteCoverage );
  809. //
  810. // Get the "GcSiteCoverage" configured parameter
  811. //
  812. NetStatus = NlParseTStr( SectionHandle,
  813. NETLOGON_KEYWORD_GCSITECOVERAGE,
  814. TRUE, // multivalued parameter
  815. (DefaultParameters == NULL) ?
  816. NULL :
  817. &DefaultParameters->GcSiteCoverage,
  818. &NlParameters->GcSiteCoverage );
  819. //
  820. // Get the "NdncSiteCoverage" configured parameter
  821. //
  822. NetStatus = NlParseTStr( SectionHandle,
  823. NETLOGON_KEYWORD_NDNCSITECOVERAGE,
  824. TRUE, // multivalued parameter
  825. (DefaultParameters == NULL) ?
  826. NULL :
  827. &DefaultParameters->NdncSiteCoverage,
  828. &NlParameters->NdncSiteCoverage );
  829. //
  830. // Get the "DnsAvoidRegisterRecords" configured parameter
  831. //
  832. NetStatus = NlParseTStr( SectionHandle,
  833. NETLOGON_KEYWORD_DNSAVOIDNAME,
  834. TRUE, // multivalued parameter
  835. (DefaultParameters == NULL) ?
  836. NULL :
  837. &DefaultParameters->DnsAvoidRegisterRecords,
  838. &NlParameters->DnsAvoidRegisterRecords );
  839. #endif // _DC_NETLOGON
  840. //
  841. // Convert parameters to a more convenient form.
  842. //
  843. NlParseRecompute( NlParameters );
  844. //
  845. // If the KerbIsDoneWithJoinDomainEntry key value is 1, delete the
  846. // Netlogon\JoinDomain entry. Also delete this entry if this machine is
  847. // a DC in which case neither we nor Kerberos needs this entry. (As a
  848. // matter of fact, Kerberos won't even create KerbIsDoneWithJoinDomainEntry
  849. // on a DC.)
  850. // Always delete KerbIsDoneWithJoinDomainEntry
  851. // Ignore errors
  852. //
  853. // Do this only on the change notify since netlogon needs this info
  854. // to set the client session first time after a reboot.
  855. //
  856. if ( IsChangeNotify &&
  857. DefaultParameters == NULL ) { // KerbIsDoneWithJoinDomainEntry is in netlogon params
  858. if ( NlParameters->KerbIsDoneWithJoinDomainEntry == 1 ||
  859. !NlGlobalMemberWorkstation )
  860. {
  861. ULONG WinError = ERROR_SUCCESS;
  862. HKEY hJoinKey = NULL;
  863. WinError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  864. NETSETUPP_NETLOGON_JD_PATH,
  865. 0,
  866. KEY_ALL_ACCESS,
  867. &hJoinKey);
  868. if ( WinError == ERROR_SUCCESS)
  869. {
  870. WinError = RegDeleteKey( hJoinKey,
  871. NETSETUPP_NETLOGON_JD );
  872. if ( WinError == ERROR_SUCCESS ) {
  873. NlPrint(( NL_INIT, "NlParse: Deleted JoinDomain reg key\n" ));
  874. }
  875. if (hJoinKey)
  876. {
  877. WinError = RegCloseKey(hJoinKey);
  878. }
  879. }
  880. }
  881. TempNetStatus = NetpOpenConfigData(
  882. &WriteSectionHandle,
  883. NULL, // no server name.
  884. SERVICE_NETLOGON,
  885. FALSE); // writable, we are deleting it.
  886. if ( TempNetStatus == NO_ERROR ) {
  887. TempNetStatus = NetpDeleteConfigKeyword ( WriteSectionHandle,
  888. NETLOGON_KEYWORD_KERBISDDONEWITHJOIN );
  889. }
  890. }
  891. NetStatus = NERR_Success;
  892. Cleanup:
  893. //
  894. // Free any locally used resources
  895. //
  896. if ( ValueT != NULL) {
  897. (VOID) NetApiBufferFree( ValueT );
  898. }
  899. if ( SectionHandle != NULL ) {
  900. (VOID) NetpCloseConfigData( SectionHandle );
  901. }
  902. if ( WriteSectionHandle != NULL ) {
  903. (VOID) NetpCloseConfigData( WriteSectionHandle );
  904. }
  905. return RetVal;
  906. }
  907. BOOL
  908. NlparseAllSections(
  909. IN PNETLOGON_PARAMETERS NlParameters,
  910. IN BOOLEAN IsChangeNotify
  911. )
  912. /*++
  913. Routine Description:
  914. Get parameters from both the Group Policy and the
  915. Netlogon Parameters registry sections.
  916. Arguments:
  917. NlParameters - Structure describing all parameters
  918. IsChangeNotify - TRUE if this call is the result of a change notification
  919. Return Value:
  920. TRUE -- iff the parse was successful.
  921. --*/
  922. {
  923. NETLOGON_PARAMETERS NlLocalParameters;
  924. NETLOGON_PARAMETERS GpParameters;
  925. RtlZeroMemory( &NlLocalParameters, sizeof(NlLocalParameters) );
  926. RtlZeroMemory( &GpParameters, sizeof(GpParameters) );
  927. //
  928. // Do the one time initialization here
  929. //
  930. if ( !IsChangeNotify ) {
  931. NT_PRODUCT_TYPE NtProductType;
  932. ULONG i;
  933. //
  934. // Flag if this is a workstation (or member server)
  935. //
  936. if ( !RtlGetNtProductType( &NtProductType ) ) {
  937. NtProductType = NtProductWinNt;
  938. }
  939. if ( NtProductType == NtProductLanManNt ) {
  940. NlGlobalMemberWorkstation = FALSE;
  941. } else {
  942. NlGlobalMemberWorkstation = TRUE;
  943. }
  944. //
  945. // Set the right default for NeutralizeNt4Emulator that depends
  946. // on whether we are a DC or not
  947. //
  948. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  949. if ( wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 ) {
  950. if ( NlGlobalMemberWorkstation ) {
  951. BoolParseTable[i].DefaultValue = FALSE; // FALSE for a workstation
  952. } else {
  953. BoolParseTable[i].DefaultValue = TRUE; // TRUE for a DC
  954. }
  955. break;
  956. }
  957. }
  958. }
  959. //
  960. // First parse the new parameters from the Netlogon Parameters section
  961. //
  962. if ( !Nlparse( &NlLocalParameters, NULL, IsChangeNotify ) ) {
  963. return FALSE; // error here is critical
  964. }
  965. //
  966. // Next parse from the GP section using the parameters from the
  967. // Netlogon Parameters section as default
  968. //
  969. if ( !Nlparse( &GpParameters, &NlLocalParameters, IsChangeNotify ) ) {
  970. //
  971. // If the GP is not defined, use the parameters from
  972. // the Netlogon Parameters section
  973. //
  974. *NlParameters = NlLocalParameters;
  975. NlPrint((NL_INIT, "Group Policy is not defined for Netlogon\n"));
  976. } else {
  977. *NlParameters = GpParameters;
  978. NlPrint((NL_INIT, "Group Policy is defined for Netlogon\n"));
  979. //
  980. // Free whatever is left in the local Netlogon parameters
  981. //
  982. NlParseFree( &NlLocalParameters );
  983. }
  984. #if NETLOGONDBG
  985. //
  986. // Dump all the values on first invocation
  987. //
  988. if ( !IsChangeNotify ) {
  989. ULONG i;
  990. //
  991. // Be Verbose
  992. //
  993. NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
  994. NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
  995. NlParameters->UnicodeSysvolPath));
  996. NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
  997. NlParameters->UnicodeScriptPath));
  998. NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
  999. NlParameters->SiteNameConfigured,
  1000. NlParameters->SiteName ));
  1001. {
  1002. LPTSTR_ARRAY TStrArray;
  1003. if ( NlParameters->SiteCoverage != NULL ) {
  1004. NlPrint((NL_INIT," SiteCoverage = " ));
  1005. TStrArray = NlParameters->SiteCoverage;
  1006. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1007. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1008. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1009. }
  1010. NlPrint((NL_INIT,"\n" ));
  1011. }
  1012. }
  1013. {
  1014. LPTSTR_ARRAY TStrArray;
  1015. if ( NlParameters->GcSiteCoverage != NULL ) {
  1016. NlPrint((NL_INIT," GcSiteCoverage = " ));
  1017. TStrArray = NlParameters->GcSiteCoverage;
  1018. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1019. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1020. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1021. }
  1022. NlPrint((NL_INIT,"\n" ));
  1023. }
  1024. }
  1025. {
  1026. LPTSTR_ARRAY TStrArray;
  1027. if ( NlParameters->NdncSiteCoverage != NULL ) {
  1028. NlPrint((NL_INIT," NdncSiteCoverage = " ));
  1029. TStrArray = NlParameters->NdncSiteCoverage;
  1030. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1031. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1032. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1033. }
  1034. NlPrint((NL_INIT,"\n" ));
  1035. }
  1036. }
  1037. {
  1038. LPTSTR_ARRAY TStrArray;
  1039. if ( NlParameters->DnsAvoidRegisterRecords != NULL ) {
  1040. NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
  1041. TStrArray = NlParameters->DnsAvoidRegisterRecords;
  1042. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1043. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1044. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1045. }
  1046. NlPrint((NL_INIT,"\n" ));
  1047. }
  1048. }
  1049. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  1050. NlPrint((NL_INIT,
  1051. " %ws = %lu (0x%lx)\n",
  1052. ParseTable[i].Keyword,
  1053. *(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset),
  1054. *(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) ));
  1055. }
  1056. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  1057. NlPrint(( NL_INIT,
  1058. " %ws = %s\n",
  1059. BoolParseTable[i].Keyword,
  1060. (*(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset)) ?
  1061. "TRUE":"FALSE" ));
  1062. }
  1063. }
  1064. #endif // NETLOGONDBG
  1065. return TRUE;
  1066. }
  1067. VOID
  1068. NlParseFree(
  1069. IN PNETLOGON_PARAMETERS NlParameters
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Free any allocated parameters.
  1074. Arguments:
  1075. NlParameters - Structure describing all parameters
  1076. Return Value:
  1077. None.
  1078. --*/
  1079. {
  1080. if ( NlParameters->SiteName != NULL) {
  1081. (VOID) NetApiBufferFree( NlParameters->SiteName );
  1082. NlParameters->SiteName = NULL;
  1083. }
  1084. if ( NlParameters->SiteCoverage != NULL) {
  1085. (VOID) NetApiBufferFree( NlParameters->SiteCoverage );
  1086. NlParameters->SiteCoverage = NULL;
  1087. }
  1088. if ( NlParameters->GcSiteCoverage != NULL) {
  1089. (VOID) NetApiBufferFree( NlParameters->GcSiteCoverage );
  1090. NlParameters->GcSiteCoverage = NULL;
  1091. }
  1092. if ( NlParameters->NdncSiteCoverage != NULL) {
  1093. (VOID) NetApiBufferFree( NlParameters->NdncSiteCoverage );
  1094. NlParameters->NdncSiteCoverage = NULL;
  1095. }
  1096. if ( NlParameters->DnsAvoidRegisterRecords != NULL) {
  1097. (VOID) NetApiBufferFree( NlParameters->DnsAvoidRegisterRecords );
  1098. NlParameters->DnsAvoidRegisterRecords = NULL;
  1099. }
  1100. if ( NlParameters->UnicodeScriptPath != NULL) {
  1101. (VOID) NetApiBufferFree( NlParameters->UnicodeScriptPath );
  1102. NlParameters->UnicodeScriptPath = NULL;
  1103. }
  1104. if ( NlParameters->UnicodeSysvolPath != NULL) {
  1105. (VOID) NetApiBufferFree( NlParameters->UnicodeSysvolPath );
  1106. NlParameters->UnicodeSysvolPath = NULL;
  1107. }
  1108. }
  1109. VOID
  1110. NlReparse(
  1111. VOID
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. This routine handle a registry change notification.
  1116. Arguments:
  1117. None.
  1118. Return Value:
  1119. None
  1120. --*/
  1121. {
  1122. NETLOGON_PARAMETERS LocalParameters;
  1123. ULONG i;
  1124. LPWSTR TempString;
  1125. BOOLEAN UpdateDns = FALSE;
  1126. BOOLEAN UpdateShares = FALSE;
  1127. BOOLEAN UpdateSiteName = FALSE;
  1128. ULONG OldDnsTtl;
  1129. BOOL OldSysVolReady;
  1130. BOOL OldDisablePasswordChange;
  1131. ULONG OldScavengeInterval;
  1132. ULONG OldMaximumPasswordAge;
  1133. //
  1134. // Grab any old values that might be interesting.
  1135. //
  1136. OldDnsTtl = NlGlobalParameters.DnsTtl;
  1137. OldSysVolReady = NlGlobalParameters.SysVolReady;
  1138. OldDisablePasswordChange = NlGlobalParameters.DisablePasswordChange;
  1139. OldScavengeInterval = NlGlobalParameters.ScavengeInterval;
  1140. OldMaximumPasswordAge = NlGlobalParameters.MaximumPasswordAge;
  1141. //
  1142. // Parse both sections in registry relevant to us
  1143. //
  1144. if (! NlparseAllSections( &LocalParameters, TRUE ) ) {
  1145. return;
  1146. }
  1147. //
  1148. // Be Verbose
  1149. //
  1150. NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
  1151. if ( (LocalParameters.UnicodeSysvolPath == NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) ||
  1152. (LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath == NULL ) ||
  1153. (LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) && _wcsicmp( LocalParameters.UnicodeSysvolPath, NlGlobalParameters.UnicodeSysvolPath) != 0 ) {
  1154. NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
  1155. LocalParameters.UnicodeSysvolPath));
  1156. // We can get away with this since only Netlogon's main thread touches
  1157. // this variable.
  1158. TempString = LocalParameters.UnicodeSysvolPath;
  1159. LocalParameters.UnicodeSysvolPath = NlGlobalParameters.UnicodeSysvolPath;
  1160. NlGlobalParameters.UnicodeSysvolPath = TempString;
  1161. UpdateShares = TRUE;
  1162. }
  1163. if ( (LocalParameters.UnicodeScriptPath == NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) ||
  1164. (LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath == NULL ) ||
  1165. (LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) && _wcsicmp( LocalParameters.UnicodeScriptPath, NlGlobalParameters.UnicodeScriptPath) != 0 ) {
  1166. NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
  1167. LocalParameters.UnicodeScriptPath));
  1168. // We can get away with this since only Netlogon's main thread touches
  1169. // this variable.
  1170. TempString = LocalParameters.UnicodeScriptPath;
  1171. LocalParameters.UnicodeScriptPath = NlGlobalParameters.UnicodeScriptPath;
  1172. NlGlobalParameters.UnicodeScriptPath = TempString;
  1173. UpdateShares = TRUE;
  1174. }
  1175. //
  1176. // Check whether the exclusive share access to Sysvol share needs update
  1177. //
  1178. if ( LocalParameters.AllowExclusiveSysvolShareAccess ) {
  1179. if ( !NlGlobalParameters.AllowExclusiveSysvolShareAccess ) {
  1180. UpdateShares = TRUE;
  1181. }
  1182. } else {
  1183. if ( NlGlobalParameters.AllowExclusiveSysvolShareAccess ) {
  1184. UpdateShares = TRUE;
  1185. }
  1186. }
  1187. //
  1188. // Check whether the exclusive share access to Scripts share needs update
  1189. //
  1190. if ( LocalParameters.AllowExclusiveScriptsShareAccess ) {
  1191. if ( !NlGlobalParameters.AllowExclusiveScriptsShareAccess ) {
  1192. UpdateShares = TRUE;
  1193. }
  1194. } else {
  1195. if ( NlGlobalParameters.AllowExclusiveScriptsShareAccess ) {
  1196. UpdateShares = TRUE;
  1197. }
  1198. }
  1199. if ( (LocalParameters.SiteNameConfigured != NlGlobalParameters.SiteNameConfigured ) ||
  1200. (LocalParameters.SiteName == NULL && NlGlobalParameters.SiteName != NULL ) ||
  1201. (LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName == NULL ) ||
  1202. (LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName != NULL ) && _wcsicmp( LocalParameters.SiteName, NlGlobalParameters.SiteName) != 0 ) {
  1203. NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
  1204. LocalParameters.SiteNameConfigured,
  1205. LocalParameters.SiteName ));
  1206. // We can get away with this since only Netlogon's main thread touches
  1207. // this variable.
  1208. TempString = LocalParameters.SiteName;
  1209. LocalParameters.SiteName = NlGlobalParameters.SiteName;
  1210. NlGlobalParameters.SiteName = TempString;
  1211. NlGlobalParameters.SiteNameConfigured = LocalParameters.SiteNameConfigured;
  1212. UpdateSiteName = TRUE;
  1213. }
  1214. //
  1215. // Handle SiteCoverage changing
  1216. //
  1217. if ( NlSitesSetSiteCoverageParam( DOM_REAL_DOMAIN, LocalParameters.SiteCoverage ) ) {
  1218. LPTSTR_ARRAY TStrArray;
  1219. NlPrint((NL_INIT," SiteCoverage = " ));
  1220. TStrArray = LocalParameters.SiteCoverage;
  1221. if ( TStrArray == NULL ) {
  1222. NlPrint((NL_INIT,"<NULL>" ));
  1223. } else {
  1224. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1225. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1226. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1227. }
  1228. }
  1229. NlPrint((NL_INIT,"\n" ));
  1230. // NlSitesSetSiteCoverageParam used this allocated buffer
  1231. LocalParameters.SiteCoverage = NULL;
  1232. UpdateDns = TRUE;
  1233. }
  1234. //
  1235. // Handle GcSiteCoverage changing
  1236. //
  1237. if ( NlSitesSetSiteCoverageParam( DOM_FOREST, LocalParameters.GcSiteCoverage ) ) {
  1238. LPTSTR_ARRAY TStrArray;
  1239. NlPrint((NL_INIT," GcSiteCoverage = " ));
  1240. TStrArray = LocalParameters.GcSiteCoverage;
  1241. if ( TStrArray == NULL ) {
  1242. NlPrint((NL_INIT,"<NULL>" ));
  1243. } else {
  1244. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1245. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1246. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1247. }
  1248. }
  1249. NlPrint((NL_INIT,"\n" ));
  1250. // NlSitesSetSiteCoverageParam used this allocated buffer
  1251. LocalParameters.GcSiteCoverage = NULL;
  1252. UpdateDns = TRUE;
  1253. }
  1254. //
  1255. // Handle NdncSiteCoverage changing
  1256. //
  1257. if ( NlSitesSetSiteCoverageParam( DOM_NON_DOMAIN_NC, LocalParameters.NdncSiteCoverage ) ) {
  1258. LPTSTR_ARRAY TStrArray;
  1259. NlPrint((NL_INIT," NdncSiteCoverage = " ));
  1260. TStrArray = LocalParameters.NdncSiteCoverage;
  1261. if ( TStrArray == NULL ) {
  1262. NlPrint((NL_INIT,"<NULL>" ));
  1263. } else {
  1264. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1265. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1266. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1267. }
  1268. }
  1269. NlPrint((NL_INIT,"\n" ));
  1270. // NlSitesSetSiteCoverageParam used this allocated buffer
  1271. LocalParameters.NdncSiteCoverage = NULL;
  1272. UpdateDns = TRUE;
  1273. }
  1274. //
  1275. // Handle DnsAvoidRegisterRecords changing
  1276. //
  1277. if ( NlDnsSetAvoidRegisterNameParam( LocalParameters.DnsAvoidRegisterRecords ) ) {
  1278. LPTSTR_ARRAY TStrArray;
  1279. NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
  1280. TStrArray = LocalParameters.DnsAvoidRegisterRecords;
  1281. if ( TStrArray == NULL ) {
  1282. NlPrint((NL_INIT,"<NULL>" ));
  1283. } else {
  1284. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1285. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1286. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1287. }
  1288. }
  1289. NlPrint((NL_INIT,"\n" ));
  1290. // NlSitesSetSiteCoverageParam used this allocated buffer
  1291. LocalParameters.DnsAvoidRegisterRecords = NULL;
  1292. UpdateDns = TRUE;
  1293. }
  1294. //
  1295. // Install all the numeric parameters.
  1296. //
  1297. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  1298. if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) !=
  1299. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) ) ) {
  1300. NlPrint((NL_INIT,
  1301. " %ws = %lu (0x%lx)\n",
  1302. ParseTable[i].Keyword,
  1303. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset),
  1304. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) ));
  1305. //
  1306. // Actually set the value
  1307. //
  1308. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) =
  1309. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset);
  1310. //
  1311. // If this changed value affects DNS,
  1312. // note that fact.
  1313. //
  1314. if ( ParseTable[i].ChangesDnsRegistration ) {
  1315. UpdateDns = TRUE;
  1316. }
  1317. }
  1318. }
  1319. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  1320. if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset) !=
  1321. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) ) ) {
  1322. NlPrint(( NL_INIT,
  1323. " %ws = %s\n",
  1324. BoolParseTable[i].Keyword,
  1325. (*(PBOOL)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset)) ?
  1326. "TRUE":"FALSE" ));
  1327. //
  1328. // Actually set the value
  1329. //
  1330. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) =
  1331. *(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset);
  1332. //
  1333. // If this changed value affects DNS,
  1334. // note that fact.
  1335. //
  1336. if ( BoolParseTable[i].ChangesDnsRegistration ) {
  1337. UpdateDns = TRUE;
  1338. }
  1339. //
  1340. // If this changed value affects LSA, inform it
  1341. //
  1342. if ( !NlGlobalMemberWorkstation &&
  1343. wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NT4EMULATOR) == 0 ) {
  1344. LsaINotifyNetlogonParametersChangeW(
  1345. LsaEmulateNT4,
  1346. REG_DWORD,
  1347. (PWSTR)&NlGlobalParameters.Nt4Emulator,
  1348. sizeof(NlGlobalParameters.Nt4Emulator) );
  1349. }
  1350. }
  1351. }
  1352. //
  1353. // Convert parameters to a more convenient form.
  1354. //
  1355. NlParseRecompute( &NlGlobalParameters );
  1356. //
  1357. // Notify other components of parameters that have changed.
  1358. //
  1359. //
  1360. // Enable detection of duplicate event log messages
  1361. //
  1362. NetpEventlogSetTimeout ( NlGlobalEventlogHandle,
  1363. NlGlobalParameters.DuplicateEventlogTimeout*1000 );
  1364. //
  1365. // Do member workstation specific updates
  1366. //
  1367. if ( NlGlobalMemberWorkstation ) {
  1368. //
  1369. // Update site name
  1370. //
  1371. if ( UpdateSiteName ) {
  1372. (VOID) NlSetSiteName( NlGlobalParameters.SiteName, NULL );
  1373. }
  1374. //
  1375. // Do DC specific updates
  1376. //
  1377. } else {
  1378. //
  1379. // Re-register DNS records
  1380. //
  1381. // If DnsTtl has changed,
  1382. // force all records to be registered.
  1383. //
  1384. if ( UpdateDns ) {
  1385. NlDnsForceScavenge( TRUE, // refresh domain records
  1386. NlGlobalParameters.DnsTtl != OldDnsTtl );
  1387. }
  1388. //
  1389. // Update the Netlogon and Sysvol shares
  1390. //
  1391. if ( UpdateShares || OldSysVolReady != NlGlobalParameters.SysVolReady ) {
  1392. NlCreateSysvolShares();
  1393. }
  1394. }
  1395. //
  1396. // If the settings that affect the scavenger have changed,
  1397. // trigger it now.
  1398. //
  1399. if ( OldDisablePasswordChange != NlGlobalParameters.DisablePasswordChange ||
  1400. OldScavengeInterval != NlGlobalParameters.ScavengeInterval ||
  1401. OldMaximumPasswordAge != NlGlobalParameters.MaximumPasswordAge ) {
  1402. //
  1403. // We don't need to set NlGlobalTimerEvent since we're already processing
  1404. // a registry notification event. That'll make NlMainLoop notice the change.
  1405. //
  1406. EnterCriticalSection( &NlGlobalScavengerCritSect );
  1407. NlGlobalScavengerTimer.Period = 0;
  1408. LeaveCriticalSection( &NlGlobalScavengerCritSect );
  1409. }
  1410. // Cleanup:
  1411. NlParseFree( &LocalParameters );
  1412. return;
  1413. }