Source code of Windows XP (NT5)
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.

1758 lines
58 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. #if NETLOGONDBG
  283. { NETLOGON_KEYWORD_DBFLAG, 0, 0, 0xFFFFFFFF, getoffset( DbFlag ), FALSE },
  284. { NETLOGON_KEYWORD_MAXIMUMLOGFILESIZE, DEFAULT_MAXIMUM_LOGFILE_SIZE, 0, 0xFFFFFFFF, getoffset( LogFileMaxSize ), FALSE },
  285. #endif // NETLOGONDBG
  286. };
  287. //
  288. // Table of boolean to parse.
  289. //
  290. struct {
  291. LPWSTR Keyword;
  292. BOOL DefaultValue;
  293. ULONG ValueOffset;
  294. BOOLEAN ChangesDnsRegistration;
  295. } BoolParseTable[] =
  296. {
  297. #ifdef _DC_NETLOGON
  298. { NETLOGON_KEYWORD_REFUSEPASSWORDCHANGE, DEFAULT_REFUSE_PASSWORD_CHANGE, getoffset( RefusePasswordChange ), FALSE },
  299. { NETLOGON_KEYWORD_ALLOWREPLINNONMIXED, DEFAULT_ALLOWREPLINNONMIXED, getoffset( AllowReplInNonMixed ), FALSE },
  300. { L"AvoidSamRepl", TRUE, getoffset( AvoidSamRepl ), FALSE },
  301. { L"AvoidLsaRepl", TRUE, getoffset( AvoidLsaRepl ), FALSE },
  302. { L"SignSecureChannel", TRUE, getoffset( SignSecureChannel ), FALSE },
  303. { L"SealSecureChannel", TRUE, getoffset( SealSecureChannel ), FALSE },
  304. { L"RequireSignOrSeal", FALSE, getoffset( RequireSignOrSeal ), FALSE },
  305. { L"RequireStrongKey", FALSE, getoffset( RequireStrongKey ), FALSE },
  306. { L"SysVolReady", TRUE, getoffset( SysVolReady ), FALSE },
  307. { L"UseDynamicDns", TRUE, getoffset( UseDynamicDns ), TRUE },
  308. { L"RegisterDnsARecords", TRUE, getoffset( RegisterDnsARecords ), TRUE },
  309. { L"AvoidPdcOnWan", FALSE, getoffset( AvoidPdcOnWan ), FALSE },
  310. { L"AutoSiteCoverage", TRUE, getoffset( AutoSiteCoverage ), TRUE },
  311. { L"AvoidDnsDeregOnShutdown", TRUE, getoffset(AvoidDnsDeregOnShutdown), TRUE },
  312. { L"DnsUpdateOnAllAdapters", FALSE, getoffset(DnsUpdateOnAllAdapters), TRUE },
  313. { NETLOGON_KEYWORD_NT4EMULATOR, FALSE, getoffset(Nt4Emulator), FALSE },
  314. #endif // _DC_NETLOGON
  315. { NETLOGON_KEYWORD_DISABLEPASSWORDCHANGE, DEFAULT_DISABLE_PASSWORD_CHANGE, getoffset( DisablePasswordChange ), FALSE },
  316. { NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR, FALSE,/* default is set later */ getoffset( NeutralizeNt4Emulator ), FALSE },
  317. { L"AllowSingleLabelDnsDomain", FALSE, getoffset(AllowSingleLabelDnsDomain), FALSE },
  318. };
  319. VOID
  320. NlParseRecompute(
  321. IN PNETLOGON_PARAMETERS NlParameters
  322. )
  323. /*++
  324. Routine Description:
  325. This routine recomputes globals that are simple functions of registry
  326. parameters.
  327. Arguments:
  328. NlParameters - Structure describing all parameters
  329. Return Value:
  330. None.
  331. --*/
  332. {
  333. ULONG RandomMinutes;
  334. //
  335. // Adjust values that are functions of each other.
  336. //
  337. if ( NlParameters->BackgroundRetryInitialPeriod < NlParameters->NegativeCachePeriod ) {
  338. NlParameters->BackgroundRetryInitialPeriod = NlParameters->NegativeCachePeriod;
  339. }
  340. if ( NlParameters->BackgroundRetryMaximumPeriod < NlParameters->BackgroundRetryInitialPeriod ) {
  341. NlParameters->BackgroundRetryMaximumPeriod = NlParameters->BackgroundRetryInitialPeriod;
  342. }
  343. if ( NlParameters->BackgroundRetryQuitTime != 0 &&
  344. NlParameters->BackgroundRetryQuitTime < NlParameters->BackgroundRetryMaximumPeriod ) {
  345. NlParameters->BackgroundRetryQuitTime = NlParameters->BackgroundRetryMaximumPeriod;
  346. }
  347. //
  348. // Convert from seconds to 100ns
  349. //
  350. NlParameters->PulseMaximum_100ns.QuadPart =
  351. Int32x32To64( NlParameters->PulseMaximum, 10000000 );
  352. NlParameters->PulseTimeout1_100ns.QuadPart =
  353. Int32x32To64( NlParameters->PulseTimeout1, 10000000 );
  354. NlParameters->PulseTimeout2_100ns.QuadPart =
  355. Int32x32To64( NlParameters->PulseTimeout2, 10000000 );
  356. NlParameters->MailslotMessageTimeout_100ns.QuadPart =
  357. Int32x32To64( NlParameters->MailslotMessageTimeout, 10000000 );
  358. NlParameters->MailslotDuplicateTimeout_100ns.QuadPart =
  359. Int32x32To64( NlParameters->MailslotDuplicateTimeout, 10000000 );
  360. NlParameters->BackgroundRetryQuitTime_100ns.QuadPart =
  361. Int32x32To64( NlParameters->BackgroundRetryQuitTime, 10000000 );
  362. //
  363. // Convert from days to 100ns
  364. //
  365. NlParameters->MaximumPasswordAge_100ns.QuadPart =
  366. ((LONGLONG) NlParameters->MaximumPasswordAge) *
  367. ((LONGLONG) 10000000) *
  368. ((LONGLONG) 24*60*60);
  369. //
  370. // Add a fraction of a day to prevent all machines created at the same time
  371. // from changing their password at the same time.
  372. RandomMinutes = (DWORD) rand() % (24*60);
  373. NlParameters->MaximumPasswordAge_100ns.QuadPart +=
  374. ((LONGLONG) RandomMinutes) *
  375. ((LONGLONG) 10000000) *
  376. ((LONGLONG) 60);
  377. #ifdef notdef
  378. NlPrint((NL_INIT," RandomMinutes = %lu (0x%lx)\n",
  379. RandomMinutes,
  380. RandomMinutes ));
  381. #endif // notdef
  382. NlParameters->ShortApiCallPeriod =
  383. SHORT_API_CALL_PERIOD + NlParameters->ExpectedDialupDelay * 1000;
  384. NlParameters->DnsRefreshIntervalPeriod =
  385. NlParameters->DnsRefreshInterval * 1000;
  386. if ( NlParameters->RequireSignOrSeal ) {
  387. NlParameters->SignSecureChannel = TRUE;
  388. }
  389. }
  390. NET_API_STATUS
  391. NlParseTStr(
  392. IN LPNET_CONFIG_HANDLE SectionHandle,
  393. IN LPWSTR Keyword,
  394. IN BOOL MultivaluedParameter,
  395. IN OUT LPWSTR *DefaultValue,
  396. OUT LPWSTR *Parameter
  397. )
  398. /*++
  399. Routine Description:
  400. This routine parses a null or doubly-null terminated string
  401. Arguments:
  402. SectionHandle - Handle to a section in registry
  403. Keyword - The name of the parameter to read
  404. MultivaluedParameter - If TRUE, the keyword is a multiple
  405. string where elements are separated by a single null
  406. character and the array is ended with two null characters.
  407. If FALSE, the keyword is a single string ended with one
  408. null terminator.
  409. DefaultValue - The default value of the parameter.
  410. If NULL, the section handle passed is that of the Netlogon Parameters section.
  411. If non-NULL, the section handle passed is that of the GP section.
  412. If specified and used by this routine, it is set to NULL to indicate
  413. that it has been consumed by this routine.
  414. Parameter - Returns the parameter read.
  415. Return Value:
  416. Status returned by NetpGetConfigTStrArray.
  417. --*/
  418. {
  419. NET_API_STATUS NetStatus;
  420. //
  421. // Get the configured parameter
  422. //
  423. // GP doesn't support multivalued strings. Instead a single
  424. // string is used where individual strings are separated
  425. // by spaces.
  426. //
  427. if ( MultivaluedParameter && DefaultValue == NULL ) {
  428. NetStatus = NetpGetConfigTStrArray (
  429. SectionHandle,
  430. Keyword,
  431. Parameter ); // Must be freed by NetApiBufferFree().
  432. } else {
  433. NetStatus = NetpGetConfigValue (
  434. SectionHandle,
  435. Keyword,
  436. Parameter ); // Must be freed by NetApiBufferFree().
  437. }
  438. //
  439. // If the parameter is empty string,
  440. // set it to NULL
  441. //
  442. if ( NetStatus == NERR_Success &&
  443. (*Parameter)[0] == UNICODE_NULL ) {
  444. NetApiBufferFree( *Parameter );
  445. *Parameter = NULL;
  446. NetStatus = NERR_CfgParamNotFound;
  447. }
  448. //
  449. // Convert the single valued string into the multivalued form
  450. //
  451. if ( NetStatus == NERR_Success && // we successfully read the registry
  452. MultivaluedParameter && // this is multivalued parameter
  453. DefaultValue != NULL ) { // we are parsing the GP section
  454. ULONG ParameterLength = 0;
  455. LPWSTR LocalParameter = NULL;
  456. //
  457. // The multivalued string will have two NULL terminator
  458. // characters at the end, so allocate enough storage
  459. //
  460. ParameterLength = wcslen(*Parameter);
  461. NetStatus = NetApiBufferAllocate( (ParameterLength + 2) * sizeof(WCHAR),
  462. &LocalParameter );
  463. if ( NetStatus == NO_ERROR ) {
  464. LPWSTR ParameterPtr = NULL;
  465. LPWSTR LocalParameterPtr = NULL;
  466. RtlZeroMemory( LocalParameter, (ParameterLength + 2) * sizeof(WCHAR) );
  467. ParameterPtr = *Parameter;
  468. LocalParameterPtr = LocalParameter;
  469. while ( *ParameterPtr != UNICODE_NULL ) {
  470. //
  471. // Disregard spaces in the input string. Note that
  472. // the user may have used several spaces to separate
  473. // two adjacent strings.
  474. //
  475. while ( *ParameterPtr == L' ' && *ParameterPtr != UNICODE_NULL ) {
  476. ParameterPtr ++;
  477. }
  478. //
  479. // Copy non-space characters
  480. //
  481. while ( *ParameterPtr != L' ' && *ParameterPtr != UNICODE_NULL ) {
  482. *LocalParameterPtr++ = *ParameterPtr++;
  483. }
  484. //
  485. // Insert one NULL character between single values
  486. //
  487. *LocalParameterPtr++ = UNICODE_NULL;
  488. }
  489. //
  490. // Free the value read from registry
  491. //
  492. NetApiBufferFree( *Parameter );
  493. *Parameter = NULL;
  494. //
  495. // If the resulting multivalued string is not empty,
  496. // use it. The resulting string may need smaller
  497. // storage that we have allocated, so allocate again
  498. // exactly what's needed to (potentially) save memory.
  499. //
  500. ParameterLength = NetpTStrArraySize( LocalParameter ); // this includes all storage
  501. if ( ParameterLength > 2*sizeof(WCHAR) ) {
  502. NetStatus = NetApiBufferAllocate( ParameterLength, Parameter );
  503. if ( NetStatus == NO_ERROR ) {
  504. RtlCopyMemory( *Parameter, LocalParameter, ParameterLength );
  505. }
  506. } else {
  507. NetStatus = ERROR_INVALID_PARAMETER;
  508. }
  509. if ( LocalParameter != NULL ) {
  510. NetApiBufferFree( LocalParameter );
  511. LocalParameter = NULL;
  512. }
  513. }
  514. }
  515. //
  516. // Handle the default
  517. //
  518. if ( NetStatus != NERR_Success ) {
  519. if ( DefaultValue == NULL ) {
  520. *Parameter = NULL;
  521. } else {
  522. *Parameter = *DefaultValue;
  523. //
  524. // Indicate that we have consumed the
  525. // value from the default parameters
  526. //
  527. *DefaultValue = NULL;
  528. }
  529. }
  530. //
  531. // Write event log on error
  532. //
  533. if ( NetStatus != NERR_Success && NetStatus != NERR_CfgParamNotFound ) {
  534. LPWSTR MsgStrings[3];
  535. if ( DefaultValue == NULL ) {
  536. MsgStrings[0] = L"Parameters";
  537. } else {
  538. MsgStrings[0] = L"Group Policy";
  539. }
  540. MsgStrings[1] = Keyword;
  541. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  542. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  543. EVENTLOG_WARNING_TYPE,
  544. (LPBYTE)&NetStatus,
  545. sizeof(NetStatus),
  546. MsgStrings,
  547. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  548. /* Not Fatal */
  549. }
  550. return NetStatus;
  551. }
  552. BOOL
  553. Nlparse(
  554. IN PNETLOGON_PARAMETERS NlParameters,
  555. IN PNETLOGON_PARAMETERS DefaultParameters OPTIONAL,
  556. IN BOOLEAN IsChangeNotify
  557. )
  558. /*++
  559. Routine Description:
  560. Get parameters from the group policy or registry.
  561. All of the parameters are described in iniparm.h.
  562. Arguments:
  563. NlParameters - Structure describing all parameters
  564. DefaultParameters - Structure describing default values for all parameters
  565. If NULL, the values are read from the Netlogon Parameters section and
  566. the default values specified in the parse table are used. If non-NULL,
  567. the values are read from the Group Policy section and the specified
  568. defaults are used.
  569. IsChangeNotify - TRUE if this call is the result of a change notification
  570. Return Value:
  571. TRUE -- the registry was opened successfully and parameters
  572. were read.
  573. FALSE -- iff we couldn't open the appropriate registry section
  574. --*/
  575. {
  576. BOOLEAN RetVal = TRUE;
  577. NET_API_STATUS NetStatus;
  578. NET_API_STATUS TempNetStatus;
  579. LPWSTR ValueT = NULL;
  580. LPWSTR Keyword = NULL;
  581. LPWSTR MsgStrings[3];
  582. ULONG i;
  583. //
  584. // Variables for scanning the configuration data.
  585. //
  586. LPNET_CONFIG_HANDLE SectionHandle = NULL;
  587. LPNET_CONFIG_HANDLE WriteSectionHandle = NULL;
  588. RtlZeroMemory( NlParameters, sizeof(NlParameters) );
  589. //
  590. // Open the appropriate configuration section
  591. //
  592. NetStatus = NetpOpenConfigDataWithPathEx(
  593. &SectionHandle,
  594. NULL, // no server name.
  595. (DefaultParameters == NULL) ?
  596. L"SYSTEM\\CurrentControlSet\\Services\\Netlogon" :
  597. TEXT(NL_GP_KEY),
  598. NULL, // default Parameters area
  599. TRUE ); // we only want readonly access
  600. if ( NetStatus != NO_ERROR ) {
  601. SectionHandle = NULL;
  602. //
  603. // The Netlogon Parameters section must always
  604. // exist. Write event log if we can't open it.
  605. //
  606. if ( DefaultParameters == NULL ) {
  607. MsgStrings[0] = L"Parameters";
  608. MsgStrings[1] = L"Parameters";
  609. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  610. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  611. EVENTLOG_WARNING_TYPE,
  612. (LPBYTE)&NetStatus,
  613. sizeof(NetStatus),
  614. MsgStrings,
  615. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  616. }
  617. RetVal = FALSE;
  618. goto Cleanup;
  619. }
  620. //
  621. // Loop parsing all the numeric parameters.
  622. //
  623. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  624. NetStatus = NlParseOne(
  625. SectionHandle,
  626. (DefaultParameters != NULL),
  627. ParseTable[i].Keyword,
  628. (DefaultParameters == NULL) ?
  629. ParseTable[i].DefaultValue :
  630. *((PULONG)(((LPBYTE)DefaultParameters)+ParseTable[i].ValueOffset)),
  631. ParseTable[i].MinimumValue,
  632. ParseTable[i].MaximumValue,
  633. (PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) );
  634. if ( NetStatus != NERR_Success ) {
  635. if ( DefaultParameters == NULL ) {
  636. MsgStrings[0] = L"Parameters";
  637. } else {
  638. MsgStrings[0] = L"Group Policy";
  639. }
  640. MsgStrings[1] = ParseTable[i].Keyword;
  641. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  642. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  643. EVENTLOG_WARNING_TYPE,
  644. (LPBYTE)&NetStatus,
  645. sizeof(NetStatus),
  646. MsgStrings,
  647. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  648. /* Not Fatal */
  649. }
  650. }
  651. //
  652. // Loop parsing all the boolean parameters.
  653. //
  654. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  655. NetStatus = NetpGetConfigBool (
  656. SectionHandle,
  657. BoolParseTable[i].Keyword,
  658. (DefaultParameters == NULL) ?
  659. BoolParseTable[i].DefaultValue :
  660. *((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset)),
  661. (PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) );
  662. //
  663. // NeutralizeNt4Emulator is a special case: it must be TRUE on DC
  664. //
  665. if ( NetStatus == NO_ERROR &&
  666. !NlGlobalMemberWorkstation &&
  667. wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 &&
  668. !(*((PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset))) ) {
  669. //
  670. // The code below will handle this error
  671. //
  672. NetStatus = ERROR_INVALID_PARAMETER;
  673. }
  674. if (NetStatus != NO_ERROR) {
  675. // Use a reasonable default
  676. if ( DefaultParameters == NULL ) {
  677. *(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
  678. BoolParseTable[i].DefaultValue;
  679. } else {
  680. *(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset) =
  681. *((PBOOL)(((LPBYTE)DefaultParameters)+BoolParseTable[i].ValueOffset));
  682. }
  683. if ( DefaultParameters == NULL ) {
  684. MsgStrings[0] = L"Parameters";
  685. } else {
  686. MsgStrings[0] = L"Group Policy";
  687. }
  688. MsgStrings[1] = BoolParseTable[i].Keyword;
  689. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  690. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  691. EVENTLOG_WARNING_TYPE,
  692. (LPBYTE)&NetStatus,
  693. sizeof(NetStatus),
  694. MsgStrings,
  695. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  696. /* Not Fatal */
  697. }
  698. }
  699. #ifdef _DC_NETLOGON
  700. //
  701. // Get the "SysVol" configured parameter
  702. //
  703. NetStatus = NlParseOnePath(
  704. SectionHandle,
  705. NETLOGON_KEYWORD_SYSVOL, // key wanted
  706. (DefaultParameters == NULL) ?
  707. DEFAULT_SYSVOL :
  708. DefaultParameters->UnicodeSysvolPath,
  709. &NlParameters->UnicodeSysvolPath );
  710. if ( NetStatus != NO_ERROR ) {
  711. NlParameters->UnicodeSysvolPath = NULL;
  712. if ( DefaultParameters == NULL ) {
  713. MsgStrings[0] = L"Parameters";
  714. } else {
  715. MsgStrings[0] = L"Group Policy";
  716. }
  717. MsgStrings[1] = NETLOGON_KEYWORD_SYSVOL;
  718. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  719. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  720. EVENTLOG_WARNING_TYPE,
  721. (LPBYTE)&NetStatus,
  722. sizeof(NetStatus),
  723. MsgStrings,
  724. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  725. /* Not Fatal */
  726. }
  727. //
  728. // Get the "SCRIPTS" configured parameter
  729. //
  730. // Default Script path is relative to Sysvol
  731. //
  732. NetStatus = NlParseOnePath(
  733. SectionHandle,
  734. NETLOGON_KEYWORD_SCRIPTS, // key wanted
  735. (DefaultParameters == NULL) ?
  736. NULL : // No default (Default computed later)
  737. DefaultParameters->UnicodeScriptPath,
  738. &NlParameters->UnicodeScriptPath );
  739. if ( NetStatus != NO_ERROR ) {
  740. NlParameters->UnicodeScriptPath = NULL;
  741. if ( DefaultParameters == NULL ) {
  742. MsgStrings[0] = L"Parameters";
  743. } else {
  744. MsgStrings[0] = L"Group Policy";
  745. }
  746. MsgStrings[1] = NETLOGON_KEYWORD_SCRIPTS;
  747. MsgStrings[2] = (LPWSTR) ULongToPtr( NetStatus );
  748. NlpWriteEventlog( NELOG_NetlogonInvalidGenericParameterValue,
  749. EVENTLOG_WARNING_TYPE,
  750. (LPBYTE)&NetStatus,
  751. sizeof(NetStatus),
  752. MsgStrings,
  753. 3 | NETP_LAST_MESSAGE_IS_NETSTATUS );
  754. /* Not Fatal */
  755. }
  756. //
  757. // Get the "SiteName" configured parameter
  758. //
  759. NetStatus = NlParseTStr( SectionHandle,
  760. NETLOGON_KEYWORD_SITENAME,
  761. FALSE, // single valued parameter
  762. (DefaultParameters == NULL) ?
  763. NULL :
  764. &DefaultParameters->SiteName,
  765. &NlParameters->SiteName );
  766. NlParameters->SiteNameConfigured = (NetStatus == NO_ERROR);
  767. //
  768. // If we are reading the Netlogon Parameters section ...
  769. //
  770. if ( DefaultParameters == NULL ) {
  771. //
  772. // If the site name is not configured, default it to the
  773. // dynamic site name determined by Netlogon
  774. //
  775. if ( NetStatus == NERR_CfgParamNotFound ) {
  776. NetStatus = NlParseTStr( SectionHandle,
  777. NETLOGON_KEYWORD_DYNAMICSITENAME,
  778. FALSE, // single valued parameter
  779. NULL,
  780. &NlParameters->SiteName );
  781. }
  782. //
  783. // If we are reading the GP section ...
  784. //
  785. } else {
  786. //
  787. // If the site name is not configured in the GP section,
  788. // may be it was configured in the Netlogon parameters section
  789. //
  790. if ( !NlParameters->SiteNameConfigured ) {
  791. NlParameters->SiteNameConfigured = DefaultParameters->SiteNameConfigured;
  792. }
  793. }
  794. //
  795. // Get the "SiteCoverage" configured parameter
  796. //
  797. NetStatus = NlParseTStr( SectionHandle,
  798. NETLOGON_KEYWORD_SITECOVERAGE,
  799. TRUE, // multivalued parameter
  800. (DefaultParameters == NULL) ?
  801. NULL :
  802. &DefaultParameters->SiteCoverage,
  803. &NlParameters->SiteCoverage );
  804. //
  805. // Get the "GcSiteCoverage" configured parameter
  806. //
  807. NetStatus = NlParseTStr( SectionHandle,
  808. NETLOGON_KEYWORD_GCSITECOVERAGE,
  809. TRUE, // multivalued parameter
  810. (DefaultParameters == NULL) ?
  811. NULL :
  812. &DefaultParameters->GcSiteCoverage,
  813. &NlParameters->GcSiteCoverage );
  814. //
  815. // Get the "NdncSiteCoverage" configured parameter
  816. //
  817. NetStatus = NlParseTStr( SectionHandle,
  818. NETLOGON_KEYWORD_NDNCSITECOVERAGE,
  819. TRUE, // multivalued parameter
  820. (DefaultParameters == NULL) ?
  821. NULL :
  822. &DefaultParameters->NdncSiteCoverage,
  823. &NlParameters->NdncSiteCoverage );
  824. //
  825. // Get the "DnsAvoidRegisterRecords" configured parameter
  826. //
  827. NetStatus = NlParseTStr( SectionHandle,
  828. NETLOGON_KEYWORD_DNSAVOIDNAME,
  829. TRUE, // multivalued parameter
  830. (DefaultParameters == NULL) ?
  831. NULL :
  832. &DefaultParameters->DnsAvoidRegisterRecords,
  833. &NlParameters->DnsAvoidRegisterRecords );
  834. #endif // _DC_NETLOGON
  835. //
  836. // Convert parameters to a more convenient form.
  837. //
  838. NlParseRecompute( NlParameters );
  839. //
  840. // If the KerbIsDoneWithJoinDomainEntry key value is 1, delete the
  841. // Netlogon\JoinDomain entry. Also delete this entry if this machine is
  842. // a DC in which case neither we nor Kerberos needs this entry. (As a
  843. // matter of fact, Kerberos won't even create KerbIsDoneWithJoinDomainEntry
  844. // on a DC.)
  845. // Always delete KerbIsDoneWithJoinDomainEntry
  846. // Ignore errors
  847. //
  848. // Do this only on the change notify since netlogon needs this info
  849. // to set the client session first time after a reboot.
  850. //
  851. if ( IsChangeNotify &&
  852. DefaultParameters == NULL ) { // KerbIsDoneWithJoinDomainEntry is in netlogon params
  853. if ( NlParameters->KerbIsDoneWithJoinDomainEntry == 1 ||
  854. !NlGlobalMemberWorkstation )
  855. {
  856. ULONG WinError = ERROR_SUCCESS;
  857. HKEY hJoinKey = NULL;
  858. WinError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  859. NETSETUPP_NETLOGON_JD_PATH,
  860. 0,
  861. KEY_ALL_ACCESS,
  862. &hJoinKey);
  863. if ( WinError == ERROR_SUCCESS)
  864. {
  865. WinError = RegDeleteKey( hJoinKey,
  866. NETSETUPP_NETLOGON_JD );
  867. if ( WinError == ERROR_SUCCESS ) {
  868. NlPrint(( NL_INIT, "NlParse: Deleted JoinDomain reg key\n" ));
  869. }
  870. if (hJoinKey)
  871. {
  872. WinError = RegCloseKey(hJoinKey);
  873. }
  874. }
  875. }
  876. TempNetStatus = NetpOpenConfigData(
  877. &WriteSectionHandle,
  878. NULL, // no server name.
  879. SERVICE_NETLOGON,
  880. FALSE); // writable, we are deleting it.
  881. if ( TempNetStatus == NO_ERROR ) {
  882. TempNetStatus = NetpDeleteConfigKeyword ( WriteSectionHandle,
  883. NETLOGON_KEYWORD_KERBISDDONEWITHJOIN );
  884. }
  885. }
  886. NetStatus = NERR_Success;
  887. Cleanup:
  888. //
  889. // Free any locally used resources
  890. //
  891. if ( ValueT != NULL) {
  892. (VOID) NetApiBufferFree( ValueT );
  893. }
  894. if ( SectionHandle != NULL ) {
  895. (VOID) NetpCloseConfigData( SectionHandle );
  896. }
  897. if ( WriteSectionHandle != NULL ) {
  898. (VOID) NetpCloseConfigData( WriteSectionHandle );
  899. }
  900. return RetVal;
  901. }
  902. BOOL
  903. NlparseAllSections(
  904. IN PNETLOGON_PARAMETERS NlParameters,
  905. IN BOOLEAN IsChangeNotify
  906. )
  907. /*++
  908. Routine Description:
  909. Get parameters from both the Group Policy and the
  910. Netlogon Parameters registry sections.
  911. Arguments:
  912. NlParameters - Structure describing all parameters
  913. IsChangeNotify - TRUE if this call is the result of a change notification
  914. Return Value:
  915. TRUE -- iff the parse was successful.
  916. --*/
  917. {
  918. NETLOGON_PARAMETERS NlLocalParameters;
  919. NETLOGON_PARAMETERS GpParameters;
  920. RtlZeroMemory( &NlLocalParameters, sizeof(NlLocalParameters) );
  921. RtlZeroMemory( &GpParameters, sizeof(GpParameters) );
  922. //
  923. // Do the one time initialization here
  924. //
  925. if ( !IsChangeNotify ) {
  926. NT_PRODUCT_TYPE NtProductType;
  927. ULONG i;
  928. //
  929. // Flag if this is a workstation (or member server)
  930. //
  931. if ( !RtlGetNtProductType( &NtProductType ) ) {
  932. NtProductType = NtProductWinNt;
  933. }
  934. if ( NtProductType == NtProductLanManNt ) {
  935. NlGlobalMemberWorkstation = FALSE;
  936. } else {
  937. NlGlobalMemberWorkstation = TRUE;
  938. }
  939. //
  940. // Set the right default for NeutralizeNt4Emulator that depends
  941. // on whether we are a DC or not
  942. //
  943. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  944. if ( wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NEUTRALIZENT4EMULATOR) == 0 ) {
  945. if ( NlGlobalMemberWorkstation ) {
  946. BoolParseTable[i].DefaultValue = FALSE; // FALSE for a workstation
  947. } else {
  948. BoolParseTable[i].DefaultValue = TRUE; // TRUE for a DC
  949. }
  950. break;
  951. }
  952. }
  953. }
  954. //
  955. // First parse the new parameters from the Netlogon Parameters section
  956. //
  957. if ( !Nlparse( &NlLocalParameters, NULL, IsChangeNotify ) ) {
  958. return FALSE; // error here is critical
  959. }
  960. //
  961. // Next parse from the GP section using the parameters from the
  962. // Netlogon Parameters section as default
  963. //
  964. if ( !Nlparse( &GpParameters, &NlLocalParameters, IsChangeNotify ) ) {
  965. //
  966. // If the GP is not defined, use the parameters from
  967. // the Netlogon Parameters section
  968. //
  969. *NlParameters = NlLocalParameters;
  970. NlPrint((NL_INIT, "Group Policy is not defined for Netlogon\n"));
  971. } else {
  972. *NlParameters = GpParameters;
  973. NlPrint((NL_INIT, "Group Policy is defined for Netlogon\n"));
  974. //
  975. // Free whatever is left in the local Netlogon parameters
  976. //
  977. NlParseFree( &NlLocalParameters );
  978. }
  979. #if NETLOGONDBG
  980. //
  981. // Dump all the values on first invocation
  982. //
  983. if ( !IsChangeNotify ) {
  984. ULONG i;
  985. //
  986. // Be Verbose
  987. //
  988. NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
  989. NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
  990. NlParameters->UnicodeSysvolPath));
  991. NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
  992. NlParameters->UnicodeScriptPath));
  993. NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
  994. NlParameters->SiteNameConfigured,
  995. NlParameters->SiteName ));
  996. {
  997. LPTSTR_ARRAY TStrArray;
  998. if ( NlParameters->SiteCoverage != NULL ) {
  999. NlPrint((NL_INIT," SiteCoverage = " ));
  1000. TStrArray = NlParameters->SiteCoverage;
  1001. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1002. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1003. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1004. }
  1005. NlPrint((NL_INIT,"\n" ));
  1006. }
  1007. }
  1008. {
  1009. LPTSTR_ARRAY TStrArray;
  1010. if ( NlParameters->GcSiteCoverage != NULL ) {
  1011. NlPrint((NL_INIT," GcSiteCoverage = " ));
  1012. TStrArray = NlParameters->GcSiteCoverage;
  1013. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1014. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1015. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1016. }
  1017. NlPrint((NL_INIT,"\n" ));
  1018. }
  1019. }
  1020. {
  1021. LPTSTR_ARRAY TStrArray;
  1022. if ( NlParameters->NdncSiteCoverage != NULL ) {
  1023. NlPrint((NL_INIT," NdncSiteCoverage = " ));
  1024. TStrArray = NlParameters->NdncSiteCoverage;
  1025. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1026. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1027. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1028. }
  1029. NlPrint((NL_INIT,"\n" ));
  1030. }
  1031. }
  1032. {
  1033. LPTSTR_ARRAY TStrArray;
  1034. if ( NlParameters->DnsAvoidRegisterRecords != NULL ) {
  1035. NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
  1036. TStrArray = NlParameters->DnsAvoidRegisterRecords;
  1037. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1038. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1039. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1040. }
  1041. NlPrint((NL_INIT,"\n" ));
  1042. }
  1043. }
  1044. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  1045. NlPrint((NL_INIT,
  1046. " %ws = %lu (0x%lx)\n",
  1047. ParseTable[i].Keyword,
  1048. *(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset),
  1049. *(PULONG)(((LPBYTE)NlParameters)+ParseTable[i].ValueOffset) ));
  1050. }
  1051. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  1052. NlPrint(( NL_INIT,
  1053. " %ws = %s\n",
  1054. BoolParseTable[i].Keyword,
  1055. (*(PBOOL)(((LPBYTE)NlParameters)+BoolParseTable[i].ValueOffset)) ?
  1056. "TRUE":"FALSE" ));
  1057. }
  1058. }
  1059. #endif // NETLOGONDBG
  1060. return TRUE;
  1061. }
  1062. VOID
  1063. NlParseFree(
  1064. IN PNETLOGON_PARAMETERS NlParameters
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. Free any allocated parameters.
  1069. Arguments:
  1070. NlParameters - Structure describing all parameters
  1071. Return Value:
  1072. None.
  1073. --*/
  1074. {
  1075. if ( NlParameters->SiteName != NULL) {
  1076. (VOID) NetApiBufferFree( NlParameters->SiteName );
  1077. NlParameters->SiteName = NULL;
  1078. }
  1079. if ( NlParameters->SiteCoverage != NULL) {
  1080. (VOID) NetApiBufferFree( NlParameters->SiteCoverage );
  1081. NlParameters->SiteCoverage = NULL;
  1082. }
  1083. if ( NlParameters->GcSiteCoverage != NULL) {
  1084. (VOID) NetApiBufferFree( NlParameters->GcSiteCoverage );
  1085. NlParameters->GcSiteCoverage = NULL;
  1086. }
  1087. if ( NlParameters->NdncSiteCoverage != NULL) {
  1088. (VOID) NetApiBufferFree( NlParameters->NdncSiteCoverage );
  1089. NlParameters->NdncSiteCoverage = NULL;
  1090. }
  1091. if ( NlParameters->DnsAvoidRegisterRecords != NULL) {
  1092. (VOID) NetApiBufferFree( NlParameters->DnsAvoidRegisterRecords );
  1093. NlParameters->DnsAvoidRegisterRecords = NULL;
  1094. }
  1095. if ( NlParameters->UnicodeScriptPath != NULL) {
  1096. (VOID) NetApiBufferFree( NlParameters->UnicodeScriptPath );
  1097. NlParameters->UnicodeScriptPath = NULL;
  1098. }
  1099. if ( NlParameters->UnicodeSysvolPath != NULL) {
  1100. (VOID) NetApiBufferFree( NlParameters->UnicodeSysvolPath );
  1101. NlParameters->UnicodeSysvolPath = NULL;
  1102. }
  1103. }
  1104. VOID
  1105. NlReparse(
  1106. VOID
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This routine handle a registry change notification.
  1111. Arguments:
  1112. None.
  1113. Return Value:
  1114. None
  1115. --*/
  1116. {
  1117. NETLOGON_PARAMETERS LocalParameters;
  1118. ULONG i;
  1119. LPWSTR TempString;
  1120. BOOLEAN UpdateDns = FALSE;
  1121. BOOLEAN UpdateShares = FALSE;
  1122. BOOLEAN UpdateSiteName = FALSE;
  1123. ULONG OldDnsTtl;
  1124. BOOL OldSysVolReady;
  1125. BOOL OldDisablePasswordChange;
  1126. ULONG OldScavengeInterval;
  1127. ULONG OldMaximumPasswordAge;
  1128. //
  1129. // Grab any old values that might be interesting.
  1130. //
  1131. OldDnsTtl = NlGlobalParameters.DnsTtl;
  1132. OldSysVolReady = NlGlobalParameters.SysVolReady;
  1133. OldDisablePasswordChange = NlGlobalParameters.DisablePasswordChange;
  1134. OldScavengeInterval = NlGlobalParameters.ScavengeInterval;
  1135. OldMaximumPasswordAge = NlGlobalParameters.MaximumPasswordAge;
  1136. //
  1137. // Parse both sections in registry relevant to us
  1138. //
  1139. if (! NlparseAllSections( &LocalParameters, TRUE ) ) {
  1140. return;
  1141. }
  1142. //
  1143. // Be Verbose
  1144. //
  1145. NlPrint((NL_INIT, "Following are the effective values after parsing\n"));
  1146. if ( (LocalParameters.UnicodeSysvolPath == NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) ||
  1147. (LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath == NULL ) ||
  1148. (LocalParameters.UnicodeSysvolPath != NULL && NlGlobalParameters.UnicodeSysvolPath != NULL ) && _wcsicmp( LocalParameters.UnicodeSysvolPath, NlGlobalParameters.UnicodeSysvolPath) != 0 ) {
  1149. NlPrint((NL_INIT," Sysvol = " FORMAT_LPWSTR "\n",
  1150. LocalParameters.UnicodeSysvolPath));
  1151. // We can get away with this since only Netlogon's main thread touches
  1152. // this variable.
  1153. TempString = LocalParameters.UnicodeSysvolPath;
  1154. LocalParameters.UnicodeSysvolPath = NlGlobalParameters.UnicodeSysvolPath;
  1155. NlGlobalParameters.UnicodeSysvolPath = TempString;
  1156. UpdateShares = TRUE;
  1157. }
  1158. if ( (LocalParameters.UnicodeScriptPath == NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) ||
  1159. (LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath == NULL ) ||
  1160. (LocalParameters.UnicodeScriptPath != NULL && NlGlobalParameters.UnicodeScriptPath != NULL ) && _wcsicmp( LocalParameters.UnicodeScriptPath, NlGlobalParameters.UnicodeScriptPath) != 0 ) {
  1161. NlPrint((NL_INIT," Scripts = " FORMAT_LPWSTR "\n",
  1162. LocalParameters.UnicodeScriptPath));
  1163. // We can get away with this since only Netlogon's main thread touches
  1164. // this variable.
  1165. TempString = LocalParameters.UnicodeScriptPath;
  1166. LocalParameters.UnicodeScriptPath = NlGlobalParameters.UnicodeScriptPath;
  1167. NlGlobalParameters.UnicodeScriptPath = TempString;
  1168. UpdateShares = TRUE;
  1169. }
  1170. if ( (LocalParameters.SiteNameConfigured != NlGlobalParameters.SiteNameConfigured ) ||
  1171. (LocalParameters.SiteName == NULL && NlGlobalParameters.SiteName != NULL ) ||
  1172. (LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName == NULL ) ||
  1173. (LocalParameters.SiteName != NULL && NlGlobalParameters.SiteName != NULL ) && _wcsicmp( LocalParameters.SiteName, NlGlobalParameters.SiteName) != 0 ) {
  1174. NlPrint((NL_INIT," SiteName (%ld) = " FORMAT_LPWSTR "\n",
  1175. LocalParameters.SiteNameConfigured,
  1176. LocalParameters.SiteName ));
  1177. // We can get away with this since only Netlogon's main thread touches
  1178. // this variable.
  1179. TempString = LocalParameters.SiteName;
  1180. LocalParameters.SiteName = NlGlobalParameters.SiteName;
  1181. NlGlobalParameters.SiteName = TempString;
  1182. NlGlobalParameters.SiteNameConfigured = LocalParameters.SiteNameConfigured;
  1183. UpdateSiteName = TRUE;
  1184. }
  1185. //
  1186. // Handle SiteCoverage changing
  1187. //
  1188. if ( NlSitesSetSiteCoverageParam( DOM_REAL_DOMAIN, LocalParameters.SiteCoverage ) ) {
  1189. LPTSTR_ARRAY TStrArray;
  1190. NlPrint((NL_INIT," SiteCoverage = " ));
  1191. TStrArray = LocalParameters.SiteCoverage;
  1192. if ( TStrArray == NULL ) {
  1193. NlPrint((NL_INIT,"<NULL>" ));
  1194. } else {
  1195. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1196. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1197. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1198. }
  1199. }
  1200. NlPrint((NL_INIT,"\n" ));
  1201. // NlSitesSetSiteCoverageParam used this allocated buffer
  1202. LocalParameters.SiteCoverage = NULL;
  1203. UpdateDns = TRUE;
  1204. }
  1205. //
  1206. // Handle GcSiteCoverage changing
  1207. //
  1208. if ( NlSitesSetSiteCoverageParam( DOM_FOREST, LocalParameters.GcSiteCoverage ) ) {
  1209. LPTSTR_ARRAY TStrArray;
  1210. NlPrint((NL_INIT," GcSiteCoverage = " ));
  1211. TStrArray = LocalParameters.GcSiteCoverage;
  1212. if ( TStrArray == NULL ) {
  1213. NlPrint((NL_INIT,"<NULL>" ));
  1214. } else {
  1215. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1216. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1217. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1218. }
  1219. }
  1220. NlPrint((NL_INIT,"\n" ));
  1221. // NlSitesSetSiteCoverageParam used this allocated buffer
  1222. LocalParameters.GcSiteCoverage = NULL;
  1223. UpdateDns = TRUE;
  1224. }
  1225. //
  1226. // Handle NdncSiteCoverage changing
  1227. //
  1228. if ( NlSitesSetSiteCoverageParam( DOM_NON_DOMAIN_NC, LocalParameters.NdncSiteCoverage ) ) {
  1229. LPTSTR_ARRAY TStrArray;
  1230. NlPrint((NL_INIT," NdncSiteCoverage = " ));
  1231. TStrArray = LocalParameters.NdncSiteCoverage;
  1232. if ( TStrArray == NULL ) {
  1233. NlPrint((NL_INIT,"<NULL>" ));
  1234. } else {
  1235. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1236. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1237. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1238. }
  1239. }
  1240. NlPrint((NL_INIT,"\n" ));
  1241. // NlSitesSetSiteCoverageParam used this allocated buffer
  1242. LocalParameters.NdncSiteCoverage = NULL;
  1243. UpdateDns = TRUE;
  1244. }
  1245. //
  1246. // Handle DnsAvoidRegisterRecords changing
  1247. //
  1248. if ( NlDnsSetAvoidRegisterNameParam( LocalParameters.DnsAvoidRegisterRecords ) ) {
  1249. LPTSTR_ARRAY TStrArray;
  1250. NlPrint((NL_INIT," DnsAvoidRegisterRecords = " ));
  1251. TStrArray = LocalParameters.DnsAvoidRegisterRecords;
  1252. if ( TStrArray == NULL ) {
  1253. NlPrint((NL_INIT,"<NULL>" ));
  1254. } else {
  1255. while (!NetpIsTStrArrayEmpty(TStrArray)) {
  1256. NlPrint((NL_INIT," '%ws'", TStrArray ));
  1257. TStrArray = NetpNextTStrArrayEntry(TStrArray);
  1258. }
  1259. }
  1260. NlPrint((NL_INIT,"\n" ));
  1261. // NlSitesSetSiteCoverageParam used this allocated buffer
  1262. LocalParameters.DnsAvoidRegisterRecords = NULL;
  1263. UpdateDns = TRUE;
  1264. }
  1265. //
  1266. // Install all the numeric parameters.
  1267. //
  1268. for ( i=0; i<sizeof(ParseTable)/sizeof(ParseTable[0]); i++ ) {
  1269. if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) !=
  1270. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) ) ) {
  1271. NlPrint((NL_INIT,
  1272. " %ws = %lu (0x%lx)\n",
  1273. ParseTable[i].Keyword,
  1274. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset),
  1275. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset) ));
  1276. //
  1277. // Actually set the value
  1278. //
  1279. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+ParseTable[i].ValueOffset) =
  1280. *(PULONG)(((LPBYTE)(&LocalParameters))+ParseTable[i].ValueOffset);
  1281. //
  1282. // If this changed value affects DNS,
  1283. // note that fact.
  1284. //
  1285. if ( ParseTable[i].ChangesDnsRegistration ) {
  1286. UpdateDns = TRUE;
  1287. }
  1288. }
  1289. }
  1290. for ( i=0; i<sizeof(BoolParseTable)/sizeof(BoolParseTable[0]); i++ ) {
  1291. if ( (*(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset) !=
  1292. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) ) ) {
  1293. NlPrint(( NL_INIT,
  1294. " %ws = %s\n",
  1295. BoolParseTable[i].Keyword,
  1296. (*(PBOOL)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset)) ?
  1297. "TRUE":"FALSE" ));
  1298. //
  1299. // Actually set the value
  1300. //
  1301. *(PULONG)(((LPBYTE)(&NlGlobalParameters))+BoolParseTable[i].ValueOffset) =
  1302. *(PULONG)(((LPBYTE)(&LocalParameters))+BoolParseTable[i].ValueOffset);
  1303. //
  1304. // If this changed value affects DNS,
  1305. // note that fact.
  1306. //
  1307. if ( BoolParseTable[i].ChangesDnsRegistration ) {
  1308. UpdateDns = TRUE;
  1309. }
  1310. //
  1311. // If this changed value affects LSA, inform it
  1312. //
  1313. if ( !NlGlobalMemberWorkstation &&
  1314. wcscmp(BoolParseTable[i].Keyword, NETLOGON_KEYWORD_NT4EMULATOR) == 0 ) {
  1315. LsaINotifyNetlogonParametersChangeW(
  1316. LsaEmulateNT4,
  1317. REG_DWORD,
  1318. (PWSTR)&NlGlobalParameters.Nt4Emulator,
  1319. sizeof(NlGlobalParameters.Nt4Emulator) );
  1320. }
  1321. }
  1322. }
  1323. //
  1324. // Convert parameters to a more convenient form.
  1325. //
  1326. NlParseRecompute( &NlGlobalParameters );
  1327. //
  1328. // Notify other components of parameters that have changed.
  1329. //
  1330. //
  1331. // Enable detection of duplicate event log messages
  1332. //
  1333. NetpEventlogSetTimeout ( NlGlobalEventlogHandle,
  1334. NlGlobalParameters.DuplicateEventlogTimeout*1000 );
  1335. //
  1336. // Do member workstation specific updates
  1337. //
  1338. if ( NlGlobalMemberWorkstation ) {
  1339. //
  1340. // Update site name
  1341. //
  1342. if ( UpdateSiteName ) {
  1343. (VOID) NlSetSiteName( NlGlobalParameters.SiteName, NULL );
  1344. }
  1345. //
  1346. // Do DC specific updates
  1347. //
  1348. } else {
  1349. //
  1350. // Re-register DNS records
  1351. //
  1352. // If DnsTtl has changed,
  1353. // force all records to be registered.
  1354. //
  1355. if ( UpdateDns ) {
  1356. NlDnsPnp( NlGlobalParameters.DnsTtl != OldDnsTtl );
  1357. }
  1358. //
  1359. // Update the Netlogon and Sysvol shares
  1360. //
  1361. if ( UpdateShares || OldSysVolReady != NlGlobalParameters.SysVolReady ) {
  1362. NlCreateSysvolShares();
  1363. }
  1364. }
  1365. //
  1366. // If the settings that affect the scavenger have changed,
  1367. // trigger it now.
  1368. //
  1369. if ( OldDisablePasswordChange != NlGlobalParameters.DisablePasswordChange ||
  1370. OldScavengeInterval != NlGlobalParameters.ScavengeInterval ||
  1371. OldMaximumPasswordAge != NlGlobalParameters.MaximumPasswordAge ) {
  1372. //
  1373. // We don't need to set NlGlobalTimerEvent since we're already processing
  1374. // a registry notification event. That'll make NlMainLoop notice the change.
  1375. //
  1376. EnterCriticalSection( &NlGlobalScavengerCritSect );
  1377. NlGlobalScavengerTimer.Period = 0;
  1378. LeaveCriticalSection( &NlGlobalScavengerCritSect );
  1379. }
  1380. // Cleanup:
  1381. NlParseFree( &LocalParameters );
  1382. return;
  1383. }