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.

1480 lines
40 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. } CS_CLUSTER_INFO, *PCS_CLUSTER_INFO;
  41. //
  42. // Parameter block used for setting the cluster 'Security Descriptor' property
  43. //
  44. typedef struct {
  45. LPBYTE Security;
  46. DWORD SecurityLength;
  47. } CS_CLUSTER_SECURITY_INFO, *PCS_CLUSTER_SECURITY_INFO;
  48. //
  49. // Parameter block used for setting the cluster 'Security' property
  50. //
  51. typedef struct {
  52. LPBYTE SecurityDescriptor;
  53. DWORD SecurityDescriptorLength;
  54. } CS_CLUSTER_SD_INFO, *PCS_CLUSTER_SD_INFO;
  55. //
  56. // Cluster Common properties.
  57. //
  58. //
  59. // Read-Write Common Properties.
  60. //
  61. RESUTIL_PROPERTY_ITEM
  62. CspClusterCommonProperties[] = {
  63. { CLUSREG_NAME_ADMIN_EXT,
  64. NULL,
  65. CLUSPROP_FORMAT_MULTI_SZ,
  66. 0,
  67. 0,
  68. 0,
  69. 0,
  70. FIELD_OFFSET(CS_CLUSTER_INFO, AdminExtensions)
  71. },
  72. { CLUSREG_NAME_CLUS_DEFAULT_NETWORK_ROLE,
  73. NULL,
  74. CLUSPROP_FORMAT_DWORD,
  75. ClusterNetworkRoleClientAccess,
  76. ClusterNetworkRoleNone,
  77. ClusterNetworkRoleInternalAndClient,
  78. 0,
  79. FIELD_OFFSET(CS_CLUSTER_INFO, DefaultNetworkRole)
  80. },
  81. { CLUSREG_NAME_CLUS_DESC,
  82. NULL,
  83. CLUSPROP_FORMAT_SZ,
  84. 0,
  85. 0,
  86. 0,
  87. 0,
  88. FIELD_OFFSET(CS_CLUSTER_INFO, Description)
  89. },
  90. { CLUSREG_NAME_CLUS_SECURITY,
  91. NULL,
  92. CLUSPROP_FORMAT_BINARY,
  93. 0,
  94. 0,
  95. 0,
  96. 0,
  97. FIELD_OFFSET(CS_CLUSTER_INFO, Security)
  98. },
  99. { CLUSREG_NAME_CLUS_SD,
  100. NULL,
  101. CLUSPROP_FORMAT_BINARY,
  102. 0,
  103. 0,
  104. 0,
  105. 0,
  106. FIELD_OFFSET(CS_CLUSTER_INFO, SecurityDescriptor)
  107. },
  108. { CLUSREG_KEYNAME_GROUPS L"\\" CLUSREG_NAME_ADMIN_EXT,
  109. NULL,
  110. CLUSPROP_FORMAT_MULTI_SZ,
  111. 0,
  112. 0,
  113. 0,
  114. 0,
  115. FIELD_OFFSET(CS_CLUSTER_INFO, GroupsAdminExtensions)
  116. },
  117. { CLUSREG_KEYNAME_NETWORKS L"\\" CLUSREG_NAME_ADMIN_EXT,
  118. NULL,
  119. CLUSPROP_FORMAT_MULTI_SZ,
  120. 0,
  121. 0,
  122. 0,
  123. 0,
  124. FIELD_OFFSET(CS_CLUSTER_INFO, NetworksAdminExtensions)
  125. },
  126. { CLUSREG_KEYNAME_NETINTERFACES L"\\" CLUSREG_NAME_ADMIN_EXT,
  127. NULL,
  128. CLUSPROP_FORMAT_MULTI_SZ,
  129. 0,
  130. 0,
  131. 0,
  132. 0,
  133. FIELD_OFFSET(CS_CLUSTER_INFO, NetworkInterfacesAdminExtensions)
  134. },
  135. { CLUSREG_KEYNAME_NODES L"\\" CLUSREG_NAME_ADMIN_EXT,
  136. NULL,
  137. CLUSPROP_FORMAT_MULTI_SZ,
  138. 0,
  139. 0,
  140. 0,
  141. 0,
  142. FIELD_OFFSET(CS_CLUSTER_INFO, NodesAdminExtensions)
  143. },
  144. { CLUSREG_KEYNAME_RESOURCES L"\\" CLUSREG_NAME_ADMIN_EXT,
  145. NULL,
  146. CLUSPROP_FORMAT_MULTI_SZ,
  147. 0,
  148. 0,
  149. 0,
  150. 0,
  151. FIELD_OFFSET(CS_CLUSTER_INFO, ResourcesAdminExtensions)
  152. },
  153. { CLUSREG_KEYNAME_RESOURCE_TYPES L"\\" CLUSREG_NAME_ADMIN_EXT,
  154. NULL,
  155. CLUSPROP_FORMAT_MULTI_SZ,
  156. 0,
  157. 0,
  158. 0,
  159. 0,
  160. FIELD_OFFSET(CS_CLUSTER_INFO, ResourceTypesAdminExtensions)
  161. },
  162. { CLUSREG_NAME_CLUS_EVTLOG_PROPAGATION,
  163. NULL,
  164. CLUSPROP_FORMAT_DWORD,
  165. 1, // default value //
  166. 0, // min value //
  167. 1, // max value //
  168. 0,
  169. FIELD_OFFSET(CS_CLUSTER_INFO, EnableEventLogReplication)
  170. },
  171. { CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  172. NULL,
  173. CLUSPROP_FORMAT_DWORD,
  174. 60, // default value //
  175. 1, // min value //
  176. 60 * 60, // max value // One hour for arbitration. Should be enough
  177. 0,
  178. FIELD_OFFSET(CS_CLUSTER_INFO, QuorumArbitrationTimeout)
  179. },
  180. { CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER,
  181. NULL,
  182. CLUSPROP_FORMAT_DWORD,
  183. 7, // default value //
  184. 0, // min value //
  185. 60 * 60, // max value // One hour for arbitration. Should be enough
  186. 0,
  187. FIELD_OFFSET(CS_CLUSTER_INFO, QuorumArbitrationEqualizer)
  188. },
  189. { CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  190. NULL,
  191. CLUSPROP_FORMAT_DWORD,
  192. 0, // default value // don't disable randomization
  193. 0, // min value //
  194. 1, // max value //
  195. 0,
  196. FIELD_OFFSET(CS_CLUSTER_INFO, DisableGroupPreferredOwnerRandomization)
  197. },
  198. { NULL, NULL, 0, 0, 0, 0, 0 } };
  199. //
  200. // Property table used for setting the cluster 'Security Descriptor' property
  201. //
  202. RESUTIL_PROPERTY_ITEM
  203. CspClusterSDProperty[] = {
  204. { CLUSREG_NAME_CLUS_SD,
  205. NULL,
  206. CLUSPROP_FORMAT_BINARY,
  207. 0,
  208. 0,
  209. 0,
  210. 0,
  211. FIELD_OFFSET(CS_CLUSTER_SD_INFO, SecurityDescriptor)
  212. },
  213. { NULL, NULL, 0, 0, 0, 0, 0 } };
  214. //
  215. // Property table used for setting the cluster 'Security' property
  216. //
  217. RESUTIL_PROPERTY_ITEM
  218. CspClusterSecurityProperty[] = {
  219. { CLUSREG_NAME_CLUS_SECURITY,
  220. NULL,
  221. CLUSPROP_FORMAT_BINARY,
  222. 0,
  223. 0,
  224. 0,
  225. 0,
  226. FIELD_OFFSET(CS_CLUSTER_SECURITY_INFO, Security)
  227. },
  228. { NULL, NULL, 0, 0, 0, 0, 0 } };
  229. //
  230. // Read-Only Common Properties.
  231. //
  232. RESUTIL_PROPERTY_ITEM
  233. CspClusterROCommonProperties[] = {
  234. { NULL, NULL, 0, 0, 0, 0, 0 } };
  235. //
  236. // Cluster registry API function pointers.
  237. //
  238. CLUSTER_REG_APIS
  239. CspClusterRegApis = {
  240. (PFNCLRTLCREATEKEY) DmRtlCreateKey,
  241. (PFNCLRTLOPENKEY) DmRtlOpenKey,
  242. (PFNCLRTLCLOSEKEY) DmCloseKey,
  243. (PFNCLRTLSETVALUE) DmSetValue,
  244. (PFNCLRTLQUERYVALUE) DmQueryValue,
  245. (PFNCLRTLENUMVALUE) DmEnumValue,
  246. (PFNCLRTLDELETEVALUE) DmDeleteValue,
  247. NULL,
  248. NULL,
  249. NULL
  250. };
  251. //
  252. // Local Functions
  253. //
  254. DWORD
  255. CspClusterControl(
  256. IN DWORD ControlCode,
  257. IN PUCHAR InBuffer,
  258. IN DWORD InBufferSize,
  259. OUT PUCHAR OutBuffer,
  260. IN DWORD OutBufferSize,
  261. OUT LPDWORD BytesReturned,
  262. OUT LPDWORD Required
  263. );
  264. DWORD
  265. CspClusterEnumCommonProperties(
  266. OUT PVOID OutBuffer,
  267. IN DWORD OutBufferSize,
  268. OUT LPDWORD BytesReturned,
  269. OUT LPDWORD Required
  270. );
  271. DWORD
  272. CspClusterGetCommonProperties(
  273. IN BOOL ReadOnly,
  274. IN HDMKEY RegistryKey,
  275. OUT PVOID OutBuffer,
  276. IN DWORD OutBufferSize,
  277. OUT LPDWORD BytesReturned,
  278. OUT LPDWORD Required
  279. );
  280. DWORD
  281. CspClusterValidateCommonProperties(
  282. IN HDMKEY RegistryKey,
  283. IN PVOID InBuffer,
  284. IN DWORD InBufferSize
  285. );
  286. DWORD
  287. CspClusterSetCommonProperties(
  288. IN HDMKEY RegistryKey,
  289. IN PVOID InBuffer,
  290. IN DWORD InBufferSize
  291. );
  292. DWORD
  293. CspClusterEnumPrivateProperties(
  294. IN HDMKEY RegistryKey,
  295. OUT PVOID OutBuffer,
  296. IN DWORD OutBufferSize,
  297. OUT LPDWORD BytesReturned,
  298. OUT LPDWORD Required
  299. );
  300. DWORD
  301. CspClusterGetPrivateProperties(
  302. IN HDMKEY RegistryKey,
  303. OUT PVOID OutBuffer,
  304. IN DWORD OutBufferSize,
  305. OUT LPDWORD BytesReturned,
  306. OUT LPDWORD Required
  307. );
  308. DWORD
  309. CspClusterValidatePrivateProperties(
  310. IN HDMKEY RegistryKey,
  311. IN PVOID InBuffer,
  312. IN DWORD InBufferSize
  313. );
  314. DWORD
  315. CspClusterSetPrivateProperties(
  316. IN HDMKEY RegistryKey,
  317. IN PVOID InBuffer,
  318. IN DWORD InBufferSize
  319. );
  320. DWORD
  321. WINAPI
  322. CsClusterControl(
  323. IN PNM_NODE HostNode OPTIONAL,
  324. IN DWORD ControlCode,
  325. IN PUCHAR InBuffer,
  326. IN DWORD InBufferSize,
  327. OUT PUCHAR OutBuffer,
  328. IN DWORD OutBufferSize,
  329. OUT LPDWORD BytesReturned,
  330. OUT LPDWORD Required
  331. )
  332. /*++
  333. Routine Description:
  334. Provides for arbitrary communication and control between an application
  335. and a cluster.
  336. Arguments:
  337. HostNode - Supplies the host node on which the cluster control should
  338. be delivered. If this is NULL, the local node is used. Not honored!
  339. ControlCode- Supplies the control code that defines the
  340. structure and action of the cluster control.
  341. Values of ControlCode between 0 and 0x10000000 are reserved
  342. for future definition and use by Microsoft. All other values
  343. are available for use by ISVs
  344. InBuffer- Supplies a pointer to the input buffer to be passed
  345. to the cluster.
  346. InBufferSize- Supplies the size, in bytes, of the data pointed
  347. to by lpInBuffer..
  348. OutBuffer- Supplies a pointer to the output buffer to be
  349. filled in by the cluster..
  350. OutBufferSize- Supplies the size, in bytes, of the available
  351. space pointed to by lpOutBuffer.
  352. BytesReturned - Returns the number of bytes of lpOutBuffer
  353. actually filled in by the cluster.
  354. Required - Returns the number of bytes if the OutBuffer is not big
  355. enough.
  356. Return Value:
  357. ERROR_SUCCESS if successful
  358. Win32 error code otherwise
  359. --*/
  360. {
  361. DWORD status;
  362. //
  363. // In the future - we should verify the access mode!
  364. //
  365. if ( CLUSCTL_GET_CONTROL_OBJECT( ControlCode ) != CLUS_OBJECT_CLUSTER ) {
  366. return(ERROR_INVALID_FUNCTION);
  367. }
  368. status = CspClusterControl(
  369. ControlCode,
  370. InBuffer,
  371. InBufferSize,
  372. OutBuffer,
  373. OutBufferSize,
  374. BytesReturned,
  375. Required
  376. );
  377. return(status);
  378. } // CsClusterControl
  379. DWORD
  380. CspClusterControl(
  381. IN DWORD ControlCode,
  382. IN PUCHAR InBuffer,
  383. IN DWORD InBufferSize,
  384. OUT PUCHAR OutBuffer,
  385. IN DWORD OutBufferSize,
  386. OUT LPDWORD BytesReturned,
  387. OUT LPDWORD Required
  388. )
  389. /*++
  390. Routine Description:
  391. Provides for arbitrary communication and control between an application
  392. and a specific instance of a node.
  393. Arguments:
  394. ControlCode- Supplies the control code that defines the
  395. structure and action of the cluster control.
  396. Values of ControlCode between 0 and 0x10000000 are reserved
  397. for future definition and use by Microsoft. All other values
  398. are available for use by ISVs
  399. InBuffer- Supplies a pointer to the input buffer to be passed
  400. to the cluster.
  401. InBufferSize- Supplies the size, in bytes, of the data pointed
  402. to by lpInBuffer.
  403. OutBuffer- Supplies a pointer to the output buffer to be
  404. filled in by the cluster.
  405. OutBufferSize- Supplies the size, in bytes, of the available
  406. space pointed to by lpOutBuffer.
  407. BytesReturned - Returns the number of bytes of lpOutBuffer
  408. actually filled in by the cluster.
  409. Required - Returns the number of bytes if the OutBuffer is not big
  410. enough.
  411. Return Value:
  412. ERROR_SUCCESS if successful
  413. Win32 error code otherwise
  414. --*/
  415. {
  416. DWORD status;
  417. CLUSPROP_BUFFER_HELPER props;
  418. DWORD bufSize;
  419. BOOL success;
  420. DWORD nameLen;
  421. if (DmClusterParametersKey == NULL) {
  422. return(ERROR_SHARING_PAUSED);
  423. }
  424. switch ( ControlCode ) {
  425. case CLUSCTL_CLUSTER_UNKNOWN:
  426. *BytesReturned = 0;
  427. status = ERROR_SUCCESS;
  428. break;
  429. case CLUSCTL_RESOURCE_GET_COMMON_PROPERTY_FMTS:
  430. status = ClRtlGetPropertyFormats( CspClusterCommonProperties,
  431. OutBuffer,
  432. OutBufferSize,
  433. BytesReturned,
  434. Required );
  435. break;
  436. case CLUSCTL_CLUSTER_GET_FQDN:
  437. // Return the fully qualified cluster name
  438. *BytesReturned = OutBufferSize;
  439. nameLen = lstrlenW( CsClusterName ) * sizeof(UNICODE_NULL);
  440. success = GetComputerNameEx( ComputerNameDnsDomain,
  441. (LPWSTR)OutBuffer,
  442. BytesReturned );
  443. *BytesReturned = *BytesReturned * sizeof(UNICODE_NULL);
  444. if ( success ) {
  445. status = STATUS_SUCCESS;
  446. //
  447. // Okay - append Cluster Name now. With a dot.
  448. //
  449. if ( (*BytesReturned + nameLen + 2*sizeof(UNICODE_NULL)) <= OutBufferSize ) {
  450. lstrcatW( (LPWSTR)OutBuffer, L"." );
  451. lstrcatW( (LPWSTR)OutBuffer, CsClusterName );
  452. *BytesReturned = *BytesReturned + nameLen + 2*sizeof(UNICODE_NULL);
  453. } else {
  454. *Required = *BytesReturned + nameLen + 2*sizeof(UNICODE_NULL);
  455. *BytesReturned = 0;
  456. status = ERROR_MORE_DATA;
  457. }
  458. } else {
  459. *Required = *BytesReturned + nameLen + sizeof(UNICODE_NULL);
  460. *BytesReturned = 0;
  461. status = GetLastError();
  462. }
  463. break;
  464. case CLUSCTL_CLUSTER_ENUM_COMMON_PROPERTIES:
  465. status = CspClusterEnumCommonProperties(
  466. OutBuffer,
  467. OutBufferSize,
  468. BytesReturned,
  469. Required
  470. );
  471. break;
  472. case CLUSCTL_CLUSTER_GET_RO_COMMON_PROPERTIES:
  473. status = CspClusterGetCommonProperties(
  474. TRUE, // ReadOnly
  475. DmClusterParametersKey,
  476. OutBuffer,
  477. OutBufferSize,
  478. BytesReturned,
  479. Required
  480. );
  481. break;
  482. case CLUSCTL_CLUSTER_GET_COMMON_PROPERTIES:
  483. status = CspClusterGetCommonProperties(
  484. FALSE, // ReadOnly
  485. DmClusterParametersKey,
  486. OutBuffer,
  487. OutBufferSize,
  488. BytesReturned,
  489. Required
  490. );
  491. break;
  492. case CLUSCTL_CLUSTER_VALIDATE_COMMON_PROPERTIES:
  493. status = CspClusterValidateCommonProperties(
  494. DmClusterParametersKey,
  495. InBuffer,
  496. InBufferSize
  497. );
  498. break;
  499. case CLUSCTL_CLUSTER_SET_COMMON_PROPERTIES:
  500. status = CspClusterSetCommonProperties(
  501. DmClusterParametersKey,
  502. InBuffer,
  503. InBufferSize
  504. );
  505. break;
  506. case CLUSCTL_CLUSTER_ENUM_PRIVATE_PROPERTIES:
  507. status = CspClusterEnumPrivateProperties(
  508. DmClusterParametersKey,
  509. OutBuffer,
  510. OutBufferSize,
  511. BytesReturned,
  512. Required
  513. );
  514. break;
  515. case CLUSCTL_CLUSTER_GET_RO_PRIVATE_PROPERTIES:
  516. if ( OutBufferSize < sizeof(DWORD) ) {
  517. *BytesReturned = 0;
  518. *Required = sizeof(DWORD);
  519. if ( OutBuffer == NULL ) {
  520. status = ERROR_SUCCESS;
  521. } else {
  522. status = ERROR_MORE_DATA;
  523. }
  524. } else {
  525. LPDWORD ptrDword = (LPDWORD) OutBuffer;
  526. *ptrDword = 0;
  527. *BytesReturned = sizeof(DWORD);
  528. status = ERROR_SUCCESS;
  529. }
  530. break;
  531. case CLUSCTL_CLUSTER_GET_PRIVATE_PROPERTIES:
  532. status = CspClusterGetPrivateProperties(
  533. DmClusterParametersKey,
  534. OutBuffer,
  535. OutBufferSize,
  536. BytesReturned,
  537. Required
  538. );
  539. break;
  540. case CLUSCTL_CLUSTER_VALIDATE_PRIVATE_PROPERTIES:
  541. status = CspClusterValidatePrivateProperties(
  542. DmClusterParametersKey,
  543. InBuffer,
  544. InBufferSize
  545. );
  546. break;
  547. case CLUSCTL_CLUSTER_SET_PRIVATE_PROPERTIES:
  548. status = CspClusterSetPrivateProperties(
  549. DmClusterParametersKey,
  550. InBuffer,
  551. InBufferSize
  552. );
  553. break;
  554. default:
  555. status = ERROR_INVALID_FUNCTION;
  556. break;
  557. }
  558. return(status);
  559. } // CspClusterControl
  560. DWORD
  561. CspClusterEnumCommonProperties(
  562. OUT PVOID OutBuffer,
  563. IN DWORD OutBufferSize,
  564. OUT LPDWORD BytesReturned,
  565. OUT LPDWORD Required
  566. )
  567. /*++
  568. Routine Description:
  569. Enumerates the common property names for a given node.
  570. Arguments:
  571. OutBuffer - Supplies the output buffer.
  572. OutBufferSize - Supplies the size of the output buffer.
  573. BytesReturned - The number of bytes returned in OutBuffer.
  574. Required - The required number of bytes if OutBuffer is too small.
  575. Return Value:
  576. ERROR_SUCCESS if successful.
  577. A Win32 error code on failure.
  578. --*/
  579. {
  580. DWORD status;
  581. //
  582. // Get the common properties.
  583. //
  584. status = ClRtlEnumProperties(
  585. CspClusterCommonProperties,
  586. OutBuffer,
  587. OutBufferSize,
  588. BytesReturned,
  589. Required
  590. );
  591. return(status);
  592. } // CspClusterEnumCommonProperties
  593. DWORD
  594. CspClusterGetCommonProperties(
  595. IN BOOL ReadOnly,
  596. IN HDMKEY RegistryKey,
  597. OUT PVOID OutBuffer,
  598. IN DWORD OutBufferSize,
  599. OUT LPDWORD BytesReturned,
  600. OUT LPDWORD Required
  601. )
  602. /*++
  603. Routine Description:
  604. Gets the common properties for a given cluster.
  605. Arguments:
  606. ReadOnly - TRUE if the read-only properties should be read.
  607. FALSE otherwise.
  608. RegistryKey - Supplies the registry key for this cluster.
  609. OutBuffer - Supplies the output buffer.
  610. OutBufferSize - Supplies the size of the output buffer.
  611. BytesReturned - The number of bytes returned in OutBuffer.
  612. Required - The required number of bytes if OutBuffer is too small.
  613. Return Value:
  614. ERROR_SUCCESS if successful.
  615. A Win32 error code on failure.
  616. --*/
  617. {
  618. DWORD status;
  619. PRESUTIL_PROPERTY_ITEM propertyTable;
  620. if ( ReadOnly ) {
  621. propertyTable = CspClusterROCommonProperties;
  622. } else {
  623. propertyTable = CspClusterCommonProperties;
  624. }
  625. //
  626. // Get the common properties.
  627. //
  628. status = ClRtlGetProperties( RegistryKey,
  629. &CspClusterRegApis,
  630. propertyTable,
  631. OutBuffer,
  632. OutBufferSize,
  633. BytesReturned,
  634. Required );
  635. return(status);
  636. } // CspClusterGetCommonProperties
  637. DWORD
  638. CspClusterValidateCommonProperties(
  639. IN HDMKEY RegistryKey,
  640. IN PVOID InBuffer,
  641. IN DWORD InBufferSize
  642. )
  643. /*++
  644. Routine Description:
  645. Validates the common properties for a given cluster.
  646. Arguments:
  647. Node - Supplies the cluster object.
  648. InBuffer - Supplies the input buffer.
  649. InBufferSize - Supplies the size of the input buffer.
  650. Return Value:
  651. ERROR_SUCCESS if successful.
  652. A Win32 error code on failure.
  653. --*/
  654. {
  655. DWORD status;
  656. //
  657. // Validate the property list.
  658. //
  659. status = ClRtlVerifyPropertyTable( CspClusterCommonProperties,
  660. NULL, // Reserved
  661. FALSE, // Don't allow unknowns
  662. InBuffer,
  663. InBufferSize,
  664. NULL );
  665. if ( status != ERROR_SUCCESS ) {
  666. ClRtlLogPrint( LOG_CRITICAL,
  667. "[CS] ValidateCommonProperties, error in verify routine.\n");
  668. }
  669. return(status);
  670. } // CspClusterValidateCommonProperties
  671. DWORD
  672. CspClusterSetCommonProperties(
  673. IN HDMKEY RegistryKey,
  674. IN PVOID InBuffer,
  675. IN DWORD InBufferSize
  676. )
  677. /*++
  678. Routine Description:
  679. Sets the common properties for a given cluster.
  680. Arguments:
  681. Node - Supplies the cluster object.
  682. InBuffer - Supplies the input buffer.
  683. InBufferSize - Supplies the size of the input buffer.
  684. Return Value:
  685. ERROR_SUCCESS if successful.
  686. A Win32 error code on failure.
  687. --*/
  688. {
  689. DWORD status;
  690. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  691. DWORD cbSecurityDescriptorSize = 0;
  692. PRESUTIL_PROPERTY_ITEM pOtherPropertyTable = NULL;
  693. LPBYTE pOtherParameterBlock = NULL;
  694. BOOL bSDFound = FALSE;
  695. BOOL bSecurityFound = FALSE;
  696. DWORD dwValue;
  697. //
  698. // Only one of securityInfo or sdInfo is going to be used at at time.
  699. // So use a union.
  700. //
  701. union
  702. {
  703. CS_CLUSTER_SECURITY_INFO securityInfo;
  704. CS_CLUSTER_SD_INFO sdInfo;
  705. } paramBlocks;
  706. //
  707. // Dummy do-while loop to avoid gotos
  708. //
  709. do
  710. {
  711. //
  712. // Validate the property list.
  713. //
  714. status = ClRtlVerifyPropertyTable(
  715. CspClusterCommonProperties,
  716. NULL, // Reserved
  717. FALSE, // Don't allow unknowns
  718. InBuffer,
  719. InBufferSize,
  720. NULL );
  721. if ( status != ERROR_SUCCESS ) {
  722. ClRtlLogPrint( LOG_CRITICAL,
  723. "[CS] ClusterSetCommonProperties, error trying to verify property table. %1!u!\n",
  724. status);
  725. break;
  726. }
  727. //
  728. // Set all the properties that were passed in.
  729. //
  730. status = ClRtlSetPropertyTable(
  731. NULL,
  732. RegistryKey,
  733. &CspClusterRegApis,
  734. CspClusterCommonProperties,
  735. NULL, // Reserved
  736. FALSE, // Don't allow unknowns
  737. InBuffer,
  738. InBufferSize,
  739. FALSE, // bForceWrite
  740. NULL
  741. );
  742. if ( status != ERROR_SUCCESS ) {
  743. ClRtlLogPrint( LOG_CRITICAL,
  744. "[CS] ClusterSetCommonProperties, error trying to set properties in table. %1!u!\n",
  745. status);
  746. break;
  747. }
  748. //
  749. // Clear the parameter blocks.
  750. //
  751. ZeroMemory( &paramBlocks, sizeof( paramBlocks ) );
  752. //
  753. // See if the "Security Descriptor" property exists in the input
  754. // property list. If so, set the 'Security' property also.
  755. status = ClRtlFindBinaryProperty(
  756. InBuffer,
  757. InBufferSize,
  758. CLUSREG_NAME_CLUS_SD,
  759. (LPBYTE *) &pSecurityDescriptor,
  760. &cbSecurityDescriptorSize
  761. );
  762. if ( status == ERROR_SUCCESS ) {
  763. //
  764. // The 'Security Descriptor' property is present.
  765. // Choose this over the 'Security' property.
  766. //
  767. if ( cbSecurityDescriptorSize > 0 ) {
  768. //
  769. // A security descriptor of nonzero size has been found.
  770. // Check if this is a valid security descriptor.
  771. //
  772. if ( IsValidSecurityDescriptor( pSecurityDescriptor ) == FALSE ) {
  773. //
  774. // Return the most appropriate error code, since IsValidSecurityDescriptor
  775. // does not provide extended error information.
  776. //
  777. ClRtlLogPrint( LOG_CRITICAL,
  778. "[CS] ClusterSetCommonProperties, Invalid security descriptor.\n");
  779. status = ERROR_INVALID_DATA;
  780. break;
  781. }
  782. paramBlocks.securityInfo.Security = ClRtlConvertClusterSDToNT4Format( pSecurityDescriptor );
  783. paramBlocks.securityInfo.SecurityLength = GetSecurityDescriptorLength(
  784. paramBlocks.securityInfo.Security );
  785. }
  786. else {
  787. //
  788. // The security string could have been passed in, but it may be
  789. // a zero length buffer. In this case, we will delete the
  790. // Security property too.
  791. //
  792. paramBlocks.securityInfo.Security = NULL;
  793. paramBlocks.securityInfo.SecurityLength = 0;
  794. }
  795. bSDFound = TRUE;
  796. pOtherPropertyTable = CspClusterSecurityProperty;
  797. pOtherParameterBlock = (LPBYTE) &paramBlocks.securityInfo;
  798. }
  799. else {
  800. //
  801. // We haven't found a valid security descriptor so far.
  802. //
  803. PSECURITY_DESCRIPTOR pSecurity = NULL;
  804. DWORD cbSecuritySize = 0;
  805. status = ClRtlFindBinaryProperty(
  806. InBuffer,
  807. InBufferSize,
  808. CLUSREG_NAME_CLUS_SECURITY,
  809. (LPBYTE *) &pSecurity,
  810. &cbSecuritySize
  811. );
  812. if ( status == ERROR_SUCCESS ) {
  813. if ( cbSecuritySize > 0 ) {
  814. //
  815. // A security descriptor of nonzero size has been found.
  816. // Check if this is a valid security descriptor.
  817. //
  818. if ( IsValidSecurityDescriptor( pSecurity ) == FALSE ) {
  819. //
  820. // Return the most appropriate error code, since IsValidSecurityDescriptor
  821. // does not provide extended error information.
  822. //
  823. ClRtlLogPrint( LOG_CRITICAL,
  824. "[CS] ClusterSetCommonProperties, Invalid security descriptor.\n");
  825. status = ERROR_INVALID_DATA;
  826. break;
  827. }
  828. //
  829. // Since we will not be modifying the info pointed to by the parameter block,
  830. // just point it to the right place in the input buffer itself.
  831. // A valid NT4 security descriptor is valid for NT5 too.
  832. //
  833. paramBlocks.sdInfo.SecurityDescriptor = pSecurity;
  834. paramBlocks.sdInfo.SecurityDescriptorLength = cbSecuritySize;
  835. }
  836. else {
  837. //
  838. // The security string could have been passed in, but it may be
  839. // a zero length buffer. In this case, we will delete the
  840. // Security Descriptor property too.
  841. //
  842. paramBlocks.sdInfo.SecurityDescriptor = NULL;
  843. paramBlocks.sdInfo.SecurityDescriptorLength = 0;
  844. }
  845. bSecurityFound = TRUE;
  846. pOtherPropertyTable = CspClusterSDProperty;
  847. pOtherParameterBlock = (LPBYTE) &paramBlocks.sdInfo;
  848. }
  849. else {
  850. //
  851. // We didn't find any security information.
  852. // Nevertheless, we were successful in setting the properties.
  853. //
  854. status = ERROR_SUCCESS;
  855. }
  856. }
  857. if ( ( bSDFound != FALSE ) || ( bSecurityFound != FALSE ) ) {
  858. PVOID pPropertyList = NULL;
  859. DWORD cbPropertyListSize = 0;
  860. DWORD cbBytesReturned = 0;
  861. DWORD cbBytesRequired = 0;
  862. //
  863. // Create a new property list to incorporate the changed security information.
  864. //
  865. status = ClRtlPropertyListFromParameterBlock(
  866. pOtherPropertyTable,
  867. NULL, // OUT PVOID pOutPropertyList
  868. &cbPropertyListSize, // IN OUT LPDWORD pcbOutPropertyListSize
  869. pOtherParameterBlock,
  870. &cbBytesReturned,
  871. &cbBytesRequired
  872. );
  873. if ( status != ERROR_MORE_DATA ) {
  874. //
  875. // We have passed in a NULL buffer, so the return code has to
  876. // be ERROR_MORE_DATA. Otherwise something else has gone wrong,
  877. // so abort.
  878. //
  879. ClRtlLogPrint( LOG_CRITICAL,
  880. "[CS] ClusterSetCommonProperties, Error getting temporary "
  881. "property list size. %1!u!\n",
  882. status);
  883. break;
  884. }
  885. pPropertyList = LocalAlloc( LMEM_FIXED, cbBytesRequired );
  886. if ( pPropertyList == NULL ) {
  887. status = GetLastError();
  888. ClRtlLogPrint( LOG_CRITICAL,
  889. "[CS] ClusterSetCommonProperties, Error allocating memory "
  890. "for property list. %1!u!\n",
  891. status);
  892. break;
  893. }
  894. cbPropertyListSize = cbBytesRequired;
  895. status = ClRtlPropertyListFromParameterBlock(
  896. pOtherPropertyTable,
  897. pPropertyList,
  898. &cbPropertyListSize,
  899. pOtherParameterBlock,
  900. &cbBytesReturned,
  901. &cbBytesRequired
  902. );
  903. if ( status == ERROR_SUCCESS ) {
  904. status = ClRtlSetPropertyTable(
  905. NULL,
  906. RegistryKey,
  907. &CspClusterRegApis,
  908. pOtherPropertyTable,
  909. NULL, // Reserved
  910. FALSE, // Don't allow unknowns
  911. pPropertyList,
  912. cbPropertyListSize,
  913. FALSE, // bForceWrite
  914. NULL
  915. );
  916. }
  917. else {
  918. ClRtlLogPrint( LOG_CRITICAL,
  919. "[CS] ClusterSetCommonProperties, Error creating property list. %1!u!\n",
  920. status);
  921. LocalFree( pPropertyList );
  922. break;
  923. }
  924. LocalFree( pPropertyList );
  925. if ( status != ERROR_SUCCESS ) {
  926. ClRtlLogPrint( LOG_CRITICAL,
  927. "[CS] ClusterSetCommonProperties, error in setting property table. %1!u!\n",
  928. status);
  929. break;
  930. }
  931. }
  932. }
  933. while ( FALSE ); // do-while: dummy loop to avoid gotos
  934. if (status == ERROR_SUCCESS) {
  935. if ( ERROR_SUCCESS == ClRtlFindDwordProperty(
  936. InBuffer,
  937. InBufferSize,
  938. CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  939. &dwValue) )
  940. {
  941. ClRtlLogPrint( LOG_UNUSUAL, "[CS] Arbitration Timeout is changed %1!d! => %2!d!.\n",
  942. MmQuorumArbitrationTimeout, dwValue);
  943. MmQuorumArbitrationTimeout = dwValue;
  944. }
  945. if ( ERROR_SUCCESS == ClRtlFindDwordProperty(
  946. InBuffer,
  947. InBufferSize,
  948. CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER,
  949. &dwValue) )
  950. {
  951. ClRtlLogPrint( LOG_UNUSUAL, "[CS] Arbitration Equalizer is changed %1!d! => %2!d!.\n",
  952. MmQuorumArbitrationEqualizer, dwValue);
  953. MmQuorumArbitrationEqualizer = dwValue;
  954. }
  955. if ( ClRtlFindDwordProperty(
  956. InBuffer,
  957. InBufferSize,
  958. CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  959. &dwValue ) == ERROR_SUCCESS )
  960. {
  961. ClRtlLogPrint(LOG_NOISE, "[CS] Cluster common property %1!ws! is changed to %2!u!...\n",
  962. CLUSREG_NAME_DISABLE_GROUP_PREFERRED_OWNER_RANDOMIZATION,
  963. dwValue);
  964. }
  965. }
  966. //
  967. // If the 'Security Descriptor' property was found, free the memory allocated,
  968. // to store the NT4 security descriptor.
  969. //
  970. if ( bSDFound != FALSE ) {
  971. LocalFree( paramBlocks.securityInfo.Security );
  972. }
  973. return(status);
  974. } // CspClusterSetCommonProperties
  975. DWORD
  976. CspClusterEnumPrivateProperties(
  977. IN HDMKEY RegistryKey,
  978. OUT PVOID OutBuffer,
  979. IN DWORD OutBufferSize,
  980. OUT LPDWORD BytesReturned,
  981. OUT LPDWORD Required
  982. )
  983. /*++
  984. Routine Description:
  985. Enumerates the private property names for a given cluster.
  986. Arguments:
  987. RegistryKey - Registry key for the cluster.
  988. OutBuffer - Supplies the output buffer.
  989. OutBufferSize - Supplies the size of the output buffer.
  990. BytesReturned - The number of bytes returned in OutBuffer.
  991. Required - The required number of bytes if OutBuffer is too small.
  992. Return Value:
  993. ERROR_SUCCESS if successful.
  994. A Win32 error code on failure.
  995. --*/
  996. {
  997. HDMKEY parametersKey;
  998. DWORD totalBufferSize = 0;
  999. DWORD status;
  1000. *BytesReturned = 0;
  1001. *Required = 0;
  1002. //
  1003. // Clear the output buffer
  1004. //
  1005. ZeroMemory( OutBuffer, OutBufferSize );
  1006. //
  1007. // Open the cluster cluster parameters key.
  1008. //
  1009. parametersKey = DmOpenKey( RegistryKey,
  1010. CLUSREG_KEYNAME_PARAMETERS,
  1011. MAXIMUM_ALLOWED );
  1012. if ( parametersKey == NULL ) {
  1013. status = GetLastError();
  1014. if ( status == ERROR_FILE_NOT_FOUND ) {
  1015. status = ERROR_SUCCESS;
  1016. }
  1017. return(status);
  1018. }
  1019. //
  1020. // Enum the private properties for the cluster.
  1021. //
  1022. status = ClRtlEnumPrivateProperties( parametersKey,
  1023. &CspClusterRegApis,
  1024. OutBuffer,
  1025. OutBufferSize,
  1026. BytesReturned,
  1027. Required );
  1028. DmCloseKey( parametersKey );
  1029. return(status);
  1030. } // CspClusterEnumPrivateProperties
  1031. DWORD
  1032. CspClusterGetPrivateProperties(
  1033. IN HDMKEY RegistryKey,
  1034. OUT PVOID OutBuffer,
  1035. IN DWORD OutBufferSize,
  1036. OUT LPDWORD BytesReturned,
  1037. OUT LPDWORD Required
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. Gets the private properties for a given cluster.
  1042. Arguments:
  1043. OutBuffer - Supplies the output buffer.
  1044. OutBufferSize - Supplies the size of the output buffer.
  1045. BytesReturned - The number of bytes returned in OutBuffer.
  1046. Required - The required number of bytes if OutBuffer is too small.
  1047. Return Value:
  1048. ERROR_SUCCESS if successful.
  1049. A Win32 error code on failure.
  1050. --*/
  1051. {
  1052. DWORD status;
  1053. HDMKEY parametersKey;
  1054. DWORD totalBufferSize = 0;
  1055. *BytesReturned = 0;
  1056. *Required = 0;
  1057. //
  1058. // Clear the output buffer
  1059. //
  1060. ZeroMemory( OutBuffer, OutBufferSize );
  1061. //
  1062. // Open the cluster\parameters key.
  1063. //
  1064. parametersKey = DmOpenKey( RegistryKey,
  1065. CLUSREG_KEYNAME_PARAMETERS,
  1066. MAXIMUM_ALLOWED );
  1067. if ( parametersKey == NULL ) {
  1068. status = GetLastError();
  1069. if ( status == ERROR_FILE_NOT_FOUND ) {
  1070. //
  1071. // If we don't have a parameters key, then return an
  1072. // item count of 0 and an endmark.
  1073. //
  1074. totalBufferSize = sizeof(DWORD) + sizeof(CLUSPROP_SYNTAX);
  1075. if ( OutBufferSize < totalBufferSize ) {
  1076. *Required = totalBufferSize;
  1077. status = ERROR_MORE_DATA;
  1078. } else {
  1079. // This is somewhat redundant since we zero the
  1080. // buffer above, but it's here for clarity.
  1081. CLUSPROP_BUFFER_HELPER buf;
  1082. buf.pb = OutBuffer;
  1083. buf.pList->nPropertyCount = 0;
  1084. buf.pdw++;
  1085. buf.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1086. *BytesReturned = totalBufferSize;
  1087. status = ERROR_SUCCESS;
  1088. }
  1089. }
  1090. return(status);
  1091. }
  1092. //
  1093. // Get private properties for the cluster.
  1094. //
  1095. status = ClRtlGetPrivateProperties( parametersKey,
  1096. &CspClusterRegApis,
  1097. OutBuffer,
  1098. OutBufferSize,
  1099. BytesReturned,
  1100. Required );
  1101. DmCloseKey( parametersKey );
  1102. return(status);
  1103. } // CspClusterGetPrivateProperties
  1104. DWORD
  1105. CspClusterValidatePrivateProperties(
  1106. IN HDMKEY RegistryKey,
  1107. IN PVOID InBuffer,
  1108. IN DWORD InBufferSize
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. Validates the private properties for a given cluster.
  1113. Arguments:
  1114. RegistryKey - Registry key for the cluster.
  1115. InBuffer - Supplies the input buffer.
  1116. InBufferSize - Supplies the size of the input buffer.
  1117. Return Value:
  1118. ERROR_SUCCESS if successful.
  1119. A Win32 error code on failure.
  1120. --*/
  1121. {
  1122. DWORD status;
  1123. //
  1124. // Validate the property list.
  1125. //
  1126. status = ClRtlVerifyPrivatePropertyList( InBuffer,
  1127. InBufferSize );
  1128. return(status);
  1129. } // CspClusterValidatePrivateProperties
  1130. DWORD
  1131. CspClusterSetPrivateProperties(
  1132. IN HDMKEY RegistryKey,
  1133. IN PVOID InBuffer,
  1134. IN DWORD InBufferSize
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. Sets the private properties for a given cluster.
  1139. Arguments:
  1140. RegistryKey - Registry key for the cluster.
  1141. InBuffer - Supplies the input buffer.
  1142. InBufferSize - Supplies the size of the input buffer.
  1143. Return Value:
  1144. ERROR_SUCCESS if successful.
  1145. A Win32 error code on failure.
  1146. --*/
  1147. {
  1148. DWORD status;
  1149. HDMKEY parametersKey;
  1150. DWORD disposition;
  1151. //
  1152. // Validate the property list.
  1153. //
  1154. status = ClRtlVerifyPrivatePropertyList( InBuffer,
  1155. InBufferSize );
  1156. if ( status == ERROR_SUCCESS ) {
  1157. //
  1158. // Open the cluster\parameters key
  1159. //
  1160. parametersKey = DmOpenKey( RegistryKey,
  1161. CLUSREG_KEYNAME_PARAMETERS,
  1162. MAXIMUM_ALLOWED );
  1163. if ( parametersKey == NULL ) {
  1164. status = GetLastError();
  1165. if ( status == ERROR_FILE_NOT_FOUND ) {
  1166. //
  1167. // Try to create the parameters key.
  1168. //
  1169. parametersKey = DmCreateKey( RegistryKey,
  1170. CLUSREG_KEYNAME_PARAMETERS,
  1171. 0,
  1172. KEY_READ | KEY_WRITE,
  1173. NULL,
  1174. &disposition );
  1175. if ( parametersKey == NULL ) {
  1176. status = GetLastError();
  1177. return(status);
  1178. }
  1179. }
  1180. }
  1181. status = ClRtlSetPrivatePropertyList( NULL, // IN HANDLE hXsaction
  1182. parametersKey,
  1183. &CspClusterRegApis,
  1184. InBuffer,
  1185. InBufferSize );
  1186. DmCloseKey( parametersKey );
  1187. }
  1188. return(status);
  1189. } // CspClusterSetPrivateProperties