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.

1746 lines
50 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Cluster control functions.
  7. Author:
  8. Mike Massa (mikemas) 23-Jan-1998
  9. Revision History:
  10. --*/
  11. #include "initp.h"
  12. //
  13. // Parameter block used for setting all cluster properties.
  14. //
  15. typedef struct {
  16. LPWSTR AdminExtensions;
  17. DWORD AdminExtensionsLength;
  18. CLUSTER_NETWORK_ROLE DefaultNetworkRole;
  19. LPWSTR Description;
  20. LPBYTE Security;
  21. DWORD SecurityLength;
  22. LPBYTE SecurityDescriptor;
  23. DWORD SecurityDescriptorLength;
  24. LPWSTR GroupsAdminExtensions;
  25. DWORD GroupsAdminExtensionsLength;
  26. LPWSTR NetworksAdminExtensions;
  27. DWORD NetworksAdminExtensionsLength;
  28. LPWSTR NetworkInterfacesAdminExtensions;
  29. DWORD NetworkInterfacesAdminExtensionsLength;
  30. LPWSTR NodesAdminExtensions;
  31. DWORD NodesAdminExtensionsLength;
  32. LPWSTR ResourcesAdminExtensions;
  33. DWORD ResourcesAdminExtensionsLength;
  34. LPWSTR ResourceTypesAdminExtensions;
  35. DWORD ResourceTypesAdminExtensionsLength;
  36. DWORD EnableEventLogReplication;
  37. DWORD QuorumArbitrationTimeout;
  38. DWORD QuorumArbitrationEqualizer;
  39. DWORD DisableGroupPreferredOwnerRandomization;
  40. DWORD EnableEventLogDeltaGeneration;
  41. DWORD EnableResourceDllDeadlockDetection;
  42. DWORD ResourceDllDeadlockTimeout;
  43. DWORD ResourceDllDeadlockThreshold;
  44. DWORD ResourceDllDeadlockPeriod;
  45. DWORD ClusSvcHeartbeatTimeout;
  46. ClussvcHangAction HangRecoveryAction;
  47. } CS_CLUSTER_INFO, *PCS_CLUSTER_INFO;
  48. //
  49. // Parameter block used for setting the cluster 'Security Descriptor' property
  50. //
  51. typedef struct {
  52. LPBYTE Security;
  53. DWORD SecurityLength;
  54. } CS_CLUSTER_SECURITY_INFO, *PCS_CLUSTER_SECURITY_INFO;
  55. //
  56. // Parameter block used for setting the cluster 'Security' property
  57. //
  58. typedef struct {
  59. LPBYTE SecurityDescriptor;
  60. DWORD SecurityDescriptorLength;
  61. } CS_CLUSTER_SD_INFO, *PCS_CLUSTER_SD_INFO;
  62. //
  63. // Cluster Common properties.
  64. //
  65. //
  66. // Read-Write Common Properties.
  67. //
  68. RESUTIL_PROPERTY_ITEM
  69. CspClusterCommonProperties[] = {
  70. { CLUSREG_NAME_ADMIN_EXT,
  71. NULL,
  72. CLUSPROP_FORMAT_MULTI_SZ,
  73. 0,
  74. 0,
  75. 0,
  76. 0,
  77. FIELD_OFFSET(CS_CLUSTER_INFO, AdminExtensions)
  78. },
  79. { CLUSREG_NAME_CLUS_DEFAULT_NETWORK_ROLE,
  80. NULL,
  81. CLUSPROP_FORMAT_DWORD,
  82. ClusterNetworkRoleClientAccess,
  83. ClusterNetworkRoleNone,
  84. ClusterNetworkRoleInternalAndClient,
  85. 0,
  86. FIELD_OFFSET(CS_CLUSTER_INFO, DefaultNetworkRole)
  87. },
  88. { CLUSREG_NAME_CLUS_DESC,
  89. NULL,
  90. CLUSPROP_FORMAT_SZ,
  91. 0,
  92. 0,
  93. 0,
  94. 0,
  95. FIELD_OFFSET(CS_CLUSTER_INFO, Description)
  96. },
  97. { CLUSREG_NAME_CLUS_SECURITY,
  98. NULL,
  99. CLUSPROP_FORMAT_BINARY,
  100. 0,
  101. 0,
  102. 0,
  103. 0,
  104. FIELD_OFFSET(CS_CLUSTER_INFO, Security)
  105. },
  106. { CLUSREG_NAME_CLUS_SD,
  107. NULL,
  108. CLUSPROP_FORMAT_BINARY,
  109. 0,
  110. 0,
  111. 0,
  112. 0,
  113. FIELD_OFFSET(CS_CLUSTER_INFO, SecurityDescriptor)
  114. },
  115. { CLUSREG_KEYNAME_GROUPS L"\\" CLUSREG_NAME_ADMIN_EXT,
  116. NULL,
  117. CLUSPROP_FORMAT_MULTI_SZ,
  118. 0,
  119. 0,
  120. 0,
  121. 0,
  122. FIELD_OFFSET(CS_CLUSTER_INFO, GroupsAdminExtensions)
  123. },
  124. { CLUSREG_KEYNAME_NETWORKS L"\\" CLUSREG_NAME_ADMIN_EXT,
  125. NULL,
  126. CLUSPROP_FORMAT_MULTI_SZ,
  127. 0,
  128. 0,
  129. 0,
  130. 0,
  131. FIELD_OFFSET(CS_CLUSTER_INFO, NetworksAdminExtensions)
  132. },
  133. { CLUSREG_KEYNAME_NETINTERFACES L"\\" CLUSREG_NAME_ADMIN_EXT,
  134. NULL,
  135. CLUSPROP_FORMAT_MULTI_SZ,
  136. 0,
  137. 0,
  138. 0,
  139. 0,
  140. FIELD_OFFSET(CS_CLUSTER_INFO, NetworkInterfacesAdminExtensions)
  141. },
  142. { CLUSREG_KEYNAME_NODES L"\\" CLUSREG_NAME_ADMIN_EXT,
  143. NULL,
  144. CLUSPROP_FORMAT_MULTI_SZ,
  145. 0,
  146. 0,
  147. 0,
  148. 0,
  149. FIELD_OFFSET(CS_CLUSTER_INFO, NodesAdminExtensions)
  150. },
  151. { CLUSREG_KEYNAME_RESOURCES L"\\" CLUSREG_NAME_ADMIN_EXT,
  152. NULL,
  153. CLUSPROP_FORMAT_MULTI_SZ,
  154. 0,
  155. 0,
  156. 0,
  157. 0,
  158. FIELD_OFFSET(CS_CLUSTER_INFO, ResourcesAdminExtensions)
  159. },
  160. { CLUSREG_KEYNAME_RESOURCE_TYPES L"\\" CLUSREG_NAME_ADMIN_EXT,
  161. NULL,
  162. CLUSPROP_FORMAT_MULTI_SZ,
  163. 0,
  164. 0,
  165. 0,
  166. 0,
  167. FIELD_OFFSET(CS_CLUSTER_INFO, ResourceTypesAdminExtensions)
  168. },
  169. { CLUSREG_NAME_CLUS_EVTLOG_PROPAGATION,
  170. NULL,
  171. CLUSPROP_FORMAT_DWORD,
  172. 1, // default value //
  173. 0, // min value //
  174. 1, // max value //
  175. 0,
  176. FIELD_OFFSET(CS_CLUSTER_INFO, EnableEventLogReplication)
  177. },
  178. { CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  179. NULL,
  180. CLUSPROP_FORMAT_DWORD,
  181. 60, // default value //
  182. 1, // min value //
  183. 60 * 60, // max value // One hour for arbitration. Should be enough
  184. 0,
  185. FIELD_OFFSET(CS_CLUSTER_INFO, QuorumArbitrationTimeout)
  186. },
  187. { CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER,
  188. NULL,
  189. CLUSPROP_FORMAT_DWORD,
  190. 7, // default value //
  191. 0, // min value //
  192. 60 * 60, // max value // One hour for arbitration. Should be enough
  193. 0,
  194. FIELD_OFFSET(CS_CLUSTER_INFO, QuorumArbitrationEqualizer)
  195. },
  196. { CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  197. NULL,
  198. CLUSPROP_FORMAT_DWORD,
  199. 0, // default value // don't disable randomization
  200. 0, // min value //
  201. 1, // max value //
  202. 0,
  203. FIELD_OFFSET(CS_CLUSTER_INFO, DisableGroupPreferredOwnerRandomization)
  204. },
  205. { CLUSREG_NAME_CLUS_EVTLOGDELTA_GENERATION,
  206. NULL,
  207. CLUSPROP_FORMAT_DWORD,
  208. 1, // default value //
  209. 0, // min value //
  210. 1, // max value //
  211. 0,
  212. FIELD_OFFSET(CS_CLUSTER_INFO, EnableEventLogDeltaGeneration)
  213. },
  214. { CLUSREG_NAME_CLUS_ENABLE_RESOURCE_DLL_DEADLOCK_DETECTION,
  215. NULL,
  216. CLUSPROP_FORMAT_DWORD,
  217. 0, // default value //
  218. 0, // min value //
  219. 1, // max value //
  220. 0,
  221. FIELD_OFFSET(CS_CLUSTER_INFO, EnableResourceDllDeadlockDetection)
  222. },
  223. { CLUSREG_NAME_CLUS_RESOURCE_DLL_DEADLOCK_TIMEOUT,
  224. NULL,
  225. CLUSPROP_FORMAT_DWORD,
  226. CLUSTER_RESOURCE_DLL_DEFAULT_DEADLOCK_TIMEOUT_SECS, // default value in secs //
  227. CLUSTER_RESOURCE_DLL_MINIMUM_DEADLOCK_TIMEOUT_SECS, // min value in secs //
  228. CLUSTER_RESOURCE_DLL_MAXIMUM_DEADLOCK_TIMEOUT_SECS, // max value in secs //
  229. 0,
  230. FIELD_OFFSET(CS_CLUSTER_INFO, ResourceDllDeadlockTimeout)
  231. },
  232. { CLUSREG_NAME_CLUS_RESOURCE_DLL_DEADLOCK_THRESHOLD,
  233. NULL,
  234. CLUSPROP_FORMAT_DWORD,
  235. CLUSTER_RESOURCE_DLL_DEFAULT_DEADLOCK_THRESHOLD, // default value in secs //
  236. CLUSTER_RESOURCE_DLL_MINIMUM_DEADLOCK_THRESHOLD, // min value in secs //
  237. CLUSTER_RESOURCE_DLL_MAXIMUM_DEADLOCK_THRESHOLD, // max value in secs //
  238. 0,
  239. FIELD_OFFSET(CS_CLUSTER_INFO, ResourceDllDeadlockThreshold)
  240. },
  241. { CLUSREG_NAME_CLUS_RESOURCE_DLL_DEADLOCK_PERIOD,
  242. NULL,
  243. CLUSPROP_FORMAT_DWORD,
  244. CLUSTER_RESOURCE_DLL_DEFAULT_DEADLOCK_PERIOD_SECS, // default value in secs //
  245. CLUSTER_RESOURCE_DLL_MINIMUM_DEADLOCK_PERIOD_SECS, // min value in secs //
  246. CLUSTER_RESOURCE_DLL_MAXIMUM_DEADLOCK_PERIOD_SECS, // max value in secs //
  247. 0,
  248. FIELD_OFFSET(CS_CLUSTER_INFO, ResourceDllDeadlockPeriod)
  249. },
  250. { CLUSTER_HEARTBEAT_TIMEOUT_KEYNAME,
  251. NULL,
  252. CLUSPROP_FORMAT_DWORD,
  253. CLUSTER_HEARTBEAT_TIMEOUT_DEFAULT,
  254. CLUSTER_HEARTBEAT_TIMEOUT_MIN,
  255. 0xFFFFFFFF,
  256. 0,
  257. FIELD_OFFSET(CS_CLUSTER_INFO, ClusSvcHeartbeatTimeout)
  258. },
  259. { CLUSTER_HANG_RECOVERY_ACTION_KEYNAME,
  260. NULL,
  261. CLUSPROP_FORMAT_DWORD,
  262. CLUSTER_HANG_RECOVERY_ACTION_DEFAULT,
  263. ClussvcHangActionDisable,
  264. ClussvcHangActionBugCheckMachine,
  265. 0,
  266. FIELD_OFFSET(CS_CLUSTER_INFO, HangRecoveryAction)
  267. },
  268. { NULL, NULL, 0, 0, 0, 0, 0 } };
  269. //
  270. // Property table used for setting the cluster 'Security Descriptor' property
  271. //
  272. RESUTIL_PROPERTY_ITEM
  273. CspClusterSDProperty[] = {
  274. { CLUSREG_NAME_CLUS_SD,
  275. NULL,
  276. CLUSPROP_FORMAT_BINARY,
  277. 0,
  278. 0,
  279. 0,
  280. 0,
  281. FIELD_OFFSET(CS_CLUSTER_SD_INFO, SecurityDescriptor)
  282. },
  283. { NULL, NULL, 0, 0, 0, 0, 0 } };
  284. //
  285. // Property table used for setting the cluster 'Security' property
  286. //
  287. RESUTIL_PROPERTY_ITEM
  288. CspClusterSecurityProperty[] = {
  289. { CLUSREG_NAME_CLUS_SECURITY,
  290. NULL,
  291. CLUSPROP_FORMAT_BINARY,
  292. 0,
  293. 0,
  294. 0,
  295. 0,
  296. FIELD_OFFSET(CS_CLUSTER_SECURITY_INFO, Security)
  297. },
  298. { NULL, NULL, 0, 0, 0, 0, 0 } };
  299. //
  300. // Read-Only Common Properties.
  301. //
  302. RESUTIL_PROPERTY_ITEM
  303. CspClusterROCommonProperties[] = {
  304. { NULL, NULL, 0, 0, 0, 0, 0 } };
  305. //
  306. // Cluster registry API function pointers.
  307. //
  308. CLUSTER_REG_APIS
  309. CspClusterRegApis = {
  310. (PFNCLRTLCREATEKEY) DmRtlCreateKey,
  311. (PFNCLRTLOPENKEY) DmRtlOpenKey,
  312. (PFNCLRTLCLOSEKEY) DmCloseKey,
  313. (PFNCLRTLSETVALUE) DmSetValue,
  314. (PFNCLRTLQUERYVALUE) DmQueryValue,
  315. (PFNCLRTLENUMVALUE) DmEnumValue,
  316. (PFNCLRTLDELETEVALUE) DmDeleteValue,
  317. NULL,
  318. NULL,
  319. NULL
  320. };
  321. //
  322. // Local Functions
  323. //
  324. DWORD
  325. CspClusterControl(
  326. IN DWORD ControlCode,
  327. IN PUCHAR InBuffer,
  328. IN DWORD InBufferSize,
  329. OUT PUCHAR OutBuffer,
  330. IN DWORD OutBufferSize,
  331. OUT LPDWORD BytesReturned,
  332. OUT LPDWORD Required
  333. );
  334. DWORD
  335. CspClusterEnumCommonProperties(
  336. OUT PVOID OutBuffer,
  337. IN DWORD OutBufferSize,
  338. OUT LPDWORD BytesReturned,
  339. OUT LPDWORD Required
  340. );
  341. DWORD
  342. CspClusterGetCommonProperties(
  343. IN BOOL ReadOnly,
  344. IN HDMKEY RegistryKey,
  345. OUT PVOID OutBuffer,
  346. IN DWORD OutBufferSize,
  347. OUT LPDWORD BytesReturned,
  348. OUT LPDWORD Required
  349. );
  350. DWORD
  351. CspClusterValidateCommonProperties(
  352. IN HDMKEY RegistryKey,
  353. IN PVOID InBuffer,
  354. IN DWORD InBufferSize
  355. );
  356. DWORD
  357. CspClusterSetCommonProperties(
  358. IN HDMKEY RegistryKey,
  359. IN PVOID InBuffer,
  360. IN DWORD InBufferSize
  361. );
  362. DWORD
  363. CspClusterEnumPrivateProperties(
  364. IN HDMKEY RegistryKey,
  365. OUT PVOID OutBuffer,
  366. IN DWORD OutBufferSize,
  367. OUT LPDWORD BytesReturned,
  368. OUT LPDWORD Required
  369. );
  370. DWORD
  371. CspClusterGetPrivateProperties(
  372. IN HDMKEY RegistryKey,
  373. OUT PVOID OutBuffer,
  374. IN DWORD OutBufferSize,
  375. OUT LPDWORD BytesReturned,
  376. OUT LPDWORD Required
  377. );
  378. DWORD
  379. CspClusterValidatePrivateProperties(
  380. IN HDMKEY RegistryKey,
  381. IN PVOID InBuffer,
  382. IN DWORD InBufferSize
  383. );
  384. DWORD
  385. CspClusterSetPrivateProperties(
  386. IN HDMKEY RegistryKey,
  387. IN PVOID InBuffer,
  388. IN DWORD InBufferSize
  389. );
  390. DWORD
  391. WINAPI
  392. CsClusterControl(
  393. IN PNM_NODE HostNode OPTIONAL,
  394. IN DWORD ControlCode,
  395. IN PUCHAR InBuffer,
  396. IN DWORD InBufferSize,
  397. OUT PUCHAR OutBuffer,
  398. IN DWORD OutBufferSize,
  399. OUT LPDWORD BytesReturned,
  400. OUT LPDWORD Required
  401. )
  402. /*++
  403. Routine Description:
  404. Provides for arbitrary communication and control between an application
  405. and a cluster.
  406. Arguments:
  407. HostNode - Supplies the host node on which the cluster control should
  408. be delivered. If this is NULL, the local node is used. Not honored!
  409. ControlCode- Supplies the control code that defines the
  410. structure and action of the cluster control.
  411. Values of ControlCode between 0 and 0x10000000 are reserved
  412. for future definition and use by Microsoft. All other values
  413. are available for use by ISVs
  414. InBuffer- Supplies a pointer to the input buffer to be passed
  415. to the cluster.
  416. InBufferSize- Supplies the size, in bytes, of the data pointed
  417. to by lpInBuffer..
  418. OutBuffer- Supplies a pointer to the output buffer to be
  419. filled in by the cluster..
  420. OutBufferSize- Supplies the size, in bytes, of the available
  421. space pointed to by lpOutBuffer.
  422. BytesReturned - Returns the number of bytes of lpOutBuffer
  423. actually filled in by the cluster.
  424. Required - Returns the number of bytes if the OutBuffer is not big
  425. enough.
  426. Return Value:
  427. ERROR_SUCCESS if successful
  428. Win32 error code otherwise
  429. --*/
  430. {
  431. DWORD status;
  432. //
  433. // In the future - we should verify the access mode!
  434. //
  435. if ( CLUSCTL_GET_CONTROL_OBJECT( ControlCode ) != CLUS_OBJECT_CLUSTER ) {
  436. return(ERROR_INVALID_FUNCTION);
  437. }
  438. status = CspClusterControl(
  439. ControlCode,
  440. InBuffer,
  441. InBufferSize,
  442. OutBuffer,
  443. OutBufferSize,
  444. BytesReturned,
  445. Required
  446. );
  447. return(status);
  448. } // CsClusterControl
  449. DWORD
  450. CspClusterControl(
  451. IN DWORD ControlCode,
  452. IN PUCHAR InBuffer,
  453. IN DWORD InBufferSize,
  454. OUT PUCHAR OutBuffer,
  455. IN DWORD OutBufferSize,
  456. OUT LPDWORD BytesReturned,
  457. OUT LPDWORD Required
  458. )
  459. /*++
  460. Routine Description:
  461. Provides for arbitrary communication and control between an application
  462. and a specific instance of a node.
  463. Arguments:
  464. ControlCode- Supplies the control code that defines the
  465. structure and action of the cluster control.
  466. Values of ControlCode between 0 and 0x10000000 are reserved
  467. for future definition and use by Microsoft. All other values
  468. are available for use by ISVs
  469. InBuffer- Supplies a pointer to the input buffer to be passed
  470. to the cluster.
  471. InBufferSize- Supplies the size, in bytes, of the data pointed
  472. to by lpInBuffer.
  473. OutBuffer- Supplies a pointer to the output buffer to be
  474. filled in by the cluster.
  475. OutBufferSize- Supplies the size, in bytes, of the available
  476. space pointed to by OutBuffer.
  477. BytesReturned - Returns the number of bytes of lpOutBuffer
  478. actually filled in by the cluster.
  479. Required - Returns the number of bytes if the OutBuffer is not big
  480. enough.
  481. Return Value:
  482. ERROR_SUCCESS if successful
  483. Win32 error code otherwise
  484. --*/
  485. {
  486. DWORD status;
  487. CLUSPROP_BUFFER_HELPER props;
  488. DWORD bufSize;
  489. BOOL success;
  490. DWORD nameLenChars;
  491. DWORD charsLeft;
  492. LPWSTR FQDNBuffer = (LPWSTR)OutBuffer;
  493. if (DmClusterParametersKey == NULL) {
  494. return(ERROR_SHARING_PAUSED);
  495. }
  496. switch ( ControlCode ) {
  497. case CLUSCTL_CLUSTER_UNKNOWN:
  498. *BytesReturned = 0;
  499. status = ERROR_SUCCESS;
  500. break;
  501. case CLUSCTL_CLUSTER_GET_COMMON_PROPERTY_FMTS:
  502. status = ClRtlGetPropertyFormats( CspClusterCommonProperties,
  503. OutBuffer,
  504. OutBufferSize,
  505. BytesReturned,
  506. Required );
  507. break;
  508. case CLUSCTL_CLUSTER_GET_FQDN:
  509. //
  510. // we leverage the passed in buffer directly; if the user didn't pass
  511. // in a large enough buffer, then clussvc won't return a partially
  512. // filled buffer; it will be null.
  513. //
  514. // get the length of the cluster name without the trailing null and
  515. // the amount of chars in the Output buffer.
  516. //
  517. nameLenChars = wcslen( CsClusterName );
  518. charsLeft = OutBufferSize / sizeof( WCHAR );
  519. if ( nameLenChars < charsLeft ) {
  520. //
  521. // output buffer is large enough to contain the name so copy it to
  522. // the beginning of the output buffer. wcsncpy will put a
  523. // terminating NULL in since the buffer is large enough to hold it.
  524. //
  525. wcsncpy( FQDNBuffer, CsClusterName, charsLeft );
  526. //
  527. // indicate remaining space by subtracting out the length of the
  528. // cluster name and the separating dot between the hostname and
  529. // the suffix.
  530. //
  531. charsLeft -= ( nameLenChars + 1 );
  532. } else {
  533. //
  534. // not enough space for the cluster name means we won't have
  535. // enough space for the domain portion.
  536. //
  537. charsLeft = 0;
  538. }
  539. //
  540. // charsLeft will be modified to reflect the number of chars written
  541. // to the buffer. If the buffer is too small, the terminating null is
  542. // included, otherwise the terminating null is NOT included.
  543. //
  544. success = GetComputerNameEx( ComputerNameDnsDomain,
  545. &FQDNBuffer[ nameLenChars + 1 ],
  546. &charsLeft );
  547. if ( success ) {
  548. if ( charsLeft > 0 ) {
  549. //
  550. // there was enough space for the domain name and something
  551. // was copied (on NT4 DCs, there is no primary DNS suffix, so
  552. // GCNEx returns success but with a returned copied char count
  553. // of zero). Add the period between the hostname and the
  554. // domain suffix. If charsLeft is zero, then the name is
  555. // properly terminated by the wcsncpy above.
  556. //
  557. FQDNBuffer[ nameLenChars ] = L'.';
  558. }
  559. //
  560. // calc the total number of bytes in the buffer by adding the
  561. // cluster name length to the domain name length. Add one for
  562. // either the separating dot or the NULL terminator (in the NT4 DC
  563. // case). Add one at the end since the terminating null is not
  564. // included in charsLeft when soemthing was successfully copied.
  565. //
  566. *BytesReturned = ( nameLenChars + 1 + charsLeft + 1 ) * sizeof( WCHAR );
  567. status = ERROR_SUCCESS;
  568. } else {
  569. status = GetLastError();
  570. if ( status == ERROR_MORE_DATA ) {
  571. //
  572. // GetComputerNameEx does return the full length (including
  573. // the terminating null) when you don't supply a large enough
  574. // buffer. Sheesh!
  575. //
  576. *Required = ( nameLenChars + 1 + charsLeft ) * sizeof( WCHAR );
  577. } else {
  578. *Required = 0;
  579. }
  580. *BytesReturned = 0;
  581. }
  582. break;
  583. case CLUSCTL_CLUSTER_ENUM_COMMON_PROPERTIES:
  584. status = CspClusterEnumCommonProperties(
  585. OutBuffer,
  586. OutBufferSize,
  587. BytesReturned,
  588. Required
  589. );
  590. break;
  591. case CLUSCTL_CLUSTER_GET_RO_COMMON_PROPERTIES:
  592. status = CspClusterGetCommonProperties(
  593. TRUE, // ReadOnly
  594. DmClusterParametersKey,
  595. OutBuffer,
  596. OutBufferSize,
  597. BytesReturned,
  598. Required
  599. );
  600. break;
  601. case CLUSCTL_CLUSTER_GET_COMMON_PROPERTIES:
  602. status = CspClusterGetCommonProperties(
  603. FALSE, // ReadOnly
  604. DmClusterParametersKey,
  605. OutBuffer,
  606. OutBufferSize,
  607. BytesReturned,
  608. Required
  609. );
  610. break;
  611. case CLUSCTL_CLUSTER_VALIDATE_COMMON_PROPERTIES:
  612. status = CspClusterValidateCommonProperties(
  613. DmClusterParametersKey,
  614. InBuffer,
  615. InBufferSize
  616. );
  617. break;
  618. case CLUSCTL_CLUSTER_SET_COMMON_PROPERTIES:
  619. status = CspClusterSetCommonProperties(
  620. DmClusterParametersKey,
  621. InBuffer,
  622. InBufferSize
  623. );
  624. break;
  625. case CLUSCTL_CLUSTER_ENUM_PRIVATE_PROPERTIES:
  626. status = CspClusterEnumPrivateProperties(
  627. DmClusterParametersKey,
  628. OutBuffer,
  629. OutBufferSize,
  630. BytesReturned,
  631. Required
  632. );
  633. break;
  634. case CLUSCTL_CLUSTER_GET_RO_PRIVATE_PROPERTIES:
  635. if ( OutBufferSize < sizeof(DWORD) ) {
  636. *BytesReturned = 0;
  637. *Required = sizeof(DWORD);
  638. if ( OutBuffer == NULL ) {
  639. status = ERROR_SUCCESS;
  640. } else {
  641. status = ERROR_MORE_DATA;
  642. }
  643. } else {
  644. LPDWORD ptrDword = (LPDWORD) OutBuffer;
  645. *ptrDword = 0;
  646. *BytesReturned = sizeof(DWORD);
  647. status = ERROR_SUCCESS;
  648. }
  649. break;
  650. case CLUSCTL_CLUSTER_GET_PRIVATE_PROPERTIES:
  651. status = CspClusterGetPrivateProperties(
  652. DmClusterParametersKey,
  653. OutBuffer,
  654. OutBufferSize,
  655. BytesReturned,
  656. Required
  657. );
  658. break;
  659. case CLUSCTL_CLUSTER_VALIDATE_PRIVATE_PROPERTIES:
  660. status = CspClusterValidatePrivateProperties(
  661. DmClusterParametersKey,
  662. InBuffer,
  663. InBufferSize
  664. );
  665. break;
  666. case CLUSCTL_CLUSTER_SET_PRIVATE_PROPERTIES:
  667. status = CspClusterSetPrivateProperties(
  668. DmClusterParametersKey,
  669. InBuffer,
  670. InBufferSize
  671. );
  672. break;
  673. default:
  674. status = ERROR_INVALID_FUNCTION;
  675. break;
  676. }
  677. return(status);
  678. } // CspClusterControl
  679. DWORD
  680. CspClusterEnumCommonProperties(
  681. OUT PVOID OutBuffer,
  682. IN DWORD OutBufferSize,
  683. OUT LPDWORD BytesReturned,
  684. OUT LPDWORD Required
  685. )
  686. /*++
  687. Routine Description:
  688. Enumerates the common property names for a given node.
  689. Arguments:
  690. OutBuffer - Supplies the output buffer.
  691. OutBufferSize - Supplies the size of the output buffer.
  692. BytesReturned - The number of bytes returned in OutBuffer.
  693. Required - The required number of bytes if OutBuffer is too small.
  694. Return Value:
  695. ERROR_SUCCESS if successful.
  696. A Win32 error code on failure.
  697. --*/
  698. {
  699. DWORD status;
  700. //
  701. // Get the common properties.
  702. //
  703. status = ClRtlEnumProperties(
  704. CspClusterCommonProperties,
  705. OutBuffer,
  706. OutBufferSize,
  707. BytesReturned,
  708. Required
  709. );
  710. return(status);
  711. } // CspClusterEnumCommonProperties
  712. DWORD
  713. CspClusterGetCommonProperties(
  714. IN BOOL ReadOnly,
  715. IN HDMKEY RegistryKey,
  716. OUT PVOID OutBuffer,
  717. IN DWORD OutBufferSize,
  718. OUT LPDWORD BytesReturned,
  719. OUT LPDWORD Required
  720. )
  721. /*++
  722. Routine Description:
  723. Gets the common properties for a given cluster.
  724. Arguments:
  725. ReadOnly - TRUE if the read-only properties should be read.
  726. FALSE otherwise.
  727. RegistryKey - Supplies the registry key for this cluster.
  728. OutBuffer - Supplies the output buffer.
  729. OutBufferSize - Supplies the size of the output buffer.
  730. BytesReturned - The number of bytes returned in OutBuffer.
  731. Required - The required number of bytes if OutBuffer is too small.
  732. Return Value:
  733. ERROR_SUCCESS if successful.
  734. A Win32 error code on failure.
  735. --*/
  736. {
  737. DWORD status;
  738. PRESUTIL_PROPERTY_ITEM propertyTable;
  739. if ( ReadOnly ) {
  740. propertyTable = CspClusterROCommonProperties;
  741. } else {
  742. propertyTable = CspClusterCommonProperties;
  743. }
  744. //
  745. // Get the common properties.
  746. //
  747. status = ClRtlGetProperties( RegistryKey,
  748. &CspClusterRegApis,
  749. propertyTable,
  750. OutBuffer,
  751. OutBufferSize,
  752. BytesReturned,
  753. Required );
  754. return(status);
  755. } // CspClusterGetCommonProperties
  756. DWORD
  757. CspValidateSecurityProperties(
  758. IN PVOID InBuffer,
  759. IN DWORD InBufferSize
  760. )
  761. /*++
  762. Routine Description:
  763. Searches for either of the security properties and validates that they are
  764. legitimate security descriptors.
  765. Arguments:
  766. InBuffer - Supplies the buffer containing the property list.
  767. InBufferSize - Supplies the size of the input buffer.
  768. Return Value:
  769. ERROR_SUCCESS if successful.
  770. A Win32 error code on failure.
  771. --*/
  772. {
  773. DWORD status;
  774. LPWSTR propNames[] = { CLUSREG_NAME_CLUS_SD, CLUSREG_NAME_CLUS_SECURITY };
  775. DWORD i;
  776. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  777. DWORD cbSecurityDescriptorSize = 0;
  778. //
  779. // See if either the "Security Descriptor" (W2K) or Security (NT4)
  780. // property exists in the input property list. If so, perform some basic
  781. // validatation.
  782. //
  783. for ( i = 0; i < RTL_NUMBER_OF( propNames ); ++i ) {
  784. status = ClRtlFindBinaryProperty(InBuffer,
  785. InBufferSize,
  786. propNames[i],
  787. (LPBYTE *) &pSecurityDescriptor,
  788. &cbSecurityDescriptorSize
  789. );
  790. if ( status == ERROR_SUCCESS ) {
  791. //
  792. // a valid security property is present; make sure it is non-null
  793. // and contains a valid SD
  794. //
  795. if ( cbSecurityDescriptorSize == 0 ||
  796. IsValidSecurityDescriptor( pSecurityDescriptor ) == FALSE )
  797. {
  798. status = ERROR_INVALID_SECURITY_DESCR;
  799. }
  800. LocalFree( pSecurityDescriptor );
  801. pSecurityDescriptor = NULL;
  802. }
  803. else if ( status == ERROR_FILE_NOT_FOUND ) {
  804. //
  805. // not an error if these properties are not present
  806. //
  807. status = ERROR_SUCCESS;
  808. }
  809. if ( status != ERROR_SUCCESS ) {
  810. break;
  811. }
  812. }
  813. return status;
  814. }
  815. DWORD
  816. CspClusterValidateCommonProperties(
  817. IN HDMKEY RegistryKey,
  818. IN PVOID InBuffer,
  819. IN DWORD InBufferSize
  820. )
  821. /*++
  822. Routine Description:
  823. Validates the common properties for a given cluster.
  824. Arguments:
  825. Node - Supplies the cluster object.
  826. InBuffer - Supplies the input buffer.
  827. InBufferSize - Supplies the size of the input buffer.
  828. Return Value:
  829. ERROR_SUCCESS if successful.
  830. A Win32 error code on failure.
  831. --*/
  832. {
  833. DWORD status;
  834. //
  835. // Validate the property list.
  836. //
  837. status = ClRtlVerifyPropertyTable( CspClusterCommonProperties,
  838. NULL, // Reserved
  839. FALSE, // Don't allow unknowns
  840. InBuffer,
  841. InBufferSize,
  842. NULL );
  843. if ( status == ERROR_SUCCESS ) {
  844. status = CspValidateSecurityProperties( InBuffer, InBufferSize );
  845. if ( status != ERROR_SUCCESS ) {
  846. ClRtlLogPrint(LOG_CRITICAL,
  847. "[CS] ValidateCommonProperties: invalid security "
  848. "property change. status %1!u!\n",
  849. status);
  850. }
  851. }
  852. else {
  853. ClRtlLogPrint( LOG_CRITICAL,
  854. "[CS] ValidateCommonProperties: error in verify routine. status %1!u!\n",
  855. status);
  856. }
  857. return(status);
  858. } // CspClusterValidateCommonProperties
  859. DWORD
  860. CspClusterSetCommonProperties(
  861. IN HDMKEY RegistryKey,
  862. IN PVOID InBuffer,
  863. IN DWORD InBufferSize
  864. )
  865. /*++
  866. Routine Description:
  867. Sets the common properties for a given cluster.
  868. Arguments:
  869. Node - Supplies the cluster object.
  870. InBuffer - Supplies the input buffer.
  871. InBufferSize - Supplies the size of the input buffer.
  872. Return Value:
  873. ERROR_SUCCESS if successful.
  874. A Win32 error code on failure.
  875. --*/
  876. {
  877. DWORD status;
  878. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  879. DWORD cbSecurityDescriptorSize = 0;
  880. PRESUTIL_PROPERTY_ITEM pOtherPropertyTable = NULL;
  881. LPBYTE pOtherParameterBlock = NULL;
  882. BOOL bSDFound = FALSE;
  883. BOOL bSecurityFound = FALSE;
  884. DWORD dwValue;
  885. //
  886. // Only one of securityInfo or sdInfo is going to be used at at time.
  887. // So use a union.
  888. //
  889. union
  890. {
  891. CS_CLUSTER_SECURITY_INFO securityInfo;
  892. CS_CLUSTER_SD_INFO sdInfo;
  893. } paramBlocks;
  894. //
  895. // Dummy do-while loop to avoid gotos
  896. //
  897. do
  898. {
  899. //
  900. // Validate the property list.
  901. //
  902. status = CspClusterValidateCommonProperties(
  903. RegistryKey,
  904. InBuffer,
  905. InBufferSize );
  906. if ( status != ERROR_SUCCESS ) {
  907. ClRtlLogPrint( LOG_CRITICAL,
  908. "[CS] ClusterSetCommonProperties, error trying to verify property table. %1!u!\n",
  909. status);
  910. break;
  911. }
  912. //
  913. // Set all the properties that were passed in.
  914. //
  915. status = ClRtlSetPropertyTable(
  916. NULL,
  917. RegistryKey,
  918. &CspClusterRegApis,
  919. CspClusterCommonProperties,
  920. NULL, // Reserved
  921. FALSE, // Don't allow unknowns
  922. InBuffer,
  923. InBufferSize,
  924. FALSE, // bForceWrite
  925. NULL
  926. );
  927. if ( status != ERROR_SUCCESS ) {
  928. ClRtlLogPrint( LOG_CRITICAL,
  929. "[CS] ClusterSetCommonProperties, error trying to set properties in table. %1!u!\n",
  930. status);
  931. break;
  932. }
  933. //
  934. // Clear the parameter blocks.
  935. //
  936. ZeroMemory( &paramBlocks, sizeof( paramBlocks ) );
  937. //
  938. // See if the "Security Descriptor" property exists in the input
  939. // property list. If so, set the 'Security' property also.
  940. status = ClRtlFindBinaryProperty(
  941. InBuffer,
  942. InBufferSize,
  943. CLUSREG_NAME_CLUS_SD,
  944. (LPBYTE *) &pSecurityDescriptor,
  945. &cbSecurityDescriptorSize
  946. );
  947. if ( status == ERROR_SUCCESS ) {
  948. //
  949. // The 'Security Descriptor' property is present.
  950. // Choose this over the 'Security' property.
  951. //
  952. if ( cbSecurityDescriptorSize > 0 ) {
  953. //
  954. // A security descriptor of nonzero size has been found.
  955. // Check if this is a valid security descriptor.
  956. //
  957. if ( IsValidSecurityDescriptor( pSecurityDescriptor ) == FALSE ) {
  958. //
  959. // Return the most appropriate error code, since IsValidSecurityDescriptor
  960. // does not provide extended error information.
  961. //
  962. ClRtlLogPrint( LOG_CRITICAL,
  963. "[CS] ClusterSetCommonProperties, Invalid security descriptor.\n");
  964. status = ERROR_INVALID_DATA;
  965. break;
  966. }
  967. paramBlocks.securityInfo.Security = ClRtlConvertClusterSDToNT4Format( pSecurityDescriptor );
  968. //
  969. // Bail on error
  970. //
  971. if ( paramBlocks.securityInfo.Security == NULL ) {
  972. status = GetLastError();
  973. ClRtlLogPrint(LOG_CRITICAL,
  974. "[CS] ClusterSetCommonProperties, Unable to convert SD to NT4 format, status %1!u!\n",
  975. status);
  976. break;
  977. }
  978. paramBlocks.securityInfo.SecurityLength = GetSecurityDescriptorLength(
  979. paramBlocks.securityInfo.Security );
  980. }
  981. else {
  982. //
  983. // The security string could have been passed in, but it may be
  984. // a zero length buffer. In this case, we will delete the
  985. // Security property too.
  986. //
  987. paramBlocks.securityInfo.Security = NULL;
  988. paramBlocks.securityInfo.SecurityLength = 0;
  989. }
  990. bSDFound = TRUE;
  991. pOtherPropertyTable = CspClusterSecurityProperty;
  992. pOtherParameterBlock = (LPBYTE) &paramBlocks.securityInfo;
  993. }
  994. else {
  995. //
  996. // We haven't found a valid security descriptor so far.
  997. //
  998. PSECURITY_DESCRIPTOR pSecurity = NULL;
  999. DWORD cbSecuritySize = 0;
  1000. status = ClRtlFindBinaryProperty(
  1001. InBuffer,
  1002. InBufferSize,
  1003. CLUSREG_NAME_CLUS_SECURITY,
  1004. (LPBYTE *) &pSecurity,
  1005. &cbSecuritySize
  1006. );
  1007. if ( status == ERROR_SUCCESS ) {
  1008. if ( cbSecuritySize > 0 ) {
  1009. //
  1010. // A security descriptor of nonzero size has been found.
  1011. // Check if this is a valid security descriptor.
  1012. //
  1013. if ( IsValidSecurityDescriptor( pSecurity ) == FALSE ) {
  1014. //
  1015. // Return the most appropriate error code, since IsValidSecurityDescriptor
  1016. // does not provide extended error information.
  1017. //
  1018. ClRtlLogPrint( LOG_CRITICAL,
  1019. "[CS] ClusterSetCommonProperties, Invalid security descriptor.\n");
  1020. status = ERROR_INVALID_DATA;
  1021. break;
  1022. }
  1023. //
  1024. // Since we will not be modifying the info pointed to by the parameter block,
  1025. // just point it to the right place in the input buffer itself.
  1026. // A valid NT4 security descriptor is valid for NT5 too.
  1027. //
  1028. paramBlocks.sdInfo.SecurityDescriptor = pSecurity;
  1029. paramBlocks.sdInfo.SecurityDescriptorLength = cbSecuritySize;
  1030. }
  1031. else {
  1032. //
  1033. // The security string could have been passed in, but it may be
  1034. // a zero length buffer. In this case, we will delete the
  1035. // Security Descriptor property too.
  1036. //
  1037. paramBlocks.sdInfo.SecurityDescriptor = NULL;
  1038. paramBlocks.sdInfo.SecurityDescriptorLength = 0;
  1039. }
  1040. bSecurityFound = TRUE;
  1041. pOtherPropertyTable = CspClusterSDProperty;
  1042. pOtherParameterBlock = (LPBYTE) &paramBlocks.sdInfo;
  1043. }
  1044. else {
  1045. //
  1046. // We didn't find any security information.
  1047. // Nevertheless, we were successful in setting the properties.
  1048. //
  1049. status = ERROR_SUCCESS;
  1050. }
  1051. }
  1052. if ( ( bSDFound != FALSE ) || ( bSecurityFound != FALSE ) ) {
  1053. PVOID pPropertyList = NULL;
  1054. DWORD cbPropertyListSize = 0;
  1055. DWORD cbBytesReturned = 0;
  1056. DWORD cbBytesRequired = 0;
  1057. //
  1058. // Create a new property list to incorporate the changed security information.
  1059. //
  1060. status = ClRtlPropertyListFromParameterBlock(
  1061. pOtherPropertyTable,
  1062. NULL, // OUT PVOID pOutPropertyList
  1063. &cbPropertyListSize, // IN OUT LPDWORD pcbOutPropertyListSize
  1064. pOtherParameterBlock,
  1065. &cbBytesReturned,
  1066. &cbBytesRequired
  1067. );
  1068. if ( status != ERROR_MORE_DATA ) {
  1069. //
  1070. // We have passed in a NULL buffer, so the return code has to
  1071. // be ERROR_MORE_DATA. Otherwise something else has gone wrong,
  1072. // so abort.
  1073. //
  1074. ClRtlLogPrint( LOG_CRITICAL,
  1075. "[CS] ClusterSetCommonProperties, Error getting temporary "
  1076. "property list size. %1!u!\n",
  1077. status);
  1078. break;
  1079. }
  1080. pPropertyList = LocalAlloc( LMEM_FIXED, cbBytesRequired );
  1081. if ( pPropertyList == NULL ) {
  1082. status = GetLastError();
  1083. ClRtlLogPrint( LOG_CRITICAL,
  1084. "[CS] ClusterSetCommonProperties, Error allocating memory "
  1085. "for property list. %1!u!\n",
  1086. status);
  1087. break;
  1088. }
  1089. cbPropertyListSize = cbBytesRequired;
  1090. status = ClRtlPropertyListFromParameterBlock(
  1091. pOtherPropertyTable,
  1092. pPropertyList,
  1093. &cbPropertyListSize,
  1094. pOtherParameterBlock,
  1095. &cbBytesReturned,
  1096. &cbBytesRequired
  1097. );
  1098. if ( status == ERROR_SUCCESS ) {
  1099. status = ClRtlSetPropertyTable(
  1100. NULL,
  1101. RegistryKey,
  1102. &CspClusterRegApis,
  1103. pOtherPropertyTable,
  1104. NULL, // Reserved
  1105. FALSE, // Don't allow unknowns
  1106. pPropertyList,
  1107. cbPropertyListSize,
  1108. FALSE, // bForceWrite
  1109. NULL
  1110. );
  1111. }
  1112. else {
  1113. ClRtlLogPrint( LOG_CRITICAL,
  1114. "[CS] ClusterSetCommonProperties, Error creating property list. %1!u!\n",
  1115. status);
  1116. LocalFree( pPropertyList );
  1117. break;
  1118. }
  1119. LocalFree( pPropertyList );
  1120. if ( status != ERROR_SUCCESS ) {
  1121. ClRtlLogPrint( LOG_CRITICAL,
  1122. "[CS] ClusterSetCommonProperties, error in setting property table. %1!u!\n",
  1123. status);
  1124. break;
  1125. }
  1126. }
  1127. }
  1128. while ( FALSE ); // do-while: dummy loop to avoid gotos
  1129. if (status == ERROR_SUCCESS) {
  1130. if ( ERROR_SUCCESS == ClRtlFindDwordProperty(
  1131. InBuffer,
  1132. InBufferSize,
  1133. CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  1134. &dwValue) )
  1135. {
  1136. ClRtlLogPrint( LOG_UNUSUAL, "[CS] Arbitration Timeout is changed %1!d! => %2!d!.\n",
  1137. MmQuorumArbitrationTimeout, dwValue);
  1138. MmQuorumArbitrationTimeout = dwValue;
  1139. }
  1140. if ( ERROR_SUCCESS == ClRtlFindDwordProperty(
  1141. InBuffer,
  1142. InBufferSize,
  1143. CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER,
  1144. &dwValue) )
  1145. {
  1146. ClRtlLogPrint( LOG_UNUSUAL, "[CS] Arbitration Equalizer is changed %1!d! => %2!d!.\n",
  1147. MmQuorumArbitrationEqualizer, dwValue);
  1148. MmQuorumArbitrationEqualizer = dwValue;
  1149. }
  1150. if ( ClRtlFindDwordProperty(
  1151. InBuffer,
  1152. InBufferSize,
  1153. CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  1154. &dwValue ) == ERROR_SUCCESS )
  1155. {
  1156. ClRtlLogPrint(LOG_NOISE, "[CS] Cluster common property %1!ws! is changed to %2!u!...\n",
  1157. CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  1158. dwValue);
  1159. }
  1160. }
  1161. //
  1162. // If the 'Security Descriptor' property was found, free the memory allocated,
  1163. // to store the NT4 security descriptor.
  1164. //
  1165. if ( bSDFound != FALSE ) {
  1166. LocalFree( paramBlocks.securityInfo.Security );
  1167. }
  1168. return(status);
  1169. } // CspClusterSetCommonProperties
  1170. DWORD
  1171. CspClusterEnumPrivateProperties(
  1172. IN HDMKEY RegistryKey,
  1173. OUT PVOID OutBuffer,
  1174. IN DWORD OutBufferSize,
  1175. OUT LPDWORD BytesReturned,
  1176. OUT LPDWORD Required
  1177. )
  1178. /*++
  1179. Routine Description:
  1180. Enumerates the private property names for a given cluster.
  1181. Arguments:
  1182. RegistryKey - Registry key for the cluster.
  1183. OutBuffer - Supplies the output buffer.
  1184. OutBufferSize - Supplies the size of the output buffer.
  1185. BytesReturned - The number of bytes returned in OutBuffer.
  1186. Required - The required number of bytes if OutBuffer is too small.
  1187. Return Value:
  1188. ERROR_SUCCESS if successful.
  1189. A Win32 error code on failure.
  1190. --*/
  1191. {
  1192. HDMKEY parametersKey;
  1193. DWORD totalBufferSize = 0;
  1194. DWORD status;
  1195. *BytesReturned = 0;
  1196. *Required = 0;
  1197. //
  1198. // Clear the output buffer
  1199. //
  1200. ZeroMemory( OutBuffer, OutBufferSize );
  1201. //
  1202. // Open the cluster cluster parameters key.
  1203. //
  1204. parametersKey = DmOpenKey( RegistryKey,
  1205. CLUSREG_KEYNAME_PARAMETERS,
  1206. MAXIMUM_ALLOWED );
  1207. if ( parametersKey == NULL ) {
  1208. status = GetLastError();
  1209. if ( status == ERROR_FILE_NOT_FOUND ) {
  1210. status = ERROR_SUCCESS;
  1211. }
  1212. return(status);
  1213. }
  1214. //
  1215. // Enum the private properties for the cluster.
  1216. //
  1217. status = ClRtlEnumPrivateProperties( parametersKey,
  1218. &CspClusterRegApis,
  1219. OutBuffer,
  1220. OutBufferSize,
  1221. BytesReturned,
  1222. Required );
  1223. DmCloseKey( parametersKey );
  1224. return(status);
  1225. } // CspClusterEnumPrivateProperties
  1226. DWORD
  1227. CspClusterGetPrivateProperties(
  1228. IN HDMKEY RegistryKey,
  1229. OUT PVOID OutBuffer,
  1230. IN DWORD OutBufferSize,
  1231. OUT LPDWORD BytesReturned,
  1232. OUT LPDWORD Required
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. Gets the private properties for a given cluster.
  1237. Arguments:
  1238. OutBuffer - Supplies the output buffer.
  1239. OutBufferSize - Supplies the size of the output buffer.
  1240. BytesReturned - The number of bytes returned in OutBuffer.
  1241. Required - The required number of bytes if OutBuffer is too small.
  1242. Return Value:
  1243. ERROR_SUCCESS if successful.
  1244. A Win32 error code on failure.
  1245. --*/
  1246. {
  1247. DWORD status;
  1248. HDMKEY parametersKey;
  1249. DWORD totalBufferSize = 0;
  1250. *BytesReturned = 0;
  1251. *Required = 0;
  1252. //
  1253. // Clear the output buffer
  1254. //
  1255. ZeroMemory( OutBuffer, OutBufferSize );
  1256. //
  1257. // Open the cluster\parameters key.
  1258. //
  1259. parametersKey = DmOpenKey( RegistryKey,
  1260. CLUSREG_KEYNAME_PARAMETERS,
  1261. MAXIMUM_ALLOWED );
  1262. if ( parametersKey == NULL ) {
  1263. status = GetLastError();
  1264. if ( status == ERROR_FILE_NOT_FOUND ) {
  1265. //
  1266. // If we don't have a parameters key, then return an
  1267. // item count of 0 and an endmark.
  1268. //
  1269. totalBufferSize = sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
  1270. if ( OutBufferSize < totalBufferSize ) {
  1271. *Required = totalBufferSize;
  1272. status = ERROR_MORE_DATA;
  1273. } else {
  1274. // This is somewhat redundant since we zero the
  1275. // buffer above, but it's here for clarity.
  1276. CLUSPROP_BUFFER_HELPER buf;
  1277. buf.pb = OutBuffer;
  1278. buf.pList->nPropertyCount = 0;
  1279. buf.pdw++;
  1280. buf.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1281. *BytesReturned = totalBufferSize;
  1282. status = ERROR_SUCCESS;
  1283. }
  1284. }
  1285. return(status);
  1286. }
  1287. //
  1288. // Get private properties for the cluster.
  1289. //
  1290. status = ClRtlGetPrivateProperties( parametersKey,
  1291. &CspClusterRegApis,
  1292. OutBuffer,
  1293. OutBufferSize,
  1294. BytesReturned,
  1295. Required );
  1296. DmCloseKey( parametersKey );
  1297. return(status);
  1298. } // CspClusterGetPrivateProperties
  1299. DWORD
  1300. CspClusterValidatePrivateProperties(
  1301. IN HDMKEY RegistryKey,
  1302. IN PVOID InBuffer,
  1303. IN DWORD InBufferSize
  1304. )
  1305. /*++
  1306. Routine Description:
  1307. Validates the private properties for a given cluster.
  1308. Arguments:
  1309. RegistryKey - Registry key for the cluster.
  1310. InBuffer - Supplies the input buffer.
  1311. InBufferSize - Supplies the size of the input buffer.
  1312. Return Value:
  1313. ERROR_SUCCESS if successful.
  1314. A Win32 error code on failure.
  1315. --*/
  1316. {
  1317. DWORD status;
  1318. //
  1319. // Validate the property list.
  1320. //
  1321. status = ClRtlVerifyPrivatePropertyList( InBuffer,
  1322. InBufferSize );
  1323. return(status);
  1324. } // CspClusterValidatePrivateProperties
  1325. DWORD
  1326. CspClusterSetPrivateProperties(
  1327. IN HDMKEY RegistryKey,
  1328. IN PVOID InBuffer,
  1329. IN DWORD InBufferSize
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. Sets the private properties for a given cluster.
  1334. Arguments:
  1335. RegistryKey - Registry key for the cluster.
  1336. InBuffer - Supplies the input buffer.
  1337. InBufferSize - Supplies the size of the input buffer.
  1338. Return Value:
  1339. ERROR_SUCCESS if successful.
  1340. A Win32 error code on failure.
  1341. --*/
  1342. {
  1343. DWORD status;
  1344. HDMKEY parametersKey;
  1345. DWORD disposition;
  1346. //
  1347. // Validate the property list.
  1348. //
  1349. status = ClRtlVerifyPrivatePropertyList( InBuffer,
  1350. InBufferSize );
  1351. if ( status == ERROR_SUCCESS ) {
  1352. //
  1353. // Open the cluster\parameters key
  1354. //
  1355. parametersKey = DmOpenKey( RegistryKey,
  1356. CLUSREG_KEYNAME_PARAMETERS,
  1357. MAXIMUM_ALLOWED );
  1358. if ( parametersKey == NULL ) {
  1359. status = GetLastError();
  1360. if ( status == ERROR_FILE_NOT_FOUND ) {
  1361. //
  1362. // Try to create the parameters key.
  1363. //
  1364. parametersKey = DmCreateKey( RegistryKey,
  1365. CLUSREG_KEYNAME_PARAMETERS,
  1366. 0,
  1367. KEY_READ | KEY_WRITE,
  1368. NULL,
  1369. &disposition );
  1370. if ( parametersKey == NULL ) {
  1371. status = GetLastError();
  1372. return(status);
  1373. }
  1374. }
  1375. }
  1376. status = ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction
  1377. parametersKey,
  1378. &CspClusterRegApis,
  1379. InBuffer,
  1380. InBufferSize );
  1381. DmCloseKey( parametersKey );
  1382. }
  1383. return(status);
  1384. } // CspClusterSetPrivateProperties
  1385. void
  1386. CsRefreshGlobalsFromRegistry()
  1387. {
  1388. DWORD dwValue;
  1389. DWORD status;
  1390. // Currently the only globals that are read once from the registry are two MM globals.
  1391. if( ERROR_SUCCESS == DmQueryDword(
  1392. DmClusterParametersKey,
  1393. CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  1394. &dwValue, NULL) )
  1395. {
  1396. if ( MmQuorumArbitrationTimeout != dwValue ) {
  1397. MmQuorumArbitrationTimeout = dwValue;
  1398. ClRtlLogPrint(LOG_NOISE,
  1399. "[CS] MmQuorumArbitrationTimeout: %1!d!.\n", dwValue);
  1400. }
  1401. }
  1402. if( ERROR_SUCCESS == DmQueryDword(
  1403. DmClusterParametersKey,
  1404. CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER,
  1405. &dwValue, NULL) )
  1406. {
  1407. if ( MmQuorumArbitrationEqualizer != dwValue ) {
  1408. MmQuorumArbitrationEqualizer = dwValue;
  1409. ClRtlLogPrint(LOG_NOISE,
  1410. "[CS] MmQuorumArbitrationEqualizer: %1!d!.\n", dwValue);
  1411. }
  1412. }
  1413. // No need to check return value or log anything here -- the routine does its own logging,
  1414. // and if we fail to read the cluster SD from the registry, it will be set to NULL and a default
  1415. // SD will be used.
  1416. InitializeClusterSD();
  1417. //
  1418. // Check if resource dll deadlock detection is enabled.
  1419. //
  1420. FmCheckIsDeadlockDetectionEnabled ();
  1421. } // CspRefreshGlobalsFromRegistry