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.

945 lines
23 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. cluster.c
  5. Abstract:
  6. Server side support for Cluster APIs dealing with the whole
  7. cluster.
  8. Author:
  9. John Vert (jvert) 9-Feb-1996
  10. Revision History:
  11. --*/
  12. #include "apip.h"
  13. #include "clusverp.h"
  14. #include "clusudef.h"
  15. HCLUSTER_RPC
  16. s_ApiOpenCluster(
  17. IN handle_t IDL_handle,
  18. OUT error_status_t *Status
  19. )
  20. /*++
  21. Routine Description:
  22. Opens a handle to the cluster. This context handle is
  23. currently used only to handle cluster notify additions
  24. and deletions correctly.
  25. Added call to ApipConnectCallback which checks that connecting
  26. users have rights to open cluster.
  27. Rod Sharper 03/27/97
  28. Arguments:
  29. IDL_handle - RPC binding handle, not used.
  30. Status - Returns any error that may occur.
  31. Return Value:
  32. A context handle to a cluster object if successful
  33. NULL otherwise.
  34. History:
  35. RodSh 27-Mar-1997 Modified to support secured user connections.
  36. --*/
  37. {
  38. PAPI_HANDLE Handle;
  39. if ( CsUseAuthenticatedRPC ) {
  40. // if user was not granted access don't return handle
  41. *Status = ApipConnectCallback( NULL, IDL_handle );
  42. if( *Status != RPC_S_OK ){
  43. SetLastError( *Status );
  44. return NULL;
  45. }
  46. }
  47. Handle = LocalAlloc(LMEM_FIXED, sizeof(API_HANDLE));
  48. if (Handle == NULL) {
  49. CL_UNEXPECTED_ERROR( ERROR_NOT_ENOUGH_MEMORY );
  50. *Status = ERROR_NOT_ENOUGH_MEMORY;
  51. return(NULL);
  52. }
  53. *Status = ERROR_SUCCESS;
  54. Handle->Type = API_CLUSTER_HANDLE;
  55. Handle->Flags = 0;
  56. Handle->Cluster = NULL;
  57. InitializeListHead(&Handle->NotifyList);
  58. return(Handle);
  59. }
  60. error_status_t
  61. s_ApiCloseCluster(
  62. IN OUT HCLUSTER_RPC *phCluster
  63. )
  64. /*++
  65. Routine Description:
  66. Closes an open cluster context handle.
  67. Arguments:
  68. phCluster - Supplies a pointer to the HCLUSTER_RPC to be closed.
  69. Returns NULL
  70. Return Value:
  71. None.
  72. --*/
  73. {
  74. PAPI_HANDLE Handle;
  75. Handle = (PAPI_HANDLE)*phCluster;
  76. if (Handle->Type != API_CLUSTER_HANDLE) {
  77. return(ERROR_INVALID_HANDLE);
  78. }
  79. ApipRundownNotify(Handle);
  80. LocalFree(*phCluster);
  81. *phCluster = NULL;
  82. return(ERROR_SUCCESS);
  83. }
  84. VOID
  85. HCLUSTER_RPC_rundown(
  86. IN HCLUSTER_RPC Cluster
  87. )
  88. /*++
  89. Routine Description:
  90. RPC rundown procedure for a HCLUSTER_RPC. Just closes the handle.
  91. Arguments:
  92. Cluster - Supplies the HCLUSTER_RPC that is to be rundown.
  93. Return Value:
  94. None.
  95. --*/
  96. {
  97. s_ApiCloseCluster(&Cluster);
  98. }
  99. error_status_t
  100. s_ApiSetClusterName(
  101. IN handle_t IDL_handle,
  102. IN LPCWSTR NewClusterName
  103. )
  104. /*++
  105. Routine Description:
  106. Changes the current cluster's name.
  107. Arguments:
  108. IDL_handle - RPC binding handle, not used
  109. NewClusterName - Supplies the new name of the cluster.
  110. Return Value:
  111. ERROR_SUCCESS if successful
  112. Win32 error code otherwise
  113. --*/
  114. {
  115. DWORD Status = ERROR_SUCCESS;
  116. DWORD dwSize;
  117. LPWSTR pszClusterName = NULL;
  118. API_CHECK_INIT();
  119. //
  120. // Get the cluster name, which is kept in the root of the
  121. // cluster registry under the "ClusterName" value, call the
  122. // FM only if the new name is different
  123. //
  124. dwSize = (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR);
  125. retry:
  126. pszClusterName = (LPWSTR)LocalAlloc(LMEM_FIXED, dwSize);
  127. if (pszClusterName == NULL) {
  128. Status = ERROR_NOT_ENOUGH_MEMORY;
  129. goto FnExit;
  130. }
  131. Status = DmQueryValue(DmClusterParametersKey,
  132. CLUSREG_NAME_CLUS_NAME,
  133. NULL,
  134. (LPBYTE)pszClusterName,
  135. &dwSize);
  136. if (Status == ERROR_MORE_DATA) {
  137. //
  138. // Try again with a bigger buffer.
  139. //
  140. LocalFree(pszClusterName);
  141. goto retry;
  142. }
  143. if ( Status == ERROR_SUCCESS ) {
  144. LPWSTR pszNewNameUpperCase = NULL;
  145. pszNewNameUpperCase = (LPWSTR) LocalAlloc(
  146. LMEM_FIXED,
  147. (lstrlenW(NewClusterName) + 1) *
  148. sizeof(*NewClusterName)
  149. );
  150. if (pszNewNameUpperCase != NULL) {
  151. lstrcpyW( pszNewNameUpperCase, NewClusterName );
  152. _wcsupr( pszNewNameUpperCase );
  153. Status = ApipValidateClusterName( pszNewNameUpperCase );
  154. if ( Status == ERROR_SUCCESS ) {
  155. Status = FmChangeClusterName(pszNewNameUpperCase);
  156. }
  157. LocalFree( pszNewNameUpperCase );
  158. }
  159. else {
  160. Status = ERROR_NOT_ENOUGH_MEMORY;
  161. }
  162. }
  163. FnExit:
  164. if ( pszClusterName ) LocalFree( pszClusterName );
  165. return(Status);
  166. }
  167. error_status_t
  168. s_ApiGetClusterName(
  169. IN handle_t IDL_handle,
  170. OUT LPWSTR *ClusterName,
  171. OUT LPWSTR *NodeName
  172. )
  173. /*++
  174. Routine Description:
  175. Returns the current cluster name and the name of the
  176. node this RPC connection is to.
  177. Arguments:
  178. IDL_handle - RPC binding handle, not used
  179. ClusterName - Returns a pointer to the cluster name.
  180. This memory must be freed by the client side.
  181. NodeName - Returns a pointer to the node name.
  182. This memory must be freed by the client side.
  183. Return Value:
  184. ERROR_SUCCESS if successful
  185. Win32 error code otherwise
  186. --*/
  187. {
  188. DWORD Size;
  189. DWORD Status=ERROR_SUCCESS;
  190. //
  191. // Get the current node name
  192. //
  193. *ClusterName = NULL;
  194. Size = MAX_COMPUTERNAME_LENGTH+1;
  195. *NodeName = MIDL_user_allocate(Size*sizeof(WCHAR));
  196. if (*NodeName == NULL) {
  197. Status = ERROR_NOT_ENOUGH_MEMORY;
  198. goto FnExit;
  199. }
  200. GetComputerNameW(*NodeName, &Size);
  201. //
  202. // Get the cluster name, which is kept in the root of the
  203. // cluster registry under the "ClusterName" value.
  204. //
  205. Status = ERROR_SUCCESS;
  206. Size = (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR);
  207. retry:
  208. *ClusterName = MIDL_user_allocate(Size);
  209. if (*ClusterName == NULL) {
  210. Status = ERROR_NOT_ENOUGH_MEMORY;
  211. goto FnExit;
  212. }
  213. Status = DmQueryValue(DmClusterParametersKey,
  214. CLUSREG_NAME_CLUS_NAME,
  215. NULL,
  216. (LPBYTE)*ClusterName,
  217. &Size);
  218. if (Status == ERROR_MORE_DATA) {
  219. //
  220. // Try again with a bigger buffer.
  221. //
  222. MIDL_user_free(*ClusterName);
  223. goto retry;
  224. }
  225. FnExit:
  226. if (Status == ERROR_SUCCESS) {
  227. return(ERROR_SUCCESS);
  228. }
  229. if (*NodeName) MIDL_user_free(*NodeName);
  230. if (*ClusterName) MIDL_user_free(*ClusterName);
  231. *NodeName = NULL;
  232. *ClusterName = NULL;
  233. return(Status);
  234. }
  235. error_status_t
  236. s_ApiGetClusterVersion(
  237. IN handle_t IDL_handle,
  238. OUT LPWORD lpwMajorVersion,
  239. OUT LPWORD lpwMinorVersion,
  240. OUT LPWORD lpwBuildNumber,
  241. OUT LPWSTR *lpszVendorId,
  242. OUT LPWSTR *lpszCSDVersion
  243. )
  244. /*++
  245. Routine Description:
  246. Returns the current cluster version information.
  247. Arguments:
  248. IDL_handle - RPC binding handle, not used
  249. lpdwMajorVersion - Returns the major version number of the cluster software
  250. lpdwMinorVersion - Returns the minor version number of the cluster software
  251. lpszVendorId - Returns a pointer to the vendor name. This memory must be
  252. freed by the client side.
  253. lpszCSDVersion - Returns a pointer to the current CSD description. This memory
  254. must be freed by the client side.
  255. N.B. The CSD Version of a cluster is currently the same as the CSD
  256. Version of the base operating system.
  257. Return Value:
  258. ERROR_SUCCESS if successful
  259. Win32 error code otherwise.
  260. --*/
  261. {
  262. LPWSTR VendorString;
  263. LPWSTR CsdString;
  264. DWORD Length;
  265. OSVERSIONINFO OsVersionInfo;
  266. Length = lstrlenA(VER_CLUSTER_PRODUCTNAME_STR)+1;
  267. VendorString = MIDL_user_allocate(Length*sizeof(WCHAR));
  268. if (VendorString == NULL) {
  269. return (ERROR_NOT_ENOUGH_MEMORY);
  270. }
  271. mbstowcs(VendorString, VER_CLUSTER_PRODUCTNAME_STR, Length);
  272. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  273. GetVersionExW(&OsVersionInfo);
  274. Length = lstrlenW(OsVersionInfo.szCSDVersion)+1;
  275. CsdString = MIDL_user_allocate(Length*sizeof(WCHAR));
  276. if (CsdString == NULL) {
  277. return (ERROR_NOT_ENOUGH_MEMORY);
  278. }
  279. lstrcpyW(CsdString, OsVersionInfo.szCSDVersion);
  280. *lpszCSDVersion = CsdString;
  281. *lpszVendorId = VendorString;
  282. *lpwMajorVersion = VER_PRODUCTVERSION_W >> 8;
  283. *lpwMinorVersion = VER_PRODUCTVERSION_W & 0xff;
  284. *lpwBuildNumber = (WORD)(CLUSTER_GET_MINOR_VERSION(CsMyHighestVersion));
  285. return(ERROR_SUCCESS);
  286. }
  287. error_status_t
  288. s_ApiGetClusterVersion2(
  289. IN handle_t IDL_handle,
  290. OUT LPWORD lpwMajorVersion,
  291. OUT LPWORD lpwMinorVersion,
  292. OUT LPWORD lpwBuildNumber,
  293. OUT LPWSTR *lpszVendorId,
  294. OUT LPWSTR *lpszCSDVersion,
  295. OUT PCLUSTER_OPERATIONAL_VERSION_INFO *ppClusterOpVerInfo
  296. )
  297. /*++
  298. Routine Description:
  299. Returns the current cluster version information.
  300. Arguments:
  301. IDL_handle - RPC binding handle, not used
  302. lpdwMajorVersion - Returns the major version number of the cluster software
  303. lpdwMinorVersion - Returns the minor version number of the cluster software
  304. lpszVendorId - Returns a pointer to the vendor name. This memory must be
  305. freed by the client side.
  306. lpszCSDVersion - Returns a pointer to the current CSD description. This memory
  307. must be freed by the client side.
  308. N.B. The CSD Version of a cluster is currently the same as the CSD
  309. Version of the base operating system.
  310. Return Value:
  311. ERROR_SUCCESS if successful
  312. Win32 error code otherwise.
  313. --*/
  314. {
  315. LPWSTR VendorString = NULL;
  316. LPWSTR CsdString = NULL;
  317. DWORD Length;
  318. OSVERSIONINFO OsVersionInfo;
  319. DWORD dwStatus;
  320. PCLUSTER_OPERATIONAL_VERSION_INFO pClusterOpVerInfo=NULL;
  321. *lpszVendorId = NULL;
  322. *lpszCSDVersion = NULL;
  323. *ppClusterOpVerInfo = NULL;
  324. Length = lstrlenA(VER_CLUSTER_PRODUCTNAME_STR)+1;
  325. VendorString = MIDL_user_allocate(Length*sizeof(WCHAR));
  326. if (VendorString == NULL) {
  327. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  328. goto FnExit;
  329. }
  330. mbstowcs(VendorString, VER_CLUSTER_PRODUCTNAME_STR, Length);
  331. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  332. GetVersionExW(&OsVersionInfo);
  333. Length = lstrlenW(OsVersionInfo.szCSDVersion)+1;
  334. CsdString = MIDL_user_allocate(Length*sizeof(WCHAR));
  335. if (CsdString == NULL) {
  336. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  337. goto FnExit;
  338. }
  339. lstrcpyW(CsdString, OsVersionInfo.szCSDVersion);
  340. pClusterOpVerInfo = MIDL_user_allocate(sizeof(CLUSTER_OPERATIONAL_VERSION_INFO));
  341. if (pClusterOpVerInfo == NULL) {
  342. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  343. goto FnExit;
  344. }
  345. pClusterOpVerInfo->dwSize = sizeof(CLUSTER_OPERATIONAL_VERSION_INFO);
  346. pClusterOpVerInfo->dwReserved = 0;
  347. dwStatus = NmGetClusterOperationalVersion(&(pClusterOpVerInfo->dwClusterHighestVersion),
  348. &(pClusterOpVerInfo->dwClusterLowestVersion),
  349. &(pClusterOpVerInfo->dwFlags));
  350. *lpszCSDVersion = CsdString;
  351. *lpszVendorId = VendorString;
  352. *ppClusterOpVerInfo = pClusterOpVerInfo;
  353. *lpwMajorVersion = VER_PRODUCTVERSION_W >> 8;
  354. *lpwMinorVersion = VER_PRODUCTVERSION_W & 0xff;
  355. *lpwBuildNumber = (WORD)CLUSTER_GET_MINOR_VERSION(CsMyHighestVersion);
  356. FnExit:
  357. if (dwStatus != ERROR_SUCCESS)
  358. {
  359. // free the strings
  360. if (VendorString) MIDL_user_free(VendorString);
  361. if (CsdString) MIDL_user_free(CsdString);
  362. if (pClusterOpVerInfo) MIDL_user_free(pClusterOpVerInfo);
  363. }
  364. return(ERROR_SUCCESS);
  365. }
  366. error_status_t
  367. s_ApiGetQuorumResource(
  368. IN handle_t IDL_handle,
  369. OUT LPWSTR *ppszResourceName,
  370. OUT LPWSTR *ppszClusFileRootPath,
  371. OUT DWORD *pdwMaxQuorumLogSize
  372. )
  373. /*++
  374. Routine Description:
  375. Gets the current cluster quorum resource.
  376. Arguments:
  377. IDL_handle - RPC binding handle, not used.
  378. *ppszResourceName - Returns a pointer to the current quorum resource name. This
  379. memory must be freed by the client side.
  380. *ppszClusFileRootPath - Returns the root path where the permanent cluster files are
  381. stored.
  382. *pdwMaxQuorumLogSize - Returns the size at which the quorum log path is set.
  383. Return Value:
  384. ERROR_SUCCESS if successful
  385. Win32 error code otherwise.
  386. --*/
  387. {
  388. DWORD Status;
  389. LPWSTR quorumId = NULL;
  390. DWORD idMaxSize = 0;
  391. DWORD idSize = 0;
  392. PFM_RESOURCE pResource=NULL;
  393. LPWSTR pszResourceName=NULL;
  394. LPWSTR pszClusFileRootPath=NULL;
  395. LPWSTR pszLogPath=NULL;
  396. LPWSTR pszEndDeviceName;
  397. API_CHECK_INIT();
  398. //
  399. // Get the quorum resource value.
  400. //
  401. Status = DmQuerySz( DmQuorumKey,
  402. CLUSREG_NAME_QUORUM_RESOURCE,
  403. (LPWSTR*)&quorumId,
  404. &idMaxSize,
  405. &idSize);
  406. if (Status != ERROR_SUCCESS) {
  407. ClRtlLogPrint(LOG_ERROR,
  408. "[API] s_ApiGetQuorumResource Failed to get quorum resource, error %1!u!.\n",
  409. Status);
  410. goto FnExit;
  411. }
  412. //
  413. // Reference the specified resource ID.
  414. //
  415. pResource = OmReferenceObjectById( ObjectTypeResource, quorumId );
  416. if (pResource == NULL) {
  417. Status = ERROR_RESOURCE_NOT_FOUND;
  418. ClRtlLogPrint(LOG_ERROR,
  419. "[API] s_ApiGetQuorumResource Failed to find quorum resource object, error %1!u!\n",
  420. Status);
  421. goto FnExit;
  422. }
  423. //
  424. // Allocate buffer for returning the resource name.
  425. //
  426. pszResourceName = MIDL_user_allocate((lstrlenW(OmObjectName(pResource))+1)*sizeof(WCHAR));
  427. if (pszResourceName == NULL) {
  428. Status = ERROR_NOT_ENOUGH_MEMORY;
  429. goto FnExit;
  430. }
  431. lstrcpyW(pszResourceName, OmObjectName(pResource));
  432. //
  433. // Get the root path for cluster temporary files
  434. //
  435. idMaxSize = 0;
  436. idSize = 0;
  437. Status = DmQuerySz( DmQuorumKey,
  438. cszPath,
  439. (LPWSTR*)&pszLogPath,
  440. &idMaxSize,
  441. &idSize);
  442. if (Status != ERROR_SUCCESS) {
  443. ClRtlLogPrint(LOG_ERROR,
  444. "[API] s_ApiGetQuorumResource Failed to get the log path, error %1!u!.\n",
  445. Status);
  446. goto FnExit;
  447. }
  448. //
  449. // Allocate buffer for returning the resource name.
  450. //
  451. pszClusFileRootPath = MIDL_user_allocate((lstrlenW(pszLogPath)+1)*sizeof(WCHAR));
  452. if (pszClusFileRootPath == NULL) {
  453. Status = ERROR_NOT_ENOUGH_MEMORY;
  454. goto FnExit;
  455. }
  456. lstrcpyW(pszClusFileRootPath, pszLogPath);
  457. *ppszResourceName = pszResourceName;
  458. *ppszClusFileRootPath = pszClusFileRootPath;
  459. DmGetQuorumLogMaxSize(pdwMaxQuorumLogSize);
  460. FnExit:
  461. if (pResource) OmDereferenceObject(pResource);
  462. if (pszLogPath) LocalFree(pszLogPath);
  463. if (quorumId) LocalFree(quorumId);
  464. if (Status != ERROR_SUCCESS)
  465. {
  466. if (pszResourceName) MIDL_user_free(pszResourceName);
  467. if (pszClusFileRootPath) MIDL_user_free(pszClusFileRootPath);
  468. }
  469. return(Status);
  470. }
  471. error_status_t
  472. s_ApiSetQuorumResource(
  473. IN HRES_RPC hResource,
  474. IN LPCWSTR lpszClusFileRootPath,
  475. IN DWORD dwMaxQuorumLogSize
  476. )
  477. /*++
  478. Routine Description:
  479. Sets the current cluster quorum resource.
  480. Arguments:
  481. hResource - Supplies a handle to the resource that should be the cluster
  482. quorum resource.
  483. lpszClusFileRootPath - The root path for storing
  484. permananent cluster maintenace files.
  485. dwMaxQuorumLogSize - The maximum size of the quorum logs before they are
  486. reset by checkpointing. If 0, the default is used.
  487. Return Value:
  488. ERROR_SUCCESS if successful
  489. Win32 error code otherwise.
  490. --*/
  491. {
  492. DWORD Status;
  493. PFM_RESOURCE Resource;
  494. LPCWSTR lpszPathName = NULL;
  495. API_CHECK_INIT();
  496. VALIDATE_RESOURCE_EXISTS(Resource, hResource);
  497. //
  498. // Chittur Subbaraman (chitturs) - 1/6/99
  499. //
  500. // Check whether the user is passing in a pointer to a NULL character
  501. // as the second parameter. If not, pass the parameter passed by the
  502. // user
  503. //
  504. if ( ( ARGUMENT_PRESENT( lpszClusFileRootPath ) ) &&
  505. ( *lpszClusFileRootPath != L'\0' ) )
  506. {
  507. lpszPathName = lpszClusFileRootPath;
  508. }
  509. //
  510. // Let FM decide if this operation can be completed.
  511. //
  512. Status = FmSetQuorumResource(Resource, lpszPathName, dwMaxQuorumLogSize );
  513. if ( Status != ERROR_SUCCESS ) {
  514. return(Status);
  515. }
  516. //Update the path
  517. return(Status);
  518. }
  519. error_status_t
  520. s_ApiSetNetworkPriorityOrder(
  521. IN handle_t IDL_handle,
  522. IN DWORD NetworkCount,
  523. IN LPWSTR *NetworkIdList
  524. )
  525. /*++
  526. Routine Description:
  527. Sets the priority order for internal (intracluster) networks.
  528. Arguments:
  529. IDL_handle - RPC binding handle, not used
  530. NetworkCount - The count of networks in the NetworkList
  531. NetworkList - An array of pointers to network IDs.
  532. Return Value:
  533. ERROR_SUCCESS if successful
  534. Win32 error code otherwise.
  535. --*/
  536. {
  537. API_CHECK_INIT();
  538. return(
  539. NmSetNetworkPriorityOrder(
  540. NetworkCount,
  541. NetworkIdList
  542. )
  543. );
  544. }
  545. error_status_t
  546. s_ApiBackupClusterDatabase(
  547. IN handle_t IDL_handle,
  548. IN LPCWSTR lpszPathName
  549. )
  550. /*++
  551. Routine Description:
  552. Requests for backup of the quorum log file and the checkpoint file.
  553. Argument:
  554. IDL_handle - RPC binding handle, not used
  555. lpszPathName - The directory path name where the files have to be
  556. backed up. This path must be visible to the node
  557. on which the quorum resource is online.
  558. Return Value:
  559. ERROR_SUCCESS if successful
  560. Win32 error code otherwise.
  561. --*/
  562. {
  563. API_CHECK_INIT();
  564. //
  565. // Let FM decide if this operation can be completed.
  566. //
  567. return( FmBackupClusterDatabase( lpszPathName ) );
  568. }
  569. DWORD
  570. ApipValidateClusterName(
  571. IN LPCWSTR lpszNewName
  572. )
  573. /*++
  574. Routine Description:
  575. Check whether the new cluster name is valid
  576. Argument:
  577. lpszNewName - New cluster name.
  578. Return Value:
  579. ERROR_SUCCESS if successful
  580. Win32 error code otherwise.
  581. --*/
  582. {
  583. DWORD dwSize = 0;
  584. PFM_RESOURCE pResource = NULL;
  585. DWORD dwStatus;
  586. DWORD dwBytesReturned;
  587. DWORD dwRequired;
  588. LPWSTR lpszClusterNameResource = NULL;
  589. CLUSPROP_BUFFER_HELPER ListEntry;
  590. PVOID pPropList = NULL;
  591. DWORD cbListSize = 0;
  592. DWORD dwBufferSize;
  593. ClRtlLogPrint(LOG_NOISE,
  594. "[API] ApipValidateClusterName: Validating new name %1!ws!...\n",
  595. lpszNewName);
  596. dwStatus = DmQuerySz( DmClusterParametersKey,
  597. CLUSREG_NAME_CLUS_CLUSTER_NAME_RES,
  598. &lpszClusterNameResource,
  599. &dwSize,
  600. &dwSize );
  601. if ( dwStatus != ERROR_SUCCESS )
  602. {
  603. ClRtlLogPrint(LOG_ERROR,
  604. "[API] ApipValidateClusterName: Failed to get cluster name resource from registry, error %1!u!...\n",
  605. dwStatus);
  606. goto FnExit;
  607. }
  608. //
  609. // Reference the specified resource ID.
  610. //
  611. pResource = OmReferenceObjectById( ObjectTypeResource,
  612. lpszClusterNameResource );
  613. if ( pResource == NULL )
  614. {
  615. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  616. ClRtlLogPrint(LOG_ERROR,
  617. "[API] ApipValidateClusterName: Failed to find cluster name resource, %1!u!...\n",
  618. dwStatus);
  619. goto FnExit;
  620. }
  621. dwBufferSize = sizeof( ListEntry.pList->nPropertyCount ) +
  622. sizeof( *ListEntry.pName ) +
  623. ALIGN_CLUSPROP( ( lstrlenW( CLUSREG_NAME_NET_NAME ) + 1 ) * sizeof( WCHAR ) ) +
  624. sizeof( *ListEntry.pStringValue ) +
  625. ALIGN_CLUSPROP( ( lstrlenW( lpszNewName ) + 1 ) * sizeof( WCHAR ) ) +
  626. sizeof( *ListEntry.pSyntax );
  627. ListEntry.pb = (PBYTE) LocalAlloc( LPTR, dwBufferSize );
  628. if ( ListEntry.pb == NULL )
  629. {
  630. dwStatus = GetLastError();
  631. ClRtlLogPrint(LOG_ERROR,
  632. "[API] ApipValidateClusterName: Error %1!u! in allocating memory...\n",
  633. dwStatus);
  634. goto FnExit;
  635. }
  636. pPropList = ListEntry.pb;
  637. ListEntry.pList->nPropertyCount = 1;
  638. cbListSize += sizeof( ListEntry.pList->nPropertyCount );
  639. ListEntry.pb += sizeof( ListEntry.pList->nPropertyCount );
  640. ListEntry.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  641. ListEntry.pName->cbLength = ( lstrlenW( CLUSREG_NAME_NET_NAME ) + 1 ) * sizeof( WCHAR );
  642. lstrcpyW( ListEntry.pName->sz, CLUSREG_NAME_NET_NAME );
  643. cbListSize += sizeof( *ListEntry.pName ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
  644. ListEntry.pb += sizeof( *ListEntry.pName ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
  645. ListEntry.pStringValue->Syntax.dw = CLUSPROP_SYNTAX_LIST_VALUE_SZ;
  646. ListEntry.pStringValue->cbLength = ( lstrlenW( lpszNewName ) + 1 ) * sizeof( WCHAR );
  647. lstrcpyW( ListEntry.pStringValue->sz, lpszNewName );
  648. cbListSize += sizeof( *ListEntry.pStringValue ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
  649. ListEntry.pb += sizeof( *ListEntry.pStringValue ) + ALIGN_CLUSPROP( ListEntry.pName->cbLength );
  650. ListEntry.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  651. cbListSize += sizeof( *ListEntry.pSyntax );
  652. ListEntry.pb += sizeof( *ListEntry.pSyntax );
  653. dwStatus = FmResourceControl( pResource,
  654. NULL,
  655. CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES,
  656. (PUCHAR)pPropList,
  657. cbListSize,
  658. NULL,
  659. 0,
  660. &dwBytesReturned,
  661. &dwRequired );
  662. FnExit:
  663. LocalFree( lpszClusterNameResource );
  664. LocalFree( pPropList );
  665. if ( pResource != NULL )
  666. {
  667. OmDereferenceObject( pResource );
  668. }
  669. ClRtlLogPrint(LOG_NOISE,
  670. "[API] ApipValidateClusterName returns %1!u!...\n",
  671. dwStatus);
  672. return( dwStatus );
  673. }
  674. /*++
  675. The set service account password API was added to the cluster
  676. service after Windows XP shipped. In order to add client-side clusapi.dll
  677. support to XP SP1 without breaking the XP SP1 build, this dummy server-side
  678. routine must be added, even though this code does not ship in XP SP1.
  679. --*/
  680. error_status_t
  681. s_ApiSetServiceAccountPassword(
  682. IN handle_t IDL_handle,
  683. IN LPWSTR lpszNewPassword,
  684. IN DWORD dwFlags,
  685. OUT IDL_CLUSTER_SET_PASSWORD_STATUS *ReturnStatusBufferPtr,
  686. IN DWORD ReturnStatusBufferSize,
  687. OUT DWORD *SizeReturned,
  688. OUT DWORD *ExpectedBufferSize
  689. )
  690. {
  691. return( ERROR_CALL_NOT_IMPLEMENTED );
  692. } // s_ApiSetServiceAccountPassword