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.

538 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. dmupdate.c
  5. Abstract:
  6. Contains the global update handlers for the Configuration Database Manager
  7. Author:
  8. John Vert (jvert) 24-Apr-1996
  9. Revision History:
  10. --*/
  11. #include "dmp.h"
  12. #if NO_SHARED_LOCKS
  13. extern CRITICAL_SECTION gLockDmpRoot;
  14. #else
  15. extern RTL_RESOURCE gLockDmpRoot;
  16. #endif
  17. VOID
  18. DmpUpdateSequence(
  19. VOID
  20. );
  21. DWORD
  22. DmpUpdateHandler(
  23. IN DWORD Context,
  24. IN BOOL SourceNode,
  25. IN DWORD BufferLength,
  26. IN PVOID Buffer
  27. )
  28. /*++
  29. Routine Description:
  30. Update handler for registry updates
  31. Arguments:
  32. Context - Supplies the update context. This is the message type
  33. SourceNode - Supplies whether or not the update originated on this node.
  34. BufferLength - Supplies the length of the update.
  35. Buffer - Supplies a pointer to the buffer.
  36. Return Value:
  37. ERROR_SUCCESS if successful
  38. Win32 error code otherwise
  39. --*/
  40. {
  41. DWORD Status;
  42. if ( gbDmpShutdownUpdates ) return( ERROR_SUCCESS );
  43. switch (Context) {
  44. case DmUpdateDeleteKey:
  45. ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateDeleteKey \n");
  46. Status = DmpUpdateDeleteKey(SourceNode,
  47. (PDM_DELETE_KEY_UPDATE)Buffer);
  48. break;
  49. case DmUpdateSetValue:
  50. ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateSetValue \n");
  51. Status = DmpUpdateSetValue(SourceNode,
  52. (PDM_SET_VALUE_UPDATE)Buffer);
  53. break;
  54. case DmUpdateDeleteValue:
  55. ClRtlLogPrint(LOG_NOISE,"[DM] DmUpdateDeleteValue\n");
  56. Status = DmpUpdateDeleteValue(SourceNode,
  57. (PDM_DELETE_VALUE_UPDATE)Buffer);
  58. break;
  59. case DmUpdateJoin:
  60. ClRtlLogPrint(LOG_UNUSUAL,"[DM] DmUpdateJoin\n");
  61. Status = ERROR_SUCCESS;
  62. // Reset this variable now that another node is beginning a join. If CsDmOrFmHasChanged is TRUE
  63. // when we see the FmUpdateJoin, then we will reject the join.
  64. CsDmOrFmHasChanged = FALSE;
  65. break;
  66. default:
  67. Status = ERROR_INVALID_DATA;
  68. CL_UNEXPECTED_ERROR(ERROR_INVALID_DATA);
  69. break;
  70. }
  71. return(Status);
  72. }
  73. DWORD
  74. DmpUpdateDeleteKey(
  75. IN BOOL SourceNode,
  76. IN PDM_DELETE_KEY_UPDATE Update
  77. )
  78. /*++
  79. Routine Description:
  80. Deletes the specified registry key on this node.
  81. Arguments:
  82. SourceNode - Supplies whether or not this node is the one that originated
  83. the update.
  84. Buffer - Supplies the DM_DELETE_KEY_UPDATE structure with the information necessary
  85. to delete the key.
  86. Return Value:
  87. ERROR_SUCCESS if successful.
  88. Win32 error otherwise.
  89. --*/
  90. {
  91. DWORD Disposition;
  92. DWORD Status;
  93. HKEY Key;
  94. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  95. Status = RegDeleteKeyW(DmpRoot, Update->Name);
  96. if (SourceNode) {
  97. *Update->lpStatus = Status;
  98. }
  99. if (Status == ERROR_SUCCESS) {
  100. DmpUpdateSequence();
  101. DmpReportNotify(Update->Name, CLUSTER_CHANGE_REGISTRY_NAME);
  102. }
  103. RELEASE_LOCK(gLockDmpRoot);
  104. return(Status);
  105. }
  106. DWORD
  107. DmpUpdateSetValue(
  108. IN BOOL SourceNode,
  109. IN PDM_SET_VALUE_UPDATE Update
  110. )
  111. /*++
  112. Routine Description:
  113. Updates the specified registry value on this node.
  114. Arguments:
  115. SourceNode - Supplies whether or not this node is the one that originated
  116. the update.
  117. Buffer - Supplies the DM_SET_VALUE_UPDATE structure with the information necessary
  118. to set the value.
  119. Return Value:
  120. ERROR_SUCCESS if successful.
  121. Win32 error otherwise.
  122. --*/
  123. {
  124. DWORD Status;
  125. HKEY Key;
  126. LPWSTR ValueName;
  127. CONST BYTE *lpData;
  128. ValueName = (LPWSTR)((PUCHAR)Update + Update->NameOffset);
  129. switch( Update->Type )
  130. {
  131. case REG_DWORD:
  132. ClRtlLogPrint(LOG_NOISE,
  133. "[DM] Setting value of %1!ws! for key %2!ws! to 0x%3!08lx!\n",
  134. ValueName,
  135. Update->KeyName,
  136. *(PDWORD)((CONST BYTE *)Update + Update->DataOffset));
  137. break;
  138. case REG_SZ:
  139. ClRtlLogPrint(LOG_NOISE,
  140. "[DM] Setting value of %1!ws! for key %2!ws! to %3!ws!\n",
  141. ValueName,
  142. Update->KeyName,
  143. (CONST BYTE *)Update + Update->DataOffset);
  144. break;
  145. default:
  146. ClRtlLogPrint(LOG_NOISE,
  147. "[DM] Setting value of %1!ws! for key %2!ws!\n",
  148. ValueName,
  149. Update->KeyName);
  150. break;
  151. }
  152. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  153. Status = RegOpenKeyExW(DmpRoot,
  154. Update->KeyName,
  155. 0,
  156. KEY_SET_VALUE,
  157. &Key);
  158. if (Status != ERROR_SUCCESS) {
  159. if (SourceNode) {
  160. *Update->lpStatus = Status;
  161. }
  162. ClRtlLogPrint(LOG_NOISE,
  163. "[DM] SetValue failed to open target key %1!ws!\n",
  164. Update->KeyName);
  165. goto FnExit;
  166. }
  167. lpData = (CONST BYTE *)Update + Update->DataOffset;
  168. Status = RegSetValueExW(Key,
  169. ValueName,
  170. 0,
  171. Update->Type,
  172. lpData,
  173. Update->DataLength);
  174. RegCloseKey(Key);
  175. if (SourceNode) {
  176. *Update->lpStatus = Status;
  177. }
  178. if (Status == ERROR_SUCCESS) {
  179. DmpUpdateSequence();
  180. DmpReportNotify(Update->KeyName, CLUSTER_CHANGE_REGISTRY_VALUE);
  181. }
  182. FnExit:
  183. RELEASE_LOCK(gLockDmpRoot);
  184. return(Status);
  185. }
  186. DWORD
  187. DmpUpdateDeleteValue(
  188. IN BOOL SourceNode,
  189. IN PDM_DELETE_VALUE_UPDATE Update
  190. )
  191. /*++
  192. Routine Description:
  193. Deletes the specified registry value on this node.
  194. Arguments:
  195. SourceNode - Supplies whether or not this node is the one that originated
  196. the update.
  197. Buffer - Supplies the DM_DELETE_VALUE_UPDATE structure with the information necessary
  198. to delete the value.
  199. Return Value:
  200. ERROR_SUCCESS if successful.
  201. Win32 error otherwise.
  202. --*/
  203. {
  204. DWORD Status;
  205. HKEY Key;
  206. LPWSTR ValueName;
  207. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  208. Status = RegOpenKeyExW(DmpRoot,
  209. Update->KeyName,
  210. 0,
  211. KEY_SET_VALUE,
  212. &Key);
  213. if (Status != ERROR_SUCCESS) {
  214. if (SourceNode) {
  215. *Update->lpStatus = Status;
  216. }
  217. goto FnExit;
  218. }
  219. ValueName = (LPWSTR)((PUCHAR)Update + Update->NameOffset);
  220. Status = RegDeleteValueW(Key, ValueName);
  221. RegCloseKey(Key);
  222. if (SourceNode) {
  223. *Update->lpStatus = Status;
  224. }
  225. if (Status == ERROR_SUCCESS) {
  226. DmpUpdateSequence();
  227. DmpReportNotify(Update->KeyName, CLUSTER_CHANGE_REGISTRY_VALUE);
  228. }
  229. FnExit:
  230. RELEASE_LOCK(gLockDmpRoot);
  231. return(Status);
  232. }
  233. VOID
  234. DmpUpdateSequence(
  235. VOID
  236. )
  237. /*++
  238. Routine Description:
  239. Updates the sequence number stored in the registry.
  240. Arguments:
  241. None.
  242. Return Value:
  243. None.
  244. --*/
  245. {
  246. DWORD Sequence;
  247. DWORD Status;
  248. Sequence = GumGetCurrentSequence(GumUpdateRegistry);
  249. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  250. Status = RegSetValueExW(DmpRoot,
  251. CLUSREG_NAME_CLUS_REG_SEQUENCE,
  252. 0,
  253. REG_DWORD,
  254. (BYTE CONST *)&Sequence,
  255. sizeof(Sequence));
  256. RELEASE_LOCK(gLockDmpRoot);
  257. if (Status != ERROR_SUCCESS) {
  258. CL_UNEXPECTED_ERROR( Status );
  259. }
  260. }
  261. DWORD
  262. DmpUpdateCreateKey(
  263. IN BOOL SourceNode,
  264. IN PDM_CREATE_KEY_UPDATE CreateUpdate,
  265. IN LPCWSTR KeyName,
  266. IN OPTIONAL LPVOID lpSecurityDescriptor
  267. )
  268. /*++
  269. Routine Description:
  270. GUM dispatch routine for creating a registry key.
  271. Arguments:
  272. SourceNode - Supplies whether or not this node initiated the GUM update.
  273. Not used.
  274. CreateUpdate - Supplies key creation options.
  275. KeyName - Supplies the key name
  276. lpSecurityDescriptor - if present, supplies the security descriptor to be
  277. applied when the key is created.
  278. Return Value:
  279. ERROR_SUCCESS if successful.
  280. Win32 error code otherwise.
  281. --*/
  282. {
  283. DWORD Disposition;
  284. DWORD Status;
  285. HKEY Key;
  286. SECURITY_ATTRIBUTES SecurityAttributes;
  287. LPSECURITY_ATTRIBUTES lpSecurityAttributes;
  288. if (CreateUpdate->SecurityPresent) {
  289. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  290. SecurityAttributes.bInheritHandle = FALSE;
  291. SecurityAttributes.lpSecurityDescriptor = lpSecurityDescriptor;
  292. lpSecurityAttributes = &SecurityAttributes;
  293. } else {
  294. lpSecurityAttributes = NULL;
  295. }
  296. ClRtlLogPrint(LOG_NOISE,
  297. "[DM] DmpUpdateCreateKey: Creating key <%1!ws!>...\n",
  298. KeyName);
  299. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  300. Status = RegCreateKeyEx(DmpRoot,
  301. KeyName,
  302. 0,
  303. NULL,
  304. CreateUpdate->dwOptions,
  305. CreateUpdate->samDesired,
  306. lpSecurityAttributes,
  307. &Key,
  308. &Disposition);
  309. if (SourceNode) {
  310. *CreateUpdate->lpDisposition = Disposition;
  311. *CreateUpdate->phKey = Key;
  312. } else {
  313. RegCloseKey(Key);
  314. }
  315. if ((Status == ERROR_SUCCESS) &&
  316. (Disposition == REG_CREATED_NEW_KEY)) {
  317. DmpUpdateSequence();
  318. DmpReportNotify(KeyName, CLUSTER_CHANGE_REGISTRY_NAME);
  319. }
  320. RELEASE_LOCK(gLockDmpRoot);
  321. return(Status);
  322. }
  323. DWORD
  324. DmpUpdateSetSecurity(
  325. IN BOOL SourceNode,
  326. IN PSECURITY_INFORMATION pSecurityInformation,
  327. IN LPCWSTR KeyName,
  328. IN PSECURITY_DESCRIPTOR lpSecurityDescriptor,
  329. IN LPDWORD pGrantedAccess
  330. )
  331. /*++
  332. Routine Description:
  333. GUM dispatch routine for creating a registry key.
  334. Arguments:
  335. SourceNode - Supplies whether or not this node initiated the GUM update.
  336. Not used.
  337. pSecurityInformation - Supplies a pointer to the security information
  338. KeyName - Supplies the key name
  339. lpSecurityDescriptor - Supplies the security descriptor to be
  340. applied.
  341. pGrantedAccess - Supplies the access that the key was opened with.
  342. Return Value:
  343. ERROR_SUCCESS if successful.
  344. Win32 error code otherwise.
  345. --*/
  346. {
  347. DWORD Status;
  348. HKEY Key;
  349. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  350. Status = RegOpenKeyExW(DmpRoot,
  351. KeyName,
  352. 0,
  353. *pGrantedAccess,
  354. &Key);
  355. if (Status != ERROR_SUCCESS) {
  356. if ((Status == ERROR_ACCESS_DENIED) ||
  357. (Status == ERROR_PRIVILEGE_NOT_HELD)) {
  358. BOOLEAN Enabled;
  359. Status = ClRtlEnableThreadPrivilege(SE_SECURITY_PRIVILEGE,
  360. &Enabled);
  361. if (Status == ERROR_SUCCESS) {
  362. Status = RegOpenKeyExW(DmpRoot,
  363. KeyName,
  364. 0,
  365. *pGrantedAccess,
  366. &Key);
  367. ClRtlRestoreThreadPrivilege(SE_SECURITY_PRIVILEGE,
  368. Enabled);
  369. }
  370. }
  371. if (Status != ERROR_SUCCESS) {
  372. goto FnExit;
  373. }
  374. }
  375. Status = RegSetKeySecurity(Key,
  376. *pSecurityInformation,
  377. lpSecurityDescriptor);
  378. RegCloseKey(Key);
  379. if (Status == ERROR_SUCCESS) {
  380. DmpUpdateSequence();
  381. DmpReportNotify(KeyName, CLUSTER_CHANGE_REGISTRY_ATTRIBUTES);
  382. }
  383. FnExit:
  384. RELEASE_LOCK(gLockDmpRoot);
  385. return(Status);
  386. }