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.
4140 lines
162 KiB
4140 lines
162 KiB
/*++
|
|
|
|
Copyright (c) 1997-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
GetConfigParam reads a configuration keyword from the registry.
|
|
|
|
Author:
|
|
|
|
David Orbits - June-1999 Complete Rewrite to make table driven.
|
|
|
|
Environment:
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <ntreppch.h>
|
|
#pragma hdrstop
|
|
|
|
#include <ctype.h>
|
|
#include <frs.h>
|
|
#include <ntfrsapi.h>
|
|
|
|
#define FULL_KEY_BUFF_SIZE 8192
|
|
|
|
VOID
|
|
FrsRegPostEventLog(
|
|
IN PFRS_REGISTRY_KEY KeyCtx,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
IN LONG IDScode
|
|
);
|
|
|
|
|
|
PGEN_TABLE ReparseTagTable;
|
|
|
|
//
|
|
// Possible errors are:
|
|
// required key not present
|
|
// required value not present
|
|
// value out of range
|
|
|
|
//
|
|
// **** NOTE: Also use this for FRS tuning parameters to select between
|
|
// workstation and server operation modes. Create a table with a list of the
|
|
// parameter codes and override values for the min, max and defaults.
|
|
// Apply during startup to reduce server footprint.
|
|
//
|
|
|
|
|
|
typedef struct _FRS_REG_KEY_REVISIONS {
|
|
|
|
LONG FrsKeyCode; // Frs code name for this key.
|
|
|
|
DWORD ValueMin; // Minimum data value, or string len
|
|
DWORD ValueMax; // Maximum Data value, or string len
|
|
DWORD ValueDefault; // Default data value if not present.
|
|
} FRS_REG_KEY_REVISIONS, *PFRS_REG_KEY_REVISIONS;
|
|
|
|
|
|
FRS_REG_KEY_REVISIONS FrsRegKeyRevisionTable[] = {
|
|
|
|
{FKC_DEBUG_MAX_LOG , 0 , MAXLONG, 10000 },
|
|
{FKC_MAX_REPLICA_THREADS , 2 , 10, 2 },
|
|
{FKC_MAX_RPC_SERVER_THREADS , 2 , 10, 2 },
|
|
{FKC_MAX_INSTALLCS_THREADS , 2 , 10, 2 },
|
|
{FKC_MAX_STAGE_GENCS_THREADS, 2 , 10, 2 },
|
|
{FKC_MAX_STAGE_FETCHCS_THREADS, 2 , 10, 2 },
|
|
{FKC_MAX_INITSYNCCS_THREADS, 2 , 10, 2 },
|
|
{FKC_SNDCS_MAXTHREADS_PAR , 2 , 10, 2 },
|
|
{FKC_MAX_NUMBER_REPLICA_SETS, 1 , 10, 5 },
|
|
{FKC_MAX_NUMBER_JET_SESSIONS, 1 , 50, 50 },
|
|
|
|
{FKC_END_OF_TABLE, 0, 0, 0 }
|
|
};
|
|
|
|
//
|
|
// See sdk\inc\ntconfig.h if more registry data types are added.
|
|
//
|
|
|
|
#define NUMBER_OF_REG_DATATYPES 12
|
|
|
|
PWCHAR RegDataTypeNames[NUMBER_OF_REG_DATATYPES] = {
|
|
|
|
L"REG_NONE" , // ( 0 ) No value type
|
|
L"REG_SZ" , // ( 1 ) Unicode nul terminated string
|
|
L"REG_EXPAND_SZ" , // ( 2 ) Unicode nul terminated string (with environment variable references)
|
|
L"REG_BINARY" , // ( 3 ) Free form binary
|
|
L"REG_DWORD" , // ( 4 ) 32-bit number
|
|
L"REG_DWORD_BIG_ENDIAN" , // ( 5 ) 32-bit number
|
|
L"REG_LINK" , // ( 6 ) Symbolic Link (unicode)
|
|
L"REG_MULTI_SZ" , // ( 7 ) Multiple Unicode strings
|
|
L"REG_RESOURCE_LIST" , // ( 8 ) Resource list in the resource map
|
|
L"REG_FULL_RESOURCE_DESCRIPTOR" , // ( 9 ) Resource list in the hardware description
|
|
L"REG_RESOURCE_REQUIREMENTS_LIST" , // ( 10 )
|
|
L"REG_QWORD" // ( 11 ) 64-bit number
|
|
};
|
|
|
|
#define REG_DT_NAME(_code_) \
|
|
(((_code_) < NUMBER_OF_REG_DATATYPES) ? \
|
|
RegDataTypeNames[(_code_)] : RegDataTypeNames[0])
|
|
|
|
//
|
|
//
|
|
// If a range check fails the event EVENT_FRS_PARAM_OUT_OF_RANGE is logged if
|
|
// FRS_RKF_LOG_EVENT is set.
|
|
//
|
|
// If a syntax check fails the event EVENT_FRS_PARAM_INVALID_SYNTAX is logged if
|
|
// FRS_RKF_LOG_EVENT is set.
|
|
//
|
|
// If a required parameter is missing the event EVENT_FRS_PARAM_MISSING is logged
|
|
// if FRS_RKF_LOG_EVENT is set.
|
|
//
|
|
|
|
BOOL Win2kPro;
|
|
|
|
|
|
FLAG_NAME_TABLE RkfFlagNameTable[] = {
|
|
{FRS_RKF_KEY_PRESENT , "KeyPresent " },
|
|
{FRS_RKF_VALUE_PRESENT , "ValuePresent " },
|
|
{FRS_RKF_DISPLAY_ERROR , "ShowErrorMsg " },
|
|
{FRS_RKF_LOG_EVENT , "ShowEventMsg " },
|
|
|
|
{FRS_RKF_READ_AT_START , "ReadAtStart " },
|
|
{FRS_RKF_READ_AT_POLL , "ReadAtPoll " },
|
|
{FRS_RKF_RANGE_CHECK , "RangeCheck " },
|
|
{FRS_RKF_SYNTAX_CHECK , "SyntaxCheck " },
|
|
|
|
{FRS_RKF_KEY_MUST_BE_PRESENT , "KeyMustBePresent " },
|
|
{FRS_RKF_VALUE_MUST_BE_PRESENT , "ValueMustBePresent " },
|
|
{FRS_RKF_OK_TO_USE_DEFAULT , "DefaultOK " },
|
|
{FRS_RKF_FORCE_DEFAULT_VALUE , "ForceDefault " },
|
|
|
|
{FRS_RKF_DEBUG_MODE_ONLY , "DebugMode " },
|
|
{FRS_RKF_TEST_MODE_ONLY , "TestMode " },
|
|
{FRS_RKF_API_ACCESS_CHECK_KEY , "DoAPIAccessChk " },
|
|
{FRS_RKF_CREATE_KEY , "CreateKey " },
|
|
|
|
{FRS_RKF_KEEP_EXISTING_VALUE , "KeepExistingValue " },
|
|
{FRS_RKF_KEY_ACCCHK_READ , "DoReadAccessChk " },
|
|
{FRS_RKF_KEY_ACCCHK_WRITE , "DoWriteAccessChk " },
|
|
{FRS_RKF_RANGE_SATURATE , "RangeSaturate " },
|
|
|
|
{FRS_RKF_DEBUG_PARAM , "DisplayAsDebugPar " },
|
|
|
|
{0, NULL}
|
|
};
|
|
|
|
|
|
//
|
|
// The following describes the registry keys used by FRS.
|
|
// KeyName ValueName DataUnits
|
|
// RegValueType DataValueType Min Max Default EventCode
|
|
// FrsKeyCode Flags
|
|
//
|
|
//
|
|
// Notation for keyName field. Multiple key components separated by commas.
|
|
// Break on commas. Open leading key then create/open each successive component.
|
|
// ARG1 means substitute the Arg1 PWSTR parameter passed to the function for this
|
|
// key component. Most often this is a stringized guid. The string FRS_RKEY_SET_N
|
|
// below will end up opening/creating the following key:
|
|
//
|
|
// "System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Replica Sets\\27d6d1c4-d6b8-480b-9f18b5ea390a0178"
|
|
// assuming the argument passed in was "27d6d1c4-d6b8-480b-9f18b5ea390a0178"
|
|
//
|
|
// see FrsRegOpenKey() for details.
|
|
//
|
|
|
|
FRS_REGISTRY_KEY FrsRegistryKeyTable[] = {
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** S e r v i c e D e b u g K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
|
|
// Number of assert files
|
|
{FRS_CONFIG_SECTION, L"Debug Assert Files", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 1000, 5, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_ASSERT_FILES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Force an assert after N seconds (0 == don't assert)
|
|
{FRS_CONFIG_SECTION, L"Debug Force Assert in N Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 0, 1000, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_ASSERT_SECONDS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_TEST_MODE_ONLY},
|
|
|
|
|
|
// Share for copying log/assert files
|
|
{FRS_CONFIG_SECTION, L"Debug Share for Assert Files", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_ASSERT_SHARE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_DEBUG_PARAM},
|
|
|
|
|
|
// If TRUE, Break into the debugger, if present
|
|
{FRS_CONFIG_SECTION, L"Debug Break", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_BREAK, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If TRUE, copy log files into assert share
|
|
{FRS_CONFIG_SECTION, L"Debug Copy Log Files into Assert Share", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_COPY_LOG_FILES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Force real out of disk space errors on database operations
|
|
{FRS_CONFIG_SECTION, L"Debug Dbs Out Of Space", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, DBG_DBS_OUT_OF_SPACE_OP_MAX, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_DBS_OUT_OF_SPACE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Force Jet Err simulated out of disk space errors on database operations
|
|
{FRS_CONFIG_SECTION, L"Debug Dbs Out Of Space Trigger", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_DBS_OUT_OF_SPACE_TRIGGER, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If TRUE, debug log file generation (DPRINTS and CO Trace output) is off.
|
|
{FRS_CONFIG_SECTION, L"Debug Disable", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_DISABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// The directory path for the FRS debug logs.
|
|
{FRS_CONFIG_SECTION, L"Debug Log File", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
|
|
L"%SystemRoot%\\debug",
|
|
FKC_DEBUG_LOG_FILE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Number of debug log files to keep as history
|
|
{FRS_CONFIG_SECTION, L"Debug Log Files", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 300, 5, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_LOG_FILES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Number of debug log records written between file flushes.
|
|
// btw: Severity 0 log records always force a log file flush.
|
|
{FRS_CONFIG_SECTION, L"Debug Log Flush Interval", UNITS_NONE,
|
|
REG_DWORD, DT_LONG, 1, MAXLONG, 20000, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_LOG_FLUSH_INTERVAL, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Print debug msgs with severity level LE DEBUG_LOG_SEVERITY to debug log.
|
|
// 0 - Most severe, eg. fatal inconsistency, mem alloc fail. Least noisey.
|
|
// 1 - Important info, eg. Key config parameters, unexpected conditions
|
|
// 2 - File tracking records.
|
|
// 3 - Change Order Process trace records.
|
|
// 4 - Status results, e.g. table lookup failures, new entry inserted
|
|
// 5 - Information level messages to show flow. Noisest level. Maybe in a loop
|
|
// see also DEBUG_SEVERITY.
|
|
{FRS_CONFIG_SECTION, L"Debug Log Severity", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 5, 2, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_LOG_SEVERITY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Max number of debug log messages output before opening a new log file.
|
|
{FRS_CONFIG_SECTION, L"Debug Maximum Log Messages", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 20000, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_MAX_LOG, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If >0, then track and check all mem alloc / dealloc. (slow)
|
|
// 1 - checks allocs and frees and prints stack of unalloced mem at exit
|
|
// 2 - checks for mem alloc region overwrite on each alloc/free - very slow.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Mem", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 4, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_MEM, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If TRUE, then call HeapCompact(GetProcessHeap(), 0) on mem dealloc. (slower)
|
|
{FRS_CONFIG_SECTION, L"Debug Mem Compact", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_MEM_COMPACT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Mail profile for sending mail notifications. (future)
|
|
{FRS_CONFIG_SECTION, L"Debug Profile", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_PROFILE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// If TRUE, then check consistency of command queues on each queue op. (slow)
|
|
{FRS_CONFIG_SECTION, L"Debug Queues", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_QUEUES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_TEST_MODE_ONLY |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Mail recipients for sending mail notifications. (future)
|
|
{FRS_CONFIG_SECTION, L"Debug Recipients", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_RECIPIENTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// Restart the service after an assertion failure iff the service was able
|
|
// to run for at least DEBUG_RESTART_SECONDS before the assert hit.
|
|
{FRS_CONFIG_SECTION, L"Debug Restart if Assert after N Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 600, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_RESTART_SECONDS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Print debug msgs with severity level LE DEBUG_SEVERITY to
|
|
// stdout if running as -notservice.
|
|
// see also DEBUG_LOG_SEVERITY.
|
|
{FRS_CONFIG_SECTION, L"Debug Severity", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 5, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DEBUG_SEVERITY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If FALSE, Print debug msgs with severity level LE DEBUG_SEVERITY to
|
|
// an attached debugger. (slow)
|
|
// see also DEBUG_LOG_SEVERITY.
|
|
{FRS_CONFIG_SECTION, L"Debug Suppress", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, TRUE, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_SUPPRESS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Suppress debug prints from components in the DEBUG_SYSTEMS list.
|
|
// default is all components print.
|
|
{FRS_CONFIG_SECTION, L"Debug Systems", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_SYSTEMS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// Test code name for FRS_DEBUG_TEST_POINT macro.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Test Code Name", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_TEST_CODE_NAME, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_DEBUG_PARAM},
|
|
|
|
|
|
// Test sub-code number for FRS_DEBUG_TEST_POINT macro.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Test Code Number", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_TEST_CODE_NUMBER, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Initial test trigger count for FRS_DEBUG_TEST_POINT macro.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Test Trigger Count", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_TEST_TRIGGER_COUNT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
// Test trigger refresh value for FRS_DEBUG_TEST_POINT macro.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Test Trigger Refresh", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_TEST_TRIGGER_REFRESH, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_DEBUG_PARAM |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// hklm\software\microsoft\windows nt\current version\buildlab
|
|
{FRS_CURRENT_VER_SECTION, L"buildlab", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_BUILDLAB, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_DEBUG_PARAM},
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** S e r v i c e C o n f i g K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
#define FRS_MUTUAL_AUTHENTICATION_IS \
|
|
L"Mutual authentication is [" FRS_IS_ENABLED L" or " FRS_IS_DISABLED L"]"
|
|
|
|
|
|
|
|
// Comm Timeout In Milliseconds
|
|
// Unjoin the cxtion if the partner doesn't respond soon enough
|
|
{FRS_CONFIG_SECTION, L"Comm Timeout In Milliseconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, (5 * 60 * 1000), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_COMM_TIMEOUT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// The directory filter exclusion list. Default: None
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_CONFIG_SECTION, L"Directory Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The directory filter inclusion list. Default: None
|
|
{FRS_CONFIG_SECTION, L"Directory Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// Minutes between polls of the DS when data does not appear to be changing.
|
|
{FRS_CONFIG_SECTION, L"DS Polling Long Interval in Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL,
|
|
NTFRSAPI_DEFAULT_LONG_INTERVAL, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DS_POLLING_LONG_INTERVAL, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Minutes between polls of the DS when data does appear to be changing.
|
|
// If no data in the DS has changed after 8 (DS_POLLING_MAX_SHORTS) short
|
|
// polling intervals then we fall back to DS_POLLING_LONG_INTERVAL.
|
|
// Note: if FRS is running on a DC always use the short interval.
|
|
{FRS_CONFIG_SECTION, L"DS Polling Short Interval in Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL,
|
|
NTFRSAPI_DEFAULT_SHORT_INTERVAL, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DS_POLLING_SHORT_INTERVAL, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Enumerate Directory Buffer Size in Bytes (WHY DO WE NEED THIS???)
|
|
{FRS_CONFIG_SECTION, L"Enumerate Directory Buffer Size in Bytes", UNITS_BYTES,
|
|
REG_DWORD, DT_ULONG, MINIMUM_ENUMERATE_DIRECTORY_SIZE, 1024*1024, 4*1024, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_ENUMERATE_DIRECTORY_SIZE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// The file filter exclusion list.
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_CONFIG_SECTION, L"File Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The file filter inclusion list. Default: L""
|
|
{FRS_CONFIG_SECTION, L"File Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, L"",
|
|
FKC_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The name of the FRS eventlog message file.
|
|
// Default value: "%SystemRoot%\system32\ntfrsres.dll"
|
|
// WHY DO WE NEED TO BE ABLE TO CHANGE THIS???
|
|
{FRS_CONFIG_SECTION, L"Message File Path", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 2, 0, 0, EVENT_FRS_NONE,
|
|
DEFAULT_MESSAGE_FILE_PATH,
|
|
FKC_FRS_MESSAGE_FILE_PATH, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Mutual authentication is [Enabled or Disabled]
|
|
{FRS_CONFIG_SECTION, FRS_MUTUAL_AUTHENTICATION_IS, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 200, 0, EVENT_FRS_NONE,
|
|
FRS_IS_DEFAULT_ENABLED,
|
|
FKC_FRS_MUTUAL_AUTHENTICATION_IS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// Maximum Join Retry time In MilliSeconds Default: 1 hr.
|
|
{FRS_CONFIG_SECTION, L"Maximum Join Retry In MilliSeconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 30*1000, 10*3600*1000, (60 * 60 * 1000), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_JOIN_RETRY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Replica Command Server Threads Default: 16
|
|
// The replica command server services commands for configuration changes
|
|
// and replication.
|
|
{FRS_CONFIG_SECTION, L"Maximum Replica Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_REPLICA_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Max Rpc Server Threads Default: 16
|
|
// Maximum number of concurrent RPC calls
|
|
{FRS_CONFIG_SECTION, L"Max Rpc Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_RPC_SERVER_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// User specified Rpc port assignment Default: 0
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Rpc TCP/IP Port Assignment", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, 0xffffffff, (0), EVENT_FRS_NONE, NULL,
|
|
FKC_RPC_PORT_ASSIGNMENT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Install Command Server Threads Default: 4
|
|
{FRS_CONFIG_SECTION, L"Maximum Install Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_INSTALLCS_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Stage Gen Command Server Threads Default: 4
|
|
{FRS_CONFIG_SECTION, L"Maximum Stage Gen Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_STAGE_GENCS_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Stage Fetch Command Server Threads Default: 4
|
|
{FRS_CONFIG_SECTION, L"Maximum Stage Fetch Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_STAGE_FETCHCS_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Initial SYnc Command Server Threads Default: 4
|
|
{FRS_CONFIG_SECTION, L"Maximum Initial Sync Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
|
|
FKC_MAX_INITSYNCCS_THREADS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Minimum Join Retry time In MilliSeconds Default: 10 sec.
|
|
// Retry a join every MinJoinRetry milliseconds, doubling the interval
|
|
// every retry. Stop retrying when the interval is greater than MaxJoinRetry.
|
|
{FRS_CONFIG_SECTION, L"Minimum Join Retry In MilliSeconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 500, 10*3600*1000, (10 * 1000), EVENT_FRS_NONE, NULL,
|
|
FKC_MIN_JOIN_RETRY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Partner Clock Skew In Minutes Default: 30 min.
|
|
// Partners are not allowed to join if their clocks are out-of-sync
|
|
{FRS_CONFIG_SECTION, L"Partner Clock Skew In Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, 1, 10*60, 30, EVENT_FRS_NONE, NULL,
|
|
FKC_PARTNER_CLOCK_SKEW, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// ChangeOrder Reconcile Event Time Window In Minutes Default: 30 min.
|
|
{FRS_CONFIG_SECTION, L"Reconcile Time Window In Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, 1, 120, 30, EVENT_FRS_NONE, NULL,
|
|
FKC_RECONCILE_WINDOW, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// ChangeOrder Inlog retry interval in seconds Default: 60 sec.
|
|
{FRS_CONFIG_SECTION, L"Inlog Retry Time In Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 1, 24*3600, 60, EVENT_FRS_NONE, NULL,
|
|
FKC_INLOG_RETRY_TIME, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// ChangeOrder Aging Delay in seconds Default: 3 sec.
|
|
// Should be a min of 3 sec to allow file system tunnel cache info to propagate.
|
|
{FRS_CONFIG_SECTION, L"Changeorder Aging Delay In Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 3, 30*60, 3, EVENT_FRS_NONE, NULL,
|
|
FKC_CO_AGING_DELAY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Outlog File Repeat Interval In Seconds Default: 30 sec.
|
|
// A CO update for a given file will not be sent out more frequently than this.
|
|
// Set to zero to disable the Outlog dominant file update optimization.
|
|
{FRS_CONFIG_SECTION, L"Outlog File Repeat Interval In Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 0, 24*3600, 30, EVENT_FRS_NONE, NULL,
|
|
FKC_OUTLOG_REPEAT_INTERVAL, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Sysvol Promotion Timeout In Milliseconds Default: 10 min.
|
|
{FRS_CONFIG_SECTION, L"Sysvol Promotion Timeout In Milliseconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 0, 3600*1000, (10 * 60 * 1000), EVENT_FRS_NONE, NULL,
|
|
FKC_PROMOTION_TIMEOUT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Replica Start Timeout In MilliSeconds Default: 0 means can't start without DS.
|
|
// Start replication even if the DS could not be accessed
|
|
// 0: no DS == no start replicas
|
|
// N: start replicas in N milliseconds
|
|
{FRS_CONFIG_SECTION, L"Replica Start Timeout In MilliSeconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 0, 3600*1000, (0), EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_START_TIMEOUT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Replica Tombstone in Days Default: 32
|
|
// The length of time we will hold onto the database state for a replica
|
|
// set after we see our membership in the DS has been deleted. Since
|
|
// delete is not explicit (except for DC Demote) it may just be that the
|
|
// DC is missing our objects or an admin erroneously deleted our subscriber
|
|
// or member object. Once this time has lapsed we will delete the tables
|
|
// from the database.
|
|
{FRS_CONFIG_SECTION, L"Replica Tombstone in Days", UNITS_DAYS,
|
|
REG_DWORD, DT_ULONG, 3, MAXLONG, (32), EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_TOMBSTONE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Shutdown Timeout in Seconds Default: 90 sec.
|
|
// The max time FRS main will wait for all threads to exit during shutdown.
|
|
{FRS_CONFIG_SECTION, L"Shutdown Timeout in Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 30, 24*60*60, DEFAULT_SHUTDOWN_TIMEOUT, EVENT_FRS_NONE, NULL,
|
|
FKC_SHUTDOWN_TIMEOUT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Send Command Server Threads Default: 16
|
|
{FRS_CONFIG_SECTION, L"Maximum Send Command Server Threads", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
|
|
FKC_SNDCS_MAXTHREADS_PAR, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Staging Space Limit in KB Default: 660 MB
|
|
{FRS_CONFIG_SECTION, L"Staging Space Limit in KB", UNITS_KBYTES,
|
|
REG_DWORD, DT_ULONG, 10*1024, MAXLONG, (660 * 1024), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_STAGING_LIMIT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_LOG_EVENT},
|
|
|
|
|
|
// VvJoin Limit in Change Orders Default: 16 ChangeOrders
|
|
// Max number of VVJoin gened COs to prevent flooding.
|
|
{FRS_CONFIG_SECTION, L"VvJoin Limit in Change Orders", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, 128, (16), EVENT_FRS_NONE, NULL,
|
|
FKC_VVJOIN_LIMIT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// VVJoin Outbound Log Throttle Timeout Default: 1 sec.
|
|
// The time FRS VVJoin thread waits after generating VVJOIN_LIMIT COs.
|
|
{FRS_CONFIG_SECTION, L"VvJoin Timeout in Milliseconds", UNITS_MILLISEC,
|
|
REG_DWORD, DT_ULONG, 100, 10*60*1000, (1000), EVENT_FRS_NONE, NULL,
|
|
FKC_VVJOIN_TIMEOUT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// The FRS working dir is where the Jet (ESENT) database is created.
|
|
// If this dir does not exist or can't be created FRS will fail to startup.
|
|
{FRS_CONFIG_SECTION, L"Working Directory", UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*(MAX_PATH+1), 4, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_WORKING_DIRECTORY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_LOG_EVENT },
|
|
|
|
|
|
// The FRS Log File Directory allows the Jet Logs to created on a different volume.
|
|
// By default they are placed in a Log subdir under the "Working Directory".
|
|
// If this dir does not exist or can't be created FRS will fail to startup.
|
|
{FRS_CONFIG_SECTION, L"DB Log File Directory", UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*(MAX_PATH+1), 4, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_DBLOG_DIRECTORY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_LOG_EVENT },
|
|
|
|
|
|
// Ntfs Journal size in MB Default: 128 Meg
|
|
{FRS_CONFIG_SECTION, L"Ntfs Journal size in MB", UNITS_MBYTES,
|
|
REG_DWORD, DT_ULONG, 4, 10000, (128), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_NTFS_JRNL_SIZE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Number of Replica Sets Default: 200.
|
|
{FRS_CONFIG_SECTION, L"Maximum Number of Replica Sets", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 1, 5000, (200), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_MAX_NUMBER_REPLICA_SETS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Number of Jet Sessions Default: 128.
|
|
{FRS_CONFIG_SECTION, L"Maximum Number of Jet Sessions", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 1, 5000, (128), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_MAX_NUMBER_JET_SESSIONS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Maximum Number of outstanding CO's per outbound connection. Default: 8.
|
|
{FRS_CONFIG_SECTION, L"Max Num Outbound COs Per Connection", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 1, 100, (8), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_OUT_LOG_CO_QUOTA, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// If TRUE, Preserve OIDs on files whenever possible Default: False
|
|
// -- See Bug 352250 for why this is a risky thing to do.
|
|
{FRS_CONFIG_SECTION, L"Preserve File OID", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_PRESERVE_FILE_OID, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
//
|
|
// Disable compression support. Need a non-auth restore to
|
|
// make sure we don't have any old compressed staging files
|
|
// when this key is turned on. Default: True
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Debug Disable Compression", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_DEBUG_DISABLE_COMPRESSION, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// Compress staging files for local changes. Set to FALSE to disable.
|
|
// This member will continue to install and propagate compressed files.
|
|
// This is useful if the customer has content that originates on this member
|
|
// which is either already compressed or doesn't compress well.
|
|
// Default: True
|
|
{FRS_CONFIG_SECTION, L"Compress Staging Files", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
|
|
FKC_COMPRESS_STAGING_FILES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
//
|
|
// This controls automatic reclaim of staging space by using an
|
|
// LRU algorithm. Default: True
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Reclaim Staging Space", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
|
|
FKC_RECLAIM_STAGING_SPACE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// Client side ldap search timeout value. Default: 10 minutes.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Ldap Search Timeout In Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, 1, 120, (10), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_LDAP_SEARCH_TIMEOUT_IN_MINUTES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
//
|
|
// Client side ldap_connect timeout value. Default: 30 seconds.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Ldap Bind Timeout In Seconds", UNITS_SECONDS,
|
|
REG_DWORD, DT_ULONG, 2, MAXLONG, (30), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_LDAP_BIND_TIMEOUT_IN_SECONDS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// The length of time we retry a change order before aborting it.
|
|
// e.g. A file create waiting for the create of a parent dir that
|
|
// never comes. Default: 7 days
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Maximum CO Retry Timeout in Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, 1, 525600, (10080), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_MAX_CO_RETRY_TIMEOUT_MINUTES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// The number of retries applied to a change order before aborting it.
|
|
// e.g. A file create waiting for the create of a parent dir that
|
|
// never comes. Default: 3000
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Maximum CO Retry Count", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 2, MAXLONG, (3000), EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_MAX_CO_RETRY_TIMEOUT_COUNT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// Enable automatic restore on journal wrap or journal recreation.
|
|
// This occurs when the replica set gets into either state
|
|
// REPLICA_STATE_JRNL_WRAP_ERROR or REPLICA_STATE_MISMATCHED_JOURNAL_ID.
|
|
// The default is FALSE because a non-auth restore will move the replica
|
|
// tree to the pre-existing dir and make the files unavailable on a DFS
|
|
// alternate. Customers did not like this.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Enable Journal Wrap Automatic Restore", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_ENABLE_JOURNAL_WRAP_AUTOMATIC_RESTORE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// If True then hold the ReplicaList lock for the duration of an outlog cleanup
|
|
// cycle (which could be many minutes). If False then don't hold the lock.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Enable Locked Outlog Cleanup", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_LOCKED_OUTLOG_CLEANUP, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// This controls how long the change orders will stay in the outlog.
|
|
// Change orders are kept in the outlog to satisfy future vvjoins
|
|
// without having to scan the idtable. Default: 1 week.
|
|
//
|
|
{FRS_CONFIG_SECTION, L"Outlog Change History In Minutes", UNITS_MINUTES,
|
|
REG_DWORD, DT_ULONG, 1, MAXLONG, (10080), EVENT_FRS_NONE, NULL,
|
|
FKC_OUTLOG_CHANGE_HISTORY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// This controls how long whether COs in the outlog even after they have
|
|
// been ACK ed by all the partners. The longer the COs stay in the outlog
|
|
// the greater the chances of avoiding complete vvjoins. The period is
|
|
// controlled by the FKC_OUTLOG_CHANGE_HISTORY key above. The
|
|
// FKC_SAVE_OUTLOG_CHANGE_HISTORY turns this feature off. Turn this off in
|
|
// cases where the outlog is getting very large. Even when
|
|
// FKC_SAVE_OUTLOG_CHANGE_HISTORY is turned off FKC_OUTLOG_CHANGE_HISTORY
|
|
// can be set to trim outlog to protect FRS against members that do not
|
|
// come back.
|
|
// Default: True
|
|
{FRS_CONFIG_SECTION, L"Debug Save Outlog Change History", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
|
|
FKC_SAVE_OUTLOG_CHANGE_HISTORY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// The "Suppress Identical Updates To Files" key controls whether FRS
|
|
// tries to identify and suppress updates that do not change the content
|
|
// (everything that is used to calculate the MD5 and attributes) of the
|
|
// file.
|
|
// Default: True
|
|
{FRS_CONFIG_SECTION, L"Suppress Identical Updates To Files", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
|
|
FKC_SUPPRESS_IDENTICAL_UPDATES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// If true, Install Override tells FRS to attempt to rename an opened
|
|
// target file out of the way in order to allow installation of a new
|
|
// updated version of the file. E.G. an open .exe or .dll file would
|
|
// be treated this way. Normally (i.e. when FALSE) FRS will wait until
|
|
// it can open the target with write access. Install override only works
|
|
// if FRS can open the file for rename. This requires DELETE access to
|
|
// the file so if the target file is currently open with a sharing mode
|
|
// that denies DELETE access to other opens then FRS will not be able to
|
|
// install the updated version until the file is closed.
|
|
// *NOTE* Install Override only applies to files, not directories.
|
|
//
|
|
// Default: FALSE
|
|
{FRS_CONFIG_SECTION, L"Enable Install Override", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_ENABLE_INSTALL_OVERRIDE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
//
|
|
// If true, then remote change orders that update existing files will
|
|
// always use a pre-install file in which to build the content followed
|
|
// by a rename to insert the file into its target location in the replica
|
|
// tree. The benefit is that if FRS runs out of disk space during the
|
|
// install phase or the system crashes then a partial file (or a truncated file)
|
|
// is not left in the tree. The old content is left in place. The
|
|
// drawback of this is the need for enough disk space to hold two copies of
|
|
// the target file.
|
|
// Default: FALSE
|
|
{FRS_CONFIG_SECTION, L"Enable Rename Based File Updates", UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
|
|
FKC_ENABLE_RENAME_BASED_UPDATES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_READ_AT_POLL |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// add ReplDirLevelLimit as a reg key
|
|
// add code support for the following
|
|
|
|
//FKC_SET_N_DIR_EXCL_FILTER_LIST,
|
|
//FKC_SET_N_DIR_INCL_FILTER_LIST,
|
|
//FKC_SET_N_FILE_EXCL_FILTER_LIST,
|
|
//FKC_SET_N_FILE_INCL_FILTER_LIST,
|
|
|
|
//FKC_SET_N_SYSVOL_DIR_EXCL_FILTER_LIST,
|
|
//FKC_SET_N_SYSVOL_DIR_INCL_FILTER_LIST,
|
|
//FKC_SET_N_SYSVOL_FILE_EXCL_FILTER_LIST,
|
|
//FKC_SET_N_SYSVOL_FILE_INCL_FILTER_LIST,
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** P e r - R e p l i c a S e t K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
|
|
#define FRS_RKEY_SETS_SECTION FRS_CONFIG_SECTION L",Replica Sets"
|
|
|
|
#define FRS_RKEY_SET_N FRS_CONFIG_SECTION L",Replica Sets,ARG1"
|
|
|
|
#define FRS_RKEY_CUM_SET_N FRS_CONFIG_SECTION L",Cumulative Replica Sets,ARG1"
|
|
|
|
#define FRS_RKEY_CUM_SET_SECTION FRS_CONFIG_SECTION L",Cumulative Replica Sets"
|
|
|
|
//
|
|
// FRS Sets parameter data. Lives in
|
|
// "System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Replica Sets\\[RS-guid]"
|
|
// Used for sysvols currently.
|
|
//
|
|
// No event log messages are generated for these keys since currently
|
|
// they are only created by the service or NTFRSAPI so if they get
|
|
// fouled up there is nothing the USER can do to correct the problem.
|
|
//
|
|
|
|
// Cumulative Replica Sets *NOTE* This is a key def only.
|
|
{FRS_RKEY_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_SECTION_KEY, 0},
|
|
|
|
// The FRS working dir is where the Jet (ESENT) database is created.
|
|
// Replica Sets\Database Directory
|
|
{FRS_RKEY_SETS_SECTION, JET_PATH, UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
|
|
FKC_SETS_JET_PATH, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK},
|
|
|
|
// Replica Sets\Guid\Replica Set Name
|
|
{FRS_RKEY_SET_N, REPLICA_SET_NAME, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 4, 512, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_NAME, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The root of the replica tree.
|
|
// Replica Sets\Guid\Replica Set Root
|
|
{FRS_RKEY_SET_N, REPLICA_SET_ROOT, UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_ROOT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK},
|
|
|
|
|
|
// The staging area for this replica set.
|
|
// Replica Sets\Guid\Replica Set Stage
|
|
{FRS_RKEY_SET_N, REPLICA_SET_STAGE, UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_STAGE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK},
|
|
|
|
|
|
// The replica set type code. ( SYSVOL, DFS, ...)
|
|
// Replica Sets\Guid\Replica Set Type
|
|
{FRS_RKEY_SET_N, REPLICA_SET_TYPE, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_TYPE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The directory filter exclusion list. Default: None
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_RKEY_SET_N, L"Directory Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The directory filter inclusion list. Default: None
|
|
{FRS_RKEY_SET_N, L"Directory Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The file filter exclusion list.
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_RKEY_SET_N, L"File Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The file filter inclusion list. Default: ~clbcatq.*
|
|
{FRS_RKEY_SET_N, L"File Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
|
|
L"~clbcatq.*",
|
|
FKC_SET_N_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The tombstone state of this replica set.
|
|
// Replica Sets\Guid\Replica Set Tombstoned
|
|
{FRS_RKEY_SET_N, REPLICA_SET_TOMBSTONED, UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_TOMBSTONED, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The operation to perform on the replica set.
|
|
// Replica Sets\Guid\Replica Set Command
|
|
{FRS_RKEY_SET_N, REPLICA_SET_COMMAND, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_COMMAND, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// If TRUE this is the first member of a replica set and we init the DB
|
|
// with the contents of the replica tree.
|
|
// Replica Sets\Guid\Replica Set Primary
|
|
{FRS_RKEY_SET_N, REPLICA_SET_PRIMARY, UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_PRIMARY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// LDAP error Status return if we have a problem creating sysvol.
|
|
// Replica Sets\Guid\Replica Set Status
|
|
{FRS_RKEY_SET_N, REPLICA_SET_STATUS, UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_REPLICA_SET_STATUS, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// Cumulative Replica Sets *NOTE* This is a key def only.
|
|
{FRS_RKEY_CUM_SET_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_CUMSET_SECTION_KEY, 0},
|
|
|
|
|
|
// Number of inbound and outbound partners for this replica set.
|
|
// Cumulative Replica Sets\Guid\Number Of Partners
|
|
{FRS_RKEY_CUM_SET_N, L"Number Of Partners", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_CUMSET_N_NUMBER_OF_PARTNERS, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// Backup / Restore flags for this replica set.
|
|
// Cumulative Replica Sets\Guid\BurFlags
|
|
{FRS_RKEY_CUM_SET_N, FRS_VALUE_BURFLAGS, UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_CUMSET_N_BURFLAGS, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** S y s t e m V o l u m e R e l a t e d K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
|
|
#define FRS_RKEY_SYSVOL_SET_N FRS_CONFIG_SECTION L",SysVol,ARG1"
|
|
#define FRS_RKEY_SYSVOL_SEED_N FRS_CONFIG_SECTION L",SysVol Seeding,ARG1"
|
|
#define FRS_RKEY_SYSVOL_SEEDING_SECTION FRS_CONFIG_SECTION L",SysVol Seeding"
|
|
|
|
|
|
//
|
|
// No event log messages are generated for these keys since currently
|
|
// they are only created by the service or NTFRSAPI so if they get
|
|
// fouled up there is nothing the USER can do to correct the problem.
|
|
//
|
|
|
|
|
|
// TRUE if sysvol is ready. Notifies NetLogon to publish computer as a DC.
|
|
// Netlogon\\Parameters\SysvolReady
|
|
{NETLOGON_SECTION, SYSVOL_READY, UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_READY, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// SysVol Section *NOTE* THis is a key only. It has no value.
|
|
{FRS_SYSVOL_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_SECTION_KEY, 0},
|
|
|
|
|
|
// TRUE if sysvol data is all present in registry.
|
|
// Tells us that DCPromo completed.
|
|
// NtFrs\Parameters\SysVol\SysVol Information is Committed
|
|
{FRS_SYSVOL_SECTION, SYSVOL_INFO_IS_COMMITTED, UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_INFO_COMMITTED, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
//
|
|
// Note that the following keys are a repeat of those in the "Per-Replica
|
|
// set" section above except the Key location in the registry is
|
|
// FRS_CONFIG_SECTION\SysVol instead of FRS_CONFIG_SECTION\Replica Sets
|
|
// unfortunate but something more to clean up later perhaps with a
|
|
// second parameter (ARG2).
|
|
//
|
|
|
|
// SysVol\<Guid>\Replica Set Name
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_NAME, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 4, 512, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_NAME, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The root of the replica tree.
|
|
// SysVol\<Guid>\Replica Set Root
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_ROOT, UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_ROOT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK},
|
|
|
|
|
|
// The staging area for this replica set.
|
|
// SysVol\<Guid>\Replica Set Stage
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_STAGE, UNITS_NONE,
|
|
REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_STAGE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT |
|
|
FRS_RKF_SYNTAX_CHECK},
|
|
|
|
|
|
// The replica set type code. ( SYSVOL, DFS, ...)
|
|
// SysVol\<Guid>\Replica Set Type
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_TYPE, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_TYPE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The directory filter exclusion list. Default: None
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_RKEY_SYSVOL_SET_N, L"Directory Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_SYSVOL_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The directory filter inclusion list. Default: None
|
|
{FRS_RKEY_SYSVOL_SET_N, L"Directory Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_SYSVOL_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The file filter exclusion list.
|
|
// Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
|
|
{FRS_RKEY_SYSVOL_SET_N, L"File Exclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_SET_N_SYSVOL_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The file filter inclusion list. Default: ~clbcatq.*
|
|
{FRS_RKEY_SYSVOL_SET_N, L"File Inclusion Filter List", UNITS_NONE,
|
|
REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
|
|
L"~clbcatq.*",
|
|
FKC_SET_N_SYSVOL_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT |
|
|
FRS_RKF_READ_AT_POLL},
|
|
|
|
|
|
// The operation to perform on the replica set.
|
|
// SysVol\<Guid>\Replica Set Command
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_COMMAND, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_COMMAND, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// The RPC binding string for the parent computer to seed from.
|
|
// SysVol\<Guid>\Replica Set Parent
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_PARENT, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_PARENT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// If TRUE this is the first member of a replica set and we init the DB
|
|
// with the contents of the replica tree.
|
|
// SysVol\<Guid>\Replica Set Primary
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_PRIMARY, UNITS_NONE,
|
|
REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_PRIMARY, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// LDAP error Status return if we have a problem creating sysvol.
|
|
// SysVol\<Guid>\Replica Set Status
|
|
{FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_STATUS, UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SET_N_SYSVOL_STATUS, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
|
|
// The RPC binding string for the parent computer to seed from.
|
|
// SysVol Seeding\ReplicaSetName(ARG1)\Replica Set Parent
|
|
{FRS_RKEY_SYSVOL_SEED_N, REPLICA_SET_PARENT, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_SEEDING_N_PARENT, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// SysVol Seeding\ReplicaSetName(ARG1)\Replica Set Name
|
|
{FRS_RKEY_SYSVOL_SEED_N, REPLICA_SET_NAME, UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_SEEDING_N_RSNAME, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_RANGE_CHECK |
|
|
FRS_RKF_VALUE_MUST_BE_PRESENT},
|
|
|
|
|
|
// SysVol Seeding *NOTE* THis is a key only. It has no value.
|
|
{FRS_RKEY_SYSVOL_SEEDING_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_SYSVOL_SEEDING_SECTION_KEY, 0},
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** E v e n t L o g g i n g C o n f i g K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
#define FRS_RKEY_EVENTLOG EVENTLOG_ROOT L",ARG1"
|
|
|
|
#define FRS_RKEY_EVENTLOG_SOURCE EVENTLOG_ROOT L"," SERVICE_LONG_NAME L",ARG1"
|
|
|
|
// EventLog\File Replication Service\File
|
|
{FRS_RKEY_EVENTLOG, L"File", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
|
|
L"%SystemRoot%\\system32\\config\\NtFrs.Evt",
|
|
FKC_EVENTLOG_FILE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\DisplayNameFile
|
|
{FRS_RKEY_EVENTLOG, L"DisplayNameFile", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
|
|
L"%SystemRoot%\\system32\\els.dll",
|
|
FKC_EVENTLOG_DISPLAY_FILENAME,FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\EventMessageFile
|
|
// EventLog\NTFRS\EventMessageFile
|
|
// Default value: "%SystemRoot%\system32\ntfrsres.dll"
|
|
{FRS_RKEY_EVENTLOG_SOURCE, L"EventMessageFile", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
|
|
DEFAULT_MESSAGE_FILE_PATH,
|
|
FKC_EVENTLOG_EVENT_MSG_FILE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\Sources
|
|
{FRS_RKEY_EVENTLOG, L"Sources", UNITS_NONE,
|
|
REG_MULTI_SZ, DT_UNICODE, 4, 0, 0, EVENT_FRS_NONE,
|
|
(SERVICE_NAME L"\0" SERVICE_LONG_NAME L"\0"),
|
|
FKC_EVENTLOG_SOURCES, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\Retention
|
|
{FRS_RKEY_EVENTLOG, L"Retention", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_EVENTLOG_RETENTION, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\MaxSize
|
|
{FRS_RKEY_EVENTLOG, L"MaxSize", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0x80000, EVENT_FRS_BAD_REG_DATA, NULL,
|
|
FKC_EVENTLOG_MAXSIZE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// EventLog\File Replication Service\DisplayNameID
|
|
{FRS_RKEY_EVENTLOG, L"DisplayNameID", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 259, EVENT_FRS_NONE, NULL,
|
|
FKC_EVENTLOG_DISPLAY_NAMEID, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
// EventLog\File Replication Service\CustomSD
|
|
// CustomSD that is used to protect the FRS log. It is essentially the default SD
|
|
// that is used to protect the custom logs, with "restrict guest access" option.
|
|
// The following permission bits are in use:
|
|
// READ=0x1, WRITE=0x2, CLEAR=0x4, BACKUP=0x20
|
|
//
|
|
// The SD is as follows:
|
|
// Owner/Group = Local system
|
|
// DACL:
|
|
// Deny: Full control, Anonymous
|
|
// Deny: Full control, Domain Guests
|
|
// Allow: Full control, Local system
|
|
// Allow: Read|Clear, Builtin Admins
|
|
// Allow: Backup, Backup operators
|
|
// Allow: Read|Clear, System operators
|
|
// Allow: Read, Everyone
|
|
// Allow: Write, Local service
|
|
// Allow: Write, Network service
|
|
//
|
|
// The resultant string is: O:SYG:SYD:(D;;0x27;;;AN)(D;;0x27;;;DG)(A;;0x27;;;SY)(A;;0x5;;;BA)(A;;0x20;;;BO)(A;;0x5;;;SO)(A;;0x1;;;WD)(A;;0x2;;;LS)(A;;0x2;;;NS)
|
|
|
|
{FRS_RKEY_EVENTLOG, L"CustomSD", UNITS_NONE,
|
|
REG_EXPAND_SZ, DT_UNICODE, 4, 0, 0, EVENT_FRS_NONE,
|
|
L"O:SYG:SYD:(D;;0x27;;;AN)(D;;0x27;;;DG)(A;;0x27;;;SY)(A;;0x5;;;BA)(A;;0x20;;;BO)(A;;0x5;;;SO)(A;;0x1;;;WD)(A;;0x2;;;LS)(A;;0x2;;;NS)",
|
|
FKC_EVENTLOG_CUSTOM_SD,FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
// EventLog\File Replication Service\TypesSupported
|
|
{FRS_RKEY_EVENTLOG_SOURCE, L"TypesSupported", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, FRS_EVENT_TYPES, EVENT_FRS_NONE, NULL,
|
|
FKC_EVENTLOG_TYPES_SUPPORTED, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** F R S A P I A c c e s s C h e c k K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_PERFMON \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_COLLECT_PERFMON_DATA
|
|
|
|
// Access Checks\Get Perfmon Data\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_PERFMON, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCCHK_PERFMON_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Get Perfmon Data\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_PERFMON, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
|
|
FKC_ACCCHK_PERFMON_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_GETDS_POLL \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_GET_DS_POLL
|
|
|
|
// Access Checks\Get Ds Polling Interval\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_GETDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCCHK_GETDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Get Ds Polling Interval\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_GETDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
|
|
FKC_ACCCHK_GETDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_GET_INFO \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_INTERNAL_INFO
|
|
|
|
// Access Checks\Get Internal Information\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_GET_INFO, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCCHK_GET_INFO_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Get Internal Information\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_GET_INFO, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
|
|
FKC_ACCCHK_GET_INFO_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_SETDS_POLL \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_SET_DS_POLL
|
|
|
|
// Access Checks\set Ds Polling Interval\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_SETDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCCHK_SETDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Set Ds Polling Interval\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_SETDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
|
|
FKC_ACCCHK_SETDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_STARTDS_POLL \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_START_DS_POLL
|
|
|
|
// Access Checks\Start Ds Polling\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_STARTDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCCHK_STARTDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Start Ds Polling\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_STARTDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
|
|
FKC_ACCCHK_STARTDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_DCPROMO \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_DCPROMO
|
|
|
|
// Access Checks\dcpromo\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_DCPROMO, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCESS_CHK_DCPROMO_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\dcpromo\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_DCPROMO, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
|
|
FKC_ACCESS_CHK_DCPROMO_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_IS_PATH_REPLICATED \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_IS_PATH_REPLICATED
|
|
|
|
// Access Checks\Is Path Replicated\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_IS_PATH_REPLICATED, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCESS_CHK_IS_PATH_REPLICATED_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Is Path Replicated\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_IS_PATH_REPLICATED, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
|
|
FKC_ACCESS_CHK_IS_PATH_REPLICATED_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
#define FRS_RKEY_ACCCHK_WRITER_COMMANDS \
|
|
FRS_CONFIG_SECTION L",Access Checks," ACK_WRITER_COMMANDS
|
|
|
|
// Access Checks\Writer Commands\Access checks are [Enabled or Disabled]
|
|
{FRS_RKEY_ACCCHK_WRITER_COMMANDS, ACCESS_CHECKS_ARE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
|
|
FKC_ACCESS_CHK_WRITER_COMMANDS_ENABLE, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
// Access Checks\Writer Commands\Access checks require [Full Control or Read]
|
|
{FRS_RKEY_ACCCHK_WRITER_COMMANDS, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
|
|
REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
|
|
ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
|
|
FKC_ACCESS_CHK_WRITER_COMMANDS_RIGHTS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_LOG_EVENT |
|
|
FRS_RKF_CREATE_KEY |
|
|
FRS_RKF_SYNTAX_CHECK |
|
|
FRS_RKF_RANGE_CHECK},
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** F R S B a c k u p / R e s t o r e R e l a t e d K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
|
|
//
|
|
// No event log messages are generated for these keys since currently
|
|
// they are only created by the service or NTFRSAPI so if they get
|
|
// fouled up there is nothing the USER can do to correct the problem.
|
|
//
|
|
|
|
#define FRS_RKEY_BACKUP_STARTUP_SET_N_SECTION FRS_BACKUP_RESTORE_MV_SETS_SECTION L",ARG1"
|
|
|
|
/*
|
|
Used in NtfrsApi.c to pass to backup/restore.
|
|
|
|
#define FRS_NEW_FILES_NOT_TO_BACKUP L"SYSTEM\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup"
|
|
FRS_NEW_FILES_NOT_TO_BACKUP REG_MULTI_SZ key
|
|
|
|
|
|
#define FRS_OLD_FILES_NOT_TO_BACKUP L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FilesNotToBackup"
|
|
FRS_OLD_FILES_NOT_TO_BACKUP REG_MULTI_SZ key
|
|
|
|
*/
|
|
|
|
|
|
// Backup/Restore
|
|
// *NOTE* THis is a key only. It has no value.
|
|
{FRS_BACKUP_RESTORE_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_SECTION_KEY, 0},
|
|
|
|
|
|
// Backup/Restore\\Stop NtFrs from Starting
|
|
// *NOTE* THis is a key only. It has no value.
|
|
{FRS_BACKUP_RESTORE_STOP_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_STOP_SECTION_KEY, 0},
|
|
|
|
|
|
// Backup/Restore\Process at Startup\Replica Sets
|
|
// *NOTE* THis is a key only. It has no value.
|
|
{FRS_BACKUP_RESTORE_MV_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_MV_SETS_SECTION_KEY, 0},
|
|
|
|
|
|
// Backup/Restore\Process at Startup\Cumulative Replica Sets
|
|
// *NOTE* THis is a key only. It has no value.
|
|
{FRS_BACKUP_RESTORE_MV_CUMULATIVE_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_MV_CUMSETS_SECTION_KEY, 0},
|
|
|
|
|
|
// Global Backup / Restore flags.
|
|
// backup/restore\Process at Startup\BurFlags
|
|
{FRS_BACKUP_RESTORE_MV_SECTION, FRS_VALUE_BURFLAGS, UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, NTFRSAPI_BUR_FLAGS_NONE, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_STARTUP_GLOBAL_BURFLAGS, FRS_RKF_READ_AT_START |
|
|
FRS_RKF_OK_TO_USE_DEFAULT},
|
|
|
|
|
|
// Backup / Restore flags for this replica set in "Process at Startup"
|
|
// backup/restore\Process at Startup\Replica Sets\<guid>\BurFlags
|
|
{FRS_RKEY_BACKUP_STARTUP_SET_N_SECTION, FRS_VALUE_BURFLAGS, UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_BKUP_STARTUP_SET_N_BURFLAGS, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*******************************************************************************
|
|
** **
|
|
** F R S P E R F M O N R e l a t e d K e y s **
|
|
** **
|
|
** **
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
//
|
|
// No event log messages are generated for these keys since currently
|
|
// they are only created by the service so if they get
|
|
// fouled up there is nothing the USER can do to correct the problem.
|
|
//
|
|
|
|
//
|
|
// Note: We can't really use thes yet since some of them are in the DLL
|
|
// which doesn't link with this module. Also some are MULTI_SZ which
|
|
// needs more work in CfgRegReadString and writestring.
|
|
|
|
#define FRS_RKEY_REPLICA_SET_PERFMON \
|
|
L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaSet\\Performance"
|
|
|
|
#define FRS_RKEY_REPLICA_SET_PERF_LINKAGE \
|
|
L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaSet\\Linkage"
|
|
|
|
#define FRS_RKEY_CXTION_PERFMON \
|
|
L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaConn\\Performance"
|
|
|
|
|
|
#define FRS_RKEY_CXTION_PERF_LINKAGE \
|
|
L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaConn\\Linkage"
|
|
|
|
|
|
|
|
// FileReplicaSet\\Performance\First Counter
|
|
{FRS_RKEY_REPLICA_SET_PERFMON, L"First Counter", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_SET_FIRST_CTR, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// FileReplicaSet\\Performance\First Help
|
|
{FRS_RKEY_REPLICA_SET_PERFMON, L"First Help", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_SET_FIRST_HELP, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// FileReplicaSet\\Linkage\Export
|
|
{FRS_RKEY_REPLICA_SET_PERF_LINKAGE, L"Export", UNITS_NONE,
|
|
REG_MULTI_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_SET_LINKAGE_EXPORT, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// FileReplicaConn\\Performance\First Counter
|
|
{FRS_RKEY_CXTION_PERFMON, L"First Counter", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_CXTION_FIRST_CTR, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
// FileReplicaConn\\Performance\First Help
|
|
{FRS_RKEY_CXTION_PERFMON, L"First Help", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_CXTION_FIRST_HELP, FRS_RKF_READ_AT_START},
|
|
|
|
// FileReplicaConn\\Linkage\Export
|
|
{FRS_RKEY_CXTION_PERF_LINKAGE, L"Export", UNITS_NONE,
|
|
REG_MULTI_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPLICA_CXTION_LINKAGE_EXPORT, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
|
|
|
|
#define FRS_RKEY_REPARSE_TAG \
|
|
FRS_REPARSE_TAG_SECTION L",ARG1"
|
|
|
|
// Reparse Tag Section *NOTE* THis is a key only. It has no value.
|
|
{FRS_REPARSE_TAG_SECTION, L"*KeyOnly*", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPARSE_TAG_KEY, 0},
|
|
|
|
//
|
|
{FRS_RKEY_REPARSE_TAG, L"Reparse Tag Type", UNITS_NONE,
|
|
REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPARSE_TAG_TYPE, FRS_RKF_READ_AT_START},
|
|
|
|
{FRS_RKEY_REPARSE_TAG, L"Data to Replicate [None or File Data or Reparse Point]", UNITS_NONE,
|
|
REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_REPARSE_TAG_REPLICATION_TYPE, FRS_RKF_READ_AT_START},
|
|
|
|
|
|
{L"End of table", NULL, UNITS_NONE,
|
|
REG_SZ, DT_UNSPECIFIED, 0, 0, 0, EVENT_FRS_NONE, NULL,
|
|
FKC_END_OF_TABLE, 0}
|
|
|
|
|
|
}; // End of FrsRegistryKeyTable
|
|
|
|
|
|
|
|
PFRS_REGISTRY_KEY
|
|
FrsRegFindKeyContext(
|
|
IN FRS_REG_KEY_CODE KeyIndex
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function takes an FRS Registry Key code and returns a pointer to
|
|
the associated key context data.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
Return Value:
|
|
|
|
Ptr to the matching Key context entry or NULL if not found.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "FrsRegFindKeyContext:"
|
|
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
FRS_ASSERT((KeyIndex > 0) && (KeyIndex < FRS_REG_KEY_CODE_MAX));
|
|
|
|
if (KeyIndex >= FRS_REG_KEY_CODE_MAX) {
|
|
return NULL;
|
|
}
|
|
|
|
KeyCtx = FrsRegistryKeyTable;
|
|
|
|
|
|
while (KeyCtx->FrsKeyCode > FKC_END_OF_TABLE) {
|
|
if (KeyIndex == KeyCtx->FrsKeyCode) {
|
|
//
|
|
// Found it.
|
|
//
|
|
return KeyCtx;
|
|
}
|
|
KeyCtx += 1;
|
|
}
|
|
|
|
//
|
|
// Not found.
|
|
//
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PWCHAR
|
|
CfgRegGetValueName(
|
|
IN FRS_REG_KEY_CODE KeyIndex
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns a ptr to the value name string in the key context.
|
|
This is NOT a ptr to an allocated string so it should NOT be freed.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
|
|
Return Value:
|
|
|
|
Ptr to value name string. NULL if KeyIndex lookup fails.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegGetValueName:"
|
|
|
|
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return L"<null>";
|
|
}
|
|
|
|
return KeyCtx->ValueName;
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
FrsRegExpandKeyStr(
|
|
IN PFRS_REGISTRY_KEY Kc,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT PWCHAR *FullKeyStr
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function only expands a key field in the given KeyContext and
|
|
returns the result in FullKeyStr. This is used primarily for error
|
|
messages but is also used to open registry access check keys.
|
|
|
|
The syntax for the the key field in the KeyContext consists of multiple
|
|
key components separated by commas. This function splits the key field on
|
|
the commas. It then opens the leading key followed by either a create or
|
|
open of each successive component. If a component matches the string
|
|
L"ARG1" then we substitute the KeyArg1 parameter passed to this function
|
|
for this key component. Most often this is a stringized guid. For
|
|
example, the string FRS_RKEY_SET_N is defined as:
|
|
|
|
FRS_CONFIG_SECTION L",Replica Sets,ARG1"
|
|
|
|
This will end up opening/creating the following key:
|
|
|
|
"System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\
|
|
Replica Sets\\
|
|
27d6d1c4-d6b8-480b-9f18b5ea390a0178"
|
|
|
|
assuming the argument passed in was "27d6d1c4-d6b8-480b-9f18b5ea390a0178".
|
|
|
|
Arguments:
|
|
|
|
Kc - A ptr to the key context struct for the desired reg key.
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
FullKeyStr - ptr to return buffer for expanded key string.
|
|
NOTE: The buffer is allocated here. Caller must free it.
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the operation.
|
|
FullKeyStr is returned NULL if operation fails.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "FrsRegExpandKeyStr:"
|
|
|
|
UNICODE_STRING TempUStr, FirstArg;
|
|
|
|
PWCHAR FullKey = NULL;
|
|
ULONG Len, FullKeyLen;
|
|
WCHAR KeyStr[MAX_PATH];
|
|
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
*FullKeyStr = NULL;
|
|
|
|
|
|
FullKey = FrsAlloc(FULL_KEY_BUFF_SIZE*sizeof(WCHAR));
|
|
FullKey[0] = UNICODE_NULL;
|
|
FullKeyLen = 1;
|
|
|
|
//
|
|
// If there are any commas in this key then we need to do a nested
|
|
// key open (perhaps creating nested keys as we go). If the key
|
|
// component matches the string L"ARG1" then we use KeyArg1 supplied by
|
|
// the caller.
|
|
//
|
|
RtlInitUnicodeString(&TempUStr, Kc->KeyName);
|
|
|
|
//
|
|
// Parse the comma list.
|
|
//
|
|
while (FrsDissectCommaList(TempUStr, &FirstArg, &TempUStr)) {
|
|
|
|
if ((FirstArg.Length == 0) || (FirstArg.Length >= sizeof(KeyStr))) {
|
|
DPRINT1(0, ":FK: ERROR - Bad keyName in Key contxt %ws\n", Kc->KeyName);
|
|
goto ERROR_RETURN;
|
|
}
|
|
|
|
//
|
|
// null terminate the key component string.
|
|
//
|
|
CopyMemory(KeyStr, FirstArg.Buffer, FirstArg.Length);
|
|
KeyStr[FirstArg.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
//
|
|
// Check the Key Component for a match on ARG1 and substitute.
|
|
//
|
|
if (wcscmp(KeyStr, L"ARG1") == 0) {
|
|
|
|
if (wcslen(KeyArg1)*sizeof(WCHAR) > sizeof(KeyStr)) {
|
|
DPRINT1(0, ":FK: ERROR - ARG1 too big %ws\n", KeyArg1);
|
|
goto ERROR_RETURN;
|
|
}
|
|
wcscpy(KeyStr, KeyArg1);
|
|
}
|
|
|
|
Len = wcslen(KeyStr);
|
|
if (FullKeyLen + Len + 1 > FULL_KEY_BUFF_SIZE) {
|
|
goto ERROR_RETURN;
|
|
}
|
|
|
|
if (FullKeyLen > 1) {
|
|
wcscat(FullKey, L"\\");
|
|
FullKeyLen += 1;
|
|
}
|
|
|
|
wcscat(FullKey, KeyStr);
|
|
FullKeyLen += Len;
|
|
|
|
} // end while()
|
|
|
|
|
|
if (FullKeyLen <= 1) {
|
|
goto ERROR_RETURN;
|
|
}
|
|
|
|
DPRINT1(4, ":FK: Expanded key name is \"%ws\"\n", FullKey);
|
|
|
|
//
|
|
// Return the expanded key to the caller.
|
|
//
|
|
*FullKeyStr = FullKey;
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
ERROR_RETURN:
|
|
|
|
DPRINT1(0, ":FK: ERROR - FrsRegExpandKeyStr Failed on %ws", Kc->KeyName);
|
|
|
|
FrsFree(FullKey);
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
DWORD
|
|
FrsRegOpenKey(
|
|
IN PFRS_REGISTRY_KEY Kc,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT PHKEY hKeyRet
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens a registry key and returns a handle.
|
|
|
|
See FrsRegExpandKeyStr() for a description of the key field syntax.
|
|
|
|
Arguments:
|
|
|
|
Kc - A ptr to the key context struct for the desired reg key.
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
FRS_RKF_KEY_ACCCHK_READ means only do a read access check on the key.
|
|
FRS_RKF_KEY_ACCCHK_WRITE means only do a KEY_ALL_ACCESS access check on the key.
|
|
|
|
if FRS_RKF_CREATE_KEY is set and FRS_RKF_KEY_MUST_BE_PRESENT is clear
|
|
and the given key component is not found, this function creates it.
|
|
|
|
hKeyRet - ptr to HKEY for returned key handle.
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
hKeyRet is returned only on a success.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "FrsRegOpenKey:"
|
|
|
|
UNICODE_STRING TempUStr, FirstArg;
|
|
ULONG WStatus;
|
|
PWCHAR FullKey = NULL;
|
|
|
|
HKEY hKey = HKEY_LOCAL_MACHINE;
|
|
HKEY hKeyParent = INVALID_HANDLE_VALUE;
|
|
|
|
ULONG AccessRights;
|
|
PCHAR AccessName;
|
|
WCHAR KeyStr[MAX_PATH];
|
|
|
|
|
|
|
|
FrsFlagsToStr(Flags, RkfFlagNameTable, sizeof(KeyStr), (PCHAR)KeyStr);
|
|
DPRINT2(4, ":FK: %ws Caller Flags [%s]\n", Kc->ValueName, (PCHAR)KeyStr);
|
|
FrsFlagsToStr(Kc->Flags, RkfFlagNameTable, sizeof(KeyStr), (PCHAR)KeyStr);
|
|
DPRINT2(4, ":FK: %ws KeyCtx Flags [%s]\n", Kc->ValueName, (PCHAR)KeyStr);
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
//
|
|
// If this is a call to make a read or write access check then we must
|
|
// first build the entire key string and then try the open. The
|
|
// caller has done an impersonation.
|
|
//
|
|
if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_ACCCHK_READ |
|
|
FRS_RKF_KEY_ACCCHK_WRITE)) {
|
|
|
|
AccessRights = KEY_READ;
|
|
AccessName = "KEY_READ";
|
|
|
|
if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_ACCCHK_WRITE)) {
|
|
AccessRights = KEY_ALL_ACCESS;
|
|
AccessName = "KEY_ALL_ACCESS";
|
|
}
|
|
|
|
//
|
|
// Expand the key string.
|
|
//
|
|
FrsRegExpandKeyStr(Kc, KeyArg1, Flags, &FullKey);
|
|
if (FullKey == NULL) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
DPRINT2(4, ":FK: Doing Access Check (%s) on key \"%ws\"\n",
|
|
AccessName, FullKey);
|
|
|
|
WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, FullKey, 0, AccessRights, &hKey);
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT1_WS(0, ":FK: ERROR - Access Check failed on %ws;", FullKey, WStatus);
|
|
FrsFree(FullKey);
|
|
return WStatus;
|
|
}
|
|
|
|
//
|
|
// Return the key handle to the caller.
|
|
//
|
|
*hKeyRet = hKey;
|
|
|
|
FrsFree(FullKey);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Not a key access check. Do normal key open processing.
|
|
//
|
|
|
|
//
|
|
// If there are any commas in this key then we need to do a nested
|
|
// key open (perhaps creating nested keys as we go). If the key
|
|
// component matches the string L"ARG1" then we use KeyArg1 supplied by
|
|
// the caller.
|
|
//
|
|
RtlInitUnicodeString(&TempUStr, Kc->KeyName);
|
|
|
|
//
|
|
// Parse the comma list.
|
|
//
|
|
while (FrsDissectCommaList(TempUStr, &FirstArg, &TempUStr)) {
|
|
|
|
if ((FirstArg.Length == 0) || (FirstArg.Length >= sizeof(KeyStr))) {
|
|
DPRINT1(0, ":FK: ERROR - Bad keyName in Key contxt %ws\n", Kc->KeyName);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
goto RETURN;
|
|
}
|
|
|
|
//
|
|
// null terminate the key component string.
|
|
//
|
|
CopyMemory(KeyStr, FirstArg.Buffer, FirstArg.Length);
|
|
KeyStr[FirstArg.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
hKeyParent = hKey;
|
|
hKey = INVALID_HANDLE_VALUE;
|
|
|
|
//
|
|
// Check the Key Component for a match on ARG1 and substitute.
|
|
//
|
|
if (wcscmp(KeyStr, L"ARG1") == 0) {
|
|
|
|
if (wcslen(KeyArg1)*sizeof(WCHAR) > sizeof(KeyStr)) {
|
|
DPRINT1(0, ":FK: ERROR - ARG1 too big %ws\n", KeyArg1);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
goto RETURN;
|
|
}
|
|
wcscpy(KeyStr, KeyArg1);
|
|
}
|
|
|
|
//
|
|
// Open the next key component.
|
|
//
|
|
DPRINT1(5, ":FK: Opening next key component [%ws]\n", KeyStr);
|
|
WStatus = RegOpenKeyEx(hKeyParent, KeyStr, 0, KEY_ALL_ACCESS, &hKey);
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
|
|
//
|
|
// If the key is supposed to be there then return error to caller.
|
|
//
|
|
if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_MUST_BE_PRESENT)) {
|
|
DPRINT1_WS(0, ":FK: Could not open key component [%ws].", KeyStr, WStatus);
|
|
|
|
FrsRegPostEventLog(Kc, KeyArg1, Flags, IDS_REG_KEY_NOT_FOUND);
|
|
goto RETURN;
|
|
}
|
|
|
|
if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_CREATE_KEY)) {
|
|
//
|
|
// Try to create the key.
|
|
//
|
|
DPRINT1(4, ":FK: Creating key component [%ws]\n", KeyStr);
|
|
WStatus = RegCreateKeyW(hKeyParent, KeyStr, &hKey);
|
|
CLEANUP1_WS(0, ":FK: Could not create key component [%ws].",
|
|
KeyStr, WStatus, RETURN);
|
|
} else {
|
|
//
|
|
// Key not there and not supposed to create it. Let caller know.
|
|
//
|
|
goto RETURN;
|
|
}
|
|
}
|
|
|
|
|
|
if (hKeyParent != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKeyParent);
|
|
}
|
|
} // end while()
|
|
|
|
|
|
|
|
//
|
|
// Return the key handle to the caller.
|
|
//
|
|
*hKeyRet = hKey;
|
|
WStatus = ERROR_SUCCESS;
|
|
|
|
|
|
RETURN:
|
|
|
|
if (hKeyParent != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKeyParent);
|
|
}
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT_WS(5, "ERROR - FrsRegOpenKey Failed.", WStatus);
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
}
|
|
|
|
|
|
return WStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegReadDWord(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT PULONG DataRet
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a keyword value from the registry.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
DataRet - ptr to DWORD for returned result.
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
Data is returned only on a success.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegReadDWord:"
|
|
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
DWORD Type;
|
|
DWORD Len;
|
|
DWORD Data;
|
|
BOOL DefaultValueUseOk;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
DefaultValueUseOk = BooleanFlagOn(Flags | KeyCtx->Flags,
|
|
FRS_RKF_OK_TO_USE_DEFAULT);
|
|
|
|
FRS_ASSERT(KeyCtx->ValueName != NULL);
|
|
|
|
DPRINT2(4, ":FK: Reading parameter [%ws] \"%ws\" \n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
|
|
|
|
//
|
|
// Table entry better be REG_DWORD.
|
|
//
|
|
if (KeyCtx->RegValueType != REG_DWORD) {
|
|
DPRINT3(4, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
|
|
|
|
FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_DWORD");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
goto RETURN;
|
|
}
|
|
|
|
//
|
|
// Read the value
|
|
//
|
|
Len = sizeof(Data);
|
|
Type = REG_DWORD;
|
|
WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, (PUCHAR)&Data, &Len);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT_WS(5, "ERROR - RegQueryValueEx Failed.", WStatus);
|
|
|
|
if (WStatus == ERROR_FILE_NOT_FOUND) {
|
|
//
|
|
// If the value is supposed to be there then return error to caller.
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_VALUE_MUST_BE_PRESENT)) {
|
|
DPRINT2_WS(0, ":FK: Value not found [%ws] \"%ws\".",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_NOT_FOUND);
|
|
goto RETURN;
|
|
}
|
|
} else {
|
|
//
|
|
// Check for expected registry datatype if we found a value.
|
|
// Check for buffer size OK. 4 bytes for DWORDs.
|
|
//
|
|
if (WIN_BUF_TOO_SMALL(WStatus) || (Type != REG_DWORD)) {
|
|
DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Type, REG_DWORD);
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
|
|
}
|
|
}
|
|
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
} else {
|
|
|
|
//
|
|
// Found a value, Check type. If wrong, use default.
|
|
//
|
|
if (Type != REG_DWORD) {
|
|
DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Type, REG_DWORD);
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
|
|
if (!WIN_SUCCESS(WStatus) && DefaultValueUseOk) {
|
|
//
|
|
// Not found or wrong type but Ok to use the default value from key context.
|
|
//
|
|
Type = KeyCtx->RegValueType;
|
|
Data = KeyCtx->ValueDefault;
|
|
WStatus = ERROR_SUCCESS;
|
|
DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\".\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
//
|
|
// Only use it once though.
|
|
//
|
|
DefaultValueUseOk = FALSE;
|
|
}
|
|
|
|
|
|
if (WIN_SUCCESS(WStatus)) {
|
|
//
|
|
// Perform syntax check based on data type in KeyCtx->DataValueType?
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_SYNTAX_CHECK)) {
|
|
NOTHING;
|
|
}
|
|
|
|
//
|
|
// Perform Range check? (Applies to default value too)
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK)) {
|
|
|
|
|
|
if ((Data < KeyCtx->ValueMin) || ( Data > KeyCtx->ValueMax)) {
|
|
|
|
DPRINT5(0, ":FK: Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Data,
|
|
KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
|
|
|
|
if (DefaultValueUseOk) {
|
|
//
|
|
// out of range but Ok to use the default value from key context.
|
|
//
|
|
DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\".\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
Type = KeyCtx->RegValueType;
|
|
Data = KeyCtx->ValueDefault;
|
|
WStatus = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Recheck the range.
|
|
//
|
|
if ((Data < KeyCtx->ValueMin) || ( Data > KeyCtx->ValueMax)) {
|
|
DPRINT5(0, ":FK: Default Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Data,
|
|
KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
goto RETURN;
|
|
}
|
|
|
|
} else {
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
goto RETURN;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Data valid and in range. Return it and save it.
|
|
//
|
|
*DataRet = Data;
|
|
|
|
DPRINT3(3, ":FK: [%ws] \"%ws\" = %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Data);
|
|
}
|
|
|
|
|
|
RETURN:
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
|
|
return WStatus;
|
|
|
|
}
|
|
|
|
DWORD
|
|
CfgRegReadString(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT PWSTR *pStrRet
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a keyword string value from the registry. The return
|
|
buffer is allocated here with FrsAlloc(). Caller must free.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
pStrRet - ptr to address of string buffer for returned result else NULL.
|
|
|
|
NOTE: The return buffer is allocated here, caller must free it.
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
Data is returned only on a success.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegReadString:"
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
DWORD Type;
|
|
DWORD Len, NewLen;
|
|
PWCHAR Data, NewData;
|
|
BOOL DefaultValueUseOk;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
WCHAR TStr[4];
|
|
|
|
// add support or new func for REG_MULTI_SZ?
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
Data = NULL;
|
|
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
*pStrRet = NULL;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
DefaultValueUseOk = BooleanFlagOn(Flags | KeyCtx->Flags,
|
|
FRS_RKF_OK_TO_USE_DEFAULT);
|
|
|
|
FRS_ASSERT(KeyCtx->ValueName != NULL);
|
|
|
|
DPRINT2(4, ":FK: Reading parameter [%ws] \"%ws\" \n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
|
|
//
|
|
// Table entry better be some kind of string.
|
|
//
|
|
if ((KeyCtx->RegValueType != REG_SZ) &&
|
|
(KeyCtx->RegValueType != REG_EXPAND_SZ)) {
|
|
DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_SZ or REG_EXPAND_SZ, Found type: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
|
|
// don't return a null ptr since calling parameter may be wrong size.
|
|
FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_SZ or REG_EXPAND_SZ");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pStrRet = NULL;
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
goto RETURN;
|
|
}
|
|
|
|
//
|
|
// Get the size and type for the value.
|
|
//
|
|
WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, NULL, &Len);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT1_WS(5, ":FK: RegQueryValueEx(%ws);", KeyCtx->ValueName, WStatus);
|
|
Len = 0;
|
|
}
|
|
|
|
//
|
|
// If the value is supposed to be there then return error to caller.
|
|
//
|
|
if ((Len == 0) &&
|
|
BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_VALUE_MUST_BE_PRESENT)) {
|
|
DPRINT2_WS(0, ":FK: Value not found [%ws] \"%ws\".",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_NOT_FOUND);
|
|
goto RETURN;
|
|
}
|
|
|
|
if (WIN_SUCCESS(WStatus)) {
|
|
|
|
//
|
|
// Should be a string.
|
|
//
|
|
if ((Type != REG_SZ) && (Type != REG_EXPAND_SZ)) {
|
|
DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Type, KeyCtx->RegValueType);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
|
|
goto CHECK_DEFAULT;
|
|
}
|
|
|
|
//
|
|
// If the string is too long or too short then complain and use default.
|
|
// If KeyCtx->ValueMax is zero then no maximum length check.
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK) &&
|
|
(Len < KeyCtx->ValueMin*sizeof(WCHAR)) ||
|
|
((KeyCtx->ValueMax != 0) && (Len > KeyCtx->ValueMax*sizeof(WCHAR)))) {
|
|
DPRINT4(0, ":FK: String size out of range for [%ws] \"%ws\". Min: %d Max: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
|
|
goto CHECK_DEFAULT;
|
|
}
|
|
|
|
//
|
|
// Alloc the return buffer and read the data.
|
|
//
|
|
Data = (PWCHAR) FrsAlloc (Len+1);
|
|
WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, (PUCHAR)Data, &Len);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT2(0, ":FK: RegQueryValueEx(%ws); WStatus %s\n", KeyCtx->ValueName, ErrLabelW32(WStatus));
|
|
Data = (PWCHAR) FrsFree(Data);
|
|
goto RETURN;
|
|
}
|
|
}
|
|
|
|
|
|
CHECK_DEFAULT:
|
|
|
|
if (!WIN_SUCCESS(WStatus) && DefaultValueUseOk) {
|
|
//
|
|
// Not found or wrong type but Ok to use the default value from key context.
|
|
//
|
|
Data = (PWCHAR) FrsFree(Data);
|
|
if (KeyCtx->StringDefault == NULL) {
|
|
DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\" = NULL\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
goto RETURN;
|
|
}
|
|
Type = KeyCtx->RegValueType;
|
|
Data = FrsWcsDup(KeyCtx->StringDefault);
|
|
|
|
WStatus = ERROR_SUCCESS;
|
|
DPRINT3(4, ":FK: Using internal default value for [%ws] \"%ws\" = %ws\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Data);
|
|
}
|
|
|
|
|
|
if (WIN_SUCCESS(WStatus) && (Data != NULL)) {
|
|
//
|
|
// Perform syntax check based on data type in KeyCtx->DataValueType?
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_SYNTAX_CHECK)) {
|
|
NOTHING;
|
|
}
|
|
|
|
DPRINT3(4, ":FK: [%ws] \"%ws\" = \"%ws\"\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, Data);
|
|
|
|
//
|
|
// Expand system strings if needed
|
|
//
|
|
if (Type == REG_EXPAND_SZ) {
|
|
|
|
NewLen = ExpandEnvironmentStrings(Data, TStr, 0);
|
|
|
|
while (TRUE) {
|
|
NewData = (PWCHAR) FrsAlloc ((NewLen+1) * sizeof(WCHAR));
|
|
|
|
Len = ExpandEnvironmentStrings(Data, NewData, NewLen);
|
|
if (Len == 0) {
|
|
WStatus = GetLastError();
|
|
DPRINT2_WS(5, ":FK: [%ws] \"%ws\" Param not expanded.",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
|
|
Data = FrsFree(Data);
|
|
NewData = FrsFree(NewData);
|
|
break;
|
|
}
|
|
|
|
if (Len <= NewLen) {
|
|
//
|
|
// Free the original buffer and set to return expanded string.
|
|
//
|
|
FrsFree(Data);
|
|
Data = NewData;
|
|
Len = NewLen;
|
|
WStatus = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get a bigger buffer.
|
|
//
|
|
NewData = (PWCHAR) FrsFree(NewData);
|
|
NewLen = Len;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Return ptr to buffer and save a copy for debug printouts.
|
|
//
|
|
*pStrRet = Data;
|
|
|
|
DPRINT3(3, ":FK: [%ws] \"%ws\" = \"%ws\"\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName,
|
|
(Data != NULL) ? Data : L"<null>");
|
|
}
|
|
|
|
//
|
|
// Close the handle if one was opened.
|
|
//
|
|
RETURN:
|
|
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
|
|
return WStatus;
|
|
}
|
|
|
|
#if 0
|
|
// multisz example)
|
|
void
|
|
RegQueryMULTISZ(
|
|
HKEY hkey,
|
|
LPSTR szSubKey,
|
|
LPSTR szValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function queries MULTISZ value in the registry using the
|
|
hkey and szSubKey as the registry key info. If the value is not
|
|
found in the registry, it is added with a zero value.
|
|
|
|
Arguments:
|
|
|
|
hkey - handle to a registry key
|
|
szSubKey - pointer to a subkey string
|
|
|
|
Return Value:
|
|
|
|
registry value
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD rc;
|
|
DWORD len;
|
|
DWORD dwType;
|
|
char buf[1024];
|
|
|
|
len = sizeof(buf);
|
|
rc = RegQueryValueEx( hkey, szSubKey, 0, &dwType, (LPBYTE)buf, &len );
|
|
if (!WIN_SUCCESS(rc)) {
|
|
if (rc == ERROR_FILE_NOT_FOUND) {
|
|
buf[0] = 0;
|
|
buf[1] = 0;
|
|
len = 2;
|
|
RegSetMULTISZ( hkey, szSubKey, buf );
|
|
}
|
|
}
|
|
|
|
CopyMemory( szValue, buf, len );
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegWriteDWord(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
IN ULONG NewData
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a keyword value from the registry.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
FRS_RKF_FORCE_DEFAULT_VALUE - if set then ignore NewData and write the
|
|
default key value from the keyCtx into the registry.
|
|
|
|
NewData - DWORD to write to registry.
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegWriteDWord:"
|
|
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
DWORD Len;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
FRS_ASSERT(KeyCtx->ValueName != NULL);
|
|
|
|
|
|
//
|
|
// Table entry better be REG_DWORD.
|
|
//
|
|
if (KeyCtx->RegValueType != REG_DWORD) {
|
|
DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
|
|
FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_DWORD");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
goto RETURN;
|
|
}
|
|
|
|
//
|
|
// Keep existing value if caller says so.
|
|
//
|
|
if (BooleanFlagOn(Flags, FRS_RKF_KEEP_EXISTING_VALUE)) {
|
|
WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, NULL, NULL, NULL);
|
|
if (WIN_SUCCESS(WStatus)) {
|
|
DPRINT2(4, ":FK: Retaining existing value for parameter [%ws] \"%ws\"\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
goto RETURN;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if we are writing the default value to the registry.
|
|
//
|
|
if (BooleanFlagOn(Flags, FRS_RKF_FORCE_DEFAULT_VALUE)) {
|
|
|
|
NewData = KeyCtx->ValueDefault;
|
|
DPRINT1(4, ":FK: Using internal default value = %d\n", NewData);
|
|
}
|
|
|
|
//
|
|
// Perform Range check? (Applies to default value too)
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags,
|
|
FRS_RKF_RANGE_CHECK | FRS_RKF_RANGE_SATURATE)) {
|
|
|
|
if ((NewData < KeyCtx->ValueMin) || ( NewData > KeyCtx->ValueMax)) {
|
|
|
|
DPRINT5(0, ":FK: Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, NewData,
|
|
KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
|
|
|
|
if (!BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_SATURATE)) {
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
|
|
goto RETURN;
|
|
}
|
|
|
|
//
|
|
// Set the value to either the min or max of the allowed range.
|
|
// WARNING: The only current use of this flag is in setting the
|
|
// DS polling interval. This flag should be used with caution
|
|
// since if a user miss-specifies a parameter and we jam
|
|
// it to the min or max value the resulting effect could be
|
|
// VERY UNDESIREABLE.
|
|
//
|
|
if (NewData < KeyCtx->ValueMin) {
|
|
DPRINT2(4, ":FK: Value (%d) below of range. Using Min value (%d)\n",
|
|
NewData, KeyCtx->ValueMin);
|
|
NewData = KeyCtx->ValueMin;
|
|
} else
|
|
|
|
if (NewData > KeyCtx->ValueMax) {
|
|
DPRINT2(4, ":FK: Value (%d) above of range. Using Max value (%d)\n",
|
|
NewData, KeyCtx->ValueMax);
|
|
NewData = KeyCtx->ValueMax;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Write the value and save it.
|
|
//
|
|
Len = sizeof(NewData);
|
|
WStatus = RegSetValueEx(hKey, KeyCtx->ValueName, 0, REG_DWORD, (PCHAR)&NewData, Len);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT_WS(0, ":FK: ERROR - RegSetValueEx Failed.", WStatus);
|
|
} else {
|
|
DPRINT3(3, ":FK: [%ws] \"%ws\" = %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, NewData);
|
|
}
|
|
|
|
|
|
RETURN:
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
|
|
return WStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegWriteString(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
IN PWSTR NewStr
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a keyword string value from the registry. The return
|
|
buffer is allocated here with FrsAlloc(). Caller must free.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
FRS_RKF_FORCE_DEFAULT_VALUE - if set then ignore NewStr and write the
|
|
default key value from the keyCtx into the registry.
|
|
|
|
NewStr - ptr to buffer for new string data.
|
|
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegWriteString:"
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
DWORD Type;
|
|
DWORD Len, NewLen;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
// add support or new func for REG_MULTI_SZ
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// Table entry better be some kind of string.
|
|
//
|
|
if ((KeyCtx->RegValueType != REG_SZ) &&
|
|
// (KeyCtx->RegValueType != REG_MULTI_SZ) &&
|
|
(KeyCtx->RegValueType != REG_EXPAND_SZ)) {
|
|
DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_SZ or REG_EXPAND_SZ, Found type: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
|
|
FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_SZ or REG_EXPAND_SZ");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
goto RETURN;
|
|
}
|
|
|
|
FRS_ASSERT(KeyCtx->ValueName != NULL);
|
|
|
|
//
|
|
// Keep existing value if caller says so.
|
|
//
|
|
if (BooleanFlagOn(Flags, FRS_RKF_KEEP_EXISTING_VALUE)) {
|
|
WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, NULL, NULL, NULL);
|
|
if (WIN_SUCCESS(WStatus)) {
|
|
DPRINT2(4, ":FK: Retaining existing value for parameter [%ws] \"%ws\"\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
goto RETURN;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if we are writing the default value to the registry.
|
|
//
|
|
if (BooleanFlagOn(Flags, FRS_RKF_FORCE_DEFAULT_VALUE)) {
|
|
if (KeyCtx->StringDefault == NULL) {
|
|
DPRINT2(0, ":FK: ERROR - Key contxt has no default value for [%ws] \"%ws\" \n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
FRS_ASSERT(!"Key contxt has no default value");
|
|
goto RETURN;
|
|
}
|
|
|
|
NewStr = KeyCtx->StringDefault;
|
|
DPRINT1(4, ":FK: Using internal default value = \"%ws\" \n", NewStr);
|
|
}
|
|
|
|
//
|
|
// Perform Range check? (Applies to default value too)
|
|
// If the string is too long or too short then complain and use default.
|
|
// If KeyCtx->ValueMax is zero then no maximum length check.
|
|
//
|
|
// Note: for REG_MULTI_SZ we need to look for double null at end of str
|
|
// or use a unique symbol for the string separator and cvt to \0 before write.
|
|
|
|
Len = (wcslen(NewStr) + 1) * sizeof(WCHAR);
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK) &&
|
|
(Len < KeyCtx->ValueMin*sizeof(WCHAR)) ||
|
|
((KeyCtx->ValueMax != 0) && (Len > KeyCtx->ValueMax*sizeof(WCHAR)))) {
|
|
DPRINT4(0, ":FK: String size out of range for [%ws] \"%ws\". Min: %d Max: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
WStatus = ERROR_INVALID_PARAMETER;
|
|
FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
|
|
goto RETURN;
|
|
}
|
|
|
|
WStatus = RegSetValueEx(hKey,
|
|
KeyCtx->ValueName,
|
|
0,
|
|
KeyCtx->RegValueType,
|
|
(PCHAR)NewStr,
|
|
Len);
|
|
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
DPRINT_WS(0, ":FK: ERROR - RegSetValueEx Failed.", WStatus);
|
|
} else {
|
|
|
|
// note: won't work for MULTI_SZ
|
|
DPRINT3(3, ":FK: [%ws] \"%ws\" = %ws\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName,
|
|
(NewStr != NULL) ? NewStr : L"<null>");
|
|
}
|
|
|
|
#if 0
|
|
// Multi_Sz example
|
|
//
|
|
// Event Message File
|
|
//
|
|
// WStatus = RegSetValueEx(FrsEventLogKey,
|
|
// L"Sources",
|
|
// 0,
|
|
// REG_MULTI_SZ,
|
|
// (PCHAR)(SERVICE_NAME L"\0"
|
|
// SERVICE_LONG_NAME L"\0"),
|
|
// (wcslen(SERVICE_NAME) +
|
|
// wcslen(SERVICE_LONG_NAME) +
|
|
// 3) * sizeof(WCHAR));
|
|
//
|
|
// Another example
|
|
//
|
|
void
|
|
RegSetMULTISZ(
|
|
HKEY hkey,
|
|
LPSTR szSubKey,
|
|
LPSTR szValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function changes a Multi_SZ value in the registry using the
|
|
hkey and szSubKey as the registry key info.
|
|
|
|
Arguments:
|
|
|
|
hkey - handle to a registry key
|
|
szSubKey - pointer to a subkey string
|
|
szValue - new registry value
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i = 1;
|
|
ULONG j = 0;
|
|
LPSTR p = szValue;
|
|
while( TRUE ) {
|
|
j = strlen( p ) + 1;
|
|
i += j;
|
|
p += j;
|
|
if (!*p) {
|
|
break;
|
|
}
|
|
}
|
|
RegSetValueEx( hkey, szSubKey, 0, REG_MULTI_SZ, (PUCHAR)szValue, i );
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// Close the handle if one was opened.
|
|
//
|
|
RETURN:
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
|
|
return WStatus;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegDeleteValue(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function deletes a keyword value from the registry.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegDeleteValue:"
|
|
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
FRS_ASSERT(KeyCtx->ValueName != NULL);
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
goto RETURN;
|
|
}
|
|
|
|
|
|
DPRINT2(3, ":FK: Deleting parameter [%ws] \"%ws\" \n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName);
|
|
|
|
//
|
|
// Delete the value.
|
|
//
|
|
WStatus = RegDeleteValue(hKey, KeyCtx->ValueName);
|
|
DPRINT2_WS(0, ":FK: WARN - Cannot delete key for [%ws] \"%ws\";",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
|
|
|
|
|
|
RETURN:
|
|
|
|
if (hKey != HKEY_LOCAL_MACHINE) {
|
|
FRS_REG_CLOSE(hKey);
|
|
}
|
|
|
|
return WStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegOpenKey(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT HKEY *RethKey
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function Opens the key associated with the entry from the FRS registry
|
|
key context table. It performs the normal substitution, key component
|
|
creation, etc.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
RethKey -- ptr to HKEY to return the key handle. Caller must close the
|
|
key with RegCloseKey().
|
|
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegOpenKey:"
|
|
|
|
|
|
DWORD WStatus;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
FRS_ASSERT(RethKey != NULL);
|
|
|
|
*RethKey = INVALID_HANDLE_VALUE;
|
|
|
|
//
|
|
// Find the key context assoicated with the supplied index.
|
|
//
|
|
KeyCtx = FrsRegFindKeyContext(KeyIndex);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
|
|
if (!WIN_SUCCESS(WStatus)) {
|
|
return WStatus;
|
|
}
|
|
|
|
|
|
DPRINT1(4, ":FK: Registry key opened [%ws]\n", KeyCtx->KeyName);
|
|
|
|
|
|
*RethKey = hKey;
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
CfgRegCheckEnable(
|
|
IN FRS_REG_KEY_CODE KeyIndex,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
OUT PBOOL Enabled,
|
|
OUT PBOOL EnabledAndRequired
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function Opens the key associated with the entry from the FRS registry
|
|
key context table. It performs the normal substitution, key component
|
|
creation, etc. It then checks to see if the data value is "Enabled"
|
|
or "Disabled" and returns the boolean result.
|
|
|
|
Arguments:
|
|
|
|
KeyIndex - An entry from the FRS_REG_KEY_CODE enum
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
Enabled -- ptr to BOOL to return the Enable / Disable state of the key.
|
|
|
|
EnabledAndRequired -- ptr to BOOL to return TRUE if the state is
|
|
"Enabled and Required", FALSE otherwise
|
|
|
|
|
|
Return Value:
|
|
|
|
Win32 status of the result of the registry operation.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegCheckEnable:"
|
|
{
|
|
|
|
ULONG WStatus;
|
|
PWCHAR WStr = NULL;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
|
|
WStatus = CfgRegReadString(KeyIndex, KeyArg1, Flags, &WStr);
|
|
|
|
if ((WStr == NULL) ||
|
|
WSTR_EQ(WStr, FRS_IS_DEFAULT_DISABLED)||
|
|
WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED) ||
|
|
WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED_AND_REQUIRED)
|
|
) {
|
|
//
|
|
// The key is in the default state so we can clobber it with a
|
|
// new default.
|
|
//
|
|
WStatus = CfgRegWriteString(KeyIndex,
|
|
KeyArg1,
|
|
FRS_RKF_FORCE_DEFAULT_VALUE,
|
|
NULL);
|
|
DPRINT1_WS(0, ":FK: WARN - Cannot create Enable key [%ws];",
|
|
CfgRegGetValueName(KeyIndex), WStatus);
|
|
|
|
//
|
|
// Now reread the key for the new default.
|
|
//
|
|
WStr = FrsFree(WStr);
|
|
WStatus = CfgRegReadString(KeyIndex, KeyArg1, Flags, &WStr);
|
|
}
|
|
|
|
if ((WStr != NULL) &&
|
|
(WSTR_EQ(WStr, FRS_IS_ENABLED) ||
|
|
WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED))) {
|
|
*Enabled = TRUE;
|
|
*EnabledAndRequired = FALSE;
|
|
DPRINT1(4, ":FK: %ws is enabled\n", CfgRegGetValueName(KeyIndex));
|
|
} else if ((WStr != NULL) &&
|
|
(WSTR_EQ(WStr, FRS_IS_ENABLED_AND_REQUIRED) ||
|
|
WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED_AND_REQUIRED))) {
|
|
*Enabled = TRUE;
|
|
*EnabledAndRequired = TRUE;
|
|
} else {
|
|
*Enabled = FALSE;
|
|
*EnabledAndRequired = FALSE;
|
|
DPRINT1_WS(0, ":FK: WARN - %ws is not enabled.",
|
|
CfgRegGetValueName(KeyIndex), WStatus);
|
|
}
|
|
|
|
WStr = FrsFree(WStr);
|
|
|
|
return WStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
IsWin2KPro (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check OS version for Win 2000 Professional (aka NT Workstation).
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
True if running on win 2K professional.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "IsWin2KPro:"
|
|
{
|
|
OSVERSIONINFOEX Osvi;
|
|
DWORDLONG ConditionMask = 0;
|
|
|
|
//
|
|
// Initialize the OSVERSIONINFOEX structure.
|
|
//
|
|
ZeroMemory(&Osvi, sizeof(OSVERSIONINFOEX));
|
|
Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
Osvi.dwMajorVersion = 5;
|
|
Osvi.wProductType = VER_NT_WORKSTATION;
|
|
|
|
//
|
|
// Initialize the condition mask.
|
|
//
|
|
VER_SET_CONDITION( ConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
|
|
VER_SET_CONDITION( ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );
|
|
|
|
//
|
|
// Perform the test.
|
|
//
|
|
return VerifyVersionInfo(&Osvi, VER_MAJORVERSION | VER_PRODUCT_TYPE, ConditionMask);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
CfgRegAdjustTuningDefaults(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function walks thru the FrsRegKeyRevisionTable and applies new
|
|
min, max and default values to the specified keys. The objective is
|
|
to reduce the footprint of FRS on the workstation.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegAdjustTuningDefaults:"
|
|
{
|
|
|
|
PFRS_REG_KEY_REVISIONS Rev;
|
|
PFRS_REGISTRY_KEY KeyCtx;
|
|
|
|
Win2kPro = IsWin2KPro();
|
|
|
|
if (!Win2kPro) {
|
|
//
|
|
// Only adjust tunables on a workstation.
|
|
//
|
|
return;
|
|
}
|
|
|
|
Rev = FrsRegKeyRevisionTable;
|
|
|
|
while (Rev->FrsKeyCode != FKC_END_OF_TABLE) {
|
|
|
|
KeyCtx = FrsRegFindKeyContext(Rev->FrsKeyCode);
|
|
if (KeyCtx == NULL) {
|
|
DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n",
|
|
Rev->FrsKeyCode);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Table entry better be REG_DWORD.
|
|
//
|
|
if (KeyCtx->RegValueType != REG_DWORD) {
|
|
DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
|
|
KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Apply the new range and default values from the table.
|
|
//
|
|
KeyCtx->ValueMin = Rev->ValueMin;
|
|
KeyCtx->ValueMax = Rev->ValueMax;
|
|
KeyCtx->ValueDefault = Rev->ValueDefault;
|
|
|
|
Rev += 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#define BACKUP_STAR L"*"
|
|
#define BACKUP_APPEND L"\\* /s"
|
|
VOID
|
|
CfgFilesNotToBackup(
|
|
IN PGEN_TABLE Replicas
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the backup registry key to prevent backing up the jet
|
|
database, staging directories, preinstall directories, ...
|
|
|
|
Set the restore registry key KeysNotToRestore so that
|
|
NtBackup will retain the ntfrs restore keys by moving
|
|
them into the final restored registry.
|
|
|
|
Arguments:
|
|
|
|
Table of replicas
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgFilesNotToBackup:"
|
|
DWORD WStatus;
|
|
PVOID Key;
|
|
PREPLICA Replica;
|
|
PWCHAR MStr = NULL;
|
|
DWORD Size = 0;
|
|
DWORD Idx = 0;
|
|
HKEY HOldBackupKey = INVALID_HANDLE_VALUE;
|
|
HKEY HNewBackupKey = INVALID_HANDLE_VALUE;
|
|
HKEY HKeysNotToRestore = INVALID_HANDLE_VALUE;
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
//
|
|
// "<Jetpath>\* /s"
|
|
//
|
|
FrsAddToMultiString(JetPath, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
|
|
|
|
//
|
|
// "<DebugInfo.LogFile>\NtFrs*" Default: "%SystemRoot%\debug\NtFrs*"
|
|
//
|
|
FrsAddToMultiString(DebugInfo.LogFile, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(NTFRS_DBG_LOG_FILE, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(BACKUP_STAR, &Size, &Idx, &MStr);
|
|
|
|
GTabLockTable(Replicas);
|
|
Key = NULL;
|
|
while (Replica = GTabNextDatumNoLock(Replicas, &Key)) {
|
|
//
|
|
// Ignore tombstoned sets
|
|
//
|
|
if (!IS_TIME_ZERO(Replica->MembershipExpires)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Preinstall directories
|
|
//
|
|
if (Replica->Root) {
|
|
FrsAddToMultiString(Replica->Root, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(NTFRS_PREINSTALL_DIRECTORY, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
|
|
}
|
|
//
|
|
// Preexisting directories
|
|
//
|
|
if (Replica->Root) {
|
|
FrsAddToMultiString(Replica->Root, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(NTFRS_PREEXISTING_DIRECTORY, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
|
|
}
|
|
//
|
|
// Staging directories
|
|
//
|
|
if (Replica->Stage) {
|
|
FrsAddToMultiString(Replica->Stage, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(GENERIC_PREFIX, &Size, &Idx, &MStr);
|
|
FrsCatToMultiString(BACKUP_STAR, &Size, &Idx, &MStr);
|
|
}
|
|
}
|
|
GTabUnLockTable(Replicas);
|
|
|
|
// Note: remove old_files_not_to_backup once existance of new key
|
|
// has been verified.
|
|
//
|
|
// FilesNotToBackup
|
|
// "SOFTWARE\Microsoft\Windows NT\CurrentVersion\FilesNotToBackup"
|
|
//
|
|
WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
FRS_OLD_FILES_NOT_TO_BACKUP,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&HOldBackupKey);
|
|
CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
|
|
FRS_OLD_FILES_NOT_TO_BACKUP, WStatus, NEW_FILES_NOT_TO_BACKUP);
|
|
|
|
//
|
|
// Set the ntfrs multistring value
|
|
//
|
|
WStatus = RegSetValueEx(HOldBackupKey,
|
|
SERVICE_NAME,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(PCHAR)MStr,
|
|
(Idx + 1) * sizeof(WCHAR));
|
|
CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
|
|
FRS_OLD_FILES_NOT_TO_BACKUP, SERVICE_NAME, WStatus, NEW_FILES_NOT_TO_BACKUP);
|
|
|
|
NEW_FILES_NOT_TO_BACKUP:
|
|
//
|
|
// FilesNotToBackup
|
|
// "SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToBackup"
|
|
//
|
|
WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
FRS_NEW_FILES_NOT_TO_BACKUP,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&HNewBackupKey);
|
|
CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
|
|
FRS_NEW_FILES_NOT_TO_BACKUP, WStatus, CLEANUP);
|
|
|
|
//
|
|
// Set the ntfrs multistring value
|
|
//
|
|
WStatus = RegSetValueEx(HNewBackupKey,
|
|
SERVICE_NAME,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(PCHAR)MStr,
|
|
(Idx + 1) * sizeof(WCHAR));
|
|
CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
|
|
FRS_NEW_FILES_NOT_TO_BACKUP, SERVICE_NAME, WStatus, CLEANUP);
|
|
|
|
//
|
|
// KeysNotToRestore
|
|
//
|
|
// Set the restore registry key KeysNotToRestore so that NtBackup will
|
|
// retain the ntfrs restore keys by moving them into the final restored
|
|
// registry.
|
|
//
|
|
// CurrentControlSet\Services\<SERVICE_NAME>\Parameters\Backup/Restore\Process at Startup\"
|
|
//
|
|
|
|
MStr = FrsFree(MStr);
|
|
Size = 0;
|
|
Idx = 0;
|
|
FrsAddToMultiString(FRS_VALUE_FOR_KEYS_NOT_TO_RESTORE, &Size, &Idx, &MStr);
|
|
|
|
//
|
|
// KeysNotToRestore
|
|
// "SYSTEM\CurrentControlSet\Control\BackupRestore\KeysNotToRestore"
|
|
//
|
|
WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
FRS_KEYS_NOT_TO_RESTORE,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&HKeysNotToRestore);
|
|
CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
|
|
FRS_KEYS_NOT_TO_RESTORE, WStatus, CLEANUP);
|
|
|
|
//
|
|
// Set the ntfrs multistring value
|
|
//
|
|
WStatus = RegSetValueEx(HKeysNotToRestore,
|
|
SERVICE_NAME,
|
|
0,
|
|
REG_MULTI_SZ,
|
|
(PCHAR)MStr,
|
|
(Idx + 1) * sizeof(WCHAR));
|
|
CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
|
|
FRS_KEYS_NOT_TO_RESTORE, SERVICE_NAME, WStatus, CLEANUP);
|
|
|
|
//
|
|
// DONE
|
|
//
|
|
WStatus = ERROR_SUCCESS;
|
|
|
|
CLEANUP:
|
|
FRS_REG_CLOSE(HOldBackupKey);
|
|
FRS_REG_CLOSE(HNewBackupKey);
|
|
FRS_REG_CLOSE(HKeysNotToRestore);
|
|
FrsFree(MStr);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
FrsRegPostEventLog(
|
|
IN PFRS_REGISTRY_KEY KeyCtx,
|
|
IN PWCHAR KeyArg1,
|
|
IN ULONG Flags,
|
|
IN LONG IDScode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This Posts an event log message for a problem with a registry key.
|
|
|
|
Arguments:
|
|
|
|
KeyCtx - Ptr to the Key Context struct for this key.
|
|
|
|
KeyArg1 - An optional caller supplied key component. NULL if not provided.
|
|
|
|
Flags - Modifer flags
|
|
|
|
IDSCode - the error message code for a resource string to put in the message.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
#undef DEBSUB
|
|
#define DEBSUB "FrsRegPostEventLog:"
|
|
{
|
|
|
|
#define LEN_DEFAULT_VALUE 48
|
|
#define LEN_RANGE_STR 256
|
|
|
|
PWCHAR ErrorStr, UnitsStr, RangeStrFmt, ValStr, FullKeyStr;
|
|
WCHAR RangeStr[LEN_RANGE_STR];
|
|
|
|
//DPRINT(0, "function entry\n");
|
|
//
|
|
// Are we posting an event log message for this key?
|
|
//
|
|
if (!BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_LOG_EVENT) ||
|
|
(KeyCtx->EventCode == EVENT_FRS_NONE)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Post Eventlog message. Include KeyString, ValueName,
|
|
// MustBePresent, Expected Type, TypeMismatch or not,
|
|
// Value out of range (with range allowed), Default Value Used,
|
|
// regedit instrs to fix the problem,
|
|
//
|
|
UnitsStr = FrsGetResourceStr(XLATE_IDS_UNITS(KeyCtx->Units));
|
|
ErrorStr = FrsGetResourceStr(IDScode);
|
|
|
|
|
|
if (KeyCtx->RegValueType == REG_DWORD) {
|
|
|
|
//
|
|
// Get the range format string from the string resource.
|
|
//
|
|
RangeStrFmt = FrsGetResourceStr(IDS_RANGE_DWORD);
|
|
//
|
|
// Show default value used if default is ok.
|
|
//
|
|
if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_OK_TO_USE_DEFAULT)) {
|
|
ValStr = FrsAlloc(LEN_DEFAULT_VALUE * sizeof(WCHAR));
|
|
_snwprintf(ValStr, LEN_DEFAULT_VALUE, L"%d", KeyCtx->ValueDefault);
|
|
} else {
|
|
ValStr = FrsGetResourceStr(IDS_NO_DEFAULT);
|
|
}
|
|
} else {
|
|
//
|
|
// No default allowed.
|
|
//
|
|
RangeStrFmt = FrsGetResourceStr(IDS_RANGE_STRING);
|
|
ValStr = FrsGetResourceStr(IDS_NO_DEFAULT);
|
|
}
|
|
|
|
//
|
|
// Build the range string.
|
|
//
|
|
_snwprintf(RangeStr, LEN_RANGE_STR, RangeStrFmt, KeyCtx->ValueMin, KeyCtx->ValueMax);
|
|
RangeStr[LEN_RANGE_STR-1] = UNICODE_NULL;
|
|
|
|
//
|
|
// Expand the key string.
|
|
//
|
|
FrsRegExpandKeyStr(KeyCtx, KeyArg1, Flags, &FullKeyStr);
|
|
if (FullKeyStr == NULL) {
|
|
FullKeyStr = FrsWcsDup(KeyCtx->KeyName);
|
|
}
|
|
|
|
//
|
|
// Post the event log message using the keycode in the KeyContext and cleanup.
|
|
//
|
|
if (KeyCtx->EventCode == EVENT_FRS_BAD_REG_DATA) {
|
|
EPRINT9(KeyCtx->EventCode,
|
|
ErrorStr, // %1
|
|
FullKeyStr, // %2
|
|
KeyCtx->ValueName, // %3
|
|
REG_DT_NAME(KeyCtx->RegValueType), // %4
|
|
RangeStr, // %5
|
|
UnitsStr, // %6
|
|
ValStr, // %7
|
|
FullKeyStr, // %8
|
|
KeyCtx->ValueName); // %9
|
|
} else {
|
|
//
|
|
// Don't know this event code but put out something.
|
|
//
|
|
DPRINT1(0, ":FK: ERROR - Unexpected EventCode number (%d). Cannot post message.\n",
|
|
KeyCtx->EventCode);
|
|
}
|
|
|
|
|
|
DPRINT1(0, ":FK: EventCode number : %d\n" , (KeyCtx->EventCode & 0xFFFF));
|
|
DPRINT1(0, ":FK: Error String : %ws\n", ErrorStr);
|
|
DPRINT1(0, ":FK: Key String : %ws\n", FullKeyStr);
|
|
DPRINT1(0, ":FK: Value Name : %ws\n", KeyCtx->ValueName);
|
|
DPRINT1(0, ":FK: Expected Reg Type : %ws\n", REG_DT_NAME(KeyCtx->RegValueType));
|
|
DPRINT1(0, ":FK: Parameter Range : %ws\n", RangeStr);
|
|
DPRINT1(0, ":FK: Parameter units : %ws\n", UnitsStr);
|
|
|
|
FrsFree(ErrorStr);
|
|
FrsFree(RangeStrFmt);
|
|
FrsFree(UnitsStr);
|
|
FrsFree(ValStr);
|
|
FrsFree(FullKeyStr);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
CfgRegReadReparseTagInfo(
|
|
VOID
|
|
)
|
|
{
|
|
#undef DEBSUB
|
|
#define DEBSUB "CfgRegReadReparseTagInfo:"
|
|
|
|
DWORD WStatus = ERROR_SUCCESS;
|
|
HKEY hKey = INVALID_HANDLE_VALUE;
|
|
DWORD Index = 0;
|
|
WCHAR SubKey[MAX_PATH];
|
|
DWORD SubKeySize = MAX_PATH;
|
|
FILETIME LastWriteTime;
|
|
DWORD *ReparseTagType = NULL;
|
|
PREPARSE_TAG_TABLE_ENTRY ReparseTagTableEntry = NULL;
|
|
PREPARSE_TAG_TABLE_ENTRY ExistingEntry = NULL;
|
|
|
|
GTabLockTable(ReparseTagTable);
|
|
|
|
//
|
|
// First clear the data in the table.
|
|
//
|
|
GTabEmptyTableNoLock(ReparseTagTable, FrsFreeType);
|
|
|
|
//
|
|
// Seed the table with the default values.
|
|
//
|
|
ReparseTagType = FrsAlloc(sizeof(DWORD));
|
|
*ReparseTagType = IO_REPARSE_TAG_HSM;
|
|
ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_FILE_DATA) + 1) * sizeof(WCHAR));
|
|
wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_FILE_DATA);
|
|
ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
|
|
FRS_ASSERT(ExistingEntry == NULL);
|
|
|
|
ReparseTagType = FrsAlloc(sizeof(DWORD));
|
|
*ReparseTagType = IO_REPARSE_TAG_SIS;
|
|
ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_FILE_DATA) + 1) * sizeof(WCHAR));
|
|
wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_FILE_DATA);
|
|
ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
|
|
FRS_ASSERT(ExistingEntry == NULL);
|
|
|
|
ReparseTagType = FrsAlloc(sizeof(DWORD));
|
|
*ReparseTagType = IO_REPARSE_TAG_DFS;
|
|
ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_REPARSE_POINT) + 1) * sizeof(WCHAR));
|
|
wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_REPARSE_POINT);
|
|
ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
|
|
FRS_ASSERT(ExistingEntry == NULL);
|
|
|
|
|
|
//
|
|
// Read the info from the registry.
|
|
//
|
|
|
|
WStatus = CfgRegOpenKey(FKC_REPARSE_TAG_KEY, NULL, 0, &hKey);
|
|
CLEANUP_WS(4, "++ WARN - Cannot open reparse tag key.", WStatus, Exit);
|
|
|
|
|
|
while(WStatus == ERROR_SUCCESS) {
|
|
SubKeySize = MAX_PATH;
|
|
|
|
ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, 0);
|
|
|
|
ReparseTagType = FrsAlloc(sizeof(DWORD));
|
|
|
|
WStatus = RegEnumKeyEx(hKey, // handle to key to enumerate
|
|
Index, // subkey index
|
|
SubKey, // subkey name
|
|
&SubKeySize, // size of subkey buffer
|
|
NULL, // reserved
|
|
NULL, // class string buffer
|
|
NULL, // size of class string buffer
|
|
&LastWriteTime // last write time
|
|
);
|
|
|
|
|
|
if(WStatus == ERROR_SUCCESS) {
|
|
WStatus = CfgRegReadDWord(FKC_REPARSE_TAG_TYPE, SubKey, 0, ReparseTagType);
|
|
}
|
|
|
|
|
|
if(WStatus == ERROR_SUCCESS) {
|
|
WStatus = CfgRegReadString(FKC_REPARSE_TAG_REPLICATION_TYPE, SubKey, 0, &(ReparseTagTableEntry->ReplicationType));
|
|
}
|
|
|
|
|
|
if(WStatus == ERROR_SUCCESS){
|
|
ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
|
|
if(ExistingEntry) {
|
|
//
|
|
// There is already an entry for this reparse tag type.
|
|
// Replace it.
|
|
//
|
|
|
|
FrsFree(ExistingEntry->ReplicationType);
|
|
ExistingEntry->ReplicationType = ReparseTagTableEntry->ReplicationType;
|
|
ReparseTagTableEntry->ReplicationType = NULL;
|
|
|
|
//
|
|
// The entry we allocated wasn't used.
|
|
// Free it up.
|
|
//
|
|
FrsFreeType(ReparseTagTableEntry);
|
|
ReparseTagTableEntry = NULL;
|
|
|
|
}
|
|
Index++;
|
|
}
|
|
|
|
ReparseTagTableEntry = NULL;
|
|
ReparseTagType = NULL;
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
GTabUnLockTable(ReparseTagTable);
|
|
|
|
FRS_REG_CLOSE(hKey);
|
|
return WStatus;
|
|
}
|
|
|