Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4140 lines
162 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. GetConfigParam reads a configuration keyword from the registry.
  7. Author:
  8. David Orbits - June-1999 Complete Rewrite to make table driven.
  9. Environment:
  10. Revision History:
  11. --*/
  12. #include <ntreppch.h>
  13. #pragma hdrstop
  14. #include <ctype.h>
  15. #include <frs.h>
  16. #include <ntfrsapi.h>
  17. #define FULL_KEY_BUFF_SIZE 8192
  18. VOID
  19. FrsRegPostEventLog(
  20. IN PFRS_REGISTRY_KEY KeyCtx,
  21. IN PWCHAR KeyArg1,
  22. IN ULONG Flags,
  23. IN LONG IDScode
  24. );
  25. PGEN_TABLE ReparseTagTable;
  26. //
  27. // Possible errors are:
  28. // required key not present
  29. // required value not present
  30. // value out of range
  31. //
  32. // **** NOTE: Also use this for FRS tuning parameters to select between
  33. // workstation and server operation modes. Create a table with a list of the
  34. // parameter codes and override values for the min, max and defaults.
  35. // Apply during startup to reduce server footprint.
  36. //
  37. typedef struct _FRS_REG_KEY_REVISIONS {
  38. LONG FrsKeyCode; // Frs code name for this key.
  39. DWORD ValueMin; // Minimum data value, or string len
  40. DWORD ValueMax; // Maximum Data value, or string len
  41. DWORD ValueDefault; // Default data value if not present.
  42. } FRS_REG_KEY_REVISIONS, *PFRS_REG_KEY_REVISIONS;
  43. FRS_REG_KEY_REVISIONS FrsRegKeyRevisionTable[] = {
  44. {FKC_DEBUG_MAX_LOG , 0 , MAXLONG, 10000 },
  45. {FKC_MAX_REPLICA_THREADS , 2 , 10, 2 },
  46. {FKC_MAX_RPC_SERVER_THREADS , 2 , 10, 2 },
  47. {FKC_MAX_INSTALLCS_THREADS , 2 , 10, 2 },
  48. {FKC_MAX_STAGE_GENCS_THREADS, 2 , 10, 2 },
  49. {FKC_MAX_STAGE_FETCHCS_THREADS, 2 , 10, 2 },
  50. {FKC_MAX_INITSYNCCS_THREADS, 2 , 10, 2 },
  51. {FKC_SNDCS_MAXTHREADS_PAR , 2 , 10, 2 },
  52. {FKC_MAX_NUMBER_REPLICA_SETS, 1 , 10, 5 },
  53. {FKC_MAX_NUMBER_JET_SESSIONS, 1 , 50, 50 },
  54. {FKC_END_OF_TABLE, 0, 0, 0 }
  55. };
  56. //
  57. // See sdk\inc\ntconfig.h if more registry data types are added.
  58. //
  59. #define NUMBER_OF_REG_DATATYPES 12
  60. PWCHAR RegDataTypeNames[NUMBER_OF_REG_DATATYPES] = {
  61. L"REG_NONE" , // ( 0 ) No value type
  62. L"REG_SZ" , // ( 1 ) Unicode nul terminated string
  63. L"REG_EXPAND_SZ" , // ( 2 ) Unicode nul terminated string (with environment variable references)
  64. L"REG_BINARY" , // ( 3 ) Free form binary
  65. L"REG_DWORD" , // ( 4 ) 32-bit number
  66. L"REG_DWORD_BIG_ENDIAN" , // ( 5 ) 32-bit number
  67. L"REG_LINK" , // ( 6 ) Symbolic Link (unicode)
  68. L"REG_MULTI_SZ" , // ( 7 ) Multiple Unicode strings
  69. L"REG_RESOURCE_LIST" , // ( 8 ) Resource list in the resource map
  70. L"REG_FULL_RESOURCE_DESCRIPTOR" , // ( 9 ) Resource list in the hardware description
  71. L"REG_RESOURCE_REQUIREMENTS_LIST" , // ( 10 )
  72. L"REG_QWORD" // ( 11 ) 64-bit number
  73. };
  74. #define REG_DT_NAME(_code_) \
  75. (((_code_) < NUMBER_OF_REG_DATATYPES) ? \
  76. RegDataTypeNames[(_code_)] : RegDataTypeNames[0])
  77. //
  78. //
  79. // If a range check fails the event EVENT_FRS_PARAM_OUT_OF_RANGE is logged if
  80. // FRS_RKF_LOG_EVENT is set.
  81. //
  82. // If a syntax check fails the event EVENT_FRS_PARAM_INVALID_SYNTAX is logged if
  83. // FRS_RKF_LOG_EVENT is set.
  84. //
  85. // If a required parameter is missing the event EVENT_FRS_PARAM_MISSING is logged
  86. // if FRS_RKF_LOG_EVENT is set.
  87. //
  88. BOOL Win2kPro;
  89. FLAG_NAME_TABLE RkfFlagNameTable[] = {
  90. {FRS_RKF_KEY_PRESENT , "KeyPresent " },
  91. {FRS_RKF_VALUE_PRESENT , "ValuePresent " },
  92. {FRS_RKF_DISPLAY_ERROR , "ShowErrorMsg " },
  93. {FRS_RKF_LOG_EVENT , "ShowEventMsg " },
  94. {FRS_RKF_READ_AT_START , "ReadAtStart " },
  95. {FRS_RKF_READ_AT_POLL , "ReadAtPoll " },
  96. {FRS_RKF_RANGE_CHECK , "RangeCheck " },
  97. {FRS_RKF_SYNTAX_CHECK , "SyntaxCheck " },
  98. {FRS_RKF_KEY_MUST_BE_PRESENT , "KeyMustBePresent " },
  99. {FRS_RKF_VALUE_MUST_BE_PRESENT , "ValueMustBePresent " },
  100. {FRS_RKF_OK_TO_USE_DEFAULT , "DefaultOK " },
  101. {FRS_RKF_FORCE_DEFAULT_VALUE , "ForceDefault " },
  102. {FRS_RKF_DEBUG_MODE_ONLY , "DebugMode " },
  103. {FRS_RKF_TEST_MODE_ONLY , "TestMode " },
  104. {FRS_RKF_API_ACCESS_CHECK_KEY , "DoAPIAccessChk " },
  105. {FRS_RKF_CREATE_KEY , "CreateKey " },
  106. {FRS_RKF_KEEP_EXISTING_VALUE , "KeepExistingValue " },
  107. {FRS_RKF_KEY_ACCCHK_READ , "DoReadAccessChk " },
  108. {FRS_RKF_KEY_ACCCHK_WRITE , "DoWriteAccessChk " },
  109. {FRS_RKF_RANGE_SATURATE , "RangeSaturate " },
  110. {FRS_RKF_DEBUG_PARAM , "DisplayAsDebugPar " },
  111. {0, NULL}
  112. };
  113. //
  114. // The following describes the registry keys used by FRS.
  115. // KeyName ValueName DataUnits
  116. // RegValueType DataValueType Min Max Default EventCode
  117. // FrsKeyCode Flags
  118. //
  119. //
  120. // Notation for keyName field. Multiple key components separated by commas.
  121. // Break on commas. Open leading key then create/open each successive component.
  122. // ARG1 means substitute the Arg1 PWSTR parameter passed to the function for this
  123. // key component. Most often this is a stringized guid. The string FRS_RKEY_SET_N
  124. // below will end up opening/creating the following key:
  125. //
  126. // "System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Replica Sets\\27d6d1c4-d6b8-480b-9f18b5ea390a0178"
  127. // assuming the argument passed in was "27d6d1c4-d6b8-480b-9f18b5ea390a0178"
  128. //
  129. // see FrsRegOpenKey() for details.
  130. //
  131. FRS_REGISTRY_KEY FrsRegistryKeyTable[] = {
  132. /******************************************************************************
  133. *******************************************************************************
  134. ** **
  135. ** S e r v i c e D e b u g K e y s **
  136. ** **
  137. ** **
  138. *******************************************************************************
  139. ******************************************************************************/
  140. // Number of assert files
  141. {FRS_CONFIG_SECTION, L"Debug Assert Files", UNITS_NONE,
  142. REG_DWORD, DT_ULONG, 0, 1000, 5, EVENT_FRS_BAD_REG_DATA, NULL,
  143. FKC_DEBUG_ASSERT_FILES, FRS_RKF_READ_AT_START |
  144. FRS_RKF_LOG_EVENT |
  145. FRS_RKF_RANGE_CHECK |
  146. FRS_RKF_DEBUG_PARAM |
  147. FRS_RKF_OK_TO_USE_DEFAULT},
  148. // Force an assert after N seconds (0 == don't assert)
  149. {FRS_CONFIG_SECTION, L"Debug Force Assert in N Seconds", UNITS_SECONDS,
  150. REG_DWORD, DT_ULONG, 0, 1000, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  151. FKC_DEBUG_ASSERT_SECONDS, FRS_RKF_READ_AT_START |
  152. FRS_RKF_LOG_EVENT |
  153. FRS_RKF_RANGE_CHECK |
  154. FRS_RKF_DEBUG_PARAM |
  155. FRS_RKF_OK_TO_USE_DEFAULT |
  156. FRS_RKF_TEST_MODE_ONLY},
  157. // Share for copying log/assert files
  158. {FRS_CONFIG_SECTION, L"Debug Share for Assert Files", UNITS_NONE,
  159. REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  160. FKC_DEBUG_ASSERT_SHARE, FRS_RKF_READ_AT_START |
  161. FRS_RKF_DEBUG_PARAM},
  162. // If TRUE, Break into the debugger, if present
  163. {FRS_CONFIG_SECTION, L"Debug Break", UNITS_NONE,
  164. REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
  165. FKC_DEBUG_BREAK, FRS_RKF_READ_AT_START |
  166. FRS_RKF_READ_AT_POLL |
  167. FRS_RKF_RANGE_CHECK |
  168. FRS_RKF_TEST_MODE_ONLY |
  169. FRS_RKF_DEBUG_PARAM |
  170. FRS_RKF_OK_TO_USE_DEFAULT},
  171. // If TRUE, copy log files into assert share
  172. {FRS_CONFIG_SECTION, L"Debug Copy Log Files into Assert Share", UNITS_NONE,
  173. REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_BAD_REG_DATA, NULL,
  174. FKC_DEBUG_COPY_LOG_FILES, FRS_RKF_READ_AT_START |
  175. FRS_RKF_LOG_EVENT |
  176. FRS_RKF_READ_AT_POLL |
  177. FRS_RKF_RANGE_CHECK |
  178. FRS_RKF_DEBUG_PARAM |
  179. FRS_RKF_OK_TO_USE_DEFAULT},
  180. // Force real out of disk space errors on database operations
  181. {FRS_CONFIG_SECTION, L"Debug Dbs Out Of Space", UNITS_NONE,
  182. REG_DWORD, DT_ULONG, 0, DBG_DBS_OUT_OF_SPACE_OP_MAX, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  183. FKC_DEBUG_DBS_OUT_OF_SPACE, FRS_RKF_READ_AT_START |
  184. FRS_RKF_LOG_EVENT |
  185. FRS_RKF_READ_AT_POLL |
  186. FRS_RKF_TEST_MODE_ONLY |
  187. FRS_RKF_RANGE_CHECK |
  188. FRS_RKF_DEBUG_PARAM |
  189. FRS_RKF_OK_TO_USE_DEFAULT},
  190. // Force Jet Err simulated out of disk space errors on database operations
  191. {FRS_CONFIG_SECTION, L"Debug Dbs Out Of Space Trigger", UNITS_NONE,
  192. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  193. FKC_DEBUG_DBS_OUT_OF_SPACE_TRIGGER, FRS_RKF_READ_AT_START |
  194. FRS_RKF_LOG_EVENT |
  195. FRS_RKF_READ_AT_POLL |
  196. FRS_RKF_TEST_MODE_ONLY |
  197. FRS_RKF_DEBUG_PARAM |
  198. FRS_RKF_OK_TO_USE_DEFAULT},
  199. // If TRUE, debug log file generation (DPRINTS and CO Trace output) is off.
  200. {FRS_CONFIG_SECTION, L"Debug Disable", UNITS_NONE,
  201. REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
  202. FKC_DEBUG_DISABLE, FRS_RKF_READ_AT_START |
  203. FRS_RKF_READ_AT_POLL |
  204. FRS_RKF_RANGE_CHECK |
  205. FRS_RKF_DEBUG_PARAM |
  206. FRS_RKF_OK_TO_USE_DEFAULT},
  207. // The directory path for the FRS debug logs.
  208. {FRS_CONFIG_SECTION, L"Debug Log File", UNITS_NONE,
  209. REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
  210. L"%SystemRoot%\\debug",
  211. FKC_DEBUG_LOG_FILE, FRS_RKF_READ_AT_START |
  212. FRS_RKF_LOG_EVENT |
  213. FRS_RKF_DEBUG_PARAM |
  214. FRS_RKF_SYNTAX_CHECK |
  215. FRS_RKF_OK_TO_USE_DEFAULT},
  216. // Number of debug log files to keep as history
  217. {FRS_CONFIG_SECTION, L"Debug Log Files", UNITS_NONE,
  218. REG_DWORD, DT_ULONG, 0, 300, 5, EVENT_FRS_BAD_REG_DATA, NULL,
  219. FKC_DEBUG_LOG_FILES, FRS_RKF_READ_AT_START |
  220. FRS_RKF_LOG_EVENT |
  221. FRS_RKF_RANGE_CHECK |
  222. FRS_RKF_DEBUG_PARAM |
  223. FRS_RKF_OK_TO_USE_DEFAULT},
  224. // Number of debug log records written between file flushes.
  225. // btw: Severity 0 log records always force a log file flush.
  226. {FRS_CONFIG_SECTION, L"Debug Log Flush Interval", UNITS_NONE,
  227. REG_DWORD, DT_LONG, 1, MAXLONG, 20000, EVENT_FRS_BAD_REG_DATA, NULL,
  228. FKC_DEBUG_LOG_FLUSH_INTERVAL, FRS_RKF_READ_AT_START |
  229. FRS_RKF_LOG_EVENT |
  230. FRS_RKF_RANGE_CHECK |
  231. FRS_RKF_DEBUG_PARAM |
  232. FRS_RKF_OK_TO_USE_DEFAULT},
  233. // Print debug msgs with severity level LE DEBUG_LOG_SEVERITY to debug log.
  234. // 0 - Most severe, eg. fatal inconsistency, mem alloc fail. Least noisey.
  235. // 1 - Important info, eg. Key config parameters, unexpected conditions
  236. // 2 - File tracking records.
  237. // 3 - Change Order Process trace records.
  238. // 4 - Status results, e.g. table lookup failures, new entry inserted
  239. // 5 - Information level messages to show flow. Noisest level. Maybe in a loop
  240. // see also DEBUG_SEVERITY.
  241. {FRS_CONFIG_SECTION, L"Debug Log Severity", UNITS_NONE,
  242. REG_DWORD, DT_ULONG, 0, 5, 2, EVENT_FRS_BAD_REG_DATA, NULL,
  243. FKC_DEBUG_LOG_SEVERITY, FRS_RKF_READ_AT_START |
  244. FRS_RKF_LOG_EVENT |
  245. FRS_RKF_READ_AT_POLL |
  246. FRS_RKF_RANGE_CHECK |
  247. FRS_RKF_DEBUG_PARAM |
  248. FRS_RKF_OK_TO_USE_DEFAULT},
  249. // Max number of debug log messages output before opening a new log file.
  250. {FRS_CONFIG_SECTION, L"Debug Maximum Log Messages", UNITS_NONE,
  251. REG_DWORD, DT_ULONG, 0, MAXLONG, 20000, EVENT_FRS_BAD_REG_DATA, NULL,
  252. FKC_DEBUG_MAX_LOG, FRS_RKF_READ_AT_START |
  253. FRS_RKF_LOG_EVENT |
  254. FRS_RKF_READ_AT_POLL |
  255. FRS_RKF_DEBUG_PARAM |
  256. FRS_RKF_OK_TO_USE_DEFAULT},
  257. // If >0, then track and check all mem alloc / dealloc. (slow)
  258. // 1 - checks allocs and frees and prints stack of unalloced mem at exit
  259. // 2 - checks for mem alloc region overwrite on each alloc/free - very slow.
  260. //
  261. {FRS_CONFIG_SECTION, L"Debug Mem", UNITS_NONE,
  262. REG_DWORD, DT_ULONG, 0, 4, 0, EVENT_FRS_NONE, NULL,
  263. FKC_DEBUG_MEM, FRS_RKF_READ_AT_START |
  264. FRS_RKF_RANGE_CHECK |
  265. FRS_RKF_TEST_MODE_ONLY |
  266. FRS_RKF_DEBUG_PARAM |
  267. FRS_RKF_OK_TO_USE_DEFAULT},
  268. // If TRUE, then call HeapCompact(GetProcessHeap(), 0) on mem dealloc. (slower)
  269. {FRS_CONFIG_SECTION, L"Debug Mem Compact", UNITS_NONE,
  270. REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
  271. FKC_DEBUG_MEM_COMPACT, FRS_RKF_READ_AT_START |
  272. FRS_RKF_READ_AT_POLL |
  273. FRS_RKF_RANGE_CHECK |
  274. FRS_RKF_TEST_MODE_ONLY |
  275. FRS_RKF_DEBUG_PARAM |
  276. FRS_RKF_OK_TO_USE_DEFAULT},
  277. // Mail profile for sending mail notifications. (future)
  278. {FRS_CONFIG_SECTION, L"Debug Profile", UNITS_NONE,
  279. REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  280. FKC_DEBUG_PROFILE, FRS_RKF_READ_AT_START |
  281. FRS_RKF_DEBUG_PARAM |
  282. FRS_RKF_READ_AT_POLL},
  283. // If TRUE, then check consistency of command queues on each queue op. (slow)
  284. {FRS_CONFIG_SECTION, L"Debug Queues", UNITS_NONE,
  285. REG_DWORD, DT_BOOL, FALSE, TRUE, FALSE, EVENT_FRS_NONE, NULL,
  286. FKC_DEBUG_QUEUES, FRS_RKF_READ_AT_START |
  287. FRS_RKF_READ_AT_POLL |
  288. FRS_RKF_RANGE_CHECK |
  289. FRS_RKF_TEST_MODE_ONLY |
  290. FRS_RKF_DEBUG_PARAM |
  291. FRS_RKF_OK_TO_USE_DEFAULT},
  292. // Mail recipients for sending mail notifications. (future)
  293. {FRS_CONFIG_SECTION, L"Debug Recipients", UNITS_NONE,
  294. REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  295. FKC_DEBUG_RECIPIENTS, FRS_RKF_READ_AT_START |
  296. FRS_RKF_DEBUG_PARAM |
  297. FRS_RKF_READ_AT_POLL},
  298. // Restart the service after an assertion failure iff the service was able
  299. // to run for at least DEBUG_RESTART_SECONDS before the assert hit.
  300. {FRS_CONFIG_SECTION, L"Debug Restart if Assert after N Seconds", UNITS_SECONDS,
  301. REG_DWORD, DT_ULONG, 0, MAXLONG, 600, EVENT_FRS_BAD_REG_DATA, NULL,
  302. FKC_DEBUG_RESTART_SECONDS, FRS_RKF_READ_AT_START |
  303. FRS_RKF_READ_AT_POLL |
  304. FRS_RKF_LOG_EVENT |
  305. FRS_RKF_DEBUG_PARAM |
  306. FRS_RKF_OK_TO_USE_DEFAULT},
  307. // Print debug msgs with severity level LE DEBUG_SEVERITY to
  308. // stdout if running as -notservice.
  309. // see also DEBUG_LOG_SEVERITY.
  310. {FRS_CONFIG_SECTION, L"Debug Severity", UNITS_NONE,
  311. REG_DWORD, DT_ULONG, 0, 5, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  312. FKC_DEBUG_SEVERITY, FRS_RKF_READ_AT_START |
  313. FRS_RKF_READ_AT_POLL |
  314. FRS_RKF_LOG_EVENT |
  315. FRS_RKF_RANGE_CHECK |
  316. FRS_RKF_DEBUG_PARAM |
  317. FRS_RKF_OK_TO_USE_DEFAULT},
  318. // If FALSE, Print debug msgs with severity level LE DEBUG_SEVERITY to
  319. // an attached debugger. (slow)
  320. // see also DEBUG_LOG_SEVERITY.
  321. {FRS_CONFIG_SECTION, L"Debug Suppress", UNITS_NONE,
  322. REG_DWORD, DT_BOOL, FALSE, TRUE, TRUE, EVENT_FRS_NONE, NULL,
  323. FKC_DEBUG_SUPPRESS, FRS_RKF_READ_AT_START |
  324. FRS_RKF_READ_AT_POLL |
  325. FRS_RKF_RANGE_CHECK |
  326. FRS_RKF_DEBUG_PARAM |
  327. FRS_RKF_OK_TO_USE_DEFAULT},
  328. // Suppress debug prints from components in the DEBUG_SYSTEMS list.
  329. // default is all components print.
  330. {FRS_CONFIG_SECTION, L"Debug Systems", UNITS_NONE,
  331. REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  332. FKC_DEBUG_SYSTEMS, FRS_RKF_READ_AT_START |
  333. FRS_RKF_DEBUG_PARAM |
  334. FRS_RKF_READ_AT_POLL},
  335. // Test code name for FRS_DEBUG_TEST_POINT macro.
  336. //
  337. {FRS_CONFIG_SECTION, L"Debug Test Code Name", UNITS_NONE,
  338. REG_EXPAND_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  339. FKC_DEBUG_TEST_CODE_NAME, FRS_RKF_READ_AT_START |
  340. FRS_RKF_READ_AT_POLL |
  341. FRS_RKF_DEBUG_PARAM},
  342. // Test sub-code number for FRS_DEBUG_TEST_POINT macro.
  343. //
  344. {FRS_CONFIG_SECTION, L"Debug Test Code Number", UNITS_NONE,
  345. REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
  346. FKC_DEBUG_TEST_CODE_NUMBER, FRS_RKF_READ_AT_START |
  347. FRS_RKF_READ_AT_POLL |
  348. FRS_RKF_DEBUG_PARAM |
  349. FRS_RKF_OK_TO_USE_DEFAULT},
  350. // Initial test trigger count for FRS_DEBUG_TEST_POINT macro.
  351. //
  352. {FRS_CONFIG_SECTION, L"Debug Test Trigger Count", UNITS_NONE,
  353. REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
  354. FKC_DEBUG_TEST_TRIGGER_COUNT, FRS_RKF_READ_AT_START |
  355. FRS_RKF_READ_AT_POLL |
  356. FRS_RKF_DEBUG_PARAM |
  357. FRS_RKF_OK_TO_USE_DEFAULT},
  358. // Test trigger refresh value for FRS_DEBUG_TEST_POINT macro.
  359. //
  360. {FRS_CONFIG_SECTION, L"Debug Test Trigger Refresh", UNITS_NONE,
  361. REG_DWORD, DT_ULONG, 0xFFFFFFFF, 0, 0, EVENT_FRS_NONE, NULL,
  362. FKC_DEBUG_TEST_TRIGGER_REFRESH, FRS_RKF_READ_AT_START |
  363. FRS_RKF_READ_AT_POLL |
  364. FRS_RKF_DEBUG_PARAM |
  365. FRS_RKF_OK_TO_USE_DEFAULT},
  366. // hklm\software\microsoft\windows nt\current version\buildlab
  367. {FRS_CURRENT_VER_SECTION, L"buildlab", UNITS_NONE,
  368. REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  369. FKC_DEBUG_BUILDLAB, FRS_RKF_READ_AT_START |
  370. FRS_RKF_DEBUG_PARAM},
  371. /******************************************************************************
  372. *******************************************************************************
  373. ** **
  374. ** S e r v i c e C o n f i g K e y s **
  375. ** **
  376. ** **
  377. *******************************************************************************
  378. ******************************************************************************/
  379. #define FRS_MUTUAL_AUTHENTICATION_IS \
  380. L"Mutual authentication is [" FRS_IS_ENABLED L" or " FRS_IS_DISABLED L"]"
  381. // Comm Timeout In Milliseconds
  382. // Unjoin the cxtion if the partner doesn't respond soon enough
  383. {FRS_CONFIG_SECTION, L"Comm Timeout In Milliseconds", UNITS_MILLISEC,
  384. REG_DWORD, DT_ULONG, 0, MAXLONG, (5 * 60 * 1000), EVENT_FRS_BAD_REG_DATA, NULL,
  385. FKC_COMM_TIMEOUT, FRS_RKF_READ_AT_START |
  386. FRS_RKF_LOG_EVENT |
  387. FRS_RKF_OK_TO_USE_DEFAULT},
  388. // The directory filter exclusion list. Default: None
  389. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  390. {FRS_CONFIG_SECTION, L"Directory Exclusion Filter List", UNITS_NONE,
  391. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  392. FKC_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  393. FRS_RKF_LOG_EVENT |
  394. FRS_RKF_SYNTAX_CHECK |
  395. FRS_RKF_READ_AT_POLL},
  396. // The directory filter inclusion list. Default: None
  397. {FRS_CONFIG_SECTION, L"Directory Inclusion Filter List", UNITS_NONE,
  398. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  399. FKC_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  400. FRS_RKF_LOG_EVENT |
  401. FRS_RKF_SYNTAX_CHECK |
  402. FRS_RKF_CREATE_KEY |
  403. FRS_RKF_OK_TO_USE_DEFAULT |
  404. FRS_RKF_READ_AT_POLL},
  405. // Minutes between polls of the DS when data does not appear to be changing.
  406. {FRS_CONFIG_SECTION, L"DS Polling Long Interval in Minutes", UNITS_MINUTES,
  407. REG_DWORD, DT_ULONG, NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL,
  408. NTFRSAPI_DEFAULT_LONG_INTERVAL, EVENT_FRS_BAD_REG_DATA, NULL,
  409. FKC_DS_POLLING_LONG_INTERVAL, FRS_RKF_READ_AT_START |
  410. FRS_RKF_READ_AT_POLL |
  411. FRS_RKF_LOG_EVENT |
  412. FRS_RKF_RANGE_CHECK |
  413. FRS_RKF_OK_TO_USE_DEFAULT},
  414. // Minutes between polls of the DS when data does appear to be changing.
  415. // If no data in the DS has changed after 8 (DS_POLLING_MAX_SHORTS) short
  416. // polling intervals then we fall back to DS_POLLING_LONG_INTERVAL.
  417. // Note: if FRS is running on a DC always use the short interval.
  418. {FRS_CONFIG_SECTION, L"DS Polling Short Interval in Minutes", UNITS_MINUTES,
  419. REG_DWORD, DT_ULONG, NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL,
  420. NTFRSAPI_DEFAULT_SHORT_INTERVAL, EVENT_FRS_BAD_REG_DATA, NULL,
  421. FKC_DS_POLLING_SHORT_INTERVAL, FRS_RKF_READ_AT_START |
  422. FRS_RKF_READ_AT_POLL |
  423. FRS_RKF_LOG_EVENT |
  424. FRS_RKF_RANGE_CHECK |
  425. FRS_RKF_OK_TO_USE_DEFAULT},
  426. // Enumerate Directory Buffer Size in Bytes (WHY DO WE NEED THIS???)
  427. {FRS_CONFIG_SECTION, L"Enumerate Directory Buffer Size in Bytes", UNITS_BYTES,
  428. REG_DWORD, DT_ULONG, MINIMUM_ENUMERATE_DIRECTORY_SIZE, 1024*1024, 4*1024, EVENT_FRS_BAD_REG_DATA, NULL,
  429. FKC_ENUMERATE_DIRECTORY_SIZE, FRS_RKF_READ_AT_START |
  430. FRS_RKF_READ_AT_POLL |
  431. FRS_RKF_LOG_EVENT |
  432. FRS_RKF_RANGE_CHECK |
  433. FRS_RKF_OK_TO_USE_DEFAULT},
  434. // The file filter exclusion list.
  435. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  436. {FRS_CONFIG_SECTION, L"File Exclusion Filter List", UNITS_NONE,
  437. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  438. FKC_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  439. FRS_RKF_LOG_EVENT |
  440. FRS_RKF_READ_AT_POLL},
  441. // The file filter inclusion list. Default: L""
  442. {FRS_CONFIG_SECTION, L"File Inclusion Filter List", UNITS_NONE,
  443. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, L"",
  444. FKC_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  445. FRS_RKF_LOG_EVENT |
  446. FRS_RKF_SYNTAX_CHECK |
  447. FRS_RKF_CREATE_KEY |
  448. FRS_RKF_OK_TO_USE_DEFAULT |
  449. FRS_RKF_READ_AT_POLL},
  450. // The name of the FRS eventlog message file.
  451. // Default value: "%SystemRoot%\system32\ntfrsres.dll"
  452. // WHY DO WE NEED TO BE ABLE TO CHANGE THIS???
  453. {FRS_CONFIG_SECTION, L"Message File Path", UNITS_NONE,
  454. REG_EXPAND_SZ, DT_UNICODE, 2, 0, 0, EVENT_FRS_NONE,
  455. DEFAULT_MESSAGE_FILE_PATH,
  456. FKC_FRS_MESSAGE_FILE_PATH, FRS_RKF_READ_AT_START |
  457. FRS_RKF_OK_TO_USE_DEFAULT},
  458. // Mutual authentication is [Enabled or Disabled]
  459. {FRS_CONFIG_SECTION, FRS_MUTUAL_AUTHENTICATION_IS, UNITS_NONE,
  460. REG_SZ, DT_UNICODE, 2, 200, 0, EVENT_FRS_NONE,
  461. FRS_IS_DEFAULT_ENABLED,
  462. FKC_FRS_MUTUAL_AUTHENTICATION_IS, FRS_RKF_READ_AT_START |
  463. FRS_RKF_RANGE_CHECK |
  464. FRS_RKF_VALUE_MUST_BE_PRESENT},
  465. // Maximum Join Retry time In MilliSeconds Default: 1 hr.
  466. {FRS_CONFIG_SECTION, L"Maximum Join Retry In MilliSeconds", UNITS_MILLISEC,
  467. REG_DWORD, DT_ULONG, 30*1000, 10*3600*1000, (60 * 60 * 1000), EVENT_FRS_NONE, NULL,
  468. FKC_MAX_JOIN_RETRY, FRS_RKF_READ_AT_START |
  469. FRS_RKF_READ_AT_POLL |
  470. FRS_RKF_RANGE_CHECK |
  471. FRS_RKF_OK_TO_USE_DEFAULT},
  472. // Maximum Replica Command Server Threads Default: 16
  473. // The replica command server services commands for configuration changes
  474. // and replication.
  475. {FRS_CONFIG_SECTION, L"Maximum Replica Command Server Threads", UNITS_NONE,
  476. REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
  477. FKC_MAX_REPLICA_THREADS, FRS_RKF_READ_AT_START |
  478. FRS_RKF_READ_AT_POLL |
  479. FRS_RKF_RANGE_CHECK |
  480. FRS_RKF_OK_TO_USE_DEFAULT},
  481. // Max Rpc Server Threads Default: 16
  482. // Maximum number of concurrent RPC calls
  483. {FRS_CONFIG_SECTION, L"Max Rpc Server Threads", UNITS_NONE,
  484. REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
  485. FKC_MAX_RPC_SERVER_THREADS, FRS_RKF_READ_AT_START |
  486. FRS_RKF_READ_AT_POLL |
  487. FRS_RKF_RANGE_CHECK |
  488. FRS_RKF_OK_TO_USE_DEFAULT},
  489. // User specified Rpc port assignment Default: 0
  490. //
  491. {FRS_CONFIG_SECTION, L"Rpc TCP/IP Port Assignment", UNITS_NONE,
  492. REG_DWORD, DT_ULONG, 0, 0xffffffff, (0), EVENT_FRS_NONE, NULL,
  493. FKC_RPC_PORT_ASSIGNMENT, FRS_RKF_READ_AT_START |
  494. FRS_RKF_READ_AT_POLL |
  495. FRS_RKF_RANGE_CHECK |
  496. FRS_RKF_OK_TO_USE_DEFAULT},
  497. // Maximum Install Command Server Threads Default: 4
  498. {FRS_CONFIG_SECTION, L"Maximum Install Command Server Threads", UNITS_NONE,
  499. REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
  500. FKC_MAX_INSTALLCS_THREADS, FRS_RKF_READ_AT_START |
  501. FRS_RKF_READ_AT_POLL |
  502. FRS_RKF_RANGE_CHECK |
  503. FRS_RKF_OK_TO_USE_DEFAULT},
  504. // Maximum Stage Gen Command Server Threads Default: 4
  505. {FRS_CONFIG_SECTION, L"Maximum Stage Gen Command Server Threads", UNITS_NONE,
  506. REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
  507. FKC_MAX_STAGE_GENCS_THREADS, FRS_RKF_READ_AT_START |
  508. FRS_RKF_READ_AT_POLL |
  509. FRS_RKF_RANGE_CHECK |
  510. FRS_RKF_OK_TO_USE_DEFAULT},
  511. // Maximum Stage Fetch Command Server Threads Default: 4
  512. {FRS_CONFIG_SECTION, L"Maximum Stage Fetch Command Server Threads", UNITS_NONE,
  513. REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
  514. FKC_MAX_STAGE_FETCHCS_THREADS, FRS_RKF_READ_AT_START |
  515. FRS_RKF_READ_AT_POLL |
  516. FRS_RKF_RANGE_CHECK |
  517. FRS_RKF_OK_TO_USE_DEFAULT},
  518. // Maximum Initial SYnc Command Server Threads Default: 4
  519. {FRS_CONFIG_SECTION, L"Maximum Initial Sync Command Server Threads", UNITS_NONE,
  520. REG_DWORD, DT_ULONG, 2, 200, (4), EVENT_FRS_NONE, NULL,
  521. FKC_MAX_INITSYNCCS_THREADS, FRS_RKF_READ_AT_START |
  522. FRS_RKF_READ_AT_POLL |
  523. FRS_RKF_RANGE_CHECK |
  524. FRS_RKF_OK_TO_USE_DEFAULT},
  525. // Minimum Join Retry time In MilliSeconds Default: 10 sec.
  526. // Retry a join every MinJoinRetry milliseconds, doubling the interval
  527. // every retry. Stop retrying when the interval is greater than MaxJoinRetry.
  528. {FRS_CONFIG_SECTION, L"Minimum Join Retry In MilliSeconds", UNITS_MILLISEC,
  529. REG_DWORD, DT_ULONG, 500, 10*3600*1000, (10 * 1000), EVENT_FRS_NONE, NULL,
  530. FKC_MIN_JOIN_RETRY, FRS_RKF_READ_AT_START |
  531. FRS_RKF_READ_AT_POLL |
  532. FRS_RKF_RANGE_CHECK |
  533. FRS_RKF_OK_TO_USE_DEFAULT},
  534. // Partner Clock Skew In Minutes Default: 30 min.
  535. // Partners are not allowed to join if their clocks are out-of-sync
  536. {FRS_CONFIG_SECTION, L"Partner Clock Skew In Minutes", UNITS_MINUTES,
  537. REG_DWORD, DT_ULONG, 1, 10*60, 30, EVENT_FRS_NONE, NULL,
  538. FKC_PARTNER_CLOCK_SKEW, FRS_RKF_READ_AT_START |
  539. FRS_RKF_READ_AT_POLL |
  540. FRS_RKF_RANGE_CHECK |
  541. FRS_RKF_OK_TO_USE_DEFAULT},
  542. // ChangeOrder Reconcile Event Time Window In Minutes Default: 30 min.
  543. {FRS_CONFIG_SECTION, L"Reconcile Time Window In Minutes", UNITS_MINUTES,
  544. REG_DWORD, DT_ULONG, 1, 120, 30, EVENT_FRS_NONE, NULL,
  545. FKC_RECONCILE_WINDOW, FRS_RKF_READ_AT_START |
  546. FRS_RKF_READ_AT_POLL |
  547. FRS_RKF_RANGE_CHECK |
  548. FRS_RKF_OK_TO_USE_DEFAULT},
  549. // ChangeOrder Inlog retry interval in seconds Default: 60 sec.
  550. {FRS_CONFIG_SECTION, L"Inlog Retry Time In Seconds", UNITS_SECONDS,
  551. REG_DWORD, DT_ULONG, 1, 24*3600, 60, EVENT_FRS_NONE, NULL,
  552. FKC_INLOG_RETRY_TIME, FRS_RKF_READ_AT_START |
  553. FRS_RKF_READ_AT_POLL |
  554. FRS_RKF_RANGE_CHECK |
  555. FRS_RKF_OK_TO_USE_DEFAULT},
  556. // ChangeOrder Aging Delay in seconds Default: 3 sec.
  557. // Should be a min of 3 sec to allow file system tunnel cache info to propagate.
  558. {FRS_CONFIG_SECTION, L"Changeorder Aging Delay In Seconds", UNITS_SECONDS,
  559. REG_DWORD, DT_ULONG, 3, 30*60, 3, EVENT_FRS_NONE, NULL,
  560. FKC_CO_AGING_DELAY, FRS_RKF_READ_AT_START |
  561. FRS_RKF_READ_AT_POLL |
  562. FRS_RKF_RANGE_CHECK |
  563. FRS_RKF_OK_TO_USE_DEFAULT},
  564. // Outlog File Repeat Interval In Seconds Default: 30 sec.
  565. // A CO update for a given file will not be sent out more frequently than this.
  566. // Set to zero to disable the Outlog dominant file update optimization.
  567. {FRS_CONFIG_SECTION, L"Outlog File Repeat Interval In Seconds", UNITS_SECONDS,
  568. REG_DWORD, DT_ULONG, 0, 24*3600, 30, EVENT_FRS_NONE, NULL,
  569. FKC_OUTLOG_REPEAT_INTERVAL, FRS_RKF_READ_AT_START |
  570. FRS_RKF_READ_AT_POLL |
  571. FRS_RKF_RANGE_CHECK |
  572. FRS_RKF_OK_TO_USE_DEFAULT},
  573. // Sysvol Promotion Timeout In Milliseconds Default: 10 min.
  574. {FRS_CONFIG_SECTION, L"Sysvol Promotion Timeout In Milliseconds", UNITS_MILLISEC,
  575. REG_DWORD, DT_ULONG, 0, 3600*1000, (10 * 60 * 1000), EVENT_FRS_NONE, NULL,
  576. FKC_PROMOTION_TIMEOUT, FRS_RKF_READ_AT_START |
  577. FRS_RKF_READ_AT_POLL |
  578. FRS_RKF_RANGE_CHECK |
  579. FRS_RKF_OK_TO_USE_DEFAULT},
  580. // Replica Start Timeout In MilliSeconds Default: 0 means can't start without DS.
  581. // Start replication even if the DS could not be accessed
  582. // 0: no DS == no start replicas
  583. // N: start replicas in N milliseconds
  584. {FRS_CONFIG_SECTION, L"Replica Start Timeout In MilliSeconds", UNITS_MILLISEC,
  585. REG_DWORD, DT_ULONG, 0, 3600*1000, (0), EVENT_FRS_NONE, NULL,
  586. FKC_REPLICA_START_TIMEOUT, FRS_RKF_READ_AT_START |
  587. FRS_RKF_READ_AT_POLL |
  588. FRS_RKF_RANGE_CHECK |
  589. FRS_RKF_OK_TO_USE_DEFAULT},
  590. // Replica Tombstone in Days Default: 32
  591. // The length of time we will hold onto the database state for a replica
  592. // set after we see our membership in the DS has been deleted. Since
  593. // delete is not explicit (except for DC Demote) it may just be that the
  594. // DC is missing our objects or an admin erroneously deleted our subscriber
  595. // or member object. Once this time has lapsed we will delete the tables
  596. // from the database.
  597. {FRS_CONFIG_SECTION, L"Replica Tombstone in Days", UNITS_DAYS,
  598. REG_DWORD, DT_ULONG, 3, MAXLONG, (32), EVENT_FRS_NONE, NULL,
  599. FKC_REPLICA_TOMBSTONE, FRS_RKF_READ_AT_START |
  600. FRS_RKF_READ_AT_POLL |
  601. FRS_RKF_RANGE_CHECK |
  602. FRS_RKF_OK_TO_USE_DEFAULT},
  603. // Shutdown Timeout in Seconds Default: 90 sec.
  604. // The max time FRS main will wait for all threads to exit during shutdown.
  605. {FRS_CONFIG_SECTION, L"Shutdown Timeout in Seconds", UNITS_SECONDS,
  606. REG_DWORD, DT_ULONG, 30, 24*60*60, DEFAULT_SHUTDOWN_TIMEOUT, EVENT_FRS_NONE, NULL,
  607. FKC_SHUTDOWN_TIMEOUT, FRS_RKF_READ_AT_START |
  608. FRS_RKF_READ_AT_POLL |
  609. FRS_RKF_RANGE_CHECK |
  610. FRS_RKF_OK_TO_USE_DEFAULT},
  611. // Maximum Send Command Server Threads Default: 16
  612. {FRS_CONFIG_SECTION, L"Maximum Send Command Server Threads", UNITS_NONE,
  613. REG_DWORD, DT_ULONG, 2, 200, (16), EVENT_FRS_NONE, NULL,
  614. FKC_SNDCS_MAXTHREADS_PAR, FRS_RKF_READ_AT_START |
  615. FRS_RKF_READ_AT_POLL |
  616. FRS_RKF_RANGE_CHECK |
  617. FRS_RKF_OK_TO_USE_DEFAULT},
  618. // Staging Space Limit in KB Default: 660 MB
  619. {FRS_CONFIG_SECTION, L"Staging Space Limit in KB", UNITS_KBYTES,
  620. REG_DWORD, DT_ULONG, 10*1024, MAXLONG, (660 * 1024), EVENT_FRS_BAD_REG_DATA, NULL,
  621. FKC_STAGING_LIMIT, FRS_RKF_READ_AT_START |
  622. FRS_RKF_RANGE_CHECK |
  623. FRS_RKF_OK_TO_USE_DEFAULT |
  624. FRS_RKF_LOG_EVENT},
  625. // VvJoin Limit in Change Orders Default: 16 ChangeOrders
  626. // Max number of VVJoin gened COs to prevent flooding.
  627. {FRS_CONFIG_SECTION, L"VvJoin Limit in Change Orders", UNITS_NONE,
  628. REG_DWORD, DT_ULONG, 2, 128, (16), EVENT_FRS_NONE, NULL,
  629. FKC_VVJOIN_LIMIT, FRS_RKF_READ_AT_START |
  630. FRS_RKF_READ_AT_POLL |
  631. FRS_RKF_RANGE_CHECK |
  632. FRS_RKF_OK_TO_USE_DEFAULT},
  633. // VVJoin Outbound Log Throttle Timeout Default: 1 sec.
  634. // The time FRS VVJoin thread waits after generating VVJOIN_LIMIT COs.
  635. {FRS_CONFIG_SECTION, L"VvJoin Timeout in Milliseconds", UNITS_MILLISEC,
  636. REG_DWORD, DT_ULONG, 100, 10*60*1000, (1000), EVENT_FRS_NONE, NULL,
  637. FKC_VVJOIN_TIMEOUT, FRS_RKF_READ_AT_START |
  638. FRS_RKF_READ_AT_POLL |
  639. FRS_RKF_RANGE_CHECK |
  640. FRS_RKF_OK_TO_USE_DEFAULT},
  641. // The FRS working dir is where the Jet (ESENT) database is created.
  642. // If this dir does not exist or can't be created FRS will fail to startup.
  643. {FRS_CONFIG_SECTION, L"Working Directory", UNITS_NONE,
  644. REG_SZ, DT_DIR_PATH, 4, 10*(MAX_PATH+1), 4, EVENT_FRS_BAD_REG_DATA, NULL,
  645. FKC_WORKING_DIRECTORY, FRS_RKF_READ_AT_START |
  646. FRS_RKF_RANGE_CHECK |
  647. FRS_RKF_VALUE_MUST_BE_PRESENT |
  648. FRS_RKF_SYNTAX_CHECK |
  649. FRS_RKF_LOG_EVENT },
  650. // The FRS Log File Directory allows the Jet Logs to created on a different volume.
  651. // By default they are placed in a Log subdir under the "Working Directory".
  652. // If this dir does not exist or can't be created FRS will fail to startup.
  653. {FRS_CONFIG_SECTION, L"DB Log File Directory", UNITS_NONE,
  654. REG_SZ, DT_DIR_PATH, 4, 10*(MAX_PATH+1), 4, EVENT_FRS_BAD_REG_DATA, NULL,
  655. FKC_DBLOG_DIRECTORY, FRS_RKF_READ_AT_START |
  656. FRS_RKF_RANGE_CHECK |
  657. FRS_RKF_SYNTAX_CHECK |
  658. FRS_RKF_LOG_EVENT },
  659. // Ntfs Journal size in MB Default: 128 Meg
  660. {FRS_CONFIG_SECTION, L"Ntfs Journal size in MB", UNITS_MBYTES,
  661. REG_DWORD, DT_ULONG, 4, 10000, (128), EVENT_FRS_BAD_REG_DATA, NULL,
  662. FKC_NTFS_JRNL_SIZE, FRS_RKF_READ_AT_START |
  663. FRS_RKF_LOG_EVENT |
  664. FRS_RKF_RANGE_CHECK |
  665. FRS_RKF_OK_TO_USE_DEFAULT},
  666. // Maximum Number of Replica Sets Default: 200.
  667. {FRS_CONFIG_SECTION, L"Maximum Number of Replica Sets", UNITS_NONE,
  668. REG_DWORD, DT_ULONG, 1, 5000, (200), EVENT_FRS_BAD_REG_DATA, NULL,
  669. FKC_MAX_NUMBER_REPLICA_SETS, FRS_RKF_READ_AT_START |
  670. FRS_RKF_LOG_EVENT |
  671. FRS_RKF_RANGE_CHECK |
  672. FRS_RKF_OK_TO_USE_DEFAULT},
  673. // Maximum Number of Jet Sessions Default: 128.
  674. {FRS_CONFIG_SECTION, L"Maximum Number of Jet Sessions", UNITS_NONE,
  675. REG_DWORD, DT_ULONG, 1, 5000, (128), EVENT_FRS_BAD_REG_DATA, NULL,
  676. FKC_MAX_NUMBER_JET_SESSIONS, FRS_RKF_READ_AT_START |
  677. FRS_RKF_LOG_EVENT |
  678. FRS_RKF_RANGE_CHECK |
  679. FRS_RKF_OK_TO_USE_DEFAULT},
  680. // Maximum Number of outstanding CO's per outbound connection. Default: 8.
  681. {FRS_CONFIG_SECTION, L"Max Num Outbound COs Per Connection", UNITS_NONE,
  682. REG_DWORD, DT_ULONG, 1, 100, (8), EVENT_FRS_BAD_REG_DATA, NULL,
  683. FKC_OUT_LOG_CO_QUOTA, FRS_RKF_READ_AT_START |
  684. FRS_RKF_LOG_EVENT |
  685. FRS_RKF_RANGE_CHECK |
  686. FRS_RKF_OK_TO_USE_DEFAULT},
  687. // If TRUE, Preserve OIDs on files whenever possible Default: False
  688. // -- See Bug 352250 for why this is a risky thing to do.
  689. {FRS_CONFIG_SECTION, L"Preserve File OID", UNITS_NONE,
  690. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  691. FKC_PRESERVE_FILE_OID, FRS_RKF_READ_AT_START |
  692. FRS_RKF_READ_AT_POLL |
  693. FRS_RKF_RANGE_CHECK |
  694. FRS_RKF_OK_TO_USE_DEFAULT},
  695. //
  696. // Disable compression support. Need a non-auth restore to
  697. // make sure we don't have any old compressed staging files
  698. // when this key is turned on. Default: True
  699. //
  700. {FRS_CONFIG_SECTION, L"Debug Disable Compression", UNITS_NONE,
  701. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  702. FKC_DEBUG_DISABLE_COMPRESSION, FRS_RKF_READ_AT_START |
  703. FRS_RKF_RANGE_CHECK |
  704. FRS_RKF_OK_TO_USE_DEFAULT},
  705. //
  706. // Compress staging files for local changes. Set to FALSE to disable.
  707. // This member will continue to install and propagate compressed files.
  708. // This is useful if the customer has content that originates on this member
  709. // which is either already compressed or doesn't compress well.
  710. // Default: True
  711. {FRS_CONFIG_SECTION, L"Compress Staging Files", UNITS_NONE,
  712. REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
  713. FKC_COMPRESS_STAGING_FILES, FRS_RKF_READ_AT_START |
  714. FRS_RKF_RANGE_CHECK |
  715. FRS_RKF_OK_TO_USE_DEFAULT},
  716. //
  717. // This controls automatic reclaim of staging space by using an
  718. // LRU algorithm. Default: True
  719. //
  720. {FRS_CONFIG_SECTION, L"Reclaim Staging Space", UNITS_NONE,
  721. REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
  722. FKC_RECLAIM_STAGING_SPACE, FRS_RKF_READ_AT_START |
  723. FRS_RKF_READ_AT_POLL |
  724. FRS_RKF_RANGE_CHECK |
  725. FRS_RKF_OK_TO_USE_DEFAULT},
  726. //
  727. // Client side ldap search timeout value. Default: 10 minutes.
  728. //
  729. {FRS_CONFIG_SECTION, L"Ldap Search Timeout In Minutes", UNITS_MINUTES,
  730. REG_DWORD, DT_ULONG, 1, 120, (10), EVENT_FRS_BAD_REG_DATA, NULL,
  731. FKC_LDAP_SEARCH_TIMEOUT_IN_MINUTES, FRS_RKF_READ_AT_START |
  732. FRS_RKF_LOG_EVENT |
  733. FRS_RKF_RANGE_CHECK |
  734. FRS_RKF_OK_TO_USE_DEFAULT},
  735. //
  736. // Client side ldap_connect timeout value. Default: 30 seconds.
  737. //
  738. {FRS_CONFIG_SECTION, L"Ldap Bind Timeout In Seconds", UNITS_SECONDS,
  739. REG_DWORD, DT_ULONG, 2, MAXLONG, (30), EVENT_FRS_BAD_REG_DATA, NULL,
  740. FKC_LDAP_BIND_TIMEOUT_IN_SECONDS, FRS_RKF_READ_AT_START |
  741. FRS_RKF_LOG_EVENT |
  742. FRS_RKF_RANGE_CHECK |
  743. FRS_RKF_OK_TO_USE_DEFAULT},
  744. //
  745. // The length of time we retry a change order before aborting it.
  746. // e.g. A file create waiting for the create of a parent dir that
  747. // never comes. Default: 7 days
  748. //
  749. {FRS_CONFIG_SECTION, L"Maximum CO Retry Timeout in Minutes", UNITS_MINUTES,
  750. REG_DWORD, DT_ULONG, 1, 525600, (10080), EVENT_FRS_BAD_REG_DATA, NULL,
  751. FKC_MAX_CO_RETRY_TIMEOUT_MINUTES, FRS_RKF_READ_AT_START |
  752. FRS_RKF_READ_AT_POLL |
  753. FRS_RKF_LOG_EVENT |
  754. FRS_RKF_RANGE_CHECK |
  755. FRS_RKF_OK_TO_USE_DEFAULT},
  756. //
  757. // The number of retries applied to a change order before aborting it.
  758. // e.g. A file create waiting for the create of a parent dir that
  759. // never comes. Default: 3000
  760. //
  761. {FRS_CONFIG_SECTION, L"Maximum CO Retry Count", UNITS_NONE,
  762. REG_DWORD, DT_ULONG, 2, MAXLONG, (3000), EVENT_FRS_BAD_REG_DATA, NULL,
  763. FKC_MAX_CO_RETRY_TIMEOUT_COUNT, FRS_RKF_READ_AT_START |
  764. FRS_RKF_READ_AT_POLL |
  765. FRS_RKF_LOG_EVENT |
  766. FRS_RKF_RANGE_CHECK |
  767. FRS_RKF_OK_TO_USE_DEFAULT},
  768. //
  769. // Enable automatic restore on journal wrap or journal recreation.
  770. // This occurs when the replica set gets into either state
  771. // REPLICA_STATE_JRNL_WRAP_ERROR or REPLICA_STATE_MISMATCHED_JOURNAL_ID.
  772. // The default is FALSE because a non-auth restore will move the replica
  773. // tree to the pre-existing dir and make the files unavailable on a DFS
  774. // alternate. Customers did not like this.
  775. //
  776. {FRS_CONFIG_SECTION, L"Enable Journal Wrap Automatic Restore", UNITS_NONE,
  777. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  778. FKC_ENABLE_JOURNAL_WRAP_AUTOMATIC_RESTORE, FRS_RKF_READ_AT_START |
  779. FRS_RKF_READ_AT_POLL |
  780. FRS_RKF_RANGE_CHECK |
  781. FRS_RKF_OK_TO_USE_DEFAULT},
  782. //
  783. // If True then hold the ReplicaList lock for the duration of an outlog cleanup
  784. // cycle (which could be many minutes). If False then don't hold the lock.
  785. //
  786. {FRS_CONFIG_SECTION, L"Enable Locked Outlog Cleanup", UNITS_NONE,
  787. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  788. FKC_LOCKED_OUTLOG_CLEANUP, FRS_RKF_READ_AT_START |
  789. FRS_RKF_RANGE_CHECK |
  790. FRS_RKF_OK_TO_USE_DEFAULT},
  791. //
  792. // This controls how long the change orders will stay in the outlog.
  793. // Change orders are kept in the outlog to satisfy future vvjoins
  794. // without having to scan the idtable. Default: 1 week.
  795. //
  796. {FRS_CONFIG_SECTION, L"Outlog Change History In Minutes", UNITS_MINUTES,
  797. REG_DWORD, DT_ULONG, 1, MAXLONG, (10080), EVENT_FRS_NONE, NULL,
  798. FKC_OUTLOG_CHANGE_HISTORY, FRS_RKF_READ_AT_START |
  799. FRS_RKF_READ_AT_POLL |
  800. FRS_RKF_RANGE_CHECK |
  801. FRS_RKF_OK_TO_USE_DEFAULT},
  802. //
  803. // This controls how long whether COs in the outlog even after they have
  804. // been ACK ed by all the partners. The longer the COs stay in the outlog
  805. // the greater the chances of avoiding complete vvjoins. The period is
  806. // controlled by the FKC_OUTLOG_CHANGE_HISTORY key above. The
  807. // FKC_SAVE_OUTLOG_CHANGE_HISTORY turns this feature off. Turn this off in
  808. // cases where the outlog is getting very large. Even when
  809. // FKC_SAVE_OUTLOG_CHANGE_HISTORY is turned off FKC_OUTLOG_CHANGE_HISTORY
  810. // can be set to trim outlog to protect FRS against members that do not
  811. // come back.
  812. // Default: True
  813. {FRS_CONFIG_SECTION, L"Debug Save Outlog Change History", UNITS_NONE,
  814. REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
  815. FKC_SAVE_OUTLOG_CHANGE_HISTORY, FRS_RKF_READ_AT_START |
  816. FRS_RKF_READ_AT_POLL |
  817. FRS_RKF_RANGE_CHECK |
  818. FRS_RKF_OK_TO_USE_DEFAULT},
  819. //
  820. // The "Suppress Identical Updates To Files" key controls whether FRS
  821. // tries to identify and suppress updates that do not change the content
  822. // (everything that is used to calculate the MD5 and attributes) of the
  823. // file.
  824. // Default: True
  825. {FRS_CONFIG_SECTION, L"Suppress Identical Updates To Files", UNITS_NONE,
  826. REG_DWORD, DT_BOOL, FALSE, TRUE, (TRUE), EVENT_FRS_NONE, NULL,
  827. FKC_SUPPRESS_IDENTICAL_UPDATES, FRS_RKF_READ_AT_START |
  828. FRS_RKF_READ_AT_POLL |
  829. FRS_RKF_RANGE_CHECK |
  830. FRS_RKF_OK_TO_USE_DEFAULT},
  831. //
  832. // If true, Install Override tells FRS to attempt to rename an opened
  833. // target file out of the way in order to allow installation of a new
  834. // updated version of the file. E.G. an open .exe or .dll file would
  835. // be treated this way. Normally (i.e. when FALSE) FRS will wait until
  836. // it can open the target with write access. Install override only works
  837. // if FRS can open the file for rename. This requires DELETE access to
  838. // the file so if the target file is currently open with a sharing mode
  839. // that denies DELETE access to other opens then FRS will not be able to
  840. // install the updated version until the file is closed.
  841. // *NOTE* Install Override only applies to files, not directories.
  842. //
  843. // Default: FALSE
  844. {FRS_CONFIG_SECTION, L"Enable Install Override", UNITS_NONE,
  845. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  846. FKC_ENABLE_INSTALL_OVERRIDE, FRS_RKF_READ_AT_START |
  847. FRS_RKF_READ_AT_POLL |
  848. FRS_RKF_RANGE_CHECK |
  849. FRS_RKF_OK_TO_USE_DEFAULT},
  850. //
  851. // If true, then remote change orders that update existing files will
  852. // always use a pre-install file in which to build the content followed
  853. // by a rename to insert the file into its target location in the replica
  854. // tree. The benefit is that if FRS runs out of disk space during the
  855. // install phase or the system crashes then a partial file (or a truncated file)
  856. // is not left in the tree. The old content is left in place. The
  857. // drawback of this is the need for enough disk space to hold two copies of
  858. // the target file.
  859. // Default: FALSE
  860. {FRS_CONFIG_SECTION, L"Enable Rename Based File Updates", UNITS_NONE,
  861. REG_DWORD, DT_BOOL, FALSE, TRUE, (FALSE), EVENT_FRS_NONE, NULL,
  862. FKC_ENABLE_RENAME_BASED_UPDATES, FRS_RKF_READ_AT_START |
  863. FRS_RKF_READ_AT_POLL |
  864. FRS_RKF_RANGE_CHECK |
  865. FRS_RKF_OK_TO_USE_DEFAULT},
  866. // add ReplDirLevelLimit as a reg key
  867. // add code support for the following
  868. //FKC_SET_N_DIR_EXCL_FILTER_LIST,
  869. //FKC_SET_N_DIR_INCL_FILTER_LIST,
  870. //FKC_SET_N_FILE_EXCL_FILTER_LIST,
  871. //FKC_SET_N_FILE_INCL_FILTER_LIST,
  872. //FKC_SET_N_SYSVOL_DIR_EXCL_FILTER_LIST,
  873. //FKC_SET_N_SYSVOL_DIR_INCL_FILTER_LIST,
  874. //FKC_SET_N_SYSVOL_FILE_EXCL_FILTER_LIST,
  875. //FKC_SET_N_SYSVOL_FILE_INCL_FILTER_LIST,
  876. /******************************************************************************
  877. *******************************************************************************
  878. ** **
  879. ** P e r - R e p l i c a S e t K e y s **
  880. ** **
  881. ** **
  882. *******************************************************************************
  883. ******************************************************************************/
  884. #define FRS_RKEY_SETS_SECTION FRS_CONFIG_SECTION L",Replica Sets"
  885. #define FRS_RKEY_SET_N FRS_CONFIG_SECTION L",Replica Sets,ARG1"
  886. #define FRS_RKEY_CUM_SET_N FRS_CONFIG_SECTION L",Cumulative Replica Sets,ARG1"
  887. #define FRS_RKEY_CUM_SET_SECTION FRS_CONFIG_SECTION L",Cumulative Replica Sets"
  888. //
  889. // FRS Sets parameter data. Lives in
  890. // "System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\Replica Sets\\[RS-guid]"
  891. // Used for sysvols currently.
  892. //
  893. // No event log messages are generated for these keys since currently
  894. // they are only created by the service or NTFRSAPI so if they get
  895. // fouled up there is nothing the USER can do to correct the problem.
  896. //
  897. // Cumulative Replica Sets *NOTE* This is a key def only.
  898. {FRS_RKEY_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
  899. REG_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  900. FKC_SET_SECTION_KEY, 0},
  901. // The FRS working dir is where the Jet (ESENT) database is created.
  902. // Replica Sets\Database Directory
  903. {FRS_RKEY_SETS_SECTION, JET_PATH, UNITS_NONE,
  904. REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
  905. FKC_SETS_JET_PATH, FRS_RKF_READ_AT_START |
  906. FRS_RKF_RANGE_CHECK |
  907. FRS_RKF_VALUE_MUST_BE_PRESENT |
  908. FRS_RKF_SYNTAX_CHECK},
  909. // Replica Sets\Guid\Replica Set Name
  910. {FRS_RKEY_SET_N, REPLICA_SET_NAME, UNITS_NONE,
  911. REG_SZ, DT_UNICODE, 4, 512, 0, EVENT_FRS_NONE, NULL,
  912. FKC_SET_N_REPLICA_SET_NAME, FRS_RKF_READ_AT_START |
  913. FRS_RKF_RANGE_CHECK |
  914. FRS_RKF_VALUE_MUST_BE_PRESENT},
  915. // The root of the replica tree.
  916. // Replica Sets\Guid\Replica Set Root
  917. {FRS_RKEY_SET_N, REPLICA_SET_ROOT, UNITS_NONE,
  918. REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
  919. FKC_SET_N_REPLICA_SET_ROOT, FRS_RKF_READ_AT_START |
  920. FRS_RKF_RANGE_CHECK |
  921. FRS_RKF_VALUE_MUST_BE_PRESENT |
  922. FRS_RKF_SYNTAX_CHECK},
  923. // The staging area for this replica set.
  924. // Replica Sets\Guid\Replica Set Stage
  925. {FRS_RKEY_SET_N, REPLICA_SET_STAGE, UNITS_NONE,
  926. REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
  927. FKC_SET_N_REPLICA_SET_STAGE, FRS_RKF_READ_AT_START |
  928. FRS_RKF_RANGE_CHECK |
  929. FRS_RKF_VALUE_MUST_BE_PRESENT |
  930. FRS_RKF_SYNTAX_CHECK},
  931. // The replica set type code. ( SYSVOL, DFS, ...)
  932. // Replica Sets\Guid\Replica Set Type
  933. {FRS_RKEY_SET_N, REPLICA_SET_TYPE, UNITS_NONE,
  934. REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
  935. FKC_SET_N_REPLICA_SET_TYPE, FRS_RKF_READ_AT_START |
  936. FRS_RKF_RANGE_CHECK |
  937. FRS_RKF_VALUE_MUST_BE_PRESENT},
  938. // The directory filter exclusion list. Default: None
  939. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  940. {FRS_RKEY_SET_N, L"Directory Exclusion Filter List", UNITS_NONE,
  941. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  942. FKC_SET_N_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  943. FRS_RKF_LOG_EVENT |
  944. FRS_RKF_SYNTAX_CHECK |
  945. FRS_RKF_READ_AT_POLL},
  946. // The directory filter inclusion list. Default: None
  947. {FRS_RKEY_SET_N, L"Directory Inclusion Filter List", UNITS_NONE,
  948. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  949. FKC_SET_N_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  950. FRS_RKF_LOG_EVENT |
  951. FRS_RKF_SYNTAX_CHECK |
  952. FRS_RKF_CREATE_KEY |
  953. FRS_RKF_OK_TO_USE_DEFAULT |
  954. FRS_RKF_READ_AT_POLL},
  955. // The file filter exclusion list.
  956. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  957. {FRS_RKEY_SET_N, L"File Exclusion Filter List", UNITS_NONE,
  958. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  959. FKC_SET_N_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  960. FRS_RKF_LOG_EVENT |
  961. FRS_RKF_READ_AT_POLL},
  962. // The file filter inclusion list. Default: ~clbcatq.*
  963. {FRS_RKEY_SET_N, L"File Inclusion Filter List", UNITS_NONE,
  964. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
  965. L"~clbcatq.*",
  966. FKC_SET_N_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  967. FRS_RKF_LOG_EVENT |
  968. FRS_RKF_SYNTAX_CHECK |
  969. FRS_RKF_CREATE_KEY |
  970. FRS_RKF_OK_TO_USE_DEFAULT |
  971. FRS_RKF_READ_AT_POLL},
  972. // The tombstone state of this replica set.
  973. // Replica Sets\Guid\Replica Set Tombstoned
  974. {FRS_RKEY_SET_N, REPLICA_SET_TOMBSTONED, UNITS_NONE,
  975. REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
  976. FKC_SET_N_REPLICA_SET_TOMBSTONED, FRS_RKF_READ_AT_START |
  977. FRS_RKF_RANGE_CHECK |
  978. FRS_RKF_VALUE_MUST_BE_PRESENT},
  979. // The operation to perform on the replica set.
  980. // Replica Sets\Guid\Replica Set Command
  981. {FRS_RKEY_SET_N, REPLICA_SET_COMMAND, UNITS_NONE,
  982. REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
  983. FKC_SET_N_REPLICA_SET_COMMAND, FRS_RKF_READ_AT_START |
  984. FRS_RKF_RANGE_CHECK |
  985. FRS_RKF_VALUE_MUST_BE_PRESENT},
  986. // If TRUE this is the first member of a replica set and we init the DB
  987. // with the contents of the replica tree.
  988. // Replica Sets\Guid\Replica Set Primary
  989. {FRS_RKEY_SET_N, REPLICA_SET_PRIMARY, UNITS_NONE,
  990. REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
  991. FKC_SET_N_REPLICA_SET_PRIMARY, FRS_RKF_READ_AT_START |
  992. FRS_RKF_RANGE_CHECK |
  993. FRS_RKF_VALUE_MUST_BE_PRESENT},
  994. // LDAP error Status return if we have a problem creating sysvol.
  995. // Replica Sets\Guid\Replica Set Status
  996. {FRS_RKEY_SET_N, REPLICA_SET_STATUS, UNITS_NONE,
  997. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  998. FKC_SET_N_REPLICA_SET_STATUS, FRS_RKF_READ_AT_START},
  999. // Cumulative Replica Sets *NOTE* This is a key def only.
  1000. {FRS_RKEY_CUM_SET_SECTION, L"*KeyOnly*", UNITS_NONE,
  1001. REG_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1002. FKC_CUMSET_SECTION_KEY, 0},
  1003. // Number of inbound and outbound partners for this replica set.
  1004. // Cumulative Replica Sets\Guid\Number Of Partners
  1005. {FRS_RKEY_CUM_SET_N, L"Number Of Partners", UNITS_NONE,
  1006. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1007. FKC_CUMSET_N_NUMBER_OF_PARTNERS, FRS_RKF_READ_AT_START},
  1008. // Backup / Restore flags for this replica set.
  1009. // Cumulative Replica Sets\Guid\BurFlags
  1010. {FRS_RKEY_CUM_SET_N, FRS_VALUE_BURFLAGS, UNITS_NONE,
  1011. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1012. FKC_CUMSET_N_BURFLAGS, FRS_RKF_READ_AT_START},
  1013. /******************************************************************************
  1014. *******************************************************************************
  1015. ** **
  1016. ** S y s t e m V o l u m e R e l a t e d K e y s **
  1017. ** **
  1018. ** **
  1019. *******************************************************************************
  1020. ******************************************************************************/
  1021. #define FRS_RKEY_SYSVOL_SET_N FRS_CONFIG_SECTION L",SysVol,ARG1"
  1022. #define FRS_RKEY_SYSVOL_SEED_N FRS_CONFIG_SECTION L",SysVol Seeding,ARG1"
  1023. #define FRS_RKEY_SYSVOL_SEEDING_SECTION FRS_CONFIG_SECTION L",SysVol Seeding"
  1024. //
  1025. // No event log messages are generated for these keys since currently
  1026. // they are only created by the service or NTFRSAPI so if they get
  1027. // fouled up there is nothing the USER can do to correct the problem.
  1028. //
  1029. // TRUE if sysvol is ready. Notifies NetLogon to publish computer as a DC.
  1030. // Netlogon\\Parameters\SysvolReady
  1031. {NETLOGON_SECTION, SYSVOL_READY, UNITS_NONE,
  1032. REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
  1033. FKC_SYSVOL_READY, FRS_RKF_READ_AT_START},
  1034. // SysVol Section *NOTE* THis is a key only. It has no value.
  1035. {FRS_SYSVOL_SECTION, L"*KeyOnly*", UNITS_NONE,
  1036. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1037. FKC_SYSVOL_SECTION_KEY, 0},
  1038. // TRUE if sysvol data is all present in registry.
  1039. // Tells us that DCPromo completed.
  1040. // NtFrs\Parameters\SysVol\SysVol Information is Committed
  1041. {FRS_SYSVOL_SECTION, SYSVOL_INFO_IS_COMMITTED, UNITS_NONE,
  1042. REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
  1043. FKC_SYSVOL_INFO_COMMITTED, FRS_RKF_READ_AT_START |
  1044. FRS_RKF_RANGE_CHECK |
  1045. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1046. //
  1047. // Note that the following keys are a repeat of those in the "Per-Replica
  1048. // set" section above except the Key location in the registry is
  1049. // FRS_CONFIG_SECTION\SysVol instead of FRS_CONFIG_SECTION\Replica Sets
  1050. // unfortunate but something more to clean up later perhaps with a
  1051. // second parameter (ARG2).
  1052. //
  1053. // SysVol\<Guid>\Replica Set Name
  1054. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_NAME, UNITS_NONE,
  1055. REG_SZ, DT_UNICODE, 4, 512, 0, EVENT_FRS_NONE, NULL,
  1056. FKC_SET_N_SYSVOL_NAME, FRS_RKF_READ_AT_START |
  1057. FRS_RKF_RANGE_CHECK |
  1058. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1059. // The root of the replica tree.
  1060. // SysVol\<Guid>\Replica Set Root
  1061. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_ROOT, UNITS_NONE,
  1062. REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
  1063. FKC_SET_N_SYSVOL_ROOT, FRS_RKF_READ_AT_START |
  1064. FRS_RKF_RANGE_CHECK |
  1065. FRS_RKF_VALUE_MUST_BE_PRESENT |
  1066. FRS_RKF_SYNTAX_CHECK},
  1067. // The staging area for this replica set.
  1068. // SysVol\<Guid>\Replica Set Stage
  1069. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_STAGE, UNITS_NONE,
  1070. REG_SZ, DT_DIR_PATH, 4, 10*1024, 4, EVENT_FRS_NONE, NULL,
  1071. FKC_SET_N_SYSVOL_STAGE, FRS_RKF_READ_AT_START |
  1072. FRS_RKF_RANGE_CHECK |
  1073. FRS_RKF_VALUE_MUST_BE_PRESENT |
  1074. FRS_RKF_SYNTAX_CHECK},
  1075. // The replica set type code. ( SYSVOL, DFS, ...)
  1076. // SysVol\<Guid>\Replica Set Type
  1077. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_TYPE, UNITS_NONE,
  1078. REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
  1079. FKC_SET_N_SYSVOL_TYPE, FRS_RKF_READ_AT_START |
  1080. FRS_RKF_RANGE_CHECK |
  1081. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1082. // The directory filter exclusion list. Default: None
  1083. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  1084. {FRS_RKEY_SYSVOL_SET_N, L"Directory Exclusion Filter List", UNITS_NONE,
  1085. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  1086. FKC_SET_N_SYSVOL_DIR_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  1087. FRS_RKF_LOG_EVENT |
  1088. FRS_RKF_SYNTAX_CHECK |
  1089. FRS_RKF_READ_AT_POLL},
  1090. // The directory filter inclusion list. Default: None
  1091. {FRS_RKEY_SYSVOL_SET_N, L"Directory Inclusion Filter List", UNITS_NONE,
  1092. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  1093. FKC_SET_N_SYSVOL_DIR_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  1094. FRS_RKF_LOG_EVENT |
  1095. FRS_RKF_SYNTAX_CHECK |
  1096. FRS_RKF_CREATE_KEY |
  1097. FRS_RKF_OK_TO_USE_DEFAULT |
  1098. FRS_RKF_READ_AT_POLL},
  1099. // The file filter exclusion list.
  1100. // Don't supply a default here. See FRS_DS_COMPOSE_FILTER_LIST for why.
  1101. {FRS_RKEY_SYSVOL_SET_N, L"File Exclusion Filter List", UNITS_NONE,
  1102. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  1103. FKC_SET_N_SYSVOL_FILE_EXCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  1104. FRS_RKF_LOG_EVENT |
  1105. FRS_RKF_READ_AT_POLL},
  1106. // The file filter inclusion list. Default: ~clbcatq.*
  1107. {FRS_RKEY_SYSVOL_SET_N, L"File Inclusion Filter List", UNITS_NONE,
  1108. REG_SZ, DT_FILE_LIST, 0, 0, 0, EVENT_FRS_BAD_REG_DATA,
  1109. L"~clbcatq.*",
  1110. FKC_SET_N_SYSVOL_FILE_INCL_FILTER_LIST, FRS_RKF_READ_AT_START |
  1111. FRS_RKF_LOG_EVENT |
  1112. FRS_RKF_SYNTAX_CHECK |
  1113. FRS_RKF_CREATE_KEY |
  1114. FRS_RKF_OK_TO_USE_DEFAULT |
  1115. FRS_RKF_READ_AT_POLL},
  1116. // The operation to perform on the replica set.
  1117. // SysVol\<Guid>\Replica Set Command
  1118. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_COMMAND, UNITS_NONE,
  1119. REG_SZ, DT_UNICODE, 2, 1024, 0, EVENT_FRS_NONE, NULL,
  1120. FKC_SET_N_SYSVOL_COMMAND, FRS_RKF_READ_AT_START |
  1121. FRS_RKF_RANGE_CHECK |
  1122. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1123. // The RPC binding string for the parent computer to seed from.
  1124. // SysVol\<Guid>\Replica Set Parent
  1125. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_PARENT, UNITS_NONE,
  1126. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1127. FKC_SET_N_SYSVOL_PARENT, FRS_RKF_READ_AT_START |
  1128. FRS_RKF_RANGE_CHECK |
  1129. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1130. // If TRUE this is the first member of a replica set and we init the DB
  1131. // with the contents of the replica tree.
  1132. // SysVol\<Guid>\Replica Set Primary
  1133. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_PRIMARY, UNITS_NONE,
  1134. REG_DWORD, DT_BOOL, 0, 1, 0, EVENT_FRS_NONE, NULL,
  1135. FKC_SET_N_SYSVOL_PRIMARY, FRS_RKF_READ_AT_START |
  1136. FRS_RKF_RANGE_CHECK |
  1137. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1138. // LDAP error Status return if we have a problem creating sysvol.
  1139. // SysVol\<Guid>\Replica Set Status
  1140. {FRS_RKEY_SYSVOL_SET_N, REPLICA_SET_STATUS, UNITS_NONE,
  1141. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1142. FKC_SET_N_SYSVOL_STATUS, FRS_RKF_READ_AT_START},
  1143. // The RPC binding string for the parent computer to seed from.
  1144. // SysVol Seeding\ReplicaSetName(ARG1)\Replica Set Parent
  1145. {FRS_RKEY_SYSVOL_SEED_N, REPLICA_SET_PARENT, UNITS_NONE,
  1146. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1147. FKC_SYSVOL_SEEDING_N_PARENT, FRS_RKF_READ_AT_START |
  1148. FRS_RKF_RANGE_CHECK |
  1149. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1150. // SysVol Seeding\ReplicaSetName(ARG1)\Replica Set Name
  1151. {FRS_RKEY_SYSVOL_SEED_N, REPLICA_SET_NAME, UNITS_NONE,
  1152. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1153. FKC_SYSVOL_SEEDING_N_RSNAME, FRS_RKF_READ_AT_START |
  1154. FRS_RKF_RANGE_CHECK |
  1155. FRS_RKF_VALUE_MUST_BE_PRESENT},
  1156. // SysVol Seeding *NOTE* THis is a key only. It has no value.
  1157. {FRS_RKEY_SYSVOL_SEEDING_SECTION, L"*KeyOnly*", UNITS_NONE,
  1158. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1159. FKC_SYSVOL_SEEDING_SECTION_KEY, 0},
  1160. /******************************************************************************
  1161. *******************************************************************************
  1162. ** **
  1163. ** E v e n t L o g g i n g C o n f i g K e y s **
  1164. ** **
  1165. ** **
  1166. *******************************************************************************
  1167. ******************************************************************************/
  1168. #define FRS_RKEY_EVENTLOG EVENTLOG_ROOT L",ARG1"
  1169. #define FRS_RKEY_EVENTLOG_SOURCE EVENTLOG_ROOT L"," SERVICE_LONG_NAME L",ARG1"
  1170. // EventLog\File Replication Service\File
  1171. {FRS_RKEY_EVENTLOG, L"File", UNITS_NONE,
  1172. REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
  1173. L"%SystemRoot%\\system32\\config\\NtFrs.Evt",
  1174. FKC_EVENTLOG_FILE, FRS_RKF_READ_AT_START |
  1175. FRS_RKF_CREATE_KEY |
  1176. FRS_RKF_SYNTAX_CHECK |
  1177. FRS_RKF_OK_TO_USE_DEFAULT},
  1178. // EventLog\File Replication Service\DisplayNameFile
  1179. {FRS_RKEY_EVENTLOG, L"DisplayNameFile", UNITS_NONE,
  1180. REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
  1181. L"%SystemRoot%\\system32\\els.dll",
  1182. FKC_EVENTLOG_DISPLAY_FILENAME,FRS_RKF_READ_AT_START |
  1183. FRS_RKF_CREATE_KEY |
  1184. FRS_RKF_SYNTAX_CHECK |
  1185. FRS_RKF_OK_TO_USE_DEFAULT},
  1186. // EventLog\File Replication Service\EventMessageFile
  1187. // EventLog\NTFRS\EventMessageFile
  1188. // Default value: "%SystemRoot%\system32\ntfrsres.dll"
  1189. {FRS_RKEY_EVENTLOG_SOURCE, L"EventMessageFile", UNITS_NONE,
  1190. REG_EXPAND_SZ, DT_FILENAME, 4, 0, 0, EVENT_FRS_NONE,
  1191. DEFAULT_MESSAGE_FILE_PATH,
  1192. FKC_EVENTLOG_EVENT_MSG_FILE, FRS_RKF_READ_AT_START |
  1193. FRS_RKF_CREATE_KEY |
  1194. FRS_RKF_SYNTAX_CHECK |
  1195. FRS_RKF_OK_TO_USE_DEFAULT},
  1196. // EventLog\File Replication Service\Sources
  1197. {FRS_RKEY_EVENTLOG, L"Sources", UNITS_NONE,
  1198. REG_MULTI_SZ, DT_UNICODE, 4, 0, 0, EVENT_FRS_NONE,
  1199. (SERVICE_NAME L"\0" SERVICE_LONG_NAME L"\0"),
  1200. FKC_EVENTLOG_SOURCES, FRS_RKF_READ_AT_START |
  1201. FRS_RKF_CREATE_KEY |
  1202. FRS_RKF_OK_TO_USE_DEFAULT},
  1203. // EventLog\File Replication Service\Retention
  1204. {FRS_RKEY_EVENTLOG, L"Retention", UNITS_NONE,
  1205. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_BAD_REG_DATA, NULL,
  1206. FKC_EVENTLOG_RETENTION, FRS_RKF_READ_AT_START |
  1207. FRS_RKF_LOG_EVENT |
  1208. FRS_RKF_CREATE_KEY |
  1209. FRS_RKF_OK_TO_USE_DEFAULT},
  1210. // EventLog\File Replication Service\MaxSize
  1211. {FRS_RKEY_EVENTLOG, L"MaxSize", UNITS_NONE,
  1212. REG_DWORD, DT_ULONG, 0, MAXLONG, 0x80000, EVENT_FRS_BAD_REG_DATA, NULL,
  1213. FKC_EVENTLOG_MAXSIZE, FRS_RKF_READ_AT_START |
  1214. FRS_RKF_LOG_EVENT |
  1215. FRS_RKF_CREATE_KEY |
  1216. FRS_RKF_OK_TO_USE_DEFAULT},
  1217. // EventLog\File Replication Service\DisplayNameID
  1218. {FRS_RKEY_EVENTLOG, L"DisplayNameID", UNITS_NONE,
  1219. REG_DWORD, DT_ULONG, 0, MAXLONG, 259, EVENT_FRS_NONE, NULL,
  1220. FKC_EVENTLOG_DISPLAY_NAMEID, FRS_RKF_READ_AT_START |
  1221. FRS_RKF_CREATE_KEY |
  1222. FRS_RKF_OK_TO_USE_DEFAULT},
  1223. // EventLog\File Replication Service\CustomSD
  1224. // CustomSD that is used to protect the FRS log. It is essentially the default SD
  1225. // that is used to protect the custom logs, with "restrict guest access" option.
  1226. // The following permission bits are in use:
  1227. // READ=0x1, WRITE=0x2, CLEAR=0x4, BACKUP=0x20
  1228. //
  1229. // The SD is as follows:
  1230. // Owner/Group = Local system
  1231. // DACL:
  1232. // Deny: Full control, Anonymous
  1233. // Deny: Full control, Domain Guests
  1234. // Allow: Full control, Local system
  1235. // Allow: Read|Clear, Builtin Admins
  1236. // Allow: Backup, Backup operators
  1237. // Allow: Read|Clear, System operators
  1238. // Allow: Read, Everyone
  1239. // Allow: Write, Local service
  1240. // Allow: Write, Network service
  1241. //
  1242. // 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)
  1243. {FRS_RKEY_EVENTLOG, L"CustomSD", UNITS_NONE,
  1244. REG_EXPAND_SZ, DT_UNICODE, 4, 0, 0, EVENT_FRS_NONE,
  1245. 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)",
  1246. FKC_EVENTLOG_CUSTOM_SD,FRS_RKF_READ_AT_START |
  1247. FRS_RKF_CREATE_KEY |
  1248. FRS_RKF_SYNTAX_CHECK |
  1249. FRS_RKF_OK_TO_USE_DEFAULT},
  1250. // EventLog\File Replication Service\TypesSupported
  1251. {FRS_RKEY_EVENTLOG_SOURCE, L"TypesSupported", UNITS_NONE,
  1252. REG_DWORD, DT_ULONG, 0, MAXLONG, FRS_EVENT_TYPES, EVENT_FRS_NONE, NULL,
  1253. FKC_EVENTLOG_TYPES_SUPPORTED, FRS_RKF_READ_AT_START |
  1254. FRS_RKF_CREATE_KEY |
  1255. FRS_RKF_OK_TO_USE_DEFAULT},
  1256. /******************************************************************************
  1257. *******************************************************************************
  1258. ** **
  1259. ** F R S A P I A c c e s s C h e c k K e y s **
  1260. ** **
  1261. ** **
  1262. *******************************************************************************
  1263. ******************************************************************************/
  1264. #define FRS_RKEY_ACCCHK_PERFMON \
  1265. FRS_CONFIG_SECTION L",Access Checks," ACK_COLLECT_PERFMON_DATA
  1266. // Access Checks\Get Perfmon Data\Access checks are [Enabled or Disabled]
  1267. {FRS_RKEY_ACCCHK_PERFMON, ACCESS_CHECKS_ARE, UNITS_NONE,
  1268. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1269. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1270. FKC_ACCCHK_PERFMON_ENABLE, FRS_RKF_READ_AT_START |
  1271. FRS_RKF_LOG_EVENT |
  1272. FRS_RKF_CREATE_KEY |
  1273. FRS_RKF_SYNTAX_CHECK |
  1274. FRS_RKF_RANGE_CHECK},
  1275. // Access Checks\Get Perfmon Data\Access checks require [Full Control or Read]
  1276. {FRS_RKEY_ACCCHK_PERFMON, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1277. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1278. ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
  1279. FKC_ACCCHK_PERFMON_RIGHTS, FRS_RKF_READ_AT_START |
  1280. FRS_RKF_LOG_EVENT |
  1281. FRS_RKF_CREATE_KEY |
  1282. FRS_RKF_SYNTAX_CHECK |
  1283. FRS_RKF_RANGE_CHECK},
  1284. #define FRS_RKEY_ACCCHK_GETDS_POLL \
  1285. FRS_CONFIG_SECTION L",Access Checks," ACK_GET_DS_POLL
  1286. // Access Checks\Get Ds Polling Interval\Access checks are [Enabled or Disabled]
  1287. {FRS_RKEY_ACCCHK_GETDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
  1288. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1289. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1290. FKC_ACCCHK_GETDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
  1291. FRS_RKF_LOG_EVENT |
  1292. FRS_RKF_CREATE_KEY |
  1293. FRS_RKF_SYNTAX_CHECK |
  1294. FRS_RKF_RANGE_CHECK},
  1295. // Access Checks\Get Ds Polling Interval\Access checks require [Full Control or Read]
  1296. {FRS_RKEY_ACCCHK_GETDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1297. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1298. ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
  1299. FKC_ACCCHK_GETDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
  1300. FRS_RKF_LOG_EVENT |
  1301. FRS_RKF_CREATE_KEY |
  1302. FRS_RKF_SYNTAX_CHECK |
  1303. FRS_RKF_RANGE_CHECK},
  1304. #define FRS_RKEY_ACCCHK_GET_INFO \
  1305. FRS_CONFIG_SECTION L",Access Checks," ACK_INTERNAL_INFO
  1306. // Access Checks\Get Internal Information\Access checks are [Enabled or Disabled]
  1307. {FRS_RKEY_ACCCHK_GET_INFO, ACCESS_CHECKS_ARE, UNITS_NONE,
  1308. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1309. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1310. FKC_ACCCHK_GET_INFO_ENABLE, FRS_RKF_READ_AT_START |
  1311. FRS_RKF_LOG_EVENT |
  1312. FRS_RKF_CREATE_KEY |
  1313. FRS_RKF_SYNTAX_CHECK |
  1314. FRS_RKF_RANGE_CHECK},
  1315. // Access Checks\Get Internal Information\Access checks require [Full Control or Read]
  1316. {FRS_RKEY_ACCCHK_GET_INFO, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1317. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1318. ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
  1319. FKC_ACCCHK_GET_INFO_RIGHTS, FRS_RKF_READ_AT_START |
  1320. FRS_RKF_LOG_EVENT |
  1321. FRS_RKF_CREATE_KEY |
  1322. FRS_RKF_SYNTAX_CHECK |
  1323. FRS_RKF_RANGE_CHECK},
  1324. #define FRS_RKEY_ACCCHK_SETDS_POLL \
  1325. FRS_CONFIG_SECTION L",Access Checks," ACK_SET_DS_POLL
  1326. // Access Checks\set Ds Polling Interval\Access checks are [Enabled or Disabled]
  1327. {FRS_RKEY_ACCCHK_SETDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
  1328. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1329. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1330. FKC_ACCCHK_SETDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
  1331. FRS_RKF_LOG_EVENT |
  1332. FRS_RKF_CREATE_KEY |
  1333. FRS_RKF_SYNTAX_CHECK |
  1334. FRS_RKF_RANGE_CHECK},
  1335. // Access Checks\Set Ds Polling Interval\Access checks require [Full Control or Read]
  1336. {FRS_RKEY_ACCCHK_SETDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1337. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1338. ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
  1339. FKC_ACCCHK_SETDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
  1340. FRS_RKF_LOG_EVENT |
  1341. FRS_RKF_CREATE_KEY |
  1342. FRS_RKF_SYNTAX_CHECK |
  1343. FRS_RKF_RANGE_CHECK},
  1344. #define FRS_RKEY_ACCCHK_STARTDS_POLL \
  1345. FRS_CONFIG_SECTION L",Access Checks," ACK_START_DS_POLL
  1346. // Access Checks\Start Ds Polling\Access checks are [Enabled or Disabled]
  1347. {FRS_RKEY_ACCCHK_STARTDS_POLL, ACCESS_CHECKS_ARE, UNITS_NONE,
  1348. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1349. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1350. FKC_ACCCHK_STARTDS_POLL_ENABLE, FRS_RKF_READ_AT_START |
  1351. FRS_RKF_LOG_EVENT |
  1352. FRS_RKF_CREATE_KEY |
  1353. FRS_RKF_SYNTAX_CHECK |
  1354. FRS_RKF_RANGE_CHECK},
  1355. // Access Checks\Start Ds Polling\Access checks require [Full Control or Read]
  1356. {FRS_RKEY_ACCCHK_STARTDS_POLL, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1357. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1358. ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
  1359. FKC_ACCCHK_STARTDS_POLL_RIGHTS, FRS_RKF_READ_AT_START |
  1360. FRS_RKF_LOG_EVENT |
  1361. FRS_RKF_CREATE_KEY |
  1362. FRS_RKF_SYNTAX_CHECK |
  1363. FRS_RKF_RANGE_CHECK},
  1364. #define FRS_RKEY_ACCCHK_DCPROMO \
  1365. FRS_CONFIG_SECTION L",Access Checks," ACK_DCPROMO
  1366. // Access Checks\dcpromo\Access checks are [Enabled or Disabled]
  1367. {FRS_RKEY_ACCCHK_DCPROMO, ACCESS_CHECKS_ARE, UNITS_NONE,
  1368. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1369. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1370. FKC_ACCESS_CHK_DCPROMO_ENABLE, FRS_RKF_READ_AT_START |
  1371. FRS_RKF_LOG_EVENT |
  1372. FRS_RKF_CREATE_KEY |
  1373. FRS_RKF_SYNTAX_CHECK |
  1374. FRS_RKF_RANGE_CHECK},
  1375. // Access Checks\dcpromo\Access checks require [Full Control or Read]
  1376. {FRS_RKEY_ACCCHK_DCPROMO, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1377. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1378. ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
  1379. FKC_ACCESS_CHK_DCPROMO_RIGHTS, FRS_RKF_READ_AT_START |
  1380. FRS_RKF_LOG_EVENT |
  1381. FRS_RKF_CREATE_KEY |
  1382. FRS_RKF_SYNTAX_CHECK |
  1383. FRS_RKF_RANGE_CHECK},
  1384. #define FRS_RKEY_ACCCHK_IS_PATH_REPLICATED \
  1385. FRS_CONFIG_SECTION L",Access Checks," ACK_IS_PATH_REPLICATED
  1386. // Access Checks\Is Path Replicated\Access checks are [Enabled or Disabled]
  1387. {FRS_RKEY_ACCCHK_IS_PATH_REPLICATED, ACCESS_CHECKS_ARE, UNITS_NONE,
  1388. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1389. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1390. FKC_ACCESS_CHK_IS_PATH_REPLICATED_ENABLE, FRS_RKF_READ_AT_START |
  1391. FRS_RKF_LOG_EVENT |
  1392. FRS_RKF_CREATE_KEY |
  1393. FRS_RKF_SYNTAX_CHECK |
  1394. FRS_RKF_RANGE_CHECK},
  1395. // Access Checks\Is Path Replicated\Access checks require [Full Control or Read]
  1396. {FRS_RKEY_ACCCHK_IS_PATH_REPLICATED, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1397. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1398. ACCESS_CHECKS_REQUIRE_DEFAULT_READ,
  1399. FKC_ACCESS_CHK_IS_PATH_REPLICATED_RIGHTS, FRS_RKF_READ_AT_START |
  1400. FRS_RKF_LOG_EVENT |
  1401. FRS_RKF_CREATE_KEY |
  1402. FRS_RKF_SYNTAX_CHECK |
  1403. FRS_RKF_RANGE_CHECK},
  1404. #define FRS_RKEY_ACCCHK_WRITER_COMMANDS \
  1405. FRS_CONFIG_SECTION L",Access Checks," ACK_WRITER_COMMANDS
  1406. // Access Checks\Writer Commands\Access checks are [Enabled or Disabled]
  1407. {FRS_RKEY_ACCCHK_WRITER_COMMANDS, ACCESS_CHECKS_ARE, UNITS_NONE,
  1408. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1409. ACCESS_CHECKS_ARE_DEFAULT_ENABLED,
  1410. FKC_ACCESS_CHK_WRITER_COMMANDS_ENABLE, FRS_RKF_READ_AT_START |
  1411. FRS_RKF_LOG_EVENT |
  1412. FRS_RKF_CREATE_KEY |
  1413. FRS_RKF_SYNTAX_CHECK |
  1414. FRS_RKF_RANGE_CHECK},
  1415. // Access Checks\Writer Commands\Access checks require [Full Control or Read]
  1416. {FRS_RKEY_ACCCHK_WRITER_COMMANDS, ACCESS_CHECKS_REQUIRE, UNITS_NONE,
  1417. REG_SZ, DT_ACCESS_CHK, 2, 200, 0, EVENT_FRS_BAD_REG_DATA,
  1418. ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE,
  1419. FKC_ACCESS_CHK_WRITER_COMMANDS_RIGHTS, FRS_RKF_READ_AT_START |
  1420. FRS_RKF_LOG_EVENT |
  1421. FRS_RKF_CREATE_KEY |
  1422. FRS_RKF_SYNTAX_CHECK |
  1423. FRS_RKF_RANGE_CHECK},
  1424. /******************************************************************************
  1425. *******************************************************************************
  1426. ** **
  1427. ** 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 **
  1428. ** **
  1429. ** **
  1430. *******************************************************************************
  1431. ******************************************************************************/
  1432. //
  1433. // No event log messages are generated for these keys since currently
  1434. // they are only created by the service or NTFRSAPI so if they get
  1435. // fouled up there is nothing the USER can do to correct the problem.
  1436. //
  1437. #define FRS_RKEY_BACKUP_STARTUP_SET_N_SECTION FRS_BACKUP_RESTORE_MV_SETS_SECTION L",ARG1"
  1438. /*
  1439. Used in NtfrsApi.c to pass to backup/restore.
  1440. #define FRS_NEW_FILES_NOT_TO_BACKUP L"SYSTEM\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup"
  1441. FRS_NEW_FILES_NOT_TO_BACKUP REG_MULTI_SZ key
  1442. #define FRS_OLD_FILES_NOT_TO_BACKUP L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FilesNotToBackup"
  1443. FRS_OLD_FILES_NOT_TO_BACKUP REG_MULTI_SZ key
  1444. */
  1445. // Backup/Restore
  1446. // *NOTE* THis is a key only. It has no value.
  1447. {FRS_BACKUP_RESTORE_SECTION, L"*KeyOnly*", UNITS_NONE,
  1448. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1449. FKC_BKUP_SECTION_KEY, 0},
  1450. // Backup/Restore\\Stop NtFrs from Starting
  1451. // *NOTE* THis is a key only. It has no value.
  1452. {FRS_BACKUP_RESTORE_STOP_SECTION, L"*KeyOnly*", UNITS_NONE,
  1453. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1454. FKC_BKUP_STOP_SECTION_KEY, 0},
  1455. // Backup/Restore\Process at Startup\Replica Sets
  1456. // *NOTE* THis is a key only. It has no value.
  1457. {FRS_BACKUP_RESTORE_MV_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
  1458. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1459. FKC_BKUP_MV_SETS_SECTION_KEY, 0},
  1460. // Backup/Restore\Process at Startup\Cumulative Replica Sets
  1461. // *NOTE* THis is a key only. It has no value.
  1462. {FRS_BACKUP_RESTORE_MV_CUMULATIVE_SETS_SECTION, L"*KeyOnly*", UNITS_NONE,
  1463. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1464. FKC_BKUP_MV_CUMSETS_SECTION_KEY, 0},
  1465. // Global Backup / Restore flags.
  1466. // backup/restore\Process at Startup\BurFlags
  1467. {FRS_BACKUP_RESTORE_MV_SECTION, FRS_VALUE_BURFLAGS, UNITS_NONE,
  1468. REG_DWORD, DT_ULONG, 0, MAXLONG, NTFRSAPI_BUR_FLAGS_NONE, EVENT_FRS_NONE, NULL,
  1469. FKC_BKUP_STARTUP_GLOBAL_BURFLAGS, FRS_RKF_READ_AT_START |
  1470. FRS_RKF_OK_TO_USE_DEFAULT},
  1471. // Backup / Restore flags for this replica set in "Process at Startup"
  1472. // backup/restore\Process at Startup\Replica Sets\<guid>\BurFlags
  1473. {FRS_RKEY_BACKUP_STARTUP_SET_N_SECTION, FRS_VALUE_BURFLAGS, UNITS_NONE,
  1474. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1475. FKC_BKUP_STARTUP_SET_N_BURFLAGS, FRS_RKF_READ_AT_START},
  1476. /******************************************************************************
  1477. *******************************************************************************
  1478. ** **
  1479. ** F R S P E R F M O N R e l a t e d K e y s **
  1480. ** **
  1481. ** **
  1482. *******************************************************************************
  1483. ******************************************************************************/
  1484. //
  1485. // No event log messages are generated for these keys since currently
  1486. // they are only created by the service so if they get
  1487. // fouled up there is nothing the USER can do to correct the problem.
  1488. //
  1489. //
  1490. // Note: We can't really use thes yet since some of them are in the DLL
  1491. // which doesn't link with this module. Also some are MULTI_SZ which
  1492. // needs more work in CfgRegReadString and writestring.
  1493. #define FRS_RKEY_REPLICA_SET_PERFMON \
  1494. L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaSet\\Performance"
  1495. #define FRS_RKEY_REPLICA_SET_PERF_LINKAGE \
  1496. L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaSet\\Linkage"
  1497. #define FRS_RKEY_CXTION_PERFMON \
  1498. L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaConn\\Performance"
  1499. #define FRS_RKEY_CXTION_PERF_LINKAGE \
  1500. L"SYSTEM\\CurrentControlSet\\Services\\FileReplicaConn\\Linkage"
  1501. // FileReplicaSet\\Performance\First Counter
  1502. {FRS_RKEY_REPLICA_SET_PERFMON, L"First Counter", UNITS_NONE,
  1503. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1504. FKC_REPLICA_SET_FIRST_CTR, FRS_RKF_READ_AT_START},
  1505. // FileReplicaSet\\Performance\First Help
  1506. {FRS_RKEY_REPLICA_SET_PERFMON, L"First Help", UNITS_NONE,
  1507. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1508. FKC_REPLICA_SET_FIRST_HELP, FRS_RKF_READ_AT_START},
  1509. // FileReplicaSet\\Linkage\Export
  1510. {FRS_RKEY_REPLICA_SET_PERF_LINKAGE, L"Export", UNITS_NONE,
  1511. REG_MULTI_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1512. FKC_REPLICA_SET_LINKAGE_EXPORT, FRS_RKF_READ_AT_START},
  1513. // FileReplicaConn\\Performance\First Counter
  1514. {FRS_RKEY_CXTION_PERFMON, L"First Counter", UNITS_NONE,
  1515. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1516. FKC_REPLICA_CXTION_FIRST_CTR, FRS_RKF_READ_AT_START},
  1517. // FileReplicaConn\\Performance\First Help
  1518. {FRS_RKEY_CXTION_PERFMON, L"First Help", UNITS_NONE,
  1519. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1520. FKC_REPLICA_CXTION_FIRST_HELP, FRS_RKF_READ_AT_START},
  1521. // FileReplicaConn\\Linkage\Export
  1522. {FRS_RKEY_CXTION_PERF_LINKAGE, L"Export", UNITS_NONE,
  1523. REG_MULTI_SZ, DT_UNICODE, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1524. FKC_REPLICA_CXTION_LINKAGE_EXPORT, FRS_RKF_READ_AT_START},
  1525. #define FRS_RKEY_REPARSE_TAG \
  1526. FRS_REPARSE_TAG_SECTION L",ARG1"
  1527. // Reparse Tag Section *NOTE* THis is a key only. It has no value.
  1528. {FRS_REPARSE_TAG_SECTION, L"*KeyOnly*", UNITS_NONE,
  1529. REG_SZ, DT_UNICODE, 2, 10*1024, 0, EVENT_FRS_NONE, NULL,
  1530. FKC_REPARSE_TAG_KEY, 0},
  1531. //
  1532. {FRS_RKEY_REPARSE_TAG, L"Reparse Tag Type", UNITS_NONE,
  1533. REG_DWORD, DT_ULONG, 0, MAXLONG, 0, EVENT_FRS_NONE, NULL,
  1534. FKC_REPARSE_TAG_TYPE, FRS_RKF_READ_AT_START},
  1535. {FRS_RKEY_REPARSE_TAG, L"Data to Replicate [None or File Data or Reparse Point]", UNITS_NONE,
  1536. REG_SZ, DT_UNICODE, 0, 0, 0, EVENT_FRS_NONE, NULL,
  1537. FKC_REPARSE_TAG_REPLICATION_TYPE, FRS_RKF_READ_AT_START},
  1538. {L"End of table", NULL, UNITS_NONE,
  1539. REG_SZ, DT_UNSPECIFIED, 0, 0, 0, EVENT_FRS_NONE, NULL,
  1540. FKC_END_OF_TABLE, 0}
  1541. }; // End of FrsRegistryKeyTable
  1542. PFRS_REGISTRY_KEY
  1543. FrsRegFindKeyContext(
  1544. IN FRS_REG_KEY_CODE KeyIndex
  1545. )
  1546. {
  1547. /*++
  1548. Routine Description:
  1549. This function takes an FRS Registry Key code and returns a pointer to
  1550. the associated key context data.
  1551. Arguments:
  1552. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  1553. Return Value:
  1554. Ptr to the matching Key context entry or NULL if not found.
  1555. --*/
  1556. #undef DEBSUB
  1557. #define DEBSUB "FrsRegFindKeyContext:"
  1558. PFRS_REGISTRY_KEY KeyCtx;
  1559. //DPRINT(0, "function entry\n");
  1560. FRS_ASSERT((KeyIndex > 0) && (KeyIndex < FRS_REG_KEY_CODE_MAX));
  1561. if (KeyIndex >= FRS_REG_KEY_CODE_MAX) {
  1562. return NULL;
  1563. }
  1564. KeyCtx = FrsRegistryKeyTable;
  1565. while (KeyCtx->FrsKeyCode > FKC_END_OF_TABLE) {
  1566. if (KeyIndex == KeyCtx->FrsKeyCode) {
  1567. //
  1568. // Found it.
  1569. //
  1570. return KeyCtx;
  1571. }
  1572. KeyCtx += 1;
  1573. }
  1574. //
  1575. // Not found.
  1576. //
  1577. return NULL;
  1578. }
  1579. PWCHAR
  1580. CfgRegGetValueName(
  1581. IN FRS_REG_KEY_CODE KeyIndex
  1582. )
  1583. {
  1584. /*++
  1585. Routine Description:
  1586. This function returns a ptr to the value name string in the key context.
  1587. This is NOT a ptr to an allocated string so it should NOT be freed.
  1588. Arguments:
  1589. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  1590. Return Value:
  1591. Ptr to value name string. NULL if KeyIndex lookup fails.
  1592. --*/
  1593. #undef DEBSUB
  1594. #define DEBSUB "CfgRegGetValueName:"
  1595. PFRS_REGISTRY_KEY KeyCtx;
  1596. //
  1597. // Find the key context assoicated with the supplied index.
  1598. //
  1599. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  1600. if (KeyCtx == NULL) {
  1601. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  1602. return L"<null>";
  1603. }
  1604. return KeyCtx->ValueName;
  1605. }
  1606. DWORD
  1607. FrsRegExpandKeyStr(
  1608. IN PFRS_REGISTRY_KEY Kc,
  1609. IN PWCHAR KeyArg1,
  1610. IN ULONG Flags,
  1611. OUT PWCHAR *FullKeyStr
  1612. )
  1613. {
  1614. /*++
  1615. Routine Description:
  1616. This function only expands a key field in the given KeyContext and
  1617. returns the result in FullKeyStr. This is used primarily for error
  1618. messages but is also used to open registry access check keys.
  1619. The syntax for the the key field in the KeyContext consists of multiple
  1620. key components separated by commas. This function splits the key field on
  1621. the commas. It then opens the leading key followed by either a create or
  1622. open of each successive component. If a component matches the string
  1623. L"ARG1" then we substitute the KeyArg1 parameter passed to this function
  1624. for this key component. Most often this is a stringized guid. For
  1625. example, the string FRS_RKEY_SET_N is defined as:
  1626. FRS_CONFIG_SECTION L",Replica Sets,ARG1"
  1627. This will end up opening/creating the following key:
  1628. "System\\CurrentControlSet\\Services\\NtFrs\\Parameters\\
  1629. Replica Sets\\
  1630. 27d6d1c4-d6b8-480b-9f18b5ea390a0178"
  1631. assuming the argument passed in was "27d6d1c4-d6b8-480b-9f18b5ea390a0178".
  1632. Arguments:
  1633. Kc - A ptr to the key context struct for the desired reg key.
  1634. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  1635. Flags - Modifer flags
  1636. FullKeyStr - ptr to return buffer for expanded key string.
  1637. NOTE: The buffer is allocated here. Caller must free it.
  1638. Return Value:
  1639. Win32 status of the result of the operation.
  1640. FullKeyStr is returned NULL if operation fails.
  1641. --*/
  1642. #undef DEBSUB
  1643. #define DEBSUB "FrsRegExpandKeyStr:"
  1644. UNICODE_STRING TempUStr, FirstArg;
  1645. PWCHAR FullKey = NULL;
  1646. ULONG Len, FullKeyLen;
  1647. WCHAR KeyStr[MAX_PATH];
  1648. //DPRINT(0, "function entry\n");
  1649. *FullKeyStr = NULL;
  1650. FullKey = FrsAlloc(FULL_KEY_BUFF_SIZE*sizeof(WCHAR));
  1651. FullKey[0] = UNICODE_NULL;
  1652. FullKeyLen = 1;
  1653. //
  1654. // If there are any commas in this key then we need to do a nested
  1655. // key open (perhaps creating nested keys as we go). If the key
  1656. // component matches the string L"ARG1" then we use KeyArg1 supplied by
  1657. // the caller.
  1658. //
  1659. RtlInitUnicodeString(&TempUStr, Kc->KeyName);
  1660. //
  1661. // Parse the comma list.
  1662. //
  1663. while (FrsDissectCommaList(TempUStr, &FirstArg, &TempUStr)) {
  1664. if ((FirstArg.Length == 0) || (FirstArg.Length >= sizeof(KeyStr))) {
  1665. DPRINT1(0, ":FK: ERROR - Bad keyName in Key contxt %ws\n", Kc->KeyName);
  1666. goto ERROR_RETURN;
  1667. }
  1668. //
  1669. // null terminate the key component string.
  1670. //
  1671. CopyMemory(KeyStr, FirstArg.Buffer, FirstArg.Length);
  1672. KeyStr[FirstArg.Length/sizeof(WCHAR)] = UNICODE_NULL;
  1673. //
  1674. // Check the Key Component for a match on ARG1 and substitute.
  1675. //
  1676. if (wcscmp(KeyStr, L"ARG1") == 0) {
  1677. if (wcslen(KeyArg1)*sizeof(WCHAR) > sizeof(KeyStr)) {
  1678. DPRINT1(0, ":FK: ERROR - ARG1 too big %ws\n", KeyArg1);
  1679. goto ERROR_RETURN;
  1680. }
  1681. wcscpy(KeyStr, KeyArg1);
  1682. }
  1683. Len = wcslen(KeyStr);
  1684. if (FullKeyLen + Len + 1 > FULL_KEY_BUFF_SIZE) {
  1685. goto ERROR_RETURN;
  1686. }
  1687. if (FullKeyLen > 1) {
  1688. wcscat(FullKey, L"\\");
  1689. FullKeyLen += 1;
  1690. }
  1691. wcscat(FullKey, KeyStr);
  1692. FullKeyLen += Len;
  1693. } // end while()
  1694. if (FullKeyLen <= 1) {
  1695. goto ERROR_RETURN;
  1696. }
  1697. DPRINT1(4, ":FK: Expanded key name is \"%ws\"\n", FullKey);
  1698. //
  1699. // Return the expanded key to the caller.
  1700. //
  1701. *FullKeyStr = FullKey;
  1702. return ERROR_SUCCESS;
  1703. ERROR_RETURN:
  1704. DPRINT1(0, ":FK: ERROR - FrsRegExpandKeyStr Failed on %ws", Kc->KeyName);
  1705. FrsFree(FullKey);
  1706. return ERROR_INVALID_PARAMETER;
  1707. }
  1708. DWORD
  1709. FrsRegOpenKey(
  1710. IN PFRS_REGISTRY_KEY Kc,
  1711. IN PWCHAR KeyArg1,
  1712. IN ULONG Flags,
  1713. OUT PHKEY hKeyRet
  1714. )
  1715. {
  1716. /*++
  1717. Routine Description:
  1718. This function opens a registry key and returns a handle.
  1719. See FrsRegExpandKeyStr() for a description of the key field syntax.
  1720. Arguments:
  1721. Kc - A ptr to the key context struct for the desired reg key.
  1722. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  1723. Flags - Modifer flags
  1724. FRS_RKF_KEY_ACCCHK_READ means only do a read access check on the key.
  1725. FRS_RKF_KEY_ACCCHK_WRITE means only do a KEY_ALL_ACCESS access check on the key.
  1726. if FRS_RKF_CREATE_KEY is set and FRS_RKF_KEY_MUST_BE_PRESENT is clear
  1727. and the given key component is not found, this function creates it.
  1728. hKeyRet - ptr to HKEY for returned key handle.
  1729. Return Value:
  1730. Win32 status of the result of the registry operation.
  1731. hKeyRet is returned only on a success.
  1732. --*/
  1733. #undef DEBSUB
  1734. #define DEBSUB "FrsRegOpenKey:"
  1735. UNICODE_STRING TempUStr, FirstArg;
  1736. ULONG WStatus;
  1737. PWCHAR FullKey = NULL;
  1738. HKEY hKey = HKEY_LOCAL_MACHINE;
  1739. HKEY hKeyParent = INVALID_HANDLE_VALUE;
  1740. ULONG AccessRights;
  1741. PCHAR AccessName;
  1742. WCHAR KeyStr[MAX_PATH];
  1743. FrsFlagsToStr(Flags, RkfFlagNameTable, sizeof(KeyStr), (PCHAR)KeyStr);
  1744. DPRINT2(4, ":FK: %ws Caller Flags [%s]\n", Kc->ValueName, (PCHAR)KeyStr);
  1745. FrsFlagsToStr(Kc->Flags, RkfFlagNameTable, sizeof(KeyStr), (PCHAR)KeyStr);
  1746. DPRINT2(4, ":FK: %ws KeyCtx Flags [%s]\n", Kc->ValueName, (PCHAR)KeyStr);
  1747. //DPRINT(0, "function entry\n");
  1748. //
  1749. // If this is a call to make a read or write access check then we must
  1750. // first build the entire key string and then try the open. The
  1751. // caller has done an impersonation.
  1752. //
  1753. if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_ACCCHK_READ |
  1754. FRS_RKF_KEY_ACCCHK_WRITE)) {
  1755. AccessRights = KEY_READ;
  1756. AccessName = "KEY_READ";
  1757. if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_ACCCHK_WRITE)) {
  1758. AccessRights = KEY_ALL_ACCESS;
  1759. AccessName = "KEY_ALL_ACCESS";
  1760. }
  1761. //
  1762. // Expand the key string.
  1763. //
  1764. FrsRegExpandKeyStr(Kc, KeyArg1, Flags, &FullKey);
  1765. if (FullKey == NULL) {
  1766. return ERROR_INVALID_PARAMETER;
  1767. }
  1768. DPRINT2(4, ":FK: Doing Access Check (%s) on key \"%ws\"\n",
  1769. AccessName, FullKey);
  1770. WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, FullKey, 0, AccessRights, &hKey);
  1771. if (!WIN_SUCCESS(WStatus)) {
  1772. DPRINT1_WS(0, ":FK: ERROR - Access Check failed on %ws;", FullKey, WStatus);
  1773. FrsFree(FullKey);
  1774. return WStatus;
  1775. }
  1776. //
  1777. // Return the key handle to the caller.
  1778. //
  1779. *hKeyRet = hKey;
  1780. FrsFree(FullKey);
  1781. return ERROR_SUCCESS;
  1782. }
  1783. //
  1784. // Not a key access check. Do normal key open processing.
  1785. //
  1786. //
  1787. // If there are any commas in this key then we need to do a nested
  1788. // key open (perhaps creating nested keys as we go). If the key
  1789. // component matches the string L"ARG1" then we use KeyArg1 supplied by
  1790. // the caller.
  1791. //
  1792. RtlInitUnicodeString(&TempUStr, Kc->KeyName);
  1793. //
  1794. // Parse the comma list.
  1795. //
  1796. while (FrsDissectCommaList(TempUStr, &FirstArg, &TempUStr)) {
  1797. if ((FirstArg.Length == 0) || (FirstArg.Length >= sizeof(KeyStr))) {
  1798. DPRINT1(0, ":FK: ERROR - Bad keyName in Key contxt %ws\n", Kc->KeyName);
  1799. WStatus = ERROR_INVALID_PARAMETER;
  1800. goto RETURN;
  1801. }
  1802. //
  1803. // null terminate the key component string.
  1804. //
  1805. CopyMemory(KeyStr, FirstArg.Buffer, FirstArg.Length);
  1806. KeyStr[FirstArg.Length/sizeof(WCHAR)] = UNICODE_NULL;
  1807. hKeyParent = hKey;
  1808. hKey = INVALID_HANDLE_VALUE;
  1809. //
  1810. // Check the Key Component for a match on ARG1 and substitute.
  1811. //
  1812. if (wcscmp(KeyStr, L"ARG1") == 0) {
  1813. if (wcslen(KeyArg1)*sizeof(WCHAR) > sizeof(KeyStr)) {
  1814. DPRINT1(0, ":FK: ERROR - ARG1 too big %ws\n", KeyArg1);
  1815. WStatus = ERROR_INVALID_PARAMETER;
  1816. goto RETURN;
  1817. }
  1818. wcscpy(KeyStr, KeyArg1);
  1819. }
  1820. //
  1821. // Open the next key component.
  1822. //
  1823. DPRINT1(5, ":FK: Opening next key component [%ws]\n", KeyStr);
  1824. WStatus = RegOpenKeyEx(hKeyParent, KeyStr, 0, KEY_ALL_ACCESS, &hKey);
  1825. if (!WIN_SUCCESS(WStatus)) {
  1826. //
  1827. // If the key is supposed to be there then return error to caller.
  1828. //
  1829. if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_KEY_MUST_BE_PRESENT)) {
  1830. DPRINT1_WS(0, ":FK: Could not open key component [%ws].", KeyStr, WStatus);
  1831. FrsRegPostEventLog(Kc, KeyArg1, Flags, IDS_REG_KEY_NOT_FOUND);
  1832. goto RETURN;
  1833. }
  1834. if (BooleanFlagOn(Flags | Kc->Flags, FRS_RKF_CREATE_KEY)) {
  1835. //
  1836. // Try to create the key.
  1837. //
  1838. DPRINT1(4, ":FK: Creating key component [%ws]\n", KeyStr);
  1839. WStatus = RegCreateKeyW(hKeyParent, KeyStr, &hKey);
  1840. CLEANUP1_WS(0, ":FK: Could not create key component [%ws].",
  1841. KeyStr, WStatus, RETURN);
  1842. } else {
  1843. //
  1844. // Key not there and not supposed to create it. Let caller know.
  1845. //
  1846. goto RETURN;
  1847. }
  1848. }
  1849. if (hKeyParent != HKEY_LOCAL_MACHINE) {
  1850. FRS_REG_CLOSE(hKeyParent);
  1851. }
  1852. } // end while()
  1853. //
  1854. // Return the key handle to the caller.
  1855. //
  1856. *hKeyRet = hKey;
  1857. WStatus = ERROR_SUCCESS;
  1858. RETURN:
  1859. if (hKeyParent != HKEY_LOCAL_MACHINE) {
  1860. FRS_REG_CLOSE(hKeyParent);
  1861. }
  1862. if (!WIN_SUCCESS(WStatus)) {
  1863. DPRINT_WS(5, "ERROR - FrsRegOpenKey Failed.", WStatus);
  1864. if (hKey != HKEY_LOCAL_MACHINE) {
  1865. FRS_REG_CLOSE(hKey);
  1866. }
  1867. }
  1868. return WStatus;
  1869. }
  1870. DWORD
  1871. CfgRegReadDWord(
  1872. IN FRS_REG_KEY_CODE KeyIndex,
  1873. IN PWCHAR KeyArg1,
  1874. IN ULONG Flags,
  1875. OUT PULONG DataRet
  1876. )
  1877. {
  1878. /*++
  1879. Routine Description:
  1880. This function reads a keyword value from the registry.
  1881. Arguments:
  1882. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  1883. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  1884. Flags - Modifer flags
  1885. DataRet - ptr to DWORD for returned result.
  1886. Return Value:
  1887. Win32 status of the result of the registry operation.
  1888. Data is returned only on a success.
  1889. --*/
  1890. #undef DEBSUB
  1891. #define DEBSUB "CfgRegReadDWord:"
  1892. DWORD WStatus;
  1893. HKEY hKey = INVALID_HANDLE_VALUE;
  1894. DWORD Type;
  1895. DWORD Len;
  1896. DWORD Data;
  1897. BOOL DefaultValueUseOk;
  1898. PFRS_REGISTRY_KEY KeyCtx;
  1899. //DPRINT(0, "function entry\n");
  1900. //
  1901. // Find the key context assoicated with the supplied index.
  1902. //
  1903. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  1904. if (KeyCtx == NULL) {
  1905. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  1906. return ERROR_INVALID_PARAMETER;
  1907. }
  1908. DefaultValueUseOk = BooleanFlagOn(Flags | KeyCtx->Flags,
  1909. FRS_RKF_OK_TO_USE_DEFAULT);
  1910. FRS_ASSERT(KeyCtx->ValueName != NULL);
  1911. DPRINT2(4, ":FK: Reading parameter [%ws] \"%ws\" \n",
  1912. KeyCtx->KeyName, KeyCtx->ValueName);
  1913. //
  1914. // Table entry better be REG_DWORD.
  1915. //
  1916. if (KeyCtx->RegValueType != REG_DWORD) {
  1917. DPRINT3(4, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
  1918. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
  1919. FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_DWORD");
  1920. return ERROR_INVALID_PARAMETER;
  1921. }
  1922. //
  1923. // Open the key.
  1924. //
  1925. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  1926. if (!WIN_SUCCESS(WStatus)) {
  1927. goto RETURN;
  1928. }
  1929. //
  1930. // Read the value
  1931. //
  1932. Len = sizeof(Data);
  1933. Type = REG_DWORD;
  1934. WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, (PUCHAR)&Data, &Len);
  1935. if (!WIN_SUCCESS(WStatus)) {
  1936. DPRINT_WS(5, "ERROR - RegQueryValueEx Failed.", WStatus);
  1937. if (WStatus == ERROR_FILE_NOT_FOUND) {
  1938. //
  1939. // If the value is supposed to be there then return error to caller.
  1940. //
  1941. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_VALUE_MUST_BE_PRESENT)) {
  1942. DPRINT2_WS(0, ":FK: Value not found [%ws] \"%ws\".",
  1943. KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
  1944. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_NOT_FOUND);
  1945. goto RETURN;
  1946. }
  1947. } else {
  1948. //
  1949. // Check for expected registry datatype if we found a value.
  1950. // Check for buffer size OK. 4 bytes for DWORDs.
  1951. //
  1952. if (WIN_BUF_TOO_SMALL(WStatus) || (Type != REG_DWORD)) {
  1953. DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
  1954. KeyCtx->KeyName, KeyCtx->ValueName, Type, REG_DWORD);
  1955. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
  1956. }
  1957. }
  1958. WStatus = ERROR_INVALID_PARAMETER;
  1959. } else {
  1960. //
  1961. // Found a value, Check type. If wrong, use default.
  1962. //
  1963. if (Type != REG_DWORD) {
  1964. DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
  1965. KeyCtx->KeyName, KeyCtx->ValueName, Type, REG_DWORD);
  1966. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
  1967. WStatus = ERROR_INVALID_PARAMETER;
  1968. }
  1969. }
  1970. if (!WIN_SUCCESS(WStatus) && DefaultValueUseOk) {
  1971. //
  1972. // Not found or wrong type but Ok to use the default value from key context.
  1973. //
  1974. Type = KeyCtx->RegValueType;
  1975. Data = KeyCtx->ValueDefault;
  1976. WStatus = ERROR_SUCCESS;
  1977. DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\".\n",
  1978. KeyCtx->KeyName, KeyCtx->ValueName);
  1979. //
  1980. // Only use it once though.
  1981. //
  1982. DefaultValueUseOk = FALSE;
  1983. }
  1984. if (WIN_SUCCESS(WStatus)) {
  1985. //
  1986. // Perform syntax check based on data type in KeyCtx->DataValueType?
  1987. //
  1988. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_SYNTAX_CHECK)) {
  1989. NOTHING;
  1990. }
  1991. //
  1992. // Perform Range check? (Applies to default value too)
  1993. //
  1994. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK)) {
  1995. if ((Data < KeyCtx->ValueMin) || ( Data > KeyCtx->ValueMax)) {
  1996. DPRINT5(0, ":FK: Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
  1997. KeyCtx->KeyName, KeyCtx->ValueName, Data,
  1998. KeyCtx->ValueMin, KeyCtx->ValueMax);
  1999. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
  2000. if (DefaultValueUseOk) {
  2001. //
  2002. // out of range but Ok to use the default value from key context.
  2003. //
  2004. DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\".\n",
  2005. KeyCtx->KeyName, KeyCtx->ValueName);
  2006. Type = KeyCtx->RegValueType;
  2007. Data = KeyCtx->ValueDefault;
  2008. WStatus = ERROR_SUCCESS;
  2009. //
  2010. // Recheck the range.
  2011. //
  2012. if ((Data < KeyCtx->ValueMin) || ( Data > KeyCtx->ValueMax)) {
  2013. DPRINT5(0, ":FK: Default Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
  2014. KeyCtx->KeyName, KeyCtx->ValueName, Data,
  2015. KeyCtx->ValueMin, KeyCtx->ValueMax);
  2016. WStatus = ERROR_INVALID_PARAMETER;
  2017. goto RETURN;
  2018. }
  2019. } else {
  2020. WStatus = ERROR_INVALID_PARAMETER;
  2021. goto RETURN;
  2022. }
  2023. }
  2024. }
  2025. //
  2026. // Data valid and in range. Return it and save it.
  2027. //
  2028. *DataRet = Data;
  2029. DPRINT3(3, ":FK: [%ws] \"%ws\" = %d\n",
  2030. KeyCtx->KeyName, KeyCtx->ValueName, Data);
  2031. }
  2032. RETURN:
  2033. if (hKey != HKEY_LOCAL_MACHINE) {
  2034. FRS_REG_CLOSE(hKey);
  2035. }
  2036. return WStatus;
  2037. }
  2038. DWORD
  2039. CfgRegReadString(
  2040. IN FRS_REG_KEY_CODE KeyIndex,
  2041. IN PWCHAR KeyArg1,
  2042. IN ULONG Flags,
  2043. OUT PWSTR *pStrRet
  2044. )
  2045. {
  2046. /*++
  2047. Routine Description:
  2048. This function reads a keyword string value from the registry. The return
  2049. buffer is allocated here with FrsAlloc(). Caller must free.
  2050. Arguments:
  2051. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2052. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2053. Flags - Modifer flags
  2054. pStrRet - ptr to address of string buffer for returned result else NULL.
  2055. NOTE: The return buffer is allocated here, caller must free it.
  2056. Return Value:
  2057. Win32 status of the result of the registry operation.
  2058. Data is returned only on a success.
  2059. --*/
  2060. #undef DEBSUB
  2061. #define DEBSUB "CfgRegReadString:"
  2062. DWORD WStatus;
  2063. HKEY hKey = INVALID_HANDLE_VALUE;
  2064. DWORD Type;
  2065. DWORD Len, NewLen;
  2066. PWCHAR Data, NewData;
  2067. BOOL DefaultValueUseOk;
  2068. PFRS_REGISTRY_KEY KeyCtx;
  2069. WCHAR TStr[4];
  2070. // add support or new func for REG_MULTI_SZ?
  2071. //DPRINT(0, "function entry\n");
  2072. Data = NULL;
  2073. //
  2074. // Find the key context assoicated with the supplied index.
  2075. //
  2076. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  2077. if (KeyCtx == NULL) {
  2078. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  2079. *pStrRet = NULL;
  2080. return ERROR_INVALID_PARAMETER;
  2081. }
  2082. DefaultValueUseOk = BooleanFlagOn(Flags | KeyCtx->Flags,
  2083. FRS_RKF_OK_TO_USE_DEFAULT);
  2084. FRS_ASSERT(KeyCtx->ValueName != NULL);
  2085. DPRINT2(4, ":FK: Reading parameter [%ws] \"%ws\" \n",
  2086. KeyCtx->KeyName, KeyCtx->ValueName);
  2087. //
  2088. // Table entry better be some kind of string.
  2089. //
  2090. if ((KeyCtx->RegValueType != REG_SZ) &&
  2091. (KeyCtx->RegValueType != REG_EXPAND_SZ)) {
  2092. DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_SZ or REG_EXPAND_SZ, Found type: %d\n",
  2093. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
  2094. // don't return a null ptr since calling parameter may be wrong size.
  2095. FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_SZ or REG_EXPAND_SZ");
  2096. return ERROR_INVALID_PARAMETER;
  2097. }
  2098. *pStrRet = NULL;
  2099. //
  2100. // Open the key.
  2101. //
  2102. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  2103. if (!WIN_SUCCESS(WStatus)) {
  2104. goto RETURN;
  2105. }
  2106. //
  2107. // Get the size and type for the value.
  2108. //
  2109. WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, NULL, &Len);
  2110. if (!WIN_SUCCESS(WStatus)) {
  2111. DPRINT1_WS(5, ":FK: RegQueryValueEx(%ws);", KeyCtx->ValueName, WStatus);
  2112. Len = 0;
  2113. }
  2114. //
  2115. // If the value is supposed to be there then return error to caller.
  2116. //
  2117. if ((Len == 0) &&
  2118. BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_VALUE_MUST_BE_PRESENT)) {
  2119. DPRINT2_WS(0, ":FK: Value not found [%ws] \"%ws\".",
  2120. KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
  2121. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_NOT_FOUND);
  2122. goto RETURN;
  2123. }
  2124. if (WIN_SUCCESS(WStatus)) {
  2125. //
  2126. // Should be a string.
  2127. //
  2128. if ((Type != REG_SZ) && (Type != REG_EXPAND_SZ)) {
  2129. DPRINT4(0, ":FK: Invalid registry data type for [%ws] \"%ws\". Found Type %d, Expecting Type %d\n",
  2130. KeyCtx->KeyName, KeyCtx->ValueName, Type, KeyCtx->RegValueType);
  2131. WStatus = ERROR_INVALID_PARAMETER;
  2132. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_WRONG_TYPE);
  2133. goto CHECK_DEFAULT;
  2134. }
  2135. //
  2136. // If the string is too long or too short then complain and use default.
  2137. // If KeyCtx->ValueMax is zero then no maximum length check.
  2138. //
  2139. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK) &&
  2140. (Len < KeyCtx->ValueMin*sizeof(WCHAR)) ||
  2141. ((KeyCtx->ValueMax != 0) && (Len > KeyCtx->ValueMax*sizeof(WCHAR)))) {
  2142. DPRINT4(0, ":FK: String size out of range for [%ws] \"%ws\". Min: %d Max: %d\n",
  2143. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->ValueMin, KeyCtx->ValueMax);
  2144. WStatus = ERROR_INVALID_PARAMETER;
  2145. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
  2146. goto CHECK_DEFAULT;
  2147. }
  2148. //
  2149. // Alloc the return buffer and read the data.
  2150. //
  2151. Data = (PWCHAR) FrsAlloc (Len+1);
  2152. WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, &Type, (PUCHAR)Data, &Len);
  2153. if (!WIN_SUCCESS(WStatus)) {
  2154. DPRINT2(0, ":FK: RegQueryValueEx(%ws); WStatus %s\n", KeyCtx->ValueName, ErrLabelW32(WStatus));
  2155. Data = (PWCHAR) FrsFree(Data);
  2156. goto RETURN;
  2157. }
  2158. }
  2159. CHECK_DEFAULT:
  2160. if (!WIN_SUCCESS(WStatus) && DefaultValueUseOk) {
  2161. //
  2162. // Not found or wrong type but Ok to use the default value from key context.
  2163. //
  2164. Data = (PWCHAR) FrsFree(Data);
  2165. if (KeyCtx->StringDefault == NULL) {
  2166. DPRINT2(4, ":FK: Using internal default value for [%ws] \"%ws\" = NULL\n",
  2167. KeyCtx->KeyName, KeyCtx->ValueName);
  2168. goto RETURN;
  2169. }
  2170. Type = KeyCtx->RegValueType;
  2171. Data = FrsWcsDup(KeyCtx->StringDefault);
  2172. WStatus = ERROR_SUCCESS;
  2173. DPRINT3(4, ":FK: Using internal default value for [%ws] \"%ws\" = %ws\n",
  2174. KeyCtx->KeyName, KeyCtx->ValueName, Data);
  2175. }
  2176. if (WIN_SUCCESS(WStatus) && (Data != NULL)) {
  2177. //
  2178. // Perform syntax check based on data type in KeyCtx->DataValueType?
  2179. //
  2180. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_SYNTAX_CHECK)) {
  2181. NOTHING;
  2182. }
  2183. DPRINT3(4, ":FK: [%ws] \"%ws\" = \"%ws\"\n",
  2184. KeyCtx->KeyName, KeyCtx->ValueName, Data);
  2185. //
  2186. // Expand system strings if needed
  2187. //
  2188. if (Type == REG_EXPAND_SZ) {
  2189. NewLen = ExpandEnvironmentStrings(Data, TStr, 0);
  2190. while (TRUE) {
  2191. NewData = (PWCHAR) FrsAlloc ((NewLen+1) * sizeof(WCHAR));
  2192. Len = ExpandEnvironmentStrings(Data, NewData, NewLen);
  2193. if (Len == 0) {
  2194. WStatus = GetLastError();
  2195. DPRINT2_WS(5, ":FK: [%ws] \"%ws\" Param not expanded.",
  2196. KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
  2197. Data = FrsFree(Data);
  2198. NewData = FrsFree(NewData);
  2199. break;
  2200. }
  2201. if (Len <= NewLen) {
  2202. //
  2203. // Free the original buffer and set to return expanded string.
  2204. //
  2205. FrsFree(Data);
  2206. Data = NewData;
  2207. Len = NewLen;
  2208. WStatus = ERROR_SUCCESS;
  2209. break;
  2210. }
  2211. //
  2212. // Get a bigger buffer.
  2213. //
  2214. NewData = (PWCHAR) FrsFree(NewData);
  2215. NewLen = Len;
  2216. }
  2217. }
  2218. //
  2219. // Return ptr to buffer and save a copy for debug printouts.
  2220. //
  2221. *pStrRet = Data;
  2222. DPRINT3(3, ":FK: [%ws] \"%ws\" = \"%ws\"\n",
  2223. KeyCtx->KeyName, KeyCtx->ValueName,
  2224. (Data != NULL) ? Data : L"<null>");
  2225. }
  2226. //
  2227. // Close the handle if one was opened.
  2228. //
  2229. RETURN:
  2230. if (hKey != HKEY_LOCAL_MACHINE) {
  2231. FRS_REG_CLOSE(hKey);
  2232. }
  2233. return WStatus;
  2234. }
  2235. #if 0
  2236. // multisz example)
  2237. void
  2238. RegQueryMULTISZ(
  2239. HKEY hkey,
  2240. LPSTR szSubKey,
  2241. LPSTR szValue
  2242. )
  2243. /*++
  2244. Routine Description:
  2245. This function queries MULTISZ value in the registry using the
  2246. hkey and szSubKey as the registry key info. If the value is not
  2247. found in the registry, it is added with a zero value.
  2248. Arguments:
  2249. hkey - handle to a registry key
  2250. szSubKey - pointer to a subkey string
  2251. Return Value:
  2252. registry value
  2253. --*/
  2254. {
  2255. DWORD rc;
  2256. DWORD len;
  2257. DWORD dwType;
  2258. char buf[1024];
  2259. len = sizeof(buf);
  2260. rc = RegQueryValueEx( hkey, szSubKey, 0, &dwType, (LPBYTE)buf, &len );
  2261. if (!WIN_SUCCESS(rc)) {
  2262. if (rc == ERROR_FILE_NOT_FOUND) {
  2263. buf[0] = 0;
  2264. buf[1] = 0;
  2265. len = 2;
  2266. RegSetMULTISZ( hkey, szSubKey, buf );
  2267. }
  2268. }
  2269. CopyMemory( szValue, buf, len );
  2270. }
  2271. #endif
  2272. DWORD
  2273. CfgRegWriteDWord(
  2274. IN FRS_REG_KEY_CODE KeyIndex,
  2275. IN PWCHAR KeyArg1,
  2276. IN ULONG Flags,
  2277. IN ULONG NewData
  2278. )
  2279. {
  2280. /*++
  2281. Routine Description:
  2282. This function reads a keyword value from the registry.
  2283. Arguments:
  2284. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2285. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2286. Flags - Modifer flags
  2287. FRS_RKF_FORCE_DEFAULT_VALUE - if set then ignore NewData and write the
  2288. default key value from the keyCtx into the registry.
  2289. NewData - DWORD to write to registry.
  2290. Return Value:
  2291. Win32 status of the result of the registry operation.
  2292. --*/
  2293. #undef DEBSUB
  2294. #define DEBSUB "CfgRegWriteDWord:"
  2295. DWORD WStatus;
  2296. HKEY hKey = INVALID_HANDLE_VALUE;
  2297. DWORD Len;
  2298. PFRS_REGISTRY_KEY KeyCtx;
  2299. //DPRINT(0, "function entry\n");
  2300. //
  2301. // Find the key context assoicated with the supplied index.
  2302. //
  2303. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  2304. if (KeyCtx == NULL) {
  2305. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  2306. return ERROR_INVALID_PARAMETER;
  2307. }
  2308. FRS_ASSERT(KeyCtx->ValueName != NULL);
  2309. //
  2310. // Table entry better be REG_DWORD.
  2311. //
  2312. if (KeyCtx->RegValueType != REG_DWORD) {
  2313. DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
  2314. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
  2315. FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_DWORD");
  2316. return ERROR_INVALID_PARAMETER;
  2317. }
  2318. //
  2319. // Open the key.
  2320. //
  2321. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  2322. if (!WIN_SUCCESS(WStatus)) {
  2323. goto RETURN;
  2324. }
  2325. //
  2326. // Keep existing value if caller says so.
  2327. //
  2328. if (BooleanFlagOn(Flags, FRS_RKF_KEEP_EXISTING_VALUE)) {
  2329. WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, NULL, NULL, NULL);
  2330. if (WIN_SUCCESS(WStatus)) {
  2331. DPRINT2(4, ":FK: Retaining existing value for parameter [%ws] \"%ws\"\n",
  2332. KeyCtx->KeyName, KeyCtx->ValueName);
  2333. goto RETURN;
  2334. }
  2335. }
  2336. //
  2337. // Check if we are writing the default value to the registry.
  2338. //
  2339. if (BooleanFlagOn(Flags, FRS_RKF_FORCE_DEFAULT_VALUE)) {
  2340. NewData = KeyCtx->ValueDefault;
  2341. DPRINT1(4, ":FK: Using internal default value = %d\n", NewData);
  2342. }
  2343. //
  2344. // Perform Range check? (Applies to default value too)
  2345. //
  2346. if (BooleanFlagOn(Flags | KeyCtx->Flags,
  2347. FRS_RKF_RANGE_CHECK | FRS_RKF_RANGE_SATURATE)) {
  2348. if ((NewData < KeyCtx->ValueMin) || ( NewData > KeyCtx->ValueMax)) {
  2349. DPRINT5(0, ":FK: Value out of range for [%ws] \"%ws\". Found %d, must be between %d and %d\n",
  2350. KeyCtx->KeyName, KeyCtx->ValueName, NewData,
  2351. KeyCtx->ValueMin, KeyCtx->ValueMax);
  2352. if (!BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_SATURATE)) {
  2353. WStatus = ERROR_INVALID_PARAMETER;
  2354. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
  2355. goto RETURN;
  2356. }
  2357. //
  2358. // Set the value to either the min or max of the allowed range.
  2359. // WARNING: The only current use of this flag is in setting the
  2360. // DS polling interval. This flag should be used with caution
  2361. // since if a user miss-specifies a parameter and we jam
  2362. // it to the min or max value the resulting effect could be
  2363. // VERY UNDESIREABLE.
  2364. //
  2365. if (NewData < KeyCtx->ValueMin) {
  2366. DPRINT2(4, ":FK: Value (%d) below of range. Using Min value (%d)\n",
  2367. NewData, KeyCtx->ValueMin);
  2368. NewData = KeyCtx->ValueMin;
  2369. } else
  2370. if (NewData > KeyCtx->ValueMax) {
  2371. DPRINT2(4, ":FK: Value (%d) above of range. Using Max value (%d)\n",
  2372. NewData, KeyCtx->ValueMax);
  2373. NewData = KeyCtx->ValueMax;
  2374. }
  2375. }
  2376. }
  2377. //
  2378. // Write the value and save it.
  2379. //
  2380. Len = sizeof(NewData);
  2381. WStatus = RegSetValueEx(hKey, KeyCtx->ValueName, 0, REG_DWORD, (PCHAR)&NewData, Len);
  2382. if (!WIN_SUCCESS(WStatus)) {
  2383. DPRINT_WS(0, ":FK: ERROR - RegSetValueEx Failed.", WStatus);
  2384. } else {
  2385. DPRINT3(3, ":FK: [%ws] \"%ws\" = %d\n",
  2386. KeyCtx->KeyName, KeyCtx->ValueName, NewData);
  2387. }
  2388. RETURN:
  2389. if (hKey != HKEY_LOCAL_MACHINE) {
  2390. FRS_REG_CLOSE(hKey);
  2391. }
  2392. return WStatus;
  2393. }
  2394. DWORD
  2395. CfgRegWriteString(
  2396. IN FRS_REG_KEY_CODE KeyIndex,
  2397. IN PWCHAR KeyArg1,
  2398. IN ULONG Flags,
  2399. IN PWSTR NewStr
  2400. )
  2401. {
  2402. /*++
  2403. Routine Description:
  2404. This function reads a keyword string value from the registry. The return
  2405. buffer is allocated here with FrsAlloc(). Caller must free.
  2406. Arguments:
  2407. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2408. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2409. Flags - Modifer flags
  2410. FRS_RKF_FORCE_DEFAULT_VALUE - if set then ignore NewStr and write the
  2411. default key value from the keyCtx into the registry.
  2412. NewStr - ptr to buffer for new string data.
  2413. Return Value:
  2414. Win32 status of the result of the registry operation.
  2415. --*/
  2416. #undef DEBSUB
  2417. #define DEBSUB "CfgRegWriteString:"
  2418. DWORD WStatus;
  2419. HKEY hKey = INVALID_HANDLE_VALUE;
  2420. DWORD Type;
  2421. DWORD Len, NewLen;
  2422. PFRS_REGISTRY_KEY KeyCtx;
  2423. // add support or new func for REG_MULTI_SZ
  2424. //DPRINT(0, "function entry\n");
  2425. //
  2426. // Find the key context assoicated with the supplied index.
  2427. //
  2428. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  2429. if (KeyCtx == NULL) {
  2430. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  2431. return ERROR_INVALID_PARAMETER;
  2432. }
  2433. //
  2434. // Table entry better be some kind of string.
  2435. //
  2436. if ((KeyCtx->RegValueType != REG_SZ) &&
  2437. // (KeyCtx->RegValueType != REG_MULTI_SZ) &&
  2438. (KeyCtx->RegValueType != REG_EXPAND_SZ)) {
  2439. DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_SZ or REG_EXPAND_SZ, Found type: %d\n",
  2440. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
  2441. FRS_ASSERT(!"Mismatch on KeyCtx->RegValueType, Expected REG_SZ or REG_EXPAND_SZ");
  2442. return ERROR_INVALID_PARAMETER;
  2443. }
  2444. //
  2445. // Open the key.
  2446. //
  2447. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  2448. if (!WIN_SUCCESS(WStatus)) {
  2449. goto RETURN;
  2450. }
  2451. FRS_ASSERT(KeyCtx->ValueName != NULL);
  2452. //
  2453. // Keep existing value if caller says so.
  2454. //
  2455. if (BooleanFlagOn(Flags, FRS_RKF_KEEP_EXISTING_VALUE)) {
  2456. WStatus = RegQueryValueEx(hKey, KeyCtx->ValueName, NULL, NULL, NULL, NULL);
  2457. if (WIN_SUCCESS(WStatus)) {
  2458. DPRINT2(4, ":FK: Retaining existing value for parameter [%ws] \"%ws\"\n",
  2459. KeyCtx->KeyName, KeyCtx->ValueName);
  2460. goto RETURN;
  2461. }
  2462. }
  2463. //
  2464. // Check if we are writing the default value to the registry.
  2465. //
  2466. if (BooleanFlagOn(Flags, FRS_RKF_FORCE_DEFAULT_VALUE)) {
  2467. if (KeyCtx->StringDefault == NULL) {
  2468. DPRINT2(0, ":FK: ERROR - Key contxt has no default value for [%ws] \"%ws\" \n",
  2469. KeyCtx->KeyName, KeyCtx->ValueName);
  2470. WStatus = ERROR_INVALID_PARAMETER;
  2471. FRS_ASSERT(!"Key contxt has no default value");
  2472. goto RETURN;
  2473. }
  2474. NewStr = KeyCtx->StringDefault;
  2475. DPRINT1(4, ":FK: Using internal default value = \"%ws\" \n", NewStr);
  2476. }
  2477. //
  2478. // Perform Range check? (Applies to default value too)
  2479. // If the string is too long or too short then complain and use default.
  2480. // If KeyCtx->ValueMax is zero then no maximum length check.
  2481. //
  2482. // Note: for REG_MULTI_SZ we need to look for double null at end of str
  2483. // or use a unique symbol for the string separator and cvt to \0 before write.
  2484. Len = (wcslen(NewStr) + 1) * sizeof(WCHAR);
  2485. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_RANGE_CHECK) &&
  2486. (Len < KeyCtx->ValueMin*sizeof(WCHAR)) ||
  2487. ((KeyCtx->ValueMax != 0) && (Len > KeyCtx->ValueMax*sizeof(WCHAR)))) {
  2488. DPRINT4(0, ":FK: String size out of range for [%ws] \"%ws\". Min: %d Max: %d\n",
  2489. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->ValueMin, KeyCtx->ValueMax);
  2490. WStatus = ERROR_INVALID_PARAMETER;
  2491. FrsRegPostEventLog(KeyCtx, KeyArg1, Flags, IDS_REG_VALUE_RANGE_ERROR);
  2492. goto RETURN;
  2493. }
  2494. WStatus = RegSetValueEx(hKey,
  2495. KeyCtx->ValueName,
  2496. 0,
  2497. KeyCtx->RegValueType,
  2498. (PCHAR)NewStr,
  2499. Len);
  2500. if (!WIN_SUCCESS(WStatus)) {
  2501. DPRINT_WS(0, ":FK: ERROR - RegSetValueEx Failed.", WStatus);
  2502. } else {
  2503. // note: won't work for MULTI_SZ
  2504. DPRINT3(3, ":FK: [%ws] \"%ws\" = %ws\n",
  2505. KeyCtx->KeyName, KeyCtx->ValueName,
  2506. (NewStr != NULL) ? NewStr : L"<null>");
  2507. }
  2508. #if 0
  2509. // Multi_Sz example
  2510. //
  2511. // Event Message File
  2512. //
  2513. // WStatus = RegSetValueEx(FrsEventLogKey,
  2514. // L"Sources",
  2515. // 0,
  2516. // REG_MULTI_SZ,
  2517. // (PCHAR)(SERVICE_NAME L"\0"
  2518. // SERVICE_LONG_NAME L"\0"),
  2519. // (wcslen(SERVICE_NAME) +
  2520. // wcslen(SERVICE_LONG_NAME) +
  2521. // 3) * sizeof(WCHAR));
  2522. //
  2523. // Another example
  2524. //
  2525. void
  2526. RegSetMULTISZ(
  2527. HKEY hkey,
  2528. LPSTR szSubKey,
  2529. LPSTR szValue
  2530. )
  2531. /*++
  2532. Routine Description:
  2533. This function changes a Multi_SZ value in the registry using the
  2534. hkey and szSubKey as the registry key info.
  2535. Arguments:
  2536. hkey - handle to a registry key
  2537. szSubKey - pointer to a subkey string
  2538. szValue - new registry value
  2539. Return Value:
  2540. None.
  2541. --*/
  2542. {
  2543. ULONG i = 1;
  2544. ULONG j = 0;
  2545. LPSTR p = szValue;
  2546. while( TRUE ) {
  2547. j = strlen( p ) + 1;
  2548. i += j;
  2549. p += j;
  2550. if (!*p) {
  2551. break;
  2552. }
  2553. }
  2554. RegSetValueEx( hkey, szSubKey, 0, REG_MULTI_SZ, (PUCHAR)szValue, i );
  2555. }
  2556. #endif
  2557. //
  2558. // Close the handle if one was opened.
  2559. //
  2560. RETURN:
  2561. if (hKey != HKEY_LOCAL_MACHINE) {
  2562. FRS_REG_CLOSE(hKey);
  2563. }
  2564. return WStatus;
  2565. }
  2566. DWORD
  2567. CfgRegDeleteValue(
  2568. IN FRS_REG_KEY_CODE KeyIndex,
  2569. IN PWCHAR KeyArg1,
  2570. IN ULONG Flags
  2571. )
  2572. {
  2573. /*++
  2574. Routine Description:
  2575. This function deletes a keyword value from the registry.
  2576. Arguments:
  2577. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2578. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2579. Flags - Modifer flags
  2580. Return Value:
  2581. Win32 status of the result of the registry operation.
  2582. --*/
  2583. #undef DEBSUB
  2584. #define DEBSUB "CfgRegDeleteValue:"
  2585. DWORD WStatus;
  2586. HKEY hKey = INVALID_HANDLE_VALUE;
  2587. PFRS_REGISTRY_KEY KeyCtx;
  2588. //DPRINT(0, "function entry\n");
  2589. //
  2590. // Find the key context assoicated with the supplied index.
  2591. //
  2592. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  2593. if (KeyCtx == NULL) {
  2594. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  2595. return ERROR_INVALID_PARAMETER;
  2596. }
  2597. FRS_ASSERT(KeyCtx->ValueName != NULL);
  2598. //
  2599. // Open the key.
  2600. //
  2601. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  2602. if (!WIN_SUCCESS(WStatus)) {
  2603. goto RETURN;
  2604. }
  2605. DPRINT2(3, ":FK: Deleting parameter [%ws] \"%ws\" \n",
  2606. KeyCtx->KeyName, KeyCtx->ValueName);
  2607. //
  2608. // Delete the value.
  2609. //
  2610. WStatus = RegDeleteValue(hKey, KeyCtx->ValueName);
  2611. DPRINT2_WS(0, ":FK: WARN - Cannot delete key for [%ws] \"%ws\";",
  2612. KeyCtx->KeyName, KeyCtx->ValueName, WStatus);
  2613. RETURN:
  2614. if (hKey != HKEY_LOCAL_MACHINE) {
  2615. FRS_REG_CLOSE(hKey);
  2616. }
  2617. return WStatus;
  2618. }
  2619. DWORD
  2620. CfgRegOpenKey(
  2621. IN FRS_REG_KEY_CODE KeyIndex,
  2622. IN PWCHAR KeyArg1,
  2623. IN ULONG Flags,
  2624. OUT HKEY *RethKey
  2625. )
  2626. {
  2627. /*++
  2628. Routine Description:
  2629. This function Opens the key associated with the entry from the FRS registry
  2630. key context table. It performs the normal substitution, key component
  2631. creation, etc.
  2632. Arguments:
  2633. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2634. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2635. Flags - Modifer flags
  2636. RethKey -- ptr to HKEY to return the key handle. Caller must close the
  2637. key with RegCloseKey().
  2638. Return Value:
  2639. Win32 status of the result of the registry operation.
  2640. --*/
  2641. #undef DEBSUB
  2642. #define DEBSUB "CfgRegOpenKey:"
  2643. DWORD WStatus;
  2644. HKEY hKey = INVALID_HANDLE_VALUE;
  2645. PFRS_REGISTRY_KEY KeyCtx;
  2646. //DPRINT(0, "function entry\n");
  2647. FRS_ASSERT(RethKey != NULL);
  2648. *RethKey = INVALID_HANDLE_VALUE;
  2649. //
  2650. // Find the key context assoicated with the supplied index.
  2651. //
  2652. KeyCtx = FrsRegFindKeyContext(KeyIndex);
  2653. if (KeyCtx == NULL) {
  2654. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n", KeyIndex);
  2655. return ERROR_INVALID_PARAMETER;
  2656. }
  2657. //
  2658. // Open the key.
  2659. //
  2660. WStatus = FrsRegOpenKey(KeyCtx, KeyArg1, Flags, &hKey);
  2661. if (!WIN_SUCCESS(WStatus)) {
  2662. return WStatus;
  2663. }
  2664. DPRINT1(4, ":FK: Registry key opened [%ws]\n", KeyCtx->KeyName);
  2665. *RethKey = hKey;
  2666. return ERROR_SUCCESS;
  2667. }
  2668. DWORD
  2669. CfgRegCheckEnable(
  2670. IN FRS_REG_KEY_CODE KeyIndex,
  2671. IN PWCHAR KeyArg1,
  2672. IN ULONG Flags,
  2673. OUT PBOOL Enabled,
  2674. OUT PBOOL EnabledAndRequired
  2675. )
  2676. /*++
  2677. Routine Description:
  2678. This function Opens the key associated with the entry from the FRS registry
  2679. key context table. It performs the normal substitution, key component
  2680. creation, etc. It then checks to see if the data value is "Enabled"
  2681. or "Disabled" and returns the boolean result.
  2682. Arguments:
  2683. KeyIndex - An entry from the FRS_REG_KEY_CODE enum
  2684. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  2685. Flags - Modifer flags
  2686. Enabled -- ptr to BOOL to return the Enable / Disable state of the key.
  2687. EnabledAndRequired -- ptr to BOOL to return TRUE if the state is
  2688. "Enabled and Required", FALSE otherwise
  2689. Return Value:
  2690. Win32 status of the result of the registry operation.
  2691. --*/
  2692. #undef DEBSUB
  2693. #define DEBSUB "CfgRegCheckEnable:"
  2694. {
  2695. ULONG WStatus;
  2696. PWCHAR WStr = NULL;
  2697. //DPRINT(0, "function entry\n");
  2698. WStatus = CfgRegReadString(KeyIndex, KeyArg1, Flags, &WStr);
  2699. if ((WStr == NULL) ||
  2700. WSTR_EQ(WStr, FRS_IS_DEFAULT_DISABLED)||
  2701. WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED) ||
  2702. WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED_AND_REQUIRED)
  2703. ) {
  2704. //
  2705. // The key is in the default state so we can clobber it with a
  2706. // new default.
  2707. //
  2708. WStatus = CfgRegWriteString(KeyIndex,
  2709. KeyArg1,
  2710. FRS_RKF_FORCE_DEFAULT_VALUE,
  2711. NULL);
  2712. DPRINT1_WS(0, ":FK: WARN - Cannot create Enable key [%ws];",
  2713. CfgRegGetValueName(KeyIndex), WStatus);
  2714. //
  2715. // Now reread the key for the new default.
  2716. //
  2717. WStr = FrsFree(WStr);
  2718. WStatus = CfgRegReadString(KeyIndex, KeyArg1, Flags, &WStr);
  2719. }
  2720. if ((WStr != NULL) &&
  2721. (WSTR_EQ(WStr, FRS_IS_ENABLED) ||
  2722. WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED))) {
  2723. *Enabled = TRUE;
  2724. *EnabledAndRequired = FALSE;
  2725. DPRINT1(4, ":FK: %ws is enabled\n", CfgRegGetValueName(KeyIndex));
  2726. } else if ((WStr != NULL) &&
  2727. (WSTR_EQ(WStr, FRS_IS_ENABLED_AND_REQUIRED) ||
  2728. WSTR_EQ(WStr, FRS_IS_DEFAULT_ENABLED_AND_REQUIRED))) {
  2729. *Enabled = TRUE;
  2730. *EnabledAndRequired = TRUE;
  2731. } else {
  2732. *Enabled = FALSE;
  2733. *EnabledAndRequired = FALSE;
  2734. DPRINT1_WS(0, ":FK: WARN - %ws is not enabled.",
  2735. CfgRegGetValueName(KeyIndex), WStatus);
  2736. }
  2737. WStr = FrsFree(WStr);
  2738. return WStatus;
  2739. }
  2740. BOOL
  2741. IsWin2KPro (
  2742. VOID
  2743. )
  2744. /*++
  2745. Routine Description:
  2746. Check OS version for Win 2000 Professional (aka NT Workstation).
  2747. Arguments:
  2748. None.
  2749. Return Value:
  2750. True if running on win 2K professional.
  2751. --*/
  2752. #undef DEBSUB
  2753. #define DEBSUB "IsWin2KPro:"
  2754. {
  2755. OSVERSIONINFOEX Osvi;
  2756. DWORDLONG ConditionMask = 0;
  2757. //
  2758. // Initialize the OSVERSIONINFOEX structure.
  2759. //
  2760. ZeroMemory(&Osvi, sizeof(OSVERSIONINFOEX));
  2761. Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  2762. Osvi.dwMajorVersion = 5;
  2763. Osvi.wProductType = VER_NT_WORKSTATION;
  2764. //
  2765. // Initialize the condition mask.
  2766. //
  2767. VER_SET_CONDITION( ConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
  2768. VER_SET_CONDITION( ConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );
  2769. //
  2770. // Perform the test.
  2771. //
  2772. return VerifyVersionInfo(&Osvi, VER_MAJORVERSION | VER_PRODUCT_TYPE, ConditionMask);
  2773. }
  2774. VOID
  2775. CfgRegAdjustTuningDefaults(
  2776. VOID
  2777. )
  2778. /*++
  2779. Routine Description:
  2780. This function walks thru the FrsRegKeyRevisionTable and applies new
  2781. min, max and default values to the specified keys. The objective is
  2782. to reduce the footprint of FRS on the workstation.
  2783. Arguments:
  2784. None.
  2785. Return Value:
  2786. None.
  2787. --*/
  2788. #undef DEBSUB
  2789. #define DEBSUB "CfgRegAdjustTuningDefaults:"
  2790. {
  2791. PFRS_REG_KEY_REVISIONS Rev;
  2792. PFRS_REGISTRY_KEY KeyCtx;
  2793. Win2kPro = IsWin2KPro();
  2794. if (!Win2kPro) {
  2795. //
  2796. // Only adjust tunables on a workstation.
  2797. //
  2798. return;
  2799. }
  2800. Rev = FrsRegKeyRevisionTable;
  2801. while (Rev->FrsKeyCode != FKC_END_OF_TABLE) {
  2802. KeyCtx = FrsRegFindKeyContext(Rev->FrsKeyCode);
  2803. if (KeyCtx == NULL) {
  2804. DPRINT1(0, ":FK: ERROR - Key contxt not found for key code number %d\n",
  2805. Rev->FrsKeyCode);
  2806. continue;
  2807. }
  2808. //
  2809. // Table entry better be REG_DWORD.
  2810. //
  2811. if (KeyCtx->RegValueType != REG_DWORD) {
  2812. DPRINT3(0, ":FK: Mismatch on KeyCtx->RegValueType for [%ws] \"%ws\". Expected REG_DWORD, Found type: %d\n",
  2813. KeyCtx->KeyName, KeyCtx->ValueName, KeyCtx->RegValueType);
  2814. continue;
  2815. }
  2816. //
  2817. // Apply the new range and default values from the table.
  2818. //
  2819. KeyCtx->ValueMin = Rev->ValueMin;
  2820. KeyCtx->ValueMax = Rev->ValueMax;
  2821. KeyCtx->ValueDefault = Rev->ValueDefault;
  2822. Rev += 1;
  2823. }
  2824. }
  2825. #define BACKUP_STAR L"*"
  2826. #define BACKUP_APPEND L"\\* /s"
  2827. VOID
  2828. CfgFilesNotToBackup(
  2829. IN PGEN_TABLE Replicas
  2830. )
  2831. /*++
  2832. Routine Description:
  2833. Set the backup registry key to prevent backing up the jet
  2834. database, staging directories, preinstall directories, ...
  2835. Set the restore registry key KeysNotToRestore so that
  2836. NtBackup will retain the ntfrs restore keys by moving
  2837. them into the final restored registry.
  2838. Arguments:
  2839. Table of replicas
  2840. Return Value:
  2841. None.
  2842. --*/
  2843. {
  2844. #undef DEBSUB
  2845. #define DEBSUB "CfgFilesNotToBackup:"
  2846. DWORD WStatus;
  2847. PVOID Key;
  2848. PREPLICA Replica;
  2849. PWCHAR MStr = NULL;
  2850. DWORD Size = 0;
  2851. DWORD Idx = 0;
  2852. HKEY HOldBackupKey = INVALID_HANDLE_VALUE;
  2853. HKEY HNewBackupKey = INVALID_HANDLE_VALUE;
  2854. HKEY HKeysNotToRestore = INVALID_HANDLE_VALUE;
  2855. //DPRINT(0, "function entry\n");
  2856. //
  2857. // "<Jetpath>\* /s"
  2858. //
  2859. FrsAddToMultiString(JetPath, &Size, &Idx, &MStr);
  2860. FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
  2861. //
  2862. // "<DebugInfo.LogFile>\NtFrs*" Default: "%SystemRoot%\debug\NtFrs*"
  2863. //
  2864. FrsAddToMultiString(DebugInfo.LogFile, &Size, &Idx, &MStr);
  2865. FrsCatToMultiString(NTFRS_DBG_LOG_FILE, &Size, &Idx, &MStr);
  2866. FrsCatToMultiString(BACKUP_STAR, &Size, &Idx, &MStr);
  2867. GTabLockTable(Replicas);
  2868. Key = NULL;
  2869. while (Replica = GTabNextDatumNoLock(Replicas, &Key)) {
  2870. //
  2871. // Ignore tombstoned sets
  2872. //
  2873. if (!IS_TIME_ZERO(Replica->MembershipExpires)) {
  2874. continue;
  2875. }
  2876. //
  2877. // Preinstall directories
  2878. //
  2879. if (Replica->Root) {
  2880. FrsAddToMultiString(Replica->Root, &Size, &Idx, &MStr);
  2881. FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
  2882. FrsCatToMultiString(NTFRS_PREINSTALL_DIRECTORY, &Size, &Idx, &MStr);
  2883. FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
  2884. }
  2885. //
  2886. // Preexisting directories
  2887. //
  2888. if (Replica->Root) {
  2889. FrsAddToMultiString(Replica->Root, &Size, &Idx, &MStr);
  2890. FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
  2891. FrsCatToMultiString(NTFRS_PREEXISTING_DIRECTORY, &Size, &Idx, &MStr);
  2892. FrsCatToMultiString(BACKUP_APPEND, &Size, &Idx, &MStr);
  2893. }
  2894. //
  2895. // Staging directories
  2896. //
  2897. if (Replica->Stage) {
  2898. FrsAddToMultiString(Replica->Stage, &Size, &Idx, &MStr);
  2899. FrsCatToMultiString(L"\\", &Size, &Idx, &MStr);
  2900. FrsCatToMultiString(GENERIC_PREFIX, &Size, &Idx, &MStr);
  2901. FrsCatToMultiString(BACKUP_STAR, &Size, &Idx, &MStr);
  2902. }
  2903. }
  2904. GTabUnLockTable(Replicas);
  2905. // Note: remove old_files_not_to_backup once existance of new key
  2906. // has been verified.
  2907. //
  2908. // FilesNotToBackup
  2909. // "SOFTWARE\Microsoft\Windows NT\CurrentVersion\FilesNotToBackup"
  2910. //
  2911. WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2912. FRS_OLD_FILES_NOT_TO_BACKUP,
  2913. 0,
  2914. KEY_SET_VALUE,
  2915. &HOldBackupKey);
  2916. CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
  2917. FRS_OLD_FILES_NOT_TO_BACKUP, WStatus, NEW_FILES_NOT_TO_BACKUP);
  2918. //
  2919. // Set the ntfrs multistring value
  2920. //
  2921. WStatus = RegSetValueEx(HOldBackupKey,
  2922. SERVICE_NAME,
  2923. 0,
  2924. REG_MULTI_SZ,
  2925. (PCHAR)MStr,
  2926. (Idx + 1) * sizeof(WCHAR));
  2927. CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
  2928. FRS_OLD_FILES_NOT_TO_BACKUP, SERVICE_NAME, WStatus, NEW_FILES_NOT_TO_BACKUP);
  2929. NEW_FILES_NOT_TO_BACKUP:
  2930. //
  2931. // FilesNotToBackup
  2932. // "SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToBackup"
  2933. //
  2934. WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2935. FRS_NEW_FILES_NOT_TO_BACKUP,
  2936. 0,
  2937. KEY_SET_VALUE,
  2938. &HNewBackupKey);
  2939. CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
  2940. FRS_NEW_FILES_NOT_TO_BACKUP, WStatus, CLEANUP);
  2941. //
  2942. // Set the ntfrs multistring value
  2943. //
  2944. WStatus = RegSetValueEx(HNewBackupKey,
  2945. SERVICE_NAME,
  2946. 0,
  2947. REG_MULTI_SZ,
  2948. (PCHAR)MStr,
  2949. (Idx + 1) * sizeof(WCHAR));
  2950. CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
  2951. FRS_NEW_FILES_NOT_TO_BACKUP, SERVICE_NAME, WStatus, CLEANUP);
  2952. //
  2953. // KeysNotToRestore
  2954. //
  2955. // Set the restore registry key KeysNotToRestore so that NtBackup will
  2956. // retain the ntfrs restore keys by moving them into the final restored
  2957. // registry.
  2958. //
  2959. // CurrentControlSet\Services\<SERVICE_NAME>\Parameters\Backup/Restore\Process at Startup\"
  2960. //
  2961. MStr = FrsFree(MStr);
  2962. Size = 0;
  2963. Idx = 0;
  2964. FrsAddToMultiString(FRS_VALUE_FOR_KEYS_NOT_TO_RESTORE, &Size, &Idx, &MStr);
  2965. //
  2966. // KeysNotToRestore
  2967. // "SYSTEM\CurrentControlSet\Control\BackupRestore\KeysNotToRestore"
  2968. //
  2969. WStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2970. FRS_KEYS_NOT_TO_RESTORE,
  2971. 0,
  2972. KEY_SET_VALUE,
  2973. &HKeysNotToRestore);
  2974. CLEANUP1_WS(4, ":FK: WARN - RegOpenKeyEx(%ws);",
  2975. FRS_KEYS_NOT_TO_RESTORE, WStatus, CLEANUP);
  2976. //
  2977. // Set the ntfrs multistring value
  2978. //
  2979. WStatus = RegSetValueEx(HKeysNotToRestore,
  2980. SERVICE_NAME,
  2981. 0,
  2982. REG_MULTI_SZ,
  2983. (PCHAR)MStr,
  2984. (Idx + 1) * sizeof(WCHAR));
  2985. CLEANUP2_WS(4, ":FK: ERROR - RegSetValueEx(%ws\\%ws);",
  2986. FRS_KEYS_NOT_TO_RESTORE, SERVICE_NAME, WStatus, CLEANUP);
  2987. //
  2988. // DONE
  2989. //
  2990. WStatus = ERROR_SUCCESS;
  2991. CLEANUP:
  2992. FRS_REG_CLOSE(HOldBackupKey);
  2993. FRS_REG_CLOSE(HNewBackupKey);
  2994. FRS_REG_CLOSE(HKeysNotToRestore);
  2995. FrsFree(MStr);
  2996. }
  2997. VOID
  2998. FrsRegPostEventLog(
  2999. IN PFRS_REGISTRY_KEY KeyCtx,
  3000. IN PWCHAR KeyArg1,
  3001. IN ULONG Flags,
  3002. IN LONG IDScode
  3003. )
  3004. /*++
  3005. Routine Description:
  3006. This Posts an event log message for a problem with a registry key.
  3007. Arguments:
  3008. KeyCtx - Ptr to the Key Context struct for this key.
  3009. KeyArg1 - An optional caller supplied key component. NULL if not provided.
  3010. Flags - Modifer flags
  3011. IDSCode - the error message code for a resource string to put in the message.
  3012. Return Value:
  3013. None.
  3014. --*/
  3015. #undef DEBSUB
  3016. #define DEBSUB "FrsRegPostEventLog:"
  3017. {
  3018. #define LEN_DEFAULT_VALUE 48
  3019. #define LEN_RANGE_STR 256
  3020. PWCHAR ErrorStr, UnitsStr, RangeStrFmt, ValStr, FullKeyStr;
  3021. WCHAR RangeStr[LEN_RANGE_STR];
  3022. //DPRINT(0, "function entry\n");
  3023. //
  3024. // Are we posting an event log message for this key?
  3025. //
  3026. if (!BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_LOG_EVENT) ||
  3027. (KeyCtx->EventCode == EVENT_FRS_NONE)) {
  3028. return;
  3029. }
  3030. //
  3031. // Post Eventlog message. Include KeyString, ValueName,
  3032. // MustBePresent, Expected Type, TypeMismatch or not,
  3033. // Value out of range (with range allowed), Default Value Used,
  3034. // regedit instrs to fix the problem,
  3035. //
  3036. UnitsStr = FrsGetResourceStr(XLATE_IDS_UNITS(KeyCtx->Units));
  3037. ErrorStr = FrsGetResourceStr(IDScode);
  3038. if (KeyCtx->RegValueType == REG_DWORD) {
  3039. //
  3040. // Get the range format string from the string resource.
  3041. //
  3042. RangeStrFmt = FrsGetResourceStr(IDS_RANGE_DWORD);
  3043. //
  3044. // Show default value used if default is ok.
  3045. //
  3046. if (BooleanFlagOn(Flags | KeyCtx->Flags, FRS_RKF_OK_TO_USE_DEFAULT)) {
  3047. ValStr = FrsAlloc(LEN_DEFAULT_VALUE * sizeof(WCHAR));
  3048. _snwprintf(ValStr, LEN_DEFAULT_VALUE, L"%d", KeyCtx->ValueDefault);
  3049. } else {
  3050. ValStr = FrsGetResourceStr(IDS_NO_DEFAULT);
  3051. }
  3052. } else {
  3053. //
  3054. // No default allowed.
  3055. //
  3056. RangeStrFmt = FrsGetResourceStr(IDS_RANGE_STRING);
  3057. ValStr = FrsGetResourceStr(IDS_NO_DEFAULT);
  3058. }
  3059. //
  3060. // Build the range string.
  3061. //
  3062. _snwprintf(RangeStr, LEN_RANGE_STR, RangeStrFmt, KeyCtx->ValueMin, KeyCtx->ValueMax);
  3063. RangeStr[LEN_RANGE_STR-1] = UNICODE_NULL;
  3064. //
  3065. // Expand the key string.
  3066. //
  3067. FrsRegExpandKeyStr(KeyCtx, KeyArg1, Flags, &FullKeyStr);
  3068. if (FullKeyStr == NULL) {
  3069. FullKeyStr = FrsWcsDup(KeyCtx->KeyName);
  3070. }
  3071. //
  3072. // Post the event log message using the keycode in the KeyContext and cleanup.
  3073. //
  3074. if (KeyCtx->EventCode == EVENT_FRS_BAD_REG_DATA) {
  3075. EPRINT9(KeyCtx->EventCode,
  3076. ErrorStr, // %1
  3077. FullKeyStr, // %2
  3078. KeyCtx->ValueName, // %3
  3079. REG_DT_NAME(KeyCtx->RegValueType), // %4
  3080. RangeStr, // %5
  3081. UnitsStr, // %6
  3082. ValStr, // %7
  3083. FullKeyStr, // %8
  3084. KeyCtx->ValueName); // %9
  3085. } else {
  3086. //
  3087. // Don't know this event code but put out something.
  3088. //
  3089. DPRINT1(0, ":FK: ERROR - Unexpected EventCode number (%d). Cannot post message.\n",
  3090. KeyCtx->EventCode);
  3091. }
  3092. DPRINT1(0, ":FK: EventCode number : %d\n" , (KeyCtx->EventCode & 0xFFFF));
  3093. DPRINT1(0, ":FK: Error String : %ws\n", ErrorStr);
  3094. DPRINT1(0, ":FK: Key String : %ws\n", FullKeyStr);
  3095. DPRINT1(0, ":FK: Value Name : %ws\n", KeyCtx->ValueName);
  3096. DPRINT1(0, ":FK: Expected Reg Type : %ws\n", REG_DT_NAME(KeyCtx->RegValueType));
  3097. DPRINT1(0, ":FK: Parameter Range : %ws\n", RangeStr);
  3098. DPRINT1(0, ":FK: Parameter units : %ws\n", UnitsStr);
  3099. FrsFree(ErrorStr);
  3100. FrsFree(RangeStrFmt);
  3101. FrsFree(UnitsStr);
  3102. FrsFree(ValStr);
  3103. FrsFree(FullKeyStr);
  3104. }
  3105. DWORD
  3106. CfgRegReadReparseTagInfo(
  3107. VOID
  3108. )
  3109. {
  3110. #undef DEBSUB
  3111. #define DEBSUB "CfgRegReadReparseTagInfo:"
  3112. DWORD WStatus = ERROR_SUCCESS;
  3113. HKEY hKey = INVALID_HANDLE_VALUE;
  3114. DWORD Index = 0;
  3115. WCHAR SubKey[MAX_PATH];
  3116. DWORD SubKeySize = MAX_PATH;
  3117. FILETIME LastWriteTime;
  3118. DWORD *ReparseTagType = NULL;
  3119. PREPARSE_TAG_TABLE_ENTRY ReparseTagTableEntry = NULL;
  3120. PREPARSE_TAG_TABLE_ENTRY ExistingEntry = NULL;
  3121. GTabLockTable(ReparseTagTable);
  3122. //
  3123. // First clear the data in the table.
  3124. //
  3125. GTabEmptyTableNoLock(ReparseTagTable, FrsFreeType);
  3126. //
  3127. // Seed the table with the default values.
  3128. //
  3129. ReparseTagType = FrsAlloc(sizeof(DWORD));
  3130. *ReparseTagType = IO_REPARSE_TAG_HSM;
  3131. ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_FILE_DATA) + 1) * sizeof(WCHAR));
  3132. wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_FILE_DATA);
  3133. ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
  3134. FRS_ASSERT(ExistingEntry == NULL);
  3135. ReparseTagType = FrsAlloc(sizeof(DWORD));
  3136. *ReparseTagType = IO_REPARSE_TAG_SIS;
  3137. ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_FILE_DATA) + 1) * sizeof(WCHAR));
  3138. wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_FILE_DATA);
  3139. ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
  3140. FRS_ASSERT(ExistingEntry == NULL);
  3141. ReparseTagType = FrsAlloc(sizeof(DWORD));
  3142. *ReparseTagType = IO_REPARSE_TAG_DFS;
  3143. ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, (wcslen(REPARSE_TAG_REPLICATION_TYPE_REPARSE_POINT) + 1) * sizeof(WCHAR));
  3144. wcscpy(ReparseTagTableEntry->ReplicationType, REPARSE_TAG_REPLICATION_TYPE_REPARSE_POINT);
  3145. ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
  3146. FRS_ASSERT(ExistingEntry == NULL);
  3147. //
  3148. // Read the info from the registry.
  3149. //
  3150. WStatus = CfgRegOpenKey(FKC_REPARSE_TAG_KEY, NULL, 0, &hKey);
  3151. CLEANUP_WS(4, "++ WARN - Cannot open reparse tag key.", WStatus, Exit);
  3152. while(WStatus == ERROR_SUCCESS) {
  3153. SubKeySize = MAX_PATH;
  3154. ReparseTagTableEntry = FrsAllocTypeSize(REPARSE_TAG_TABLE_ENTRY_TYPE, 0);
  3155. ReparseTagType = FrsAlloc(sizeof(DWORD));
  3156. WStatus = RegEnumKeyEx(hKey, // handle to key to enumerate
  3157. Index, // subkey index
  3158. SubKey, // subkey name
  3159. &SubKeySize, // size of subkey buffer
  3160. NULL, // reserved
  3161. NULL, // class string buffer
  3162. NULL, // size of class string buffer
  3163. &LastWriteTime // last write time
  3164. );
  3165. if(WStatus == ERROR_SUCCESS) {
  3166. WStatus = CfgRegReadDWord(FKC_REPARSE_TAG_TYPE, SubKey, 0, ReparseTagType);
  3167. }
  3168. if(WStatus == ERROR_SUCCESS) {
  3169. WStatus = CfgRegReadString(FKC_REPARSE_TAG_REPLICATION_TYPE, SubKey, 0, &(ReparseTagTableEntry->ReplicationType));
  3170. }
  3171. if(WStatus == ERROR_SUCCESS){
  3172. ExistingEntry = GTabInsertUniqueEntryNoLock(ReparseTagTable, ReparseTagTableEntry, ReparseTagType, NULL);
  3173. if(ExistingEntry) {
  3174. //
  3175. // There is already an entry for this reparse tag type.
  3176. // Replace it.
  3177. //
  3178. FrsFree(ExistingEntry->ReplicationType);
  3179. ExistingEntry->ReplicationType = ReparseTagTableEntry->ReplicationType;
  3180. ReparseTagTableEntry->ReplicationType = NULL;
  3181. //
  3182. // The entry we allocated wasn't used.
  3183. // Free it up.
  3184. //
  3185. FrsFreeType(ReparseTagTableEntry);
  3186. ReparseTagTableEntry = NULL;
  3187. }
  3188. Index++;
  3189. }
  3190. ReparseTagTableEntry = NULL;
  3191. ReparseTagType = NULL;
  3192. }
  3193. Exit:
  3194. GTabUnLockTable(ReparseTagTable);
  3195. FRS_REG_CLOSE(hKey);
  3196. return WStatus;
  3197. }