Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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