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.

2533 lines
59 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. recv.c
  5. Abstract:
  6. Cluster FM remote receive request routines.
  7. Author:
  8. Rod Gamache (rodga) 21-Mar-1996
  9. Revision History:
  10. --*/
  11. #include "fmp.h"
  12. #define LOG_MODULE RECV
  13. //
  14. // Global data
  15. //
  16. extern BOOL FmpOkayToProceed;
  17. //
  18. // Local function prototypes
  19. //
  20. BOOL
  21. FmpEnumMyGroups(
  22. IN OUT PGROUP_ENUM *Enum,
  23. IN LPDWORD Allocated,
  24. IN PFM_GROUP Group,
  25. IN LPCWSTR Id
  26. );
  27. BOOL
  28. FmpEnumResources(
  29. IN OUT PRESOURCE_ENUM *Enum,
  30. IN LPDWORD Allocated,
  31. IN PFM_RESOURCE Resource,
  32. IN LPCWSTR Id
  33. );
  34. error_status_t
  35. s_FmsOnlineGroupRequest(
  36. IN handle_t IDL_handle,
  37. IN LPCWSTR GroupId
  38. )
  39. /*++
  40. Routine Description:
  41. Receives a Group Online Request from (THE) remote system and returns
  42. status for that request.
  43. Arguments:
  44. IDL_handle - The binding context - not used.
  45. GroupId - The Id of the Group to bring online.
  46. Return Value:
  47. ERROR_SUCCESS if successful.
  48. A Win32 error code on error.
  49. --*/
  50. {
  51. PFM_GROUP group;
  52. DWORD status;
  53. FmpMustBeOnline( );
  54. ClRtlLogPrint(LOG_NOISE,
  55. "[FM] FmsOnlineGroupRequest: To bring group '%1!ws!' online\n",
  56. GroupId);
  57. //
  58. // Find the specified group.
  59. //
  60. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  61. if ( group == NULL ) {
  62. ClRtlLogPrint(LOG_NOISE,
  63. "[FM] FmsOnlineGroupRequest: Could not find Group %1!ws!\n",
  64. GroupId);
  65. return(ERROR_GROUP_NOT_FOUND);
  66. }
  67. //
  68. // Only one of these requests per group at a time.
  69. //
  70. FmpAcquireLocalGroupLock( group );
  71. //
  72. // Now bring it online.
  73. //
  74. if ( group->OwnerNode == NmLocalNode ) {
  75. //
  76. // Set the Group's Current State.
  77. //
  78. FmpSetGroupPersistentState( group, ClusterGroupOnline );
  79. status = FmpOnlineGroup( group, TRUE );
  80. } else {
  81. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  82. }
  83. FmpReleaseLocalGroupLock( group );
  84. OmDereferenceObject( group );
  85. return(status);
  86. } // FmsOnlineGroupRequest
  87. error_status_t
  88. s_FmsOfflineGroupRequest(
  89. IN handle_t IDL_handle,
  90. IN LPCWSTR GroupId
  91. )
  92. /*++
  93. Routine Description:
  94. Receives a Group Offline Request from (THE) remote system and returns
  95. status for that request.
  96. Arguments:
  97. IDL_handle - The binding context - not used.
  98. GroupId - The Id of the Group to bring offline.
  99. Return Value:
  100. ERROR_SUCCESS if successful.
  101. A Win32 error code on error.
  102. --*/
  103. {
  104. PFM_GROUP group;
  105. DWORD status;
  106. FmpMustBeOnline( );
  107. ClRtlLogPrint(LOG_NOISE,
  108. "[FM] FmsOfflineGroupRequest: To take group '%1!ws!' offline\n",
  109. GroupId);
  110. //
  111. // Find the specified group.
  112. //
  113. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  114. if ( group == NULL ) {
  115. ClRtlLogPrint(LOG_NOISE,
  116. "[FM] FmsOfflineGroupRequest: Could not find Group %1!ws!\n",
  117. GroupId);
  118. return(ERROR_GROUP_NOT_FOUND);
  119. }
  120. //
  121. // Now take it offline if we are the owner.
  122. //
  123. if ( group->OwnerNode == NmLocalNode ) {
  124. //
  125. // Set the Group's Current State.
  126. //
  127. FmpSetGroupPersistentState( group, ClusterGroupOffline );
  128. status = FmpOfflineGroup( group, FALSE, TRUE );
  129. } else {
  130. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  131. }
  132. OmDereferenceObject( group );
  133. return(status);
  134. } // FmsOfflineGroupRequest
  135. error_status_t
  136. s_FmsMoveGroupRequest(
  137. IN handle_t IDL_handle,
  138. IN LPCWSTR GroupId,
  139. IN LPCWSTR DestinationNode OPTIONAL
  140. )
  141. /*++
  142. Routine Description:
  143. Receives a Group Move Request from (THE) remote system and returns
  144. status for that request.
  145. Arguments:
  146. IDL_handle - The binding context - not used.
  147. GroupId - The Id of the Group to move.
  148. DestinationNode - The Id of the node to move the Group to.
  149. Return Value:
  150. ERROR_SUCCESS if successful.
  151. A Win32 error code on error.
  152. --*/
  153. {
  154. PFM_GROUP group;
  155. PNM_NODE node = NULL;
  156. DWORD status;
  157. FmpMustBeOnline( );
  158. ClRtlLogPrint(LOG_NOISE,
  159. "[FM] FmsMoveGroupRequest: To move group '%1!ws!'\n",
  160. GroupId);
  161. //
  162. //
  163. // Find the specified group.
  164. //
  165. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  166. if ( group == NULL ) {
  167. ClRtlLogPrint(LOG_NOISE,
  168. "[FM] FmsMoveGroupRequest: Could not find Group %1!ws!\n",
  169. GroupId);
  170. return(ERROR_GROUP_NOT_FOUND);
  171. }
  172. //
  173. // Find the specified destination node.
  174. //
  175. if ( ARGUMENT_PRESENT( DestinationNode ) ) {
  176. node = OmReferenceObjectById( ObjectTypeNode, DestinationNode );
  177. if ( node == NULL ) {
  178. OmDereferenceObject( group );
  179. ClRtlLogPrint(LOG_NOISE,"[FM] FmsMoveGroupRequest: Could not find Node %1!ws!\n", DestinationNode);
  180. return(ERROR_HOST_NODE_NOT_AVAILABLE);
  181. }
  182. }
  183. //
  184. // Make sure we are the owner of the Group.
  185. //
  186. FmpAcquireLocalGroupLock( group );
  187. if ( group->OwnerNode == NmLocalNode ) {
  188. status = FmpDoMoveGroup( group, node, TRUE );
  189. } else {
  190. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  191. }
  192. FmpReleaseLocalGroupLock( group );
  193. OmDereferenceObject( group );
  194. if ( node != NULL ) {
  195. OmDereferenceObject( node );
  196. }
  197. return(status);
  198. } // FmsMoveGroupRequest
  199. error_status_t
  200. s_FmsTakeGroupRequest(
  201. IN handle_t IDL_handle,
  202. IN LPCWSTR GroupId,
  203. IN PRESOURCE_ENUM ResourceList
  204. )
  205. /*++
  206. Routine Description:
  207. Receives a Take Group Request from (THE) remote system and returns
  208. status for that request.
  209. Arguments:
  210. IDL_handle - The binding context - not used.
  211. GroupId - The Id of the Group to take locally.
  212. ResourceList - The list of resources and their states.
  213. Return Value:
  214. ERROR_SUCCESS if successful.
  215. A Win32 error code on error.
  216. --*/
  217. {
  218. PFM_GROUP group;
  219. DWORD status = ERROR_SUCCESS;
  220. //SS: removing this check from here
  221. //FmpTakeGroupRequest does this check since if this call returns a failure,
  222. //the intended owner needs to be reset to invalidnode to avoid inconsistencies
  223. //FmpMustBeOnline( );
  224. ClRtlLogPrint(LOG_NOISE,
  225. "[FM] FmsTakeGroupRequest: To take group '%1!ws!'.\n",
  226. GroupId );
  227. //
  228. //
  229. // Find the specified group.
  230. //
  231. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  232. if ( group == NULL ) {
  233. ClRtlLogPrint(LOG_NOISE,
  234. "[FM] FmsTakeGroupRequest: Could not find Group %1!ws!\n",
  235. GroupId);
  236. if ( !FmpFMOnline ) {
  237. return(ERROR_HOST_NODE_NOT_AVAILABLE);
  238. }
  239. return(ERROR_GROUP_NOT_FOUND);
  240. }
  241. status = FmpTakeGroupRequest(group, ResourceList);
  242. OmDereferenceObject(group);
  243. return(status);
  244. } // FmsTakeGroupRequest
  245. error_status_t
  246. s_FmsOnlineResourceRequest(
  247. IN handle_t IDL_handle,
  248. IN LPCWSTR ResourceId
  249. )
  250. /*++
  251. Routine Description:
  252. Receives a Resource Online Request from (THE) remote system and returns
  253. status for that request.
  254. Arguments:
  255. IDL_handle - The binding context - not used.
  256. ResourceId - The Id of the Resource to bring online.
  257. Return Value:
  258. ERROR_SUCCESS if successful.
  259. A Win32 error code on error.
  260. --*/
  261. {
  262. PFM_RESOURCE resource;
  263. DWORD status;
  264. FmpMustBeOnline( );
  265. ClRtlLogPrint(LOG_NOISE,
  266. "[FM] FmsOnlineResourceRequest: To bring resource '%1!ws!' online\n",
  267. ResourceId);
  268. //
  269. // Find the specified resource.
  270. //
  271. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  272. if ( resource == NULL ) {
  273. ClRtlLogPrint(LOG_NOISE,
  274. "[FM] FmsOnlineResourceRequest: Could not find Resource %1!ws!\n",
  275. ResourceId);
  276. return(ERROR_RESOURCE_NOT_FOUND);
  277. }
  278. FmpAcquireLocalResourceLock( resource );
  279. if (!(resource->QuorumResource) &&
  280. !FmpInPreferredList( resource->Group, resource->Group->OwnerNode, TRUE, resource ) ) {
  281. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  282. goto FnExit;
  283. }
  284. //
  285. // Now bring it online.
  286. //
  287. CL_ASSERT( resource->Group != NULL );
  288. if ( resource->Group->OwnerNode == NmLocalNode ) {
  289. //
  290. // This can only be invoked through the API, so force all
  291. // resources online.
  292. //
  293. status = FmOnlineResource( resource );
  294. } else {
  295. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  296. }
  297. FnExit:
  298. FmpReleaseLocalResourceLock( resource );
  299. OmDereferenceObject( resource );
  300. return(status);
  301. } // FmsOnlineResourceRequest
  302. error_status_t
  303. s_FmsOfflineResourceRequest(
  304. IN handle_t IDL_handle,
  305. IN LPCWSTR ResourceId
  306. )
  307. /*++
  308. Routine Description:
  309. Receives a Resource Offline Request from (THE) remote system and returns
  310. status for that request.
  311. Arguments:
  312. IDL_handle - The binding context - not used.
  313. ResourceId - The Id of the Resource to bring offline.
  314. Return Value:
  315. ERROR_SUCCESS if successful.
  316. A Win32 error code on error.
  317. --*/
  318. {
  319. PFM_RESOURCE resource;
  320. DWORD status;
  321. FmpMustBeOnline( );
  322. ClRtlLogPrint(LOG_NOISE,
  323. "[FM] FmsOfflineResourceRequest: To take resource '%1!ws!' offline\n",
  324. ResourceId);
  325. //
  326. // Find the specified resource.
  327. //
  328. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  329. if ( resource == NULL ) {
  330. ClRtlLogPrint(LOG_NOISE,
  331. "[FM] FmsOfflineResourceRequest: Could not find Resource %1!ws!\n",
  332. ResourceId);
  333. return(ERROR_RESOURCE_NOT_FOUND);
  334. }
  335. FmpAcquireLocalResourceLock(resource);
  336. //
  337. // Now take it offline if we are the owner.
  338. //
  339. CL_ASSERT( resource->Group != NULL );
  340. if ( resource->Group->OwnerNode != NmLocalNode )
  341. {
  342. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  343. goto FnExit;
  344. }
  345. //else handle it locally
  346. status = FmOfflineResource( resource );
  347. FnExit:
  348. FmpReleaseLocalResourceLock(resource);
  349. OmDereferenceObject( resource );
  350. return(status);
  351. } // FmsOfflineResourceRequest
  352. error_status_t
  353. s_FmsChangeResourceNode(
  354. IN handle_t IDL_handle,
  355. IN LPCWSTR ResourceId,
  356. IN LPCWSTR NodeId,
  357. IN BOOL Add
  358. )
  359. /*++
  360. Routine Description:
  361. Receives a Resource change node request from a remote system and returns
  362. status for that request.
  363. Arguments:
  364. IDL_handle - The binding context - not used.
  365. ResourceId - The Id of the Resource to change a node.
  366. NodeId - The node id of the node to add or remove.
  367. Add - Indicates whether to add or remove the node.
  368. Return Value:
  369. ERROR_SUCCESS if successful.
  370. A Win32 error code on error.
  371. --*/
  372. {
  373. PFM_RESOURCE resource;
  374. DWORD status;
  375. FmpMustBeOnline( );
  376. ClRtlLogPrint(LOG_NOISE,
  377. "[FM] FmsChangeResourceNode: To %1!ws! node %2!ws! to/from resource '%3!ws!'.\n",
  378. Add ? L"Add" : L"Remove",
  379. NodeId,
  380. ResourceId);
  381. //
  382. // Find the specified resource.
  383. //
  384. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  385. if ( resource == NULL ) {
  386. ClRtlLogPrint(LOG_NOISE,
  387. "[FM] FmsChangeResourceNode: Could not find Resource %1!ws!\n",
  388. ResourceId);
  389. return(ERROR_RESOURCE_NOT_FOUND);
  390. }
  391. FmpAcquireLocalResourceLock( resource );
  392. status = FmpChangeResourceNode(resource, NodeId, Add);
  393. FmpReleaseLocalResourceLock( resource );
  394. OmDereferenceObject( resource );
  395. return(status);
  396. } // FmsChangeResourceNode
  397. error_status_t
  398. s_FmsArbitrateResource(
  399. IN handle_t IDL_handle,
  400. IN LPCWSTR ResourceId
  401. )
  402. /*++
  403. Routine Description:
  404. Arbitrates a Resource for a remote system.
  405. Arguments:
  406. IDL_handle - The binding context - not used.
  407. ResourceId - The Id of the Resource to bring online.
  408. Return Value:
  409. ERROR_SUCCESS if successful.
  410. A Win32 error code on error.
  411. --*/
  412. {
  413. PFM_RESOURCE resource;
  414. DWORD status;
  415. //
  416. // Find the specified resource.
  417. //
  418. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  419. if ( resource == NULL ) {
  420. ClRtlLogPrint(LOG_NOISE,
  421. "[FM] FmsArbitrateResource: Could not find Resource %1!ws!\n",
  422. ResourceId);
  423. return(ERROR_RESOURCE_NOT_FOUND);
  424. }
  425. status = FmpRmArbitrateResource( resource );
  426. OmDereferenceObject( resource );
  427. return(status);
  428. } // FmsArbitrateResource
  429. error_status_t
  430. s_FmsQueryOwnedGroups(
  431. IN handle_t IDL_handle,
  432. OUT PGROUP_ENUM *OwnedGroups,
  433. OUT PRESOURCE_ENUM *OwnedResources
  434. )
  435. /*++
  436. Routine Description:
  437. Server side used to propagate FM state to a joining node.
  438. Arguments:
  439. IDL_handle - Supplies RPC binding handle, not used.
  440. OwnedGroups - Returns the list of groups owned by this node and
  441. their state.
  442. OwnedResources - Returns the list of resources contained by groups
  443. owned by this node and their state.
  444. Return Value:
  445. ERROR_SUCCESS if successful
  446. Win32 error otherwise.
  447. --*/
  448. {
  449. DWORD status = ERROR_SUCCESS;
  450. DWORD allocated;
  451. PGROUP_ENUM groupEnum = NULL;
  452. PFM_GROUP group;
  453. PRESOURCE_ENUM resourceEnum = NULL;
  454. PFM_RESOURCE resource;
  455. DWORD i;
  456. allocated = ENUM_GROW_SIZE;
  457. groupEnum = MIDL_user_allocate(GROUP_SIZE(allocated));
  458. if ( groupEnum == NULL ) {
  459. CL_LOGFAILURE(ERROR_NOT_ENOUGH_MEMORY);
  460. return(ERROR_NOT_ENOUGH_MEMORY);
  461. }
  462. groupEnum->EntryCount = 0;
  463. //
  464. // Enumerate all groups
  465. //
  466. OmEnumObjects( ObjectTypeGroup,
  467. FmpEnumMyGroups,
  468. &groupEnum,
  469. &allocated );
  470. //
  471. // Enumerate all the resources in each group.
  472. //
  473. allocated = ENUM_GROW_SIZE;
  474. resourceEnum = MIDL_user_allocate(RESOURCE_SIZE(allocated));
  475. if (resourceEnum == NULL) {
  476. status = ERROR_NOT_ENOUGH_MEMORY;
  477. CL_LOGFAILURE(status);
  478. goto error_exit;
  479. }
  480. resourceEnum->EntryCount = 0;
  481. for (i=0; i < groupEnum->EntryCount; i++) {
  482. //
  483. // Get the group given its name.
  484. //
  485. group = OmReferenceObjectById( ObjectTypeGroup,
  486. groupEnum->Entry[i].Id );
  487. if (group == NULL) {
  488. continue;
  489. }
  490. //
  491. // Enumerate all the resources in this group.
  492. //
  493. status = FmpEnumerateGroupResources(group,
  494. FmpEnumResources,
  495. &resourceEnum,
  496. &allocated);
  497. if ( status != ERROR_SUCCESS ) {
  498. ClRtlLogPrint(LOG_NOISE,
  499. "[FM] FmsQueryOwnedGroups: Failed group '%1!ws!', status %2!u!.\n",
  500. OmObjectId(group),
  501. status);
  502. }
  503. OmDereferenceObject(group);
  504. }
  505. *OwnedGroups = groupEnum;
  506. *OwnedResources = resourceEnum;
  507. return(ERROR_SUCCESS);
  508. error_exit:
  509. if (groupEnum != NULL) {
  510. //
  511. // Free up group enum
  512. //
  513. for (i=0; i < groupEnum->EntryCount; i++) {
  514. MIDL_user_free(groupEnum->Entry[i].Id);
  515. }
  516. MIDL_user_free(groupEnum);
  517. }
  518. return(status);
  519. }
  520. error_status_t
  521. s_FmsFailResource(
  522. IN handle_t IDL_handle,
  523. IN LPCWSTR ResourceId
  524. )
  525. /*++
  526. Routine Description:
  527. Receives a Resource Fail Request from a remote system and returns
  528. status for that request.
  529. Arguments:
  530. IDL_handle - The binding context - not used.
  531. ResourceId - The Id of the Resource to fail.
  532. Return Value:
  533. ERROR_SUCCESS if successful.
  534. A Win32 error code on error.
  535. --*/
  536. {
  537. PFM_RESOURCE resource;
  538. DWORD status;
  539. FmpMustBeOnline( );
  540. ClRtlLogPrint(LOG_NOISE,
  541. "[FM] FmsFailResource: To fail resource '%1!ws!'.\n",
  542. ResourceId);
  543. //
  544. // Find the specified resource.
  545. //
  546. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  547. if ( resource == NULL ) {
  548. ClRtlLogPrint(LOG_NOISE,
  549. "[FM] FmsFailResource: Could not find Resource %1!ws!\n",
  550. ResourceId);
  551. return(ERROR_RESOURCE_NOT_FOUND);
  552. }
  553. FmpAcquireLocalResourceLock( resource );
  554. //
  555. // Now fail it.
  556. //
  557. if ( resource->Group->OwnerNode == NmLocalNode ) {
  558. status = FmpRmFailResource( resource );
  559. } else {
  560. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  561. }
  562. FmpReleaseLocalResourceLock( resource );
  563. return(status);
  564. } // FmsFailResource
  565. error_status_t
  566. s_FmsCreateResource(
  567. IN handle_t IDL_handle,
  568. IN LPCWSTR GroupId,
  569. IN LPWSTR ResourceId,
  570. IN LPCWSTR ResourceName
  571. )
  572. /*++
  573. Routine Description:
  574. Receives a Create Resource Request from a remote system and returns
  575. status for that request.
  576. Arguments:
  577. IDL_handle - The binding context - not used.
  578. GroupId - The Id of the Group to create the resource inside.
  579. ResourceId - The Id of the Resource to create.
  580. ResourceName - The name of the Resource to create.
  581. Return Value:
  582. ERROR_SUCCESS if successful.
  583. A Win32 error code on error.
  584. Notes:
  585. The Resource lock is acquired to synchronize access to the resource. This
  586. satisfies locking the resource on all nodes in the cluster... so long
  587. as the local node is the owner of the resource.
  588. --*/
  589. {
  590. PFM_GROUP group;
  591. DWORD status;
  592. PGUM_CREATE_RESOURCE gumResource;
  593. DWORD groupIdLen;
  594. DWORD resourceIdLen;
  595. DWORD resourceNameLen;
  596. DWORD bufSize;
  597. HDMKEY resourceKey;
  598. HDMKEY paramsKey;
  599. DWORD disposition;
  600. ClRtlLogPrint(LOG_NOISE,
  601. "[FM] FmsCreateResource: To create resource '%1!ws!'\n",
  602. ResourceId);
  603. //
  604. // Find the specified group.
  605. //
  606. group = OmReferenceObjectById( ObjectTypeGroup,
  607. GroupId );
  608. if ( group == NULL ) {
  609. ClRtlLogPrint(LOG_NOISE,
  610. "[FM] FmsCreateResource: Could not find Group %1!ws!\n",
  611. GroupId);
  612. return(ERROR_GROUP_NOT_FOUND);
  613. }
  614. FmpAcquireLocalGroupLock( group );
  615. //
  616. // Now delete it on all nodes in the cluster if we are the owner.
  617. //
  618. if ( group->OwnerNode == NmLocalNode ) {
  619. //
  620. // Allocate a message buffer.
  621. //
  622. groupIdLen = (lstrlenW(GroupId)+1) * sizeof(WCHAR);
  623. resourceIdLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
  624. resourceNameLen = (lstrlenW(ResourceName)+1) * sizeof(WCHAR);
  625. bufSize = sizeof(GUM_CREATE_RESOURCE) - sizeof(WCHAR) +
  626. groupIdLen + resourceIdLen + resourceNameLen;
  627. gumResource = LocalAlloc(LMEM_FIXED, bufSize);
  628. if (gumResource == NULL) {
  629. CsInconsistencyHalt( ERROR_NOT_ENOUGH_MEMORY );
  630. return(ERROR_NOT_ENOUGH_MEMORY);
  631. }
  632. //
  633. // Fill in message buffer.
  634. //
  635. gumResource->Resource = NULL;
  636. gumResource->GroupIdLen = groupIdLen;
  637. gumResource->ResourceIdLen = resourceIdLen;
  638. CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
  639. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
  640. ResourceId,
  641. resourceIdLen);
  642. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
  643. ResourceName,
  644. resourceNameLen);
  645. //
  646. // Send message.
  647. //
  648. status = GumSendUpdate(GumUpdateFailoverManager,
  649. FmUpdateCreateResource,
  650. bufSize,
  651. gumResource);
  652. if ( ( status == ERROR_SUCCESS ) &&
  653. ( gumResource->Resource != NULL ) )
  654. FmpCleanupPossibleNodeList(gumResource->Resource);
  655. LocalFree(gumResource);
  656. } else {
  657. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  658. }
  659. FmpReleaseLocalGroupLock( group );
  660. return(status);
  661. } // FmsCreateResource
  662. error_status_t
  663. s_FmsDeleteResource(
  664. IN handle_t IDL_handle,
  665. IN LPCWSTR ResourceId
  666. )
  667. /*++
  668. Routine Description:
  669. Receives a Delete Resource Request from a remote system and returns
  670. status for that request.
  671. Arguments:
  672. IDL_handle - The binding context - not used.
  673. ResourceId - The Id of the Resource to delete.
  674. Return Value:
  675. ERROR_SUCCESS if successful.
  676. A Win32 error code on error.
  677. Notes:
  678. The Resource lock is acquired to synchronize access to the resource. This
  679. satisfies locking the resource on all nodes in the cluster... so long
  680. as the local node is the owner of the resource.
  681. --*/
  682. {
  683. PFM_RESOURCE resource;
  684. DWORD status;
  685. DWORD resourceLen;
  686. FmpMustBeOnline();
  687. ClRtlLogPrint(LOG_NOISE,
  688. "[FM] FmsDeleteResource: To delete resource '%1!ws!'\n",
  689. ResourceId);
  690. //
  691. // Find the specified resource.
  692. //
  693. resource = OmReferenceObjectById( ObjectTypeResource,
  694. ResourceId );
  695. if ( resource == NULL ) {
  696. ClRtlLogPrint(LOG_NOISE,
  697. "[FM] FmsDeleteResource: Could not find Resource %1!ws!\n",
  698. ResourceId);
  699. return(ERROR_RESOURCE_NOT_FOUND);
  700. }
  701. FmpAcquireLocalResourceLock( resource );
  702. //
  703. // Now delete it on all nodes in the cluster if we are the owner.
  704. //
  705. if ( resource->Group->OwnerNode == NmLocalNode ) {
  706. //
  707. // Check if this is the quorum resource.
  708. //
  709. if ( resource->QuorumResource ) {
  710. status = ERROR_QUORUM_RESOURCE;
  711. goto FnExit;
  712. }
  713. //other core resources cannot be deleted either
  714. if (resource->ExFlags & CLUS_FLAG_CORE)
  715. {
  716. status = ERROR_CORE_RESOURCE;
  717. goto FnExit;
  718. }
  719. //
  720. // Check the state of the resource, before attempting to delete it.
  721. // It must be offline or failed in order to perform the delete.
  722. //
  723. if ((resource->State != ClusterResourceOffline) &&
  724. (resource->State != ClusterResourceFailed)) {
  725. status = ERROR_RESOURCE_ONLINE;
  726. goto FnExit;
  727. }
  728. //
  729. // Check whether this resource provides for any other resources.
  730. // If so, it cannot be deleted.
  731. //
  732. if (!IsListEmpty(&resource->ProvidesFor)) {
  733. status = ERROR_DEPENDENT_RESOURCE_EXISTS;
  734. goto FnExit;
  735. }
  736. if (resource->Group->MovingList)
  737. {
  738. status = ERROR_INVALID_STATE;
  739. goto FnExit;
  740. }
  741. resourceLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
  742. FmpBroadcastDeleteControl(resource);
  743. //
  744. // Send message.
  745. //
  746. status = GumSendUpdateEx(GumUpdateFailoverManager,
  747. FmUpdateDeleteResource,
  748. 1,
  749. resourceLen,
  750. ResourceId);
  751. } else {
  752. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  753. }
  754. FnExit:
  755. FmpReleaseLocalResourceLock( resource );
  756. return(status);
  757. } // FmsDeleteResource
  758. BOOL
  759. FmpEnumMyGroups(
  760. IN OUT PGROUP_ENUM *Enum,
  761. IN LPDWORD Allocated,
  762. IN PFM_GROUP Group,
  763. IN LPCWSTR Id
  764. )
  765. /*++
  766. Routine Description:
  767. Worker callback routine for the enumeration of Groups.
  768. This routine adds the specified Group to the list that is being
  769. generated if it is owned by the local system.
  770. Arguments:
  771. Enum - The Group Enumeration list. Can be an output if a new list is
  772. allocated.
  773. Allocated - The current number of allocated entries in Enum.
  774. Group - The Group object being enumerated.
  775. Id - The Id of the Group object being enumerated.
  776. Returns:
  777. TRUE - to indicate that the enumeration should continue.
  778. --*/
  779. {
  780. PGROUP_ENUM groupEnum;
  781. PGROUP_ENUM newEnum;
  782. DWORD newAllocated;
  783. DWORD index;
  784. LPWSTR newId;
  785. CLUSTER_GROUP_STATE state;
  786. //
  787. // If we don't own the Group, return now.
  788. //
  789. if (Group->OwnerNode != NmLocalNode) {
  790. return(TRUE);
  791. }
  792. groupEnum = *Enum;
  793. if ( groupEnum->EntryCount >= *Allocated ) {
  794. //
  795. // Time to grow the GROUP_ENUM
  796. //
  797. newAllocated = *Allocated + ENUM_GROW_SIZE;
  798. newEnum = MIDL_user_allocate(GROUP_SIZE(newAllocated));
  799. if ( newEnum == NULL ) {
  800. return(FALSE);
  801. }
  802. CopyMemory(newEnum, groupEnum, GROUP_SIZE(*Allocated));
  803. *Allocated = newAllocated;
  804. *Enum = newEnum;
  805. MIDL_user_free(groupEnum);
  806. groupEnum = newEnum;
  807. }
  808. //
  809. // Initialize new entry
  810. //
  811. newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
  812. if ( newId == NULL ) {
  813. return(FALSE);
  814. }
  815. lstrcpyW(newId, Id);
  816. groupEnum->Entry[groupEnum->EntryCount].Id = newId;
  817. groupEnum->Entry[groupEnum->EntryCount].State = Group->State;
  818. groupEnum->Entry[groupEnum->EntryCount].StateSequence = Group->StateSequence;
  819. ++groupEnum->EntryCount;
  820. return(TRUE);
  821. } // FmpEnumMyGroups
  822. BOOL
  823. FmpEnumResources(
  824. IN OUT PRESOURCE_ENUM *Enum,
  825. IN LPDWORD Allocated,
  826. IN PFM_RESOURCE Resource,
  827. IN LPCWSTR Id
  828. )
  829. /*++
  830. Routine Description:
  831. Worker callback routine for the enumeration of Group resources.
  832. This routine adds the specified resource to the list that is being
  833. generated.
  834. Arguments:
  835. Enum - The resource enumeration list. Can be an output if a new list is
  836. allocated.
  837. Allocated - The current number of allocated entries in Enum.
  838. Resource - The Resource object being enumerated.
  839. Id - The Id of the resource object being enumerated.
  840. Returns:
  841. TRUE - to indicate that the enumeration should continue.
  842. FALSE - to indicate that the enumeration should not continue.
  843. --*/
  844. {
  845. PRESOURCE_ENUM resourceEnum;
  846. PRESOURCE_ENUM newEnum;
  847. DWORD newAllocated;
  848. DWORD index;
  849. LPWSTR newId;
  850. resourceEnum = *Enum;
  851. if ( resourceEnum->EntryCount >= *Allocated ) {
  852. //
  853. // Time to grow the RESOURCE_ENUM
  854. //
  855. newAllocated = *Allocated + ENUM_GROW_SIZE;
  856. newEnum = MIDL_user_allocate(RESOURCE_SIZE(newAllocated));
  857. if ( newEnum == NULL ) {
  858. return(FALSE);
  859. }
  860. CopyMemory(newEnum, resourceEnum, RESOURCE_SIZE(*Allocated));
  861. *Allocated = newAllocated;
  862. *Enum = newEnum;
  863. MIDL_user_free(resourceEnum);
  864. resourceEnum = newEnum;
  865. }
  866. //
  867. // Initialize new entry
  868. //
  869. newId = MIDL_user_allocate((lstrlenW(Id)+1) * sizeof(WCHAR));
  870. if ( newId == NULL ) {
  871. return(FALSE);
  872. }
  873. lstrcpyW(newId, Id);
  874. resourceEnum->Entry[resourceEnum->EntryCount].Id = newId;
  875. resourceEnum->Entry[resourceEnum->EntryCount].State = Resource->State;
  876. resourceEnum->Entry[resourceEnum->EntryCount].StateSequence = Resource->StateSequence;
  877. ++resourceEnum->EntryCount;
  878. return(TRUE);
  879. } // FmpEnumResources
  880. error_status_t
  881. s_FmsResourceControl(
  882. IN handle_t IDL_handle,
  883. IN LPCWSTR ResourceId,
  884. IN DWORD ControlCode,
  885. IN PUCHAR InBuffer,
  886. IN DWORD InBufferSize,
  887. OUT PUCHAR OutBuffer,
  888. IN DWORD OutBufferSize,
  889. OUT LPDWORD BytesReturned,
  890. OUT LPDWORD Required
  891. )
  892. /*++
  893. Routine Description:
  894. This routine passes a resource control request from a remote system.
  895. Arguments:
  896. IDL_handle - the binding context - not used
  897. ResourceId - the Id of the Resource to control
  898. ControlCode - the control code for this request
  899. InBuffer - the input buffer
  900. InBufferSize - the size of the input buffer
  901. OutBuffer - the output buffer
  902. OutBufferSize - the size of the output buffer
  903. ByteReturned - the number of bytes returned in the output buffer
  904. Required - the number of bytes required if OutBuffer is not big enough.
  905. Returns:
  906. ERROR_SUCCESS if successful.
  907. Win32 error code on failure.
  908. --*/
  909. {
  910. PFM_RESOURCE resource;
  911. DWORD status;
  912. DWORD bufSize;
  913. DWORD dataLength;
  914. CLUSPROP_BUFFER_HELPER props;
  915. //
  916. // Find the specified resource.
  917. //
  918. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  919. if ( resource == NULL ) {
  920. ClRtlLogPrint(LOG_NOISE,
  921. "[FM] FmsResourceControl: Could not find Resource %1!ws!\n",
  922. ResourceId);
  923. return(ERROR_RESOURCE_NOT_FOUND);
  924. }
  925. CL_ASSERT( resource->Group != NULL );
  926. status = FmpRmResourceControl( resource,
  927. ControlCode,
  928. InBuffer,
  929. InBufferSize,
  930. OutBuffer,
  931. OutBufferSize,
  932. BytesReturned,
  933. Required
  934. );
  935. OmDereferenceObject(resource);
  936. return(status);
  937. } // FmsResourceControl
  938. error_status_t
  939. s_FmsResourceTypeControl(
  940. IN handle_t IDL_handle,
  941. IN LPCWSTR ResourceTypeName,
  942. IN DWORD ControlCode,
  943. IN PUCHAR InBuffer,
  944. IN DWORD InBufferSize,
  945. OUT PUCHAR OutBuffer,
  946. IN DWORD OutBufferSize,
  947. OUT LPDWORD BytesReturned,
  948. OUT LPDWORD Required
  949. )
  950. /*++
  951. Routine Description:
  952. This routine passes a resource control request from a remote system.
  953. Arguments:
  954. IDL_handle - the binding context - not used
  955. ResourceTypeName - the name of the Resource Type to control
  956. ControlCode - the control code for this request
  957. InBuffer - the input buffer
  958. InBufferSize - the size of the input buffer
  959. OutBuffer - the output buffer
  960. OutBufferSize - the size of the output buffer
  961. ByteReturned - the number of bytes returned in the output buffer
  962. Required - the number of bytes required if OutBuffer is not big enough.
  963. Returns:
  964. ERROR_SUCCESS if successful.
  965. Win32 error code on failure.
  966. --*/
  967. {
  968. PFM_RESOURCE resource;
  969. DWORD status;
  970. status = FmpRmResourceTypeControl( ResourceTypeName,
  971. ControlCode,
  972. InBuffer,
  973. InBufferSize,
  974. OutBuffer,
  975. OutBufferSize,
  976. BytesReturned,
  977. Required
  978. );
  979. if ((status == ERROR_MOD_NOT_FOUND) || (status == ERROR_PROC_NOT_FOUND))
  980. {
  981. FmpRemovePossibleNodeForResType(ResourceTypeName, NmLocalNode);
  982. }
  983. #if 0
  984. if ( ((status == ERROR_SUCCESS) ||
  985. (status == ERROR_RESOURCE_PROPERTIES_STORED)) &&
  986. (ControlCode & CLCTL_MODIFY_MASK) ) {
  987. ClusterEvent( CLUSTER_EVENT_RESTYPE_PROPERTY_CHANGE, XXX );
  988. }
  989. #endif
  990. return(status);
  991. } // FmsResourceTypeControl
  992. error_status_t
  993. s_FmsGroupControl(
  994. IN handle_t IDL_handle,
  995. IN LPCWSTR GroupId,
  996. IN DWORD ControlCode,
  997. IN PUCHAR InBuffer,
  998. IN DWORD InBufferSize,
  999. OUT PUCHAR OutBuffer,
  1000. IN DWORD OutBufferSize,
  1001. OUT LPDWORD BytesReturned,
  1002. OUT LPDWORD Required
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine processes a group control request from a remote system.
  1007. Arguments:
  1008. IDL_handle - the binding context - not used
  1009. GroupId - the Id of the Group to control
  1010. ControlCode - the control code for this request
  1011. InBuffer - the input buffer
  1012. InBufferSize - the size of the input buffer
  1013. OutBuffer - the output buffer
  1014. OutBufferSize - the size of the output buffer
  1015. ByteReturned - the number of bytes returned in the output buffer
  1016. Required - the number of bytes required if OutBuffer is not big enough.
  1017. Returns:
  1018. ERROR_SUCCESS if successful.
  1019. Win32 error code on failure.
  1020. --*/
  1021. {
  1022. PFM_GROUP group;
  1023. DWORD status;
  1024. //
  1025. // Find the specified group
  1026. //
  1027. group = OmReferenceObjectById( ObjectTypeGroup, GroupId );
  1028. if ( group == NULL ) {
  1029. ClRtlLogPrint(LOG_NOISE,
  1030. "[FM] FmsGroupControl: Could not find Group %1!ws!\n",
  1031. GroupId);
  1032. return(ERROR_GROUP_NOT_FOUND);
  1033. }
  1034. status = FmpGroupControl(group, ControlCode, InBuffer, InBufferSize,
  1035. OutBuffer, OutBufferSize, BytesReturned, Required);
  1036. OmDereferenceObject(group);
  1037. return(status);
  1038. } // FmsGroupControl
  1039. error_status_t
  1040. s_FmsPrepareQuorumResChange(
  1041. IN handle_t IDL_handle,
  1042. IN LPCWSTR ResourceId,
  1043. IN LPCWSTR lpszQuoLogPath,
  1044. IN DWORD dwMaxQuoLogSize
  1045. )
  1046. /*++
  1047. Routine Description:
  1048. Receives a request to prepare a resource to become the quorum resource.
  1049. A resource must be able to support a quorum log file and registry replication
  1050. files.
  1051. Arguments:
  1052. IDL_handle - The binding context - not used.
  1053. ResourceId - The Id of the resource to be made the quorum resource.
  1054. lpszQuoLogPath - The path where the logs must be created.
  1055. dwMaxQuoLogSize - The maximum size of the quorum log file.
  1056. Return Value:
  1057. ERROR_SUCCESS if successful.
  1058. A Win32 error code on error.
  1059. --*/
  1060. {
  1061. PFM_RESOURCE pResource=NULL;
  1062. DWORD Status;
  1063. ClRtlLogPrint(LOG_NOISE,
  1064. "[FM] FmsPrepareQuorumResChange: Entry\r\n");
  1065. // Find the specified resource.
  1066. //
  1067. pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1068. if ( pResource == NULL )
  1069. {
  1070. ClRtlLogPrint(LOG_NOISE,
  1071. "[FM] FmsPrepareQuorumResource: Could not find Resource %1!ws!\n",
  1072. ResourceId);
  1073. Status = ERROR_RESOURCE_NOT_FOUND;
  1074. goto FnExit;
  1075. }
  1076. CL_ASSERT( pResource->Group != NULL );
  1077. if ( pResource->Group->OwnerNode == NmLocalNode )
  1078. Status = FmpPrepareQuorumResChange(pResource, lpszQuoLogPath, dwMaxQuoLogSize);
  1079. else
  1080. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1081. FnExit:
  1082. if (pResource) OmDereferenceObject( pResource );
  1083. return(Status);
  1084. } // FmsPrepareQuorumResChange
  1085. error_status_t
  1086. s_FmsCompleteQuorumResChange(
  1087. IN handle_t IDL_handle,
  1088. IN LPCWSTR lpszOldQuoResId,
  1089. IN LPCWSTR lpszOldQuoLogPath
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Receives a request to clean up quorum logging and cluster registry files
  1094. on the old quorum resource.
  1095. Arguments:
  1096. IDL_handle - The binding context - not used.
  1097. lpszOldQuoResId - The Id of the resource to be made the quorum resource.
  1098. lpszQuoLogPath - The path where the logs must be created.
  1099. Return Value:
  1100. ERROR_SUCCESS if successful.
  1101. A Win32 error code on error.
  1102. --*/
  1103. {
  1104. PFM_RESOURCE pResource=NULL;
  1105. DWORD Status;
  1106. ClRtlLogPrint(LOG_NOISE,
  1107. "[FM] FmsCompleteQuorumResChange: Entry\r\n");
  1108. // Find the specified resource.
  1109. //
  1110. pResource = OmReferenceObjectById( ObjectTypeResource, lpszOldQuoResId );
  1111. if ( pResource == NULL )
  1112. {
  1113. ClRtlLogPrint(LOG_NOISE,
  1114. "[FM] FmsCompleteQuorumResource: Could not find Resource %1!ws!\n",
  1115. lpszOldQuoResId);
  1116. Status = ERROR_RESOURCE_NOT_FOUND;
  1117. goto FnExit;
  1118. }
  1119. CL_ASSERT( pResource->Group != NULL );
  1120. if ( pResource->Group->OwnerNode == NmLocalNode )
  1121. Status = FmpCompleteQuorumResChange(lpszOldQuoResId, lpszOldQuoLogPath);
  1122. else
  1123. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1124. FnExit:
  1125. if (pResource) OmDereferenceObject( pResource );
  1126. return(Status);
  1127. } // FmsCompleteQuorumResChange
  1128. error_status_t
  1129. s_FmsQuoNodeOnlineResource(
  1130. IN handle_t IDL_handle,
  1131. IN LPCWSTR ResourceId,
  1132. IN LPCWSTR NodeId,
  1133. OUT LPDWORD State
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. Receives a RmResourceOnline request from (THE) remote system and returns
  1138. status for that request.
  1139. This system must own the quorum resource.
  1140. This is the first half of the sling shot. We acquire locks
  1141. and then RPC back to the originating node with a request to perform
  1142. the online.
  1143. This request is only valid for non-quorum resources.
  1144. Arguments:
  1145. IDL_handle - The binding context - not used.
  1146. ResourceId - The Id of the Resource to bring online.
  1147. NodeId - The Id of the Node that originated the request.
  1148. State - Returns the new state of the resource.
  1149. Return Value:
  1150. ERROR_SUCCESS if successful.
  1151. A Win32 error code on error.
  1152. --*/
  1153. {
  1154. //not used
  1155. return(ERROR_INVALID_FUNCTION);
  1156. }
  1157. // FmsQuoNodeOnlineResource
  1158. error_status_t
  1159. s_FmsQuoNodeOfflineResource(
  1160. IN handle_t IDL_handle,
  1161. IN LPCWSTR ResourceId,
  1162. IN LPCWSTR NodeId,
  1163. OUT LPDWORD State
  1164. )
  1165. /*++
  1166. Routine Description:
  1167. Receives a Resource Offline Request from (THE) remote system and returns
  1168. status for that request.
  1169. Arguments:
  1170. IDL_handle - The binding context - not used.
  1171. ResourceId - The Id of the Resource to bring offline.
  1172. NodeId - The Id of the Node that originated the request.
  1173. State - Returns the new state of the resource.
  1174. Return Value:
  1175. ERROR_SUCCESS if successful.
  1176. A Win32 error code on error.
  1177. --*/
  1178. {
  1179. //not used
  1180. return(ERROR_INVALID_FUNCTION);
  1181. }// FmsQuoNodeOfflineResource
  1182. error_status_t
  1183. s_FmsRmOnlineResource(
  1184. IN handle_t IDL_handle,
  1185. IN LPCWSTR ResourceId,
  1186. OUT LPDWORD pdwState
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. Receives a RmResourceOnline request from quorum node and returns
  1191. status for that request.
  1192. This system was the originator of the original online request.
  1193. This is the second half of the sling shot. It just does the online
  1194. request.
  1195. This request is only valid for non-quorum resources.
  1196. Arguments:
  1197. IDL_handle - The binding context - not used.
  1198. ResourceId - The Id of the Resource to bring online.
  1199. State - Returns the new state of the resource.
  1200. Return Value:
  1201. ERROR_SUCCESS if successful.
  1202. A Win32 error code on error.
  1203. Notes:
  1204. We can't acquire any locks... but the originating thread has the
  1205. lock held for us.
  1206. --*/
  1207. {
  1208. PFM_RESOURCE resource;
  1209. DWORD status;
  1210. FmpMustBeOnline( );
  1211. ClRtlLogPrint(LOG_NOISE,
  1212. "[FM] s_FmsRmOnlineResource: To bring resource '%1!ws!' online\n",
  1213. ResourceId);
  1214. //
  1215. // Find the specified resource.
  1216. //
  1217. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1218. if ( resource == NULL ) {
  1219. ClRtlLogPrint(LOG_NOISE,
  1220. "[FM] s_FmsRmOnlineResource: Could not find Resource %1!ws!\n",
  1221. ResourceId);
  1222. return(ERROR_RESOURCE_NOT_FOUND);
  1223. }
  1224. //
  1225. // This must not be done on the quorum resource, and the local system
  1226. // must not own the quorum resource. We'll assume that the quorum
  1227. // resource migrated while we were performng this request.
  1228. //
  1229. CL_ASSERT( gpQuoResource != NULL );
  1230. CL_ASSERT( gpQuoResource->Group != NULL );
  1231. CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
  1232. if ( resource->QuorumResource ||
  1233. (gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
  1234. OmDereferenceObject( resource );
  1235. return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
  1236. }
  1237. //
  1238. // The local node must own the resource.
  1239. //
  1240. CL_ASSERT( resource->Group != NULL );
  1241. CL_ASSERT( resource->Group->OwnerNode != NULL );
  1242. if ( resource->Group->OwnerNode != NmLocalNode ) {
  1243. OmDereferenceObject( resource );
  1244. return(ERROR_RESOURCE_NOT_AVAILABLE);
  1245. }
  1246. //
  1247. // Just call the function that does the work.
  1248. //
  1249. OmNotifyCb( resource, NOTIFY_RESOURCE_PREONLINE );
  1250. status = RmOnlineResource( resource->Id, pdwState );
  1251. //call the synchronous notifications on the resource
  1252. FmpCallResourceNotifyCb(resource, *pdwState);
  1253. OmDereferenceObject( resource );
  1254. return(status);
  1255. } // FmsRmOnlineResource
  1256. error_status_t
  1257. s_FmsRmOfflineResource(
  1258. IN handle_t IDL_handle,
  1259. IN LPCWSTR ResourceId,
  1260. OUT LPDWORD pdwState
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. Receives a Resource Offline Request from (THE) remote system and returns
  1265. status for that request.
  1266. Arguments:
  1267. IDL_handle - The binding context - not used.
  1268. ResourceId - The Id of the Resource to bring offline.
  1269. State - Returns the new state of the resource.
  1270. Return Value:
  1271. ERROR_SUCCESS if successful.
  1272. A Win32 error code on error.
  1273. Notes:
  1274. We can't acquire any locks... but the originating thread has the
  1275. lock held for us.
  1276. --*/
  1277. {
  1278. PFM_RESOURCE resource;
  1279. DWORD status;
  1280. FmpMustBeOnline( );
  1281. ClRtlLogPrint(LOG_NOISE,
  1282. "[FM] s_FmsRmOfflineResource: To take resource '%1!ws!' offline\n",
  1283. ResourceId);
  1284. //
  1285. // Find the specified resource.
  1286. //
  1287. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1288. if ( resource == NULL ) {
  1289. ClRtlLogPrint(LOG_NOISE,
  1290. "[FM] s_FmsRmOfflineResource: Could not find Resource %1!ws!\n",
  1291. ResourceId);
  1292. return(ERROR_RESOURCE_NOT_FOUND);
  1293. }
  1294. //
  1295. // This must not be done on the quorum resource, and the local system
  1296. // must not own the quorum resource. We'll assume that the quorum
  1297. // resource migrated while we were performng this request.
  1298. //
  1299. CL_ASSERT( gpQuoResource != NULL );
  1300. CL_ASSERT( gpQuoResource->Group != NULL );
  1301. CL_ASSERT( gpQuoResource->Group->OwnerNode != NULL );
  1302. if ( resource->QuorumResource ||
  1303. (gpQuoResource->Group->OwnerNode == NmLocalNode) ) {
  1304. OmDereferenceObject( resource );
  1305. return(ERROR_HOST_NODE_NOT_RESOURCE_OWNER);
  1306. }
  1307. //
  1308. // The local node must own the resource.
  1309. //
  1310. CL_ASSERT( resource->Group != NULL );
  1311. CL_ASSERT( resource->Group->OwnerNode != NULL );
  1312. if ( resource->Group->OwnerNode != NmLocalNode ) {
  1313. OmDereferenceObject( resource );
  1314. return(ERROR_RESOURCE_NOT_AVAILABLE);
  1315. }
  1316. //
  1317. // Just call the function that does the work.
  1318. //
  1319. OmNotifyCb( resource, NOTIFY_RESOURCE_PREOFFLINE );
  1320. status = RmOfflineResource( resource->Id, pdwState );
  1321. //call the post offline obj synchronous notifications
  1322. FmpCallResourceNotifyCb(resource, *pdwState);
  1323. OmDereferenceObject( resource );
  1324. return(status);
  1325. } // FmsRmOfflineResource
  1326. error_status_t
  1327. s_FmsBackupClusterDatabase(
  1328. IN handle_t IDL_handle,
  1329. IN LPCWSTR ResourceId,
  1330. IN LPCWSTR lpszPathName
  1331. )
  1332. /*++
  1333. Routine Description:
  1334. Receives a request to backup the quorum log file and the checkpoint
  1335. file
  1336. Arguments:
  1337. IDL_handle - The binding context - not used.
  1338. ResourceId - The Id of the quorum resource
  1339. lpszPathName - The directory path name where the files have to be
  1340. backed up. This path must be visible to the node
  1341. on which the quorum resource is online.
  1342. Return Value:
  1343. ERROR_SUCCESS if successful.
  1344. A Win32 error code on error.
  1345. --*/
  1346. {
  1347. PFM_RESOURCE pResource = NULL;
  1348. DWORD Status;
  1349. FmpMustBeOnline( );
  1350. ClRtlLogPrint(LOG_NOISE,
  1351. "[FM] s_FmsBackupClusterDatabase: Entry...\r\n");
  1352. //
  1353. // Chittur Subbaraman (chitturs) - 10/12/1998
  1354. //
  1355. // Find the specified quorum resource
  1356. //
  1357. pResource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  1358. if ( pResource == NULL )
  1359. {
  1360. ClRtlLogPrint(LOG_NOISE,
  1361. "[FM] s_FmsBackupClusterDatabase: Could not find Resource %1!ws!\n",
  1362. ResourceId);
  1363. Status = ERROR_RESOURCE_NOT_FOUND;
  1364. goto FnExit;
  1365. }
  1366. FmpAcquireLocalResourceLock( pResource );
  1367. CL_ASSERT( pResource->Group != NULL );
  1368. //
  1369. // Make sure the local node owns the quorum resource
  1370. //
  1371. if ( pResource->Group->OwnerNode == NmLocalNode )
  1372. {
  1373. Status = FmpBackupClusterDatabase( pResource, lpszPathName );
  1374. }
  1375. else
  1376. {
  1377. Status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1378. ClRtlLogPrint(LOG_NOISE,
  1379. "[FM] s_FmsBackupClusterDatabase: This node is not the quorum resource owner...\n"
  1380. );
  1381. }
  1382. FmpReleaseLocalResourceLock( pResource );
  1383. FnExit:
  1384. if ( pResource ) OmDereferenceObject( pResource );
  1385. return( Status );
  1386. } // FmsBackupClusterDatabase
  1387. error_status_t
  1388. s_FmsChangeResourceGroup(
  1389. IN handle_t IDL_handle,
  1390. IN LPCWSTR pszResourceId,
  1391. IN LPCWSTR pszGroupId
  1392. )
  1393. /*++
  1394. Routine Description:
  1395. Receives a Resource change group request from a remote system and returns
  1396. status for that request.
  1397. Arguments:
  1398. IDL_handle - The binding context - not used.
  1399. pszResourceId - The Id of the Resource to change a resource
  1400. pszGroupId - The Id of the Group to change to.
  1401. Return Value:
  1402. ERROR_SUCCESS if successful.
  1403. A Win32 error code on error.
  1404. --*/
  1405. {
  1406. PFM_RESOURCE pResource = NULL;
  1407. PFM_GROUP pNewGroup = NULL;
  1408. DWORD dwStatus;
  1409. PFM_GROUP pOldGroup;
  1410. FmpMustBeOnline( );
  1411. //
  1412. // Find the specified resource.
  1413. //
  1414. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1415. if ( pResource == NULL ) {
  1416. ClRtlLogPrint(LOG_NOISE,
  1417. "[FM] FmsChangeResourceNode: Could not find Resource %1!ws!\n",
  1418. pszResourceId);
  1419. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1420. goto FnExit;
  1421. }
  1422. //
  1423. // Find the specified group.
  1424. //
  1425. pNewGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
  1426. if ( pNewGroup == NULL ) {
  1427. ClRtlLogPrint(LOG_NOISE,
  1428. "[FM] s_FmsChangeResourceGroupe: Could not find NewGroup %1!ws!\n",
  1429. pszGroupId);
  1430. dwStatus = ERROR_GROUP_NOT_FOUND;
  1431. goto FnExit;
  1432. }
  1433. ClRtlLogPrint(LOG_NOISE,
  1434. "[FM] s_FmChangeResourceGroup : Resource <%1!ws!> NewGroup %2!ws!\n",
  1435. OmObjectId( pResource ),
  1436. OmObjectId( pNewGroup ));
  1437. //
  1438. // Synchronize both the old and the new groups.
  1439. // Lock the lowest by lowest Group Id first - to prevent deadlocks!
  1440. // Note - the order of release is unimportant.
  1441. //
  1442. // strictly, the comparison below cannot be equal!
  1443. //
  1444. if ( lstrcmpiW( OmObjectId( pResource->Group ), OmObjectId( pNewGroup ) ) <= 0 ) {
  1445. FmpAcquireLocalGroupLock( pResource->Group );
  1446. FmpAcquireLocalGroupLock( pNewGroup );
  1447. } else {
  1448. FmpAcquireLocalGroupLock( pNewGroup );
  1449. FmpAcquireLocalGroupLock( pResource->Group );
  1450. }
  1451. //remember the old group for freeing locks
  1452. pOldGroup = pResource->Group;
  1453. //boy if we are not the owner any more
  1454. //shunt the request to the new owner
  1455. if ( pResource->Group->OwnerNode != NmLocalNode )
  1456. {
  1457. // Note: FmcChangeResourceNode must release the resource lock.
  1458. dwStatus = FmcChangeResourceGroup( pResource, pNewGroup );
  1459. goto FnExit;
  1460. }
  1461. else
  1462. {
  1463. dwStatus = FmpChangeResourceGroup( pResource, pNewGroup );
  1464. }
  1465. FmpReleaseLocalGroupLock( pNewGroup );
  1466. FmpReleaseLocalGroupLock( pOldGroup );
  1467. FnExit:
  1468. if ( pResource ) OmDereferenceObject( pResource );
  1469. if ( pNewGroup ) OmDereferenceObject( pNewGroup );
  1470. ClRtlLogPrint(LOG_NOISE,
  1471. "[FM] s_FmsChangeResourceGroup : returned <%1!u!>\r\n",
  1472. dwStatus);
  1473. return( dwStatus );
  1474. } //s_FmsChangeResourceGroup
  1475. error_status_t
  1476. s_FmsDeleteGroupRequest(
  1477. IN handle_t IDL_handle,
  1478. IN LPCWSTR pszGroupId
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. Receives a delete group request from a remote system and returns
  1483. the status for that request.
  1484. Arguments:
  1485. IDL_handle - The binding context - not used.
  1486. pszGroupId - The Id of the group to be deleted.
  1487. Return Value:
  1488. ERROR_SUCCESS if successful.
  1489. A Win32 error code on error.
  1490. --*/
  1491. {
  1492. PFM_GROUP pGroup = NULL;
  1493. DWORD dwStatus = ERROR_SUCCESS;
  1494. FmpMustBeOnline( );
  1495. //
  1496. // Find the specified group.
  1497. //
  1498. pGroup = OmReferenceObjectById( ObjectTypeGroup, pszGroupId );
  1499. if ( pGroup == NULL )
  1500. {
  1501. ClRtlLogPrint(LOG_NOISE,
  1502. "[FM] FmsDeleteGroupRequest: Could not find group %1!ws!\n",
  1503. pszGroupId);
  1504. dwStatus = ERROR_GROUP_NOT_FOUND;
  1505. goto FnExit;
  1506. }
  1507. FmpAcquireLocalGroupLock( pGroup );
  1508. if ( pGroup->OwnerNode == NmLocalNode )
  1509. {
  1510. dwStatus = FmpDeleteGroup( pGroup );
  1511. }
  1512. else
  1513. {
  1514. //
  1515. // FmcDeleteGroup releases the group lock
  1516. //
  1517. dwStatus = FmcDeleteGroupRequest( pGroup );
  1518. goto FnExit;
  1519. }
  1520. FmpReleaseLocalGroupLock( pGroup );
  1521. FnExit:
  1522. if ( pGroup ) OmDereferenceObject( pGroup );
  1523. return( dwStatus );
  1524. } //s_FmsChangeResourceGroup
  1525. error_status_t
  1526. s_FmsAddResourceDependency(
  1527. IN handle_t IDL_handle,
  1528. IN LPCWSTR pszResourceId,
  1529. IN LPCWSTR pszDependsOnId
  1530. )
  1531. /*++
  1532. Routine Description:
  1533. Receives an add resource dependency request from a remote system
  1534. and returns the status for that request.
  1535. Arguments:
  1536. IDL_handle - The binding context - not used.
  1537. pszResourceId - The Id of the resource to add a dependent resource.
  1538. pszDependentResourceId - The Id of the dependent resource.
  1539. Return Value:
  1540. ERROR_SUCCESS if successful.
  1541. A Win32 error code on error.
  1542. --*/
  1543. {
  1544. PFM_RESOURCE pResource = NULL;
  1545. PFM_RESOURCE pDependentResource = NULL;
  1546. DWORD dwStatus = ERROR_SUCCESS;
  1547. DWORD dwResourceLen;
  1548. DWORD dwDependsOnLen;
  1549. //
  1550. // Chittur Subbaraman (chitturs) - 5/16/99
  1551. //
  1552. // Handle add resource dependency RPC calls from non-owner nodes
  1553. //
  1554. FmpMustBeOnline( );
  1555. ClRtlLogPrint(LOG_NOISE,
  1556. "[FM] s_FmsAddResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
  1557. pszResourceId,
  1558. pszDependsOnId);
  1559. //
  1560. // Find the specified resources.
  1561. //
  1562. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1563. if ( pResource == NULL )
  1564. {
  1565. ClRtlLogPrint(LOG_NOISE,
  1566. "[FM] s_FmsAddResourceDependency: Could not find resource <%1!ws!>\n",
  1567. pszResourceId);
  1568. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1569. goto FnExit;
  1570. }
  1571. pDependentResource = OmReferenceObjectById( ObjectTypeResource,
  1572. pszDependsOnId );
  1573. if ( pDependentResource == NULL )
  1574. {
  1575. ClRtlLogPrint(LOG_NOISE,
  1576. "[FM] s_FmsAddResourceDependency: Could not find dependent resource <%1!ws!>\n",
  1577. pszDependsOnId);
  1578. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1579. goto FnExit;
  1580. }
  1581. //
  1582. // Acquire the resource lock
  1583. //
  1584. FmpAcquireLocalResourceLock( pResource );
  1585. if ( pResource->Group->OwnerNode != NmLocalNode )
  1586. {
  1587. dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1588. goto FnUnlock;
  1589. }
  1590. dwStatus = FmpValAddResourceDependency( pResource, pDependentResource );
  1591. if ( dwStatus != ERROR_SUCCESS )
  1592. {
  1593. goto FnUnlock;
  1594. }
  1595. dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
  1596. dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
  1597. dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
  1598. FmUpdateAddDependency,
  1599. 2,
  1600. dwResourceLen,
  1601. pszResourceId,
  1602. dwDependsOnLen,
  1603. pszDependsOnId );
  1604. if ( dwStatus == ERROR_SUCCESS )
  1605. {
  1606. FmpBroadcastDependencyChange( pResource,
  1607. pszDependsOnId,
  1608. FALSE );
  1609. }
  1610. FnUnlock:
  1611. FmpReleaseLocalResourceLock( pResource );
  1612. FnExit:
  1613. if ( pResource ) OmDereferenceObject( pResource );
  1614. if ( pDependentResource ) OmDereferenceObject( pDependentResource );
  1615. ClRtlLogPrint(LOG_NOISE,
  1616. "[FM] FmsAddResourceDependency Exit: Status = %1!u!\n",
  1617. dwStatus);
  1618. return( dwStatus );
  1619. } // s_FmsAddResourceDependency
  1620. error_status_t
  1621. s_FmsRemoveResourceDependency(
  1622. IN handle_t IDL_handle,
  1623. IN LPCWSTR pszResourceId,
  1624. IN LPCWSTR pszDependsOnId
  1625. )
  1626. /*++
  1627. Routine Description:
  1628. Receives a remove resource dependency request from a remote system
  1629. and returns the status for that request.
  1630. Arguments:
  1631. IDL_handle - The binding context - not used.
  1632. pszResourceId - The Id of the resource to remove a dependent resource from.
  1633. pszDependentResourceId - The Id of the dependent resource.
  1634. Return Value:
  1635. ERROR_SUCCESS if successful.
  1636. A Win32 error code on error.
  1637. --*/
  1638. {
  1639. PFM_RESOURCE pResource = NULL;
  1640. PFM_RESOURCE pDependentResource = NULL;
  1641. DWORD dwStatus = ERROR_SUCCESS;
  1642. DWORD dwResourceLen;
  1643. DWORD dwDependsOnLen;
  1644. //
  1645. // Chittur Subbaraman (chitturs) - 5/16/99
  1646. //
  1647. // Handle remove resource dependency RPC calls from non-owner nodes
  1648. //
  1649. FmpMustBeOnline( );
  1650. ClRtlLogPrint(LOG_NOISE,
  1651. "[FM] s_FmsRemoveResourceDependency: Resource <%1!ws!>, Dependent Resource <%2!ws!>\n",
  1652. pszResourceId,
  1653. pszDependsOnId);
  1654. //
  1655. // Find the specified resources.
  1656. //
  1657. pResource = OmReferenceObjectById( ObjectTypeResource, pszResourceId );
  1658. if ( pResource == NULL )
  1659. {
  1660. ClRtlLogPrint(LOG_NOISE,
  1661. "[FM] s_FmsRemoveResourceDependency: Could not find resource <%1!ws!>\n",
  1662. pszResourceId);
  1663. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1664. goto FnExit;
  1665. }
  1666. pDependentResource = OmReferenceObjectById( ObjectTypeResource,
  1667. pszDependsOnId );
  1668. if ( pDependentResource == NULL )
  1669. {
  1670. ClRtlLogPrint(LOG_NOISE,
  1671. "[FM] s_FmsRemoveResourceDependency: Could not find dependent resource <%1!ws!>\n",
  1672. pszDependsOnId);
  1673. dwStatus = ERROR_RESOURCE_NOT_FOUND;
  1674. goto FnExit;
  1675. }
  1676. //
  1677. // Acquire the resource lock
  1678. //
  1679. FmpAcquireLocalResourceLock( pResource );
  1680. dwStatus = FmpValRemoveResourceDependency( pResource, pDependentResource );
  1681. if ( dwStatus != ERROR_SUCCESS )
  1682. {
  1683. ClRtlLogPrint(LOG_NOISE,
  1684. "[FM] s_FmsRemoveResourceDependency: FmpValRemoveResourceDependency returns %1!u!\n",
  1685. dwStatus);
  1686. goto FnUnlock;
  1687. }
  1688. if ( pResource->Group->OwnerNode != NmLocalNode )
  1689. {
  1690. dwStatus = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1691. goto FnUnlock;
  1692. }
  1693. pszResourceId = OmObjectId( pResource );
  1694. dwResourceLen = ( lstrlenW( pszResourceId ) + 1 ) * sizeof( WCHAR );
  1695. pszDependsOnId = OmObjectId( pDependentResource );
  1696. dwDependsOnLen = ( lstrlenW( pszDependsOnId ) + 1 ) * sizeof( WCHAR );
  1697. dwStatus = GumSendUpdateEx( GumUpdateFailoverManager,
  1698. FmUpdateRemoveDependency,
  1699. 2,
  1700. dwResourceLen,
  1701. pszResourceId,
  1702. dwDependsOnLen,
  1703. pszDependsOnId );
  1704. if ( dwStatus == ERROR_SUCCESS )
  1705. {
  1706. FmpBroadcastDependencyChange( pResource,
  1707. pszDependsOnId,
  1708. TRUE );
  1709. }
  1710. FnUnlock:
  1711. FmpReleaseLocalResourceLock( pResource );
  1712. FnExit:
  1713. if ( pResource ) OmDereferenceObject( pResource );
  1714. if ( pDependentResource ) OmDereferenceObject( pDependentResource );
  1715. ClRtlLogPrint(LOG_NOISE,
  1716. "[FM] FmsRemoveResourceDependency Exit: Status = %1!u!\n",
  1717. dwStatus);
  1718. return( dwStatus );
  1719. } // s_FmsRemoveResourceDependency
  1720. error_status_t
  1721. s_FmsCreateResource2(
  1722. IN handle_t IDL_handle,
  1723. IN LPCWSTR GroupId,
  1724. IN LPWSTR ResourceId,
  1725. IN LPCWSTR ResourceName,
  1726. IN LPCWSTR ResourceType,
  1727. IN DWORD dwFlags
  1728. )
  1729. /*++
  1730. Routine Description:
  1731. Receives a Create Resource Request from a remote system and returns
  1732. status for that request.
  1733. Arguments:
  1734. IDL_handle - The binding context - not used.
  1735. GroupId - The Id of the Group to create the resource inside.
  1736. ResourceId - The Id of the Resource to create.
  1737. ResourceName - The name of the Resource to create.
  1738. ResourceType - The name of the Resource Type.
  1739. dwFlags - Flags for the resource.
  1740. Return Value:
  1741. ERROR_SUCCESS if successful.
  1742. A Win32 error code on error.
  1743. Notes:
  1744. The Resource lock is acquired to synchronize access to the resource. This
  1745. satisfies locking the resource on all nodes in the cluster... so long
  1746. as the local node is the owner of the resource.
  1747. --*/
  1748. {
  1749. PFM_GROUP group;
  1750. DWORD status;
  1751. PGUM_CREATE_RESOURCE gumResource;
  1752. DWORD groupIdLen;
  1753. DWORD resourceIdLen;
  1754. DWORD resourceNameLen;
  1755. DWORD resourceTypeLen;
  1756. DWORD bufSize;
  1757. HDMKEY resourceKey;
  1758. HDMKEY paramsKey;
  1759. DWORD disposition;
  1760. FmpMustBeOnline();
  1761. ClRtlLogPrint(LOG_NOISE,
  1762. "[FM] FmsCreateResource2: To create resource '%1!ws!'\n",
  1763. ResourceId);
  1764. //
  1765. // Find the specified group.
  1766. //
  1767. group = OmReferenceObjectById( ObjectTypeGroup,
  1768. GroupId );
  1769. if ( group == NULL ) {
  1770. ClRtlLogPrint(LOG_NOISE,
  1771. "[FM] FmsCreateResource2: Could not find Group %1!ws!\n",
  1772. GroupId);
  1773. return(ERROR_GROUP_NOT_FOUND);
  1774. }
  1775. FmpAcquireLocalGroupLock( group );
  1776. //
  1777. // Now delete it on all nodes in the cluster if we are the owner.
  1778. //
  1779. if ( group->OwnerNode == NmLocalNode ) {
  1780. //
  1781. // Allocate a message buffer.
  1782. //
  1783. groupIdLen = (lstrlenW(GroupId)+1) * sizeof(WCHAR);
  1784. resourceIdLen = (lstrlenW(ResourceId)+1) * sizeof(WCHAR);
  1785. resourceNameLen = (lstrlenW(ResourceName)+1) * sizeof(WCHAR);
  1786. resourceTypeLen = (lstrlenW(ResourceType)+1) * sizeof(WCHAR);
  1787. bufSize = sizeof(GUM_CREATE_RESOURCE) - sizeof(WCHAR) +
  1788. groupIdLen + resourceIdLen + resourceNameLen + resourceTypeLen + 2 * sizeof( DWORD );
  1789. gumResource = LocalAlloc(LMEM_FIXED, bufSize);
  1790. if (gumResource == NULL) {
  1791. CsInconsistencyHalt( ERROR_NOT_ENOUGH_MEMORY );
  1792. return(ERROR_NOT_ENOUGH_MEMORY);
  1793. }
  1794. //
  1795. // Fill in message buffer.
  1796. //
  1797. gumResource->Resource = NULL;
  1798. gumResource->GroupIdLen = groupIdLen;
  1799. gumResource->ResourceIdLen = resourceIdLen;
  1800. CopyMemory(gumResource->GroupId, GroupId, groupIdLen);
  1801. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen,
  1802. ResourceId,
  1803. resourceIdLen);
  1804. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen,
  1805. ResourceName,
  1806. resourceNameLen);
  1807. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen,
  1808. &resourceTypeLen,
  1809. sizeof( DWORD ) );
  1810. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ),
  1811. ResourceType,
  1812. resourceTypeLen );
  1813. CopyMemory((PCHAR)gumResource->GroupId + groupIdLen + resourceIdLen + resourceNameLen + sizeof( DWORD ) + resourceTypeLen,
  1814. &dwFlags,
  1815. sizeof( DWORD ) );
  1816. //
  1817. // Send message.
  1818. //
  1819. status = GumSendUpdate(GumUpdateFailoverManager,
  1820. FmUpdateCreateResource,
  1821. bufSize,
  1822. gumResource);
  1823. if ( ( status == ERROR_SUCCESS ) &&
  1824. ( gumResource->Resource != NULL ) )
  1825. FmpCleanupPossibleNodeList(gumResource->Resource);
  1826. if( ( gumResource->Resource == NULL ) && FmpShutdown ) {
  1827. status = ERROR_CLUSTER_NODE_SHUTTING_DOWN;
  1828. }
  1829. LocalFree(gumResource);
  1830. } else {
  1831. status = ERROR_HOST_NODE_NOT_RESOURCE_OWNER;
  1832. }
  1833. FmpReleaseLocalGroupLock( group );
  1834. return(status);
  1835. } // FmsCreateResource2